I followed this great tutorial on digitally signing / verifying data using .NET. I changed this sample code to use SHA256 and hit the "Invalid algorithm defined" exception, which led me to this SO question about signing data with SHA256 in .NET 4.0.
One of the answers from this post helped me figure out how to correctly generate a digital signature by explicitly loading the crypto provider supporting SHA256, without relying on the exported private one (see the code at the bottom of the following method where RSACryptoServiceProvider is built ):
static string mKeyContainerName;
static byte[] SignText(string text, string publicCertPath)
{
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
X509Certificate2 publicCert = new X509Certificate2(publicCertPath);
publicCert.Verify();
string publicHash = publicCert.GetCertHashString();
X509Certificate2 privateCert = null;
foreach(X509Certificate2 cert in store.Certificates)
{
if(cert.GetCertHashString() == publicHash)
{
privateCert = cert;
break;
}
}
store.Close();
if(privateCert == null)
{
throw new Exception("No valid private cert was found");
}
UnicodeEncoding encoding = new UnicodeEncoding();
byte[] data = encoding.GetBytes(text);
SHA256Managed sha256 = new SHA256Managed();
byte[] hash = sha256.ComputeHash(data);
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);
return csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA256"));
}
, , makecert.exe. , -sp -sy makercert.exe. ( -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);
byte[] signature = csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA256"));
csp = (RSACryptoServiceProvider)publicCert.PublicKey.Key;
if (!csp.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA256"), signature))
throw new CryptographicException();
return signature;
(BTW, SignData/VerifyDatastrong > , SignHash/VerifyHash). , , - , SHA256. , KeyContainerName CspKeyContainerInfo, , null. , , , - ( ) KeyContainerName. , mKeyContainerName :
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. , .
- , ? !