AWS:签名版本 4 的签名密钥:如何使用 Web 加密 API?

AWS: signing key for Signature Version 4: how to do it using Web Cryptography API?

对于我的网络应用程序,我想直接从客户端与 DynamoDB 通信,而无需中间 API 网关和 Lambda。而且我不想仅将 JS SDK 用于一些 http 调用和密钥签名。我偶然发现 key signing - examples given for a few languages but not for native js module Crypto。使用 crypto-js 的示例:

Crypto.HmacSHA256(regionName, kDate);

我试过了:

const kSecret  = '41575334774a616c725855746e46454d492f4b374d44454e472b62507852666943594558414d504c454b4559',
    dateStamp = '20120215'


function _binaryToHex(array) {
    return array.map(b => ('00' + b.toString(16)).slice(-2)).join('');
}


/**
 * https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey
 */
async function _importKey(keyDataArrayBuffer) {
    return crypto.subtle.importKey(
        'raw',
        keyDataArrayBuffer,
        {'name': 'hmac', 'hash': {'name': 'SHA-256'}},
        false,
        ['sign']);
}

const kDate = _binaryToHex(
    Array.from(
        new Uint8Array(
            await crypto.subtle.sign(
                'HMAC',
                await _importKey(
                    new TextEncoder().encode(kSecret)
                ),
                new TextEncoder().encode(dateStamp)
            )
        )
    )
);
console.log(kDate);
/* Must be
 * '969fbb94feb542b71ede6f87fe4d5fa29c789342b0f407474670f0c2489e0a0d'
 */ 

但输出与示例中的不一样。

像往常一样,我必须细心周到 - 这里是简单的错误 - 输入密钥 kSecret 已经编码为十六进制 - 但必须是

的原始人类可读值

new TextEncoder().encode('AWS4wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY')