使用BouncyCastle读取RSA PEM私钥

时间:2017-05-07 11:46:48

标签: c# rsa bouncycastle pkcs#1

我想要在C#中导入/导出PEM / DER字符串的函数。我在python和C#上使用RSA,但我没有解决方案谁在两种语言之间工作得很好。 经过多次尝试和多次研究,我终于找到了一个为读取PEM公钥工作的解决方案。以下代码有效:

// pubkey is the PEM file without header/footer and encoded base64
Asn1Object obj = Asn1Object.FromByteArray(pubkey_bytes);
DerSequence publicKeySequence = (DerSequence)obj;
DerSequence publicKey = (DerSequence)Asn1Object.FromByteArray(publicKeySequence.GetEncoded());

DerInteger modulus = (DerInteger)publicKey[0];
DerInteger exponent = (DerInteger)publicKey[1];

RsaKeyParameters keyParameters = new RsaKeyParameters(false, modulus.PositiveValue, exponent.PositiveValue);
RSAParameters parameters = DotNetUtilities.ToRSAParameters(keyParameters);

这段代码的灵感来源于我在StackOverflow上找到的解决方案。但是,当我试图使用相同的私钥解决方案时,我有一个例外“Spécified尺寸太小”。此错误似乎出现在“InverseQ”行中。在我正在使用的代码下面:

// Private key encode base64 without header/footer
Asn1Object obj = Asn1Object.FromByteArray(privkey_bytes);
DerSequence privateKeySequence = (DerSequence)obj;
DerSequence privateKey = (DerSequence)Asn1Object.FromByteArray(privateKeySequence.GetEncoded());

DerInteger M = (DerInteger)privateKey[1];
DerInteger E = (DerInteger)privateKey[2];
DerInteger D = (DerInteger)privateKey[3];
DerInteger P = (DerInteger)privateKey[4];
DerInteger Q = (DerInteger)privateKey[5];
DerInteger DP = (DerInteger)privateKey[6];
DerInteger DQ = (DerInteger)privateKey[7];
DerInteger IQ = (DerInteger)privateKey[8];

var keyParameters = new RsaPrivateCrtKeyParameters(M.PositiveValue, 
E.PositiveValue, D.PositiveValue, P.PositiveValue, Q.PositiveValue, 
DP.PositiveValue, DQ.PositiveValue, IQ.PositiveValue);

RSAParameters parameters = DotNetUtilities.ToRSAParameters(keyParameters); // Exception here !

我还尝试了另一个StackOverflow帖子中的代码,用于修复填充问题,但这不是我的问题:

RSAParameters parameters = new RSAParameters();
parameters.Modulus = M.PositiveValue.ToByteArrayUnsigned();
parameters.Exponent = E.PositiveValue.ToByteArrayUnsigned();
parameters.P = P.PositiveValue.ToByteArrayUnsigned();
parameters.Q = Q.PositiveValue.ToByteArrayUnsigned();Modulus.Length);
parameters.DP = ConvertRSAParametersField(DP.PositiveValue, parameters.P.Length);
parameters.DQ = ConvertRSAParametersField(DQ.PositiveValue, parameters.Q.Length);
parameters.InverseQ = ConvertRSAParametersField(IQ.PositiveValue, parameters.Q.Length);

public static RSAParameters ToRSAParameters(RsaPrivateCrtKeyParameters privKey)
{
    RSAParameters rp = new RSAParameters();
    rp.Modulus = privKey.Modulus.ToByteArrayUnsigned();
    rp.Exponent = privKey.PublicExponent.ToByteArrayUnsigned();
    rp.P = privKey.P.ToByteArrayUnsigned();
    rp.Q = privKey.Q.ToByteArrayUnsigned();
    rp.D = ConvertRSAParametersField(privKey.Exponent, rp.Modulus.Length);
    rp.DP = ConvertRSAParametersField(privKey.DP, rp.P.Length);
    rp.DQ = ConvertRSAParametersField(privKey.DQ, rp.Q.Length);
    rp.InverseQ = ConvertRSAParametersField(privKey.QInv, rp.Q.Length); // Exception HERE
    return rp;
}

