Lin*_*yen 6 javascript python arrays hash node.js
我得到了以下 Javascript 代码,我需要将其转换为 Python(我不是哈希方面的专家,所以很抱歉我在这个主题上的知识)
function generateAuthHeader(dataToSign) {
let apiSecretHash = new Buffer("Rbju7azu87qCTvZRWbtGqg==", 'base64');
let apiSecret = apiSecretHash.toString('ascii');
var hash = CryptoJS.HmacSHA256(dataToSign, apiSecret);
return hash.toString(CryptoJS.enc.Base64);
}
Run Code Online (Sandbox Code Playgroud)
当我跑的时候generateAuthHeader("abc")它返回了+jgBeooUuFbhMirhh1KmQLQ8bV4EXjRorK3bR/oW37Q=
所以我尝试编写以下Python代码:
def generate_auth_header(data_to_sign):
api_secret_hash = bytearray(base64.b64decode("Rbju7azu87qCTvZRWbtGqg=="))
hash = hmac.new(api_secret_hash, data_to_sign.encode(), digestmod=hashlib.sha256).digest()
return base64.b64encode(hash).decode()
Run Code Online (Sandbox Code Playgroud)
但是当我运行时generate_auth_header("abc")它返回了不同的结果aOGo1XCa5LgT1CIR8C1a10UARvw2sqyzWWemCJBJ1ww=
有人能告诉我我的 Python 代码有什么问题以及我需要更改什么吗?
base64 是我为这篇文章自己生成的字符串
更新:这是我正在使用的文档
//Converting the Rbju7azu87qCTvZRWbtGqg== (key) into byte array
//Converting the data_to_sign into byte array
//Generate the hmac signature
Run Code Online (Sandbox Code Playgroud)
它看起来像apiSecretHash并且api_secret_hash是不同的,但我不太明白,因为new Buffer()NodeJS 中的等价物bytearray()在 python 中
我花了2天的时间查了一下,并询问了python discord中的人,我终于得到了答案。我来总结一下问题:
JavaScript
apiSecret = "E8nm,ns:\u0002NvQY;F*"
Run Code Online (Sandbox Code Playgroud)
Python
api_secret_hash = b'E\xb8\xee\xed\xac\xee\xf3\xba\x82N\xf6QY\xbbF\xaa'
Run Code Online (Sandbox Code Playgroud)
一旦我们用 python 代码替换了哈希值,它就会返回相同的结果
def generate_auth_header(data_to_sign):
api_secret_hash = "E8nm,ns:\u0002NvQY;F*".encode()
hash = hmac.new(api_secret_hash, data_to_sign.encode(), digestmod=hashlib.sha256).digest()
return base64.b64encode(hash).decode()
Run Code Online (Sandbox Code Playgroud)
Node.js 中的 ASCII 编码可以在这里找到https://github.com/nodejs/node/blob/a2a32d8beef4d6db3a8c520572e8a23e0e51a2f8/src/string_bytes.cc#L636-L647
case ASCII:
if (contains_non_ascii(buf, buflen)) {
char* out = node::UncheckedMalloc(buflen);
if (out == nullptr) {
*error = node::ERR_MEMORY_ALLOCATION_FAILED(isolate);
return MaybeLocal<Value>();
}
force_ascii(buf, out, buflen);
return ExternOneByteString::New(isolate, out, buflen, error);
} else {
return ExternOneByteString::NewFromCopy(isolate, buf, buflen, error);
}
Run Code Online (Sandbox Code Playgroud)
当数据包含非ASCII字符时,会调用这个force_ascii()函数,该函数在此处实现https://github.com/nodejs/node/blob/a2a32d8beef4d6db3a8c520572e8a23e0e51a2f8/src/string_bytes.cc#L531-L573
所以我们需要检查与 NodeJS 相同的哈希值,这样我们就得到了 Python 代码的最终版本:
def generate_auth_header(data_to_sign):
# convert to bytearray so the for loop below can modify the values
api_secret_hash = bytearray(base64.b64decode("Rbju7azu87qCTvZRWbtGqg=="))
# "force" characters to be in ASCII range
for i in range(len(api_secret_hash)):
api_secret_hash[i] &= 0x7f;
hash = hmac.new(api_secret_hash, data_to_sign.encode(), digestmod=hashlib.sha256).digest()
return base64.b64encode(hash).decode()
Run Code Online (Sandbox Code Playgroud)
现在它返回与 NodeJS 相同的结果
感谢来自 python discord 的 Mark 帮助我理解并解决这个问题!
希望将来尝试将字节数组从 javascript 转换为 python 的任何人都知道 NodeJS Buffer() 函数的不同之处