Python HMAC到CryptoJS

时间:2018-01-24 19:28:10

标签: javascript python hmac cryptojs

我的问题与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);

如果我使用相同的timestampnonce(通过明确设置它们而不是在运行时生成它们)和相同的api_keyapi_secret(它们是恒定的调用)我希望在sig(Javascript)中获得与base64_signature_hash(Python)中相同的值,但事实并非如此。

我知道这可能是一个编码问题,但我的js-fu很弱。有什么想法吗?

编辑添加:每个用methodurl也相同。

2 个答案:

答案 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的好翻译

python sign-api-request

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

等于nodejs sign-api-request

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())


npm install crypto-js