Skip to main content

A python package that creates and verifies HMAC signatures

Project description

HMAC Authentication (easy-hmac)

A pure python package with no dependencies to easily handle the generation and verification of HMAC signatures.

Installation

This package is hosted at https://pypi.org/project/easy-hmac/

User

If you don't need to customise this package, just install the package from here.

Ie. pip install easy-hmac

Developer

  1. Clone this repository
  2. Build the package in your local environment.
pipenv shell
pipenv install build
python -m build easy-hmac
  1. Install the easy-hmac package in editing mode by running:
pip install -e easy-hmac
  1. If you want to make sure everything went well, try running the tests from test_easy-hmac
python easy_hmac/test/test_easy-hmac.py

Usage

easy-hmac provides two helper functions for HMAC authentication:

  • generate_hmac_sha256 - generates a SHA256 HMAC from two strings (a secret key and a http message)
  • verify_hmac - given an HMAC and a message, verifies if the HMAC generated by the message is equal to the one passed as argument

Step 1

Import the package. python import datetime from easy_hmac import core import hmac import hashlib from base64 import b64encode from typing import Dict, Any

Step 2

Create some vars we can use to generate and verify the HMAC.

# fake identifier used to retrieve the secret from a db.
secret = "79721503-d1ef-46b7-b4ca-fec39ece902f"
body = '{"event": "lifecycle_updated", "payload": {"uuid": "cb8c79cd-8d79-4698-90a2-662eeab8da98", "timestamp": "2021-12-10T00:16:08.048401Z", "status": "PROCESSING"}}'
method = "POST"
timestamp = datetime.datetime.now(datetime.UTC).strftime("%a, %d %b %Y %H:%M:%S GMT")
path = "/api/v1/my/path"

# vars required for verifying the HMAC.
# This step is a little long because we need to fake some parameters we'd usually already have.
identifier = "2e42a19593f047e080285e49864b0fb6"
hash = hashlib.md5(body.encode())
content_type = "application/json"
content_md5 = b64encode(hash.digest()).decode('utf-8')
message = "\n".join([method, content_md5, content_type, timestamp, path])
signature = hmac.new(bytes(secret, "latin-1"), bytes(message, "latin-1"), digestmod=hashlib.sha256)
hmac_base64 = b64encode(signature.digest()).decode("utf-8")

headers = {
    "Date": timestamp,
    "Content-MD5": content_md5,
    "Content-Type": content_type,
    "Authorization": "HMAC {}:{}".format(identifier, hmac_base64),
}
request = {"method": method, "body": body, "path": path, "headers": headers}

Step 3

Create and verify the signature.

result_digest = core.generate_hmac_sha256(secret, method, body, path, timestamp)
actual_signature = b64encode(result_digest).decode()
expected_signature = "d8laojz+oDCPizTL1a401mHq5IpR1A9f9QK3+RQ/6hA="

core.verify_hmac(secret, hmac_base64, headers["Content-MD5"], body.encode(), headers["Date"], headers["Content-Type"], path, method)

``

You can raise an exception that the request has expired by changing the timestamp to;
`timestamp = "Fri, 10 Dec 2021 00:16:57 GMT"`
and then rerunning the second set of vars above to generate an incoming request that is too old and verifying
the signature again.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

easy-hmac-0.0.6.tar.gz (9.2 kB view hashes)

Uploaded Source

Built Distribution

easy_hmac-0.0.6-py3-none-any.whl (7.0 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page