zoukankan      html  css  js  c++  java
  • 前端CryptoJS加密、后端解密代码实现参考

    前端CryptoJS加密、后端解密代码实现参考

    1、使用AES算法的CBC模式加密

    1.1、前端加密代码实现参考

    vue项目需要安装CryptoJS安装包,安装命令如下:

    npm install crypto-js
    

    在项目中引入CryptoJS

    import CryptoJS from 'crypto-js'
    

    参考代码如下:

    <script>
         // 此处key为16进制
         let key = '385f33cb91484b04a177828829081ab7';
         console.log('密钥:', key);
         // key格式化处理
         key = CryptoJS.enc.Utf8.parse(key)
         // 偏移量长度为16位, 注:偏移量需要与后端定义好,保证一致
         let iv = "37fa77f6a3b0462d";
         iv = CryptoJS.enc.Utf8.parse("37fa77f6a3b0462d");
         // 加密内容
         const source = {
        	"username": "用户名",
        	"password": "密码",
        	"timestamp": new Date().getTime()
    	}
    	const content = JSON.stringify(source);
         console.log('加密前:', source);
         // 加密方法
         const encryptedContent = CryptoJS.AES.encrypt(content, key, {
             iv: iv,
             mode: CryptoJS.mode.CBC,  
             padding: CryptoJS.pad.Pkcs7
         })
         const encStr = encryptedContent.ciphertext.toString()
         console.log("加密后:", encStr);
         // 解密方法
         const decryptedContent = CryptoJS.AES.decrypt(CryptoJS.format.Hex.parse(encStr), key, {
             iv: iv,
             mode: CryptoJS.mode.CBC,  
             padding: CryptoJS.pad.Pkcs7
         })
         console.log('解密:',CryptoJS.enc.Utf8.stringify(decryptedContent));
    </script>
    

    前端打印结果

    说明

    1> CBC模式前、后端需要确定偏移量的值,并且保持一致,这样才能确保后端解密成功。

    2> 前端CBC模式或者ECB模式下的填充方式 Pkcs7,对应后端AES算法模式中的 PKCS5Padding 填充方式

    3> CryptoJS对应的API文档地址:https://cryptojs.gitbook.io/docs/#encoders

    1.2、后端解密代码实现参考

    后端代码实现需要引入的maven依赖如下:

    <dependency>
        <groupId>commons-codec</groupId>
        <artifactId>commons-codec</artifactId>
        <version>1.15</version>
    </dependency>
    

    参考代码实现如下:

    import org.apache.commons.codec.DecoderException;
    import org.apache.commons.codec.binary.Hex;
    
    import javax.crypto.*;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    import java.io.UnsupportedEncodingException;
    import java.security.InvalidAlgorithmParameterException;
    import java.security.InvalidKeyException;
    import java.security.NoSuchAlgorithmException;
    
    /**
     * AES对称加密工具类
     *
     * @author 星空流年
     */
    public class AesUtil {
        /**
         * 偏移量
         *
         * 说明:偏移量字符串必须是16位 当模式是CBC的时候必须设置偏移量
         * 此处值与前端偏移量值保持一致
         */
        private static String iv = "37fa77f6a3b0462d";
    
        /**
         * 加密算法
         */
        private static String Algorithm = "AES";
    
        /**
         * 算法/模式/补码方式
         */
        private static String AlgorithmProvider = "AES/CBC/PKCS5Padding";
    
        /**
         * 加密
         *
         * @param src 加密内容
         * @param uniqueKey 加密key
         * @return
         * @throws NoSuchPaddingException
         * @throws NoSuchAlgorithmException
         * @throws InvalidKeyException
         * @throws BadPaddingException
         * @throws IllegalBlockSizeException
         * @throws InvalidAlgorithmParameterException
         * @throws UnsupportedEncodingException
         */
        public static String encrypt(String src, String uniqueKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, UnsupportedEncodingException {
            byte[] key = uniqueKey.getBytes();
            SecretKey secretKey = new SecretKeySpec(key, Algorithm);
            IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes("utf-8"));
            Cipher cipher = Cipher.getInstance(AlgorithmProvider);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);
            byte[] cipherBytes = cipher.doFinal(src.getBytes("UTF-8"));
            return byteToHexString(cipherBytes);
        }
    
        /**
         * 解密
         *
         * @param enc       加密内容
         * @param uniqueKey 唯一key
         * @return
         * @throws NoSuchPaddingException
         * @throws NoSuchAlgorithmException
         * @throws UnsupportedEncodingException
         * @throws InvalidAlgorithmParameterException
         * @throws InvalidKeyException
         * @throws DecoderException
         * @throws BadPaddingException
         * @throws IllegalBlockSizeException
         */
        public static String decrypt(String enc, String uniqueKey) throws NoSuchPaddingException, NoSuchAlgorithmException, UnsupportedEncodingException, InvalidAlgorithmParameterException, InvalidKeyException, DecoderException, BadPaddingException, IllegalBlockSizeException {
            byte[] key = uniqueKey.getBytes();
            SecretKey secretKey = new SecretKeySpec(key, Algorithm);
            IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes("utf-8"));
            Cipher cipher = Cipher.getInstance(AlgorithmProvider);
            cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
            byte[] hexBytes = hexStringToBytes(enc);
            byte[] plainBytes = cipher.doFinal(hexBytes);
            return new String(plainBytes, "UTF-8");
        }
    
        /**
         * 将byte数组转换为16进制字符串
         *
         * @param src
         * @return
         */
        private static String byteToHexString(byte[] src) {
            return Hex.encodeHexString(src);
        }
    
        /**
         * 将16进制字符串转换为byte数组
         *
         * @param hexString
         * @return
         */
        private static byte[] hexStringToBytes(String hexString) throws DecoderException {
            return Hex.decodeHex(hexString);
        }
    
        /**
         * AES加密、解密测试方法
         *
         * @param args
         */
        public static void main(String[] args) {
            try {
                // 唯一key作为密钥
                String uniqueKey = "385f33cb91484b04a177828829081ab7";
                // 加密前数据,此处数据与前端数据一致(加密内容包含有时间戳),请注意查看前端加密前数据
                String src = "{"username":"用户名","password":"密码","timestamp":1628218094188}";
                System.out.println("密钥:" + uniqueKey);
                System.out.println("原字符串:" + src);
                // 加密
                String encrypt = encrypt(src, uniqueKey);
                System.out.println("加密:" + encrypt);
                // 解密
                String decrypt = decrypt(encrypt, uniqueKey);
                System.out.println("解密:" + decrypt);
            } catch (InvalidKeyException e) {
                e.printStackTrace();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (NoSuchPaddingException e) {
                e.printStackTrace();
            } catch (IllegalBlockSizeException e) {
                e.printStackTrace();
            } catch (BadPaddingException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    测试结果

    2、使用AES算法的ECB模式加密

    前面也说到,AES的ECB和CBC模式下的填充方式 Pkcs7,对应后端AES算法模式中的 PKCS5Padding 填充方式,只不过CBC模式需要添加偏移量,而ECB模式则不需要,大体实现方式本质上没有太大差别。

    2.1、前端加密代码实现参考

    vue项目需要安装CryptoJS安装包,安装命令如下:

    npm install crypto-js
    

    在项目中引入CryptoJS

    import CryptoJS from 'crypto-js'
    

    参考代码如下:

    <script>
         // 此处key为16进制
         let key = '385f33cb91484b04a177828829081ab7';
         console.log('密钥:', key);
         // key格式化处理
         key = CryptoJS.enc.Utf8.parse(key)
    	// 加密内容
         const source = {
        	"username": "用户名",
        	"password": "密码",
        	"timestamp": new Date().getTime()
    	}
    	const content = JSON.stringify(source);
         console.log('加密前:', source);
         // 加密方法
         const encryptedContent = CryptoJS.AES.encrypt(content, key, {
             mode: CryptoJS.mode.ECB,  
             padding: CryptoJS.pad.Pkcs7
         })
         const encStr = encryptedContent.ciphertext.toString()
         console.log('加密后:', encStr);
         // 解密方法
         const decryptedContent = CryptoJS.AES.decrypt(CryptoJS.format.Hex.parse(encStr), key, {
             mode: CryptoJS.mode.ECB,  
             padding: CryptoJS.pad.Pkcs7
         })
         console.log('解密:',CryptoJS.enc.Utf8.stringify(decryptedContent));
    </script>
    

    前端打印结果

    2.2、后端加密代码实现参考

    import org.apache.commons.codec.DecoderException;
    import org.apache.commons.codec.binary.Hex;
    
    import javax.crypto.*;
    import javax.crypto.spec.SecretKeySpec;
    import java.io.UnsupportedEncodingException;
    import java.nio.charset.StandardCharsets;
    import java.security.InvalidAlgorithmParameterException;
    import java.security.InvalidKeyException;
    import java.security.NoSuchAlgorithmException;
    
    /**
     * AES对称加密工具类
     *
     * @author 星空流年
     */
    public class AesUtil {
        /**
         * 加密算法
         */
        private static String Algorithm = "AES";
    
        /**
         * 算法/模式/补码方式
         */
        private static String AlgorithmProvider = "AES/ECB/PKCS5Padding";
    
        /**
         * 加密
         *
         * @param src       原内容
         * @param uniqueKey 唯一key
         * @return
         * @throws NoSuchPaddingException
         * @throws NoSuchAlgorithmException
         * @throws InvalidKeyException
         * @throws BadPaddingException
         * @throws IllegalBlockSizeException
         * @throws DecoderException
         */
        public static String encrypt(String src, String uniqueKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, DecoderException {
            byte[] key = uniqueKey.getBytes();
            SecretKey secretKey = new SecretKeySpec(key, Algorithm);
            Cipher cipher = Cipher.getInstance(AlgorithmProvider);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            byte[] cipherBytes = cipher.doFinal(src.getBytes(StandardCharsets.UTF_8));
            return byteToHexString(cipherBytes);
        }
    
        /**
         * 解密
         *
         * @param enc       加密内容
         * @param uniqueKey 唯一key
         * @return
         * @throws NoSuchPaddingException
         * @throws NoSuchAlgorithmException
         * @throws UnsupportedEncodingException
         * @throws InvalidAlgorithmParameterException
         * @throws InvalidKeyException
         * @throws DecoderException
         * @throws BadPaddingException
         * @throws IllegalBlockSizeException
         */
        public static String decrypt(String enc, String uniqueKey) throws NoSuchPaddingException, NoSuchAlgorithmException, UnsupportedEncodingException, InvalidAlgorithmParameterException, InvalidKeyException, DecoderException, BadPaddingException, IllegalBlockSizeException {
            byte[] key = uniqueKey.getBytes();
            SecretKey secretKey = new SecretKeySpec(key, Algorithm);
            Cipher cipher = Cipher.getInstance(AlgorithmProvider);
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            byte[] hexBytes = hexStringToBytes(enc);
            byte[] plainBytes = cipher.doFinal(hexBytes);
            return new String(plainBytes, SystemConstants.UTF_8);
        }
    
        /**
         * 将byte数组转换为16进制字符串
         *
         * @param src
         * @return
         */
        private static String byteToHexString(byte[] src) {
            return Hex.encodeHexString(src);
        }
    
        /**
         * 将16进制字符串转换为byte数组
         *
         * @param hexString
         * @return
         */
        private static byte[] hexStringToBytes(String hexString) throws DecoderException {
            return Hex.decodeHex(hexString);
        }
    
        /**
         * AES加密、解密测试方法
         *
         * @param args
         */
        public static void main(String[] args) {
            try {
                // 唯一key作为密钥
                String uniqueKey = "385f33cb91484b04a177828829081ab7";
                // 加密前数据,此处数据与前端数据一致(加密内容包含有时间戳),请注意查看前端加密前数据
                String src = "{"username":"用户名","password":"密码","timestamp":1628220492939}";
                System.out.println("密钥:" + uniqueKey);
                System.out.println("原字符串:" + src);
                // 加密
                String encrypt = encrypt(src, uniqueKey);
                System.out.println("加密:" + encrypt);
                // 解密
                String decrypt = decrypt(encrypt, uniqueKey);
                System.out.println("解密:" + decrypt);
            } catch (InvalidKeyException e) {
                e.printStackTrace();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (NoSuchPaddingException e) {
                e.printStackTrace();
            } catch (IllegalBlockSizeException e) {
                e.printStackTrace();
            } catch (BadPaddingException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    测试结果

    参考内容:

    1、https://blog.csdn.net/lsvtogergo/article/details/80804312
    2、https://cryptojs.gitbook.io/docs/#encoders
    3、https://www.cnblogs.com/hetutu-5238/p/10648116.html

    遨游在代码世界里的一条不知名的小船。。。。。。
  • 相关阅读:
    面向对象的七大设计原则
    06章 初始继承和多态
    面向太阳,不问春暖花开
    05章 体检套餐管理系统
    02章《深入C#数据类型》项目经理评分
    MongoDB快速入门(十二) -- 索引
    MongoDB快速入门(十一)- sort() 方法
    MongoDB快速入门(十)- Limit(),Skip() 方法
    MongoDB快速入门(九)- 投影
    MongoDB快速入门(八)- 删除文档
  • 原文地址:https://www.cnblogs.com/cndarren/p/15108270.html
Copyright © 2011-2022 走看看