热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何在节点jsSDK中使用AWSKMS加密-HowtouseAWSKMSEncryptioninthenodejsSDK

IcannotfigureouthowtouploadfilesintoAWSS3usingKMSencryptionfromtheNodeJSSDK.Ikee

I cannot figure out how to upload files into AWS S3 using KMS encryption from the Node JS SDK. I keep getting a 403: Access Denied error. I am able to get files from AWS S3 using KMS.

我无法弄清楚如何使用Node JS SDK中的KMS加密将文件上传到AWS S3。我一直收到403:拒绝访问错误。我可以使用KMS从AWS S3获取文件。

I am reusing most of the code from https://github.com/gilt/node-s3-encryption-client

我正在重用https://github.com/gilt/node-s3-encryption-client中的大部分代码

Main Class
var fs = require('fs'),
    AWS = require('aws-sdk'),
    crypt = require("./crypt"),
    kms,
    s3;

const metadataCipherAlgorithm = 'cipher-algorithm',
      metadataDecryptedEncoding = 'decrypted-encoding'
      metadataKmsKeyName = 'x-amz-key';


/**
 * Constructor - Initializes S3 sdk connection
 */
function S3FileStreamer(key, secret, region) {
    if (region) {
        AWS.config.region = region;
    }
    //set credentials if passed in
    if (key && secret) {
        AWS.config.update({accessKeyId: key, secretAccessKey: secret})
    }
    s3 = new AWS.S3({signatureVersion: "v4"});
    kms = new AWS.KMS({apiVersion: '2014-11-01'});
}

S3FileStreamer.prototype.uploadFile = function(bucket, key, kmsKey, filename, onComplete) {
    var params = {
        Bucket: bucket,
        Key: key,
        Body: fs.readFileSync(filename),
        ContentType: getMimeType(filename)
    };

    params.KmsParams = {
        KeyId: kmsKey,
        KeySpec: 'AES_256'
    }

    kmsUpload(params, function(err, data) {
        if (err) onComplete(err, null);
        else {
            onComplete(err, data);
        }
    });
};

function kmsUpload(params, callback) {
  var kmsParams = params.KmsParams
  if (kmsParams && kmsParams.KeyId) {
    kms.generateDataKey(kmsParams, function(err, kmsData) {
      if (err) {
        callback(err, null);
      } else {
        var helper = new crypt.Helper(kmsData.Plaintext.toString('base64'), {algorithm: params.CipherAlgorithm, decryptedEncoding: params.DecryptedEncoding});
        params.Body = helper.encrypt(params.Body);
        params.Metadata = params.Metadata || {};
        params.Metadata[metadataKmsKeyName] = kmsData.CiphertextBlob.toString('base64');
        if (params.CipherAlgorithm) params.Metadata[metadataCipherAlgorithm] = params.CipherAlgorithm;
        if (params.DecryptedEncoding) params.Metadata[metadataDecryptedEncoding] = params.DecryptedEncoding;
        putObject(params, callback);
      }
    })
  } else {
    putObject(params, callback);
  }
}

function putObject(params, callback) {
  delete params.KmsParams;
  delete params.CipherAlgorithm;
  delete params.DecryptedEncoding;
  s3.putObject(params, callback);
}
Crypt class
var crypto = require('crypto');

/*
  options:
    algorithm: Anything from crypto.getCiphers()
    decryptedEncoding: 'utf8', 'ascii', or 'binary'
    outputEncoding: 'binary', 'base64', or 'hex'
 */
exports.Helper = function(password, options) {
  this.password = password;
  optiOns= options || {};
  this.algorithm = options.algorithm || 'aes-256-cbc';
  this.decryptedEncoding = options.decryptedEncoding || 'utf8';
  this.encryptedEncoding = options.encryptedEncoding || 'base64';
}

exports.Helper.prototype.encrypt = function(unencrypted) {
  var cipher = crypto.createCipher(this.algorithm, this.password);
  return cipher.update(unencrypted, this.decryptedEncoding, this.encryptedEncoding) + cipher.final(this.encryptedEncoding);
}

