首页 > 编程语言 >C#.NET Framework 使用BC库(BouncyCastle) RSA 私钥签名 公钥验签(验证签名) ver:20230704

C#.NET Framework 使用BC库(BouncyCastle) RSA 私钥签名 公钥验签(验证签名) ver:20230704

时间:2023-07-04 10:34:17浏览次数:37  
标签:20230704 BouncyCastle string Replace ----- 签名 123ABC 泰酷

C#.NET Framework 使用BC库(BouncyCastle) RSA 私钥签名 公钥验签(验证签名) ver:20230704

 

环境说明:

.NET Framework 4.6 的控制台程序 。

 

2020年以后 ,有部分PKCS8私钥(openssl生成)无法用RsaUtil.LoadPrivateKey(strPriPkcs8, "PKCS8")来解析 (https://www.cnblogs.com/runliuv/p/17474269.html)

 可以尝试用BC库来处理。

 

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

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

 

关键代码:

BC库,私钥转换,默认支持PKCS8:

private static AsymmetricKeyParameter GetPrivateKeyParameter(string privateKeyPem)
        {
            //获取私钥纯字符串
            privateKeyPem = privateKeyPem.Replace("-----BEGIN RSA PRIVATE KEY-----", "").Replace("-----END RSA PRIVATE KEY-----", "").Replace("\r", "").Replace("\n", "").Trim();
            privateKeyPem = privateKeyPem.Replace("-----BEGIN PRIVATE KEY-----", "").Replace("-----END PRIVATE KEY-----", "").Replace("\r", "").Replace("\n", "").Trim();

            byte[] privateInfoByte = Convert.FromBase64String(privateKeyPem);

            AsymmetricKeyParameter priKey = PrivateKeyFactory.CreateKey(privateInfoByte);
            return priKey;
        }

公钥转换:

private static AsymmetricKeyParameter GetPublicKeyParameter(string publicKeyPem)
        {
            //获取公钥纯字符串
            publicKeyPem = publicKeyPem.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "").Replace("\r", "").Replace("\n", "").Trim();

            byte[] publicInfoByte = Convert.FromBase64String(publicKeyPem);

            AsymmetricKeyParameter pubKey = PublicKeyFactory.CreateKey(publicInfoByte);
            return pubKey;
        }

BCSignUtil 辅助类,nuget 中引用 Portable.BouncyCastle。

using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Security;
using System;
using System.Text;

namespace CommonUtils
{
    public static class BCSignUtil
    {
        /// <summary>
        /// 签名
        /// </summary>
        /// <param name="orgData">原数据字符串</param>
        /// <param name="privateKeyPKCS8">必须是PKCS8的</param>
        /// <param name="algorithm">算法</param>
        /// <returns></returns>
        public static string SignData(string orgData, string privateKeyPKCS8, string algorithm)
        {
            if (string.IsNullOrEmpty(orgData))
                throw new Exception("字符串不能为空!");

            if (string.IsNullOrEmpty(privateKeyPKCS8))
                throw new Exception("privateKeyPKCS8不能为空!");

            if (string.IsNullOrEmpty(privateKeyPKCS8))
                throw new Exception("algorithm 不能为空!");

            AsymmetricKeyParameter priKey = GetPrivateKeyParameter(privateKeyPKCS8);

            byte[] byteData = Encoding.UTF8.GetBytes(orgData);

            ISigner normalSig = SignerUtilities.GetSigner(algorithm);
            normalSig.Init(true, priKey);
            normalSig.BlockUpdate(byteData, 0, byteData.Length);//注意:是byte数组和数组长度,别写成string的长度了
            byte[] normalResult = normalSig.GenerateSignature(); //签名结果
            string sign = Convert.ToBase64String(normalResult);

            return sign;
        }

        private static AsymmetricKeyParameter GetPrivateKeyParameter(string privateKeyPem)
        {
            //获取私钥纯字符串
            privateKeyPem = privateKeyPem.Replace("-----BEGIN RSA PRIVATE KEY-----", "").Replace("-----END RSA PRIVATE KEY-----", "").Replace("\r", "").Replace("\n", "").Trim();
            privateKeyPem = privateKeyPem.Replace("-----BEGIN PRIVATE KEY-----", "").Replace("-----END PRIVATE KEY-----", "").Replace("\r", "").Replace("\n", "").Trim();

            byte[] privateInfoByte = Convert.FromBase64String(privateKeyPem);

            AsymmetricKeyParameter priKey = PrivateKeyFactory.CreateKey(privateInfoByte);
            return priKey;
        }

        /// <summary>
        /// 验证签名
        /// </summary>
        /// <param name="orgData">原数据字符串</param>
        /// <param name="publicKeyPem">公钥</param>
        /// <param name="responseSign">对方的签名串</param>
        /// <param name="algorithm">算法</param>
        /// <returns></returns>
        public static bool VerifySignature(string orgData, string publicKeyPem, string responseSign, string algorithm)
        {

            AsymmetricKeyParameter pubKey = GetPublicKeyParameter(publicKeyPem);

            byte[] signBytes = Convert.FromBase64String(responseSign);
            byte[] plainBytes = Encoding.UTF8.GetBytes(orgData);

            ISigner verifier = SignerUtilities.GetSigner(algorithm);
            verifier.Init(false, pubKey);
            verifier.BlockUpdate(plainBytes, 0, plainBytes.Length);//注意:是byte数组和数组长度,别写成string的长度了

            bool isOK = verifier.VerifySignature(signBytes); //验签结果
            return isOK;
        }

        private static AsymmetricKeyParameter GetPublicKeyParameter(string publicKeyPem)
        {
            //获取公钥纯字符串
            publicKeyPem = publicKeyPem.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "").Replace("\r", "").Replace("\n", "").Trim();

            byte[] publicInfoByte = Convert.FromBase64String(publicKeyPem);

            AsymmetricKeyParameter pubKey = PublicKeyFactory.CreateKey(publicInfoByte);
            return pubKey;
        }


    }
}

使用代码:

using CommonUtils;
using System;

namespace ConsoleNetFxRsa加密签名使用BC库
{
    class Program
    {
        static void Main(string[] args)
        {
            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);                

                #region 一、私钥签名
                //string algorithm = "SHA1withRSA";
                string algorithm = "SHA256withRSA";
                string strSigned = BCSignUtil.SignData(strDJM, strPriPkcs8, algorithm); //PKCS8
                Console.WriteLine("签名值:" + strSigned);
                #endregion

                #region 二、公钥验签(验证签名)
                //二、公钥验签(验证签名)
                //验证签名
                bool bCheck = BCSignUtil.VerifySignature(strDJM, strPub, strSigned, algorithm);//验证签名双方要保持一致
                Console.WriteLine("验证签名:" + bCheck.ToString());
                #endregion
            }
            catch (Exception ex)
            {
                Console.WriteLine("ex:" + ex.Message);
            }

            Console.WriteLine("hello END.");
            Console.ReadKey();
        }
    }
}

 

标签:20230704,BouncyCastle,string,Replace,-----,签名,123ABC,泰酷
From: https://www.cnblogs.com/runliuv/p/17525028.html

相关文章

  • PowerShell脚本数字签名错误
    1.以管理员身份打开powershell,使用get-executionpolicy-list查看策略设置2.将所有的scope的值为:undefined具体设置的命令是:Set-ExecutionPolicy-ExecutionPolicyundefined-ScopeLocalMachine3.找到报错中提示中有问题的xxx.ps1脚本,选中该脚本,右键选择属性,然后勾选“解......
  • uni.app 签名 canvas 变成图片 上传图片 移动端 h5
     使用canvas 即脚本绘制图形<template> <view> <viewclass="wrapper"> <viewclass="handBtn"> <button@click="retDraw"class="delBtn">重写</button> <!--<button@click="......
  • 接口签名规则和Java实现签名和验签代码
    接口签名规则和Java实现签名和验签代码签名规则 签名生成的通用步骤如下: 第一步,设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。 特别注意以下重要规则: ◆......
  • vue使用电子签名插件vue-esign
    功能描述:1,兼容PC和Mobile;2,画布自适应屏幕大小变化(窗口缩放、屏幕旋转时画布无需重置,自动校正坐标偏移);3,自定义画布尺寸(导出图尺寸),画笔粗细、颜色,画布背景色;4,支持裁剪(针对需求:有的签字需要裁剪掉四周空白)。5,导出图片格式为base64;第一步:安装:npminstallvue-esign--save第二......
  • Android自动化签名
    APK 签名 V1自动化签名脚本  命令结构为:jarsigner -verbose -keystore release.jks -storepass xxx -keypass xxx -sigfile CERT -signedjar app-sign.apk app-release-jiagu.apk xxx参数解释:jarsigner: 签名工具,安装好jdk环境即可直接使用-verbose: ......
  • RSA 加密签名验签解密
    importjavax.crypto.Cipher;importjavax.crypto.spec.OAEPParameterSpec;importjavax.crypto.spec.PSource;importjava.security.*;importjava.security.spec.MGF1ParameterSpec;importjava.security.spec.PKCS8EncodedKeySpec;importjava.security.spec.X509Enc......
  • jmeter测试签名接口
    Jmeter测试签名接口一.了解签名规则1.常见的签名规则:业务数据+当前时间戳2.签名方式:md5(大部分)二.接口信息1.Ip和端口号:10.196.104:80802.接口路径:/pinter/com/userInfo3.请求类型:post4.数据类型:json5.请求参数:{ "phoneNum":"123434", "optCode":"testfan", "timestamp":"......
  • Android应用签名
    为了要签名?   开发Android的人这么多,完全有可能大家都把类名,包名起成了一个同样的名字,这时候如何区分?签名这时候就是起区分作用的。   由于开发商可能通过使用相同的PackageName来混淆替换已经安装的程序,签名可以保证相当名字,但是签名不同的包不被替换。   APK如果使......
  • 获取文件嵌套签名[转]
    Msdn的Sample只是获取单个签名, 现给出获取多个嵌套签名的心法.//参考网址https://social.msdn.microsoft.com/Forums/sqlserver/en-US/40dcf50b-c637-4d7d-b0c0-598a61f96f8c/rfc3161-timestamp-information-in-digital-signature-authenticode?forum=windowsgeneraldevelopme......
  • org/bouncycastle/util/Encodable not found
    08:39:30.719[main]DEBUGcn.com.jit.new_vstk.dataAggregator.AbsRecevieChunk-receviecosttime:0ms08:39:30.719[main]DEBUGjar.org.apache.http.impl.conn.PoolingHttpClientConnectionManager-Connection[id:1][route:{}->http://192.168.1.222:8000]......