前后端(JAVA)實現AES對稱加解密方式

文章目錄

  • 前后端(JAVA)實現AES對稱加解密方式
    • 1 對稱加密分類以及概括
      • 1.1 加密安全等級 DES < 3DES < AES < RC
      • 1.2 DES
      • 1.3 3DES
      • 1.4 AES
      • 1.5 RC
    • 2 前后端實現AES對稱加解密方式
    • 3 后端AES對稱加解密(ECB和CBC模式)工具類
    • 4 前端(VUE)AES對稱加解密(CBC模式)工具類
      • 4.1 aseKeConfig.js AES+CBC配置
      • 4.2 加密解密工具類 aesSecretUtil.js

前后端(JAVA)實現AES對稱加解密方式

1 對稱加密分類以及概括

文章《加解密篇 - 對稱加密算法 (DES、3DES、AES、RC)》有對這幾種對稱加密的說明,我大概概括一下。

1.1 加密安全等級 DES < 3DES < AES < RC

依次是DES < 3DES < AES < RC

1.2 DES

DES全稱 Data Encryption Standard,是一種使用密鑰加密的塊算法,該加密算法運用非常普遍,是一種標準的加密算法。現在認為是一種不安全的加密算法,因為現在已經有用窮舉法攻破 DES 密碼的報道了,所以誕生了3DES。

1.3 3DES

3DES(或稱為 Triple DES)是三重數據加密算法(TDEA,Triple Data Encryption Algorithm)塊密碼的通稱。它相當于是對每個數據塊應用三次 DES 加密算法。

1.4 AES

AES 加密算法的安全性要高于 DES 和 3DES,所以 AES 已經成為了主要的對稱加密算法。AES 加密算法就是眾多對稱加密算法中的一種,它的英文全稱是 Advanced Encryption Standard,翻譯過來是高級加密標準,它是用來替代之前的 DES 加密算法的。

AES 一共有四種加密模式,分別是 ECB(電子密碼本模式)、CBC(密碼分組鏈接模式)、CFB、OFB,我們一般使用的是 CBC 模式。四種模式中除了 ECB 相對不安全之外,其它三種模式的區別并沒有那么大。

1.5 RC

RC加密包括RC2,RC4,RC5,RC2 是由著名密碼學家 Ron Rivest 設計的一種傳統對稱分組加密算法,它可作為 DES 算法的建議替代算法。它的輸入和輸出都是64bit。密鑰的長度是從1字節到128字節可變,但目前的實現是8字節(1998年)。

參考:
加解密篇 - 對稱加密算法 (DES、3DES、AES、RC)

2 前后端實現AES對稱加解密方式

  1. AES為對稱加密算法,顧名思義,如果是前后端加解密場景,那前端需要保存一份秘鑰,后端也需要保存一份秘鑰,這兩個秘鑰是相同的,才可以實現加解密。

  2. AES的秘鑰默認長度為16位,初始向量 IV也是16位,這兩個默認長度一定要遵守,否則會有很多不可未知的錯誤。如果需要增加秘鑰的長度增加復雜性,則推薦使用RC加密算法,因為該算法的秘鑰長度可變。

  3. 待解密長度需要為16的倍數,否則會報以下錯誤,常用的解決辦法為加密后使用Base64包裝密文,則會自動補齊為16的倍數,解密時先使用Base64解密,則密文一定是16的整數倍。

    Input length must be multiple of 16 when decrypting with padded cipher
    

3 后端AES對稱加解密(ECB和CBC模式)工具類

