How can I (correctly) verify a file using RSA and SHA256 with .NET?

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)
{
    // 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. , -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);

// 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;

(BTW, SignData/VerifyData​​strong > , SignHash/VerifyHash). , , - , SHA256. , KeyContainerName CspKeyContainerInfo, , 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. , .

- , ? !

+4
1

. , , makecert.exe, . , OpenSSL , , SHA256. , CspParameters, RSACryptoServiceProvider. , :

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, , .

0

Source: https://habr.com/ru/post/1599000/


All Articles