不喜欢广告? 无广告 今天

为开发者提供的AES加密 何时需要以及如何工作

发布日期
为开发者提供的AES加密:何时需要以及如何工作 1
广告 移除?

如果您正在存储敏感数据——用户个人身份信息(PII)、API密钥、财务记录——那么AES加密就是您需要的工具。它是静态数据对称加密的行业标准:速度快、经过充分验证,并且在所有主流编程语言中都原生支持。

但错误使用AES比无用更糟糕。ECB模式会泄露数据模式。在GCM模式下重复使用IV会完全破坏其安全性保证。而将密钥与密文存储在一起则彻底失去了加密的意义。

以下是您在生产环境中正确使用AES所需的内容。

什么是AES?

AES(高级加密标准)是一种对称分组密码。对称意味着相同的密钥用于加密和解密。分组密码意味着它以固定大小的128位数据块进行操作。

AES于2001年取代DES,如今它无处不在:TLS、磁盘加密、密码管理器、数据库字段加密。与非对称加密(如RSA、ECDH)不同,AES足够快,可以实时加密大量数据。其代价是双方必须共享同一个密钥,因此密钥分发成为您的问题。

AES-128与AES-256:选择哪种密钥长度?

AES有三种密钥长度:128位、192位和256位。在实际应用中,您通常会在128位和256位之间进行选择。

AES-128AES-256
密钥长度128位256位
轮数1014
表现更快约慢40%
安全安全——目前没有已知的实际攻击方法更安全——对未来量子计算机具有抗性
结论适用于大多数应用场景用于高敏感数据或长期保留的数据

AES-128尚未被破解。目前不存在实际攻击方法。但如果您正在加密需要在20年以上保持安全的数据,或者您的威胁模型包括未来量子计算机,那么AES-256提供了有意义的安全余量。对于当前大多数数据库字段加密应用,AES-128是足够的。如有疑问,请使用AES-256;在典型工作负载下,性能损失可以忽略不计。

操作模式:为何选择GCM而非ECB

AES单独只能加密一个128位的数据块。对于真实数据,您需要一种操作模式来正确处理多个数据块并按顺序排列。这一选择至关重要。

模式认证需要IV结论
ECB永远不要使用——相同的明文会产生相同的密文,会泄露数据模式
CBC是的已过时——没有认证功能,易受填充预言攻击
GCM是(AEAD)是(nonce)使用此模式——一次加密并认证

使用GCM。GCM(伽罗瓦/计数器模式)是一种AEAD密码——带关联数据的认证加密。它同时完成两项任务:

  1. 加密您的数据,使其在没有密钥的情况下无法被读取
  2. 生成一个认证标签,以立即检测任何篡改行为

如果没有认证,攻击者可以修改密文中的位,而您将解密出垃圾数据却毫无察觉。在GCM模式下,如果密文被篡改,解密过程会立即失败,而不会返回任何明文数据。

IV/Nonce:随机且永不重复

GCM需要一个初始化向量(IV),也称为“一次性数字”(nonce)。IV不需要保密,但必须满足以下条件:

  • 随机的 —— 使用密码学安全的随机数生成器生成
  • 独特的 —— 与相同密钥永不重复使用

在GCM模式下,使用相同密钥和IV重复加密是灾难性的。如果攻击者看到两个使用相同密钥和IV加密的密文,他们可以将这两个密文进行异或运算,从而恢复出两个明文。这不是理论上的问题——它已经在生产系统中发生过。

每次加密操作使用96位(12字节)的随机IV。由于您需要它来进行解密,因此应将其与密文一起存储——将IV置于密文之前是传统格式。

工作代码:AES-256-GCM

以下是生产级别的代码片段。这些代码将IV和认证标签与密文一起存储,以确保解密过程的自包含性。

Node.js

const crypto = require('crypto');

const ALGORITHM = 'aes-256-gcm';
const KEY_LENGTH = 32; // 256 bits
const IV_LENGTH  = 12; // 96 bits — recommended for GCM
const TAG_LENGTH = 16; // 128-bit auth tag

function encrypt(plaintext, key) {
  const iv = crypto.randomBytes(IV_LENGTH);
  const cipher = crypto.createCipheriv(ALGORITHM, key, iv);

  const encrypted = Buffer.concat([
    cipher.update(plaintext, 'utf8'),
    cipher.final(),
  ]);
  const tag = cipher.getAuthTag();

  // Layout: [iv (12)] + [tag (16)] + [ciphertext]
  return Buffer.concat([iv, tag, encrypted]).toString('base64');
}

function decrypt(ciphertextB64, key) {
  const data      = Buffer.from(ciphertextB64, 'base64');
  const iv        = data.subarray(0, IV_LENGTH);
  const tag       = data.subarray(IV_LENGTH, IV_LENGTH + TAG_LENGTH);
  const encrypted = data.subarray(IV_LENGTH + TAG_LENGTH);

  const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);
  decipher.setAuthTag(tag);

  return Buffer.concat([decipher.update(encrypted), decipher.final()]).toString('utf8');
}

// Usage
const key        = crypto.randomBytes(KEY_LENGTH); // store this securely
const ciphertext = encrypt('sensitive data here', key);
const plaintext  = decrypt(ciphertext, key);

Python

import os, base64
from cryptography.hazmat.primitives.ciphers.aead import AESGCM

IV_LENGTH = 12  # 96 bits

def encrypt(plaintext: str, key: bytes) -> str:
    iv = os.urandom(IV_LENGTH)
    aesgcm = AESGCM(key)
    # encrypt() appends the 16-byte auth tag automatically
    ciphertext = aesgcm.encrypt(iv, plaintext.encode(), None)
    return base64.b64encode(iv + ciphertext).decode()

def decrypt(ciphertext_b64: str, key: bytes) -> str:
    data       = base64.b64decode(ciphertext_b64)
    iv         = data[:IV_LENGTH]
    ciphertext = data[IV_LENGTH:]
    aesgcm = AESGCM(key)
    return aesgcm.decrypt(iv, ciphertext, None).decode()

# Usage
key        = AESGCM.generate_key(bit_length=256)  # store this securely
ciphertext = encrypt('sensitive data here', key)
plaintext  = decrypt(ciphertext, key)

安装依赖项: pip install cryptography

您可以使用无需任何设置的交互式工具进行AES加密和解密测试—— IO Tools AES加密/解密工具.

密钥管理:最难的部分

您的加密强度取决于密钥管理。最常见的错误包括:

  • 密钥存储在与加密数据相同的数据库中 —— 如果攻击者获取了数据库导出,他们将同时获得两者。
  • 密钥提交到源代码控制 —— 即使在被忽略的git目录中 .env,旋转密钥变得困难且历史记录会保留。
  • 密钥出现在日志中 —— 应用程序日志会被发送到聚合平台。密钥绝不能出现在这些日志中。

加密密钥应存储在何处:

  • AWS KMS / Google Cloud KMS / Azure Key Vault —— 带有审计日志和自动轮换的托管密钥存储
  • HashiCorp Vault —— 自托管,适用于多云环境
  • 环境变量 —— 适用于低敏感度工作负载且暴露面有限的情况

对于数据库字段加密,环境加密是标准模式:为每条记录或每列生成一个数据加密密钥(DEK),然后使用存储在KMS中的主密钥对DEK进行加密。您的数据库中只包含加密后的DEK和密文——主密钥永远不会进入数据库。

何时使用AES——以及何时不使用

AES适用于以下场景:

  • 数据库字段加密 —— 社会安全号码(SSN)、卡号、健康记录
  • 静态文件加密 在云存储之前
  • 服务间共享密钥 这些服务共享预先建立的密钥

AES不适用于以下场景:

  • 在网络上传输数据 —— 使用TLS。不要自行构建传输层。
  • 需要非对称加密 —— 如果发送方和接收方无法预先共享密钥,则使用RSA或ECDH进行密钥交换。
  • 存储密码 —— 使用bcrypt、scrypt或Argon2。加密的密码可以被解密;而正确哈希的密码则无法被解密。
  • 使用托管解决方案 —— AWS Secrets Manager、Vault等工具可自动处理轮换、访问控制和审计日志。如果这些功能符合您的需求,优先选择这些托管方案而非手动AES。

大多数开发者犯下的错误是将AES视为完整的安全解决方案。它只是一个基础组件。搭配认证模式(如GCM)、每次操作使用唯一的IV以及正确的密钥管理,它将非常有效。如果缺少其中任何一项,您构建的系统看起来安全,实际上却并不安全。

想要享受无广告的体验吗? 立即无广告

安装我们的扩展

将 IO 工具添加到您最喜欢的浏览器,以便即时访问和更快地搜索

添加 Chrome 扩展程序 添加 边缘延伸 添加 Firefox 扩展 添加 Opera 扩展

记分板已到达!

记分板 是一种有趣的跟踪您游戏的方式,所有数据都存储在您的浏览器中。更多功能即将推出!

广告 移除?
广告 移除?
广告 移除?

新闻角 包含技术亮点

参与其中

帮助我们继续提供有价值的免费工具

给我买杯咖啡
广告 移除?