首页 > 解决方案 > 无法分离 AWS KMS 客户端节点示例中的加密和解密逻辑

问题描述

我正在尝试使用 AWS KMS 团队为@aws-crypto 中的客户端节点加密提供的示例,以使用 AWS KMS 加密和解密节点 js 中的文件。**AWS KMS 团队示例 **

import {
  KmsKeyringNode,
  decryptStream,
  encryptStream,
  MessageHeader // eslint-disable-line no-unused-vars
} from '@aws-crypto/client-node'

import { finished } from 'stream'
import { createReadStream } from 'fs'
import { promisify } from 'util'
const finishedAsync = promisify(finished)

export async function kmsStreamTest (filename: string) {
  /* A KMS CMK is required to generate the data key.
   * You need kms:GenerateDataKey permission on the CMK in generatorKeyId.
   */
  const generatorKeyId = 'arn:aws:kms:us-west-2:658956600833:alias/EncryptDecrypt'

  /* The KMS keyring must be configured with the desired CMKs */
  const keyring = new KmsKeyringNode({ generatorKeyId })

  /* Encryption context is a *very* powerful tool for controlling and managing access.
   * It is ***not*** secret!
   * Encrypted data is opaque.
   * You can use an encryption context to assert things about the encrypted data.
   * Just because you can decrypt something does not mean it is what you expect.
   * For example, if you are are only expecting data from 'us-west-2',
   * the origin can identify a malicious actor.
   * See: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context
   */
  const context = {
    stage: 'demo',
    purpose: 'simple demonstration app',
    origin: 'us-west-2'
  }

  /* Create a simple pipeline to encrypt the package.json for this project. */
  const stream = createReadStream(filename)
    .pipe(encryptStream(keyring, { encryptionContext: context }))
    .pipe(decryptStream(new KmsKeyringNode({ discovery: true })))
    .on('MessageHeader', ({ encryptionContext }: MessageHeader) => {
      /* Verify the encryption context.
      * Depending on the Algorithm Suite, the `encryptionContext` _may_ contain additional values.
      * In Signing Algorithm Suites the public verification key is serialized into the `encryptionContext`.
      * Because the encryption context might contain additional key-value pairs,
      * do not add a test that requires that all key-value pairs match.
      * Instead, verify that the key-value pairs you expect match.
      */
      Object
        .entries(context)
        .forEach(([key, value]) => {
          console.log();''
          if (encryptionContext[key] !== value) throw new Error('Encryption Context does not match expected values')
        })
    })

  /* This is not strictly speaking part of the example.
   * Streams need a place to drain.
   * To test this code I just accumulate the stream.
   * Then I can return that Buffer and verify.
   * In a real world case you do not want to always buffer the whole stream.
   */
  const buff: Buffer[] = []
  stream.on('data', (chunk: Buffer) => {
    buff.push(chunk)
  })

  await finishedAsync(stream)
  return Buffer.concat(buff)
}

我坚持的是,如何分离加密和解密的逻辑。他们在这里使用管道,当我做了类似的事情时:

** 我的实现 **

const crypto = require('@aws-crypto/client-node');
const KmsKeyringNode = crypto.KmsKeyringNode;
const encryptStream = crypto.encryptStream;
const decryptStream = crypto.decryptStream;
const MessageHeader = crypto.MessageHeader;
const finished = require('stream');
const fs = require('fs');
const promisify = require('util');
const finishedAsync = promisify.promisify(finished)

kmsStreamTest = async (filename) => {
    try {


        const generatorKeyId = 'mykey'

        /* The KMS keyring must be configured with the desired CMKs */
        const keyring = new KmsKeyringNode({ generatorKeyId })
        const context = {
            stage: 'demo',
            purpose: 'simple demonstration app',
            origin: 'us-west-2'
        }

        /* Create a simple pipeline to encrypt the package.json for this project. */
        const encryptedStream = fs.createReadStream(filename)
            .pipe(encryptStream(keyring, { encryptionContext: context }))


        const buff = []
        encryptedStream.on('data', (chunk) => {
            console.log(chunk.toString());
            buff.push(chunk);
            fs.writeFileSync(`${global.appRoot}/fileHandler/encrypted.json`, buff, { flag: 'wx' });    
        })
        await finishedAsync(stream)
        return Buffer.concat(buff)
    }
    catch (err) {
        console.log("Errror----->>", Error);
    }
}


kmsDecryptionTest =async (filename) => {
    try {
        const generatorKeyId = 'arn:aws:kms:us-east-2:362495994317:alias/data-key-encryptor';

        /* The KMS keyring must be configured with the desired CMKs */
        const keyring = new KmsKeyringNode({ generatorKeyId })
        const context = {
            stage: 'demo',
            purpose: 'simple demonstration app',
            origin: 'us-west-2'
        }
        const decryptedStream = fs.createReadStream(filename)
            .pipe(decryptStream(new KmsKeyringNode({ discovery: true })))

        const decryptedBuffer = []
        decryptedStream.on('data', (chunk) => {
            console.log("Decryption Buffer ------->".toString());
            decryptedBuffer.push(chunk);
        })
        await finishedAsync(stream)
        return Buffer.concat(buff)
    }
    catch (err) {
        console.log("Error Data", err);
    }
}

module.exports = { kmsStreamTest, kmsDecryptionTest }

当我尝试调用 encrypt 函数时,会使用一些乱码文本(如预期的那样)创建文件。但是当我尝试读取该文件并调用它时,kmsDecryptionTest它会给我一个错误,即“格式错误的标题”。

有人可以帮我解决这个问题吗?为什么会这样?

PS:我的目标是加密和解密一个 .zip 文件,但现在我只是在 JSON 上尝试这个。

标签: node.jsamazon-web-servicesamazon-s3aws-kms

解决方案


推荐阅读