Menu
Amazon Web Services
General Reference (Version 1.0)

Examples of How to Derive a Signing Key for Signature Version 4

This page shows examples in several programming languages for how to derive a signing key for Signature Version 4.

Note

If you are using one of the AWS SDKs (including the SDK for Java, .NET, Python, Ruby, or JavaScript), you do not have to manually perform the steps of deriving a signing key and adding authentication information to a request. The SDKs perform this work for you. You need to manually sign requests only if you are directly making HTTP or HTTPS requests.

Deriving the Signing Key with Java

static 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"));
}

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

Deriving the Signing Key with .NET (C#)

static byte[] HmacSHA256(String data, byte[] key)
{
    String algorithm = "HmacSHA256";
    KeyedHashAlgorithm kha = KeyedHashAlgorithm.Create(algorithm);
    kha.Key = key;

    return kha.ComputeHash(Encoding.UTF8.GetBytes(data));
}

static byte[] getSignatureKey(String key, String dateStamp, String regionName, String serviceName)
{
    byte[] kSecret = Encoding.UTF8.GetBytes(("AWS4" + key).ToCharArray());
    byte[] kDate = HmacSHA256(dateStamp, kSecret);
    byte[] kRegion = HmacSHA256(regionName, kDate);
    byte[] kService = HmacSHA256(serviceName, kRegion);
    byte[] kSigning = HmacSHA256("aws4_request", kService);

    return kSigning;
}

Deriving the Signing Key with Python

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

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

Deriving the Signing Key with Ruby

def getSignatureKey key, dateStamp, regionName, serviceName
    kDate = OpenSSL::HMAC.digest('sha256', "AWS4" + key, dateStamp)
    kRegion = OpenSSL::HMAC.digest('sha256', kDate, regionName)
    kService = OpenSSL::HMAC.digest('sha256', kRegion, serviceName)
    kSigning = OpenSSL::HMAC.digest('sha256', kService, "aws4_request")

    kSigning
end

Deriving the Signing Key with JavaScript

The following example uses the crypto-js library. For more information, see https://www.npmjs.com/package/crypto-js and https://code.google.com/archive/p/crypto-js/.

var crypto = require("crypto-js");

function getSignatureKey(Crypto, key, dateStamp, regionName, serviceName) {
    var kDate = Crypto.HmacSHA256(dateStamp, "AWS4" + key);
    var kRegion = Crypto.HmacSHA256(regionName, kDate);
    var kService = Crypto.HmacSHA256(serviceName, kRegion);
    var kSigning = Crypto.HmacSHA256("aws4_request", kService);
    return kSigning;
}

Deriving the Signing Key with Other Languages

If you need to implement this logic in a different programming language, we recommend testing the intermediary steps of the key derivation algorithm against the values in this section. The following example in Ruby prints the results using the hexEncode function after each step in the algorithm.

def hexEncode bindata
    result=""
    data=bindata.unpack("C*")
    data.each {|b| result+= "%02x" % b}
    result
end

Given the following test input:

key = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY'
dateStamp = '20120215'
regionName = 'us-east-1'
serviceName = 'iam'

Your program should generate the following values for the values in getSignatureKey. Note that these are hex-encoded representations of the binary data; the key itself and the intermediate values should be in binary format.

kSecret  = '41575334774a616c725855746e46454d492f4b374d44454e472b62507852666943594558414d504c454b4559'
kDate    = '969fbb94feb542b71ede6f87fe4d5fa29c789342b0f407474670f0c2489e0a0d'
kRegion  = '69daa0209cd9c5ff5c8ced464a696fd4252e981430b10e3d3fd8e2f197d7a70c'
kService = 'f72cfd46f26bc4643f06a11eabb6c0ba18780c19a8da0c31ace671265e3c87fa'
kSigning = 'f4780e2d9f65fa895f9c67b32ce1baf0b0d8a43505a000a1a9e090d414db404d'

Common Coding Mistakes

To simplify your task, avoid the following common coding errors.

Tip

Examine the HTTP request that you're sending to AWS with a tool that shows you what your raw HTTP requests look like. This can help you spot issues that aren't evident from your code.

  • Don't include an extra newline character, or forget one where it's required.

  • Don't format the date incorrectly in the credential scope, such as using a time stamp instead of YYYYMMDD format.

  • Make sure the headers in the canonical headers and the signed headers are the same.

  • Don't inadvertently swap the key and the data (message) when calculating intermediary keys. The result of the previous step's computation is the key, not the data. Check the documentation for your cryptographic primitives carefully to ensure that you place the parameters in the proper order.

  • Don't forget to add the string "AWS4" in front of the key for the first step. If you implement the key derivation using a for loop or iterator, don't forget to special-case the first iteration so that it includes the "AWS4" string.

For more information about possible errors, see Troubleshooting AWS Signature Version 4 Errors.