How to retrieve the Signature hash algorithm friendly name using c# cryptography?

冷暖自知 提交于 2020-03-19 06:29:00

问题


The following function uses a certificate to sign and verify.

private static bool Sign_Verify(X509Certificate2 x509, byte[] random_data)
        {
            //
            // Local variable definitions
            //
            bool isVerified = false;
            byte[] buffer = Encoding.Default.GetBytes("Hello World ... !");
            byte[] signature_Data = null;
            byte[] signature_Hash = null;
            //
            // Retrieve the private key of the certificate selected.
            //
            RSACryptoServiceProvider privateKey

                                  = x509.PrivateKey as RSACryptoServiceProvider;

        if (null == privateKey)
        {
            Console.WriteLine("Invalid Private Key");
        } // if
        else
        {
            Console.WriteLine("Certificate has private key.");
        } // else

        HashAlgorithm hashAlgo = HashAlgorithm.Create("SHA256");

        byte[] hash = hashAlgo.ComputeHash(random_data);

        //
        // Perform signing using the private key
        try
        {
            signature_Hash = privateKey.SignHash(
                                                    hash,
                                                    CryptoConfig.MapNameToOID("SHA256"));
            if (null == signature_Hash)
            {
                Console.WriteLine("Error: SignHash\n\n");
            } // if
            else
            {
                Console.WriteLine("Signature_Hash generated......\n\n");
            } // else
        } // try
        catch (CryptographicException)
        {
            //e.StackTrace();
        } // catch

        //
        // Retrieve the public key of the certificate selected.
        //
        RSACryptoServiceProvider publicKey

                                    = x509.PublicKey.Key as RSACryptoServiceProvider;
        if (null == publicKey)
        {
            Console.WriteLine("Invalid Public Key");
        } // if
        else
        {
            Console.WriteLine("Certificate has public key.");
        } // else


         isVerified = publicKey.VerifyHash(
                                                hash,
                                                CryptoConfig.MapNameToOID("SHA256"),
                                                signature_Hash);
        if (false == isVerified)
        {
            Console.WriteLine("Signature of Hash verification failed.");
        } // if
        else
        {
            Console.WriteLine("Signature of Hash verified successfully.");
        } // else

        return isVerified;
    } // Sign_Verify 

In the HashAlgorithm.Create("SHA256"); , we are hard coding the name of signature hash algorithm. How to get the name of the signature hash algorithm of the certificate instead of hard coding it?


回答1:


It seems that there is no easy way to get signature hash algorithm from certificate in .NET. What you can do is first get signature algorithm OID

cert.SignatureAlgorithm.Value;

Then you need to somehow map this OID (this can be for example SHA256 with RSA encryption) to OID or name of just hash algorithm, without encryption (just SHA256). You can either build such map yourself, or use existing maps, for example Bouncy Castle library has one. Unfortunately it contains it in internal class, so you will have to use some reflection to get to it. So add reference to Bouncy Castle first (via nuget), then:

var mapField = typeof(Org.BouncyCastle.Cms.CmsSignedData).Assembly.GetType("Org.BouncyCastle.Cms.CmsSignedHelper").GetField("digestAlgs", BindingFlags.Static | BindingFlags.NonPublic);
var map = (System.Collections.IDictionary) mapField.GetValue(null);

This will grab value of private digestAlgs field of internal CmsSignedHelper class, which contains just the map you need.

Then you do:

var hashAlgName = (string)map[cert.SignatureAlgorithm.Value];// returns "SHA256" for OID of sha256 with RSA.
var hashAlg = HashAlgorithm.Create(hashAlgName); // your SHA256


来源:https://stackoverflow.com/questions/36277604/how-to-retrieve-the-signature-hash-algorithm-friendly-name-using-c-sharp-cryptog

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!