exports.Helper.prototype.decrypt = function(encrypted) {
  var decipher = crypto.createDecipher(this.algorithm, this.password);
  return decipher.update(encrypted, this.encryptedEncoding, this.decryptedEncoding) + decipher.final(this.decryptedEncoding);
}

Is there something I am missing here, an extra metadata tag that needs to be set?

我在这里缺少什么,需要设置额外的元数据标签吗?

Is the keyId parameter that is passed to the kms generateDataKey method supposed to be in some sort of unique format? I am just simply passing in my key.

传递给kms generateDataKey方法的keyId参数是否应该采用某种独特的格式?我只是简单地传递我的钥匙。

2 个解决方案

#1


1  

While the other answer about checking permissions is undoubtedly correct. I had a hard time finding a good example of how to decode S3 objects using the AES GCM encryption algorithm. I managed to get this code to work based on the aws ruby sdk (as I found the node-s3-encryption-client a little old).

而关于检查权限的另一个答案无疑是正确的。我很难找到一个如何使用AES GCM加密算法解码S3对象的好例子。我设法让这个代码基于aws ruby​​ sdk工作(因为我发现node-s3-encryption-client有点旧)。

/**
 * Decrypt s3 file data
 * @param  {object}   objectData result of s3 get call
 * @param  {Function} callback   function(err, data) returns error or decrypted data
 */
function decrypt(objectData, callback) {
    var metadata = objectData.Metadata || {};
    var kmsKeyBase64 = metadata['x-amz-key-v2'];
    var iv = metadata['x-amz-iv'];
    var tagLen = (metadata['x-amz-tag-len'] || 0)/8;
    var algo = metadata['x-amz-cek-alg'];
    var encryptiOnContext= JSON.parse(metadata['x-amz-matdesc']);

    switch (algo) {
        case 'AES/GCM/NoPadding':
            algo = 'aes-256-gcm';
            break;
        case 'AES/CBC/PKCS5Padding':
            algo = 'aes-256-cbc';
            break;
        default:
            callback(new Error('Unsupported algorithm: ' + algo), null);
            return;
    }

    if (typeof (kmsKeyBase64) === 'undefined') {
        callback(new Error('Missing key in metadata'), null);
        return;
    }

    var kmsKeyBuffer = new Buffer(kmsKeyBase64, 'base64');
    kms.decrypt({
        CiphertextBlob: kmsKeyBuffer,
        EncryptionContext: encryptionContext
    }, function(err, kmsData) {
        if (err) {
            callback(err, null);
        } else {
            var decipher = crypto.createDecipheriv(algo,
                                                   kmsData.Plaintext,
                                                   new Buffer(iv, 'base64'));

            if (tagLen !== 0) {
                // the tag is appended to the data buffer
                var tag = objectData.Body.slice(-tagLen);
                decipher.setAuthTag(tag);
            }
            var data = objectData.Body.slice(0,-tagLen);

            var dec = decipher.update(data, 'binary', 'utf8');
            dec += decipher.final('utf8');

            console.log("Decoded:", dec);
            callback(null, dec);
        }
    });
}

#2


0  

Thanks for all the help. I figured out the solution to my question.

谢谢你的帮助。我想出了我的问题的解决方案。

I went back to using just using the aws-sdk node module and took out all the code I got from the node-s3-encryption-client module.

我回去使用aws-sdk节点模块,并从node-s3-encryption-client模块中取出了所有代码。

All I needed to do in order to successfully upload a file into Amazon S3 using KMS encryption was to add two parameters before passing my params object to the putObject method. These parameters were ServerSideEncryption and SSEKMSKeyId as shown below. It now works!

为了使用KMS加密将文件成功上传到Amazon S3,我需要做的就是在将params对象传递给putObject方法之前添加两个参数。这些参数是ServerSideEncryption和SSEKMSKeyId,如下所示。它现在有效!

