【问题标题】:sha-256 encryption within Google Sheets using App Scripts使用应用脚本在 Google 表格中进行 sha-256 加密
【发布时间】:2020-12-14 22:48:27
【问题描述】:

我正在尝试将 3 个不同的元素加密为 API 的 http 标头的身份验证令牌。此 API 已内置于 Google 表格中,我目前无法使用其他任何东西。

身份验证令牌需要 4 个部分:

  1. API 密钥
  2. UTC 格式的时间戳
  3. API 操作
  4. API 密钥

API KEY:TIMESTAMP:API ACTION:API Secret Key 格式

出于本示例的目的,假设

  1. API 密钥为 test123,
  2. UTC 日期:2011 年 4 月 14 日星期四 22:44:22 GMT
  3. API 操作是“分类帐”
  4. API 密钥是 UAV213Q

当我在 python 中使用以下格式“test123:Thu, 14 Apr 2011 22:44:22 GMT:ledger:UAV213Q”测试示例时,我得到了结果 15594d1f608134cbfa3075ecda4664519cd198738b8f5c3ffa2c95272b854199 >

这是我使用的python脚本

def sha256():
    # tested on Python 3.8.5
    from urllib import parse, request
    import hashlib
    import datetime
    from time import strftime, gmtime

    # credentials and request params
    my_merchant_id = 'apikey'
    api_token = 'test123'
    api_secret_key = 'UAV213Q'
    my_timestamp = strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime())
    api_version = 2.9
    action_verb = 'ledger'

    # set up request params
    data = parse.urlencode({'merchantId': my_merchant_id, 'token': api_token,
                        'version': api_version, 'action': action_verb})

    # authentication
    sig = api_token + ':' + my_timestamp + ':' + action_verb + ':' + api_secret_key
    sig_hash = hashlib.sha256(sig.encode('utf-8')).hexdigest()
    my_headers = {'x-ShareASale-Date': my_timestamp,
                'x-ShareASale-Authentication': sig_hash}

    print(sig_hash)

我尝试使用以下其他 StackOverFlow 问题的解决方案 How do I get Google Apps Script to do SHA-256 encryption?sha3-256 of a cell text in Google Spreadsheet,所有的建议。

但是,我不断收到错误消息“此函数不允许使用 NOW()、RAND() 或 RANDBETWEEN() 引用单元格。”

我尝试通过在 A1 中设置 NOW() 并设置 B1 =A1 来引用间接引用 NOW() 的单元格,我什至尝试使用 TEXT() 将其转换为文本。

API 密钥需要具有时间戳才能正常工作。我正在考虑在 App 脚本本身中计算它,因为它是一个已知常数。例如,在加密脚本中,它将对 api 令牌进行硬编码,以 utc 格式调用时间戳,并以正确的格式对 api 密钥进行硬编码,并且可能只是添加操作的函数,以便我可以进行更改,因此它将是 sha256 (分类帐)并将其合并到加密中

【问题讨论】:

  • 您能否提供您期望的示例输入和输出值?不幸的是,根据您的问题,我无法理解它们。对此我深表歉意。
  • @Tanaike 编辑以包含展示示例输入的格式。我期望这样的输出 78D54A3051AE0AAAF022AA2DA230B97D5219D82183FEFF71E2D53DEC6057D9F1
  • 感谢您的回复。在您的情况下,您能否提供创建签名的规范?因为我无法理解从API key is test123API action is 'ledger'API Secret key is UAV213QIn the format of API KEY:TIMESTAMP:API ACTION:API Secret Key 的值中检索78D54A3051AE0AAAF022AA2DA230B97D5219D82183FEFF71E2D53DEC6057D9F1 输出的逻辑。而且,我认为为了检索您的预期结果,需要“TIMESTAMP”的样本值。也可以提供吗?
  • @Tanaike 谢谢,我还是新手。我已经使用示例格式和使用 python 获得的预期输出编辑了问题。在没有使用示例输入之前忽略我给你的那个
  • 感谢您的回复。您可以将python脚本添加到您的问题中吗?我想尝试了解从您的 python 脚本创建签名的规范。

标签: javascript google-apps-script encryption google-sheets sha256


【解决方案1】:

这个答案怎么样?

修改点:

  • 当我看到您的 python 脚本时,我确认您的问题中显示的规范与 python 脚本的规范不同。
    • 看来Thu, 14 Apr 2011 22:44:22 GMTThu, 14 Apr 2011 22:44:22 +0000
    • 似乎需要使用摘要的“SHA_256”。

示例脚本:

当您的 python 脚本转换为 Google Apps 脚本时,它变为如下。请将其复制并粘贴到脚本编辑器中,然后在脚本编辑器中运行函数myFunction。这样就可以在日志中看到结果值了。

function myFunction() {
  const api_token = 'test123';
  const api_secret_key = 'UAV213Q';
  const my_timestamp = 'Thu, 14 Apr 2011 22:44:22 +0000';
  const action_verb = 'ledger';

  const value = `${api_token}:${my_timestamp}:${action_verb}:${api_secret_key}`;
  const bytes = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, value);
  const res = bytes.map(byte => ('0' + (byte & 0xFF).toString(16)).slice(-2)).join('');
  console.log(res)
}

结果:

test123:Thu, 14 Apr 2011 22:44:22 +0000:ledger:UAV213Q 用于上述Google Apps 脚本和您的python 脚本时,两者结果相同,如下所示。

8c3a6873fe71c402dc1e3ca7bc828712e3dfb7a66ed09feeeca2152dd809df81

参考:

补充:

回答附加问题1:

当你想检索像Thu, 14 Apr 2011 22:44:22 +0000这样的日期字符串时,请使用以下脚本。

const my_timestamp = new Date().toUTCString().replace("GMT", "+0000");

回答附加问题 2:

当您想检索大写的值时,请使用以下脚本。但是当我测试你的python脚本时,结果值是小写的。所以请注意这一点。

function myFunction() {
  const api_token = 'test123';
  const api_secret_key = 'UAV213Q';
  const my_timestamp = 'Thu, 14 Apr 2011 22:44:22 +0000';
  const action_verb = 'ledger';

  const value = `${api_token}:${my_timestamp}:${action_verb}:${api_secret_key}`;
  const bytes = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, value);
  const res = bytes.map(byte => ('0' + (byte & 0xFF).toString(16)).slice(-2)).join('').toUpperCase();
  console.log(res)
}
  • 在这种情况下,得到8C3A6873FE71C402DC1E3CA7BC828712E3DFB7A66ED09FEEECA2152DD809DF81

参考资料:

【讨论】:

  • 我可以确认我得到了相同的答案,但是,我需要 my_timestamp 以动态方式在处理时以该格式获取时间。当我将其转换为实际值时。我必须将时间戳从 +0000 更改为 GMT 以获得与 api 展示的相同结果,但是脚本中的值都是小写的,而它们的值是大写的。这有什么不同吗?
  • @Jknight 感谢您的回复。关于您的另外两个问题,我更新了我的答案。你能确认一下吗?
  • @Jknight 顺便说一句,我可能无法理解I had to change the timestamp from +0000 to GMT for it to get the same result that the api showcases, but the values from your script is all lower case whereas theirs is uppercase. Does that make a difference?。如果我的理解不正确,我可以问你它的细节吗?而new Date().toUTCString() 返回的格式类似于Thu, 14 Apr 2011 22:44:22 GMT。这个怎么样?我只有你的 python 脚本的信息,没有关于你正在使用的 API 的信息。所以也请注意这一点。
  • 这很有效,谢谢。现在我必须让 API 的其余部分工作,但我认为加密是正确的。由于时间戳是加密的一部分,因此很难在同一台机器上同时运行 python 和应用程序脚本。但看起来不错。谢谢
  • 这是python的其余API代码,# execute request call = request.Request('https://shareasale.com/w.cfm?%s' % data, headers=my_headers) try: return_result = request.urlopen(call).read() # output results to console or write to file # f = open('out.txt', 'w') # print >> f, return_result # f.close() print(return_result) except Exception as inst: print(inst)
猜你喜欢
  • 2020-04-10
  • 2021-04-03
  • 1970-01-01
  • 2017-03-02
  • 1970-01-01
  • 1970-01-01
  • 2017-02-13
  • 2011-06-28
  • 2015-03-14
相关资源
最近更新 更多