import org.apache.commons.lang3.StringUtils;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Base64;/*** @author * @description AES加解密(ECB和CBC模式)* @date 2023/12/8 15:08*/
public class AESEncryptUtil {/*** 加密模式* ECB: AES/ECB/PKCS5Padding* CBC: AES/CBC/NoPadding*/private static final String[] TRANSFORM_ALGORITHM = new String[]{"AES/ECB/PKCS5Padding", "AES/CBC/NoPadding"};/*** 初始向量樣式 IV*/private static String iv =  "HBJNRU56MDk4NzK6";private static final String ALGORITHM = "AES";private static final String CHARSET_NAME = "UTF-8";/*** AES加解key樣式*/public static String ENCRYPT_KEY = "7CC408B24462ABD1";/*** AES的ECB模式加解* @param data 待加密參數* @param key 加密key* @return*/public static String encryptECB(String data, String key) {if (StringUtils.isEmpty(key)) {throw new IllegalArgumentException("加密失敗,加密key為空");}SecretKeySpec aesKey = new SecretKeySpec(key.getBytes(Charset.forName(CHARSET_NAME)), ALGORITHM);try {Cipher cipher = Cipher.getInstance(TRANSFORM_ALGORITHM[0]);cipher.init(Cipher.ENCRYPT_MODE, aesKey);byte[] encrypted = cipher.doFinal(data.getBytes(Charset.forName(CHARSET_NAME)));// 使用Base64來包裝是規避報錯Input length must be multiple of 16 when decrypting with padded cipher// 解密的字節數組必須是16的倍數return Base64.getEncoder().encodeToString(encrypted);} catch (Exception e) {throw new IllegalArgumentException("加密失敗: "+ e.getMessage());}}/*** AES的ECB模式解密* @param data 待解密參數* @param key 解密key* @return*/public static String decryptECB(String data, String key) {if (StringUtils.isEmpty(key)) {throw new IllegalArgumentException("解密失敗,解密key為空");}byte[] decode = Base64.getDecoder().decode(data.getBytes(StandardCharsets.UTF_8));SecretKeySpec aesKey = new SecretKeySpec(key.getBytes(Charset.forName(CHARSET_NAME)), ALGORITHM);try {Cipher cipher = Cipher.getInstance(TRANSFORM_ALGORITHM[0]);cipher.init(Cipher.DECRYPT_MODE, aesKey);return new String(cipher.doFinal(decode));} catch (Exception e) {throw new IllegalArgumentException("解密失敗: "+ e.getMessage());}}/*** AES的CBC模式加密* @param data 要加密的數據* @param key 加密key* @return 加密的結果*/public static String encryptCBC(String data, String key) {try {// "算法/模式/補碼方式"Cipher cipher = Cipher.getInstance(TRANSFORM_ALGORITHM[1]);int blockSize = cipher.getBlockSize();byte[] dataBytes = data.getBytes(StandardCharsets.UTF_8);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 keyStr = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");IvParameterSpec ivStr = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));cipher.init(Cipher.ENCRYPT_MODE, keyStr, ivStr);byte[] encrypted = cipher.doFinal(plaintext);return Base64.getEncoder().encodeToString(encrypted);} catch (Exception e) {throw new IllegalArgumentException("加密失敗: "+ e.getMessage());}}/*** AES的CBC模式解密* @param data 要解密的數據* @param key 解密key* @return 解密的結果*/public static String decryptCBC(String data, String key) {try {byte[] encrypted1 = Base64.getDecoder().decode(data);Cipher cipher = Cipher.getInstance(TRANSFORM_ALGORITHM[1]);SecretKeySpec keyStr = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");IvParameterSpec ivStr = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));cipher.init(Cipher.DECRYPT_MODE, keyStr, ivStr);byte[] original = cipher.doFinal(encrypted1);return new String(original, StandardCharsets.UTF_8);} catch (Exception e) {throw new IllegalArgumentException("解密失敗: "+ e.getMessage());}}public static void main(String[] args) throws Exception {String data = "hello Test symmetric encry";String keyStr = "7CC408B24462ABD1";String encryDataStr = encryptECB(data, keyStr);System.out.println("encryptECB = " + encryDataStr);System.out.println("decryptECB = " + decryptECB(encryDataStr, keyStr));encryDataStr = encryptCBC(data, keyStr);System.out.println("encryptCBC = " + encryDataStr);System.out.println("decryptCBC = " + decryptCBC(encryDataStr, keyStr));}}

4 前端(VUE)AES對稱加解密(CBC模式)工具類

前端其他工程配置請看文章《java前后端參數和返回加密解密AES+CBC》

npm install crypto-js

4.1 aseKeConfig.js AES+CBC配置

export const AES_KEY = 'MTIzNDU2Nzg5MEFC'
export const AES_IV = 'QUJDRURGMDk4NzY1'
// 參數是否進行加密設置,需要與后端配置保持一致
export const PARAM_ENCRYPT_ABLE = true
// 結果是否進行加密
export const RESULT_ENCRYPT_ABLE = true
// 需要排除的不進行加密的接口,正則匹配
export const EXCLUE_PATH = ['.*/orc/.*', '.*/fastdfs/.*', '.*/eempFastdfs/.*', ',.*/homepage/preview', '.*oauth/getClickApplicationInfo', '.*/common/defaultKaptcha.*', '.*/autoKeyword$', '.*/getLayerCount$', '.*/getLayerInfoListByPage$','.*/epUiImgSaveAndAnalysisMultipartFile$', '/v7/weather']

4.2 加密解密工具類 aesSecretUtil.js

import CryptoJS from 'crypto-js'
import {AES_KEY,AES_IV,PARAM_ENCRYPT_ABLE,EXCLUE_PATH,RESULT_ENCRYPT_ABLE
}
from '../config/aesKeyConfig.js'
const key = CryptoJS.enc.Utf8.parse(AES_KEY) // 16位const iv = CryptoJS.enc.Utf8.parse(AES_IV)const excluePath = EXCLUE_PATHconst paramEncryptAble = PARAM_ENCRYPT_ABLEconst resultEncryptAble = RESULT_ENCRYPT_ABLE/***Description AES CBC BASE64加密解密*@author*@date 13:38 2022/3/31*/export default {// aes加密encrypt(word) {let encrypted = ''if (typeof word === 'string') {const srcs = CryptoJS.enc.Utf8.parse(word)encrypted = CryptoJS.AES.encrypt(srcs, key, {iv: iv,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.ZeroPadding})} else if (typeof word === 'object') {// 對象格式的轉成json字符串const data = JSON.stringify(word)const srcs = CryptoJS.enc.Utf8.parse(data)encrypted = CryptoJS.AES.encrypt(srcs, key, {iv: iv,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.ZeroPadding})}return CryptoJS.enc.Base64.stringify(encrypted.ciphertext)},// aes解密decrypt(word) {if (word) {let base64 = CryptoJS.enc.Base64.parse(word)let src = CryptoJS.enc.Base64.stringify(base64)var decrypt = CryptoJS.AES.decrypt(src, key, {iv: iv,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.ZeroPadding})var decryptedStr = decrypt.toString(CryptoJS.enc.Utf8)return decryptedStr.toString()} else {return word}},// 判斷url是否在匹配的正則表達式上,匹配則不進行加密,不配則需要加密checkIsExcluePath(url) {// 如果包含需要排除加密的接口返回truelet flag = falsefor (let i = 0; i < excluePath.length; i++) {if (new RegExp('^' + excluePath[i]).test(url)) {flag = truebreak} else {flag = false}}return flag},// 判斷是否請求需要進行加密,配置值true的時候需要加密否則不需要checkParamEncryptAble() {// console.log(encryptAble)return paramEncryptAble},// 判斷是否只對結果進行加密checkResultEncryptAble() {// console.log(encryptAble)return resultEncryptAble}}

參考:
java前后端參數和返回加密解密
對稱加密( 共享密鑰密碼 ) —用相同的密鑰進行加密和解密
手寫一個java加密工具類Securit
Java中的AES加解密(CBC模式)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/213438.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/213438.shtml
英文地址,請注明出處:http://en.pswp.cn/news/213438.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Python百寶箱】從傳感器到云端:深度解析Python在物聯網中的多面應用

邁向智能未來&#xff1a;Python與物聯網生態系統的完美融合 前言 隨著物聯網技術的不斷發展&#xff0c;Python作為一種靈活且強大的編程語言&#xff0c;逐漸成為物聯網開發的重要工具之一。本文將深入探討物聯網領域中常用的Python庫和框架&#xff0c;涵蓋了從輕量級通信…

JavaScript <有道翻譯之數據解密‘23年12月06日版‘>--案例(三)

前言: 記得上半年還是去年,有道翻譯還是直接返回明文數據;現在也跟著,用接口返回加密數據了; 娛樂一下,破他的密文數據... 成品效果圖: js部分: 對于找他的密文數據有點費時,針對密文--->搜他地址和啟動器不是特別容易,輾轉多時(搜:descrypt/json.parse 結合使用更快),有圖…

通訊錄實現

下方是頭文件的代碼 #define _CRT_SECURE_NO_WARNINGS #include <assert.h> #include<stdio.h> #include<string.h> #include<stdlib.h>#define NAME_MAX 20 #define SEX_MAX 6 #define TELE_MAX 12 #define ADDR_MAX 30 #define MAX 100 #define D…

swing快速入門(四)

注釋很詳細&#xff0c;直接上代碼 上一篇 增加內容 流式布局范例 import java.awt.*;public class swing_test_2{public static void main(String[] args){//創建一個窗口對象Frame framenew Frame("test");//設置窗口大小frame.setSize(800,800);//這里演示的是…

Gateway全局異常處理及請求響應監控

前言 我們在上一篇文章基于壓測進行Feign調優完成的服務間調用的性能調優&#xff0c;此時我們也關注到一個問題&#xff0c;如果我們統一從網關調用服務&#xff0c;但是網關因為某些原因報錯或者沒有找到服務怎么辦呢&#xff1f; 如下所示&#xff0c;筆者通過網關調用acc…

中小企業管理者如何培育團隊精神?

某石油工程有限公司總經理曾提問&#xff1a;“作為中小企業的管理者如何才能更好的激發團隊精神呢&#xff1f;” 每個企業都向往和號召團隊精神&#xff0c;但是往往事與愿違。在各種羨慕嫉妒恨的情緒影響下&#xff0c;難免會產生一些落差&#xff0c;影響到團隊精神。 所…

超聲波清洗機會損傷物品嗎?一文明白超聲波清洗機有哪些優點

正確使用超聲波清洗機且買對超聲波清洗機是不會對清洗物品造成傷害的&#xff01; 一、超聲波清洗機工作原理是如何的&#xff1f; 超聲波清洗機的工作原理是利用超聲波產生的空化振動來清潔物體。當超聲波在清洗液中傳播時&#xff0c;它會產生微小的氣泡和振動&#xff0c;這…

論jenkins的使用方法(初步)

&#x1f4d1;打牌 &#xff1a; da pai ge的個人主頁 &#x1f324;?個人專欄 &#xff1a; da pai ge的博客專欄 ??寶劍鋒從磨礪出&#xff0c;梅花香自苦寒來 目錄 &#x1f4d1;什么是持續集成&…

1-1、Java概述

語雀原文鏈接 文章目錄 1、Java發展2、Java體系結構3、Java特點 1、Java發展 1990年&#xff0c;Sun公司(Stanford University Network,斯坦福大學網絡公司)詹姆斯高斯林推出的一門語言最開始注冊的名字oak語言(橡樹)&#xff0c;重名了被迫改成Java2009年Sun公司被甲骨文Ora…

Docker 容器中使用 Docker - DinD 和 DooD

突然間研究這個來的緣由是正在從 Jenkins 往 Harness 的過度, 而完全用命令來構建 Docker 鏡像變得不一樣了。在 Jenkins 中 Agent 本身也是一個 Docker Daemon, 所以 Docker 命令執行無障礙&#xff0c;而 Harness 的所謂的 Agent 就是一個個的運行在 Kubernetes 中的 Docker …

error:gmapping

– Could not find the required component ‘gmapping’. The following CMake error indicates that you either need to install the package with the same name or change your environment so that it can be found. CMake Error at /opt/ros/kinetic/share/catkin/cmake…

logstash插件簡單介紹

logstash插件 輸入插件(input) Input&#xff1a;輸入插件。 Input plugins | Logstash Reference [8.11] | Elastic 所有輸入插件都支持的配置選項 SettingInput typeRequiredDefaultDescriptionadd_fieldhashNo{}添加一個字段到一個事件codeccodecNoplain用于輸入數據的…

【SpringBoot教程】SpringBoot Thymeleaf 基于HTML5的現代模板引擎

作者簡介&#xff1a;大家好&#xff0c;我是擼代碼的羊駝&#xff0c;前阿里巴巴架構師&#xff0c;現某互聯網公司CTO 聯系v&#xff1a;sulny_ann&#xff08;17362204968&#xff09;&#xff0c;加我進群&#xff0c;大家一起學習&#xff0c;一起進步&#xff0c;一起對抗…

error:move_base_msgs

CMake Warning at /opt/ros/kinetic/share/catkin/cmake/catkinConfig.cmake:76 (find_package): Could not find a package configuration file provided by “move_base_msgs” with any of the following names: move_base_msgsConfig.cmake move_base_msgs-config.cmake …

鼠標光標不見了怎么辦?速速get這4個方法!

“非常奇怪&#xff0c;我的鼠標光標用著用著就不見了&#xff0c;這是為什么呢&#xff1f;有什么方法可以解決這個問題嗎&#xff1f;” 在電腦使用過程中&#xff0c;有時候會遇到鼠標光標突然消失的情況&#xff0c;這無疑會給我們日常操作帶來很大的不便。那么&#xff0c…

Linux bin包生成

需求背景&#xff1a; 在實際項目時我們很少把源碼用個tar給到客戶&#xff0c;這樣顯得很不專業&#xff0c;且有的時候我們提供補丁&#xff0c;那么這個時候我們提供一個補丁的bin包可以直接安裝運行就顯得很高大上了。 物料準備 準備一臺liunx&#xff0c;虛擬機亦可&am…

自定義插件vue-router簡單實現hashRouter設計思路

步驟 1.掛載 vue.prototype.$router 2.聲明兩個組件 router-view this.$router.current>component > h(component) router-link h(a,{attrs:{href:#this.to}},this.$slots.default) 3.url的監聽&#xff1a;window hashchange的改變 4.定義響應式current&#xff0…

使用Python提取PDF文件中指定頁面的內容

在日常工作和學習中&#xff0c;我們經常需要從PDF文件中提取特定頁面的內容。在本篇文章中&#xff0c;我們將介紹如何使用Python編程語言和兩個強大的庫——pymupdf和wxPython&#xff0c;來實現這個任務。 1. 準備工作 首先&#xff0c;確保你已經安裝了以下兩個Python庫&…

JavaScript深拷貝和淺拷貝

對于原始數據類型&#xff0c;并沒有深淺拷貝的區別&#xff0c;深淺拷貝都是對于引用數據類型而言&#xff0c;如果我們要賦值對象的所有屬性都是引用類型可以用淺拷貝 淺拷貝&#xff1a;只復制一層對象&#xff0c;當對象的屬性是引用類型時&#xff0c;實質復制的是其引用&…

【辦公軟件】Outlook啟動一直顯示“正在啟動”的解決方法

早上打開電腦Outlook2016以后&#xff0c;半個多小時了&#xff0c;一直顯示這個界面&#xff1a; 解決辦法 按WIN R鍵打開“運行”&#xff0c;輸入如下命令&#xff1a; outlook.exe /safe 然后點擊“確定” 這樣就進入了Outlook的安全模式。 點擊“文件”->“選項”-…