🔐 JSON Web Signature (JWS) – Sign, Verify & Decode
A JSON Web Signature (JWS) is a compact, URL-safe representation of digitally-signed or MAC-protected content defined by RFC 7515. JWS is the cryptographic backbone behind the widely-used JSON Web Token (JWT) standard and is used wherever APIs need to ensure the integrity and authenticity of transmitted data — from authentication tokens to webhook payloads and API request signing.
🏗️ How a JWS Token Is Structured
A compact-serialized JWS token consists of three Base64URL-encoded sections separated by dots: HEADER.PAYLOAD.SIGNATURE.
| Part | Color | Content | Example |
|---|---|---|---|
| Header | Red | Algorithm (alg) + optional type (typ), key ID (kid) | { "alg": "HS256", "typ": "JWT" } |
| Payload | Purple | Any JSON object — standard JWT claims or custom data | { "sub": "1234", "exp": 1700003600 } |
| Signature | Green | Cryptographic signature over BASE64URL(header).BASE64URL(payload) | SflKxwRJSMeK… |
🔑 Supported Algorithms
JWS supports three families of cryptographic algorithms. Your choice depends on whether you need a shared secret (symmetric) or a public/private key pair (asymmetric):
| Family | Algorithms | Key Type | Best For |
|---|---|---|---|
| HMAC | HS256, HS384, HS512 | Symmetric secret | Server-to-server where both parties share a secret |
| RSA | RS256, RS384, RS512, PS256, PS384, PS512 | RSA key pair | Public key distribution (OAuth 2.0, OpenID Connect) |
| ECDSA | ES256, ES384, ES512 | EC key pair | Smaller key sizes with equivalent security to RSA |
⚙️ The Three Operation Modes
🔏 Sign Mode
Enter a JSON payload (such as standard JWT claims like sub, iat,exp), select your algorithm, and provide a secret or private key. The tool generates a compact JWS token with a color-coded breakdown of all three parts.
✅ Verify Mode
Paste an existing JWS token and provide the matching secret (for HMAC) or public key (for RSA/EC). The tool cryptographically verifies the signature and clearly shows whether it is valid or invalid — along with the decoded header and payload for inspection.
🔍 Decode Mode
Instantly decode and pretty-print the header and payload of any compact JWS token — no key required. This is invaluable for debugging, inspecting expiry times, checking the algorithm used, or understanding the contents of a token from an API response.
📋 Common JWT Claims Reference
| Claim | Full Name | Description |
|---|---|---|
iss | Issuer | Entity that issued the token (e.g., "auth.myapp.com") |
sub | Subject | Entity the token represents (e.g., a user ID) |
aud | Audience | Intended recipient(s) of the token |
exp | Expiration Time | Unix timestamp after which the token is invalid |
nbf | Not Before | Unix timestamp before which the token is not yet valid |
iat | Issued At | Unix timestamp when the token was issued |
jti | JWT ID | Unique identifier for the token, used to prevent replay attacks |
🛡️ Security Best Practices
- Never use the
nonealgorithm — a token with no signature provides zero authenticity guarantees and is a known attack vector. - Always validate
exp— reject tokens whose expiry timestamp is in the past, even if the signature is valid. - Prefer asymmetric algorithms (RS256, ES256) for public-facing APIs where multiple services need to verify tokens but only one service should sign them.
- Use HMAC (HS256) only when all parties that verify tokens are also trusted to sign them — since the same key can both sign and verify.
- Keep secrets and private keys out of client-side code — tokens should be generated and signed on a secure server, never in the browser in production.
💻 Implementation Examples
// Node.js / Browser — using the 'jose' library
import { SignJWT, jwtVerify, decodeJwt } from 'jose';
// Sign a JWT (JWS with JSON payload)
const secret = new TextEncoder().encode('your-256-bit-secret');
const token = await new SignJWT({ sub: '1234', name: 'Alice' })
.setProtectedHeader({ alg: 'HS256' })
.setIssuedAt()
.setExpirationTime('1h')
.sign(secret);
// Verify a JWT
const { payload } = await jwtVerify(token, secret);
console.log(payload); // { sub: '1234', name: 'Alice', iat: ..., exp: ... }
// Decode without verification (for inspection only)
const claims = decodeJwt(token);
console.log(claims);All cryptographic operations in this tool run entirely in your browser using the jose library backed by the browser's native WebCrypto API — no data is ever sent to a server. Use the Generate Test Key button to quickly create algorithm-appropriate keys for experimentation.