jwt-algorithms


Namejwt-algorithms JSON
Version 1.0.5 PyPI version JSON
download
home_pageNone
SummaryImplements 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.
upload_time2025-09-14 17:24:25
maintainerNone
docs_urlNone
authorNone
requires_python>=3.10
licenseNone
keywords json web encryption json web signature json web token jwt jwt algorithms jwt sign jwt verify
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            [![Test](https://github.com/Mari6814/py-jwt-algorithms/actions/workflows/test.yml/badge.svg)](https://github.com/Mari6814/py-jwt-algorithms/actions/workflows/test.yml)
[![Coverage](https://github.com/Mari6814/py-jwt-algorithms/raw/main/badges/coverage.svg)](https://github.com/Mari6814/py-jwt-algorithms/raw/main/badges/coverage.svg)
[![Versions](https://github.com/Mari6814/py-jwt-algorithms/raw/main/badges/python-versions.svg)](https://github.com/Mari6814/py-jwt-algorithms/raw/main/badges/python-versions.svg)

# Introduction
A simple library for signing and verifying messages using common JWT algorithms without the overhead of a full JWT library or a lot of setup.

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.

# Basic Usage

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

```python
from jwt_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:

```python
from jwt_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.

```python
from pathlib import Path
from jwt_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.

```python
import os
from jwt_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.

```python
from pathlib import Path
from jwt_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:

```python
from jwt_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:

```bash
# 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:

```bash
# 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:

```bash
# 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:

```bash
# 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:

```bash
# 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:

```bash
# 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
```


            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "jwt-algorithms",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": null,
    "keywords": "json web encryption, json web signature, json web token, jwt, jwt algorithms, jwt sign, jwt verify",
    "author": null,
    "author_email": "Marian Plivelic <marianplivelic@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/88/8c/affd345a31cec4cdae143c357037ce6c3acac54dd8addf6f13d7b9a19892/jwt_algorithms-1.0.5.tar.gz",
    "platform": null,
    "description": "[![Test](https://github.com/Mari6814/py-jwt-algorithms/actions/workflows/test.yml/badge.svg)](https://github.com/Mari6814/py-jwt-algorithms/actions/workflows/test.yml)\n[![Coverage](https://github.com/Mari6814/py-jwt-algorithms/raw/main/badges/coverage.svg)](https://github.com/Mari6814/py-jwt-algorithms/raw/main/badges/coverage.svg)\n[![Versions](https://github.com/Mari6814/py-jwt-algorithms/raw/main/badges/python-versions.svg)](https://github.com/Mari6814/py-jwt-algorithms/raw/main/badges/python-versions.svg)\n\n# Introduction\nA simple library for signing and verifying messages using common JWT algorithms without the overhead of a full JWT library or a lot of setup.\n\nThis library provides two enums:\n\n- **`SymmetricAlgorithm`**: for symmetric algorithms like HMAC, where the same secret is used for signing and verifying.\n- **`AsymmetricAlgorithm`**: for asymmetric algorithms like RSA and ECDSA, where a private key is used for signing and a public key is used for verification.\n\nSelect 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.\n\n# Basic Usage\n\nSymmetric algorithms use shared *secrets* that are simple random byte strings:\n\n```python\nfrom jwt_algorithms import SymmetricAlgorithm\n\n# Our message we want to sign and verify using HMAC-SHA256\nmessage = b\"Hello, World!\"\n\n# Generate a new secret random bytes\nkey = SymmetricAlgorithm.HS256.generate_secret()\n\n# Sign the message\nsignature = SymmetricAlgorithm.HS256.sign(message, key)\n\n# Verify the signature\nassert SymmetricAlgorithm.HS256.verify(message, key, signature)\n```\n\nFor more security, asymmetric algorithms use a *private key* to sign messages and a *public key* to verify signatures:\n\n```python\nfrom jwt_algorithms import AsymmetricAlgorithm\n\n# Our message we want to sign and verify using RSA-SHA256\nmessage = b\"Hello, World!\"\n\n# We need a public and private key pair\npublic_key, private_key = AsymmetricAlgorithm.RS256.generate_keypair()\n\n# Sign the message with the private key\nsignature = AsymmetricAlgorithm.RS256.sign(message, private_key)\n\n# Verify the signature with the public key\nassert AsymmetricAlgorithm.RS256.verify(message, public_key, signature)\n```\n\n# Keys from files\nThe private keys can also be loaded from files by passing a `pathlib.Path` object to the loading functions.\n\n```python\nfrom pathlib import Path\nfrom jwt_algorithms import AsymmetricAlgorithm\n\n# The message to sign using RSA-SHA256\nmessage = b'Hello, World!'\n\n# Sign with a private key loaded from a file\nsignature = AsymmetricAlgorithm.RS256.sign(\n    message,\n    Path('path/to/private_key.pem')\n)\n\n# Verify with a public key loaded from a file\nassert AsymmetricAlgorithm.RS256.verify(\n    message,\n    Path('path/to/public_key.pem'),\n    signature\n)\n```\n\n# From raw text or environment\nKeys 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.\n\n```python\nimport os\nfrom jwt_algorithms import AsymmetricAlgorithm\n\n# The message to sign using RSA-SHA256\nmessage = b'Hello, World!'\n\n# Sign with a private key loaded from an environment variable\nsignature = AsymmetricAlgorithm.RS256.sign(message, os.environ['PRIVATE_KEY'])\n\n# Verify with a public key loaded from an environment variable\nassert AsymmetricAlgorithm.RS256.verify(message, os.environ['PUBLIC_KEY'], signature)\n```\n\n# Encrypted private keys\nWhen loading private keys, you can provide an optional password if the private key is encrypted.\n**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.\n\n```python\nfrom pathlib import Path\nfrom jwt_algorithms import AsymmetricAlgorithm\n\n# Sign with an encrypted private key loaded from a file\nsignature = AsymmetricAlgorithm.RS256.sign(\n    b'Hello, World!',\n    Path('path/to/encrypted_private_key.pem'),\n    password='my_secret_password'\n)\n\n# Public keys are not encrypted, so no password is needed here\nassert AsymmetricAlgorithm.RS256.verify(\n    b'Hello, World!',\n    Path('path/to/public_key.pem'),\n    signature\n)\n```\n\n# Using this enum in your own code\nYou 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:\n\n```python\nfrom jwt_algorithms import SymmetricAlgorithm, AsymmetricAlgorithm\n\ndef index(request):\n    alg_name = request.headers.get(\"X-Signature-Algorithm\")\n    algorithm = SymmetricAlgorithm[alg_name] if alg_name in SymmetricAlgorithm else AsymmetricAlgorithm[alg_name]\n    message = request.body\n    signature = request.headers.get(\"X-Signature\")\n    key = get_key_somehow(alg_name)  # Load the key from a database\n    if not algorithm.verify(message, key, signature):\n        raise ValueError(\"Invalid signature\")\n    # Process the request\n```\n\n# How to generate keys\nIn case you don't have keys yet, here are some examples of how to generate them.\n\n## HMAC\n\nSymmetric HMAC-SHA is just some random bytes:\n\n```bash\n# Using openssl\nopenssl rand -base64 32 > hmac_secret.key\n\n# Using python\npython -c \"import os; print(os.urandom(32).hex())\" > hmac_secret.key\n```\n\n## RSA\n\nUsing openssl:\n\n```bash\n# Generate a 2048-bit RSA private key in PEM format\nopenssl genpkey -algorithm RSA -out rsa_private.pem -pkeyopt rsa_keygen_bits:2048\n\n# Extract the public key from the private key\nopenssl rsa -pubout -in rsa_private.pem -out rsa_public.pem\n```\n\nUsing ssh-keygen:\n\n```bash\n# Generate a 2048-bit RSA private key in PEM format\nssh-keygen -t rsa -b 2048 -m PEM -f rsa_private.pem\n\n# Extract the public key from the private key\nssh-keygen -y -f rsa_private.pem > rsa_public.pem\n```\n\n## ECDSA\n\nUsing openssl:\n\n```bash\n# Generate a private key for the P-256 curve in PEM format\nopenssl ecparam -name prime256v1 -genkey -noout -out ecdsa_private.pem\n\n# Extract the public key from the private key\nopenssl ec -in ecdsa_private.pem -pubout -out ecdsa_public.pem\n```\n\nUsing ssh-keygen:\n\n```bash\n# Generate a private key for the P-256 curve in PEM format\nssh-keygen -t ecdsa -b 256 -m PEM -f ecdsa_private.pem\n\n# Extract the public key from the private key\nssh-keygen -y -f ecdsa_private.pem > ecdsa_public.pem\n```\n\n## EdDSA (Ed25519)\n\nUsing ssh-keygen:\n\n```bash\n# Generate an Ed25519 private key in PEM format\nssh-keygen -t ed25519 -m PEM -f ed25519_private.pem\n\n# Extract the public key from the private key\nssh-keygen -y -f ed25519_private.pem > ed25519_public.pem\n```\n\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "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.",
    "version": "1.0.5",
    "project_urls": {
        "Documentation": "https://github.com/Mari6814/py-jwt-algorithms",
        "Repository": "https://github.com/Mari6814/py-jwt-algorithms"
    },
    "split_keywords": [
        "json web encryption",
        " json web signature",
        " json web token",
        " jwt",
        " jwt algorithms",
        " jwt sign",
        " jwt verify"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "7c627a6481f7043fab946343c10000ace41492527a35bf142312ffb45e27de17",
                "md5": "d5147fc487030310d49397a5cf2d2307",
                "sha256": "a6ff0a6c1a2bef478c2b6bd4fd5b8950fc2592202a07989cb77d4f4c244d968b"
            },
            "downloads": -1,
            "filename": "jwt_algorithms-1.0.5-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "d5147fc487030310d49397a5cf2d2307",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 20611,
            "upload_time": "2025-09-14T17:24:23",
            "upload_time_iso_8601": "2025-09-14T17:24:23.952516Z",
            "url": "https://files.pythonhosted.org/packages/7c/62/7a6481f7043fab946343c10000ace41492527a35bf142312ffb45e27de17/jwt_algorithms-1.0.5-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "888caffd345a31cec4cdae143c357037ce6c3acac54dd8addf6f13d7b9a19892",
                "md5": "c81297b9b484ec41e6c428ae3ec65c4d",
                "sha256": "0ac4a27d8d0703a6baad7d41d9342d7feea5e1e3f78d209798128a971884fc16"
            },
            "downloads": -1,
            "filename": "jwt_algorithms-1.0.5.tar.gz",
            "has_sig": false,
            "md5_digest": "c81297b9b484ec41e6c428ae3ec65c4d",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 12446,
            "upload_time": "2025-09-14T17:24:25",
            "upload_time_iso_8601": "2025-09-14T17:24:25.144510Z",
            "url": "https://files.pythonhosted.org/packages/88/8c/affd345a31cec4cdae143c357037ce6c3acac54dd8addf6f13d7b9a19892/jwt_algorithms-1.0.5.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-09-14 17:24:25",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "Mari6814",
    "github_project": "py-jwt-algorithms",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "jwt-algorithms"
}
        
Elapsed time: 0.71885s