SHA256签名 [英] signature with 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屋!