AES的加密和解密

AES的基础知识

AES的加密模式(Mode)

AES的加密模式有:CBC、ECB、CTR、OCF、CFB。
其中 ECB 有安全问题,所以一定不选择。
而常用的是 CBC,并且 crypto-js 默认也用了 CBC 所以就无脑选择了 CBC

密钥的长度(Key)

AES需要指定密钥长度必须为 128 位、192 位或256 位,即字符串长度为:16、24 或 32。

初始化向量(IV)

一段固定长度的随机数,用于增强AES加密的强度。
IV的长度通常为16字节(即128位),它必须与密钥一起使用。

填充方式(Padding)

由于AES加密的块大小通常为128位,而明文的长度可能不是块大小的整数倍,因此需要进行填充。
常见的填充方式有PKCS#5和PKCS#7,它们可以保证明文长度为块大小的整数倍。

AES加密解密示例

php 示例

1$key       = 'a7gE3fH9jKmN1pQ2rS4tU6vY8zW9xL01';
2$iv        = '7hJ3kQxZW45mNpR2';
3$data      = '123456';
4$encrypted = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
5echo base64_encode($encrypted), PHP_EOL;
6$decrypted = openssl_decrypt($encrypted, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
7echo $decrypted;

javascript 示例

请先引入CryptoJS:<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>

 1  const key = CryptoJS.enc.Utf8.parse('a7gE3fH9jKmN1pQ2rS4tU6vY8zW9xL01'); // 秘钥
 2  const iv = CryptoJS.enc.Utf8.parse('7hJ3kQxZW45mNpR2'); // 初始化向量
 3  const plaintext = "Hello, AES encryption!"; // 原文
 4
 5  const encryptData = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(plaintext), key, {
 6    iv: iv, // 初始化向量
 7    mode: CryptoJS.mode.CBC, // 加密模式
 8    padding: CryptoJS.pad.Pkcs7 // 填充方式
 9  });
10  var ciphertext = encryptData.toString(); // 加密后的字符串
11  console.log(ciphertext);
12
13  var decryptData = CryptoJS.AES.decrypt(ciphertext, key, {
14    iv: iv, // 初始化向量
15    mode: CryptoJS.mode.CBC, // 加密模式
16    padding: CryptoJS.pad.Pkcs7 // 填充方式
17  });
18  var originalText = decryptData.toString(CryptoJS.enc.Utf8); // 解密后的字符串
19  console.log(originalText);

golang 示例

 1package main
 2
 3import (
 4	"bytes"
 5	"crypto/aes"
 6	"crypto/cipher"
 7	"encoding/base64"
 8	"fmt"
 9)
10
11func PKCS7Padding(paddingBytes []byte, blockSize int) []byte {
12	padding := blockSize - len(paddingBytes)%blockSize
13	padText := bytes.Repeat([]byte{byte(padding)}, padding)
14	return append(paddingBytes, padText...)
15}
16
17func PKCS7UnPadding(unPaddingBytes []byte) []byte {
18	length := len(unPaddingBytes)
19	unPadding := int(unPaddingBytes[length-1])
20	return unPaddingBytes[:(length - unPadding)]
21}
22
23func AesEncryptCBC(originalText string, key string, iv string) string {
24	originalBytes := []byte(originalText)
25	keyBytes := []byte(key)
26	ivBytes := []byte(iv)
27
28	block, _ := aes.NewCipher(keyBytes)
29	blockSize := block.BlockSize()
30	originalBytes = PKCS7Padding(originalBytes, blockSize)
31	cipherBytes := make([]byte, len(originalBytes))
32
33	blockMode := cipher.NewCBCEncrypter(block, ivBytes[:blockSize])
34	blockMode.CryptBlocks(cipherBytes, originalBytes)
35	return base64.StdEncoding.EncodeToString(cipherBytes)
36}
37
38func AesDecryptCBC(ciphertext string, key string, iv string) string {
39	cipherBytes, _ := base64.StdEncoding.DecodeString(ciphertext)
40	keyBytes := []byte(key)
41	ivBytes := []byte(iv)
42
43	block, _ := aes.NewCipher(keyBytes)
44	blockSize := block.BlockSize()
45	originalBytes := make([]byte, len(cipherBytes))
46
47	blockMode := cipher.NewCBCDecrypter(block, ivBytes[:blockSize])
48	blockMode.CryptBlocks(originalBytes, cipherBytes)
49	originalBytes = PKCS7UnPadding(originalBytes)
50	return string(originalBytes)
51}
52
53func main() {
54	key := "a7gE3fH9jKmN1pQ2rS4tU6vY8zW9xL01"
55	iv := "7hJ3kQxZW45mNpR2"
56	plaintext := "Hello, AES encryption!"
57	ciphertext := AesEncryptCBC(plaintext, key, iv)
58	fmt.Println(ciphertext)
59	originalText := AesDecryptCBC(ciphertext, key, iv)
60	fmt.Println(originalText)
61}

java 示例

该示例采用Hutool的Crypto模块,请先在pom.xml中引入Hutool库:

1<dependency>
2    <groupId>cn.hutool</groupId>
3    <artifactId>hutool-all</artifactId>
4    <version>5.8.16</version> <!-- 版本可调整 -->
5</dependency>

示例代码:

 1package com.tob.biz.qt.validator;
 2
 3import cn.hutool.crypto.symmetric.AES;
 4
 5import java.nio.charset.StandardCharsets;
 6
 7public class AESTest {
 8    public static void main(String[] args) {
 9        String key = "a7gE3fH9jKmN1pQ2rS4tU6vY8zW9xL01"; // 秘钥
10        String iv = "7hJ3kQxZW45mNpR2"; // 初始化向量
11        String plaintext = "Hello, AES encryption!"; // 原文
12
13        AES aes = new AES("CBC", "PKCS7Padding",
14                key.getBytes(StandardCharsets.UTF_8),  // 密钥,可以自定义
15                iv.getBytes(StandardCharsets.UTF_8) // 初始化向量
16        );
17
18        String ciphertext = aes.encryptBase64(plaintext); // 加密后的字符串
19        System.out.println(ciphertext);
20
21        String originalText = aes.decryptStr(ciphertext); // 解密后的字符串
22        System.out.println(originalText);
23    }
24}