• RSA加密、解密、签名、校验签名


    先说下RSA概率:

    公钥和私钥是通过本地openssl软件生成。

    正常:

    公钥加密=》私钥解密;

    私钥签名=》公钥校验签名

    最近做一个项目,对方用java公钥去校验签名,这边java的Demo使用私钥来加密的。

    代码如下:

    public class SignAccess {
    
    
    
    
        public String REQ_SERIAL_NO="";
        public String REQ_TIME="";
        public String ENV_FLAG="";
        public String  APP_ID="";
          public String PRIVATE_KEY="";
    
        public SignAccess(String REQ_SERIAL_NO, String REQ_TIME, String ENV_FLAG, String APP_ID,String PRIVATE_KEY) {
            this.REQ_SERIAL_NO = REQ_SERIAL_NO;
            this.REQ_TIME = REQ_TIME;
            this.ENV_FLAG = ENV_FLAG;
            this.APP_ID = APP_ID;
            this.PRIVATE_KEY = PRIVATE_KEY;
        }
    
        /**
         * 获取对应的sign值
         * @return
         */
        public  String getSign(){
            //组装输入参数map
            Map<String,Object> map = new HashMap<>();
            map.put("REQ_SERIAL_NO", REQ_SERIAL_NO);
            map.put("REQ_TIME", REQ_TIME);
            map.put("ENV_FLAG", ENV_FLAG);
            map.put("APP_ID", APP_ID);
                //给map排序后转换为字符串
            StringBuilder sb = new StringBuilder();
            final Map<String,Object>  sortMap = new TreeMap(new Comparator<String>() {
    
                @Override
                public int compare(String str1, String str2) {
                    return str1.compareTo(str2);
                }
            });
            sortMap.putAll(map);
            for (final Map.Entry<String,Object> entry : sortMap.entrySet()) {
                sb = sb.append(entry.getKey()).append(entry.getValue());
            }
            String dest =  sb.toString();
            //sha256加密
            String strDes=encrypt(dest);
            //私钥加密
            byte[] enBytes = null;
            byte[] data;
            try {
                data = strDes.getBytes("UTF-8");
                final Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
                cipher.init(Cipher.ENCRYPT_MODE, getPrivateKey(PRIVATE_KEY));
                for (int i = 0; i < data.length; i += 128) {
                    final byte[] doFinal = cipher.doFinal(ArrayUtils.subarray(data, i, i + 128));
                    enBytes = ArrayUtils.addAll(enBytes, doFinal);
                }
                try {
                    return Base64.encodeBase64String(enBytes);
                } catch (final Exception e) {
                    System.err.println("Base64出错");
                }
            } catch (final Exception e) {
                System.err.println("私钥加密出错");
            }
            return "";
        }
    
        /**
         * 秘钥转换方法
         * @param key
         * @return
         */
        public  PrivateKey getPrivateKey(String key){
            java.security.Security.addProvider(
                    new org.bouncycastle.jce.provider.BouncyCastleProvider()
            );
            byte[] keyBytes;
            keyBytes = Base64.decodeBase64(key);
            final PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory;
            try {
                keyFactory = KeyFactory.getInstance("RSA");
                final PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
                return privateKey;
            } catch (final Exception e) {
                System.err.println("获取私钥出错");
            }
            return null;
        }
    
        private  String encrypt(final String strSrc) {
    
            MessageDigest md = null;
            String strDes = null;
            try {
                // byte[] bt = strSrc.getBytes();
                md = MessageDigest.getInstance("SHA-256");
                // md.update(bt);
                try {
                    strDes = bytesToHexString(md.digest(strSrc.getBytes("UTF-8")));
                } catch (final UnsupportedEncodingException e) {
                     System.err.println("编码失败");
                }
            } catch (final NoSuchAlgorithmException e) {
                 System.err.println("编码失败");
    
            }
            return strDes;
        }
        /**
         * 转16进制
         *
         * @param src
         * @return
         */
        private  String bytesToHexString(final byte[] src) {
    
            final StringBuilder stringBuilder = new StringBuilder("");
            if (src == null || src.length <= 0) {
                return null;
            }
            for (int i = 0; i < src.length; i++) {
                final int v = src[i] & 0xFF;
                final String hv = Integer.toHexString(v);
                if (hv.length() < 2) {
                    stringBuilder.append(0);
                }
                stringBuilder.append(hv);
            }
            return stringBuilder.toString();
        }
    
       
        public static void main(String args[])
        {
    
            String privateKey="MIICWwIBAAKBgQC2TSwydOrZ0Ija3YbloMWXQP6xOIn1DUOiOHCYJkRYTk+FviR+
    P6EOOSwPLFcd91k65jHZOF91pifQf6tHzFQjhc0phTGWsjpHPhGeJ6tgzSZr5xIQ
    mCp4xPW4x7N0Y1vciz3ZBfTZyMu2k3iHgbxT8uPeKDKD2vZhC0FEOVU0oQIDAQAB
    AoGAarwma2he9KaO6i4XxCxsY9GPDW3///UDK2CGM9771wQKtVCNh0lz36MDs+KP
    IyFmIgETII5L/dMJrp6BRylP/PsWWQAZqfoI7FQbKFWKnvTGhDxCtW7FvZOq9MhG
    VMA5BfdE4zBgauo9kYdqzsKxIzndE5EJg4j86pFZwn6BWb0CQQDjWnoh25AXEHhw
    Fo5Gd0N5aceK4uFQ5DukTUSH1y5b/z4Q5OvC3JopjUMVfDYk32C+sSw3zF9PuCK8
    XmIE476rAkEAzUV/P6onzngqIiXPtpd5EuDKDM+4pvxJine7+2onY3rCtA1LFaLn
    laIrAQ/2/b0Ub4cJMNxID4v1WDfBYo1p4wJADe2qE87uuesBZeSL3NdLo/GODv0t
    TpZc7QjqzOOq7GnrtH9BzlNTgn4sAPH2IzYoKCaUjeqQYELopd+mY6RMNwJAJO8s
    RjhHkU7txdcn2KLIliz8LfHyN5mNYezJViNzkuKzxdHegLYfFT1on3hP6LfsxWR2
    suPv01xLeOQPV7w6IQJAO/bB2Ul7hRAgyHzlBMZoVEMY4LGfd41yDzrrpNjr2JUT
    dsrXPbduLGGEdqE4M4uM/T+Vg3elAWM+eW7tGD2v5w==";
            String reqSerialNo="1234567890";
            String reqTime="1234567890";
            String envFlag="0";
            String appId="1234567890";
            SignAccess signAccess=new SignAccess(reqSerialNo,reqTime,envFlag,appId,privateKey);
            System.out.println(signAccess.getSign());
        }
    }
    View Code

    c#试了N多方式,没有做到签名一致。这里贴下c#的加密和签名的代码

    加密解密代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Security.Cryptography;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace RSA加密
    {
        public class RSACSharp
        {
    
            public static void test()
            {
                string de = "iBILuPJFgPMxgpbgN3F2JjD6XjcqRSApjVVbvBBEBDV21Pjj7lTrfhEjSVnJX/MVoZrmX0lxsvoXTMvvVwVF7K7W5hs7Qo+aMN96yWke7wiLEM9M4pPz60A/KSckskiona67tXcqOLXb8N18TKaNCKHv0Ce+GyEKK5+MT7e1vao=";
                //string encrypt = RSAEncrypt("", "chenhailong");   
                byte[] encrypt = RSAEncrypt("APP_IDA2018030910304500031ENV_FLAG0REQ_SERIAL_NO20170310155124REQ_TIME20170310155124");
                string name = RSADecrypt(encrypt);   
                //string name = RSADecrypt(Convert.FromBase64String(de));
                Console.WriteLine(encrypt.Length);
                Console.WriteLine(Convert.ToBase64String(encrypt));
                Console.WriteLine(name);
                Console.ReadKey();
            }
    
            /// <summary>   
            /// RSA encrypt   
            /// </summary>   
            /// <param name="publickey"></param>   
            /// <param name="content"></param>   
            /// <returns></returns>   
            public static byte[] RSAEncrypt(string content)
            {
                string publickey = @"<RSAKeyValue><Modulus>5m9m14XH3oqLJ8bNGw9e4rGpXpcktv9MSkHSVFVMjHbfv+SJ5v0ubqQxa5YjLN4vc49z7SVju8s0X4gZ6AzZTn06jzWOgyPRV54Q4I0DCYadWW4Ze3e+BOtwgVU1Og3qHKn8vygoj40J6U85Z/PTJu3hN1m75Zr195ju7g9v4Hk=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
    
                string pKey = @"-----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2TSwydOrZ0Ija3YbloMWXQP6x
    OIn1DUOiOHCYJkRYTk+FviR+P6EOOSwPLFcd91k65jHZOF91pifQf6tHzFQjhc0p
    hTGWsjpHPhGeJ6tgzSZr5xIQmCp4xPW4x7N0Y1vciz3ZBfTZyMu2k3iHgbxT8uPe
    KDKD2vZhC0FEOVU0oQIDAQAB
    -----END PUBLIC KEY-----";
                string pk= EncryptionHelper.RSA_KeyJavaToCsharp(pKey, false);
                RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
                byte[] cipherbytes;
                rsa.FromXmlString(pk);
                cipherbytes = rsa.Encrypt(Encoding.UTF8.GetBytes(content), false);
    
                //return Convert.ToBase64String(cipherbytes);   
                return cipherbytes;
            }
    
            /// <summary>   
            /// RSA decrypt   
            /// </summary>   
            /// <param name="privatekey"></param>   
            /// <param name="content"></param>   
            /// <returns></returns>   
            public static string RSADecrypt(byte[] content)
            {
                string privatekey = @"<RSAKeyValue><Modulus>5m9m14XH3oqLJ8bNGw9e4rGpXpcktv9MSkHSVFVMjHbfv+SJ5v0ubqQxa5YjLN4vc49z7SVju8s0X4gZ6AzZTn06jzWOgyPRV54Q4I0DCYadWW4Ze3e+BOtwgVU1Og3qHKn8vygoj40J6U85Z/PTJu3hN1m75Zr195ju7g9v4Hk=</Modulus><Exponent>AQAB</Exponent><P>/hf2dnK7rNfl3lbqghWcpFdu778hUpIEBixCDL5WiBtpkZdpSw90aERmHJYaW2RGvGRi6zSftLh00KHsPcNUMw==</P><Q>6Cn/jOLrPapDTEp1Fkq+uz++1Do0eeX7HYqi9rY29CqShzCeI7LEYOoSwYuAJ3xA/DuCdQENPSoJ9KFbO4Wsow==</Q><DP>ga1rHIJro8e/yhxjrKYo/nqc5ICQGhrpMNlPkD9n3CjZVPOISkWF7FzUHEzDANeJfkZhcZa21z24aG3rKo5Qnw==</DP><DQ>MNGsCB8rYlMsRZ2ek2pyQwO7h/sZT8y5ilO9wu08Dwnot/7UMiOEQfDWstY3w5XQQHnvC9WFyCfP4h4QBissyw==</DQ><InverseQ>EG02S7SADhH1EVT9DD0Z62Y0uY7gIYvxX/uq+IzKSCwB8M2G7Qv9xgZQaQlLpCaeKbux3Y59hHM+KpamGL19Kg==</InverseQ><D>vmaYHEbPAgOJvaEXQl+t8DQKFT1fudEysTy31LTyXjGu6XiltXXHUuZaa2IPyHgBz0Nd7znwsW/S44iql0Fen1kzKioEL3svANui63O3o5xdDeExVM6zOf1wUUh/oldovPweChyoAdMtUzgvCbJk1sYDJf++Nr0FeNW1RB1XG30=</D></RSAKeyValue>";
    
                string priK = @"-----BEGIN RSA PRIVATE KEY-----
    MIICWwIBAAKBgQC2TSwydOrZ0Ija3YbloMWXQP6xOIn1DUOiOHCYJkRYTk+FviR+
    P6EOOSwPLFcd91k65jHZOF91pifQf6tHzFQjhc0phTGWsjpHPhGeJ6tgzSZr5xIQ
    mCp4xPW4x7N0Y1vciz3ZBfTZyMu2k3iHgbxT8uPeKDKD2vZhC0FEOVU0oQIDAQAB
    AoGAarwma2he9KaO6i4XxCxsY9GPDW3///UDK2CGM9771wQKtVCNh0lz36MDs+KP
    IyFmIgETII5L/dMJrp6BRylP/PsWWQAZqfoI7FQbKFWKnvTGhDxCtW7FvZOq9MhG
    VMA5BfdE4zBgauo9kYdqzsKxIzndE5EJg4j86pFZwn6BWb0CQQDjWnoh25AXEHhw
    Fo5Gd0N5aceK4uFQ5DukTUSH1y5b/z4Q5OvC3JopjUMVfDYk32C+sSw3zF9PuCK8
    XmIE476rAkEAzUV/P6onzngqIiXPtpd5EuDKDM+4pvxJine7+2onY3rCtA1LFaLn
    laIrAQ/2/b0Ub4cJMNxID4v1WDfBYo1p4wJADe2qE87uuesBZeSL3NdLo/GODv0t
    TpZc7QjqzOOq7GnrtH9BzlNTgn4sAPH2IzYoKCaUjeqQYELopd+mY6RMNwJAJO8s
    RjhHkU7txdcn2KLIliz8LfHyN5mNYezJViNzkuKzxdHegLYfFT1on3hP6LfsxWR2
    suPv01xLeOQPV7w6IQJAO/bB2Ul7hRAgyHzlBMZoVEMY4LGfd41yDzrrpNjr2JUT
    dsrXPbduLGGEdqE4M4uM/T+Vg3elAWM+eW7tGD2v5w==
    -----END RSA PRIVATE KEY-----";
                string pk = EncryptionHelper.RSA_KeyJavaToCsharp(priK, true);
                RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
                byte[] cipherbytes;
                rsa.FromXmlString(pk);
                cipherbytes = rsa.Decrypt(content, false);
    
                return Encoding.UTF8.GetString(cipherbytes);
            }
        }
    }
    View Code

    将java密钥转换为c#密钥方法:

            ///RSA秘钥
            ///是否为RSA私钥:true:是|false:否
            /// 
            public static string RSA_KeyJavaToCsharp(string rsakeys, bool isPrivateKey)
            {
                try
                {
                    using (var memoryStream = new MemoryStream())
                    using (var streamWriter = new StreamWriter(memoryStream))
                    using (var streamReader = new StreamReader(memoryStream))
                    {
                        streamWriter.Write(rsakeys);
                        streamWriter.Flush();
                        memoryStream.Position = 0;
                        var pemReader = new PemReader(streamReader);
                        object keys = pemReader.ReadObject();
                        RSA rsaservice = isPrivateKey ? GetPrivateRSACSharp(keys) : GetPublicRSACsharp(keys);
                        return rsaservice.ToXmlString(isPrivateKey);
                    }
                }
                catch (Exception ex)
                {
                    throw new Exception("Asymmetric cipher key is error");
                }
            }
    
            ///
    
            /// 传入RSA秘钥对象返回读取秘钥后的RSA对象
            ///
    
            ///RSA私钥
            /// 
            private static RSA GetPrivateRSACSharp(object rsakeys)
            {
                //根据传入对象 强制转化为需要的对象 提供已经读取私钥的RSA对象
                if ((rsakeys as RsaPrivateCrtKeyParameters) != null)
                    return DotNetUtilities.ToRSA((RsaPrivateCrtKeyParameters)rsakeys);
                var keys = (AsymmetricCipherKeyPair)rsakeys;
                return DotNetUtilities.ToRSA((RsaPrivateCrtKeyParameters)keys.Private);
            }
    
    
            ///
    
            /// 传入RSA秘钥对象返回读取秘钥后的RSA对象
            ///
    
            ///RSA公钥
            /// 
            private static RSA GetPublicRSACsharp(object rsakeys)
            {
                //提供已经读取公钥钥的RSA对象
                var keys = (RsaKeyParameters)rsakeys;
                return DotNetUtilities.ToRSA(keys);
            }
    View Code

    签名的方法:

            ///
    
            /// RSA C# 填充签名
            ///
    
            ///私钥
            ///待签名字符串
            ///编码对象
            ///加密算法
            /// 
            public static string RSA_GetSignCsharp(string privateKey, string body, Encoding encoding, EncryptType encryptType = EncryptType.MD5)
            {
                try
                {
                    using (RSACryptoServiceProvider rsaservice = new RSACryptoServiceProvider())
                    {
                        rsaservice.FromXmlString(privateKey);
                        RSAPKCS1SignatureFormatter rsasignformatter = new RSAPKCS1SignatureFormatter(rsaservice);
                        rsasignformatter.SetHashAlgorithm(encryptType.ToString());
                        encoding = encoding ?? Encoding.UTF8;
                        byte[] hashBytes = GetComputeHash(body, encoding, encryptType);
                        byte[] signBytes = rsasignformatter.CreateSignature(hashBytes);
                        return Convert.ToBase64String(signBytes);
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
    
            ///
    
            /// 根据编码及Hash类型计算Hash值
            ///
    
            ///待计算Hash值得字符串
            ///编码对象
            ///Hash类型
            /// 
            public static byte[] GetComputeHash(string body, Encoding encoding, EncryptType encryptType)
            {
                encoding = encoding ?? Encoding.UTF8;
                byte[] sourceBytes = encoding.GetBytes(body);
                return GetComputeHash(sourceBytes, encryptType);
            }
    View Code

    校验签名方法:

            ///
    
            /// RSA C# 验证签名
            ///
    
            ///公钥
            ///待验证数据
            ///签名结果
            ///编码 可传NULL
            ///签名时加密方式 可传NULL
            /// 
            public static bool RSA_GetVerifyCsharp(string publicKey, string body, string signature, Encoding encoding, EncryptType encryptType = EncryptType.MD5)
            {
                try
                {
                    using (RSACryptoServiceProvider rsaservice = new RSACryptoServiceProvider())
                    {
                        rsaservice.FromXmlString(publicKey);//加载公钥
                        RSAPKCS1SignatureDeformatter rsasignformatter = new RSAPKCS1SignatureDeformatter(rsaservice);
                        rsasignformatter.SetHashAlgorithm(encryptType.ToString());//设置算法
                        encoding = encoding ?? Encoding.UTF8;
                        var dataBytes = GetComputeHash(body, encoding, encryptType);
                        var signBytes = Convert.FromBase64String(signature);
                        return rsasignformatter.VerifySignature(dataBytes, signBytes);
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
    View Code

    最后按照java代码来翻译代码也没有成功,就用IKVM将jar包转换为dll终于达到目的。

    第一步:将java代码打包,我这里用的idea打的包,百度下都有,这里不重复介绍。

    https://www.cnblogs.com/qifengshi/p/6036870.html

    https://jingyan.baidu.com/article/7e4409531fbf292fc1e2ef51.html

    第二步:将jar包转换为dll。

    转的步骤:https://www.cnblogs.com/rucwxb/p/7494586.html

    这里要注意下:IKVM一定要用最新版本8.1.7版本,才能转java8,开始用的7.2版本,怎么转引用包都出问题。

    第三步:将dll引用。

  • 相关阅读:
    Python 面向对象(一)
    【Python之搜索引擎】(一)概述
    【Python】回文palindrome——利用字符串反转
    【Python】raw转义字符
    【Python】directory字典类型
    【Python】面向对象编程思想
    【Python】Sublime text 3 搭建Python IDE
    【Python】卸载完Python3 之后 Python2 无法打开IDLE
    【Python】猜数小游戏(文件操作)
    【Python】list和tuple 区别比较
  • 原文地址:https://www.cnblogs.com/zhuyapeng/p/8669684.html
Copyright © 2020-2023  润新知