將Windows Forms應用程序從.NET 1.1框架升級到.NET 3.5框架時,我遇到了RSACryptoServiceProvider
問題。在數據庫中,我存儲了包含加密簽名(SHA1哈希)的二進制文件,並且我有一個存儲在文件系統中的公鑰作爲包含十六進制字符串的文本文檔。在從文件系統讀取文件並獲取證書中的公鑰時,我沒有任何問題。RSACryptoServiceProvider.ImportParameters拋出System.Security.Cryptography.CryptographicException:錯誤數據
從公鑰中我得到模塊和指數字段作爲公鑰的一部分。我將這些值分配給RSAParameters
對象的新實例。接下來,我創建一個RSACryptoServiceProvider
類的新實例並調用ImportParameters
。在那個調用中,3.5代碼拋出一個異常。請注意,1.1代碼完全沒有問題。
有沒有人知道給予RSAParameters屬性的字節數組是否需要轉換,所以我可以在3.5代碼中使用它們呢?我已經嘗試了顛倒數組或將字節數組轉換爲BigInteger,但這並不能解決我的問題。
作爲參考完整堆棧跟蹤:
System.Security.Cryptography.CryptographicException: Bad Data.
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)
源代碼,其中,直到該錯誤: // ---------------------- -------------------------------------------- * //驗證證書。 * // ---------------------------------------------- -------------------- *
// verify the CA certificate (output = public key van CA)
byte[] lv_PkCA = VerifyCertificate(byte[], in_PkEUR);
// verify the VU certificate (output = public key van VU)
byte[] lv_PkVU = VerifyCertificate(byte[], lv_PkCA);
//------------------------------------------------------------------
// Verify the signatures
//------------------------------------------------------------------
// calculate hash with the SHA1 algorithm
SHA1 lv_HashAlgoritm = new SHA1CryptoServiceProvider();
byte[] lv_Modulus = new byte[128];
byte[] lv_Exponent = new byte[8];
Buffer.BlockCopy(lv_PkVU, lv_PkVU.Length - 128 - 8, lv_Modulus , 0, lv_Modulus.Length);
Buffer.BlockCopy(lv_PkVU, lv_PkVU.Length - 8 , lv_Exponent, 0, lv_Exponent.Length);
// init RSA parameters
RSAParameters lv_RSAKeyInfo = new RSAParameters();
lv_RSAKeyInfo.Modulus = lv_Modulus;
lv_RSAKeyInfo.Exponent = lv_Exponent;
// init RSA algoritme
RSACryptoServiceProvider lv_RSA = new RSACryptoServiceProvider();
lv_RSA.ImportParameters(lv_RSAKeyInfo);
有關更多參考,請參閱VerifyCertificate方法的內容。
private byte[] VerifyCertificate(
byte[] in_Certificate,
byte[] in_PublicKey)
{
byte[] lv_CHR = new byte[8];
byte[] lv_Modulus = new byte[128];
byte[] lv_Exponent = new byte[8];
Buffer.BlockCopy(in_PublicKey, in_PublicKey.Length - 128 - 8 - 8, lv_CHR , 0, lv_CHR.Length);
Buffer.BlockCopy(in_PublicKey, in_PublicKey.Length - 128 - 8 , lv_Modulus , 0, lv_Modulus.Length);
Buffer.BlockCopy(in_PublicKey, in_PublicKey.Length - 8 , lv_Exponent, 0, lv_Exponent.Length);
byte[] lv_Signature = new byte[128];
byte[] lv_Cn = new byte[58];
byte[] lv_CAR = new byte[8];
Buffer.BlockCopy(in_Certificate, 0, lv_Signature, 0, lv_Signature.Length);
Buffer.BlockCopy(in_Certificate, 128, lv_Cn , 0, lv_Cn.Length);
Buffer.BlockCopy(in_Certificate, 186, lv_CAR , 0, lv_CAR.Length);
for (int lv_Index = 0; lv_Index < lv_CAR.Length; lv_Index++)
{
if (lv_CAR[lv_Index] != lv_CHR[lv_Index])
throw new Exception("Validation error: CAR not in public key.");
}
BigInteger lv_BiModulus = new BigInteger(lv_Modulus);
BigInteger lv_BiExponent = new BigInteger(lv_Exponent);
BigInteger lv_BiSignature = new BigInteger(lv_Signature);
byte[] lv_Sr = lv_BiSignature.modPow(lv_BiExponent, lv_BiModulus).getBytes(lv_Signature.Length);
if (lv_Sr.Length != 128)
throw new Exception("The certificate coult not be validated: size of signature should be 128 bytes.");
if ((lv_Sr[0] != (byte)0x6A) ||
(lv_Sr[127] != (byte)0xBC))
throw new Exception("The certificate coult not be validated: invalid format.");
byte[] lv_Cr = new byte[106];
byte[] lv_H = new byte[20];
Buffer.BlockCopy(lv_Sr, 1, lv_Cr, 0, lv_Cr.Length);
Buffer.BlockCopy(lv_Sr, 107, lv_H , 0, lv_H.Length);
byte[] lv_C = new byte[164];
Buffer.BlockCopy(lv_Cr, 0, lv_C, 0, lv_Cr.Length);
Buffer.BlockCopy(lv_Cn, 0, lv_C, 106, lv_Cn.Length);
// bereken de Hash van de public key
SHA1CryptoServiceProvider lv_SHA1 = new SHA1CryptoServiceProvider();
byte[] lv_Hash = lv_SHA1.ComputeHash(lv_C);
// vergelijk de berekende hash met de hash in het certificaat
if (lv_Hash.Length != lv_H.Length)
throw new Exception("The certificate coult not be verified: hash length invalid.");
for (int lv_Index = 0; lv_Index < lv_Hash.Length; lv_Index++)
{
if (lv_Hash[lv_Index] != lv_H[lv_Index])
throw new DiantaException("The certificate coult not be verified: hash not invalid.");
}
return lv_C;
}
感謝您的幫助提前。
親切的問候,
勒
請張貼您的代碼 – Predator 2011-04-03 04:54:18
完成後,請指教。 – 2011-04-04 07:01:48
嗨,我打算提供幫助,但你的問題超出了我的專業知識。對不起,關於那個:( – Predator 2011-04-04 16:35:59