SOP页面跳转设计 RAS AES加密算法应用跨服务免登陆接口设计

SOP页面跳转设计 RAS AES加密算法应用跨服务免登陆接口设计

SOP,是 Standard Operating Procedure三个单词中首字母的大写 ,即标准作业程序,指将某一事件的标准操作步骤和要求以统一的格式描述出来,用于指导和规范日常的工作。

加密/加签过程:
1.动态随机生成AES密钥aesKey,而不是静态的AES密钥。提高安全性。
2.使用该AES对传输的接口数据data加密。 比如:username=AES(username原文,aesKey)&age=AES(age原文,aesKey)
3.使用RSA公钥对aesKey加密,作为参数传递 prikey=RSA(aeskey,公钥)

以上完整的路径:http://IP地址+端口/path?username=AES(username,aesKey)&age=AES(age,aesKey)&prikey=RSA(aeskey,公钥)

解密/解签过程:
1.先用私钥从prikey解密获取aesKey
2.用aesKey解密username,age获得username原文,age原文

* Invalid AES key length: 33 bytes
*
* 如果未指定init LEN,则根据参数的key自适应。AES KEY长度为 16位,24位,32位。
* 否则可以指定AES KEY长度
* // KeyGenerator kgen = KeyGenerator.getInstance(TYPE);
* // //Wrong keysize: must be equal to 128, 192 or 256
* // kgen.init(LEN); //128 / 8 = 16
*
* 经过测试发现:
* keysize: must be equal to 128, 192 or 256
* aes key长度 16,24,32
* 以上的两个条件相互都成立,而不是如下的第一组,第二组,第三组的强制配对。

DEMO代码示例:

package com.example.core.mydemo.spi;

import com.alibaba.fastjson.JSONObject;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Date;

/**
 * Invalid AES key length: 33 bytes
 *
 * 如果未指定init LEN,则根据参数的key自适应。AES KEY长度为 16位,24位,32位。
 * 否则可以指定AES KEY长度
 * //        KeyGenerator kgen = KeyGenerator.getInstance(TYPE);
 * //        //Wrong keysize: must be equal to 128, 192 or 256
 * //        kgen.init(LEN);  //128 / 8 = 16
 *
 * 经过测试发现:
 * keysize: must be equal to 128, 192 or 256
 * aes key长度 16,24,32
 * 以上的两个条件相互都成立,而不是如下的第一组,第二组,第三组的强制配对。
 */
public class AesUtil {

    //算法
    private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding";
    //密钥 (静态aesKey)
    //第一组
    public static final String KEY = "9862ecf540c64534";
//    public static final String KEY = "yyyyyyyyyyyyyyyy";  //16位
    //
    private static final Integer LEN = 128;

    //第二组
//    public static final String KEY = "yyyyyyyyyyyyyyyy91a1e003c11b414e";  //32位
//    private static final Integer LEN = 256;

    //第三组
//    public static final String KEY = "yyyyyyyyyyyyyyyy91a1e003";  //24位
//    private static final Integer LEN = 192;

    // 加密类型
    private static final String TYPE = "AES";

    /**
     * aes加密 - 静态aesKey
     *
     * @param content
     * @return
     * @throws Exception
     */
    public static String aesEncrypt(String content) {
        try {
            return aesEncrypt(content, KEY);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * aes解密 - 静态aesKey
     *
     * @param encrypt 内容
     * @return
     * @throws Exception
     */
    public static String aesDecrypt(String encrypt) {
        try {
            return aesDecrypt(encrypt, KEY);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 将base 64 code AES解密
     *
     * @param encryptStr 待解密的base 64 code
     * @param decryptKey 解密密钥
     * @return 解密后的string
     * @throws Exception
     */
    public static String aesDecrypt(String encryptStr, String decryptKey) throws Exception {
        return isEmpty(encryptStr) ? null : aesDecryptByBytes(base64Decode(encryptStr), decryptKey);
    }

    /**
     * AES解密
     *
     * @param encryptBytes 待解密的byte[]
     * @param decryptKey   解密密钥
     * @return 解密后的String
     * @throws Exception
     */
    public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance(TYPE);
        //Wrong keysize: must be equal to 128, 192 or 256
        kgen.init(LEN);

        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), TYPE));
        byte[] decryptBytes = cipher.doFinal(encryptBytes);
        return new String(decryptBytes);
    }

    /**
     * base 64 decode
     *
     * @param base64Code 待解码的base 64 code
     * @return 解码后的byte[]
     * @throws Exception
     */
    public static byte[] base64Decode(String base64Code) throws Exception {
        return isEmpty(base64Code) ? null : Base64.getDecoder().decode(base64Code);
    }



    /**
     * AES加密为base 64 code
     *
     * @param content    待加密的内容
     * @param encryptKey 加密密钥
     * @return 加密后的base 64 code
     * @throws Exception
     */
    public static String aesEncrypt(String content, String encryptKey) throws Exception {
        return base64Encode(aesEncryptToBytes(content, encryptKey));
    }

    /**
     * base 64 encode
     *
     * @param bytes 待编码的byte[]
     * @return 编码后的base 64 code
     */
    public static String base64Encode(byte[] bytes) {
        return Base64.getEncoder().encodeToString(bytes);
    }

    /**
     * AES加密
     *
     * @param content    待加密的内容
     * @param encryptKey 加密密钥
     * @return 加密后的byte[]
     * @throws Exception
     */
    public static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance(TYPE);
        //Wrong keysize: must be equal to 128, 192 or 256
        kgen.init(LEN);  //128 / 8 = 16

        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), TYPE));
        return cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * 将byte[]转为各种进制的字符串
     *
     * @param bytes byte[]
     * @param radix 可以转换进制的范围,从Character.MIN_RADIX到Character.MAX_RADIX,超出范围后变为10进制
     * @return 转换后的字符串
     */
    public static String binary(byte[] bytes, int radix) {
        return new BigInteger(1, bytes).toString(radix);// 这里的1代表正数
    }

    public static boolean isEmpty(CharSequence cs) {
        return cs == null || cs.length() == 0;
    }
    
    /**
     * 测试
     * output:
     * 对比:RASPublicAuthUtil.java输出结果  对比一致
     * username AES加密后的数据:wG2GS4DxYko57DoL0kAAWA%3D%3D
     * username解码:wG2GS4DxYko57DoL0kAAWA==
     *
     *encrypt=wG2GS4DxYko57DoL0kAAWA==
     * encodeEncrypt=wG2GS4DxYko57DoL0kAAWA%3D%3D
     * decrypt=admin
     *
     */
    public static void main(String[] args) throws Exception {
//        JSONObject jsonObject = new JSONObject();
//        jsonObject.put("ticketId", "8310000002021051115277C");
//        jsonObject.put("serviceItemId", "100000000708");
//        jsonObject.put("timestamp", new Date());
//        System.out.println("json data=" + jsonObject.toJSONString());
//        String encrypt = aesEncrypt(jsonObject.toJSONString());
        //aes加密
        String encrypt = aesEncrypt("admin");
        System.out.println("encrypt=" + encrypt);
        //aes编码
        String encodeEncrypt = URLEncoder.encode(encrypt, "UTF-8");
        System.out.println("encodeEncrypt=" + encodeEncrypt);

        //aes解密
        String decodeEncrypt = URLDecoder.decode(encodeEncrypt,"UTF-8");
        String decrypt = aesDecrypt(decodeEncrypt);
        System.out.println("decrypt=" + decrypt);
    }
}
     

package com.example.core.mydemo.spi;

import com.alibaba.fastjson.JSONObject;

import javax.crypto.Cipher;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.UUID;

/**
 **/
public class RSAPublicAuthUtil {

    // Base64解密
    private static final Base64.Decoder decoder = Base64.getDecoder();
    // Base64加密
    private static final Base64.Encoder encoder = Base64.getEncoder();
    
    /**
     * 非对称密钥算法
     */
    public static final String KEY_ALGORITHM = "RSA";

    /**
     * 公钥
     */
    private static final String PUBLIC_KEY = "可以使用支付宝开放平台开发助手.exe工具生成";
    /**
     * 私钥
     */
    private static final String PRIVATE_KEY = "可以使用支付宝开放平台开发助手.exe工具生成";

    /**
     * @param data
     * @throws
     * @Description:
     * @return: java.lang.String
     * @Author: MeiQi
     * @Date: 2021/7/12 20:50
     **/
    public static String encryptByPublicKey(String data)throws Exception {
        byte[] key_byte = decoder.decode(PUBLIC_KEY);
        byte[] encrypt_str = encryptByPublicKey(decoder.decode(data), key_byte);
        return encoder.encodeToString(encrypt_str);
    }

    /**
     * @param data  待加密数据
     * @param key   密钥
     * @throws
     * @Description:    公钥加密
     * @return: byte[]  加密数据
     * @Author: MeiQi
     * @Date: 2021/7/12 20:51
     **/
    private static byte[] encryptByPublicKey(byte[] data, byte[] key) throws Exception {
        //实例化密钥工厂
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        //初始化公钥
        //密钥材料转换
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
        //产生公钥
        PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
        //数据加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        return cipher.doFinal(data);
    }

    /**
     * 私钥解密
     * @param secretText    待解密的密文字符串
     * @return 解密后的明文
     */
    public static String decryptByPrivateKey(String secretText) {
        try {
            String privateKeyStr = PRIVATE_KEY;
            String input_charset = "UTF-8";
            // 生成私钥
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, getPrivateKey(privateKeyStr));
            // 密文解码
            byte[] secretTextDecoded = decoder.decode(secretText);
            byte[] tempBytes = cipher.doFinal(secretTextDecoded);
//            return new String(tempBytes);
            return encoder.encodeToString(tempBytes);
        } catch (Exception e) {
            throw new RuntimeException("解密字符串[" + secretText + "]时遇到异常", e);
        }
    }

    /**
     * 得到私钥
     * @param key 密钥字符串(经过base64编码)
     * @throws Exception
     */
    private static PrivateKey getPrivateKey(String key) throws Exception {
        byte[] keyBytes;
        keyBytes = decoder.decode(key);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        return privateKey;
    }


    /**
     * output:
     * 公钥:~~
     * 原文:admin
     * 原文:25
     * aesKey:9862ecf540c64534
     * username AES加密后的数据:wG2GS4DxYko57DoL0kAAWA%3D%3D
     * age AES加密后的数据:NUjk8UtCDZq7U8HhRNixNQ%3D%3D
     * 使用公钥加密prikey后的数据:NJ2dUzqqUwzcrYqV5GX0xKDo9eBuC1hjvTUAmtZmC9xoTX7nc0JhEErO2AZRyCS47Bc6CZi68MWSKsBt9bNxIfkY3ciGWOxSgHNhOVpWM8wEjWb6q%2BNcoLV9p7wapdur43v3jdcGFhzD0ugmDMiTPhCPfp0Dz3s9qTZD6rN1uc0%3D
     * http://localhost:8010/#/index?&username=wG2GS4DxYko57DoL0kAAWA%3D%3D&age=NUjk8UtCDZq7U8HhRNixNQ%3D%3D&prikey=NJ2dUzqqUwzcrYqV5GX0xKDo9eBuC1hjvTUAmtZmC9xoTX7nc0JhEErO2AZRyCS47Bc6CZi68MWSKsBt9bNxIfkY3ciGWOxSgHNhOVpWM8wEjWb6q%2BNcoLV9p7wapdur43v3jdcGFhzD0ugmDMiTPhCPfp0Dz3s9qTZD6rN1uc0%3D
     * prikey解码:NJ2dUzqqUwzcrYqV5GX0xKDo9eBuC1hjvTUAmtZmC9xoTX7nc0JhEErO2AZRyCS47Bc6CZi68MWSKsBt9bNxIfkY3ciGWOxSgHNhOVpWM8wEjWb6q+NcoLV9p7wapdur43v3jdcGFhzD0ugmDMiTPhCPfp0Dz3s9qTZD6rN1uc0=
     * prikey解密:9862ecf540c64534
     * username解码:wG2GS4DxYko57DoL0kAAWA==
     * username解密:admin
     * age解码:NUjk8UtCDZq7U8HhRNixNQ==
     * age解密:25
     */

    /**
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        //发送端
        System.out.println("公钥:" + PUBLIC_KEY);
        String username = "admin";
        System.out.println("原文:" + username);
        String age = "25";
        System.out.println("原文:" + age);


        String nonceStr = UUID.randomUUID().toString().replace("-", "");
        String aesKey = nonceStr.substring(0, 16);
        System.out.println("aesKey:" + aesKey);

        username = AesUtil.aesEncrypt(username, aesKey);
        username = URLEncoder.encode(username, "UTF-8");
        System.out.println("username AES加密后的数据:" + username);

        age = AesUtil.aesEncrypt(age, aesKey);
        age = URLEncoder.encode(age, "UTF-8");
        System.out.println("age AES加密后的数据:" + age);


        //发送端进行数据的加密
        String prikey = RSAPublicAuthUtil.encryptByPublicKey(aesKey);
        prikey = URLEncoder.encode(prikey, "UTF-8");
        System.out.println("使用公钥加密prikey后的数据:" + prikey);
        
        String base_url = "http://localhost:8010/#/index?";
        System.out.println(base_url.concat("&username=").concat(username).concat("&age=").concat(age).concat("&prikey=").concat(prikey));

        //接收端
        prikey = URLDecoder.decode(prikey,"UTF-8");
        System.out.println("prikey解码:" + prikey);
        String decryAes = RSAPublicAuthUtil.decryptByPrivateKey(prikey);
        System.out.println("prikey解密:" + decryAes);

        username = URLDecoder.decode(username,"UTF-8");
        System.out.println("username解码:" + username);
        String decryUsernameStr = AesUtil.aesDecrypt(username,decryAes);
        System.out.println("username解密:" + decryUsernameStr);

        age = URLDecoder.decode(age,"UTF-8");
        System.out.println("age解码:" + age);
        String decryAgeStr = AesUtil.aesDecrypt(age,decryAes);
        System.out.println("age解密:" + decryAgeStr);

    }
}

 RSA公私钥生成可以使用支付宝开放平台开发助手.exe工具生成

 

posted on 2024-05-22 06:33  oktokeep  阅读(2)  评论(0编辑  收藏  举报