C#.NET CORE .NET6 RSA 私钥签名 公钥验签(验证签名) ver:20230614

环境说明:

.NET CORE 版本:.NET 6 。

.NET CORE 对于RSA的支持:

1. .NET 6 中内置了对 PKCS1,PKCS8 2种私钥格式的支持。

2.私钥字符串要去除"-----BEGIN RSA PRIVATE KEY-----"、"-----END RSA PRIVATE KEY-----"、"-----BEGIN PRIVATE KEY-----"、"-----END PRIVATE KEY-----"和换行符。

3.公钥要去除:"-----BEGIN PUBLIC KEY-----"、"-----END PUBLIC KEY-----"和换行符。

注意:.NET CORE 加载公钥为 rsaPub.ImportSubjectPublicKeyInfo。

核心重点是拿到 .NET CORE 的RSA  对象。

签名(双方要协商好编码):

1.将原始报文用UTF8转为byte数组。(参数为byte[] data) 原始报文的编码双方要协商好。

2.调用 SignData(byte[] data, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) 方法,其中HashAlgorithmName 是HASH算法,双方要协商好,有:SHA256、SHA1、MD5。SHA256对应JAVA的 SHA256withRSA. (其它还有 SHA1withRSA,MD5withRSA),RSASignaturePadding 一般是Pkcs1.

3.将输出结果转为BASE64字符串。输出结果转字符串的编码,双方要协商好,不一定用BASE64。

公钥验签:

1.将原始报文用UTF8转为byte数组。(参数为byte[] data)

2.将签名串(BASE64字符串)用Convert.FromBase64String()转为byte数组。(参数为:byte[] signature)

3.使用  VerifyData(byte[] data, byte[] signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) ; 方法验签。其中HashAlgorithmName 是HASH算法,有:SHA256、SHA1、MD5。RSASignaturePadding 一般是Pkcs1.

用“支付宝开放平台开发助手”生成一组公私钥:

PKCS8私钥:

MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBAMz0Czg6QUtTISa2pUkloeQB/TEpHdqrfyroWpKLW9B/LWFSOGH9nyTk1pPZaeadyEZQ6gay/C0pUAetLraq9bMA/Luxq68b87uG7WX7dKytEO2/87qGpGMRs97H+GlkzWil2QO2KK4cHnAcVicPsmi5aZ72U0BWJFyPhtd+qdmrAgMBAAECgYEAvW67iAbgHt0BASVD9C3iSjpEaVHVlC165o/IVzaTcEx8Bz3Ve0zN8W3JnvIO3ebsG4HiLLr2Nk++9rltOc0eNeGMv7F1e/OFot1wN0ON6s1g4bYh1z5Uz8FcYiMWcqHHICrx+oSFeK9x+I2Zge7enQXcsVnqEhm77ZE5YczSryECQQD9nB58e5efYchF+cYbmURioX18cUMuhQbB9Aq2N55cd689Lg35KZqT8JQTp/8tQSdCJG8d2nU8VKspUKTEAuaDAkEAzuKIIoc9PVJvy90LhIPA9c1S8BPCI7EMCaTZqJ5o3VaR2dqvUZDGX7kL3kYkQ+n7mq3KIECvkEFzA+FOP96XuQJBAJQTKHW0T/YeSKoayUHp/lS8R6F2HCy4PRbXn71+wfbpZqcJEd2OHhQM3tiPOV258esbjMlYeSUNppZL4LgVnXMCQQC7Lvs9Ql+GPDAqo7ToEM1lmICR906QPIBHuX+1sJ3wpYMROWumwPa7ZRH36j6ls+6R5OwcgmpWeuE1gYTrBNsBAkEAn2pEtAljX1foQff6CLozYg/J6J9RmVFcJ6qz0LX3052qNFBQYw8CMHB7VkVNzsDIDC8LX5uP2pzTrdPLew+pPA==

与之匹配的 PKCS1 私钥,用助手转换的:

MIICXwIBAAKBgQDM9As4OkFLUyEmtqVJJaHkAf0xKR3aq38q6FqSi1vQfy1hUjhh/Z8k5NaT2WnmnchGUOoGsvwtKVAHrS62qvWzAPy7sauvG/O7hu1l+3SsrRDtv/O6hqRjEbPex/hpZM1opdkDtiiuHB5wHFYnD7JouWme9lNAViRcj4bXfqnZqwIDAQABAoGBAL1uu4gG4B7dAQElQ/Qt4ko6RGlR1ZQteuaPyFc2k3BMfAc91XtMzfFtyZ7yDt3m7BuB4iy69jZPvva5bTnNHjXhjL+xdXvzhaLdcDdDjerNYOG2Idc+VM/BXGIjFnKhxyAq8fqEhXivcfiNmYHu3p0F3LFZ6hIZu+2ROWHM0q8hAkEA/ZwefHuXn2HIRfnGG5lEYqF9fHFDLoUGwfQKtjeeXHevPS4N+Smak/CUE6f/LUEnQiRvHdp1PFSrKVCkxALmgwJBAM7iiCKHPT1Sb8vdC4SDwPXNUvATwiOxDAmk2aieaN1Wkdnar1GQxl+5C95GJEPp+5qtyiBAr5BBcwPhTj/el7kCQQCUEyh1tE/2HkiqGslB6f5UvEehdhwsuD0W15+9fsH26WanCRHdjh4UDN7YjzldufHrG4zJWHklDaaWS+C4FZ1zAkEAuy77PUJfhjwwKqO06BDNZZiAkfdOkDyAR7l/tbCd8KWDETlrpsD2u2UR9+o+pbPukeTsHIJqVnrhNYGE6wTbAQJBAJ9qRLQJY19X6EH3+gi6M2IPyeifUZlRXCeqs9C199OdqjRQUGMPAjBwe1ZFTc7AyAwvC1+bj9qc063Ty3sPqTw=

与之匹配的公钥:

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDM9As4OkFLUyEmtqVJJaHkAf0xKR3aq38q6FqSi1vQfy1hUjhh/Z8k5NaT2WnmnchGUOoGsvwtKVAHrS62qvWzAPy7sauvG/O7hu1l+3SsrRDtv/O6hqRjEbPex/hpZM1opdkDtiiuHB5wHFYnD7JouWme9lNAViRcj4bXfqnZqwIDAQAB

示例代码:

// See https://aka.ms/new-console-template for more information


using System.Security.Cryptography;
using System.Text;

