【问题标题】:How to HMAC SHA256 sign a string with a double array key or an hex string key using google apps script?如何使用谷歌应用脚​​本使用双数组键或十六进制字符串键对字符串进行 HMAC SHA256 签名?
【发布时间】:2019-12-17 18:18:50
【问题描述】:

AWS example on Signature Version 4 之后,我正在尝试使用带有 Google 应用程序脚本的 Google 表格来重现该示例。我在示例中遇到了 kregion 签名的问题。虽然我可以使用 an online signature tool 确认 AWS 示例有效,但我永远无法使用任何 Google 应用程序脚本重现示例输出。由于 HMAC SHA256 签名适用于示例的前面部分(kdate),问题似乎来自数据的存储或使用方式。

another stackoverflow entry to convert byte array to hex stringGoogle apps script documentation for computeHmacSha256Signature 的帮助下,kDate 的工作如下:

var input="20120215";
var key="AWS4"+"wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY";//Do not worry, this is an example key, not my actual key
var signature=Utilities.computeHmacSha256Signature(input,key);
signature=signature.map(function(chr){return (chr+256).toString(16).slice(-2)}).join('');//convert byte array to hex string
Logger.log(signature);//valid 969fbb94feb542b71ede6f87fe4d5fa29c789342b0f407474670f0c2489e0a0d

kRegion 也是这样:

var input="us-east-1";
var key="969fbb94feb542b71ede6f87fe4d5fa29c789342b0f407474670f0c2489e0a0d";
var signature=Utilities.computeHmacSha256Signature(input,key);
signature=signature.map(function(chr){return (chr+256).toString(16).slice(-2)}).join('');
Logger.log(signature);//non-valid a59e30f9d899c47b3dd68ea1c0ab3bb529e03a8f4ed2f54cb64af547330a22a0

我并不惊讶它没有生成有效的示例 kRegion 输出 69daa0209cd9c5ff5c8ced464a696fd4252e981430b10e3d3fd8e2f197d7a70c,因为密钥存储为没有多大意义的十六进制字符串。这与尝试将十六进制字符串解码为受github entry启发的字节数组的尝试相同:

var input="us-east-1";
var key="969fbb94feb542b71ede6f87fe4d5fa29c789342b0f407474670f0c2489e0a0d";
var a=[];
for(var i=0, len=key.length; i<len; i+=2) {
  a.push(parseInt(key.substr(i,2),16));
}
key=a;
Logger.log(key);//[150.0, 159.0, 187.0, 148.0, 254.0, 181.0, 66.0, 183.0, 30.0, 222.0, 111.0, 135.0, 254.0, 77.0, 95.0, 162.0, 156.0, 120.0, 147.0, 66.0, 176.0, 244.0, 7.0, 71.0, 70.0, 112.0, 240.0, 194.0, 72.0, 158.0, 10.0, 13.0]
var signature=Utilities.computeHmacSha256Signature(input,key);
signature=signature.map(function(chr){return (chr+256).toString(16).slice(-2)}).join('');
Logger.log(signature);//non-valid ac7a5b21190d18b323886d48cd3c4c7486a0f1dd4edb80d245a221a95f5e689b

使用online converter,我可以确认密钥已正确转换。然而,输出签名仍然是错误的。 我想知道是否可能是因为密钥字节存储为双精度。因此,我尝试了以下操作,输出签名没有区别:

var input="us-east-1";
var key=[0x96, 0x9f, 0xbb, 0x94, 0xfe, 0xb5, 0x42, 0xb7, 0x1e, 0xde, 0x6f, 0x87, 0xfe, 0x4d, 0x5f, 0xa2, 0x9c, 0x78, 0x93, 0x42, 0xb0, 0xf4, 0x07, 0x47, 0x46, 0x70, 0xf0, 0xc2, 0x48, 0x9e, 0x0a, 0x0d];
var signature=Utilities.computeHmacSha256Signature(input,key);
signature=signature.map(function(chr){return (chr+256).toString(16).slice(-2)}).join('');
Logger.log(signature);//non-valid ac7a5b21190d18b323886d48cd3c4c7486a0f1dd4edb80d245a221a95f5e689b

然后我想也许computeHmacSha256Signature函数的两个参数都需要是字节数组:

