MeV MeV - 1 month ago 24
PHP Question

AWS4 Signature key - is this tutorial wrong?

According to this page: Examples of How to Derive a Signing Key for Signature Version 4

The result of this code:


$kDate = hash_hmac('sha256', "20120215", "AWS4" . $kSecret);
echo "date: " . $kDate . "<br>";

$kRegion = hash_hmac('sha256', "us-east-1", $kDate);
echo "region: " . $kRegion . "<br>";

$kService = hash_hmac('sha256', "iam", $kRegion);
echo "service: " . $kService . "<br>";

$kSigning = hash_hmac('sha256', "aws4_request", $kService);
echo "signing: " . $kSigning . "<br>";

should print:

kDate = '969fbb94feb542b71ede6f87fe4d5fa29c789342b0f407474670f0c2489e0a0d'

kRegion = '69daa0209cd9c5ff5c8ced464a696fd4252e981430b10e3d3fd8e2f197d7a70c'

kService = 'f72cfd46f26bc4643f06a11eabb6c0ba18780c19a8da0c31ace671265e3c87fa'

kSigning = 'f4780e2d9f65fa895f9c67b32ce1baf0b0d8a43505a000a1a9e090d414db404d'

So, kDate I get is correct. kRegion is not correct as I get the value:


I have tried using this website to calculate the HMAC (hmac generator) and I get the same result.

enter image description here

I really wonder if the page is wrong. Can anyone explain if it's my fault or AWS fault?

Thank you

  1. You should understand the values are binary and printed in hexadecimal form
  2. You are passing date in hexadecimal. You should convert it to binary and pass it before calling hash_hmac. Or store it in binary and print the same in hexadecimal
  3. You never mentioned the language you are using. I had to google to find out what language you are using. In PHP, you can pass: $raw_output = true to get the binary string
  4. Store the strings n binary and convert them to hex before printing.

Since I am not familiar with PHP, I tried the same in Python and the output matched the expected output. See how I convert it to hex and print.

import hmac
import hashlib
from base64 import b16encode as b16

def sign(key, msg):
    return, msg.encode("utf-8"), hashlib.sha256).digest()

def getSignatureKey(key, dateStamp, regionName, serviceName):
    kDate = sign(("AWS4" + key).encode("utf-8"), dateStamp)
    print b16(kDate)
    kRegion = sign(kDate, regionName)
    print b16(kRegion)
    kService = sign(kRegion, serviceName)
    print b16(kService)
    kSigning = sign(kService, "aws4_request")
    print b16(kSigning)
    return kSigning

dateStamp = '20120215'
regionName = 'us-east-1'
serviceName = 'iam'

getSignatureKey(key, dateStamp, regionName, serviceName)




string hash_hmac ( string $algo , string $data , string $key [, bool $raw_output = false ] )