private static byte[] ConvertRSAParametersField(BigInteger n, int size)
{
    byte[] bs = n.ToByteArrayUnsigned();
    if (bs.Length == size)
        return bs;
    if (bs.Length > size) // HERE
        throw new ArgumentException("Specified size too small", "size");
    byte[] padded = new byte[size];
    Array.Copy(bs, 0, padded, size - bs.Length, bs.Length);
    return padded;
}

我的私钥是由python生成的,我认为它是普通密钥:

-----BEGIN RSA PRIVATE KEY-----
MIICYAIBAAKBgQCUkUk/vvyTI3begsdjz7eQVchjMTYMTyqt8HHHSXYXY2GrQCZS
VfBVxFLmx19brgMdLrKO93CjJWt+ACXAaLHmuGCsvNgGjCFqgg4XxM4Xamt9PeOc
F8HhMH7iS3OcgybQuu9GrekZB0yL2L9GVpyVrXpVlVHi4gBVjUr80e5LUwIDAQAB
AoGAGgK9wk1bxx8EZrya0BzD1J9QMB2jitApdr6MDQoNhNa/eM4IZ43oP/vZT9JE
Hbb/kJJmbKVhsQ6SHUNFO6qJA0FWYNqEA1xsTtat3RXAB/WCExxW9GwDG6pEXjK8
OrJFbKyIOhmqy3sBib9V76ROYsMi7Gioih8vtYKz8NFBiZECRQCmOHzCqEbsWJnK
5JUsUG8DyR3wg8mzi98m1qYGz3hsuBJMCW2M/QBSgyWGdDxExbQMcTb9lmTelq4W
sHbZLQ3FVxJsbwI9AOTP4ZCLDnzblroQjiUCW1vbVE6YnoO0YTb67Dj/g9CNOZpz
E0lJ3boUlg6lOEpDdwKxSswXhQU53OMJXQJFAKC+BaB0/Uk4EVnNHZkiG4lsp2Bd
AeR4wg8cCqiRYCK7Cy6u+1sZm4Mvwk05AMN88TYLEiO/mcJLswTMF9LDqAqLvoxP
AjxDmlPXo+4k37AZyzhkIN0jN5siGZ+D5DBw0RQoBv5ICOHDC0rgdW2IQ/rN2uzV
rDcmWYFy6WQI1j636ZUCRHWmzCi6ymkcUnqwlYXsjbZSVM7njOc3sJyVhaOgqs+o
1Zjbtpqq7DYEBHPFizh/nu6kf4lT3w5+vIKGs8r4k2IUMcJi
-----END RSA PRIVATE KEY-----

我对“Asn1Object.FromByteArray()”返回的参数的顺序有疑问。我注意到[0]只是一个“0”,这对我来说意味着空洞。长度是9所以它似乎是好方法,我只是不确定它们返回的顺序。试图找到一些文件,但我一无所获。

提前感谢人们帮助我

修改
首先,我想说我的目标是获得一个RSAParameters对象。

由于某人删除了他的帖子,我改变了

 rp.InverseQ = ConvertRSAParametersField(privKey.QInv, rp.Q.Length);

 rp.InverseQ = ConvertRSAParametersField(privKey.QInv, rp.P.Length);

但是在完成之后,我收到了一个异常的System.Security.Cryptography.CryptographicException,他告诉我“数据不正确”。在线

var csp = new RSACryptoServiceProvider(); // my csp object is already defined somewhere else but it change nothing
csp.ImportParameters(parameters); // Exception here, he doesn't like my object who doesn't seems valid for him. 

真正的问题似乎是“为什么我的对象被RSACryptoServiceProvider.ImportParameters()拒绝

0 个答案:

没有答案