简体   繁体   中英

Decrypting cognito codes with KMS client from aws-sdk-v3

I am following this instruction to implement custom message sender in Cognito https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-custom-sms-sender.html

All works well with similar code (I use Typescript on AWS Lambda):

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

However, this library @aws-crypto/client-node makes my bundle really huge, almost 20MB. Probably because it depends on some of older AWS libs...

I used to use modular libraries like @aws-sdk/xxx which indeed give much smaller bundles.

I have found that for encrypt/decrypt I can use @aws-sdk/client-kms . But it doesn't work!

I am trying the following code:

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'}))

Which gives me an error:

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'
}

What am I doing wrong? Does this KMSClient support what I need?

I have also tried AWS CLI aws kms decrypt --ciphertext-blob... command, gives me exactly same response. Though if I encrypt and decrypt any random message like "hello world", it works like a charm.

What am I doing wrong and what is so special about Cognito code ciphertext so I have to decrypt it somehow another way?

Short answer: Cognito does not use KMS to encrypt the text, it uses the Encryption SDK. So you cannot use KMS to decrypt Cognito ciphertext.

Longer answer: I spent the past day trying to get a Python email-sender-trigger function working against Cognito using boto3 and the KMS client until I found another post (somewhere?) explaining that Cognito does not encrypt data using KMS, rather the Encryption SDK. Of course these two encryption mechanisms are not compatible.

For JavaScript and Node.js applications, it looks like you have an alternative to including the entire crypto-client: https://www.npmjs.com/package/@aws-crypto/decrypt-node

If all you are doing is decrypting, the above package will let you decrypt using the Encryption SDK and it's only 159KB.

I have managed to solve my task. I have realized that indeed it does not simply uses KMS to encrypt the text, the encryption/decryption process is much more complicated.

There is reference page https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/message-format.html

It describes how the message looks like, with all the headers and body, with IV, AAD, keys, etc... I have written my own script to parse it all and properly decrypt, it worked. Probably it's too long to share... I suggest to use the reference instead. Hopefully in future they will publish proper modular version of SDK.

The one from '@aws-crypto' didn't work for me, probably doesn't support all the protocols properly. This might be not the truth at the moment you are reading it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM