• RSA 加密 解密 (长字符串) JAVA JS版本加解密


    系统与系统的数据交互中,有些敏感数据是不能直接明文传输的,所以在发送数据之前要进行加密,在接收到数据时进行解密处理;然而由于系统与系统之间的开发语言不同。

    本次需求是生成二维码是通过java生成,由php来解密。基于这类需求所以选择了RSA进行加解密。

    生成RSA公私钥分成三步生成,第1、2步可以满足php的使用,由于java的私钥要转化为PKCS8格式才能使用,所以执行第3步来实现。

    还有一种加密方式参考: DES ECB 模式 JAVA PHP C# 实现 加密 解密 兼容 。

    1、生成私钥

    openssl genrsa -out rsa_private_key.pem 1024 

    如下:

    复制代码
    -----BEGIN RSA PRIVATE KEY-----
    MIICXQIBAAKBgQC6BSDlbRplhMMNZBKHX4xe8AwESpzHVfAcHHsX9FFSMuF91W3c
    xgT/g5n+qlLLFzCE3hWG/yX5NMAxR4mS3MlhyXKwko3tK9Ua691afod1lxORR3Ia
    Z8nV7v5Bv8y4JDe4E3/f/bQIGzroWiJ0sXTcO41GqvOw3G9leClSvjVnSwIDAQAB
    AoGAagooYYCbTomq4wRL562ZCDmQsBWUX7Fmia/Wn6YfgVsN3bx/vx2Gld2AOIMB
    ZVJXzzYGUYk7LV9bu/vKudRwWvtPIYzxPEOBoaFGPrEPTAfDVwOklhzTz3zDmCHi
    hLSpjQXYCG7boZ6G96NfKyTRSGPqgovHY3+KJvd/gAoZqOkCQQDt9YXfanpuwZx1
    7MYjMEvoh5UY1vSsV72ts3/gTVEUkWdfXHj0XhyRhOL9Qu99TGZcoEwecygoUPLm
    dySyiXl/AkEAyB+JP8W7oTG/HTHc5QGDfwlPjIH1o5YG2I8Tp02i3G7OTJc/b9/+
    SPxcKsT78xrgox5ModPKBX50F783Y2DANQJBAKY4Mjp882b4gWVybnlYHD4ir0h5
    ptHYPFvgnfu9plx6sT3Qp4DzWHth2vlUT1w0CPC83E8M28lFula4dP7tvtsCQQCt
    a2asdNVbophS3FrnuKAS/iaJRDVxRRk5oQMPACAZlYwAozC96gWZidb02S7cRHZV
    5HPT6IwwppxD19hPrg/hAkBdnl+BGF/eRw80OHJtZBkLnY4Hx9YGft9AyIp3SB1z
    QDhaWHgFA+8lED+bWTvJxt/IMmzyYBaGnZbEjCECKZLD
    -----END RSA PRIVATE KEY-----
    复制代码

    2、生成公钥

    openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

    如下:

    -----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6BSDlbRplhMMNZBKHX4xe8AwE
    SpzHVfAcHHsX9FFSMuF91W3cxgT/g5n+qlLLFzCE3hWG/yX5NMAxR4mS3MlhyXKw
    ko3tK9Ua691afod1lxORR3IaZ8nV7v5Bv8y4JDe4E3/f/bQIGzroWiJ0sXTcO41G
    qvOw3G9leClSvjVnSwIDAQAB
    -----END PUBLIC KEY-----

    3、将RSA私钥转换成PKCS8格式

    openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt > java_rsa_private_key.pem

    如下:

    复制代码
    -----BEGIN PRIVATE KEY-----
    MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALoFIOVtGmWEww1k
    EodfjF7wDARKnMdV8Bwcexf0UVIy4X3VbdzGBP+Dmf6qUssXMITeFYb/Jfk0wDFH
    iZLcyWHJcrCSje0r1Rrr3Vp+h3WXE5FHchpnydXu/kG/zLgkN7gTf9/9tAgbOuha
    InSxdNw7jUaq87Dcb2V4KVK+NWdLAgMBAAECgYBqCihhgJtOiarjBEvnrZkIOZCw
    FZRfsWaJr9afph+BWw3dvH+/HYaV3YA4gwFlUlfPNgZRiTstX1u7+8q51HBa+08h
    jPE8Q4GhoUY+sQ9MB8NXA6SWHNPPfMOYIeKEtKmNBdgIbtuhnob3o18rJNFIY+qC
    i8djf4om93+AChmo6QJBAO31hd9qem7BnHXsxiMwS+iHlRjW9KxXva2zf+BNURSR
    Z19cePReHJGE4v1C731MZlygTB5zKChQ8uZ3JLKJeX8CQQDIH4k/xbuhMb8dMdzl
    AYN/CU+MgfWjlgbYjxOnTaLcbs5Mlz9v3/5I/FwqxPvzGuCjHkyh08oFfnQXvzdj
    YMA1AkEApjgyOnzzZviBZXJueVgcPiKvSHmm0dg8W+Cd+72mXHqxPdCngPNYe2Ha
    +VRPXDQI8LzcTwzbyUW6Vrh0/u2+2wJBAK1rZqx01VuimFLcWue4oBL+JolENXFF
    GTmhAw8AIBmVjACjML3qBZmJ1vTZLtxEdlXkc9PojDCmnEPX2E+uD+ECQF2eX4EY
    X95HDzQ4cm1kGQudjgfH1gZ+30DIindIHXNAOFpYeAUD7yUQP5tZO8nG38gybPJg
    FoadlsSMIQIpksM=
    -----END PRIVATE KEY-----
    复制代码

    4.JAVA版本加解密:

    复制代码
    import org.apache.commons.codec.binary.Base64;
    import org.apache.commons.lang3.ArrayUtils;
    
    import javax.crypto.Cipher;
    import java.security.*;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    
    public class RSAUtils {
    
        /**
         * RSA最大加密明文大小
         */
        private static final int MAX_ENCRYPT_BLOCK = 117;
    
        /**
         * RSA最大解密密文大小
         */
        private static final int MAX_DECRYPT_BLOCK = 128;
    
        public static final String SIGN_ALGORITHMS = "SHA256withRSA";
    
        private static String ALGORITHM_RSA = "RSA";
    
        /**
         * 使用公钥将数据加密
         * @param sourceData
         * @param publicKey
         * @return
         */
        public static String publicEncrypt(String sourceData, String publicKey){
            return rsaEncrypt(sourceData,publicKey,false);
        }
    
        /**
         * 使用私钥将数据加密
         * @param sourceData
         * @param privateKey
         * @return
         */
        public static String privateEncrypt(String sourceData, String privateKey){
            return rsaEncrypt(sourceData,privateKey,true);
        }
    
    
        /**
         * 使用公钥解密
         * @param encryptedData
         * @param privateKey
         * @return
         */
        public static String publicDecrypt(String encryptedData, String privateKey) {
            return rsaDecrypt(encryptedData,privateKey,false);
        }
    
        /**
         * 使用私钥解密
         * @param encryptedData
         * @param privateKey
         * @return
         */
        public static String privateDecrypt(String encryptedData, String privateKey) {
            return rsaDecrypt(encryptedData,privateKey,true);
        }
    
        protected static String rsaEncrypt(String sourceData, String key,boolean isPrivate){
            try {
                Key key1 = isPrivate ? loadPrivateKey(key) : loadPublicKey(key);
                byte[] data = sourceData.getBytes();
                byte[] dataReturn = new byte[0];
                Cipher cipher = Cipher.getInstance(ALGORITHM_RSA);
                cipher.init(Cipher.ENCRYPT_MODE, key1);
    
                // 加密时超过117字节就报错。为此采用分段加密的办法来加密
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < data.length; i += MAX_ENCRYPT_BLOCK) {
                    byte[] doFinal = cipher.doFinal(ArrayUtils.subarray(data, i,i + MAX_ENCRYPT_BLOCK));
                    sb.append(new String(doFinal));
                    dataReturn = ArrayUtils.addAll(dataReturn, doFinal);
                }
    
                return Base64.encodeBase64URLSafeString(dataReturn);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
        protected static String rsaDecrypt(String encryptedData, String key,boolean isPrivate){
            try {
                Key key1 = isPrivate ? loadPrivateKey(key) : loadPublicKey(key);
                byte[] data = Base64.decodeBase64(encryptedData);
    
                Cipher cipher = Cipher.getInstance(ALGORITHM_RSA);
                cipher.init(Cipher.DECRYPT_MODE, key1);
    
                // 解密时超过128字节就报错。为此采用分段解密的办法来解密
                byte[] dataReturn = new byte[0];
                for (int i = 0; i < data.length; i += MAX_DECRYPT_BLOCK) {
                    byte[] doFinal = cipher.doFinal(ArrayUtils.subarray(data, i, i + MAX_DECRYPT_BLOCK));
                    dataReturn = ArrayUtils.addAll(dataReturn, doFinal);
                }
    
                return new String(dataReturn);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
        /**
         * 私钥加签名
         * @param encryptData
         * @param privateKey
         * @return
         */
        public static String rsaSign(String encryptData, String privateKey) {
            try {
                Signature signature = Signature.getInstance(SIGN_ALGORITHMS);
                signature.initSign(loadPrivateKey(privateKey));
                signature.update(encryptData.getBytes());
                byte[] signed = signature.sign();
                return Base64.encodeBase64URLSafeString(signed);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        /**
         * 公钥验签
         * @param encryptStr
         * @param sign
         * @param publicKey
         * @return
         * @throws Exception
         */
        public static boolean verifySign(String encryptStr, String sign, String publicKey)throws Exception {
            try {
                Signature signature = Signature.getInstance(SIGN_ALGORITHMS);
                signature.initVerify(loadPublicKey(publicKey));
                signature.update(encryptStr.getBytes());
                return signature.verify(Base64.decodeBase64(sign));
            }  catch (NoSuchAlgorithmException e) {
                throw new Exception(String.format("验证数字签名时没有[%s]此类算法", SIGN_ALGORITHMS));
            } catch (InvalidKeyException e) {
                throw new Exception("验证数字签名时公钥无效");
            } catch (SignatureException e) {
                throw new Exception("验证数字签名时出现异常");
            }
        }
    
        public static PublicKey loadPublicKey(String publicKeyStr) throws Exception {
            byte[] buffer = Base64.decodeBase64(publicKeyStr);
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
            return keyFactory.generatePublic(keySpec);
        }
    
        public static PrivateKey loadPrivateKey(String privateKeyStr) throws Exception {
            byte[] buffer = Base64.decodeBase64(privateKeyStr);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
            return keyFactory.generatePrivate(keySpec);
        }
    
        public  static String urlsafe_encode (String encryptStr){
            return encryptStr.replaceAll("\+","-").replaceAll("/","_").replaceAll("=","").replaceAll("(
    |
    |
    |
    
    )","");
    
        }
    
        public  static String urlsafe_decode(String encryptStr){
            encryptStr= encryptStr.replaceAll("-","+").replaceAll("_","/");
            int mob = encryptStr.length()%4;
            if(mob>0){
                encryptStr+="====".substring(mob);
            }
            return encryptStr;
        }
    
        public  static  void main(String[ ] asdfs) throws Exception {
            String publicKeyStr = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6BSDlbRplhMMNZBKHX4xe8AwE" +
                    "SpzHVfAcHHsX9FFSMuF91W3cxgT/g5n+qlLLFzCE3hWG/yX5NMAxR4mS3MlhyXKw" +
                    "ko3tK9Ua691afod1lxORR3IaZ8nV7v5Bv8y4JDe4E3/f/bQIGzroWiJ0sXTcO41G" +
                    "qvOw3G9leClSvjVnSwIDAQAB";
            String privateKeyStr = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALoFIOVtGmWEww1k" +
                    "EodfjF7wDARKnMdV8Bwcexf0UVIy4X3VbdzGBP+Dmf6qUssXMITeFYb/Jfk0wDFH" +
                    "iZLcyWHJcrCSje0r1Rrr3Vp+h3WXE5FHchpnydXu/kG/zLgkN7gTf9/9tAgbOuha" +
                    "InSxdNw7jUaq87Dcb2V4KVK+NWdLAgMBAAECgYBqCihhgJtOiarjBEvnrZkIOZCw" +
                    "FZRfsWaJr9afph+BWw3dvH+/HYaV3YA4gwFlUlfPNgZRiTstX1u7+8q51HBa+08h" +
                    "jPE8Q4GhoUY+sQ9MB8NXA6SWHNPPfMOYIeKEtKmNBdgIbtuhnob3o18rJNFIY+qC" +
                    "i8djf4om93+AChmo6QJBAO31hd9qem7BnHXsxiMwS+iHlRjW9KxXva2zf+BNURSR" +
                    "Z19cePReHJGE4v1C731MZlygTB5zKChQ8uZ3JLKJeX8CQQDIH4k/xbuhMb8dMdzl" +
                    "AYN/CU+MgfWjlgbYjxOnTaLcbs5Mlz9v3/5I/FwqxPvzGuCjHkyh08oFfnQXvzdj" +
                    "YMA1AkEApjgyOnzzZviBZXJueVgcPiKvSHmm0dg8W+Cd+72mXHqxPdCngPNYe2Ha" +
                    "+VRPXDQI8LzcTwzbyUW6Vrh0/u2+2wJBAK1rZqx01VuimFLcWue4oBL+JolENXFF" +
                    "GTmhAw8AIBmVjACjML3qBZmJ1vTZLtxEdlXkc9PojDCmnEPX2E+uD+ECQF2eX4EY" +
                    "X95HDzQ4cm1kGQudjgfH1gZ+30DIindIHXNAOFpYeAUD7yUQP5tZO8nG38gybPJg" +
                    "FoadlsSMIQIpksM=";
    
            //加密
            String data = "i like java";
            String privateEncryptStr = RSAUtils.privateEncrypt(data, privateKeyStr);
            String publicEncryptStr = RSAUtils.publicEncrypt(data, publicKeyStr);
            String privateEncryptSign = RSAUtils.rsaSign(privateEncryptStr,privateKeyStr);
            String publicEncryptSign = RSAUtils.rsaSign(publicEncryptStr,privateKeyStr);
    
            System.out.println("source:" + data);
            System.out.println("private encryptStr: " + privateEncryptStr);
            System.out.println("public encryptStr: " + publicEncryptStr);
            System.out.println("private encrypt sign: " + privateEncryptSign);
            System.out.println("public encrypt sign: " + publicEncryptSign);
            System.out.println("public decrypt:" + RSAUtils.publicDecrypt(privateEncryptStr, publicKeyStr));
            System.out.println("private decrypt:" + RSAUtils.privateDecrypt(publicEncryptStr, privateKeyStr));
            System.out.println("verifySign1: " + RSAUtils.verifySign(privateEncryptStr,privateEncryptSign,publicKeyStr));
            System.out.println("verifySign2: " + RSAUtils.verifySign(publicEncryptStr,publicEncryptSign,publicKeyStr));
    
            System.out.println("
    ");
            publicEncryptStr = "WopnO2LnolZ7XpOwA_ktOhfkkaQQJQgkJudk3ZH_-ob36GQFv968nE1UBXxNekA9pIHBcvcl0ZWfwFhk-kyOF2FmQvpPY9LkqiCV0T32vhJet0n93ti2PBoFILxvChjzdOgSG9M0flH78Vm696Q4mHo7VMt_XMoHDTd3Rbagvt8";
            privateEncryptStr = "Fwb5BtLRveCWbx7FkXarl1zVOdwDvbDTl7gv-vPHXpj-T2wm9GlUDn3X0wnHHXkE8cqAT6PcE0g0ide6beP9_ysHMLgnC6wVqkomIKsi6C9TcGd4d6XQBjeJgdgccvDcD-7pcKrV9W-_Z7jkYkwwrjPGPd_uckEHR_cDXyOX4PU";
            System.out.println("php >>>> private decrypt: " + RSAUtils.privateDecrypt(publicEncryptStr, privateKeyStr));
            System.out.println("php >>>> public decrypt: " + RSAUtils.publicDecrypt(privateEncryptStr, publicKeyStr));
    
            publicEncryptStr = "T2LFtY3dF_b6OBO07BN-3LtMSEBZqDukovDZ4HGCff8wosvlowf6IFJ3U7LFBIeHfiHBKiFuAV8-pFltCfTXtA4AwgVUnwbBMBWBfIJiLDi02ev30V-5BcYEuSF-cEdnSUd7WecrX4rHhzYLueGuj8H6c7RRbSbrJ6_3EFfU-K0";
            System.out.println("js >>>> private decrypt: " + RSAUtils.privateDecrypt(publicEncryptStr, privateKeyStr));
        }
    }
    复制代码

    输出如下:

    复制代码
    source: i like java
    private encryptStr: fHG5JMpTTF-KzrPCp827opRy3BvqmVIpIZS4gVuWqY5NeLsgoLxdrq3SaxUp_oBQ9pVqNlEiU9SIwbqJDjIqjHsCtVMOLoEdWicib_wCaoB16veKTEC4GnvviJwlS5IedH27oWGHKTTc6Ii5cLiQncjDAadvm0KCdC74yrwPqnc
    public encryptStr: raoQQsfN0KBfPAMRWnxr9kFPvJ6BgQ7PRBCMnz0nWsH03sD4IdlMvKpj78BHe7V7Ga1HZHyDxuJhVaJ0T5qKl8qHXzvKquzNtdMru7G4X9o8ylzkGxJLg-HYCWOrsZ77ZMaKoV9p-TCf-yMI21OpL_5JGot-XNfVVPkmg0z9FW0
    private encrypt sign: jlJvXY5t8KesDi3WaPr71jj2BigHLDr3b827Jl9xspbecdUjPB44Xe3sjWnzvFDLpKJGiNTvqE-Qyu3FZpG_NyI5yhVrAQgZmyYfVywmeDDsTOQYk1xP0UEfFgB0MXsFdlfSdMu5JcR5kgC5Xl5jds1b0Z2Nq7gQ-bvFJQcuHgU
    public encrypt sign: ngN2kQppfITyn5yAfNc1c-ofK20trKJWXIjlaJhWtm7s2jzv5rcsPY5JH06CMAIIbnKGIUcoVvMeKavAIVFb4G_h3CvXIYnxMjQL19Op-SbtyGNwT-rZzTEP8tKfxFRVm7SrHHDz2s287S3vqQz9vGEGNmgDHEdrCfHBmmoFkQA
    public decrypt: i like java
    private decrypt: i like java
    verifySign1: true
    verifySign2: true
     
    
    php >>>> private decrypt: i like php
    php >>>> public decrypt: i like php
    
    js >>>> private decrypt: i like JS
    复制代码

    5.PHP版本加解密

    复制代码
    <?php
    
    $private_key = <<<KEY
    -----BEGIN RSA PRIVATE KEY-----
    MIICXQIBAAKBgQC6BSDlbRplhMMNZBKHX4xe8AwESpzHVfAcHHsX9FFSMuF91W3c
    xgT/g5n+qlLLFzCE3hWG/yX5NMAxR4mS3MlhyXKwko3tK9Ua691afod1lxORR3Ia
    Z8nV7v5Bv8y4JDe4E3/f/bQIGzroWiJ0sXTcO41GqvOw3G9leClSvjVnSwIDAQAB
    AoGAagooYYCbTomq4wRL562ZCDmQsBWUX7Fmia/Wn6YfgVsN3bx/vx2Gld2AOIMB
    ZVJXzzYGUYk7LV9bu/vKudRwWvtPIYzxPEOBoaFGPrEPTAfDVwOklhzTz3zDmCHi
    hLSpjQXYCG7boZ6G96NfKyTRSGPqgovHY3+KJvd/gAoZqOkCQQDt9YXfanpuwZx1
    7MYjMEvoh5UY1vSsV72ts3/gTVEUkWdfXHj0XhyRhOL9Qu99TGZcoEwecygoUPLm
    dySyiXl/AkEAyB+JP8W7oTG/HTHc5QGDfwlPjIH1o5YG2I8Tp02i3G7OTJc/b9/+
    SPxcKsT78xrgox5ModPKBX50F783Y2DANQJBAKY4Mjp882b4gWVybnlYHD4ir0h5
    ptHYPFvgnfu9plx6sT3Qp4DzWHth2vlUT1w0CPC83E8M28lFula4dP7tvtsCQQCt
    a2asdNVbophS3FrnuKAS/iaJRDVxRRk5oQMPACAZlYwAozC96gWZidb02S7cRHZV
    5HPT6IwwppxD19hPrg/hAkBdnl+BGF/eRw80OHJtZBkLnY4Hx9YGft9AyIp3SB1z
    QDhaWHgFA+8lED+bWTvJxt/IMmzyYBaGnZbEjCECKZLD
    -----END RSA PRIVATE KEY-----
    KEY;
    
    $private8_key = <<<KEY
    -----BEGIN PRIVATE KEY-----
    MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALoFIOVtGmWEww1k
    EodfjF7wDARKnMdV8Bwcexf0UVIy4X3VbdzGBP+Dmf6qUssXMITeFYb/Jfk0wDFH
    iZLcyWHJcrCSje0r1Rrr3Vp+h3WXE5FHchpnydXu/kG/zLgkN7gTf9/9tAgbOuha
    InSxdNw7jUaq87Dcb2V4KVK+NWdLAgMBAAECgYBqCihhgJtOiarjBEvnrZkIOZCw
    FZRfsWaJr9afph+BWw3dvH+/HYaV3YA4gwFlUlfPNgZRiTstX1u7+8q51HBa+08h
    jPE8Q4GhoUY+sQ9MB8NXA6SWHNPPfMOYIeKEtKmNBdgIbtuhnob3o18rJNFIY+qC
    i8djf4om93+AChmo6QJBAO31hd9qem7BnHXsxiMwS+iHlRjW9KxXva2zf+BNURSR
    Z19cePReHJGE4v1C731MZlygTB5zKChQ8uZ3JLKJeX8CQQDIH4k/xbuhMb8dMdzl
    AYN/CU+MgfWjlgbYjxOnTaLcbs5Mlz9v3/5I/FwqxPvzGuCjHkyh08oFfnQXvzdj
    YMA1AkEApjgyOnzzZviBZXJueVgcPiKvSHmm0dg8W+Cd+72mXHqxPdCngPNYe2Ha
    +VRPXDQI8LzcTwzbyUW6Vrh0/u2+2wJBAK1rZqx01VuimFLcWue4oBL+JolENXFF
    GTmhAw8AIBmVjACjML3qBZmJ1vTZLtxEdlXkc9PojDCmnEPX2E+uD+ECQF2eX4EY
    X95HDzQ4cm1kGQudjgfH1gZ+30DIindIHXNAOFpYeAUD7yUQP5tZO8nG38gybPJg
    FoadlsSMIQIpksM=
    -----END PRIVATE KEY-----
    KEY;
    
    $public_key = <<<KEY
    -----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6BSDlbRplhMMNZBKHX4xe8AwE
    SpzHVfAcHHsX9FFSMuF91W3cxgT/g5n+qlLLFzCE3hWG/yX5NMAxR4mS3MlhyXKw
    ko3tK9Ua691afod1lxORR3IaZ8nV7v5Bv8y4JDe4E3/f/bQIGzroWiJ0sXTcO41G
    qvOw3G9leClSvjVnSwIDAQAB
    -----END PUBLIC KEY-----
    KEY;
    
    $data = 'i like php';
    //使用公钥将数据加密
    $encrypt_data = RsaUtils::publicEncrypt($data,$public_key);
    //使用私钥将数据解密
    $decrypt_data = RsaUtils::privateDecrypt($encrypt_data,$private_key);
    
    echo 'public encrypt data:'.$encrypt_data.PHP_EOL;
    echo 'private decrypt data:'.$decrypt_data.PHP_EOL;
    
    
    //使用私钥将数据加密
    $encrypt_data = RsaUtils::privateEncrypt($data,$private_key);
    //使用私钥将加密数据加签
    $private_encrypt_sign = RsaUtils::rsaSign($encrypt_data,$private_key);
    //使用公钥解签
    $public_check_sign = RsaUtils::verifySign($encrypt_data,$private_encrypt_sign,$public_key);
    //使用公钥将数据解密
    $decrypt_data = RsaUtils::publicDecrypt($encrypt_data,$public_key);
    
    echo 'private encrypt data: '.$encrypt_data.PHP_EOL;
    echo 'private encrypt sign: '.$private_encrypt_sign.PHP_EOL;
    echo 'public check sign: '.$public_check_sign.PHP_EOL;
    echo 'public decrypt data: '.$decrypt_data.PHP_EOL;
    
    
    
    //验证java加密解密方法
    $private_encrypt_data = 'fHG5JMpTTF-KzrPCp827opRy3BvqmVIpIZS4gVuWqY5NeLsgoLxdrq3SaxUp_oBQ9pVqNlEiU9SIwbqJDjIqjHsCtVMOLoEdWicib_wCaoB16veKTEC4GnvviJwlS5IedH27oWGHKTTc6Ii5cLiQncjDAadvm0KCdC74yrwPqnc';
    $public_decrypt_data = RsaUtils::publicDecrypt($private_encrypt_data,$public_key);
    $sign_data1 = 'jlJvXY5t8KesDi3WaPr71jj2BigHLDr3b827Jl9xspbecdUjPB44Xe3sjWnzvFDLpKJGiNTvqE-Qyu3FZpG_NyI5yhVrAQgZmyYfVywmeDDsTOQYk1xP0UEfFgB0MXsFdlfSdMu5JcR5kgC5Xl5jds1b0Z2Nq7gQ-bvFJQcuHgU';
    $verify_sign1 = RsaUtils::verifySign($private_encrypt_data,$sign_data1,$public_key);
    
    $public_encrypt_data = 'raoQQsfN0KBfPAMRWnxr9kFPvJ6BgQ7PRBCMnz0nWsH03sD4IdlMvKpj78BHe7V7Ga1HZHyDxuJhVaJ0T5qKl8qHXzvKquzNtdMru7G4X9o8ylzkGxJLg-HYCWOrsZ77ZMaKoV9p-TCf-yMI21OpL_5JGot-XNfVVPkmg0z9FW0';
    $private_decrypt_data = RsaUtils::privateDecrypt($public_encrypt_data, $private_key);
    $sign_data2 = 'ngN2kQppfITyn5yAfNc1c-ofK20trKJWXIjlaJhWtm7s2jzv5rcsPY5JH06CMAIIbnKGIUcoVvMeKavAIVFb4G_h3CvXIYnxMjQL19Op-SbtyGNwT-rZzTEP8tKfxFRVm7SrHHDz2s287S3vqQz9vGEGNmgDHEdrCfHBmmoFkQA';
    $verify_sign2 = RsaUtils::verifySign($public_encrypt_data,$sign_data2,$public_key);
    
    echo PHP_EOL;
    echo 'public_decrypt_data: '.$public_decrypt_data.PHP_EOL;
    echo 'verifySign1: '. $verify_sign1.PHP_EOL;
    
    echo 'private_decrypt_data: '.$private_decrypt_data.PHP_EOL;
    echo 'verifySign2: '. $verify_sign2.PHP_EOL;
    
    $public_encrypt_data = 'T2LFtY3dF_b6OBO07BN-3LtMSEBZqDukovDZ4HGCff8wosvlowf6IFJ3U7LFBIeHfiHBKiFuAV8-pFltCfTXtA4AwgVUnwbBMBWBfIJiLDi02ev30V-5BcYEuSF-cEdnSUd7WecrX4rHhzYLueGuj8H6c7RRbSbrJ6_3EFfU-K0';
    $private_decrypt_data = RsaUtils::privateDecrypt($public_encrypt_data,$private_key);
    echo PHP_EOL;
    echo 'private_decrypt_data: '.$private_decrypt_data.PHP_EOL;
    
    
    
    class RsaUtils{
    
        /**
         * 签名算法,SHA256WithRSA
         */
        private const SIGNATURE_ALGORITHM = OPENSSL_ALGO_SHA256;
    
        /**
         * RSA最大加密明文大小
         */
        private const MAX_ENCRYPT_BLOCK = 117;
    
        /**
         * RSA最大解密密文大小
         */
        private const MAX_DECRYPT_BLOCK = 128;
    
        /**
         * 使用公钥将数据加密
         * @param $data string 需要加密的数据
         * @param $publicKey string 公钥
         * @return string 返回加密串(base64编码)
         */
        public static function publicEncrypt($data,$publicKey){
            $data = str_split($data, self::MAX_ENCRYPT_BLOCK);
    
            $encrypted = '';
            foreach($data as & $chunk){
                if(!openssl_public_encrypt($chunk, $encryptData, $publicKey)){
                    return '';
                }else{
                    $encrypted .= $encryptData;
                }
            }
            return self::urlSafeBase64encode($encrypted);
        }
    
        /**
         * 使用私钥解密
         * @param $data string 需要解密的数据
         * @param $privateKey string 私钥
         * @return string 返回解密串
         */
        public static function privateDecrypt($data,$privateKey){
            $data = str_split(self::urlSafeBase64decode($data), self::MAX_DECRYPT_BLOCK);
    
            $decrypted = '';
            foreach($data as & $chunk){
                if(!openssl_private_decrypt($chunk, $decryptData, $privateKey)){
                    return '';
                }else{
                    $decrypted .= $decryptData;
                }
            }
            return $decrypted;
        }
    
        /**
         * 使用私钥将数据加密
         * @param $data string 需要加密的数据
         * @param $privateKey string 私钥
         * @return string 返回加密串(base64编码)
         */
        public static function privateEncrypt($data,$privateKey){
            $data = str_split($data, self::MAX_ENCRYPT_BLOCK);
    
            $encrypted = '';
            foreach($data as & $chunk){
                if(!openssl_private_encrypt($chunk, $encryptData, $privateKey)){
                    return '';
                }else{
                    $encrypted .= $encryptData;
                }
            }
            return self::urlSafeBase64encode($encrypted);
        }
    
    
        /**
         * 使用公钥解密
         * @param $data string 需要解密的数据
         * @param $publicKey string 公钥
         * @return string 返回解密串
         */
        public static function publicDecrypt($data,$publicKey){
            $data = str_split(self::urlSafeBase64decode($data), self::MAX_DECRYPT_BLOCK);
    
            $decrypted = '';
            foreach($data as & $chunk){
                if(!openssl_public_decrypt($chunk, $decryptData, $publicKey)){
                    return '';
                }else{
                    $decrypted .= $decryptData;
                }
            }
            return $decrypted;
        }
    
    
        /**
         * 私钥加签名
         * @param $data 被加签数据
         * @param $privateKey 私钥
         * @return mixed|string
         */
        public static function rsaSign($data, $privateKey){
            if(openssl_sign($data, $sign, $privateKey, self::SIGNATURE_ALGORITHM)){
                return self::urlSafeBase64encode($sign);
            }
            return '';
        }
    
        /**
         * 公钥验签
         * @param $data 被加签数据
         * @param $sign 签名
         * @param $publicKey 公钥
         * @return bool
         */
        public static function verifySign($data, $sign, $publicKey):bool {
            return (1 == openssl_verify($data, self::urlSafeBase64decode($sign), $publicKey, self::SIGNATURE_ALGORITHM));
        }
    
        /**
         * url base64编码
         * @param $string
         * @return mixed|string
         */
        public static function urlSafeBase64encode($string){
            $data = str_replace(array('+','/','='), array( '-','_',''), base64_encode($string));
            return $data;
        }
    
        /**
         * url base64解码
         * @param $string
         * @return bool|string
         */
        public static function urlSafeBase64decode($string){
            $data = str_replace(array('-','_'), array('+','/'), $string);
            $mod4 = strlen($data) % 4;
            if($mod4){
                $data .= substr('====', $mod4);
            }
            return base64_decode($data);
        }
    }
    复制代码

    输出如下:

    复制代码
    public encrypt data: WopnO2LnolZ7XpOwA_ktOhfkkaQQJQgkJudk3ZH_-ob36GQFv968nE1UBXxNekA9pIHBcvcl0ZWfwFhk-kyOF2FmQvpPY9LkqiCV0T32vhJet0n93ti2PBoFILxvChjzdOgSG9M0flH78Vm696Q4mHo7VMt_XMoHDTd3Rbagvt8
    private decrypt data: i like php
    public encrypt data: Fwb5BtLRveCWbx7FkXarl1zVOdwDvbDTl7gv-vPHXpj-T2wm9GlUDn3X0wnHHXkE8cqAT6PcE0g0ide6beP9_ysHMLgnC6wVqkomIKsi6C9TcGd4d6XQBjeJgdgccvDcD-7pcKrV9W-_Z7jkYkwwrjPGPd_uckEHR_cDXyOX4PU
    private rsa sign: T-I3KLkBEMRi9YdflyjNZxh_IhEC2mG4vFaq5FeFzs03l7ojtmf3pXFOwjz6qbHUwIJ-tjIMVammfCrYKa0AjMAX_L7-99_EUPmMvmjXS_8z0aZuY5dZPgRCBxklKem56r0qss-iSGTGsh3eivhUiHvtRTBXhtbkpjjlkkqXy-k
    public check sign: 1
    private decrypt data: i like php
    public_decrypt_data: i like java verifySign1: 1 private_decrypt_data: i like java verifySign2: 1

    private_decrypt_data: i like JS
    复制代码

    6.JS版本加解密

    复制代码
    var b64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    var b64pad = "=";
    
    var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
    
    //整型转字符串
    function int2char(n) {
        return BI_RM.charAt(n);
    }
    
    //十六进制转Base64字符串
    function hex2b64(h) {
        var i;
        var c;
        var ret = "";
        for (i = 0; i + 3 <= h.length; i += 3) {
            c = parseInt(h.substring(i, i + 3), 16);
            ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63);
        }
        if (i + 1 == h.length) {
            c = parseInt(h.substring(i, i + 1), 16);
            ret += b64map.charAt(c << 2);
        }
        else if (i + 2 == h.length) {
            c = parseInt(h.substring(i, i + 2), 16);
            ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4);
        }
        while ((ret.length & 3) > 0) {
            ret += b64pad;
        }
        return ret;
    }
    
    //Base64字符串转十六进制
    function b64tohex(s) {
        var ret = "";
        var i;
        var k = 0; // b64 state, 0-3
        var slop = 0;
        for (i = 0; i < s.length; ++i) {
            if (s.charAt(i) == b64pad) {
                break;
            }
            var v = b64map.indexOf(s.charAt(i));
            if (v < 0) {
                continue;
            }
            if (k == 0) {
                ret += int2char(v >> 2);
                slop = v & 3;
                k = 1;
            }
            else if (k == 1) {
                ret += int2char((slop << 2) | (v >> 4));
                slop = v & 0xf;
                k = 2;
            }
            else if (k == 2) {
                ret += int2char(slop);
                ret += int2char(v >> 2);
                slop = v & 3;
                k = 3;
            }
            else {
                ret += int2char((slop << 2) | (v >> 4));
                ret += int2char(v & 0xf);
                k = 0;
            }
        }
        if (k == 1) {
            ret += int2char(slop << 2);
        }
        return ret;
    }
    
    //十六进制转字节
    function hexToBytes(hex) {
        for (var bytes = [], c = 0; c < hex.length; c += 2)
            bytes.push(parseInt(hex.substr(c, 2), 16));
        return bytes;
    }
    
    //字节转十六进制
    function bytesToHex(bytes) {
        for (var hex = [], i = 0; i < bytes.length; i++) {
            hex.push((bytes[i] >>> 4).toString(16));
            hex.push((bytes[i] & 0xF).toString(16));
        }
        return hex.join("");
    }
    
    String.prototype.replaceAllStr=function(f,e){
        var reg=new RegExp(f,"g");
        return this.replace(reg,e);
    }
    
    function urlsafeEncode(e) {
        return e.replaceAllStr("\+","-").replaceAllStr("/","_").replaceAllStr("=","");
    }
    
    function urlsafeDecode(e) {
        e =  e.replaceAllStr("-","+").replaceAllStr("_","/");
        var mob = e.length%4;
        if(mob>0){
            e += "====".substr(mob);
        }
        return e;
    }
    
    
    //长字符串加密
    JSEncrypt.prototype.encryptLong = function (string) {
        var k = this.getKey();
        //var MAX_ENCRYPT_BLOCK = (((k.n.bitLength() + 7) >> 3) - 11);
        var MAX_ENCRYPT_BLOCK = 117;
    
        try {
            var lt = "";
            var ct = "";
            //RSA每次加密117bytes,需要辅助方法判断字符串截取位置
            //1.获取字符串截取点
            var bytes = new Array();
            bytes.push(0);
            var byteNo = 0;
            var len, c;
            len = string.length;
    
            var temp = 0;
            for (var i = 0; i < len; i++) {
                c = string.charCodeAt(i);
                if (c >= 0x010000 && c <= 0x10FFFF) {
                    byteNo += 4;
                } else if (c >= 0x000800 && c <= 0x00FFFF) {
                    byteNo += 3;
                } else if (c >= 0x000080 && c <= 0x0007FF) {
                    byteNo += 2;
                } else {
                    byteNo += 1;
                }
                if ((byteNo % MAX_ENCRYPT_BLOCK) >= 114 || (byteNo % MAX_ENCRYPT_BLOCK) == 0) {
                    if (byteNo - temp >= 114) {
                        bytes.push(i);
                        temp = byteNo;
                    }
                }
            }
    
            //2.截取字符串并分段加密
            if (bytes.length > 1) {
                for (var i = 0; i < bytes.length - 1; i++) {
                    var str;
                    if (i == 0) {
                        str = string.substring(0, bytes[i + 1] + 1);
                    } else {
                        str = string.substring(bytes[i] + 1, bytes[i + 1] + 1);
                    }
                    var t1 = k.encrypt(str);
                    ct += t1;
                }
                ;
                if (bytes[bytes.length - 1] != string.length - 1) {
                    var lastStr = string.substring(bytes[bytes.length - 1] + 1);
                    ct += k.encrypt(lastStr);
                }
                return hex2b64(ct);
            }
            var t = k.encrypt(string);
            var y = hex2b64(t);
            return y;
        } catch (ex) {
            return false;
        }
    };
    
    //长字符串解密
    JSEncrypt.prototype.decryptLong = function (string) {
        var k = this.getKey();
        // var MAX_DECRYPT_BLOCK = ((k.n.bitLength()+7)>>3);
        var MAX_DECRYPT_BLOCK = 128;
        try {
            var ct = "";
            var t1;
            var bufTmp;
            var hexTmp;
            var str = b64tohex(string);
            var buf = hexToBytes(str);
            var inputLen = buf.length;
            //开始长度
            var offSet = 0;
            //结束长度
            var endOffSet = MAX_DECRYPT_BLOCK;
    
            //分段加密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                    bufTmp = buf.slice(offSet, endOffSet);
                    hexTmp = bytesToHex(bufTmp);
                    t1 = k.decrypt(hexTmp);
                    ct += t1;
    
                } else {
                    bufTmp = buf.slice(offSet, inputLen);
                    hexTmp = bytesToHex(bufTmp);
                    t1 = k.decrypt(hexTmp);
                    ct += t1;
    
                }
                offSet += MAX_DECRYPT_BLOCK;
                endOffSet += MAX_DECRYPT_BLOCK;
            }
            return ct;
        } catch (ex) {
            return false;
        }
    };
    
    
    // Call this code when the page is done loading.
    var publicKeyStr =  "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6BSDlbRplhMMNZBKHX4xe8AwE" +
        "SpzHVfAcHHsX9FFSMuF91W3cxgT/g5n+qlLLFzCE3hWG/yX5NMAxR4mS3MlhyXKw" +
        "ko3tK9Ua691afod1lxORR3IaZ8nV7v5Bv8y4JDe4E3/f/bQIGzroWiJ0sXTcO41G" +
        "qvOw3G9leClSvjVnSwIDAQAB";
    
    var privateKeyStr = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALoFIOVtGmWEww1k" +
        "EodfjF7wDARKnMdV8Bwcexf0UVIy4X3VbdzGBP+Dmf6qUssXMITeFYb/Jfk0wDFH" +
        "iZLcyWHJcrCSje0r1Rrr3Vp+h3WXE5FHchpnydXu/kG/zLgkN7gTf9/9tAgbOuha" +
        "InSxdNw7jUaq87Dcb2V4KVK+NWdLAgMBAAECgYBqCihhgJtOiarjBEvnrZkIOZCw" +
        "FZRfsWaJr9afph+BWw3dvH+/HYaV3YA4gwFlUlfPNgZRiTstX1u7+8q51HBa+08h" +
        "jPE8Q4GhoUY+sQ9MB8NXA6SWHNPPfMOYIeKEtKmNBdgIbtuhnob3o18rJNFIY+qC" +
        "i8djf4om93+AChmo6QJBAO31hd9qem7BnHXsxiMwS+iHlRjW9KxXva2zf+BNURSR" +
        "Z19cePReHJGE4v1C731MZlygTB5zKChQ8uZ3JLKJeX8CQQDIH4k/xbuhMb8dMdzl" +
        "AYN/CU+MgfWjlgbYjxOnTaLcbs5Mlz9v3/5I/FwqxPvzGuCjHkyh08oFfnQXvzdj" +
        "YMA1AkEApjgyOnzzZviBZXJueVgcPiKvSHmm0dg8W+Cd+72mXHqxPdCngPNYe2Ha" +
        "+VRPXDQI8LzcTwzbyUW6Vrh0/u2+2wJBAK1rZqx01VuimFLcWue4oBL+JolENXFF" +
        "GTmhAw8AIBmVjACjML3qBZmJ1vTZLtxEdlXkc9PojDCmnEPX2E+uD+ECQF2eX4EY" +
        "X95HDzQ4cm1kGQudjgfH1gZ+30DIindIHXNAOFpYeAUD7yUQP5tZO8nG38gybPJg" +
        "FoadlsSMIQIpksM=";
    
    
    var sourceStr = "i like JS";
    
    //公钥加密
    var encrypt = new JSEncrypt();
    encrypt.setPublicKey(publicKeyStr);
    var encrypted = encrypt.encryptLong(sourceStr);
    encrypted = urlsafeEncode(encrypted);
    
    //私钥解密
    var decrypt = new JSEncrypt();
    decrypt.setPrivateKey(privateKeyStr);
    var uncrypted = decrypt.decryptLong(urlsafeDecode(encrypted));
    
    console.log("public encrypted: ",encrypted);
    console.log("private uncrypted: ",uncrypted);

      console.log("private uncrypted: ",decrypt.decryptLong(urlsafeDecode("WopnO2LnolZ7XpOwA_ktOhfkkaQQJQgkJudk3ZH_-ob36GQFv968nE1UBXxNekA9pIHBcvcl0ZWfwFhk-kyOF2FmQvpPY9LkqiCV0T32vhJet0n93ti2PBoFILxvChjzdOgSG9M0flH78Vm696Q4mHo7VMt_XMoHDTd3Rbagvt8")));
      console.log("private uncrypted: ",decrypt.decryptLong(urlsafeDecode("raoQQsfN0KBfPAMRWnxr9kFPvJ6BgQ7PRBCMnz0nWsH03sD4IdlMvKpj78BHe7V7Ga1HZHyDxuJhVaJ0T5qKl8qHXzvKquzNtdMru7G4X9o8ylzkGxJLg-HYCWOrsZ77ZMaKoV9p-TCf-yMI21OpL_5JGot-XNfVVPkmg0z9FW0")));

    引入 <script src="https://cdn.bootcss.com/jsencrypt/3.0.0-beta.1/jsencrypt.js"></script> 

     
     
  • 相关阅读:
    225. 用队列实现栈
    415. 字符串相加
    rabbitmq的基本使用
    3. 无重复字符的最长子串
    面试题59
    面试题30. 包含min函数的栈
    面试题09. 用两个栈实现队列
    287. 寻找重复数
    1137. 第 N 个泰波那契数
    70. 爬楼梯
  • 原文地址:https://www.cnblogs.com/web-chuanfa/p/11105735.html
Copyright © 2020-2023  润新知