You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复AWS KMS解密时unencryptedDataKey has not been set报错

问题现象

基于AWS官方教程使用AWS KMS服务,通过AWS Management Console中已配置完成的Master Key实现数据加密,加密流程可正常运行,但解密生成的密文时抛出错误:unencryptedDataKey has not been set。

复现代码

密钥环初始化逻辑

const generatorKeyId = 'arn:aws:kms:eu-central-1:51426*****:alias/my-key';
const keyIds = [];

const keyring = new KmsKeyringNode({ generatorKeyId, keyIds });

console.log(keyring);

运行后打印的KmsKeyringNode实例内容如下:

KmsKeyringNode {
  clientProvider: [Function (anonymous)],
  keyIds: [],
  generatorKeyId: 'arn:aws:kms:eu-central-1:51426*****:alias/my-key',
  grantTokens: undefined,
  isDiscovery: false,
  discoveryFilter: undefined
}

加密逻辑

const context = {
  stage: 'demo',
  purpose: 'simple demonstration app',
  origin: 'eu-central-1',
};

/* 待加密明文字符串 */
const cleartext = 'my-cypher-teststring';

const { encrypt, decrypt } = buildClient(CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT);

const { result } = await encrypt(keyring, cleartext, { encryptionContext: context });
console.log("RESULT", result)

加密流程运行后控制台输出:

RESULT <Buffer 02 05 78 02 4b 48 c9 96 75 f8 08 5e 33 d0 91 18 67 51
31 4c 7a 9d a9 ac bd df e

解密逻辑

const { plaintext, messageHeader } = await decrypt(keyring, result);
console.log("Plaintext", plaintext)
console.log("MessageHeader", messageHeader)

执行解密时抛出异常栈如下:

Error  AM [ExceptionsHandler] unencryptedDataKey has not been set - {
    stack: [
      'Error: unencryptedDataKey has not been set\n' +
        '    at needs (/Users/xxxxx/xxxx/node_modules/@aws-crypto/material-management/src/needs.ts:21:11)\n' +
        '    at NodeDecryptionMaterial.getUnencryptedDataKey (/Users/xxxx/xxxx/node_modules/@aws-crypto/material-management/src/cryptographic_material.ts:417:10)\n' +
        '    at NodeDefaultCryptographicMaterialsManager.decryptMaterials (/Users/xxxxxx/yyyyyy/node_modules/@aws-crypto/material-management-node/src/node_cryptographic_materials_manager.ts:109:20)\n' +
        '    at processTicksAndRejections (node:internal/process/task_queues:96:5)'
    ]
  }
根因分析

该错误本质是解密流程中,密钥环没能从KMS服务拿到解密后的明文数据密钥,常见触发原因有三个:

  • 初始化KmsKeyringNode时未显式指定KMS客户端,默认凭证链加载的身份/默认区域配置和密钥所在区域不匹配,或者身份没有对应KMS密钥的解密权限,导致调用KMS解密数据密钥失败。
  • 传入解密方法的密文存在截断、损坏:比如直接将二进制Buffer转UTF-8字符串导致二进制数据丢失,或者存储/传输过程中密文被截断,无法解析出加密后的数据密钥字段。
  • 加密时配置的encryptionContext与解密时传入的上下文不匹配,KMS会拒绝解密数据密钥请求,最终拿不到明文数据密钥。
修复方案

按以下步骤逐一排查修复:

  1. 显式初始化和密钥同区域的KMS客户端,传入密钥环构造函数,避免默认配置匹配错误:
    const { KMSClient } = require("@aws-sdk/client-kms");
    // 配置和KMS密钥一致的区域
    const kmsClient = new KMSClient({
      region: "eu-central-1",
      // 本地调试可临时配置凭证,生产环境请使用云资源绑定的IAM角色,不要硬编码密钥
      // credentials: {
      //   accessKeyId: "你的访问密钥ID",
      //   secretAccessKey: "你的访问密钥"
      // }
    });
    
    const generatorKeyId = 'arn:aws:kms:eu-central-1:51426*****:alias/my-key';
    const keyring = new KmsKeyringNode({ 
      generatorKeyId, 
      keyIds: [],
      clientProvider: () => kmsClient
    });
    
  2. 校验运行环境绑定的IAM身份权限:无论是本地调试的用户身份,还是云上EC2/Lambda/ECS绑定的IAM角色,都需要具备目标KMS密钥的以下权限,同时KMS密钥自身的资源策略要允许该身份执行对应操作:
    • kms:Encrypt
    • kms:Decrypt
    • kms:GenerateDataKey
  3. 校验密文完整性:如果密文需要存储或跨服务传输,不要直接将Buffer转成UTF-8字符串,要转成Base64编码,解密前再解码回Buffer,避免二进制数据损坏:
    // 加密后转Base64存储/传输
    const encryptedBase64 = result.toString("base64");
    // 解密前先转回原始Buffer
    const ciphertext = Buffer.from(encryptedBase64, "base64");
    const { plaintext } = await decrypt(keyring, ciphertext);
    
  4. 如果解密时显式传入encryptionContext参数,必须保证和加密时传入的键值对完全一致,键名、值、大小写都不能有差异。

内容的提问来源于stack exchange,提问作者MrsBookik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 07:15:33