Javascript &引用;在'处的值无效;密文';(键入“U字节”)“;

Javascript &引用;在'处的值无效;密文';(键入“U字节”)“;,javascript,node.js,encryption,google-cloud-platform,google-cloud-kms,Javascript,Node.js,Encryption,Google Cloud Platform,Google Cloud Kms,情况: gcs.bucket(bucketName) .file('mysecret.txt.encrypted.txt') .download({ destination: 'mysecret.txt.encrypted.txt' }) .then(() => { fs.readFile('mysecret.txt.encrypted.txt', (err, data) => { if (err) throw err; console.log

情况:

gcs.bucket(bucketName)
.file('mysecret.txt.encrypted.txt')
.download({ destination: 'mysecret.txt.encrypted.txt' })
.then(() => {
    fs.readFile('mysecret.txt.encrypted.txt', (err, data) => {
        if (err) throw err;
        console.log("DATA: "+data);
        var formData = {
           ciphertext: data, 
        };
        request.post({
            headers: {
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ...'
            },
            url: 'https://cloudkms.googleapis.com/v1/projects/kms-raimarketplace/locations/global/keyRings/.../cryptoKeys/...:decrypt',
            form: formData
        },
        function (err, httpResponse, body) {
            if (err) {
                console.log("ERROR: "+err);
            }
            else {
                console.log("BODY: "+body);
            }
            console.log(err, body);
        });
    });
}).catch(e => {
    console.error('getEnv.js: There was an error: ${JSON.stringify(e, undefined, 2)}');
});
BODY: {
  "error": {
    "code": 400,
    "message": "Invalid value at 'ciphertext' (TYPE_BYTES), ",
    "status": "INVALID_ARGUMENT",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.BadRequest",
        "fieldViolations": [
          {
            "field": "ciphertext",
            "description": "Invalid value at 'ciphertext' (TYPE_BYTES), "
          }
        ]
      }
    ]
  }
}
我正试图从我的谷歌云存储桶中下载并解密一些数据

对于加密和解密,我使用:

遗憾的是,我得到了一个错误:“在‘密文’(TYPE_BYTES)处的值无效”

我知道密码是正确的,我相信这可能是Google KMS API所期望的数据类型的问题,即:检索加密数据时,我的代码在将POST请求发送到Google KMS API之前以某种方式更改了它的类型

我做错了什么?我该如何修复它


代码:

gcs.bucket(bucketName)
.file('mysecret.txt.encrypted.txt')
.download({ destination: 'mysecret.txt.encrypted.txt' })
.then(() => {
    fs.readFile('mysecret.txt.encrypted.txt', (err, data) => {
        if (err) throw err;
        console.log("DATA: "+data);
        var formData = {
           ciphertext: data, 
        };
        request.post({
            headers: {
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ...'
            },
            url: 'https://cloudkms.googleapis.com/v1/projects/kms-raimarketplace/locations/global/keyRings/.../cryptoKeys/...:decrypt',
            form: formData
        },
        function (err, httpResponse, body) {
            if (err) {
                console.log("ERROR: "+err);
            }
            else {
                console.log("BODY: "+body);
            }
            console.log(err, body);
        });
    });
}).catch(e => {
    console.error('getEnv.js: There was an error: ${JSON.stringify(e, undefined, 2)}');
});
BODY: {
  "error": {
    "code": 400,
    "message": "Invalid value at 'ciphertext' (TYPE_BYTES), ",
    "status": "INVALID_ARGUMENT",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.BadRequest",
        "fieldViolations": [
          {
            "field": "ciphertext",
            "description": "Invalid value at 'ciphertext' (TYPE_BYTES), "
          }
        ]
      }
    ]
  }
}

输出:

gcs.bucket(bucketName)
.file('mysecret.txt.encrypted.txt')
.download({ destination: 'mysecret.txt.encrypted.txt' })
.then(() => {
    fs.readFile('mysecret.txt.encrypted.txt', (err, data) => {
        if (err) throw err;
        console.log("DATA: "+data);
        var formData = {
           ciphertext: data, 
        };
        request.post({
            headers: {
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ...'
            },
            url: 'https://cloudkms.googleapis.com/v1/projects/kms-raimarketplace/locations/global/keyRings/.../cryptoKeys/...:decrypt',
            form: formData
        },
        function (err, httpResponse, body) {
            if (err) {
                console.log("ERROR: "+err);
            }
            else {
                console.log("BODY: "+body);
            }
            console.log(err, body);
        });
    });
}).catch(e => {
    console.error('getEnv.js: There was an error: ${JSON.stringify(e, undefined, 2)}');
});
BODY: {
  "error": {
    "code": 400,
    "message": "Invalid value at 'ciphertext' (TYPE_BYTES), ",
    "status": "INVALID_ARGUMENT",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.BadRequest",
        "fieldViolations": [
          {
            "field": "ciphertext",
            "description": "Invalid value at 'ciphertext' (TYPE_BYTES), "
          }
        ]
      }
    ]
  }
}

