Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
298 changes: 297 additions & 1 deletion docs/03.辅助查询/04.加密算法/08.aes.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ article: false

::: details 关于

# AES加密核心参数说明表
| 参数 | 说明 | 可选值(推荐) |
| ---- | ---- | ---- |
| 密钥长度 | AES 标准密钥长度,决定加密强度(对称加密中密钥需双方共享,长度需一致) | 128 位、192 位、256 位(推荐 256 位) |
| 加密模式 | 数据分组的处理方式,需加密 / 解密端保持一致 | CBC(需 IV)、GCM(带认证,更安全) |
| 填充方式 | 当数据长度不足分组长度(16 字节)时的补全规则 | PKCS#7(通用)、ZeroPadding |
| 初始向量(IV) | 仅 CBC/GCM 等模式需用,随机生成(每次加密不同),需和密文一起传输 | 16 字节随机数(CBC)、12 字节(GCM) |
| 密钥格式 | 通常用 Base64 编码存储 / 传输,便于文本格式处理 | Base64 字符串(推荐)、Hex 字符串 |

::: right
AES [维基百科]()
:::
Expand All @@ -16,9 +25,90 @@ AES [维基百科]()
<code-group>
<code-block title="依赖库" active>
</code-block>

<code-block title="纯源码">
</code-block>
```python
import base64
import os
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad # 处理PKCS#7填充

def generate_aes_key(key_size=256):
"""生成AES密钥(256位),返回Base64编码的密钥字符串(便于存储/传输)"""
if key_size not in [128, 192, 256]:
raise ValueError("AES密钥长度仅支持128、192、256位")
# 生成对应字节数的随机密钥(1位=8字节,256位=32字节)
key_bytes = os.urandom(key_size // 8)
return base64.b64encode(key_bytes).decode("utf-8")

def aes_encrypt_gcm(plaintext, aes_key_b64):
"""
AES-GCM模式加密(带认证,防篡改)
:param plaintext: 待加密明文(字符串)
:param aes_key_b64: Base64编码的AES密钥
:return: 字典(包含密文、IV、认证标签,需一起传输给解密端)
"""
# 1. 解码Base64密钥
key_bytes = base64.b64decode(aes_key_b64)
# 2. 生成GCM模式所需的12字节IV(GCM推荐IV长度12字节,安全性更高)
iv = os.urandom(12)
# 3. 初始化AES加密器(GCM模式)
cipher = AES.new(key_bytes, AES.MODE_GCM, nonce=iv)
# 4. 加密(GCM无需额外填充,自动处理分组)
ciphertext_bytes, tag = cipher.encrypt_and_digest(plaintext.encode("utf-8"))
# 5. 密文、IV、标签均用Base64编码(便于文本传输,如JSON/HTTP)
return {
"ciphertext": base64.b64encode(ciphertext_bytes).decode("utf-8"),
"iv": base64.b64encode(iv).decode("utf-8"),
"tag": base64.b64encode(tag).decode("utf-8")
}

def aes_decrypt_gcm(encrypted_data, aes_key_b64):
"""
AES-GCM模式解密
:param encrypted_data: 加密后的数据字典(ciphertext、iv、tag)
:param aes_key_b64: Base64编码的AES密钥
:return: 解密后的明文(字符串)
"""
try:
# 1. 解码各参数
key_bytes = base64.b64decode(aes_key_b64)
iv = base64.b64decode(encrypted_data["iv"])
ciphertext_bytes = base64.b64decode(encrypted_data["ciphertext"])
tag = base64.b64decode(encrypted_data["tag"])
# 2. 初始化AES解密器(需传入IV和标签)
cipher = AES.new(key_bytes, AES.MODE_GCM, nonce=iv)
# 3. 解密并验证标签(标签不匹配会抛异常,说明数据被篡改)
plaintext_bytes = cipher.decrypt_and_verify(ciphertext_bytes, tag)
return plaintext_bytes.decode("utf-8")
except Exception as e:
raise ValueError(f"解密失败(数据可能被篡改或参数错误):{str(e)}")

# ------------------------------ 示例:使用流程 ------------------------------
if __name__ == "__main__":
# 1. 生成AES密钥(仅需生成一次,双方保存,切勿泄露)
aes_key = generate_aes_key(key_size=256)
print(f"AES-256密钥(Base64):\n{aes_key}\n")

# 2. 加密数据(如敏感信息、长文本)
plaintext = "这是需要加密的敏感数据:SpiderAPI - 虫术,包含RSA/AES混合加密场景"
encrypted = aes_encrypt_gcm(plaintext, aes_key)
print(f"加密后数据:\n{encrypted}\n")

# 3. 解密数据(解密端需获取加密后的ciphertext、iv、tag)
decrypted = aes_decrypt_gcm(encrypted, aes_key)
print(f"解密后明文:\n{decrypted}")
"""
AES-256密钥(Base64):
d2fril3Gq2mvYw1wePmDGoA/sWcosbs/g=

加密后数据:
{'ciphertext': 'udcsoo1u7740Odjr9584FM8qzfO0jNqOGeYSZ4uNvcsADfl6EcK1Ya1bOwp7swvqnsY/IEX6HkotLz3PefJYEeED2QDdDD+KPHu7snxsFECg==', 'iv': 'wUnusEDh53Qgqull', 'tag': 'XmYBjOZgLXOAPWScjxhLZQ=='}

解密后明文:
这是需要加密的敏感数据:SpiderAPI - 虫术,包含RSA/AES混合加密场景
"""
```
</code-group>

## JavaScript <Badge text="Node.js"/> <Badge text="ECMAScript 5.1+"/>
Expand All @@ -28,6 +118,85 @@ AES [维基百科]()
</code-block>

<code-block title="纯源码">
```javascript
const crypto = require("crypto");

/**
* 生成AES密钥(256位),返回Base64编码的密钥
* @param {number} keySize - 密钥长度(128/192/256)
* @returns {string} Base64编码的AES密钥
*/
function generateAesKey(keySize = 256) {
if (![128, 192, 256].includes(keySize)) {
throw new Error("AES密钥长度仅支持128、192、256位");
}
// 生成对应字节数的随机密钥(256位=32字节)
const keyBytes = crypto.randomBytes(keySize / 8);
return keyBytes.toString("base64");
}

/**
* AES-GCM模式加密
* @param {string} plaintext - 待加密明文
* @param {string} aesKeyB64 - Base64编码的AES密钥
* @returns {object} 包含ciphertext(密文)、iv(初始向量)、tag(认证标签)的对象
*/
function aesEncryptGcm(plaintext, aesKeyB64) {
// 1. 解码Base64密钥
const keyBytes = Buffer.from(aesKeyB64, "base64");
// 2. 生成12字节IV(GCM推荐长度)
const iv = crypto.randomBytes(12);
// 3. 初始化加密器(GCM模式,自动处理分组,无需额外填充)
const cipher = crypto.createCipheriv("aes-256-gcm", keyBytes, iv);
// 4. 加密(分两段处理:update+final,兼容长文本)
let ciphertext = cipher.update(plaintext, "utf8", "base64");
ciphertext += cipher.final("base64");
// 5. 获取认证标签(GCM模式必须,用于解密时验证数据完整性)
const tag = cipher.getAuthTag().toString("base64");
return { ciphertext, iv: iv.toString("base64"), tag };
}

/**
* AES-GCM模式解密
* @param {object} encryptedData - 加密数据({ciphertext, iv, tag})
* @param {string} aesKeyB64 - Base64编码的AES密钥
* @returns {string} 解密后的明文
*/
function aesDecryptGcm(encryptedData, aesKeyB64) {
try {
// 1. 解码各参数
const keyBytes = Buffer.from(aesKeyB64, "base64");
const iv = Buffer.from(encryptedData.iv, "base64");
const ciphertext = Buffer.from(encryptedData.ciphertext, "base64");
const tag = Buffer.from(encryptedData.tag, "base64");
// 2. 初始化解密器(需传入IV和标签)
const decipher = crypto.createDecipheriv("aes-256-gcm", keyBytes, iv);
decipher.setAuthTag(tag); // 设置认证标签,验证数据完整性
// 3. 解密(分两段处理)
let plaintext = decipher.update(ciphertext, null, "utf8");
plaintext += decipher.final("utf8");
return plaintext;
} catch (error) {
throw new Error(`解密失败(数据篡改或参数错误):${error.message}`);
}
}

// ------------------------------ 示例:使用流程 ------------------------------
(function () {
// 1. 生成AES密钥
const aesKey = generateAesKey(256);
console.log(`AES-256密钥(Base64):\n${aesKey}\n`);

// 2. 加密数据
const plaintext = "这是需要加密的敏感数据:SpiderAPI - 虫术,包含RSA/AES混合加密场景";
const encrypted = aesEncryptGcm(plaintext, aesKey);
console.log("加密后数据:\n", JSON.stringify(encrypted, null, 2), "\n");

// 3. 解密数据
const decrypted = aesDecryptGcm(encrypted, aesKey);
console.log(`解密后明文:\n${decrypted}`);
})();
```
</code-block>
</code-group>

Expand All @@ -38,6 +207,133 @@ AES [维基百科]()
</code-block>

<code-block title="纯源码">
```go
package main

import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"encoding/json"
"fmt"
"io"
)

// AESKey 封装AES密钥相关操作
type AESKey struct {
KeySize int // 密钥长度(128/192/256)
KeyB64 string // Base64编码的密钥
}

// GenerateAESKey 生成AES密钥(默认256位)
func GenerateAESKey(keySize int) (*AESKey, error) {
if keySize != 128 && keySize != 192 && keySize != 256 {
return nil, fmt.Errorf("AES密钥长度仅支持128、192、256位,当前输入:%d", keySize)
}
// 生成对应字节数的随机密钥(256位=32字节)
keyBytes := make([]byte, keySize/8)
if _, err := io.ReadFull(rand.Reader, keyBytes); err != nil {
return nil, fmt.Errorf("生成密钥失败:%w", err)
}
return &AESKey{
KeySize: keySize,
KeyB64: base64.StdEncoding.EncodeToString(keyBytes),
}, nil
}

// AESEncryptGCM AES-GCM模式加密
func (k *AESKey) AESEncryptGCM(plaintext string) (map[string]string, error) {
// 1. 解码Base64密钥
keyBytes, err := base64.StdEncoding.DecodeString(k.KeyB64)
if err != nil {
return nil, fmt.Errorf("密钥解码失败:%w", err)
}
// 2. 创建AES块
block, err := aes.NewCipher(keyBytes)
if err != nil {
return nil, fmt.Errorf("初始化AES块失败:%w", err)
}
// 3. 初始化GCM模式(GCM推荐IV长度12字节)
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, fmt.Errorf("初始化GCM模式失败:%w", err)
}
// 4. 生成IV
iv := make([]byte, gcm.NonceSize()) // gcm.NonceSize()返回12(GCM模式)
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
return nil, fmt.Errorf("生成IV失败:%w", err)
}
// 5. 加密(GCM自动处理填充和认证标签)
ciphertextBytes := gcm.Seal(nil, iv, []byte(plaintext), nil)
// 6. 编码返回(密文、IV、标签,标签已包含在ciphertextBytes末尾,无需单独生成)
return map[string]string{
"ciphertext": base64.StdEncoding.EncodeToString(ciphertextBytes),
"iv": base64.StdEncoding.EncodeToString(iv),
}, nil
}

// AESDecryptGCM AES-GCM模式解密
func (k *AESKey) AESDecryptGCM(encryptedData map[string]string) (string, error) {
// 1. 解码各参数
keyBytes, err := base64.StdEncoding.DecodeString(k.KeyB64)
if err != nil {
return "", fmt.Errorf("密钥解码失败:%w", err)
}
iv, err := base64.StdEncoding.DecodeString(encryptedData["iv"])
if err != nil {
return "", fmt.Errorf("IV解码失败:%w", err)
}
ciphertextBytes, err := base64.StdEncoding.DecodeString(encryptedData["ciphertext"])
if err != nil {
return "", fmt.Errorf("密文解码失败:%w", err)
}
// 2. 创建AES块和GCM模式
block, err := aes.NewCipher(keyBytes)
if err != nil {
return "", fmt.Errorf("初始化AES块失败:%w", err)
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return "", fmt.Errorf("初始化GCM模式失败:%w", err)
}
// 3. 解密(GCM自动验证标签,标签不匹配会抛异常)
plaintextBytes, err := gcm.Open(nil, iv, ciphertextBytes, nil)
if err != nil {
return "", fmt.Errorf("解密失败(数据篡改或参数错误):%w", err)
}
return string(plaintextBytes), nil
}

// ------------------------------ 示例:使用流程 ------------------------------
func main() {
// 1. 生成AES-256密钥
aesKey, err := GenerateAESKey(256)
if err != nil {
fmt.Printf("生成密钥失败:%v\n", err)
return
}
fmt.Printf("AES-256密钥(Base64):\n%s\n\n", aesKey.KeyB64)

// 2. 加密数据
plaintext := "这是需要加密的敏感数据:SpiderAPI - 虫术,包含RSA/AES混合加密场景"
encryptedData, err := aesKey.AESEncryptGCM(plaintext)
if err != nil {
fmt.Printf("加密失败:%v\n", err)
return
}
encryptedJSON, _ := json.MarshalIndent(encryptedData, "", " ")
fmt.Printf("加密后数据:\n%s\n\n", encryptedJSON)

// 3. 解密数据
decryptedText, err := aesKey.AESDecryptGCM(encryptedData)
if err != nil {
fmt.Printf("解密失败:%v\n", err)
return
}
fmt.Printf("解密后明文:\n%s\n", decryptedText)
}
```
</code-block>
</code-group>

Expand Down