Skip to main content

Implements the most common JWT algorithms to generate keys or sign and verify payloads without the requirement to first read a lot of documentation just to do the signing and verifying part.

Project description

Test Coverage Versions

Introduction

A simple library for signing and verifying messages using common JWS (JSON Web Signature) algorithms without the overhead of a full JWT/JWS library or a lot of setup and reading documentation when you do not need JWT/JWS.

This library provides two enums:

  • SymmetricAlgorithm: for symmetric algorithms like HMAC, where the same secret is used for signing and verifying.
  • AsymmetricAlgorithm: for asymmetric algorithms like RSA and ECDSA, where a private key is used for signing and a public key is used for verification.

Select the algorithm you want to use from the enum, then call its sign and verify methods, or if you still need a key generate_secret or generate_keypair depending on the algorithm.

Installation

You can install the package via pip:

pip install jws-algorithms

Basic Usage

Symmetric algorithms use shared secrets that are simple random byte strings:

from jws_algorithms import SymmetricAlgorithm

# Our message we want to sign and verify using HMAC-SHA256
message = b"Hello, World!"

# Generate a new secret random bytes
key = SymmetricAlgorithm.HS256.generate_secret()

# Sign the message
signature = SymmetricAlgorithm.HS256.sign(message, key)

# Verify the signature
assert SymmetricAlgorithm.HS256.verify(message, key, signature)

For more security, asymmetric algorithms use a private key to sign messages and a public key to verify signatures:

from jws_algorithms import AsymmetricAlgorithm

# Our message we want to sign and verify using RSA-SHA256
message = b"Hello, World!"

# We need a public and private key pair
public_key, private_key = AsymmetricAlgorithm.RS256.generate_keypair()

# Sign the message with the private key
signature = AsymmetricAlgorithm.RS256.sign(message, private_key)

# Verify the signature with the public key
assert AsymmetricAlgorithm.RS256.verify(message, public_key, signature)

Keys from files

The private keys can also be loaded from files by passing a pathlib.Path object to the loading functions.

from pathlib import Path
from jws_algorithms import AsymmetricAlgorithm

# The message to sign using RSA-SHA256
message = b'Hello, World!'

# Sign with a private key loaded from a file
signature = AsymmetricAlgorithm.RS256.sign(
    message,
    Path('path/to/private_key.pem')
)

# Verify with a public key loaded from a file
assert AsymmetricAlgorithm.RS256.verify(
    message,
    Path('path/to/public_key.pem'),
    signature
)

From raw text or environment

Keys can also be passed as raw text (often from environment variables) by calling the functions with a str or bytes instead of a Path or compiled representation of the cryptography package.

import os
from jws_algorithms import AsymmetricAlgorithm

# The message to sign using RSA-SHA256
message = b'Hello, World!'

# Sign with a private key loaded from an environment variable
signature = AsymmetricAlgorithm.RS256.sign(message, os.environ['PRIVATE_KEY'])

# Verify with a public key loaded from an environment variable
assert AsymmetricAlgorithm.RS256.verify(message, os.environ['PUBLIC_KEY'], signature)

Encrypted private keys

When loading private keys, you can provide an optional password if the private key is encrypted. Important: You have to install with all optional dependencies or specifically the encryption extra to use this feature, as it depends on the bcrypt package.

from pathlib import Path
from jws_algorithms import AsymmetricAlgorithm

# Sign with an encrypted private key loaded from a file
signature = AsymmetricAlgorithm.RS256.sign(
    b'Hello, World!',
    Path('path/to/encrypted_private_key.pem'),
    password='my_secret_password'
)

# Public keys are not encrypted, so no password is needed here
assert AsymmetricAlgorithm.RS256.verify(
    b'Hello, World!',
    Path('path/to/public_key.pem'),
    signature
)

Using this enum in your own code

You can use the SymmetricAlgorithm and AsymmetricAlgorithm enums in your own code to select algorithms dynamically. For example, when your client has a signature, they can send the algorithm name along it and you can parse it using the enum:

from jws_algorithms import SymmetricAlgorithm, AsymmetricAlgorithm

def index(request):
    alg_name = request.headers.get("X-Signature-Algorithm")
    algorithm = SymmetricAlgorithm[alg_name] if alg_name in SymmetricAlgorithm else AsymmetricAlgorithm[alg_name]
    message = request.body
    signature = request.headers.get("X-Signature")
    key = get_key_somehow(alg_name)  # Load the key from a database
    if not algorithm.verify(message, key, signature):
        raise ValueError("Invalid signature")
    # Process the request

How to generate keys

In case you don't have keys yet, here are some examples of how to generate them.

HMAC

Symmetric HMAC-SHA is just some random bytes:

# Using openssl
openssl rand -base64 32 > hmac_secret.key

# Using python
python -c "import os; print(os.urandom(32).hex())" > hmac_secret.key

RSA

Using openssl:

# Generate a 2048-bit RSA private key in PEM format
openssl genpkey -algorithm RSA -out rsa_private.pem -pkeyopt rsa_keygen_bits:2048

# Extract the public key from the private key
openssl rsa -pubout -in rsa_private.pem -out rsa_public.pem

Using ssh-keygen:

# Generate a 2048-bit RSA private key in PEM format
ssh-keygen -t rsa -b 2048 -m PEM -f rsa_private.pem

# Extract the public key from the private key
ssh-keygen -y -f rsa_private.pem > rsa_public.pem

ECDSA

Using openssl:

# Generate a private key for the P-256 curve in PEM format
openssl ecparam -name prime256v1 -genkey -noout -out ecdsa_private.pem

# Extract the public key from the private key
openssl ec -in ecdsa_private.pem -pubout -out ecdsa_public.pem

Using ssh-keygen:

# Generate a private key for the P-256 curve in PEM format
ssh-keygen -t ecdsa -b 256 -m PEM -f ecdsa_private.pem

# Extract the public key from the private key
ssh-keygen -y -f ecdsa_private.pem > ecdsa_public.pem

EdDSA (Ed25519)

Using ssh-keygen:

# Generate an Ed25519 private key in PEM format
ssh-keygen -t ed25519 -m PEM -f ed25519_private.pem

# Extract the public key from the private key
ssh-keygen -y -f ed25519_private.pem > ed25519_public.pem

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

jws_algorithms-1.1.1.tar.gz (12.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

jws_algorithms-1.1.1-py3-none-any.whl (21.2 kB view details)

Uploaded Python 3

File details

Details for the file jws_algorithms-1.1.1.tar.gz.

File metadata

  • Download URL: jws_algorithms-1.1.1.tar.gz
  • Upload date:
  • Size: 12.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for jws_algorithms-1.1.1.tar.gz
Algorithm Hash digest
SHA256 fdfa76ce152bb04067f3fecedfddeb85b625e4c36df9b5218723b350636564c1
MD5 5099a5a2f67ce23ac97d561f5d56a040
BLAKE2b-256 865c3e8e1e775246d93b2bd45ae5eca27a96a1f389f34d943846ba0a17bacf54

See more details on using hashes here.

Provenance

The following attestation bundles were made for jws_algorithms-1.1.1.tar.gz:

Publisher: publish.yml on Mari6814/py-jws-algorithms

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file jws_algorithms-1.1.1-py3-none-any.whl.

File metadata

  • Download URL: jws_algorithms-1.1.1-py3-none-any.whl
  • Upload date:
  • Size: 21.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for jws_algorithms-1.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 8f94ec7ea0289fab057858c128509c714137b92fe1224aa3f140988e81903d99
MD5 1247f7982ab8ec41abff42c0b17197e7
BLAKE2b-256 975a6284aa75d8293e198d44d85686e7d7b36d319ff6e8039505acd2030c2181

See more details on using hashes here.

Provenance

The following attestation bundles were made for jws_algorithms-1.1.1-py3-none-any.whl:

Publisher: publish.yml on Mari6814/py-jws-algorithms

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

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