使用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 % 2 != 0) 
                throw new ArgumentException("text 长度为奇数。"); 
 
            List<byte> lstRet = new List<byte>(); 
            for (int i = 0; i < text.Length; i = i + 2) 
            { 
                lstRet.Add(Convert.ToByte(text.Substring(i, 2), 16)); 
            } 
            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 * 2); 
            for (int i = 0; i < data.Length; i++) 
            { 
                sbRet.Append(Convert.ToString(data[i], 16).PadLeft(2, '0')); 
            } 
            return sbRet.ToString(); 
        }

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

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/15841.html

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论