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áš”,代码也会产生不同的结果!