C# 在.NET中使用PEM编码的RSA私钥
我有一个私钥,如下所示: -----开始RSA私钥------ 一些私钥数据 -----结束RSA PRIVAC# 在.NET中使用PEM编码的RSA私钥,c#,.net,cryptography,rsa,private-key,C#,.net,Cryptography,Rsa,Private Key,我有一个私钥,如下所示: -----开始RSA私钥------ 一些私钥数据 -----结束RSA PRIVA 我需要在我的C#项目中使用此键,但我找不到任何示例如何使用此格式的键。感谢所有主要的.NET/C#加密库(如BouncyCastle或SecureBackbox[commercial])都应该支持这种格式,以及加载密钥的操作(加密/解密/签名/验证)。尽管是一篇较老的帖子,我还是想在今年早些时候遇到同样的挑战时,我会粘上自己对这个问题的答案。 我编写了一个用于处理PEM密钥、加密、解密
我需要在我的C#项目中使用此键,但我找不到任何示例如何使用此格式的键。感谢所有主要的.NET/C#加密库(如BouncyCastle或SecureBackbox[commercial])都应该支持这种格式,以及加载密钥的操作(加密/解密/签名/验证)。尽管是一篇较老的帖子,我还是想在今年早些时候遇到同样的挑战时,我会粘上自己对这个问题的答案。 我编写了一个用于处理PEM密钥、加密、解密、签名和签名验证的库。 它附带了一个完整的示例解决方案(Load Encrypt Decrypt Save),因此您应该能够立即启动运行 干杯, 克里斯托弗
private RSACryptoServiceProvider CreateSProviderFromPrivateKey(字符串privateKey)
{
var privateKeyBits=System.Convert.FromBase64String(privateKey);
var RSA=new RSACryptoServiceProvider();
var rsaparms=新的rsaparmeters();
使用(BinaryReader binr=new BinaryReader(new MemoryStream(privateKeyBits)))
{
字节bt=0;
ushort-twobytes=0;
twobytes=binr.ReadUInt16();
如果(两个字节==0x8130)
binr.ReadByte();
else if(两个字节==0x8230)
binr.ReadInt16();
其他的
抛出新异常(“意外值read binr.ReadUInt16()”;
twobytes=binr.ReadUInt16();
如果(两个字节!=0x0102)
抛出新异常(“意外版本”);
bt=binr.ReadByte();
如果(bt!=0x00)
抛出新异常(“意外值read binr.ReadByte()”;
rsaparms.module=binr.ReadBytes(getintegerize(binr));
rsaparms.Exponent=binr.ReadBytes(getintegerize(binr));
rsaparms.D=binr.ReadBytes(getintegerize(binr));
rsaparms.P=binr.ReadBytes(getintegerize(binr));
rsaparms.Q=binr.ReadBytes(getintegerize(binr));
rsaparms.DP=binr.ReadBytes(getintegerize(binr));
rsaparms.DQ=binr.ReadBytes(getintegerize(binr));
rsaparms.InverseQ=binr.ReadBytes(getintegerize(binr));
}
RSA.输入参数(rsaparms);
返回RSA;
}
私有整数GetIntegerSize(BinaryReader binr)
{
字节bt=0;
字节lowbyte=0x00;
字节高字节=0x00;
整数计数=0;
bt=binr.ReadByte();
如果(bt!=0x02)
返回0;
bt=binr.ReadByte();
如果(bt==0x81)
count=binr.ReadByte();
其他的
如果(bt==0x82)
{
highbyte=binr.ReadByte();
lowbyte=binr.ReadByte();
byte[]modint={lowbyte,highbyte,0x00,0x00};
count=位转换器.ToInt32(modint,0);
}
其他的
{
计数=bt;
}
while(binr.ReadByte()==0x00)
{
计数-=1;
}
binr.BaseStream.Seek(-1,SeekOrigin.Current);
返回计数;
}
下面我写的关于数字签名的文章给出了一个c#的解决方案(不需要额外的库)。代码显示了如何将PEM格式的RSA私钥转换为.NET RSACryptoServiceProvider类使用的XML格式
使用Atlando Crypto Currency Geo Service,注册后您的身份将存储在浏览器中。在每次请求时,我们都会使用您的私钥通过此身份签署并加密与我们的合同。本文解释了它的工作原理
下面的代码通过比较原始版本和签名版本,在C#(RSACryptServiceProvider类)中实现了身份验证过程。模数来自PEM格式的RSA公钥(指数AQAB)
私有静态bool验证(字符串原始、字符串签名、字符串模数)
{
SHA256Managed sha=新的SHA256Managed();
byte[]bytes=Encoding.UTF8.GetBytes(原始);
byte[]hash=sha.ComputeHash(字节);
sha.Clear();
byte[]signed=新字节[signature.Length/2];
对于(int i=0;i private static bool Verify(string original, string signature, string modulus)
{
SHA256Managed sha = new SHA256Managed();
byte[] bytes = Encoding.UTF8.GetBytes(original);
byte[] hash = sha.ComputeHash(bytes);
sha.Clear();
byte[] signed = new byte[signature.Length/2];
for (int i = 0; i < signature.Length; i += 2)
{
signed[i/2] = Convert.ToByte(Convert.ToInt32(signature.Substring(i, 2), 16));
}
string key = "<RSAKeyValue><Modulus>" + modulus + "</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.FromXmlString(key);
RSAPKCS1SignatureDeformatter RSADeformatter = new RSAPKCS1SignatureDeformatter(rsa);
RSADeformatter.SetHashAlgorithm("SHA256");
return RSADeformatter.VerifySignature(hash, signed);
}
}
public static string Modulus(string pem)
{
byte[] x509der = Convert.FromBase64String(pem.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", ""));
byte[] seqOID = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 };
MemoryStream ms = new MemoryStream(x509der);
BinaryReader reader = new BinaryReader(ms);
if (reader.ReadByte() == 0x30) ReadASNLength(reader); //skip the size
else return null;
int identifierSize = 0; //total length of Object Identifier section
if (reader.ReadByte() == 0x30) identifierSize = ReadASNLength(reader);
else return null;
if (reader.ReadByte() == 0x06) //is the next element an object identifier?
{
int oidLength = ReadASNLength(reader);
byte[] oidBytes = new byte[oidLength];
reader.Read(oidBytes, 0, oidBytes.Length);
if (oidBytes.SequenceEqual(seqOID) == false) return null; //is the object identifier rsaEncryption PKCS#1?
int remainingBytes = identifierSize - 2 - oidBytes.Length;
reader.ReadBytes(remainingBytes);
}
if (reader.ReadByte() == 0x03) //is the next element a bit string?
{
ReadASNLength(reader); //skip the size
reader.ReadByte(); //skip unused bits indicator
if (reader.ReadByte() == 0x30)
{
ReadASNLength(reader); //skip the size
if (reader.ReadByte() == 0x02) //is it an integer?
{
int modulusSize = ReadASNLength(reader);
byte[] modulus = new byte[modulusSize];
reader.Read(modulus, 0, modulus.Length);
if (modulus[0] == 0x00) //strip off the first byte if it's 0
{
byte[] tempModulus = new byte[modulus.Length - 1];
Array.Copy(modulus, 1, tempModulus, 0, modulus.Length - 1);
modulus = tempModulus;
}
if (reader.ReadByte() == 0x02) //is it an integer?
{
int exponentSize = ReadASNLength(reader);
byte[] exponent = new byte[exponentSize];
reader.Read(exponent, 0, exponent.Length);
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
RSAParameters RSAKeyInfo = new RSAParameters();
RSAKeyInfo.Modulus = modulus;
RSAKeyInfo.Exponent = exponent;
rsa.ImportParameters(RSAKeyInfo);
return rsa.ToXmlString(false).Replace("<RSAKeyValue><Modulus>", "").Replace("</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>", "");
}
}
}
}
return null;
}
public static int ReadASNLength(BinaryReader reader)
{//Note: this method only reads lengths up to 4 bytes long as this is satisfactory for the majority of situations.
int length = reader.ReadByte();
if ((length & 0x00000080) == 0x00000080) //is the length greater than 1 byte
{
int count = length & 0x0000000f;
byte[] lengthBytes = new byte[4];
reader.Read(lengthBytes, 4 - count, count);
Array.Reverse(lengthBytes); //
length = BitConverter.ToInt32(lengthBytes, 0);
}
return length;
}
public string GenerateJWTToken(string rsaPrivateKey)
{
var rsaParams = GetRsaParameters(rsaPrivateKey);
var encoder = GetRS256JWTEncoder(rsaParams);
// create the payload according to your need
var payload = new Dictionary<string, object>
{
{ "iss", ""},
{ "sub", "" },
// and other key-values
};
var token = encoder.Encode(payload, new byte[0]);
return token;
}
private static IJwtEncoder GetRS256JWTEncoder(RSAParameters rsaParams)
{
var csp = new RSACryptoServiceProvider();
csp.ImportParameters(rsaParams);
var algorithm = new RS256Algorithm(csp, csp);
var serializer = new JsonNetSerializer();
var urlEncoder = new JwtBase64UrlEncoder();
var encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
return encoder;
}
private static RSAParameters GetRsaParameters(string rsaPrivateKey)
{
var byteArray = Encoding.ASCII.GetBytes(rsaPrivateKey);
using (var ms = new MemoryStream(byteArray))
{
using (var sr = new StreamReader(ms))
{
// use Bouncy Castle to convert the private key to RSA parameters
var pemReader = new PemReader(sr);
var keyPair = pemReader.ReadObject() as AsymmetricCipherKeyPair;
return DotNetUtilities.ToRSAParameters(keyPair.Private as RsaPrivateCrtKeyParameters);
}
}
}