Question

How to generate HmacSHA1 value with a string and secret key using Python


I'm trying to create a signature to use as access for an API call but can't figure out the syntax for the PythonCaller (if that is indeed the right transformer to be using). I need to use an input (a concatenated string comprised of Date, Accesskey, HTTP method, path) and a secret key to "calculate the HmacSHA1 value for the signature, and Base64 encode it". This tool helps but I'm trying to replicate this process in FME: https://hash.online-convert.com/sha1-generator


5 replies

Userlevel 3
Badge +17

Hi @ntippett

Do you have an example of what your workspace looks like so far?

If you are still in the beginning stages, I would recommend taking a look at the following Q&A post for an example of a Python script which creates an HMAC-SHA1 signature.

Based on your input (concatenated string), you may have to make some changes either to the Python script or pre-process your input using transformers.

Hi @ntippett

Do you have an example of what your workspace looks like so far?

If you are still in the beginning stages, I would recommend taking a look at the following Q&A post for an example of a Python script which creates an HMAC-SHA1 signature.

Based on your input (concatenated string), you may have to make some changes either to the Python script or pre-process your input using transformers.

Thank you @debbiatsafe - the other post was very helpful and is getting me further than before however I still can't get the final signature to match what https://hash.online-convert.com/sha1-generator is giving me for using the same inputs.

I've dumbed down the Python to try and find what's going wrong but can't seem to find it. this is what it's looking like...

 

import sys, getopt, hashlib, os

from hashlib import sha1

import hmac

import base64

import time

import requests

import subprocess

import json

import fme

import fmeobjects

import datetime

 

def calculate_signature(feature):

 

shared_secret = '23e2c7da7f7048e5b46f96bc91624800'

sig_block = '2013-11-09 14:33:46de235a6a15c340b6b1e1cb5f3697d04aPOST/activity.json/search?lang=EN&currency=ISK'

decoded_secret = base64.b64decode(shared_secret)

hashed = hmac.new(decoded_secret, sig_block, sha1)

sig = hashed.digest().encode("base64").rstrip('\\n')

# add sig value to feature as attribute

feature.setAttribute('sig',sig)

#feature.setAttribute('timestamp',str(timestamp))

 

 

I figure it must be something with the lines after the sig_block but I'm at a loss for what to change. Any ideas?

Userlevel 3
Badge +17

Thank you @debbiatsafe - the other post was very helpful and is getting me further than before however I still can't get the final signature to match what https://hash.online-convert.com/sha1-generator is giving me for using the same inputs.  

I've dumbed down the Python to try and find what's going wrong but can't seem to find it.  this is what it's looking like...

 

import sys, getopt, hashlib, os

from hashlib import sha1

import hmac

import base64

import time

import requests

import subprocess

import json

import fme

import fmeobjects

import datetime

 

def calculate_signature(feature):

 

    shared_secret = '23e2c7da7f7048e5b46f96bc91624800'

 

    sig_block = '2013-11-09 14:33:46de235a6a15c340b6b1e1cb5f3697d04aPOST/activity.json/search?lang=EN&currency=ISK'

 

    decoded_secret = base64.b64decode(shared_secret)

    hashed = hmac.new(decoded_secret, sig_block, sha1)

    sig = hashed.digest().encode("base64").rstrip('\n')

    # add sig value to feature as attribute

    feature.setAttribute('sig',sig)

    #feature.setAttribute('timestamp',str(timestamp))

 

 

I figure it must be something with the lines after the sig_block but I'm at a loss for what to change.  Any ideas?

Hi @ntippett

It appears your shared secret is not Base64 encoded so it is not necessary to decode it before creating the hash. Please try this instead:

from hashlib import sha1
import hmac
import base64
import fme
import fmeobjects

def calculate_signature(feature):

    shared_secret = b'23e2c7da7f7048e5b46f96bc91624800'
    sig_block = b'2013-11-09 14:33:46de235a6a15c340b6b1e1cb5f3697d04aPOST/activity.json/search?lang=EN&currency=ISK'

    #Shared secret is not Base64 encoded; no need to decode
    #decoded_secret = base64.b64decode(shared_secret)

    hashed = hmac.new(shared_secret, sig_block, sha1)
    
    #Use with Python 2.7
    sig = hashed.digest().encode("base64").rstrip('\n')
    
    #Use with Python 3.x
    #sig = base64.b64encode(hashed.digest()).decode('utf-8')

    # add sig value to feature as attribute
    feature.setAttribute('sig',sig)

In addition, it appears you are using Python 2.7. We have deprecated Python 2.7 starting in FME 2019 (for more information, please see this deprecation article) so we recommend any new workspace development use Python 3.x instead for ease of future compatibility.

Hi @ntippett

Do you have an example of what your workspace looks like so far?

If you are still in the beginning stages, I would recommend taking a look at the following Q&A post for an example of a Python script which creates an HMAC-SHA1 signature.

Based on your input (concatenated string), you may have to make some changes either to the Python script or pre-process your input using transformers.

YAY!! Thank you @debbiatsafe! That seems to have done the trick (and I've updated to the 3.x version of Python as well).

I also swapped out the string data with incoming feature variables to get this:

 

shared_secret = bytes(feature.getAttribute('SecretKey'), encoding='utf-8')

sig_block = bytes(feature.getAttribute('string'), encoding='utf-8')

 

and everything works perfectly!

 

Thank you so much!

Hi @ntippett

It appears your shared secret is not Base64 encoded so it is not necessary to decode it before creating the hash. Please try this instead:

from hashlib import sha1
import hmac
import base64
import fme
import fmeobjects

def calculate_signature(feature):

    shared_secret = b'23e2c7da7f7048e5b46f96bc91624800'
    sig_block = b'2013-11-09 14:33:46de235a6a15c340b6b1e1cb5f3697d04aPOST/activity.json/search?lang=EN&currency=ISK'

    #Shared secret is not Base64 encoded; no need to decode
    #decoded_secret = base64.b64decode(shared_secret)

    hashed = hmac.new(shared_secret, sig_block, sha1)
    
    #Use with Python 2.7
    sig = hashed.digest().encode("base64").rstrip('\n')
    
    #Use with Python 3.x
    #sig = base64.b64encode(hashed.digest()).decode('utf-8')

    # add sig value to feature as attribute
    feature.setAttribute('sig',sig)

In addition, it appears you are using Python 2.7. We have deprecated Python 2.7 starting in FME 2019 (for more information, please see this deprecation article) so we recommend any new workspace development use Python 3.x instead for ease of future compatibility.

@debbiatsafe I created this account to say thank you. I am so grateful for this.

Reply