try
{
    //PKCS8格式私钥
    string strPriPkcs8 = "MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBAMz0Czg6QUtTISa2pUkloeQB/TEpHdqrfyroWpKLW9B/LWFSOGH9nyTk1pPZaeadyEZQ6gay/C0pUAetLraq9bMA/Luxq68b87uG7WX7dKytEO2/87qGpGMRs97H+GlkzWil2QO2KK4cHnAcVicPsmi5aZ72U0BWJFyPhtd+qdmrAgMBAAECgYEAvW67iAbgHt0BASVD9C3iSjpEaVHVlC165o/IVzaTcEx8Bz3Ve0zN8W3JnvIO3ebsG4HiLLr2Nk++9rltOc0eNeGMv7F1e/OFot1wN0ON6s1g4bYh1z5Uz8FcYiMWcqHHICrx+oSFeK9x+I2Zge7enQXcsVnqEhm77ZE5YczSryECQQD9nB58e5efYchF+cYbmURioX18cUMuhQbB9Aq2N55cd689Lg35KZqT8JQTp/8tQSdCJG8d2nU8VKspUKTEAuaDAkEAzuKIIoc9PVJvy90LhIPA9c1S8BPCI7EMCaTZqJ5o3VaR2dqvUZDGX7kL3kYkQ+n7mq3KIECvkEFzA+FOP96XuQJBAJQTKHW0T/YeSKoayUHp/lS8R6F2HCy4PRbXn71+wfbpZqcJEd2OHhQM3tiPOV258esbjMlYeSUNppZL4LgVnXMCQQC7Lvs9Ql+GPDAqo7ToEM1lmICR906QPIBHuX+1sJ3wpYMROWumwPa7ZRH36j6ls+6R5OwcgmpWeuE1gYTrBNsBAkEAn2pEtAljX1foQff6CLozYg/J6J9RmVFcJ6qz0LX3052qNFBQYw8CMHB7VkVNzsDIDC8LX5uP2pzTrdPLew+pPA==";
    //PKCS1格式私钥
    string strPriPkcs1 = "MIICXwIBAAKBgQDM9As4OkFLUyEmtqVJJaHkAf0xKR3aq38q6FqSi1vQfy1hUjhh/Z8k5NaT2WnmnchGUOoGsvwtKVAHrS62qvWzAPy7sauvG/O7hu1l+3SsrRDtv/O6hqRjEbPex/hpZM1opdkDtiiuHB5wHFYnD7JouWme9lNAViRcj4bXfqnZqwIDAQABAoGBAL1uu4gG4B7dAQElQ/Qt4ko6RGlR1ZQteuaPyFc2k3BMfAc91XtMzfFtyZ7yDt3m7BuB4iy69jZPvva5bTnNHjXhjL+xdXvzhaLdcDdDjerNYOG2Idc+VM/BXGIjFnKhxyAq8fqEhXivcfiNmYHu3p0F3LFZ6hIZu+2ROWHM0q8hAkEA/ZwefHuXn2HIRfnGG5lEYqF9fHFDLoUGwfQKtjeeXHevPS4N+Smak/CUE6f/LUEnQiRvHdp1PFSrKVCkxALmgwJBAM7iiCKHPT1Sb8vdC4SDwPXNUvATwiOxDAmk2aieaN1Wkdnar1GQxl+5C95GJEPp+5qtyiBAr5BBcwPhTj/el7kCQQCUEyh1tE/2HkiqGslB6f5UvEehdhwsuD0W15+9fsH26WanCRHdjh4UDN7YjzldufHrG4zJWHklDaaWS+C4FZ1zAkEAuy77PUJfhjwwKqO06BDNZZiAkfdOkDyAR7l/tbCd8KWDETlrpsD2u2UR9+o+pbPukeTsHIJqVnrhNYGE6wTbAQJBAJ9qRLQJY19X6EH3+gi6M2IPyeifUZlRXCeqs9C199OdqjRQUGMPAjBwe1ZFTc7AyAwvC1+bj9qc063Ty3sPqTw=";
    //公钥
    string strPub = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDM9As4OkFLUyEmtqVJJaHkAf0xKR3aq38q6FqSi1vQfy1hUjhh/Z8k5NaT2WnmnchGUOoGsvwtKVAHrS62qvWzAPy7sauvG/O7hu1l+3SsrRDtv/O6hqRjEbPex/hpZM1opdkDtiiuHB5wHFYnD7JouWme9lNAViRcj4bXfqnZqwIDAQAB";

    string strDJM = "泰酷拉!123ABC";//待签名字符串
    strDJM = "泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC";//待加密字符串,超过117字符的测试

    Console.WriteLine("待签名字符串:" + strDJM);

    //一、私钥签名
    //获取私钥对象
    //转为纯字符串,不带格式
    strPriPkcs1 = strPriPkcs1.Replace("-----BEGIN RSA PRIVATE KEY-----", "").Replace("-----END RSA PRIVATE KEY-----", "").Replace("\r", "").Replace("\n", "").Trim();
    strPriPkcs1 = strPriPkcs1.Replace("-----BEGIN PRIVATE KEY-----", "").Replace("-----END PRIVATE KEY-----", "").Replace("\r", "").Replace("\n", "").Trim();
    RSA rsaPri = RSA.Create();
    rsaPri.ImportRSAPrivateKey(Convert.FromBase64String(strPriPkcs1), out _);
    //如果私钥是PKCS8格式:rsaPri.ImportPkcs8PrivateKey(Convert.FromBase64String(privateKeyPem), out _);

    //待签名字符串 转为byte 数组
    byte[] byToSign = Encoding.UTF8.GetBytes(strDJM); // 编码要和其它语言一致,一般是:UTF8 
    byte[] bySigned = rsaPri.SignData(byToSign, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);//SHA256,对应JAVA,SHA256withRSA,签名结果是 byte 数组
    string strSigned = Convert.ToBase64String(bySigned);//将byte 数组转为字符串,方便传输,一般是base64字符串,其它类型需和对方协商
    Console.WriteLine("签名值:" + strSigned);

    //二、公钥验签(验证签名)
    //获取公钥对象
    strPub = strPub.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "").Replace("\r", "").Replace("\n", "").Trim();
    RSA rsaPub = RSA.Create();
    rsaPub.ImportSubjectPublicKeyInfo(Convert.FromBase64String(strPub), out _);
    //将对方的签名值转为BYTE数组。
    byte[] byToCheckSign = Convert.FromBase64String(strSigned);
    //将原始报文转为byte数组
    byte[] byBody = Encoding.UTF8.GetBytes(strDJM);// 编码要和其它语言一致,一般是:UTF8 
                                                   //验证签名
    bool bCheck = rsaPub.VerifyData(byBody, byToCheckSign, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);//验证签名双方要保持一致
    Console.WriteLine("验证签名:" + bCheck.ToString());

}
catch (Exception ex)
{
    Console.WriteLine("ex:" + ex.Message);
}


Console.WriteLine("Hello, World!");
Console.ReadKey();

.NET CORE 与.NET FRAMEWORK的区别。

签名:

.NET CORE:SignData(byte[] data, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) ,默认3个参数,后2个得是枚举。

.NET FRAMEWORK:SignData(byte[] buffer, object halg),默认2参数,halg 可以是字符串。

验证签名:

.NET CORE:VerifyData(byte[] data, byte[] signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding),默认4个参数,后2个得是枚举。

.NET FRAMEWORK:VerifyData(byte[] buffer, object halg, byte[] signature),默认3参数,halg 可以是字符串。 data(buffer) 和 signature 的顺序有变化。

-

06-14 17:49