Skip to content

Algorithms

Overview

JOSE supports multiple algorithms organized into three categories:

  • Signing Algorithms (JWS) - for creating and verifying digital signatures
  • Key Management Algorithms (JWE) - for encrypting Content Encryption Keys
  • Content Encryption Algorithms (JWE) - for encrypting payload data

Signing Algorithms (JWS)

Used with JWS class and JWT.encode() / JWT.decode().

HMAC (Symmetric)

Algorithm Key Size Notes
HS256 256-bit HMAC with SHA-256
HS384 384-bit HMAC with SHA-384
HS512 512-bit HMAC with SHA-512

Requires a shared secret key on both sides.

from jam.jose import JWS, JWT

# JWS
jws = JWS(alg="HS256", key="shared-secret-key-32-bytes!")
token = jws.sign(header={}, data={"data": "value"})

# JWT
jwt = JWT(alg="HS256", secret_key="shared-secret-key-32-bytes!")
token = jwt.encode(exp=3600, payload={"user": "admin"})

RSA (Asymmetric)

Algorithm Signature Type Notes
RS256 PKCS#1 v1.5 SHA-256
RS384 PKCS#1 v1.5 SHA-384
RS512 PKCS#1 v1.5 SHA-512

Uses RSA key pair. Sign with private key, verify with public key.

from jam.jose import JWS, JWT

# Sign with private key
jws_sign = JWS(alg="RS256", key=rsa_private_key)
token = jws_sign.sign(header={}, data={"data": "value"})

# Verify with public key
jws_verify = JWS(alg="RS256", key=rsa_public_key)
result = jws_verify.verify(token)

# JWT
jwt = JWT(alg="RS256", secret_key=rsa_private_key)
token = jwt.encode(exp=3600, payload={"user": "admin"})

ECDSA (Asymmetric)

Algorithm Curve Notes
ES256 P-256 256-bit security
ES384 P-384 384-bit security
ES512 P-521 521-bit security

Shorter signatures compared to RSA.

from jam.jose import JWS, JWT

jws = JWS(alg="ES256", key=ec_private_key)
token = jws.sign(header={}, data={"data": "value"})

jwt = JWT(alg="ES256", secret_key=ec_private_key)
token = jwt.encode(exp=3600, payload={"user": "admin"})

RSA-PSS (Asymmetric)

Algorithm Signature Type Notes
PS256 PSS SHA-256, probabilistic
PS384 PSS SHA-384, probabilistic
PS512 PSS SHA-512, probabilistic

More modern RSA signature scheme with probabilistic salt.

from jam.jose import JWS, JWT

jws = JWS(alg="PS256", key=rsa_private_key)
token = jws.sign(header={}, data={"data": "value"})

jwt = JWT(alg="PS256", secret_key=rsa_private_key)
token = jwt.encode(exp=3600, payload={"user": "admin"})

Key Management Algorithms (JWE)

Used with JWE class for encrypting Content Encryption Keys.

RSA

Algorithm Type Notes
RSA1_5 RSA PKCS#1 v1.5 (legacy, not recommended)
RSA-OAEP RSA OAEP with SHA-256 (recommended)
RSA-OAEP-256 RSA OAEP with SHA-256 (same as RSA-OAEP)

Encrypt CEK with RSA public key, decrypt with private key.

from jam.jose import JWE

jwe = JWE(
    alg="RSA-OAEP",
    enc="A128CBC-HS256",
    key=rsa_public_key
)
token = jwe.encrypt(plaintext={"data": "sensitive"})

jwe_dec = JWE(
    alg="RSA-OAEP",
    enc="A128CBC-HS256",
    key=rsa_private_key
)
data = jwe_dec.decrypt(token)

AES Key Wrap

Algorithm Key Size Notes
A128KW 128-bit AES Key Wrap
A192KW 192-bit AES Key Wrap
A256KW 256-bit AES Key Wrap

Symmetric key wrapping. Requires shared key.

from jam.jose import JWE

jwe = JWE(
    alg="A256KW",
    enc="A256GCM",
    key="your-256-bit-key-here!!"  # 32 bytes
)
token = jwe.encrypt(plaintext="secret")

ECDH-ES

Algorithm Curve Notes
ECDH-ES - Ephemeral-static ECDH, CEK = derived key
ECDH-ES+A128KW P-256 ECDH with AES key wrap
ECDH-ES+A192KW P-384 ECDH with AES key wrap
ECDH-ES+A256KW P-521 ECDH with AES key wrap

Ephemeral-static ECDH provides perfect forward secrecy.

from jam.jose import JWE

jwe = JWE(
    alg="ECDH-ES+A256KW",
    enc="A128CBC-HS256",
    key=ec_public_key
)
token = jwe.encrypt(plaintext={"data": "sensitive"})

AES-GCM Key Wrap

Algorithm Key Size Notes
A128GCMKW 128-bit AES-GCM key wrap
A256GCMKW 256-bit AES-GCM key wrap

Similar to AES Key Wrap but uses GCM mode.

from jam.jose import JWE

jwe = JWE(
    alg="A256GCMKW",
    enc="A256GCM",
    key="your-256-bit-key-here!!"
)
token = jwe.encrypt(plaintext={"data": "sensitive"})

PBES2 (Password-Based)

Algorithm Hash Key Wrap Notes
PBES2-HS256+A128KW SHA-256 A128KW 100k iterations
PBES2-HS384+A192KW SHA-384 A192KW 100k iterations
PBES2-HS512+A256KW SHA-512 A256KW 100k iterations

Password-based encryption using PBKDF2 with AES key wrap.

from jam.jose import JWE

jwe = JWE(
    alg="PBES2-HS512+A256KW",
    enc="A256CBC-HS512",
    password=b"user_password"
)
token = jwe.encrypt(plaintext={"data": "sensitive"})

Content Encryption Algorithms (JWE)

Used with JWE class for encrypting payload data.

AES-CBC-HS

Algorithm Key Size MAC Size Notes
A128CBC-HS256 256-bit 128-bit HMAC-SHA-256
A192CBC-HS384 384-bit 192-bit HMAC-SHA-384
A256CBC-HS512 512-bit 256-bit HMAC-SHA-512

HMAC-based authenticated encryption in CBC mode.

from jam.jose import JWE

jwe = JWE(
    alg="RSA-OAEP",
    enc="A128CBC-HS256",
    key=rsa_public_key
)
token = jwe.encrypt(plaintext={"data": "sensitive"})

AES-GCM

Algorithm Key Size Notes
A128GCM 128-bit Authenticated encryption
A256GCM 256-bit Authenticated encryption

Galois/Counter Mode provides built-in authenticated encryption.

from jam.jose import JWE

jwe = JWE(
    alg="A256KW",
    enc="A256GCM",
    key="your-256-bit-key-here!!"
)
token = jwe.encrypt(plaintext={"data": "sensitive"})

Algorithm Combinations

Common recommended combinations:

Symmetric (HMAC)

HS256 + A128CBC-HS256  → Basic security
HS384 + A192CBC-HS384  → Medium security
HS512 + A256CBC-HS512  → High security

RSA (Asymmetric)

RS256/PS256 + RSA-OAEP + A128CBC-HS256  → Basic RSA encryption
RS512/PS512 + RSA-OAEP + A256CBC-HS512  → High security RSA encryption

ECDH (Perfect Forward Secrecy)

ES256 + ECDH-ES + A128CBC-HS256   → P-256 ECDH
ES384 + ECDH-ES+A192KW + A192CBC-HS384  → P-384 ECDH
ES512 + ECDH-ES+A256KW + A256CBC-HS512  → P-521 ECDH

Algorithm Security Notes

Algorithm Status Notes
RSA1_5 ⚠️ Legacy PKCS#1 v1.5 has known vulnerabilities, avoid if possible
none ❌ Disabled Algorithm "none" is not supported for security
HS256 Secure with sufficient key length (256+ bits)
RS256 Secure with sufficient key size (2048+ bits)
ES256 Recommended for new implementations
RSA-OAEP Recommended, uses SHA-256
A128GCM Authenticated encryption
PBES2-* Secure with strong passwords