简体   繁体   English

WebCrypto JS SHA256 HMAC 不匹配

[英]WebCrypto JS SHA256 HMAC Mismatch

I have two scripts that generate a SHA256 HMAC, with a plaintext message and Base64 encoded key.我有两个生成 SHA256 HMAC 的脚本,带有纯文本消息和 Base64 编码密钥。 One is written in PHP and the other in JavaScript.一个写在 PHP 中,另一个写在 JavaScript 中。 The PHP script returns the correct HMAC, but for some reason the JS version does not. PHP 脚本返回正确的 HMAC,但由于某种原因,JS 版本没有。 What is causing this?这是什么原因造成的?

Here are the code samples, with a redacted (still similar in nature) key.以下是代码示例,带有经过编辑(本质上仍然相似)的密钥。

PHP PHP

<?php

header("content-type: text/plain");

$key = "YdkQZp9Pq0OsKT5TlFzrgry7j1nw0XEmbNFm86zNU3+XFEmM/I+WxrAZE7yjFAD3iWJTQ10VN2+JK3fz4b3Viw==";
$message = "1614117737467myJSON.json" . '{"json_data": "to-be-encoded"}';

$hmac = base64_encode(hash_hmac('sha256', $message, base64_decode($key), true));

// to base64
echo base64_encode("1614117737467;" . $hmac);

This script, returns MTYxNDExNzczNzQ2NztFdXcwQ1l0bTBTMkdIdnZ2ZnN2ZGFkTEFDMGVPbVlJeHFzZk9PQWExS1BzPQ==此脚本返回MTYxNDExNzczNzQ2NztFdXcwQ1l0bTBTMkdIdnZ2ZnN2ZGFkTEFDMGVPbVlJeHFzZk9PQWExS1BzPQ==

JS JS

async function hash_hmac(type, message, key, base64) {
    const getUtf8Bytes = str =>
        new Uint8Array(
        [...unescape(encodeURIComponent(str))].map(c => c.charCodeAt(0))
    );

    const keyBytes = getUtf8Bytes(key);
    const messageBytes = getUtf8Bytes(message);

    const cryptoKey = await crypto.subtle.importKey(
        "raw", keyBytes, { name: "HMAC", hash: type },
        true, ["sign"]
    );

    const sig = await crypto.subtle.sign("HMAC", cryptoKey, messageBytes);

    const data = String.fromCharCode(...new Uint8Array(sig));

    return base64 ? btoa(data) : data;
}

(async function() {
    let key = "YdkQZp9Pq0OsKT5TlFzrgry7j1nw0XEmbNFm86zNU3+XFEmM/I+WxrAZE7yjFAD3iWJTQ10VN2+JK3fz4b3Viw==";
    let message = "1614117737467myJSON.json" + '{"json_data": "to-be-encoded"}';
    
    let hmac = await hash_hmac("SHA-256", message, atob(key), true);

    console.log(
        btoa("1614117737467;" + hmac)
    );
})();

Which returns MTYxNDExNzczNzQ2NztBeGxFRVJCTzVYWm5KN2ZHNCtoeWlxalJ0VmxZQmJpekNUSEwzcldMQVhzPQ==返回MTYxNDExNzczNzQ2NztBeGxFRVJCTzVYWm5KN2ZHNCtoeWlxalJ0VmxZQmJpekNUSEwzcldMQVhzPQ==

Why are these seemingly identical scripts returning different results?为什么这些看似相同的脚本会返回不同的结果?

It have to do with the differences in handling binary arrays or strings in php/javascript.它与处理二进制 arrays 或 php/javascript 中的字符串的差异有关。 If you change base64_decode($key) to $key (php) and atob(key) to key (javascript) it works fine.如果您将base64_decode($key)更改为$key (php) 并将atob(key)更改为key (javascript),它可以正常工作。

Edit:编辑:

The error is in unescape(encodeURIComponent(str)) , just remove the functions and change to str and it should work.错误在unescape(encodeURIComponent(str))中,只需删除函数并更改为str即可。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM