0

我正在尝试使用 aws-sdk 和 NodeJs 解密一些使用 AWS KMS 加密的文本。我今天开始玩 NodeJs,所以我是一个新手。我已经用 Java 解决了这个问题,但我正在尝试将现有的 Alexa 技能从 Java 迁移到 NodeJs。

解密的代码是:

function decrypt(buffer) {
    const kms = new aws.KMS({
        accessKeyId: 'accessKeyId',
        secretAccessKey: 'secretAccessKey',
        region: 'eu-west-1'
    });
    return new Promise((resolve, reject) => {
        let params = {
            "CiphertextBlob" : buffer,
        };
        kms.decrypt(params, (err, data) => {
            if (err) {
                reject(err);
            } else {
                resolve(data.Plaintext);
            }
        });
    });
};

当我使用正确的 CiphertextBlob 运行此代码时,我收到此错误:

Promise {
  <rejected> { MissingRequiredParameter: Missing required key 'CiphertextBlob' in params
    at ParamValidator.fail (D:\Developing\abono-transportes-js\node_modules\aws-sdk\lib\param_validator.js:50:37)
    at ParamValidator.validateStructure (D:\Developing\abono-transportes-js\node_modules\aws-sdk\lib\param_validator.js:61:14)
    at ParamValidator.validateMember (D:\Developing\abono-transportes-js\node_modules\aws-sdk\lib\param_validator.js:88:21)
    at ParamValidator.validate (D:\Developing\abono-transportes-js\node_modules\aws-sdk\lib\param_validator.js:34:10)
    at Request.VALIDATE_PARAMETERS (D:\Developing\abono-transportes-js\node_modules\aws-sdk\lib\event_listeners.js:126:42)
    at Request.callListeners (D:\Developing\abono-transportes-js\node_modules\aws-sdk\lib\sequential_executor.js:106:20)
    at callNextListener (D:\Developing\abono-transportes-js\node_modules\aws-sdk\lib\sequential_executor.js:96:12)
    at D:\Developing\abono-transportes-js\node_modules\aws-sdk\lib\event_listeners.js:86:9
    at finish (D:\Developing\abono-transportes-js\node_modules\aws-sdk\lib\config.js:349:7)
    at D:\Developing\abono-transportes-js\node_modules\aws-sdk\lib\config.js:367:9
  message: 'Missing required key \'CiphertextBlob\' in params',
  code: 'MissingRequiredParameter',
  time: 2019-06-30T20:29:18.890Z } }

我不明白为什么我会收到 ifCiphertextBlob在 params 变量中。

有谁知道?提前致谢!

编辑 01/07

测试编码功能:第一个功能:

const CheckExpirationDateHandler = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'IntentRequest'
            && handlerInput.requestEnvelope.request.intent.name === 'TtpConsultaIntent';
    },
    handle(handlerInput) {

        var fecha = "";
        var speech = "";

        userData = handlerInput.attributesManager.getSessionAttributes();

        if (Object.keys(userData).length === 0) {
            speech = consts.No_Card_Registered;
        } else {
            console.log("Retrieving expiration date from 3rd API");
            fecha = crtm.expirationDate(cipher.decrypt(userData.code.toString()));
            speech = "Tu abono caducará el " + fecha;
        }

        return handlerInput.responseBuilder
            .speak(speech)
            .shouldEndSession(true)
            .getResponse();

    }
}

随日志提供的解密功能:

// source is plaintext
async function decrypt(source) {

    console.log("Decrypt func INPUT: " + source)
    const params = {
        CiphertextBlob: Buffer.from(source, 'base64'),
    };
    const { Plaintext } = await kms.decrypt(params).promise();
    return Plaintext.toString();
};

输出:

2019-07-01T19:01:12.814Z 38b45272-809d-4c84-b155-928bee61a4f8 INFO 从第 3 个 API 检索到期日期 2019-07-01T19:01:12.814Z 38b45272-809d-4c84-b155-928BEENPUT1:4ffunc6 AYADeHK9xoVE19u/3vBTiug3LuYAewACABVhd3MtY3J5cHRvLXB1YmxpYy1rZXkAREF4UW0rcW5PSElnY1ZnZ2l1bHQ2bzc3ZnFLZWZMM2J6YWJEdnFCNVNGNzEyZGVQZ1dXTDB3RkxsdDJ2dFlRaEY4UT09AA10dHBDYXJkTnVtYmVyAAt0aXRsZU51bWJlcgABAAdhd3Mta21zAEthcm46YXdzOmttczpldS13ZXN0LTE6MjQwMTE3MzU1MTg4OmtleS81YTRkNmFmZS03MzkxLTRkMDQtYmUwYi0zZDJlMWRhZTRkMmIAuAECAQB4sE8Iv75TZ0A9b/ila9Yi/3vTSja3wM7mN/B0ThqiHZEBxYsoWpX7jCqHMoeoYOkVtAAAAH4wfAYJKoZIhvcNAQcGoG8wbQIBADBoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDNnGIwghz+b42E07KAIBEIA76sV3Gmp5ib99S9H4MnY0d1l............ 2019-07-01T19:01:12.925Z 38b45272-809d-4c84-b155-928bee61a4f8 INFO Error handled: handlerInput.responseBuilder.说话(...).shouldEndSession 不是函数 2019-07-01T19:01:13.018Z 38b45272-809d-4c84-b155-928bee61a4f8 错误未处理的承诺拒绝 {"errorType":"Runtime.UnhandledPromiseRejection","errorMessage":"InvalidCiphertextException: null" ,"堆栈":["Runtime.UnhandledPromiseRejection: InvalidCiphertextException: null","...

4

3 回答 3

9

这要么意味着您缺少密钥“CiphertextBlob”,要么它的值未定义。

请检查您作为buffer.

作为参考,我还添加了我使用的工作代码示例。

import { KMS } from 'aws-sdk';

import config from '../config';

const kms = new KMS({
  accessKeyId: config.aws.accessKeyId,
  secretAccessKey: config.aws.secretAccessKey,
  region: config.aws.region,
});

// source is plaintext
async function encrypt(source) {
  const params = {
    KeyId: config.aws.kmsKeyId,
    Plaintext: source,
  };
  const { CiphertextBlob } = await kms.encrypt(params).promise();

  // store encrypted data as base64 encoded string
  return CiphertextBlob.toString('base64');
}

// source is plaintext
async function decrypt(source) {
  const params = {
    CiphertextBlob: Buffer.from(source, 'base64'),
  };
  const { Plaintext } = await kms.decrypt(params).promise();
  return Plaintext.toString();
}

export default {
  encrypt,
  decrypt,
};

- - - 添加 - - -

我能够重现您的问题。

decrypt("this text has never been encrypted before!");

此代码引发相同的错误。

因此,如果您传递以前从未加密过或已使用不同密钥加密的纯文本,则会抛出InvalidCiphertextException: null.

现在我给你一个使用例子。

encrypt("hello world!") // this will return base64 encoded string
  .then(decrypt) // this one accepts encrypted string
  .then(decoded => console.log(decoded)); // hello world!
于 2019-06-30T23:50:56.673 回答
3

在尝试接受的解决方案时,我在AWS lambda中不断收到此错误,在我使用AWS用户界面加密的环境变量上使用AWS KMS 。

它使用改编自AWS 官方解决方案的这段代码对我有用:

解密.js

const AWS = require('aws-sdk');
AWS.config.update({ region: 'us-east-1' });

module.exports = async (env) => {
    const functionName = process.env.AWS_LAMBDA_FUNCTION_NAME;
    const encrypted = process.env[env];
    
    if (!process.env[env]) {
        throw Error(`Environment variable ${env} not found`) 
    }
    
    const kms = new AWS.KMS();
    try {
        const data = await kms.decrypt({
            CiphertextBlob: Buffer.from(process.env[env], 'base64'),
            EncryptionContext: { LambdaFunctionName: functionName },
        }).promise();
        console.info(`Environment variable ${env} decrypted`)
        return data.Plaintext.toString('ascii');
    } catch (err) {
        console.log('Decryption error:', err);
        throw err;
    }
}

像这样使用:

index.js

const decrypt = require("./decrypt.js")

exports.handler = async (event, context, callback) => {
    console.log(await decrypt("MY_CRYPTED_ENVIRONMENT_VARIABLE"))
}
于 2020-09-11T22:54:23.347 回答
1
  1. EncryptionContext 是必须的。
  2. 假设 EnvironmentVariable 的名称是Secret
  3. 下面的代码读取名为Secret的 EnvironmentVariable ,并在正文中以纯文本形式返回解密后的密钥。
  4. 请看下面贴出的功能代码

'使用严格';

const aws = require('aws-sdk');
var kms = new aws.KMS();

exports.handler = (event, context, callback) => {
    const functionName = process.env.AWS_LAMBDA_FUNCTION_NAME;
    const encryptedSecret = process.env.Secret;

    kms.decrypt({
            CiphertextBlob: new Buffer(encryptedSecret, 'base64'),
            EncryptionContext: {
                LambdaFunctionName: functionName /*Providing the name of the function as the Encryption Context is a must*/
            },
        },
        (err, data) => {

            if (err) {
                /*Handle the error please*/
            }

            var decryptedSecret = data.Plaintext.toString('ascii');

            callback(null, {
                statusCode: 200,
                body: decryptedSecret,
                headers: {
                    'Content-Type': 'application/json',
                },
            });
        });
};
于 2021-02-23T11:14:40.087 回答