| « PreviousNext » | |
![]() | Did this page help you? Yes | No | Tell us about it... |
Topics
Errors in implementing the key derivation algorithm are difficult to troubleshoot. For security reasons, AWS services report only a signature mismatch in response to an error—not the expected result. To simplify your task, you can use the following code examples to implement the derivation in several widely used programming languages.
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;
}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;
}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 kSigningdef 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
endFor more information about Crypto-JS and HMAC, go to 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.
If you need to implement this logic in a different programming language,
we recommend testing against the reference code. The example below prints
the results using the following Ruby hexEncode function after
each step in the algorithm.
def hexEncode bindata
result=""
data=bindata.unpack("C*")
data.each {|b| result+= "%02x" % b}
result
endGiven 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. These are hex-encoded representations of
the binary data.
kSecret = '41575334774a616c725855746e46454d492f4b374d44454e472b62507852666943594558414d504c454b4559' kDate = '969fbb94feb542b71ede6f87fe4d5fa29c789342b0f407474670f0c2489e0a0d' kRegion = '69daa0209cd9c5ff5c8ced464a696fd4252e981430b10e3d3fd8e2f197d7a70c' kService = 'f72cfd46f26bc4643f06a11eabb6c0ba18780c19a8da0c31ace671265e3c87fa' kSigning = 'f4780e2d9f65fa895f9c67b32ce1baf0b0d8a43505a000a1a9e090d414db404d'
During development and testing of Signature Version 4, we came across a number of coding errors we share below in the hope of simplifying your task.
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 prepend the string "AWS" in front of the key for
the first step. It is possible to implement the key derivation using
a for loop or iterator. When you do, don't forget to
special-case the first iteration so that it includes the "AWS"
string.
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.
Taking a query parameter from within a URL-encoded request like the POST request in Signed Signature Version 4 Requests Examples to use as a query parameter string in the canonical query string. The parameters that you use as part of your canonical query string cannot come from the body of this type of request.