使用SHA256WithRSA来签名和验签(.NET/C#)

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)

public string Sign(string contentForSign,string priKeyFile, string keyPwd)
{
var rsa = GetPrivateKey(priKeyFile,keyPwd);
// Create a new RSACryptoServiceProvider
var rsaClear = new RSACryptoServiceProvider();
// Export RSA parameters from 'rsa' and import them into 'rsaClear'
var paras = rsa.ExportParameters(true);
rsaClear.ImportParameters(paras);
using (var sha256 = new SHA256CryptoServiceProvider())
{
var signData = rsa.SignData(Encoding.UTF8.GetBytes(contentForSign), sha256);
return BytesToHex(signData);
}
} public bool VerifySign(string contentForSign, string signedData,pubKeyFile)
{
var rsa = GetPublicKey(pubKeyFile); using (var sha256 = new SHA256CryptoServiceProvider())
{
return rsa.VerifyData(Encoding.UTF8.GetBytes(contentForSign), sha256, HexToBytes(signedData));
}
} /// <summary>
/// 获取签名证书私钥
/// </summary>
/// <param name="priKeyFile"></param>
/// <param name="keyPwd"></param>
/// <returns></returns>
private static RSACryptoServiceProvider GetPrivateKey(string priKeyFile, string keyPwd)
{
var pc = new X509Certificate2(priKeyFile, keyPwd, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet);
return (RSACryptoServiceProvider) pc.PrivateKey;
} /// <summary>
/// 获取验签证书
/// </summary>
/// <param name="pubKeyFile"></param>
/// <returns></returns>
private static RSACryptoServiceProvider GetPublicKey(string pubKeyFile)
{
var pc = new X509Certificate2(pubKeyFile);
return (RSACryptoServiceProvider) pc.PublicKey.Key;
}
  public static byte[] HexToBytes(string text)
{
if (text.Length % != )
throw new ArgumentException("text 长度为奇数。"); List<byte> lstRet = new List<byte>();
for (int i = ; i < text.Length; i = i + )
{
lstRet.Add(Convert.ToByte(text.Substring(i, ), ));
}
return lstRet.ToArray();
} /// <summary>
/// bytes转换hex
/// </summary>
/// <param name="data">bytes</param>
/// <returns>转换后的hex字符串</returns>
public static string BytesToHex(byte[] data)
{
StringBuilder sbRet = new StringBuilder(data.Length * );
for (int i = ; i < data.Length; i++)
{
sbRet.Append(Convert.ToString(data[i], ).PadLeft(, ''));
}
return sbRet.ToString();
}

https://*.com/questions/10673146/signature-with-sha256

上一篇:springboot系列十二、springboot集成RestTemplate及常见用法


下一篇:【转】CoreData以及MagicalRecord (一)