var input=[0x75, 0x73, 0x2d, 0x65, 0x61, 0x73, 0x74, 0x2d, 0x31];
var key=[0x96, 0x9f, 0xbb, 0x94, 0xfe, 0xb5, 0x42, 0xb7, 0x1e, 0xde, 0x6f, 0x87, 0xfe, 0x4d, 0x5f, 0xa2, 0x9c, 0x78, 0x93, 0x42, 0xb0, 0xf4, 0x07, 0x47, 0x46, 0x70, 0xf0, 0xc2, 0x48, 0x9e, 0x0a, 0x0d];
var signature=Utilities.computeHmacSha256Signature(input,key);//leads to error "Cannot convert Array to (class)[]."
signature=signature.map(function(chr){return (chr+256).toString(16).slice(-2)}).join('');
Logger.log(signature);

以上导致错误“无法将数组转换为(类)[]。”。这似乎表明 computeHmacSha256Signature 函数更适合字符串输入。

通过使用 kDate 的输出签名而不将其转换为字符串,我得到了另一个无效的 kRegion 输出签名:

var input="20120215";
var key="AWS4"+"wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY";
var signature=Utilities.computeHmacSha256Signature(input,key);
input="us-east-1";
key=signature;
signature = Utilities.computeHmacSha256Signature(input,key);
signature=signature.map(function(chr){return (chr+256).toString(16).slice(-2)}).join('');
Logger.log(signature);//non-valid c3b37a4dc2e085fcd35411493526592a33ef1d7d38454a25e574a34fe190d7be

我尝试了许多其他转换,但均未成功。

【问题讨论】:

    标签: amazon-web-services google-apps-script digital-signature sha256 hmac


    【解决方案1】:
    • 您希望使用 Google Apps Script 实现 "Examples of How to Derive a Signing Key for Signature Version 4" 示例脚本的结果。

      • 在您的情况下,您希望从以下示例值中检索f4780e2d9f65fa895f9c67b32ce1baf0b0d8a43505a000a1a9e090d414db404d 的值kSigning

        key = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY'
        dateStamp = '20120215'
        regionName = 'us-east-1'
        serviceName = 'iam'
        

    如果我的理解是正确的,这个示例脚本怎么样?

    要点:

    • 在 Google Apps 脚本中,Utilities.computeHmacSha256Signature() 加密的数据是带符号的十六进制字节数组。在the sample scripts 中,字节数组被转换为无符号十六进制。所以需要转换。
      • 但是,当Utilities.computeHmacSha256Signature()创建字节数组时,创建的字节数组无需转换即可用于Utilities.computeHmacSha256Signature()

    根据上述情况,Google Apps Script 的示例脚本可以制作如下。

    示例脚本:

    在这个示例脚本中,为了检查脚本是否正确,我使用https://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html 的示例值测试了脚本。

    function myFunction() {
      // These are the sample values of https://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html
      var key = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY';
      var dateStamp = '20120215';
      var regionName = 'us-east-1';
      var serviceName = 'iam';
    
      // I prepared the following script.
      var kDate = Utilities.computeHmacSha256Signature(dateStamp, "AWS4" + key);
      var kRegion = Utilities.computeHmacSha256Signature(Utilities.newBlob(regionName).getBytes(), kDate);
      var kService = Utilities.computeHmacSha256Signature(Utilities.newBlob(serviceName).getBytes(), kRegion);
      var kSigning = Utilities.computeHmacSha256Signature(Utilities.newBlob("aws4_request").getBytes(), kService);
      kSigning = kSigning.map(function(e) {return ("0" + (e < 0 ? e + 256 : e).toString(16)).slice(-2)}).join("");
    
      Logger.log(kSigning) // Result
    }
    
    • 关于上面的脚本,例如kDate是字节数组。所以regionName需要转换为字节数组。请注意这一点。

    结果:

    f4780e2d9f65fa895f9c67b32ce1baf0b0d8a43505a000a1a9e090d414db404d
    

    此值与the sample value 相同。至此,发现编写好的脚本返回了正确的值。

    参考资料:

    如果我误解了您的问题并且这不是您想要的结果,我深表歉意。

    【讨论】:

    • 是的,您非常了解我的问题并解决了我的问题!我遇到的问题就是您提到的:如果键是字节数组,则输入也必须是字节数组。我虽然是这样,但我尝试应用它的尝试失败了,原因尚不清楚。无论如何,我现在有了你的解决方案。非常感谢@Tanaike 的大力帮助!
    • @luvzfootball 感谢您的回复和测试。我很高兴你的问题得到了解决。也谢谢你。
    • 你是我的英雄 :)
    猜你喜欢
    • 2012-02-15
    • 1970-01-01
    • 1970-01-01
    • 2017-08-14
    • 1970-01-01
    • 2018-07-27
    • 2018-03-05
    • 2022-11-03
    • 2019-07-27
    相关资源
    最近更新 更多