SHA256签名 [英] signature with SHA256

查看:246
本文介绍了SHA256签名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个智能卡,我需要为此签名文件. 正如我在stackover中看到的那样,这是一个大问题.

我无法使用RSACryptoServiceProvider,bkz它不支持RSA-SHA256算法.

起初,我使用CAPICOM.dll,例如下面的代码

SignedData sed = new SignedData();
sed.Content = "a"; // data to sign
Signer ser = new Signer();
ser.Certificate = cc;
string singnn = sed.Sign(ser, false, CAPICOM_ENCODING_TYPE.CAPICOM_ENCODE_BASE64);

但是没有公共密钥来验证我的签名值,我无法从capicom.dll获取验证密钥.

然后,

我使用了X509Certificate2和RSACryptoServiceProvider之类的代码,如下所示,

        X509Certificate2 certificate = new X509Certificate2();
        // Access Personal (MY) certificate store of current user
        X509Store my = new X509Store(StoreName.My, StoreLocation.CurrentUser);
        my.Open(OpenFlags.ReadOnly);

        // Find the certificate we'll use to sign            
        RSACryptoServiceProvider csp = null;
        foreach (X509Certificate2 cert in my.Certificates)
        {
            if (cert.Subject.Contains(certSubject))
            {
                // We found it. 
                // Get its associated CSP and private key
                certificate = cert;
                csp = (RSACryptoServiceProvider)cert.PrivateKey;
            }
        }
        if (csp == null)
        {
            throw new Exception("No valid cert was found");
        }

        // Hash the data
        SHA1Managed sha1 = new SHA1Managed();
        UnicodeEncoding encoding = new UnicodeEncoding();
        byte[] data = encoding.GetBytes(text);
        byte[] hash = sha1.ComputeHash(data);

        //byte[] data = Encoding.UTF8.GetBytes(text);
        //HashAlgorithm sha = new SHA256Managed();
        //byte[] hash = sha.TransformFinalBlock(data, 0, data.Length);

        string key = csp.ToXmlString(false);
        // Sign the hash
        csp.PersistKeyInCsp = true;
        byte[] response = csp.SignData(data, CryptoConfig.MapNameToOID("SHA1"));
        string signbase64 = Convert.ToBase64String(response);

它可以工作,但是我需要使用RSA-SHA256算法进行签名. 当我改变这样的哈希算法

byte[] response = csp.SignData(data, CryptoConfig.MapNameToOID("SHA256"));

我得到

错误:未指定的错误".

那是我的问题, 解决方案是什么,或者我应该使用哪个库?

谢谢您的建议.

解决方案

RSACryptoServiceProvider确实可以使用基于SHA2的签名,但是您必须为此付出一些努力.

当您使用证书获取RSACryptoServiceProvider时,真正重要的是底层的CryptoAPI提供程序.默认情况下,当您使用"makecert"创建证书时,它是"RSA-FULL",仅支持SHA1哈希进行签名.您需要新的支持SHA2的"RSA-AES".

因此,您可以使用其他选项创建证书:-sp"Microsoft增强型RSA和AES密码提供程序"(或等效的-sy 24),然后您的代码将如下所示(在.NET 4.0中):

var rsa = signerCertificate.PrivateKey as RSACryptoServiceProvider;
//
byte[] signature = rsa.SignData(data, CryptoConfig.CreateFromName("SHA256"));

如果您无法更改证书的颁发方式,则有一个半合法的解决方法,该解决方法基于以下事实:默认情况下,RSACryptoServiceProvider是在支持SHA2的情况下创建的.因此,以下代码也可以使用,但是有点难看: (此代码的作用是创建一个新的RSACryptoServiceProvider并从我们从证书中获得的密钥中导入密钥)

var rsa = signerCertificate.PrivateKey as RSACryptoServiceProvider;
// Create a new RSACryptoServiceProvider
RSACryptoServiceProvider rsaClear = new RSACryptoServiceProvider();
// Export RSA parameters from 'rsa' and import them into 'rsaClear'
rsaClear.ImportParameters(rsa.ExportParameters(true));
byte[] signature = rsaClear.SignData(data, CryptoConfig.CreateFromName("SHA256"));

希望这对您有所帮助.

I have a smartcard and I need to sign a file with this. That is a big problem as I see in stackover.

I couldnt use RSACryptoServiceProvider, bkz it doesnt support RSA-SHA256 alogrithm.

At First I used CAPICOM.dll , like code bellow,

SignedData sed = new SignedData();
sed.Content = "a"; // data to sign
Signer ser = new Signer();
ser.Certificate = cc;
string singnn = sed.Sign(ser, false, CAPICOM_ENCODING_TYPE.CAPICOM_ENCODE_BASE64);

But there isnt a public key to validate my signature value,, I couldnt get a validate key from capicom.dll.

And after ,

I used X509Certificate2 , and RSACryptoServiceProvider like code below,

        X509Certificate2 certificate = new X509Certificate2();
        // Access Personal (MY) certificate store of current user
        X509Store my = new X509Store(StoreName.My, StoreLocation.CurrentUser);
        my.Open(OpenFlags.ReadOnly);

        // Find the certificate we'll use to sign            
        RSACryptoServiceProvider csp = null;
        foreach (X509Certificate2 cert in my.Certificates)
        {
            if (cert.Subject.Contains(certSubject))
            {
                // We found it. 
                // Get its associated CSP and private key
                certificate = cert;
                csp = (RSACryptoServiceProvider)cert.PrivateKey;
            }
        }
        if (csp == null)
        {
            throw new Exception("No valid cert was found");
        }

        // Hash the data
        SHA1Managed sha1 = new SHA1Managed();
        UnicodeEncoding encoding = new UnicodeEncoding();
        byte[] data = encoding.GetBytes(text);
        byte[] hash = sha1.ComputeHash(data);

        //byte[] data = Encoding.UTF8.GetBytes(text);
        //HashAlgorithm sha = new SHA256Managed();
        //byte[] hash = sha.TransformFinalBlock(data, 0, data.Length);

        string key = csp.ToXmlString(false);
        // Sign the hash
        csp.PersistKeyInCsp = true;
        byte[] response = csp.SignData(data, CryptoConfig.MapNameToOID("SHA1"));
        string signbase64 = Convert.ToBase64String(response);

It works , but I need to sign with RSA-SHA256 algorithm. When I changw hash algorithm like this

byte[] response = csp.SignData(data, CryptoConfig.MapNameToOID("SHA256"));

I m getting an

error : "unspecified error".

Thats my problem, What is the sollution , or which library should I use ??

Thanks for any advice..

解决方案

RSACryptoServiceProvider does work with SHA2-based signatures, but you have to invest some effort into it.

When you use a certificate to get your RSACryptoServiceProvider it really matters what's the underlying CryptoAPI provider. By default, when you create a certificate with 'makecert', it's "RSA-FULL" which only supports SHA1 hashes for signature. You need the new "RSA-AES" one that supports SHA2.

So, you can create your certificate with an additional option: -sp "Microsoft Enhanced RSA and AES Cryptographic Provider" (or an equivalent -sy 24) and then your code would look like (in .NET 4.0):

var rsa = signerCertificate.PrivateKey as RSACryptoServiceProvider;
//
byte[] signature = rsa.SignData(data, CryptoConfig.CreateFromName("SHA256"));

If you are unable to change the way your certificate is issued, there is a semi-ligitimate workaround that is based on the fact that by default RSACryptoServiceProvider is created with support for SHA2. So, the following code would also work, but it is a bit uglier: (what this code does is it creates a new RSACryptoServiceProvider and imports the keys from the one we got from the certificate)

var rsa = signerCertificate.PrivateKey as RSACryptoServiceProvider;
// Create a new RSACryptoServiceProvider
RSACryptoServiceProvider rsaClear = new RSACryptoServiceProvider();
// Export RSA parameters from 'rsa' and import them into 'rsaClear'
rsaClear.ImportParameters(rsa.ExportParameters(true));
byte[] signature = rsaClear.SignData(data, CryptoConfig.CreateFromName("SHA256"));

Hope you find this helpful.

这篇关于SHA256签名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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