使用 aws-sdk-v3 中的 KMS 客户端解密认知代码

问题描述 投票:0回答:3

我按照此说明在 Cognito 中实现自定义消息发送器https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-custom-sms-sender.html

所有功能都适用于类似的代码(我在 AWS Lambda 上使用 Typescript):

import {buildClient, CommitmentPolicy, KmsKeyringNode} from '@aws-crypto/client-node';
import b64 from 'base64-js';

const {decrypt} = buildClient(CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT);
const keyring = new KmsKeyringNode({keyIds: ["my-key-arn"]});

...
const {plaintext} = await decrypt(keyring, b64.toByteArray(event.request.code));
console.log(plainttext.toString()) // prints plain text exactly as I need

但是,这个库

@aws-crypto/client-node
让我的包变得非常巨大,几乎有20MB!可能是因为它依赖于一些较旧的 AWS 库...

我曾经使用像

@aws-sdk/xxx
这样的模块化库,它确实提供了更小的包。

我发现对于加密/解密我可以使用

@aws-sdk/client-kms
。但这不起作用!

我正在尝试以下代码:

import {KMSClient, DecryptCommand} from "@aws-sdk/client-kms";
import b64 from 'base64-js';

const client = new KMSClient;
await client.send(new DecryptCommand({CiphertextBlob: b64.toByteArray(event.request.code), KeyId: 'my-key-arn'}))

这给了我一个错误:

InvalidCiphertextException: UnknownError
    at deserializeAws_json1_1InvalidCiphertextExceptionResponse (/projectdir/node_modules/@aws-sdk/client-kms/dist-cjs/protocols/Aws_json1_1.js:3157:23)
    at deserializeAws_json1_1DecryptCommandError (/projectdir/node_modules/@aws-sdk/client-kms/dist-cjs/protocols/Aws_json1_1.js:850:25)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async /projectdir/node_modules/@aws-sdk/middleware-serde/dist-cjs/deserializerMiddleware.js:7:24
    at async /projectdir/node_modules/@aws-sdk/middleware-signing/dist-cjs/middleware.js:14:20
    at async StandardRetryStrategy.retry (/projectdir/node_modules/@aws-sdk/middleware-retry/dist-cjs/StandardRetryStrategy.js:51:46)
    at async /projectdir/node_modules/@aws-sdk/middleware-logger/dist-cjs/loggerMiddleware.js:6:22
    at async REPL7:1:33 {
  '$fault': 'client',
  '$metadata': {
    httpStatusCode: 400,
    requestId: '<uuid>',
    extendedRequestId: undefined,
    cfId: undefined,
    attempts: 1,
    totalRetryDelay: 0
  },
  __type: 'InvalidCiphertextException'
}

我做错了什么?这个KMSClient支持我需要的吗?

我还尝试了 AWS CLI

aws kms decrypt --ciphertext-blob ...
命令,给了我完全相同的响应。不过,如果我加密和解密任何随机消息(例如“hello world”),它就会像魅力一样发挥作用。

我做错了什么,Cognito 代码密文有什么特别之处,所以我必须以另一种方式解密它?

amazon-cognito aws-sdk-js amazon-kms aws-sdk-js-v3
3个回答
4
投票

简短回答: Cognito 不使用 KMS 来加密文本,它使用加密 SDK。所以你不能使用KMS来解密Cognito密文。

更长的答案:过去一天我试图使用 boto3 和 KMS 客户端让 Python 电子邮件发送器触发函数与 Cognito 一起工作,直到我发现另一篇文章(在某个地方?)解释 Cognito 不使用 KMS 加密数据,而不是加密 SDK。当然这两种加密机制是不兼容的。

对于 JavaScript 和 Node.js 应用程序,您似乎可以选择包含整个加密客户端:https://www.npmjs.com/package/@aws-crypto/decrypt-node

如果你所做的只是解密,上面的包可以让你使用Encryption SDK进行解密,而且它只有159KB。


1
投票

我已经成功地解决了我的任务。我发现它确实不是简单地使用KMS来加密文本,加密/解密过程要复杂得多。

有参考页面https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/message-format.html

它描述了消息的外观,包括所有标头和正文、IV、AAD、密钥等...我已经编写了自己的脚本来解析所有内容并正确解密,它起作用了!可能太长了,无法分享...我建议改用参考资料。希望将来他们能够发布合适的模块化版本的 SDK。

“@aws-crypto”中的那个对我不起作用,可能无法正确支持所有协议。在您阅读本文时,这可能不是事实。


0
投票

因为显然这在互联网上的其他任何地方都不存在,并且 AWS 对于 python 也没有明确记录它,因此以下是实现此功能的代码:

# ...previous code...

import base64

import aws_encryption_sdk
from aws_encryption_sdk import CommitmentPolicy

# Get the code from the event
code: str = event["request"]["code"]

# Set up an encryption client with an explicit commitment policy. If you do not explicitly choose a
# commitment policy, REQUIRE_ENCRYPT_REQUIRE_DECRYPT is used by default.
client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT)

# Create an AWS KMS master key provider
kms_kwargs = dict(key_ids=[KMS_KEY_ARN])
kms_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(**kms_kwargs)

# Decrypt the encrypted message using the AWS Encryption SDK. It returns the decrypted message and the header.
plaintext_bytes, decrypted_message_header = client.decrypt(source=base64.b64decode(code), key_provider=kms_key_provider)

template_kwargs = {"verificationCode": plaintext_bytes.decode("utf-8")}

文档明确指出“Amazon Cognito 使用 AWS 加密 SDK 来加密授权用户 API 请求的秘密、临时密码和代码。”

他们还提供了一个 JS 示例(并且 aws-encryption-sdk python 库有一些不错的示例),但没有人提到的是,您需要在

base64.b64decode
代码上使用
Cognito
才能实现此目的工作。

否则,您会收到

aws_encryption_sdk.exceptions.NotSupportedError: Unsupported version
错误。

© www.soinside.com 2019 - 2024. All rights reserved.