从GCS下载加密数据后调用Google KMS API解密遇TYPE_BYTES错误求助
Google KMS Decrypt Error: "Invalid value at 'ciphertext' (TYPE_BYTES)"
我尝试从Google Cloud存储桶下载并解密数据,参考Google KMS的解密方案,但触发了"Invalid value at 'ciphertext' (TYPE_BYTES)"错误。我确认密文内容正确,推测问题出在向Google KMS API发送POST请求前数据类型被意外修改。
我的代码如下:
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)}'); });
返回的错误输出为:
{ "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), " } ] } ] } }
请问我哪里操作有误,该如何修复?
问题根源分析
你遇到的问题主要有两个核心原因:
- 数据编码不符合要求:Google KMS的
decryptAPI明确要求ciphertext必须是Base64编码的字符串,但你直接将fs.readFile返回的原始Buffer对象传了进去,而且通过form字段发送请求时,Buffer会被自动转换成乱码的字符串或原始字节流,完全不符合API的格式要求。 - 请求格式冲突:你设置了
Content-Type: application/json头部,但却用form字段发送表单数据——这两者是完全冲突的,JSON格式的请求需要把数据序列化为JSON字符串,而不是表单格式。
修复方案
修改代码时需要做以下两处关键调整:
1. 将密文Buffer转换为Base64字符串
调用data.toString('base64')把fs.readFile返回的Buffer转换成Base64编码,这是KMS API接受的唯一格式。
2. 正确发送JSON格式请求
把请求数据序列化为JSON字符串,用body字段传递,而不是form字段,同时保持Content-Type: application/json头部不变。
修改后的完整代码如下:
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 (Base64): "+data.toString('base64')); // 转换为Base64编码 const requestBody = { ciphertext: data.toString('base64') }; request.post({ headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ...' }, url: 'https://cloudkms.googleapis.com/v1/projects/kms-raimarketplace/locations/global/keyRings/.../cryptoKeys/...:decrypt', // 用body传递JSON序列化后的字符串 body: JSON.stringify(requestBody) }, 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)}`); });
额外优化建议
- 用
async/await替代嵌套回调,让代码更简洁易读:
async function decryptSecret() { try { await gcs.bucket(bucketName).file('mysecret.txt.encrypted.txt').download({ destination: 'mysecret.txt.encrypted.txt' }); const data = await fs.promises.readFile('mysecret.txt.encrypted.txt'); const requestBody = { ciphertext: data.toString('base64') }; const response = await request.post({ headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ...' }, url: 'https://cloudkms.googleapis.com/v1/projects/kms-raimarketplace/locations/global/keyRings/.../cryptoKeys/...:decrypt', body: JSON.stringify(requestBody) }); console.log("BODY: ", response.body); } catch (e) { console.error(`getEnv.js: There was an error: ${JSON.stringify(e, undefined, 2)}`); } } decryptSecret();
- 优先使用官方的Google Cloud KMS客户端库(
@google-cloud/kms),它会自动处理编码、请求格式和身份验证,避免手动调用API的各种坑:
const { KeyManagementServiceClient } = require('@google-cloud/kms'); const client = new KeyManagementServiceClient(); async function decrypt() { const name = client.cryptoKeyPath('kms-raimarketplace', 'global', 'YOUR_KEY_RING_NAME', 'YOUR_CRYPTO_KEY_NAME'); const data = await fs.promises.readFile('mysecret.txt.encrypted.txt'); const [result] = await client.decrypt({ name, ciphertext: data, }); console.log('Plaintext: ', result.plaintext.toString()); } decrypt();
内容的提问来源于stack exchange,提问作者TheProgrammer
相关产品推荐
相关产品推荐

