Search code examples
javaphpamazon-web-servicescryptojs

AWS signature 4: Java and Crypto-JS does not march


I am using java to do some post with AWS signature header. The signing process is below

    private String calculateSignature(String stringToSign) {
        try {
                byte[] signatureKey = getSignatureKey(secretAccessKey, currentDate, regionName, serviceName);
                byte[] signature = HmacSHA256(stringToSign, signatureKey);
                String strHexSignature = bytesToHex(signature);
                return strHexSignature;
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            return null;
    }

    private byte[] HmacSHA256(String data, byte[] key) throws Exception {
        String algorithm = "HmacSHA256";
        Mac mac = Mac.getInstance(algorithm);
        mac.init(new SecretKeySpec(key, algorithm));
        return mac.doFinal(data.getBytes("UTF8"));
    }

    private byte[] getSignatureKey(String key, String date, String regionName, String serviceName) throws Exception {
        byte[] kSecret = ("AWS4" + key).getBytes("UTF8");
        byte[] kDate = HmacSHA256(date, kSecret);
        byte[] kRegion = HmacSHA256(regionName, kDate);
        byte[] kService = HmacSHA256(serviceName, kRegion);
        byte[] kSigning = HmacSHA256(aws4Request, kService);
        return kSigning;
    }

    private String bytesToHex(byte[] bytes) {
        final StringBuilder hexString = new StringBuilder();
        for(byte b : bytes)
            hexString.append(String.format("%02x", b));
        return hexString.toString().toLowerCase().trim();
    }

However, when I send use this signature, it does not match the signature calculated by the server. The server is written in PHP, and it us Crypto-JS to calculate the signature. I have compared two strings need to sign and Canonical Request between Java and PHP. They are matching.

I have checked space, command and other characteries. but cannot figure out why. Are Java HmacSHA256 and crypto-js HmacSHA256 different? Or something wrong with bytesToHex method?

The Java output of Canonical Request

POST
/

content-length:667
content-type:application/json
host:host.name.com
x-amz-date:20171205T012629Z
x-amz-target:_20141201.XXXXXXX

content-length;content-type;host;x-amz-date;x-amz-target
c5b31b699700e6debe4548836a723f89b73ffcef6570e1bed4c534c0f247dc26

The PHP returns:

POST
/

content-length:667
content-type:application/json
host:host.name.com
x-amz-date:20171205T012629Z
x-amz-target:_20141201.XXXXXXX

content-length;content-type;host;x-amz-date;x-amz-target
c5b31b699700e6debe4548836a723f89b73ffcef6570e1bed4c534c0f247dc26

Any help or any idea will be appreciated.


Solution

  • Found the issue. The reason was the algorithm of the secret key was changed, but i was not aware of that change