keepcalculator

06 Numbers and Powers

JWT Algorithm Check: HS256 vs RS256

Card No. 06·4863 · Updated · Standard formula, shown below

To check which JWT algorithm your provider uses, decode the token’s header and look at the alg field — it will say either HS256 or RS256. You can do this by pasting the token into a debugger like jwt.io or by running a simple command in your terminal; the header is the first of the three dot-separated parts of any JWT.

What HS256 and RS256 Actually Are

HS256 and RS256 are the two most common signing algorithms for JSON Web Tokens (JWTs). They both produce a signature that proves the token was issued by someone who knows a secret, but they use fundamentally different cryptographic approaches.

  • HS256 (HMAC with SHA-256) is a symmetric algorithm. The same secret key is used to sign the token and to verify it. The server that issues the token and the server that validates it must share that exact key.
  • RS256 (RSA with SHA-256) is an asymmetric algorithm. A private key signs the token, and a separate public key verifies it. The public key can be shared widely, while the private key stays secret on the issuing server.

This difference matters because it affects how you validate the token and how you manage keys. With HS256, anyone who has the verification key can also forge tokens, because the same key signs. With RS256, the verification key is public, so it can be distributed without compromising the ability to create new tokens.

How to Decode the JWT Header

Every JWT has three parts separated by dots: header.payload.signature. The header is a base64url-encoded JSON object that contains the algorithm. Here’s how to see it in a few common environments.

Using a browser or online tool: Go to jwt.io, paste the entire token into the left panel, and the decoded header appears immediately. The alg field will show HS256 or RS256 (or something else).

Using the command line (Linux/macOS): Copy the token and split it on the dots. The first part is the header. Decode it with base64:

echo '<header_part>' | base64 -d 2>/dev/null || echo '<header_part>' | base64 -D 2>/dev/null

On Linux, use -d; on macOS, use -D. If the output looks like garbled text, add padding with = characters until the length is a multiple of 4, or use a tool that handles base64url automatically.

Using Python: A quick one-liner:

import base64, json
token = "<your_token>"
header = token.split('.')[0]
header += '=' * (4 - len(header) % 4)
print(json.loads(base64.urlsafe_b64decode(header)))

This prints the full header, including the alg field.

Why the Algorithm Matters

Knowing which algorithm your provider uses is not just trivia — it determines how you must verify the token. If you get this wrong, your application will either reject valid tokens or, worse, accept forged ones.

  • HS256 verification requires the same secret key that the issuer used. That key must be stored securely on every server that validates tokens. If an attacker obtains the key, they can mint their own tokens.
  • RS256 verification requires the issuer’s public key. You can fetch it from a well-known URL (like /.well-known/jwks.json) and use it to check the signature. The private key never leaves the issuer.

Many identity providers (like Auth0, Okta, or Azure AD) use RS256 because it allows any client to verify tokens without sharing a secret. If you are using a third-party provider, it is almost certainly RS256. If you are using a simple internal service, it might be HS256.

How to Verify the Signature Correctly

Once you know the algorithm, you must verify the signature using the correct method. Here’s what each requires.

For HS256: You need the secret key. In most libraries, you pass the key as a string or buffer. For example, in Node.js with the jsonwebtoken package:

jwt.verify(token, 'your-secret-key')

For RS256: You need the public key, usually in PEM format or as a JWK. In Node.js:

const publicKey = fs.readFileSync('public.pem')
jwt.verify(token, publicKey, { algorithms: ['RS256'] })

Always specify the expected algorithm in your verification call. Many libraries allow you to pass an algorithms array. This prevents an attack where an attacker changes the algorithm in the header to none or to HS256 and signs with the public key (which is public) to fool a verifier that expects RS256.

Common Problems and Misconceptions

There are several pitfalls that trip up developers when dealing with JWT algorithms.

  • Mixing up the key type: Using a public key to verify an HS256 token will fail, because HS256 expects a symmetric secret, not an RSA public key. Conversely, using a secret string to verify RS256 will also fail.
  • Not checking the algorithm: If your verifier doesn’t force the algorithm, an attacker can change the header to none (no signature) or switch to HS256 and sign with the public key. Always pin the allowed algorithms.
  • Assuming all providers use RS256: Some legacy systems and internal services still use HS256. Always check the header rather than assuming.
  • Forgetting that the header is base64url, not base64: The header uses URL-safe characters (- and _) instead of + and /. If you decode with standard base64, you may get errors.

How to Choose Between HS256 and RS256

If you are designing a system that issues and verifies its own tokens, the choice depends on your architecture.

  • Choose HS256 when you have a single server or a small cluster that shares a secret. It is faster and simpler, but the secret must be kept absolutely private.
  • Choose RS256 when you have multiple services that need to verify tokens independently, or when you want to allow third parties to verify without sharing secrets. The public key can be distributed freely, and the private key stays with the issuer.

For most modern applications, RS256 is the safer default because it limits the blast radius if a verifier is compromised. The public key is useless for forging tokens.

Frequently Asked Questions

Can I use the same secret for HS256 and RS256?

No. HS256 uses a symmetric key (a random string of bytes), while RS256 uses an RSA key pair (private and public). They are different key types and cannot be interchanged.

What if the header shows a different algorithm, like ES256?

ES256 is ECDSA with SHA-256, another asymmetric algorithm. The verification process is similar to RS256 but uses an EC public key. The same rules apply: check the algorithm and use the correct key type.

Is it safe to paste my JWT into jwt.io?

For tokens that are meant to be public (like ID tokens that contain non-sensitive claims), it’s generally fine. However, if the token contains sensitive data or is a long-lived access token, avoid pasting it into any online tool. Use a local script instead.

How do I get the public key for RS256 verification?

Most providers publish their public keys at a URL like https://your-provider.com/.well-known/jwks.json. This JSON file contains one or more JWK objects with the n and e values. Your JWT library can usually fetch and use them automatically.

What happens if I verify an HS256 token with an RS256 public key?

Verification will fail because the signature was created with HMAC, not RSA. The library will throw an error, and the token will be rejected.

Can an attacker change the algorithm from RS256 to HS256?

They can change the header, but the signature will not match. Unless the verifier is misconfigured to accept HS256 without checking the key type, the attack will fail. Always pin the allowed algorithms in your verification code.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →