[英]How can I (properly) verify a file using RSA and SHA256 with .NET?
我正在按照這個關於使用.NET進行數字簽名/驗證數據的精彩教程 。 我修改了該示例代碼以使用SHA256並點擊“指定的無效算法”異常,這引發了我在.NET 4.0中使用SHA256簽署數據的問題 。
該帖子的答案之一幫助我弄清楚如何通過顯式加載支持SHA256的加密提供程序而不依賴於可導出的私鑰來正確生成數字簽名(請參閱以下方法底部的代碼,其中構建了RSACryptoServiceProvider ) ):
static string mKeyContainerName;
static byte[] SignText(string text, string publicCertPath)
{
// Access Personal (MY) certificate store of current user
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
// Load the certificate we'll use to verify the signature from a file.
X509Certificate2 publicCert = new X509Certificate2(publicCertPath);
publicCert.Verify();
string publicHash = publicCert.GetCertHashString();
// Find the certificate we'll use to sign
X509Certificate2 privateCert = null;
foreach(X509Certificate2 cert in store.Certificates)
{
if(cert.GetCertHashString() == publicHash)
{
// We found it. Get its associated private key
privateCert = cert;
break;
}
}
store.Close();
if(privateCert == null)
{
throw new Exception("No valid private cert was found");
}
// Hash the string
UnicodeEncoding encoding = new UnicodeEncoding();
byte[] data = encoding.GetBytes(text);
SHA256Managed sha256 = new SHA256Managed();
byte[] hash = sha256.ComputeHash(data);
// The basic crypto provider only supports SHA-1.
// Force Enhanced RSA and AES Cryptographic Provider which supports SHA-256.
RSACryptoServiceProvider csp = (RSACryptoServiceProvider)privateCert.PrivateKey;
var enhCsp = new RSACryptoServiceProvider().CspKeyContainerInfo;
mKeyContainerName = csp.CspKeyContainerInfo.KeyContainerName;
var cspparams = new CspParameters
(
enhCsp.ProviderType, enhCsp.ProviderName, mKeyContainerName
);
csp = new RSACryptoServiceProvider(cspparams);
// Sign the hash
return csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA256"));
}
值得注意的是,我使用的是makecert.exe的自簽名證書。 根據同一篇文章中的另一個答案 ,如果我在makercert.exe中包含正確的-sp或-sy標志,則不會出現這些問題。 但是,即使指定了這些標志之一(當前使用-sy 24 ),我仍然需要執行變通方法。
此實現與該帖子中接受的答案略有不同(同樣,由於我們的私鑰不可導出)。 但該答案確實表明可以在不明確加載支持SHA256的加密提供程序的情況下完成驗證。 因此,我應該能夠在返回上述方法之前執行此操作:
RSACryptoServiceProvider csp = (RSACryptoServiceProvider)privateCert.PrivateKey;
var enhCsp = new RSACryptoServiceProvider().CspKeyContainerInfo;
mKeyContainerName = csp.CspKeyContainerInfo.KeyContainerName;
var cspparams = new CspParameters
(
enhCsp.ProviderType, enhCsp.ProviderName, mKeyContainerName
);
csp = new RSACryptoServiceProvider(cspparams);
// Sign the hash
byte[] signature = csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA256"));
// Test to verify the signed hash with public cert
csp = (RSACryptoServiceProvider)publicCert.PublicKey.Key;
if (!csp.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA256"), signature))
throw new CryptographicException();
return signature;
但是,這不會驗證(順便說一句,我已經嘗試過SignData / VerifyData和SignHash / VerifyHash )。 我可以讓它驗證的唯一方法是我是否再次明確加載一個支持SHA256的加密提供程序。 不幸的是,從公共證書構造的CspKeyContainerInfo的KeyContainerName成員始終為null。 因此,我可以獲得數據驗證的唯一方法是緩存(或硬編碼)私鑰的KeyContainerName。 因此,上面的方法和片段中的mKeyContainerName字段的原因如下:
// Test to verify the signed hash with public cert
csp = (RSACryptoServiceProvider)publicCert.PublicKey.Key;
enhCsp = new RSACryptoServiceProvider().CspKeyContainerInfo;
cspparams = new CspParameters
(
enhCsp.ProviderType, enhCsp.ProviderName, mKeyContainerName
);
csp = new RSACryptoServiceProvider(cspparams);
if (!csp.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA256"), signature))
throw new CryptographicException();
這確實驗證了,但我不喜歡硬編碼私鑰的KeyContainerName 。 私鑰在進行驗證的計算機上不可用。
有誰知道更好的方法來實現這一目標? 謝謝!
我偶然發現了自己的答案。 原來使用makecert.exe創建的自簽名證書是罪魁禍首。 如果我使用使用OpenSSL或商業證書創建的證書,我不再需要顯式加載支持SHA256的加密提供程序。 因此,我不必在用於實例化RSACryptoServiceProvider的CspParameters對象中對容器名稱進行硬編碼。 此簽名代碼現在按預期工作:
RSACryptoServiceProvider csp = (RSACryptoServiceProvider)privateCert.PrivateKey;
// Sign the hash
byte[] signature = csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA256"));
驗證方面也是如此:
// Test to verify the signed hash with public cert
csp = (RSACryptoServiceProvider)publicCert.PublicKey.Key;
我從來沒有發現makecert.exe生成的證書有什么不同,但它對我來說並不重要,因為我們現在正在簽署商業證書。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.