From e8888756a24538bca7d1d1f5395c9dbd89467165 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=88=B1=E5=96=9D=E6=B0=B4=E7=9A=84=E6=9C=A8=E5=AD=90?= <50564847+ice-a@users.noreply.github.com> Date: Fri, 29 Aug 2025 15:33:42 +0800 Subject: [PATCH] Update 08.aes.md --- .../08.aes.md" | 298 +++++++++++++++++- 1 file changed, 297 insertions(+), 1 deletion(-) diff --git "a/docs/03.\350\276\205\345\212\251\346\237\245\350\257\242/04.\345\212\240\345\257\206\347\256\227\346\263\225/08.aes.md" "b/docs/03.\350\276\205\345\212\251\346\237\245\350\257\242/04.\345\212\240\345\257\206\347\256\227\346\263\225/08.aes.md" index e137c5430..1584ec6f7 100644 --- "a/docs/03.\350\276\205\345\212\251\346\237\245\350\257\242/04.\345\212\240\345\257\206\347\256\227\346\263\225/08.aes.md" +++ "b/docs/03.\350\276\205\345\212\251\346\237\245\350\257\242/04.\345\212\240\345\257\206\347\256\227\346\263\225/08.aes.md" @@ -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 [维基百科]() ::: @@ -16,9 +25,90 @@ AES [维基百科]() - + ```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混合加密场景 +""" + ``` ## JavaScript @@ -28,6 +118,85 @@ AES [维基百科]() + ```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}`); +})(); + ``` @@ -38,6 +207,133 @@ AES [维基百科]() + ```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) +} + ```