2010-09-02 155 views
7

我想驗證使用C#和.NetCF的X.509證書。我有CA證書,如果我理解正確,我需要使用此CA證書中的公鑰來解密不可信證書的簽名。這應該給我不可信證書的計算哈希值。然後我應該自己計算證書的散列值,並確保兩個值匹配。如何在使用Compact Framework的C#中驗證X.509證書

我一直在玩這個幾天,我沒有走得很遠。我一直在使用X509Certificate和RSACryptoServiceProvider類。首先,我試圖從X509Certificate類中獲取公鑰和簽名。我能夠獲得公鑰,但沒有簽名。接下來,我嘗試解析構成證書的二進制數據,這使得我可以獲得簽名(以及我想要的任何其他數據),但是我無法使用RSACryptoServiceProvider解密簽名。我試過這樣的事情,但當我試圖解密時不斷收到異常說「壞鑰匙」:

RSAParameters rsaParams = new RSAParameters(); 
rsaParams.Exponent = exp; 
rsaParams.Modulus = mod; 
RSACryptoServiceProvider rsaServ = new RSACryptoServiceProvider(); 
rsaServ.ImportParameters(rsaParams); 
byte[] decryptedSig = rsaServ.Decrypt(encryptedSig, false); 

任何意見將不勝感激。

編輯: 我嘗試了一些似乎更好,但返回一個奇怪的結果。我在這裏使用X509Certificate2類,因爲它測試起來更容易一些,但是稍後我需要爲.NetCF切換到X509Certificate。我認爲RSACryptoServiceProvider.VerifyData可能是我需要的。我試了下面的代碼。

X509Certificate2 cert = new X509Certificate2(certBytes); 
X509Certificate2 certCA1 = new X509Certificate2(@"C:\certs\certCA1.cer"); 

byte[] encryptedSig = new byte[256]; 
Array.Copy(certBytes, certBytes.Length - 256, encryptedSig, 0, 256); 

RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)certA1.PublicKey.Key; 
bool good = rsa.VerifyData(cert.RawData, "1.3.14.3.2.26", encryptedSig); 

正如我所說的,我可以手動解碼和解釋證書的二進制數據,所以我敢肯定的是cert.RawData證書的簽名的數據和最後256個字節加密簽名。字符串是散列算法的OID,我從證書中獲得,但我不能100%確定它是正確的。 VerifyData返回false,但我不確定爲什麼。

想法?

回答

3

這裏是我的碼。

RSACryptoServiceProvider rsa = signingCertificate_GetPublicKey(); 
return rsa.VerifyData(SignedValue(), CryptoConfig.MapNameToOID("SHA1"), Signature()); 

RSACryptoServiceProvider signingCertificate_GetPublicKey() 
{ 
    RSACryptoServiceProvider publicKey = new RSACryptoServiceProvider(); 

    RSAParameters publicKeyParams = new RSAParameters(); 
    publicKeyParams.Modulus = GetPublicKeyModulus(); 
    publicKeyParams.Exponent = GetPublicKeyExponent(); 

    publicKey.ImportParameters(publicKeyParams); 

    return publicKey; 
} 

byte[] GetPublicKeyExponent() 
{ 
    // The value of the second TLV in your Public Key 
} 

byte[] GetPublicKeyModulus() 
{ 
    // The value of the first TLV in your Public Key 
} 

byte[] SignedValue() 
{ 
    // The first TLV in your Ceritificate 
} 

byte[] Signature() 
{ 
    // The value of the third TLV in your Certificate 
} 

我希望能幫助任何正在解決這個問題的人。

1

WinCE是否支持與Win32 MSCrypto.dll兼容的東西?如果是的話,看看.NET的X509Certificate2類和CLR Security library on Codeplex.它包含了很多有用的.NET例程,它們位於核心操作系統加密庫之上。您可以下載源代碼,看看它是如何編譯爲.NetCF

要加載和驗證X509證書,這樣做(未經測試):

var cert = new X509Certificate2("mycert.cer"); 
if (!cert.Verify()) 
{ 
    <fail> 
} 

有近十幾構造函數X509Certificate2構造來自多種來源 - 磁盤上的文件,內存中的字節陣列,本地證書存儲區的加載等。

用於簽署證書的根CA將需要安裝在本地證書存儲區中。如果證書不包含信任鏈中的中間CA,則這些中間件也需要位於本地計算機上,一直到位於本地計算機中可信任證書存儲區中的根CA。

不幸的是,我無法從MSDN文檔中知道X509Certificate2是否可用於.NetCF。

+0

WinCE的限制可能很粗糙,而我對X.509完全不熟悉,所以我實際上一直試圖在普通的Win32環境中首先使用它,而且我甚至無法做到這一點。我看了一下您指出的CLR安全庫,但我沒有看到任何驗證X509證書的地方。你能再給我多一點繼續嗎? – Ben 2010-09-02 21:16:46

+0

我用示例代碼更新了答案。 – dthorpe 2010-09-02 21:28:47

+0

X509Certificate2在.NetCF上不可用,但這很有幫助。謝謝。 – Ben 2010-09-03 00:40:07

0

它爲我在Win32中,但在Compact Framework中,我面臨同樣的問題,有沒有X509Certificate2所以我實際上阻塞,Win32的,我們可以這樣做:

X509Certificate2 l__PublicKeyCertificate = new X509Certificate2("cert.cer"); 

RSACryptoServiceProvider l__rsaCspPublic = (RSACryptoServiceProvider)l__PublicKeyCertificate .PublicKey.Key; 

//... 

l__isVerified = l__rsaCspPublic.VerifyData(l__fileData, CryptoConfig.MapNameToOID("SHA1"), l__fileSignature); 
+0

我剛纔想到了這個,忘了發佈答案。我會看看我的源代碼,並在週一發佈答案。 – Ben 2010-12-11 04:37:08