問題描述
我正在創建一個證書分發系統來跟蹤客戶和資料.
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的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!