C# 使用Bouncy Castle将RSA公钥转换为RFC 4716公钥
我希望将RSA公钥转换为可以用作SSH公钥的内容 目前,Bouncy Castle为我生成了一个公钥,如下所示:C# 使用Bouncy Castle将RSA公钥转换为RFC 4716公钥,c#,ssh,bouncycastle,ssh-keys,rsa-key-fingerprint,C#,Ssh,Bouncycastle,Ssh Keys,Rsa Key Fingerprint,我希望将RSA公钥转换为可以用作SSH公钥的内容 目前,Bouncy Castle为我生成了一个公钥,如下所示: -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq1Y5300i8bN+cI2U3wJE Kh3xG/.........jbuz+WB0vvG P25UwCle2k5siVMwbImEYsr+Xt0dsMmGVB3/6MHAqrM3QQdQ8p2E5TyzL+JYa1FT gwIDAQAB
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq1Y5300i8bN+cI2U3wJE
Kh3xG/.........jbuz+WB0vvG
P25UwCle2k5siVMwbImEYsr+Xt0dsMmGVB3/6MHAqrM3QQdQ8p2E5TyzL+JYa1FT
gwIDAQAB
-----END PUBLIC KEY-----
var r = new Org.BouncyCastle.Crypto.Generators.RsaKeyPairGenerator();
r.Init(new KeyGenerationParameters(new SecureRandom(), 2048));
var keys = r.GenerateKeyPair();
var stringWriter = new StringWriter();
var pemWriter = new PemWriter(stringWriter);
pemWriter.WriteObject(keys.Private);
pemWriter.Writer.Flush();
stringWriter.Close();
PrivateKey = stringWriter.ToString();
stringWriter = new StringWriter();
pemWriter = new PemWriter(stringWriter);
pemWriter.WriteObject(keys.Public);
pemWriter.Writer.Flush();
stringWriter.Close();
PublicKey = stringWriter.ToString();
我希望它的RFC 4716格式与此类似:
ssh rsa AAAAB3NzaC1yc2..G1p2Ag3mZLFsks7RNHVLgMsGIAikQ=
到目前为止,我使用Bouncy Castle的代码如下所示:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq1Y5300i8bN+cI2U3wJE
Kh3xG/.........jbuz+WB0vvG
P25UwCle2k5siVMwbImEYsr+Xt0dsMmGVB3/6MHAqrM3QQdQ8p2E5TyzL+JYa1FT
gwIDAQAB
-----END PUBLIC KEY-----
var r = new Org.BouncyCastle.Crypto.Generators.RsaKeyPairGenerator();
r.Init(new KeyGenerationParameters(new SecureRandom(), 2048));
var keys = r.GenerateKeyPair();
var stringWriter = new StringWriter();
var pemWriter = new PemWriter(stringWriter);
pemWriter.WriteObject(keys.Private);
pemWriter.Writer.Flush();
stringWriter.Close();
PrivateKey = stringWriter.ToString();
stringWriter = new StringWriter();
pemWriter = new PemWriter(stringWriter);
pemWriter.WriteObject(keys.Public);
pemWriter.Writer.Flush();
stringWriter.Close();
PublicKey = stringWriter.ToString();
如何重新格式化和编码密钥,使其看起来像这样
有人用Bouncy Castle或类似的工具创建了SSH公钥吗?意识到你的帖子已经发布了几个月了,但是如果你仍然在寻找,请尝试下面的代码片段,灵感来自gotoalberto on
我在BouncyCastle中找不到用于此的现成函数。因此,解决方法是使用
PemReader
,然后格式化结果。结果将作为publicsh
属性提供:
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
using System;
using System.IO;
using System.Text;
namespace Deploy4Me.Common.Utils
{
public class RSAKey
{
public string PublicPEM { get; set; }
public string PrivatePEM { get; set; }
public string PublicSSH { get; set; }
}
public static class RSA
{
public static RSAKey Generate()
{
try
{
RSAKey result = new RSAKey();
IAsymmetricCipherKeyPairGenerator gen;
KeyGenerationParameters param;
gen = new RsaKeyPairGenerator();
param = new RsaKeyGenerationParameters(
BigInteger.ValueOf(3L),
new SecureRandom(),
2048,
80
);
gen.Init(param);
AsymmetricCipherKeyPair pair = gen.GenerateKeyPair();
using(TextWriter textWriter = new StringWriter())
{
PemWriter wr = new PemWriter(textWriter);
wr.WriteObject(pair.Private);
wr.Writer.Flush();
result.PrivatePEM = textWriter.ToString();
}
using (TextWriter textWriter = new StringWriter())
{
PemWriter wr = new PemWriter(textWriter);
wr.WriteObject(pair.Public);
wr.Writer.Flush();
result.PublicPEM = textWriter.ToString();
}
using (StringReader sr = new StringReader(result.PublicPEM))
{
PemReader reader = new PemReader(sr);
RsaKeyParameters r = (RsaKeyParameters)reader.ReadObject();
byte[] sshrsa_bytes = Encoding.Default.GetBytes("ssh-rsa");
byte[] n = r.Modulus.ToByteArray();
byte[] e = r.Exponent.ToByteArray();
string buffer64;
using(MemoryStream ms = new MemoryStream()){
ms.Write(ToBytes(sshrsa_bytes.Length), 0, 4);
ms.Write(sshrsa_bytes, 0, sshrsa_bytes.Length);
ms.Write(ToBytes(e.Length), 0, 4);
ms.Write(e, 0, e.Length);
ms.Write(ToBytes(n.Length), 0, 4);
ms.Write(n, 0, n.Length);
ms.Flush();
buffer64 = Convert.ToBase64String(ms.ToArray());
}
result.PublicSSH = string.Format("ssh-rsa {0} generated-key", buffer64);
}
return result;
}
catch (Org.BouncyCastle.Crypto.CryptoException ex)
{
throw ex;
}
}
private static byte[] ToBytes(int i)
{
byte[] bts = BitConverter.GetBytes(i);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(bts);
}
return bts;
}
}
}
注意:我在微软工作,但这不是微软的答案,只是个人问题 添加到Pavels答案中 我发现出于某种原因,在生成3072位RSA密钥时,PuttyGen会生成与我不同的RSA公钥 经过研究,我发现在Putty Gen程序的源代码中,它似乎可以做到。字节数组的长度+1,加上一个前导0 对于BouncyCastle,您可以更改此行
ms.Write(ToBytes(n.Length), 0, 4);
ms.Write(n, 0, n.Length);
到
对于Microsoft.netRSACryptServiceProvider来说,它看起来是这样的
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(3072);
byte[] sshrsa_bytes = Encoding.Default.GetBytes("ssh-rsa");
byte[] n = RSA.ExportParameters(false).Modulus;
byte[] e = RSA.ExportParameters(false).Exponent;
string buffer64;
using (MemoryStream ms = new MemoryStream())
{
ms.Write(ToBytes(sshrsa_bytes.Length), 0, 4);
ms.Write(sshrsa_bytes, 0, sshrsa_bytes.Length);
ms.Write(ToBytes(e.Length), 0, 4);
ms.Write(e, 0, e.Length);
ms.Write(ToBytes(n.Length+1), 0, 4); //Remove the +1 if not Emulating Putty Gen
ms.Write(new byte[] { 0 }, 0, 1); //Add a 0 to Emulate PuttyGen
ms.Write(n, 0, n.Length);
ms.Flush();
buffer64 = Convert.ToBase64String(ms.ToArray());
}
string pubssh = string.Format("ssh-rsa {0} generated-key", buffer64);
你可以看到我用于测试的私钥&putty gen源代码链接这在.net中根本不起作用,似乎只是使用了完全不同的对象名。它在.net中可能不起作用,因为它是Java。同意Doug的说法-非常好,允许我生成用于SFTP的密钥。