Skip to content

Instantly share code, notes, and snippets.

@mjkrause
Last active February 24, 2020 20:46
Show Gist options
  • Save mjkrause/14fe0709fd65c9f5d1662c42e10f6650 to your computer and use it in GitHub Desktop.
Save mjkrause/14fe0709fd65c9f5d1662c42e10f6650 to your computer and use it in GitHub Desktop.
HMAC Base 64 encoded key to authenticate HTTP calls

Create a base-64-encrypted HMAC from message and secret key, using SHA256

API Key authentication based on UNIX epoch (an integer). Copy get_hmac_sha256.py and username_host.json into the same directory. Set ACCESSKEY and SECRETKEY as environment variables in the shell from which this script is run.

Then running the following in a shell

export ACCESS=1234
export SECRETKEY=abc123
python3 get_hmac_sha256.py

should return

2020-02-24 12:29:51,359 - Generating a base 64 hash from a HMAC SHA256
2020-02-24 12:29:51,359 - Message is: 1234john.doe1582575857some.domainname.com
2020-02-24 12:29:51,359 - Signature: 7zqGhpu1s8WAiRbnsjjF+YQJXCgwIwf+RerldlYpMMI=
2020-02-24 12:29:51,359 - Timestamp is: 1582575857

(timestamps of log messages will differ, of course)

#!/usr/bin/env python3
import errno
import hashlib
import hmac
import base64
import json
import os
import logging
ROOT_DIR = os.path.abspath(os.path.dirname(__name__))
logging.basicConfig(format='%(asctime)s - %(message)s', level=logging.INFO)
logger = logging.getLogger(__name__)
def main():
logger.info('Generating a base 64 hash from a HMAC SHA256')
username_host = os.path.join(ROOT_DIR, 'username_host.json')
username, host = get_username_and_host(username_host)
unix_time_seconds = str(1582575857)
accesskey = os.environ.get('ACCESSKEY')
secretkey = os.environ.get('SECRETKEY')
if not accesskey or not secretkey:
raise ValueError(f'ACCESSKEY or SECRETKEY not set?')
message = accesskey + username + unix_time_seconds + host
encoding = 'utf-8'
message = bytes(message, encoding)
secret = bytes(secretkey, encoding)
signature = base64.b64encode(hmac.new(secret, message, digestmod=hashlib.sha256).digest())
logger.info(f'Signature: {signature.decode(encoding)}')
logger.info(f'Timestamp is: {unix_time_seconds}')
def get_username_and_host(username_host):
if not os.path.isfile(username_host):
raise FileNotFoundError(
errno.ENOENT, os.strerror(errno.ENOENT), username_host
)
with open(username_host, 'r') as fp:
creds = json.load(fp)
return (creds['username'], creds['host'])
if __name__ == '__main__':
main()
{
"username": "john.doe",
"host": "some.domainname.com"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment