CryptoJS 加密、解密使用方法


使用步骤

一、前端实现

安装

npm install crypto-js --save-dev
yarn add crypto-js --dev
// 或者下载js文件https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.js

引入crypto-js

支持ES6导入、Modular

import CryptoJS from "crypto-js";

或者

const CryptoJS = require("crypto-js");

设置密钥和密钥偏移量

// 十六位十六进制数作为密钥
const SECRET_KEY = CryptoJS.enc.Utf8.parse("1234123412341234");
// 十六位十六进制数作为密钥偏移量
const SECRET_IV = CryptoJS.enc.Utf8.parse("1234123412341234");

封装加密/解密方法

import CryptoJS from 'crypto-js';

// 十六位十六进制数作为密钥
const SECRET_KEY = CryptoJS.enc.Utf8.parse("1234123412341234");
// 十六位十六进制数作为密钥偏移量
const SECRET_IV = CryptoJS.enc.Utf8.parse("1234123412341234");


export default {
    
    
    /**
     * 随机生成指定数量的16进制key
     * @param num
     */
    generateKey(num) {
    
    
        let library = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        let key = "";
        for (var i = 0; i < num; i++) {
    
    
            let randomPoz = Math.floor(Math.random() * library.length);
            key += library.substring(randomPoz, randomPoz + 1);
        }
        return key;
    },

    /**
     * 加密方法
     * @param data
     * @param keyStr
     */
    encrypt(data, keyStr) {
    
    
        if (typeof data === "object") {
    
    
            try {
    
    
                data = JSON.stringify(data);
            } catch (error) {
    
    
                console.log("encrypt error:", error);
            }
        }
        //判断是否存在ksy,不存在就用定义好的key
        keyStr = keyStr ? keyStr : 'XXXXXXXXXXXXX';
        const key = CryptoJS.enc.Utf8.parse(keyStr);
        const dataHex = CryptoJS.enc.Utf8.parse(data);
        const encrypted = CryptoJS.AES.encrypt(dataHex, key,
            {
    
    
                mode: CryptoJS.mode.ECB,
                padding: CryptoJS.pad.Pkcs7
            }
        );
        return encrypted.toString();
    },
    /**
     * 解密方法
     * @param data
     * @param keyStr
     */
    decrypt(data, keyStr) {
    
    

        keyStr = keyStr ? keyStr : 'XXXXXXXXXXXXX';
        const key = CryptoJS.enc.Utf8.parse(keyStr);

        const decrypt = CryptoJS.AES.decrypt(data, key,
            {
    
    
                mode: CryptoJS.mode.ECB,
                padding: CryptoJS.pad.Pkcs7
            });
        return CryptoJS.enc.Utf8.stringify(decrypt).toString();
    }
}


配置偏移量(iv)方式

代码如下:

/**
 * 加密方法
 * @param data
 * @returns {string}
 */
export function encrypt(data) {
    
    
    if (typeof data === "object") {
    
    
        try {
    
    
            // eslint-disable-next-line no-param-reassign
            data = JSON.stringify(data);
        } catch (error) {
    
    
            console.log("encrypt error:", error);
        }
    }
    const dataHex = CryptoJS.enc.Utf8.parse(data);
    const encrypted = CryptoJS.AES.encrypt(dataHex, SECRET_KEY, {
    
    
        iv: SECRET_IV,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    });
    return encrypted.ciphertext.toString();
}

/**
 * 解密方法
 * @param data
 * @returns {string}
 */
export function decrypt(data) {
    
    
    const encryptedHexStr = CryptoJS.enc.Hex.parse(data);
    const str = CryptoJS.enc.Base64.stringify(encryptedHexStr);
    const decrypt = CryptoJS.AES.decrypt(str, SECRET_KEY, {
    
    
        iv: SECRET_IV,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    });
    const decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
    return decryptedStr.toString();
}

使用方法

import AES from '@/utils/crypto'
 
 const keys = CryptoJS.enc.Utf8.parse("1234123412341234");

//如果是对象/数组的话,需要先JSON.stringify转换成字符串
let password = AES.encrypt("abcd123456789", keys);
console.log("crypto encrypt 加密", password);

const decryptPassword = AES.decrypt(password, keys)
console.log("crypto decrypt 解密", decryptPassword, decryptPassword.length);

二、后端实现

后端采用的是Spring Boot框架,基于Java实现

java后端使用的是javax.crypto包,所以不用引依赖。

直接编写加密解密工具类,java类代码如下:

package cn.com.wasec.gd_plice.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;

/**
 * 登陆密码加密
 */
@Slf4j
public class AesUtil {
    
    

    private static final String ALGORITHMS = "AES/ECB/PKCS5Padding";

    /**
     * 加密
     *
     * @param content 内容
     * @param key     key
     * @return java.lang.String
     */
    public static String encrypt(String content, String key) {
    
    
        try {
    
    
            //获得密码的字节数组
            byte[] raw = key.getBytes();
            //根据密码生成AES密钥
            SecretKeySpec skey = new SecretKeySpec(raw, "AES");
            //根据指定算法ALGORITHM自成密码器
            Cipher cipher = Cipher.getInstance(ALGORITHMS);
            //初始化密码器,第一个参数为加密(ENCRYPT_MODE)或者解密(DECRYPT_MODE)操作,第二个参数为生成的AES密钥
            cipher.init(Cipher.ENCRYPT_MODE, skey);
            //获取加密内容的字节数组(设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码
            byte[] byteContent = content.getBytes(StandardCharsets.UTF_8);
            //密码器加密数据
            byte[] encodeContent = cipher.doFinal(byteContent);
            //将加密后的数据转换为字符串返回
            return Base64.encodeBase64String(encodeContent);
        } catch (Exception e) {
    
    
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 解密
     *
     * @param encryptStr 加密后的内容
     * @param decryptKey 解密key
     * @return java.lang.String
     */
    public static String decrypt(String encryptStr, String decryptKey) {
    
    
        try {
    
    
            //获得密码的字节数组
            byte[] raw = decryptKey.getBytes();
            //根据密码生成AES密钥
            SecretKeySpec skey = new SecretKeySpec(raw, "AES");
            //根据指定算法ALGORITHM自成密码器
            Cipher cipher = Cipher.getInstance(ALGORITHMS);
            //初始化密码器,第一个参数为加密(ENCRYPT_MODE)或者解密(DECRYPT_MODE)操作,第二个参数为生成的AES密钥
            cipher.init(Cipher.DECRYPT_MODE, skey);
            //把密文字符串转回密文字节数组
            byte[] encodeContent = Base64.decodeBase64(encryptStr);
            //密码器解密数据
            byte[] byteContent = cipher.doFinal(encodeContent);
            //将解密后的数据转换为字符串返回
            return new String(byteContent, StandardCharsets.UTF_8);
        } catch (Exception e) {
    
    
            log.error("String : {} aes decrypt error", encryptStr);
            return null;
        }
    }
}

直接调用静态方法

String passWord= AesUtil.decrypt(loginDTO.getPassword(),"XXXXXXXXXXXXXX");

三、总结

总之,加密和解密在实际业务中还是很必要的,而选择哪样的方式加密自己斟酌。

另外,以上例子中其实存在些许问题,例如秘钥写死在前端代码中,这样其实别人是可以通过抓取你的js文件进行分析获取的,建议通过后端获取。

如果对安全要求更高的话,还是建议使用https吧

猜你喜欢

转载自blog.csdn.net/weixin_48353638/article/details/128939446