AWS 签名 V2:为 Javascript 中的查询请求生成签名

AWS Signature V2: generate a signature for a Query request in Javascript

我正在尝试在 java 脚本上重新创建 AWS 签名版本 2 身份验证,我现在拥有的是

String.prototype.getBytes = () => {
    return this.toString()
        .split('')
        .map((i) => i.charCodeAt(0));
};

let key = 'redacted_access_key_id';

const bytes = key.getBytes();

let signingKey = crypto.HmacSHA256(bytes, key);

let data = JSON.stringify({ lang: 'en', pageNumber: 0, pageSize: 20 });

const contentMd5 = crypto.MD5(data).toString();

data = data.getBytes();

signingKey = crypto.HmacSHA256(data, key);

const result = Buffer.from(signingKey.toString()).toString('base64');

输出类似

ZGY0MmI3MDVjNmJlNzY5ZWYwZjU1ZTc5MDhhOGNkYzI3ZWVjYzQ5ODBmY2M1NGI5NTc2MmVmNTY1NzEwNjhhMA== 

这是不正确的,因为散列的长度应该正好是 28 个字符。现在 AWS 签名版本 2 授权文档显示了它是如何制作的,但仅限于 java

import java.security.SignatureException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import com.amazonaws.util.*;

/**
* This class defines common routines for generating
* authentication signatures for AWS Platform requests.
*/
public class Signature {
    private static final String HMAC_SHA256_ALGORITHM = "HmacSHA256";
    public static String calculateRFC2104HMAC(String data, String key)
    throws java.security.SignatureException
    {
        String result;
        try {

            // Get an hmac_sha256 key from the raw key bytes.
            SecretKeySpec signingKey = new SecretKeySpec(key.getBytes("UTF-8"), HMAC_SHA256_ALGORITHM);

            // Get an hmac_sha256 Mac instance and initialize with the signing key.
            Mac mac = Mac.getInstance(HMAC_SHA256_ALGORITHM);
            mac.init(signingKey);

            // Compute the hmac on input data bytes.
            byte[] rawHmac = mac.doFinal(data.getBytes("UTF-8"));

            // Base64-encode the hmac by using the utility in the SDK
            result = BinaryUtils.toBase64(rawHmac);
            

        } catch (Exception e) {
            throw new SignatureException("Failed to generate HMAC : " + e.getMessage());
        }
        return result;
    }
}

我正在尝试在 java 脚本中重新创建完全相同的代码,但出了点问题。有人可以帮我解决这个问题吗,我在 javascript.

中找不到任何示例

谢谢。

下面的代码相当于JS中calculateRFC2104HMAC的Java版本

const CryptoJS = require('crypto-js');

const calculateRFC2104HMAC = (data, key) => {
    const rawHmac = CryptoJS.HmacSHA256(CryptoJS.enc.Utf8.parse(data), CryptoJS.enc.Utf8.parse(key));
    return CryptoJS.enc.Base64.stringify(rawHmac);
}

示例用法基于 AWS Signature V2 页面

上的示例
const urlSafeSignature = (data, key) => encodeURIComponent(calculateRFC2104HMAC(data, key));

const data = 
`GET
elasticmapreduce.amazonaws.com
/
AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE&Action=DescribeJobFlows&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2011-10-03T15%3A19%3A30&Version=2009-03-31`
const key = `wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`
console.log(urlSafeSignature(data, key));

文档建议使用 AWS Signature V4 which has a AWS published library on NPM here。 AWS 签名的请求是针对 AWS 服务的,请求中的签名有助于验证请求,防止重放攻击。我不确定您要在以下代码中发送什么以及针对哪个 AWS 服务。

let data = JSON.stringify({ lang: 'en', pageNumber: 0, pageSize: 20 });

您必须根据 AWS 文档提供签署请求所需的所有详细信息。