Aarunya AppsAarunya Apps

ES384 JWT Algorithm

ES384 uses the P-384 (secp384r1) elliptic curve with SHA-384. It provides a higher security margin than ES256 — approximately equivalent to RSA-7680 — while remaining far more efficient than RSA at that security level. P-384 is included in NIST's recommended curves and NSA Suite B.

Family
ECDSA
Hash
SHA-384
Key type
asymmetric
Performance
Medium (0.1–1ms)

Key Requirements

EC key pair on the P-384 (secp384r1) curve. Generate: openssl ecparam -name secp384r1 -genkey -noout -out ec-private.pem

JWT Header

Every JWT using ES384 has this header (base64url-encoded as the first segment):

{
  "alg": "ES384",
  "typ": "JWT"
}

Code Examples

Node.js — Sign (jose library)
import { SignJWT, importPKCS8 } from 'jose'

const privateKey = await importPKCS8(process.env.EC_PRIVATE_KEY!, 'ES384')

export async function signToken(payload: Record<string, unknown>) {
  return new SignJWT(payload)
    .setProtectedHeader({ alg: 'ES384' })
    .setIssuedAt()
    .setExpirationTime('1h')
    .sign(privateKey)
}
Node.js — Verify (jose library)
import { jwtVerify, importSPKI } from 'jose'

const publicKey = await importSPKI(process.env.EC_PUBLIC_KEY!, 'ES384')

export async function verifyToken(token: string) {
  const { payload } = await jwtVerify(token, publicKey, { algorithms: ['ES384'] })
  return payload
}
Python — PyJWT
import jwt
from cryptography.hazmat.primitives import serialization

with open("ec-private.pem", "rb") as f:
    private_key = serialization.load_pem_private_key(f.read(), password=None)
with open("ec-public.pem", "rb") as f:
    public_key = serialization.load_pem_public_key(f.read())

token = jwt.encode({"sub": "1234"}, private_key, algorithm="ES384")
payload = jwt.decode(token, public_key, algorithms=["ES384"])

When to Use ES384

Systems requiring the NSA Suite B 192-bit security level (SECRET classification). Financial services, healthcare data, and government applications that must meet NIST SP 800-57 requirements for long-term data protection.

Security Considerations

P-384 is a NIST-standardised curve with extensive cryptographic review. Slightly slower than ES256 but still faster than RSA equivalents. The ECDSA nonce-reuse vulnerability (see ES256 notes) applies equally here.

Related Algorithms

Standardised in RFC 7518 §3.4 — JSON Web Algorithms (JWA).

Decode a real JWT

Paste any JWT into the debugger to inspect the header, payload, and verify an ES384 signature.

Open JWT Debugger

Frequently Asked Questions

How does ECDSA compare to RSA for JWT signing?

ECDSA provides equivalent security to RSA with much smaller keys: ES256 (P-256, 256-bit key) ≈ RSA-3072. This means smaller JWT signatures, faster verification, and shorter key material. ES256 is the preferred modern choice when asymmetric signing is needed.

What elliptic curve does ES256 use?

ES256 uses the P-256 curve (also known as secp256r1 or prime256v1). ES384 uses P-384 (secp384r1), and ES512 uses P-521 (secp521r1 — note: P-521, not P-512). The curve is specified in the 'crv' field of the JWK.

Is ECDSA safe from the nonce-reuse attack?

Modern ECDSA implementations in JavaScript (Node.js crypto, WebCrypto) and reputable libraries use the OS CSPRNG for nonce generation — making nonce reuse extremely unlikely. The infamous PS3 ECDSA attack happened because Sony used a constant nonce, not a random one. Using the jose or jsonwebtoken library protects you from this.