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
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fdfa76ce152bb04067f3fecedfddeb85b625e4c36df9b5218723b350636564c1
|
|
| MD5 |
5099a5a2f67ce23ac97d561f5d56a040
|
|
| BLAKE2b-256 |
865c3e8e1e775246d93b2bd45ae5eca27a96a1f389f34d943846ba0a17bacf54
|
Provenance
The following attestation bundles were made for jws_algorithms-1.1.1.tar.gz:
Publisher:
publish.yml on Mari6814/py-jws-algorithms
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
jws_algorithms-1.1.1.tar.gz -
Subject digest:
fdfa76ce152bb04067f3fecedfddeb85b625e4c36df9b5218723b350636564c1 - Sigstore transparency entry: 543593449
- Sigstore integration time:
-
Permalink:
Mari6814/py-jws-algorithms@a200a3e5f62a6f4f1d927a0013abb518c8ef0544 -
Branch / Tag:
refs/tags/v1.1.1 - Owner: https://github.com/Mari6814
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a200a3e5f62a6f4f1d927a0013abb518c8ef0544 -
Trigger Event:
release
-
Statement type:
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8f94ec7ea0289fab057858c128509c714137b92fe1224aa3f140988e81903d99
|
|
| MD5 |
1247f7982ab8ec41abff42c0b17197e7
|
|
| BLAKE2b-256 |
975a6284aa75d8293e198d44d85686e7d7b36d319ff6e8039505acd2030c2181
|
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
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
jws_algorithms-1.1.1-py3-none-any.whl -
Subject digest:
8f94ec7ea0289fab057858c128509c714137b92fe1224aa3f140988e81903d99 - Sigstore transparency entry: 543593461
- Sigstore integration time:
-
Permalink:
Mari6814/py-jws-algorithms@a200a3e5f62a6f4f1d927a0013abb518c8ef0544 -
Branch / Tag:
refs/tags/v1.1.1 - Owner: https://github.com/Mari6814
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a200a3e5f62a6f4f1d927a0013abb518c8ef0544 -
Trigger Event:
release
-
Statement type: