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}
评论