Node Buffer 对象的 Google Apps Script 等价物是什么?

What is the Google Apps Script equivalent of a Node Buffer object?

Node.js Fiddle:

const crypto = require('crypto');

let secret = 'my_secret';
let message = 'my_message';

let signer = crypto.createHmac('sha512', secret)
const signature = signer.update(message).digest('base64');
console.log(signature); 
//signature = DWpafZMnI4PT5v0jdidFtU5qoh3fsvUKnaOga/Y2Nzy/tvsx1F9p61SjE+hlRQ97y/LMmBkG39IyL5Ja46bJlw==

// ***** Use Hex Buffer instead of string - same result
let message_buffer = Buffer.from(message); //<Buffer 6d 79 5f 6d 65 73 73 61 67 65>
let signer_from_buffer = crypto.createHmac('sha512', secret)
const signature_from_buffer = signer_from_buffer.update(message_buffer).digest('base64');
console.log(signature_from_buffer); 
// signature = DWpafZMnI4PT5v0jdidFtU5qoh3fsvUKnaOga/Y2Nzy/tvsx1F9p61SjE+hlRQ97y/LMmBkG39IyL5Ja46bJlw==

并且在 Google Apps 脚本中:

var secret =  'my_secret';
var message = 'my_message';

var signature_hash = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_512, message, secret);
var signature = Utilities.base64Encode(signature_hash);
Logger.log(signature);
//signature = DWpafZMnI4PT5v0jdidFtU5qoh3fsvUKnaOga/Y2Nzy/tvsx1F9p61SjE+hlRQ97y/LMmBkG39IyL5Ja46bJlw==

// Use Hex Array instead of string - different result
var message_buffer = ["6d", "79", "5f", "6d", "65", "73", "73", "61", "67", "65"];
var signature_hash_from_buffer = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_512, message_buffer , secret);
var signature_from_buffer = Utilities.base64Encode(signature_hash_from_buffer );
Logger.log(signature_from_buffer );
//signature_from_buffer = gGK0Y/KytE+8ZKWs/og1VQ1wMdPnoFmJMCHGpKdi+QODFwykqvDK5qJwgzZrr1b1g5050j9r8jpfXlM2ZA+3qQ==

所以我知道我的加密过程工作正常。问题是,我是从十六进制数组开始的,所以我希望能够得到相同的结果。我不知道节点缓冲区是什么类型的对象,以及如何将其转换为 Google Apps 脚本。

写在node documentation,

Buffer objects are used to represent a fixed-length sequence of bytes. Many Node.js APIs support Buffers.

The Buffer class is a subclass of JavaScript's Uint8Array class and extends it with methods that cover additional use cases. Node.js APIs accept plain Uint8Arrays wherever Buffers are supported as well.

没有直接支持Buffer

  • Apps 脚本支持 Byte Array from Blobs。所以可以模拟 Buffer.from

  • 在 Google Apps 脚本中,Utilities.newBlob(str).getBytes() returns Int8Array。为了将无符号十六进制数组转换为 Google Apps 脚本的字节数组,需要将其转换为 Int8Array.

  • Apps脚本也直接支持Uint8Array

const Buffer={from: str => Utilities.newBlob(str).getBytes()};
var message_buffer = Buffer.from(message);
var signature_hash_from_buffer = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_512, message_buffer , Buffer.from(secret));//modified as well

我相信你的目标如下。

  • 您想使用 Google Apps 脚本从 ["6d", "79", "5f", "6d", "65", "73", "73", "61", "67", "65"] 检索 DWpafZMnI4PT5v0jdidFtU5qoh3fsvUKnaOga/Y2Nzy/tvsx1F9p61SjE+hlRQ97y/LMmBkG39IyL5Ja46bJlw==

在 Google Apps 脚本中,getBytes() returns Int8Array 是 twos-complement 8 位有符号整数的数组。所以在这种情况下,首先需要从 ["6d", "79", "5f", "6d", "65", "73", "73", "61", "67", "65"] 转换为 Int8Array。而当Utilities.computeHmacSignature使用字节数组时,secret也需要转为字节数组。关于这一点,TheMaster的回答中已经提到了。

以上几点反映到Google Apps Script,变成如下。

示例脚本:

function myFunction() {
  var secret =  'my_secret';
  var message_buffer = ["6d", "79", "5f", "6d", "65", "73", "73", "61", "67", "65"];
  
  // Convert message_buffer (Unsigned hexadecimal array) to Int8Array.
  var message = message_buffer.map(e => parseInt(e[0], 16).toString(2).length == 4 ? parseInt(e, 16) - 256: parseInt(e, 16));
  
  var signature_hash = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_512, message, Utilities.newBlob(secret).getBytes());
  var signature = Utilities.base64Encode(signature_hash);
  Logger.log(signature);
  // DWpafZMnI4PT5v0jdidFtU5qoh3fsvUKnaOga/Y2Nzy/tvsx1F9p61SjE+hlRQ97y/LMmBkG39IyL5Ja46bJlw==
}

其他图案:

和其他模式一样,在这个模式中,message_buffer转换为Unit8Array,Unit8Array转换为Int8Array,然后Int8Array与Utilities.computeHmacSignature()一起使用。

function myFunction() {
  var secret =  'my_secret';
  var message_buffer = ["6d", "79", "5f", "6d", "65", "73", "73", "61", "67", "65"];
  
  // Convert message_buffer (Unsigned hexadecimal array) to Unit8Array.
  var unit8Array = message_buffer.map(e => parseInt(e, 16));
  
  // Convert Unit8Array to Int8Array.
  var int8Array = [...new Int8Array(Uint8Array.from(unit8Array).buffer)];

  var signature_hash = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_512, int8Array, Utilities.newBlob(secret).getBytes());
  var signature = Utilities.base64Encode(signature_hash);
  Logger.log(signature);
  // DWpafZMnI4PT5v0jdidFtU5qoh3fsvUKnaOga/Y2Nzy/tvsx1F9p61SjE+hlRQ97y/LMmBkG39IyL5Ja46bJlw==
}

参考文献: