Node.jsencryption中的HMAC与Google Apps脚本(GAS)

你可以解释一下,使用Node.JS的Crypto模块创buildHmacSha512签名和Google Apps脚本有什么不同吗?

代码1 – Node.JS

var secret = "my secret"; var message = "message"; var crypto = require("crypto"); var hmac = new crypto.createHmac("sha512", secret); var signature = hmac.update(message).digest("base64"); console.log(signature); 

代码1 – Google Apps脚本

 var secret = "my secret"; var message = "message"; var signature = Utilities.base64Encode(Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_512, message, secret)); Logger.log(signature); 

两个代码都会生成相同的签名:

 g4fZkM2XGNjhti9Wah3TU2/rvmxbL3nk4F3ZLljpED23oQ7Y7dtVmVKprQKuzyt0B4Spo214isWCvnoXXVTS8g== 

但是当我们拥有base64编码密钥forms的秘密时,问题就来了。 所以,我们要做的第一步就是准备这个秘密。 我们来修改代码:

代码2 – Node.JS

 var key = "JOLDQW5wVIdwvHbhSDCktxhfwpgtxlAH+DG5EPoeDT8aPGSDYYh5U6QjbASUhvztjGPgA/Ue2x8QKwUklX7+Xw=="; var secret = new Buffer(key, "base64"); var message = "message"; var crypto = require("crypto"); var hmac = new crypto.createHmac("sha512", secret); var signature = hmac.update(message).digest("base64"); console.log(signature); 

结果:

 GELSKf33zit7nIfjj8XH3wZIga/CSYuCU5oTGysqOg6C/wFggunw59wzc7Mr95XW/gZ8putB67AADqnP0gLdiw== 

代码2 – Google Apps脚本

 var key = "JOLDQW5wVIdwvHbhSDCktxhfwpgtxlAH+DG5EPoeDT8aPGSDYYh5U6QjbASUhvztjGPgA/Ue2x8QKwUklX7+Xw=="; var message = "message"; var secret = Utilities.base64Decode(key); var signature = Utilities.base64Encode(Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_512, message, secret)); Logger.log(signature); 

结果:

 l11xAQ5C5ARx/r/pbNYpMKCqWOwIaxFTkfS9OXCwfUxv33y3gU/sL2vHueOxpkCKmF+lxIcFMYblwrvfWaTZkg== 

差别可能在于处理/解码密钥(Buffer vs. Utilities.base64Decode。)Node.js版本是正确的(它已经在服务器端进行了validation)。

如何使用Google Apps脚本正确解码和使用密钥?

Utilities.base64Decode()返回一个字节数组而不是一个string。 您可以从字节数组中创build一个blob,然后将其作为恢复原始编码string的string来获取。

 var secret = Utilities.base64Decode(key); secret = Utilities.newBlob(secret).getDataAsString(); 

试试这个例子。 我用一个新的base64编码的stringreplace了你的密钥,并将b64解码的输出转换为string:
在节点中:

 var key = "VEhJUyBJUyBBIFNUUklORw=="; //var key = "JOLDQW5wVIdwvHbhSDCktxhfwpgtxlAH+DG5EPoeDT8aPGSDYYh5U6QjbASUhvztjGPgA/Ue2x8QKwUklX7+Xw=="; var secret = new Buffer(key, "base64").toString(); var message = "message"; var crypto = require("crypto"); var hmac = new crypto.createHmac("sha512", secret); var signature = hmac.update(message).digest("base64"); console.log(signature); 

在GAS中:

 //var key = "JOLDQW5wVIdwvHbhSDCktxhfwpgtxlAH+DG5EPoeDT8aPGSDYYh5U6QjbASUhvztjGPgA/Ue2x8QKwUklX7+Xw=="; var key = "VEhJUyBJUyBBIFNUUklORw==" var message = "message"; var secret = Utilities.base64Decode(key); secret = Utilities.newBlob(secret).getDataAsString(); var hmac = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_512, message, secret); var signature = Utilities.base64Encode(hmac); Logger.log(signature); 

都返回签名:

 a9Jk2YQsKC164zEUoVChIpyfnEUZLj+Sj1mCAqs+jhDFvOliTupIfV+D6CNtaQGhQvAO40FZLhvYGubt1R5jQA== 

但是,如果我把你的钥匙放回签名再次停止匹配。

附属调查结果:

斯宾塞写道,当使用另一个密钥时,结果与两个代码都是相同的。 但还有一件奇怪的事情。 让我们使用斯宾塞的钥匙来确保两个代码都可以工作。 当我们想用非ASCII字符标记信息时,例如“Tomáš”,代码也会产生不同的结果!