我认为您可能没有传递base64编码的密文;这是解码失败时返回的错误(尽管在其他情况下也可能出现此消息)

我创建了一个世界通用的密钥,任何人都可以用它来解密,你应该可以用它来测试

这是我用来创建密文的代码。(您将无法运行此代码,因为我尚未打开密钥的加密权限。此代码直接从中导出,插入了我的密钥,并内联了base64编码)

当我运行这个程序时,我得到以下输出(我在GCP Cloud Shell中运行它,作为我的gmail帐户登录,我已经授予了对密钥的加密权限):

于是我运行了下面的命令;您将看到我从加密操作的输出复制并粘贴了密文。任何经过身份验证的人都可以运行此命令以使用我的密钥解密密文,因此现在可以自由运行它:

curl -s -X POST "https://cloudkms.googleapis.com/v1/projects/cloud-kms-demonstration/locations/global/keyRings/insecure-example-key-ring/cryptoKeys/insecure-example-key:decrypt" \
  -d "{\"ciphertext\":\"CiQAOay+bYR0HXjYHihHZmjPnu0ZEdOm4/HW4S6ZBifwWfFnL1QSNQBA6mRpHiq1MPQ7MerLyJ+gFJdeQooBFU0K0YmGlxRy5Ke/2eV16yR0viHPII6flFpzxnmD\"}" \
  -H "Authorization:Bearer $(gcloud auth application-default print-access-token)" \
  -H "Content-Type:application/json"
结果是:

{
  "plaintext": "aGVsbG8gd29ybGQK"
}
这是我的纯文本的base64编码:

$ echo "aGVsbG8gd29ybGQK" | base64 -d
hello world
如果我使用的是库,它可能会将base64编码作为传输需求的一部分进行处理。所以,希望您可以使用这个已知的好的密文和一个密钥来解密它,以调试您自己的代码。祝你好运


注意:如名称所示,请勿使用我提供的任何安全密钥(这就是为什么我没有打开密钥的加密权限)。

我不熟悉您使用的请求库。request.post的“form”选项似乎将主体格式化为application/x-www-form-urlencoded,而不是JSON。相反,请尝试使用“json”选项。post({json:formData})您是如何获得加密数据的?base64编码可能很棘手:我想知道您的密文是不是为传输而进行base64编码,还是双重编码。@RussAmos
BODY:[object object]null{error:{code:400,消息:'接收到无效的JSON负载。未知名称“type”在“密文”处:找不到字段。\n收到无效的JSON有效负载。在“密文”处的未知名称“数据”:找不到字段。状态:“无效参数”,详细信息:[[Object]]}
如果你像我大约4小时前那样在谷歌上搜索此内容……并且像我一样,习惯性地在文本文件中添加新行(包括
mysecret.txt.encrypted.txt
…),您可能遇到了与我相同的问题,即
数据
包含一个自诱导的尾随换行符,它实际上不是有效的Base64。假设
mysecret.txt.encrypted.txt
的其余内容已经是Base64编码的,请尝试传递
密文:data.toString().trim()
。这不是怎么回事,你不能用钥匙从他们那里获得任何人的凭据,就像我可以从你看谷歌文档时窃取你的谷歌密码一样。(另外,FWIW,我是负责谷歌云KMS的工程总监;我只是想帮你。)…这是否构成安全漏洞。非常感谢您的帮助。顺便说一句,我得到了我想要的请求!我只是想知道对另一个项目的请求(授权头中有$(gcloud auth application default print access token))是否会暴露令牌(我想是这样的)向所述其他项目的所有者和所述用户发送,然后用户可以使用auth令牌获得对资源的不必要访问。这取决于您所说的“我”的意思。我发布的URL不是我的个人URL:它是Google Cloud API端点。你在与Google交谈,而你使用的是我控制的密钥,这一事实使我无法访问你的身份或凭据。现在,我碰巧在Google工作,当然,Google可以访问你在访问GCP时使用的身份。但我,作为一名员工,甚至作为一名运行该服务的高级员工,无法访问该信息。也就是说,这是一个合理的担忧:如果我插入了一个我控制的坏主机名,您将向我发送一个令牌,让我可以像您一样使用谷歌API。感谢您的关注!(但在这种情况下,*.googleapis.com可以安全使用。)太好了!谢谢:)