BouncyCastle RSAPrivateKey 到 .NET RSAPrivateKey

时间:2023-03-28
本文介绍了BouncyCastle RSAPrivateKey 到 .NET RSAPrivateKey的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

我正在创建一个证书分发系统来跟踪客户和资料.

I'm creating a certificate distribution system to keep track of clients and stuff.

会发生什么:

  • 客户端向服务器发送 CSR
  • 服务器检查并签署证书
  • 服务器向客户端发送签名证书
  • 客户将签名证书和私钥放在 Windows 存储中.

所以在客户端会发生这种情况:

So on the client this happens:

//Pseudo Server Object:
Server s = new Server();  

//Requested Certificate Name and things
X509Name name = new X509Name("CN=Client Cert, C=NL");  

//Key generation 2048bits
RsaKeyPairGenerator rkpg = new RsaKeyPairGenerator();
rkpg.Init(new KeyGenerationParameters(new SecureRandom(), 2048));
AsymmetricCipherKeyPair ackp = rkpg.GenerateKeyPair();  

//PKCS #10 Certificate Signing Request
Pkcs10CertificationRequest csr = new Pkcs10CertificationRequest("SHA1WITHRSA", name, ackp.Public, null, ackp.Private);  

//Make it a nice PEM thingie
StringBuilder sb = new StringBuilder();
PemWriter pemwrit = new PemWriter(new StringWriter(b));
pemwrit.WriteObject(csr);
pemwrit.Writer.Flush();
s.SendRequest(sb.ToSting());

好的,所以我将跳过服务器端只要相信我,服务器会签署证书并将其发送回客户端.那就是我要采取行动的地方.

Ok So I'll skip serverside Just trust me the server signs the cert and send it back to the client. Thats where I'll pick up the action.

PemReader pr = new PemReader(new StringReader(b.ToString()));
X509Certificate cert = (X509Certificate)pr.ReadObject();  

//So lets asume I saved the AsymmetricCipherKeyPair (ackp) from before
//I have now the certificate and my private key;

//first I make it a "Microsoft" x509cert.
//This however does not have a PrivateKey thats in the AsymmetricCipherKeyPair (ackp)
System.Security.Cryptography.X509Certificates.X509Certificate2 netcert = DotNetUtilities.ToX509Certificate(cert);

//So here comes the RSACryptoServerProvider:
System.Security.Cryptography.RSACryptoServiceProvider rcsp = new System.Security.Cryptography.RSACryptoServiceProvider();  

//And the privateKeyParameters
System.Security.Cryptography.RSAParameters parms = new System.Security.Cryptography.RSAParameters();  

//now I have to translate ackp.PrivateKey to parms;
RsaPrivateCrtKeyParameters BCKeyParms = ((RsaPrivateCrtKeyParameters)ackp1.Private);  

//D is the private exponent
parms.Modulus   = BCKeyParms.Modulus.ToByteArray();
parms.P         = BCKeyParms.P.ToByteArray();
parms.Q         = BCKeyParms.Q.ToByteArray();
parms.DP        = BCKeyParms.DP.ToByteArray();
parms.DQ        = BCKeyParms.DQ.ToByteArray();
parms.InverseQ  = BCKeyParms.QInv.ToByteArray();
parms.D         = BCKeyParms.Exponent.ToByteArray();
parms.Exponent  = BCKeyParms.PublicExponent.ToByteArray();  

//Now I should be able to import the RSAParameters into the RSACryptoServiceProvider
rcsp.ImportParameters(parms);  

//<em><b>not really</b></em> This breaks says "Bad Data" and not much more. I'll Post the 
//stacktrace at the end  

//I open up the windows cert store because thats where I want to save it.
//Add it and save it this works fine without the privkey.
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.MaxAllowed);
store.Add(netcert);
store.Close();

现在您可能认为服务器端一定有问题.嗯,我也是这么想的,但是当我从这个证书制作一个 pfx 文件并手动导入它时,它工作得很好......

Now you're probably thinking there must be something going wrong at the server side. Well thats what I thought too but When I made a pfx file from this cert and imported it by hand it worked fine ....

不知何故,.NET RSA 私钥和 BouncyCastle RSA 私钥之间存在差异,我无法确定.

Somehow there's a diference bewteen a .NET RSA privatekey and a BouncyCastle RSA privatekey and I can't put my finger on it.

您可能会建议导入 pfx,然后通过 X509Store 从中获取私钥.我试过.:S 失败了.当我尝试 ExportParameters(true) 时,true 代表包含私有参数.它说密钥在指定状态下无效.".最后查看完整的例外情况.

You will probably suggest to import the pfx and then get the private key from it via the X509Store. I tried. :S And failed. As soon as I try to ExportParameters(true) the true stands for including privateparameters. It says "Key not valid for use in specified state.". See for complete exception at the end.

我希望你们中的一些人以前杀过这头猪,或者可以帮助我.

I hope some of you have slain this pig before or might be able to help me.

***Exceptions:***

System.Security.Cryptography.CryptographicException was unhandled
  Message="Key not valid for use in specified state.
"
  Source="mscorlib"
  StackTrace:
       at System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(Int32 hr)
       at System.Security.Cryptography.Utils._ExportKey(SafeKeyHandle hKey, Int32 blobType, Object cspObject)
       at System.Security.Cryptography.RSACryptoServiceProvider.ExportParameters(Boolean includePrivateParameters)
  InnerException: 

***And the other one:***

System.Security.Cryptography.CryptographicException was unhandled
  Message="Bad Data.
"
  Source="mscorlib"
  StackTrace:
       at System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(Int32 hr)
       at System.Security.Cryptography.Utils._ImportKey(SafeProvHandle hCSP, Int32 keyNumber, CspProviderFlags flags, Object cspObject, SafeKeyHandle& hKey)
       at System.Security.Cryptography.RSACryptoServiceProvider.ImportParameters(RSAParameters parameters)
  InnerException: 

推荐答案

答案(来自用户名)指向正确的方向:padding.

The answer (from username) points to the right direction: padding.

Bouncy-castle 最新版本的 git 代码如下:

Bouncy-castle's latest version from git has the following code:

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);
   return rp;
}

private static byte[] ConvertRSAParametersField(BigInteger n, int size)
{
   byte[] bs = n.ToByteArrayUnsigned();
   if (bs.Length == size)
      return bs;
   if (bs.Length > size)
      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;
}

nb:此代码不在充气城堡的 nuget 版本 (2011) 中,或者在大多数代码示例中只是简单地复制了 RSA 参数.

nb: This code in not in the nuget version (2011) of bouncy castle, or in most code samples were RSA parameters are simply copied.

此代码与您在其他任何地方看到的基本上复制/粘贴关键参数的代码不同,并且不执行额外的填充步骤.

This code is different from the code you can see anywhere else which basically copy/paste the key parameters, and does not perform the extra padding step.

这篇关于BouncyCastle RSAPrivateKey 到 .NET RSAPrivateKey的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

上一篇:C# 如何验证 Root-CA-Cert 证书 (x509) 链? 下一篇:是否可以使用.net RSACryptoServiceProvider 使用私钥加密?

相关文章