Menu
Amazon Web Services
General Reference (Version 1.0)

Examples of How to Derive a Version 4 Signing Key

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

Note

If you are using one of the AWS SDKs (including the AWS SDK for Java, .NET, Python, Ruby, and 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

For more information about Crypto-JS and HMAC, see http://code.google.com/p/crypto-js/#HMAC.

function getSignatureKey(key, dateStamp, regionName, serviceName) {

   var kDate= Crypto.HMAC(Crypto.SHA256, dateStamp, "AWS4" + key, { asBytes: true})
   var kRegion= Crypto.HMAC(Crypto.SHA256, regionName, kDate, { asBytes: true });
   var kService=Crypto.HMAC(Crypto.SHA256, serviceName, kRegion, { asBytes: true });
   var kSigning= Crypto.HMAC(Crypto.SHA256, "aws4_request", kService, { asBytes: true });

   return kSigning;
}

Important

Use the asBytes option when calling Crypto.HMAC in JScript or JavaScript. Otherwise, the HMAC implementation will perform an additional encoding by default.

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 request that you're sending to AWS with a tool that shows you what your raw requests look like. This can help you spot issues that aren't evident from your code.

  • Including an extra newline character or forgetting one where it's required.

  • Formatting the date incorrectly such as using a time stamp instead of YYYYMMDD in the credential scope.

  • Not matching the headers in the canonical headers to the signed headers list.

  • Inadvertently swapping the key and the data 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.

  • Forgetting to add the string "AWS" 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 "AWS" string.

  • If you're using JavaScript, forgetting to use the asBytes option for the JavaScript HMAC.Crypto function. If you don't use the asBytes option, the HMAC implementation will perform an additional hex encoding by default.

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