如何使用c#密码检索签名散列算法友好名称? [英] How to retrieve the Signature hash algorithm friendly name using c# cryptography?

查看:136
本文介绍了如何使用c#密码检索签名散列算法友好名称?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



  private static bool Sign_Verify(X509Certificate2 x509,byte [] random_data )
{
//
//局部变量定义
//
bool isVerified = false;
byte [] buffer = Encoding.Default.GetBytes(Hello World ...!);
byte [] signature_Data = null;
byte [] signature_Hash = null;
//
//检索所选证书的私钥。
//
RSACryptoServiceProvider privateKey

= x509.PrivateKey作为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);

//
//使用私钥执行签名
尝试
{
signature_Hash = privateKey.SignHash(
hash,
CryptoConfig.MapNameToOID(SHA256));
if(null == signature_Hash)
{
Console.WriteLine(Error:SignHash\\\
\\\
);
} // if
else
{
Console.WriteLine(Signature_Hash generated ...... \\\
\\\
);
} // else
} //尝试
catch(CryptographicException)
{
//e.StackTrace();
} //捕获

//
//检索所选证书的公钥。
//
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(哈希验证签名失败。);
} //如果
else
{
Console.WriteLine(哈希签名验证成功。);
} // else

return isVerified;
} // Sign_Verify

在HashAlgorithm.Create(SHA256); ,我们对签名散列算法的名称进行了硬编码。如何获取证书的签名散列算法的名称而不是硬编码呢? 解决方案

似乎没有在.NET中从证书获得签名散列算法的简单方法。你可以做的是首先得到签名算法OID

  cert.SignatureAlgorithm.Value; 

然后您需要以某种方式将此OID(例如,带有RSA加密的SHA256)映射到OID或只是哈希算法的名称,不加密(只是SHA256)。你可以自己建立这样的地图,或者使用现有的地图,例如Bouncy Castle图书馆有一个。不幸的是它包含在内部类中,所以你将不得不使用一些反射来实现它。因此,首先添加对Bouncy Castle的引用(通过nuget),然后:

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

这将获取内部CmsSignedHelper类的private digestAlgs字段的值,该字段仅包含您需要的地图。

然后你可以这样做:

  var hashAlgName =(string)map [cert.SignatureAlgorithm.Value]; //使用RSA为sha256的OID返回SHA256。 
var hashAlg = HashAlgorithm.Create(hashAlgName); //你的SHA256


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?

解决方案

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

这篇关于如何使用c#密码检索签名散列算法友好名称?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