Calculating a SHA hash with a string + secret key in python
Question:
Amazon Product API now requires a signature with every request which I’m trying to generate ushing Python.
The step I get hung up on is this one:
“Calculate an RFC 2104-compliant HMAC with the SHA256 hash algorithm using the string above with our “dummy” Secret Access Key: 1234567890. For more information about this step, see documentation and code samples for your programming language.”
Given a string and a secret key (in this case 1234567890) how do I calculate this hash using Python?
———– UPDATE ————-
The first solution using HMAC.new looks correct however I’m getting a different result than they are.
http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/index.html?rest-signature.html
According to Amazon’s example when you hash the secret key 1234567890 and the following string
GET
webservices.amazon.com
/onca/xml
AWSAccessKeyId=00000000000000000000&ItemId=0679722769&Operation=I
temLookup&ResponseGroup=ItemAttributes%2COffers%2CImages%2CReview
s&Service=AWSECommerceService&Timestamp=2009-01-01T12%3A00%3A00Z&
Version=2009-01-06
You should get the following signature: 'Nace+U3Az4OhN7tISqgs1vdLBHBEijWcBeCqL5xN9xg='
I am getting this: '411a59403c9f58b4a434c9c6a14ef6e363acc1d1bb2c6faf9adc30e20898c83b'
Answers:
From http://docs.python.org/library/hashlib.html#module-hashlib (modified a bit):
import hashlib
secretKey = "1234567890"
m = hashlib.sha256()
# Get string and put into givenString.
m.update(givenString + secretKey)
m.digest()
import hmac
import hashlib
import base64
dig = hmac.new(b'1234567890', msg=your_bytes_string, digestmod=hashlib.sha256).digest()
base64.b64encode(dig).decode() # py3k-mode
'Nace+U3Az4OhN7tISqgs1vdLBHBEijWcBeCqL5xN9xg='
>>> import hmac
>>> import hashlib
>>> import base64
>>> s = """GET
... webservices.amazon.com
... /onca/xml
... AWSAccessKeyId=00000000000000000000&ItemId=0679722769&Operation=ItemLookup&ResponseGroup=ItemAttributes%2COffers%2CImages%2CReviews&Service=AWSECommerceService&Timestamp=2009-01-01T12%3A00%3A00Z&Version=2009-01-06"""
>>> base64.b64encode(hmac.new("1234567890", msg=s, digestmod=hashlib.sha256).digest())
'Nace+U3Az4OhN7tISqgs1vdLBHBEijWcBeCqL5xN9xg='
import hmac
import hashlib
import base64
digest = hmac.new(secret, msg=thing_to_hash, digestmod=hashlib.sha256).digest()
signature = base64.b64encode(digest).decode()
I know this sounds silly, but make sure you don’t have a trailing space on your secret by accident.
If you are trying to sign up a user to AWS cognito using Python3, you can use the following code.
#For the SecretHash
import hmac
import hashlib
import base64
//Please note that the b in the secretKey and encode('utf-8') are really really important.
secretKey = b"secret key that you get from Coginito -> User Pool -> General Settings -> App Clients-->Click on Show more details -> App client secret "
clientId = "Coginito -> User Pool -> General Settings -> App Clients-->App client id"
digest = hmac.new(secretKey,
msg=(user_name + clientId).encode('utf-8'),
digestmod=hashlib.sha256
).digest()
secrethash = base64.b64encode(digest).decode()
The username user_name in the above is same as the user that you want to register in the cognito
client = boto3.client('cognito-idp', region_name='eu-west-1' )
response = client.sign_up(
ClientId='Coginito -> User Pool -> General Settings -> App Clients-->App client id',
Username='Username of the person you are planning to register',
Password='Password of the person you are planning to register',
SecretHash=secrethash,
UserAttributes=[
{
'Name': 'given_name',
'Value': given_name
},
{
'Name': 'family_name',
'Value': family_name
},
{
'Name': 'email',
'Value': user_email
}
],
ValidationData=[
{
'Name': 'email',
'Value': user_email
},
]
If you have string secret and string token, it may help (I know it may be too late, but just in case it works for someone). All three options worked for me in python 3 –
import hmac
import hashlib
import base64
access_token = 'a'
app_secret = 'b'
access_token = <your token in string format>
app_secret = <your secret access key in string format>
# use any one, all three options work.
# OPTION 1 (it works)
# digest = hmac.new(app_secret.encode('UTF-8'),
# access_token.encode('UTF-8'), hashlib.sha256)
# OPTION 2 (it works)
# digest = hmac.new(str.encode(app_secret),
# str.encode(access_token), hashlib.sha256)
# OPTION 3 (it works)
digest = hmac.new(bytes(app_secret, 'UTF-8'),
bytes(access_token, 'UTF-8'), hashlib.sha256)
signature = digest.hexdigest()
print(signature)
Amazon Product API now requires a signature with every request which I’m trying to generate ushing Python.
The step I get hung up on is this one:
“Calculate an RFC 2104-compliant HMAC with the SHA256 hash algorithm using the string above with our “dummy” Secret Access Key: 1234567890. For more information about this step, see documentation and code samples for your programming language.”
Given a string and a secret key (in this case 1234567890) how do I calculate this hash using Python?
———– UPDATE ————-
The first solution using HMAC.new looks correct however I’m getting a different result than they are.
http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/index.html?rest-signature.html
According to Amazon’s example when you hash the secret key 1234567890 and the following string
GET
webservices.amazon.com
/onca/xml
AWSAccessKeyId=00000000000000000000&ItemId=0679722769&Operation=I
temLookup&ResponseGroup=ItemAttributes%2COffers%2CImages%2CReview
s&Service=AWSECommerceService&Timestamp=2009-01-01T12%3A00%3A00Z&
Version=2009-01-06
You should get the following signature: 'Nace+U3Az4OhN7tISqgs1vdLBHBEijWcBeCqL5xN9xg='
I am getting this: '411a59403c9f58b4a434c9c6a14ef6e363acc1d1bb2c6faf9adc30e20898c83b'
From http://docs.python.org/library/hashlib.html#module-hashlib (modified a bit):
import hashlib
secretKey = "1234567890"
m = hashlib.sha256()
# Get string and put into givenString.
m.update(givenString + secretKey)
m.digest()
import hmac
import hashlib
import base64
dig = hmac.new(b'1234567890', msg=your_bytes_string, digestmod=hashlib.sha256).digest()
base64.b64encode(dig).decode() # py3k-mode
'Nace+U3Az4OhN7tISqgs1vdLBHBEijWcBeCqL5xN9xg='
>>> import hmac
>>> import hashlib
>>> import base64
>>> s = """GET
... webservices.amazon.com
... /onca/xml
... AWSAccessKeyId=00000000000000000000&ItemId=0679722769&Operation=ItemLookup&ResponseGroup=ItemAttributes%2COffers%2CImages%2CReviews&Service=AWSECommerceService&Timestamp=2009-01-01T12%3A00%3A00Z&Version=2009-01-06"""
>>> base64.b64encode(hmac.new("1234567890", msg=s, digestmod=hashlib.sha256).digest())
'Nace+U3Az4OhN7tISqgs1vdLBHBEijWcBeCqL5xN9xg='
import hmac
import hashlib
import base64
digest = hmac.new(secret, msg=thing_to_hash, digestmod=hashlib.sha256).digest()
signature = base64.b64encode(digest).decode()
I know this sounds silly, but make sure you don’t have a trailing space on your secret by accident.
If you are trying to sign up a user to AWS cognito using Python3, you can use the following code.
#For the SecretHash
import hmac
import hashlib
import base64
//Please note that the b in the secretKey and encode('utf-8') are really really important.
secretKey = b"secret key that you get from Coginito -> User Pool -> General Settings -> App Clients-->Click on Show more details -> App client secret "
clientId = "Coginito -> User Pool -> General Settings -> App Clients-->App client id"
digest = hmac.new(secretKey,
msg=(user_name + clientId).encode('utf-8'),
digestmod=hashlib.sha256
).digest()
secrethash = base64.b64encode(digest).decode()
The username user_name in the above is same as the user that you want to register in the cognito
client = boto3.client('cognito-idp', region_name='eu-west-1' )
response = client.sign_up(
ClientId='Coginito -> User Pool -> General Settings -> App Clients-->App client id',
Username='Username of the person you are planning to register',
Password='Password of the person you are planning to register',
SecretHash=secrethash,
UserAttributes=[
{
'Name': 'given_name',
'Value': given_name
},
{
'Name': 'family_name',
'Value': family_name
},
{
'Name': 'email',
'Value': user_email
}
],
ValidationData=[
{
'Name': 'email',
'Value': user_email
},
]
If you have string secret and string token, it may help (I know it may be too late, but just in case it works for someone). All three options worked for me in python 3 –
import hmac
import hashlib
import base64
access_token = 'a'
app_secret = 'b'
access_token = <your token in string format>
app_secret = <your secret access key in string format>
# use any one, all three options work.
# OPTION 1 (it works)
# digest = hmac.new(app_secret.encode('UTF-8'),
# access_token.encode('UTF-8'), hashlib.sha256)
# OPTION 2 (it works)
# digest = hmac.new(str.encode(app_secret),
# str.encode(access_token), hashlib.sha256)
# OPTION 3 (it works)
digest = hmac.new(bytes(app_secret, 'UTF-8'),
bytes(access_token, 'UTF-8'), hashlib.sha256)
signature = digest.hexdigest()
print(signature)