我的问题与Translation from Python to JavaScript: HMAC-SHA256非常相似,但问题从未得到解答。
以下Python代码生成正确的哈希:
def sign_api_request(api_secret, api_key, method, url):
encoded_url = urllib.parse.quote(url.lower(), '').lower()
timestamp = int(time.time())print("timestamp: " + str(timestamp))
nonce = str(uuid.uuid4())
signature = api_key + method + encoded_url + str(timestamp) + nonce
secret_bytes = base64.b64decode(api_secret)
signature_bytes = signature.encode('UTF8')
signature_hash = hmac.new(secret_bytes, signature_bytes, hashlib.sha256).digest()
base64_signature_hash = base64.b64encode(signature_hash).decode()
print(base64_signature_hash)
我正在尝试使用Javascript(作为Postman预请求脚本)生成相同的哈希字符串。这就是我所拥有的:
function epochTime() {
var d = new Date();
var t = d.getTime();
var o = t + "";
return o.substring(0, 10);
}
function newGuid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { var r = Math.random() * 16 | 0, v = c == 'x' ? r : r & 0x3 | 0x8; return v.toString(16); });
}
var uri_path = encodeURIComponent(request.url.toLowerCase()).toLowerCase();
var payload = uri_path; //.toLowerCase();
timestamp = epochTime();
nonce = newGuid();
signature = environment.api_key + "GET" + payload + timestamp + nonce;
secret_bytes = atob(environment.api_secret);
var hash = CryptoJS.HmacSHA256(signature, secret_bytes);
var hashInBase64 = CryptoJS.enc.Base64.stringify(hash);
var sig = "amx " + environment.api_key + ":" + hashInBase64 + ":" + nonce + ":" + timestamp;
postman.setGlobalVariable("signature", sig);
如果我使用相同的timestamp
和nonce
(通过明确设置它们而不是在运行时生成它们)和相同的api_key
和api_secret
(它们是恒定的调用)我希望在sig
(Javascript)中获得与base64_signature_hash
(Python)中相同的值,但事实并非如此。
我知道这可能是一个编码问题,但我的js-fu很弱。有什么想法吗?
编辑添加:每个用method
和url
也相同。
答案 0 :(得分:0)
基本上,有两个问题。首先,在Python和JS代码中, secret_bytes 都应为base64编码的字符串。其次,在JavaScript代码 secret_bytes 中没有从base64字符串正确解码。请在下面找到更正后的Python和JavaScript示例。
Python:
import hmac
import time
import uuid
import base64
import hashlib
import urllib.parse
def sign_api_request(api_secret, api_key, method, url):
encoded_url = urllib.parse.quote(url.lower(), '').lower()
# timestamp = int(time.time())
# nonce = str(uuid.uuid4())
timestamp = str(1569158586);
nonce = '708b7df1-7494-49fa-812c-e5f6c24aeab6'
signature = api_key + method + encoded_url + timestamp + nonce
# print(signature)
secret_bytes = base64.standard_b64decode(api_secret)
# print(secret_bytes)
signature_bytes = signature.encode('UTF8')
signature_hash = hmac.new(secret_bytes, signature_bytes, hashlib.sha256).digest()
base64_signature_hash = base64.b64encode(signature_hash).decode()
return base64_signature_hash
base64_signature_hash = sign_api_request('MTIzNDU2NzgxMjM0NTY3ODEyMzQ1Njc4MTIzNDU2Nzg=', '0987654321', 'POST', '/signin')
print(base64_signature_hash)
JavaScript:
const CryptoJS = require('crypto-js');
function epochTime() {
var d = new Date();
var t = d.getTime();
var o = t + "";
return o.substring(0, 10);
}
function newGuid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { var r = Math.random() * 16 | 0, v = c == 'x' ? r : r & 0x3 | 0x8; return v.toString(16); });
}
let api_secret = 'MTIzNDU2NzgxMjM0NTY3ODEyMzQ1Njc4MTIzNDU2Nzg=';
let api_key = '0987654321';
let method = 'POST';
let url_path = '/signin';
let encoded_url = encodeURIComponent(url_path.toLowerCase()).toLowerCase();
let timestamp = '1569158586';
let nonce = '708b7df1-7494-49fa-812c-e5f6c24aeab6';
let signature = api_key + method + encoded_url + timestamp + nonce;
// console.log(signature);
let secret_bytes = new Buffer.from(api_secret, 'base64');
secret_bytes = secret_bytes.toString('ascii');
// console.log(secret_bytes);
let hash = CryptoJS.HmacSHA256(signature, secret_bytes);
let hashInBase64 = CryptoJS.enc.Base64.stringify(hash);
console.log(hashInBase64);
两者的输出应相同:
1Hw92JPDJPFB3Je4MvwapODmn5S6KdIbvot3MAvg0jM=
答案 1 :(得分:0)
这是从python到javascript的好翻译
import hmac
import base64
import hashlib
SECRET_KEY = 'b7566b7c87365a970e64109f92bb7415719cca1a0fea04c196f7ca7a45cc64b4'
API_KEY = '/v1/users/me'
def sign_api_request(api_secret=SECRET_KEY, api_key=API_KEY):
signature_hash = hmac.new(api_secret.encode(), api_key.encode(), hashlib.sha512).digest()
base64_signature_hash = base64.b64encode(signature_hash).decode()
return base64_signature_hash
const CryptoJS = require('crypto-js');
SECRET_KEY = 'b7566b7c87365a970e64109f92bb7415719cca1a0fea04c196f7ca7a45cc64b4'
API_KEY = '/v1/users/me'
function sign_api_request(api_secret=SECRET_KEY, api_key=API_KEY) {
return CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA512(api_key, api_secret));
}
console.log(sign_api_request())