Reputation: 153
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==
and in Google Apps Script:
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==
So I know my Crypto process is working correctly. The problem is, I am starting from the Hex Array, so I want to be able to get the same result. I can't figure out what kind of Object the Node Buffer is, and how to translate that to Google Apps Script.
Upvotes: 1
Views: 730
Reputation: 50774
As written in 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.
There is no direct support of Buffer
Apps script supports Byte Array
from Blob
s. So it is possible to emulate Buffer.from
At Google Apps script, Utilities.newBlob(str).getBytes()
returns Int8Array
. In order to convert unsigned hexadecimal array to the byte array for Google Apps Script, it is required to convert it to Int8Array
.
Apps script also directly supports 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
Upvotes: 2
Reputation: 201623
I believe your goal as follows.
DWpafZMnI4PT5v0jdidFtU5qoh3fsvUKnaOga/Y2Nzy/tvsx1F9p61SjE+hlRQ97y/LMmBkG39IyL5Ja46bJlw==
from ["6d", "79", "5f", "6d", "65", "73", "73", "61", "67", "65"]
using Google Apps Script.At Google Apps Script, getBytes()
returns Int8Array which is an array of twos-complement 8-bit signed integers. So in this case, at first, it is requierd to convert from ["6d", "79", "5f", "6d", "65", "73", "73", "61", "67", "65"]
to Int8Array. And when the byte array is used for Utilities.computeHmacSignature
, secret
is required to be also converted to the byte array. About this, it has already been mentioned by TheMaster's answer. Ref
Above points are reflected to Google Apps Script, it becomes as follows.
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==
}
As other pattern, in this pattern, message_buffer
is converted to Unit8Array, and Unit8Array is converted to Int8Array, and then, the Int8Array is used with 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==
}
The Int8Array typed array represents an array of twos-complement 8-bit signed integers.
The Uint8Array typed array represents an array of 8-bit unsigned integers.
Upvotes: 3