java前后端加密解密crypto-js

Posted 渔夫搬砖

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java前后端加密解密crypto-js相关的知识,希望对你有一定的参考价值。

项目场景:

适用于接口数据敏感信息,比如 明文传输姓名、居住地址、手机号等信息,如果存在明文传输敏感数据问题、及数据泄漏风险,则可使用此方法加密解密。


一、下载crypot-js

1.如果为vue项目,安装cnpm,采用命令安装即可:

安装命令:cnpm install crypto-js;

2.如果为一般web项目,https://github.com/brix/crypto-js,进行下载;


二、前端引入crypto-js文件,并命名为secrt.js

import CryptoJS from 'crypto-js'

// 默认的 KEY 与 iv 如果没有给,可自行设定,但必须16位

const KEY = CryptoJS.enc.Utf8.parse("abcdefgh12345678");

const IV = CryptoJS.enc.Utf8.parse('12345678abcdefgh');

/**

 * AES加密 :字符串 key iv  返回base64

 */

export function Encrypt(word, keyStr, ivStr)

    let key = KEY;

    let iv = IV;

    if (keyStr)

        key = CryptoJS.enc.Utf8.parse(keyStr);

        iv = CryptoJS.enc.Utf8.parse(ivStr);

   

    let srcs = CryptoJS.enc.Utf8.parse(word);

    var encrypted = CryptoJS.AES.encrypt(srcs, key,

        iv: iv,

        mode: CryptoJS.mode.CBC,

        padding: CryptoJS.pad.ZeroPadding

    );

    return CryptoJS.enc.Base64.stringify(encrypted.ciphertext);

/**

 1. AES 解密 :字符串 key iv  返回base64

 2.  3. @return string

 */

export function Decrypt(word, keyStr, ivStr)

    let key = KEY;

    let iv = IV;

    if (keyStr)

        key = CryptoJS.enc.Utf8.parse(keyStr);

        iv = CryptoJS.enc.Utf8.parse(ivStr);

   

    let base64 = CryptoJS.enc.Base64.parse(word);

    let src = CryptoJS.enc.Base64.stringify(base64);

    let decrypt = CryptoJS.AES.decrypt(src, key,

        iv: iv,

        mode: CryptoJS.mode.CBC,

        padding: CryptoJS.pad.ZeroPadding

    );

    let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);

    return decryptedStr.toString();


三、前端页面引入并加密数据

import Encrypt from '../../secrt.js'

//text为需要加密的内容

var userId= Encrypt(text);

四、后端解密数据

1.pom引用

2.创建工具类

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;

public class SecretUtil
    /***
     * key和iv值可以随机生成,确保与前端的key,iv对应
     */
    private static String KEY = "abcdefgh12345678";
    private static String IV = "12345678abcdefgh";

    /***
     * 加密
     * 
     * @param data 要加密的数据
     * @return encrypt
     */
    public static String encrypt(String data)
        return encrypt(data, KEY, IV);
    
    
    /***

     *  解密
     * @param data 要解密的数据
     */
    public static String desEncrypt(String data)
        return desEncrypt(data, KEY, IV);
    

    /**
     * 加密方法
     */
    private static String encrypt(String data, String key, String iv)
        try
            // "算法/模式/补码方式"NoPadding PkcsPadding
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            int blockSize = cipher.getBlockSize();
            byte[] dataBytes = data.getBytes();
            int plaintextLength = dataBytes.length;
            if (plaintextLength % blockSize != 0)
                plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
            
            byte[] plaintext = new byte[plaintextLength];
            System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
            byte[] encrypted = cipher.doFinal(plaintext);

            return new Base64().encodeToString(encrypted);
         catch (Exception e)
            e.printStackTrace();
            return null;
        
    

    /**
     * 解密方法
     */
    private static String desEncrypt(String data, String key, String iv)
        try
            byte[] encrypted1 = new Base64().decode(data);

            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
            byte[] original = cipher.doFinal(encrypted1);
            return new String(original).trim();
         catch (Exception e)
            e.printStackTrace();
            return null;
        
    

 

3.数据解密

@GetMapping(value = "/userInfo")
 public getUserInfo(@RequestParam(name = "userId") String userId)
    String userId= desEncrypt(userId);

三分钟撸完前后端crypto-js加解密,你学废了吗?


前言

去年公司做了一个教育项目,该项目涉及到的敏感数据比较多,都是政府单位的人员保密数据,最终决定前后端进行接口加密处理,采用的是 AES + BASE64 算法加密,本篇文章我们再来复盘一下,不过之前公司的加密方式比这个复杂,不过整体思路设计上面和这个大同小异。


一、AES概念

高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法(微信小程序加密传输就是用这个加密算法的)。

相比于其他加密,AES加密似乎模式很多,包括ECB、CBC等等,本篇文章使用的是CBC模式,每个模式又包括IV参数和Padding参数,并且不同语言对AES加密的库设计有区别,这就导致了在不同的语言上面编写代码的难度。所以在我们设计AES加密的时候,应该注意一下几点:

  • 加密秘钥长度,秘钥,IV值,加密模式,PADDING方式(一般为:PKCS5, PKCS7, NOPADDING)
  • AES加密解密的秘钥有一对,一个是IV一个是KEY,并且他们的长度都有严格要求(十六位十六进制数)

二、前端加密

这里我们前后端统一采用AES对称加密的算法来实现登录密码和账号的加密。

对称加密算法:加密和解密用到的密钥是相同的,这种加密方式加密速度非常快,适合经常发送数据的场合。缺点是密钥的传输比较麻烦。

非对称加密算法:加密和解密用的密钥是不同的,这种加密方式是用数学上的难解问题构造的,通常加密解密的速度比较慢,适合偶尔发送数据的场合。优点是密钥传输方便。常见的非对称加密算法为RSA、ECC和EIGamal。

实际中,一般是通过RSA加密AES的密钥,传输到接收方,接收方解密得到AES密钥,然后发送方和接收方用AES密钥来通信。

1.安装依赖库

npm install crypto-js --save-dev

2.实现AES加密算法

CBC:是一种循环模式,前一个分组的密文和当前分组的明文异或或操作后再加密,这样做的目的是增强破解难度。(不容易主动攻击,安全性好于ECB,是SSL、IPSec的标准)

const CryptoJS = require('crypto-js');            
// 十六位十六进制数作为密钥(KEY必须和后台保持一致)
const key = CryptoJS.enc.Utf8.parse("CMDDTYDF&WY196KJ");
// 十六位十六进制数作为密钥偏移量
const iv = CryptoJS.enc.Utf8.parse('CMDDTYDF&WY196KJ');   

//解密方法
function Decrypt(data) 
    let encryptedHexStr = CryptoJS.enc.Base64.parse(data);
    let srcs = CryptoJS.enc.Base64.stringify(encryptedHexStr);
    let decrypt = CryptoJS.AES.decrypt(srcs, key,  iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 );
    let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
    return decryptedStr.toString();


//加密方法
function Encrypt(data) 
    let srcs = CryptoJS.enc.Utf8.parse(data);
    let encrypted = CryptoJS.AES.encrypt(srcs, key,  iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 );
    return CryptoJS.enc.Base64.stringify(encrypted.ciphertext);


export default 
    Decrypt ,
    Encrypt

3.前端演示效果


全部代码:

<template>
    <div class="container">
        <el-row>
            <el-card shadow="never">
                <div slot="header">
                    <h1>AES加密测试:<el-button type="primary" size="small" @click="keyBtn">AES加密</el-button></h1>
                    <p><el-input v-model="password" placeholder="请输入新密码"></el-input></p>
                    <p><el-input v-model="key" placeholder="秘钥" readonly></el-input></p>
                    <h1>AES解密测试:<el-button type="success" size="small" @click="keyBtn1">AES解密</el-button></h1>
                    <p><el-input v-model="key1" placeholder="请输入秘钥"></el-input></p>
                    <p><el-input v-model="password1" placeholder="原密码" disabled></el-input></p>
                </div>
            </el-card>
        </el-row>
    </div>
</template>

<script>
export default 
    data() 
        return 
            password: '',
            key: '',
            password1: '',
            key1: ''
        
    ,
    methods: 
        keyBtn: function () 
            let password = this.cryptoAes.Encrypt(this.password)
            this.key = password
        ,
        keyBtn1: function () 
            let key1 = this.cryptoAes.Decrypt(this.key1)
            this.password1 = key1
        
    

</script>

三、后端加密

1.加密工具类

/**
 * AES加密工具类
 * @author DT
 * @date 2021/9/4 13:10
 */
public class AesEncryptUtils 

    /**
     * 使用AES-128-CBC加密模式,key需要为16位,key和iv可以相同,也可以不同!
     */
    private static final String KEY = "CMDDTYDF&WY196KJ";
    private static final String IV = "CMDDTYDF&WY196KJ";

    /**
     * 算法/模式/补码方式
     */
    private static final String CIPHER_ALGORITHM_CBC = "AES/CBC/NoPadding";
    private static final String AES_ENC = "AES";

    /**
     * 加密方法
     * @param data 要加密的数据
     * @return     加密的结果
     */
    public static String encrypt(String data)
        try 
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC);
            int blockSize = cipher.getBlockSize();
            byte[] dataBytes = data.getBytes();
            int plaintextLength = dataBytes.length;
            if (plaintextLength % blockSize != 0) 
                plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
            
            byte[] plaintext = new byte[plaintextLength];
            System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
            SecretKeySpec keySpec = new SecretKeySpec(KEY.getBytes(), AES_ENC);
            IvParameterSpec ivSpec = new IvParameterSpec(IV.getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
            byte[] encrypted = cipher.doFinal(plaintext);
            return new Base64().encodeToString(encrypted);
         catch (Exception e) 
            e.printStackTrace();
            return null;
        
    

    /**
     * 解密方法
     * @param data 解密的数据
     * @return     解密的结果
     */
    public static String desEncrypt(String data) 
        try 
            byte[] encrypted1 = new Base64().decode(data);
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC);
            SecretKeySpec keySpec = new SecretKeySpec(KEY.getBytes(), AES_ENC);
            IvParameterSpec ivSpec = new IvParameterSpec(IV.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
            byte[] original = cipher.doFinal(encrypted1);
            return new String(original).trim();
         catch (Exception e) 
            e.printStackTrace();
            return null;
        
    

2.加密测试

public static void main(String[] args) 
       String encrypt = encrypt("123456");
       System.out.println("加密结果:"+encrypt);
   

 public static void main(String[] args) 
        String encrypt = desEncrypt("Ey4UI/fer5TjFituPzYEAA==");
        System.out.println("解密结果:"+encrypt);
    

四、Security实现密码加解密

1、前台加密


1、后台解密


总结

最后文章到这里就结束了,最近小编的最新版Spring Cloud Alibaba微服务架构-Sentinel高可用防护组件篇马上也要发布了,希望大家尝鲜,并且小编之前打造过一个后台管理系统,正在代码重构当中,集成了Activiti工作流,大家可以期待一下,总之不负小伙伴们的支持,后面会越来越多的干货,并且会给大家整体理一下,作为一个新生代农民工,我们应该如何提高我们的技术,这里小编自己创建了一个交流群,感兴趣的同学可以加入,群号在博客主页能看到,大家一起畅聊,无论前端还是后端,运维,都欢迎,职业不限。

本篇文章结束了,后面我们再继续深入研究微服务其他的组件的使用以及原理剖析,创作不易,喜欢的请关注小编CSDN:https://blog.csdn.net/qq_41107231 以及掘金:https://juejin.cn/user/3940246036699848

以上是关于java前后端加密解密crypto-js的主要内容,如果未能解决你的问题,请参考以下文章

java前后端加密解密crypto-js

【参数加密】前后端分离请求参数加密与响应结果加密处理

java结合node.js非对称加密,实现密文登录传参——让前后端分离的项目更安全

前后端分类,数据传输问题

SM2前后端交互加解密(已联调测通)

rsa加密前后端不一致