【问题标题】:How do I get Google Apps Script to do SHA-256 encryption?如何让 Google Apps 脚本进行 SHA-256 加密?
【发布时间】:2020-04-10 09:52:07
【问题描述】:

我需要使用 TEXT 输入、1 轮、HEX 输出、SHA-256 加密来加密字符串。应该是长度为 64 的字符串。
我在 Google Apps 脚本文档中尝试过的每个 SHA-256 加密模块都会返回一组数字。例如。

function SHA256() {
    var signature = Utilities.computeHmacSha256Signature("this is my input",
                                                 "my key - use a stronger one",
                                                 Utilities.Charset.US_ASCII);
Logger.log(signature);
    }

输出

[53, -75, -52, -25, -47, 86, -21, 14, -2, -57, 5, -13, 24, 105, -2, -84, 127, 115, -40, -75, -93, -27, -21, 34, -55, -117, -36, -103, -47, 116, -55, -61]

我没有在文档或其他地方看到任何指定我在上面为 GAS 概述的每个参数的内容。如果需要的话,我不介意从头开始对它进行更深入的解释。我正在加密信息以发送到 Facebook 以进行广告的离线转换。 Facebook 如何解密加密字符串?
Google Apps 脚本文档
https://developers.google.com/apps-script/reference/utilities/utilities#computeHmacSha256Signature(String,String,Charset)

【问题讨论】:

  • Edit 显示示例输入和输出
  • SHA-256、十六进制、1 轮、文本输入是否写在 Javascript 函数的某处,我可以将其复制并粘贴到我的脚本中?这个函数,例如geraintluff.github.io/sha256 ?我什至不确定这是如何工作的,接收者如何解密字符串 tbh。
  • 这就是它的输出。你期望它输出什么?给定输入的预期结果是什么?
  • "你希望它输出什么?"长度为 64 的字符串。

标签: javascript google-apps-script sha256 sha


【解决方案1】:

这里有一对函数可以将 SHA-256 哈希值生成为十六进制字符串:

function Sha256Hash(value) {
  return BytesToHex(
    Utilities.computeDigest(
      Utilities.DigestAlgorithm.SHA_256, value));
}

function BytesToHex(bytes) {
  let hex = [];
  for (let i = 0; i < bytes.length; i++) {
    let b = parseInt(bytes[i]);
    if (b < 0) {
      c = (256+b).toString(16);
    } else {
      c = b.toString(16);
    }
    if (c.length == 1) {
      hex.push("0" + c);
    } else {
      hex.push(c);
    }
  }
  return hex.join("");
}

事实证明bytes[] 类型可以用作普通的Array,所以我在编写BytesToHex() 时利用了这一点。

必须有更优雅的方法,但我更进一步,并设法获得了调用 AWS API 的正确签名:

// Google Apps Script version of https://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-javascript
function getSignatureKey(key, dateStamp, regionName, serviceName) {
  const kDate = Utilities.computeHmacSha256Signature(dateStamp, "AWS4" + key);
  Logger.log("kDate    = '" + BytesToHex(kDate) + "'");
  const kRegion = Utilities.computeHmacSha256Signature(Utilities.newBlob(regionName).getBytes(), kDate);
  Logger.log("kRegion  = '" + BytesToHex(kRegion) + "'");
  const kService = Utilities.computeHmacSha256Signature(Utilities.newBlob(serviceName).getBytes(), kRegion);
  Logger.log("kService = '" + BytesToHex(kService) + "'");
  const kSigning = Utilities.computeHmacSha256Signature(Utilities.newBlob("aws4_request").getBytes(), kService);
  Logger.log("kSigning = '" + BytesToHex(kSigning) + "'");
  return kSigning;
}

function Sha256Hmac(value, key) {
  return BytesToHex(Utilities.computeHmacSha256Signature(Utilities.newBlob(value).getBytes(), key));
}

【讨论】:

    【解决方案2】:

    ̶U̶t̶i̶l̶i̶t̶i̶e̶s̶.̶c̶o̶m̶p̶u̶t̶e̶H̶m̶a̶c̶S̶h̶a̶2̶5̶6̶S̶i̶g̶n̶a̶t̶u̶r̶e̶Utilities.computeDigest()返回一个字节数组(8 位整数)。如果您想将该数组转换为由十六进制字符组成的字符串,您必须手动执行以下操作:

    /** @type Byte[] */
    var signature = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, value);
    
    /** @type String */
    var hexString = signature
        .map(function(byte) {
            // Convert from 2's compliment
            var v = (byte < 0) ? 256 + byte : byte;
    
            // Convert byte to hexadecimal
            return ("0" + v.toString(16)).slice(-2);
        })
        .join("");
    

    【讨论】:

    • 谢谢。这是一个愚蠢的问题,但是我的接收者,我发送加密字符串的人,他们如何解密字符串?他们如何获得钥匙?
    • 如果toString(16) 返回单个数字而不是双精度,您还需要用0 预填充每个字节。此外,字节数组值是有符号的(+-)。它需要未签名
    • @Hugh 签名是一种单向哈希。你不能解密它
    • 这个答案并没有完全给出我从 jsSHA("SHA-256", "TEXT", 1) npm 模块中得到的信息。您的答案输出中有十几个破折号。
    • @TheMaster 我只是尝试按照此处的说明将数据发送到 Facebook。我不确定我错过了什么,但我确定他们不想要随机字符串而不是电子邮件地址。 developers.facebook.com/ads/blog/post/2018/05/29/…
    猜你喜欢
    • 2020-12-14
    • 2012-03-08
    • 2017-03-02
    • 2021-04-03
    • 1970-01-01
    • 2013-01-31
    • 1970-01-01
    相关资源
    最近更新 更多