var params = {
    Bucket: bucket,
    Key: key,
    Body: fs.readFileSync(filename),
    ContentType: getMimeType(filename),
    ServerSideEncryption: 'aws:kms',
    SSEKMSKeyId: kmsKey
};

s3.putObject(params, function(err, data) {
    if (err) {
      console.log(err);
    } else {
      console.log(data);
});

推荐阅读
  • Webpack5内置处理图片资源的配置方法
    本文介绍了在Webpack5中处理图片资源的配置方法。在Webpack4中,我们需要使用file-loader和url-loader来处理图片资源,但是在Webpack5中,这两个Loader的功能已经被内置到Webpack中,我们只需要简单配置即可实现图片资源的处理。本文还介绍了一些常用的配置方法,如匹配不同类型的图片文件、设置输出路径等。通过本文的学习,读者可以快速掌握Webpack5处理图片资源的方法。 ... [详细]
  • 20211101CleverTap参与度和分析工具功能平台学习/实践
    1.应用场景主要用于学习CleverTap的使用,该平台主要用于客户保留与参与平台.为客户提供价值.这里接触到的原因,是目前公司用到该平台的服务~2.学习操作 ... [详细]
  • FeatureRequestIsyourfeaturerequestrelatedtoaproblem?Please ... [详细]
  • intellij idea的安装与使用(保姆级教程)
    intellijidea的安装与使用(保姆级教程)IntelliJ在业界被公认为最好的java开发工具,尤其在智能代码助手、代码自动提示、重构、JavaEE支持、各类版本工具(gi ... [详细]
  • 代理模式的详细介绍及应用场景
    代理模式是一种在软件开发中常用的设计模式,通过在客户端和目标对象之间增加一层中间层,让代理对象代替目标对象进行访问,从而简化系统的复杂性。代理模式可以根据不同的使用目的分为远程代理、虚拟代理、Copy-on-Write代理、保护代理、防火墙代理、智能引用代理和Cache代理等几种。本文将详细介绍代理模式的原理和应用场景。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • baresip android编译、运行教程1语音通话
    本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
  • 本文介绍了通过ABAP开发往外网发邮件的需求,并提供了配置和代码整理的资料。其中包括了配置SAP邮件服务器的步骤和ABAP写发送邮件代码的过程。通过RZ10配置参数和icm/server_port_1的设定,可以实现向Sap User和外部邮件发送邮件的功能。希望对需要的开发人员有帮助。摘要长度:184字。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • 图像因存在错误而无法显示 ... [详细]
  • 本文介绍了关系型数据库和NoSQL数据库的概念和特点,列举了主流的关系型数据库和NoSQL数据库,同时描述了它们在新闻、电商抢购信息和微博热点信息等场景中的应用。此外,还提供了MySQL配置文件的相关内容。 ... [详细]
  • 本文介绍了如何在Azure应用服务实例上获取.NetCore 3.0+的支持。作者分享了自己在将代码升级为使用.NET Core 3.0时遇到的问题,并提供了解决方法。文章还介绍了在部署过程中使用Kudu构建的方法,并指出了可能出现的错误。此外,还介绍了开发者应用服务计划和免费产品应用服务计划在不同地区的运行情况。最后,文章指出了当前的.NET SDK不支持目标为.NET Core 3.0的问题,并提供了解决方案。 ... [详细]
  • ShiftLeft:将静态防护与运行时防护结合的持续性安全防护解决方案
    ShiftLeft公司是一家致力于将应用的静态防护和运行时防护与应用开发自动化工作流相结合以提升软件开发生命周期中的安全性的公司。传统的安全防护方式存在误报率高、人工成本高、耗时长等问题,而ShiftLeft提供的持续性安全防护解决方案能够解决这些问题。通过将下一代静态代码分析与应用开发自动化工作流中涉及的安全工具相结合,ShiftLeft帮助企业实现DevSecOps的安全部分,提供高效、准确的安全能力。 ... [详细]
author-avatar
廖蓉以
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有