The problem: no exposed public key
Algorithm confusion requires knowing the server's RSA public key. Most servers expose it at /.well-known/jwks.json - but some don't. Even without a public JWKS endpoint, the public key can be recovered mathematically from two JWT signatures produced by the same private key. This technique was formalised by PortSwigger Research in 2022 as a prerequisite step for algorithm confusion attacks against servers that hide their public key.
Mathematical foundation
RSA-PKCS#1v1.5 signatures have the form: s ≡ m^d (mod n) where m is the padded message hash,d is the private exponent, and n is the public modulus.
Given a signature s and message m with public exponent e = 65537: s^e ≡ m (mod n) which means n | (s^e - m) . For two signature/message pairs (s1, m1) and (s2, m2), the modulus ndivides both (s1^e - m1) and (s2^e - m2). Therefore n divides their GCD:
How many signatures?
In theory, two signatures suffice. In practice:
- Two signatures from a 2048-bit key reliably produce the correct modulus in most cases
- The GCD may return a multiple of
n- testing bothnand small multiples resolves this - Three or four signatures reduce ambiguity and handle edge cases
- All signatures must come from the same private key (same server, same key rotation period)
Using rsa_sign2n
The rsa_sign2n tool by Silent Signal automates the entire recovery process. It accepts two or more JWTs, extracts signature and message bytes, computes the GCD, and outputs candidate public key PEM files:
Reconstructing the full public key
The recovery gives the modulus n. The public exponent eis almost universally 65537 (0x10001). Reconstructing the PEM:
Chaining to algorithm confusion
Once the public key is recovered, the complete attack chain is:
n or 2n. Test each candidate against the target - only the correct one will produce a verifiable forged token.ECDSA - why recovery doesn't apply
ECDSA signatures use a random nonce k per signature. Two signatures from the same private key produce mathematically independent results - there is no GCD relationship exploitable for key recovery. However, if the RNG is weak or deterministic and produces the same ktwice (as in the PlayStation 3 failure), the private key can be recovered via the lattice attack. This is a separate class of vulnerability.
- Confirmed viable attack chain by PortSwigger Research (2022) against RS256 JWTs
- Requires only two valid JWTs from the target - obtainable by logging in twice
- The recovered key enables algorithm confusion without server cooperation
- Particularly impactful against servers that use RS256 but have no JWKS endpoint and no algorithm enforcement
Mitigations
- Enforce
algorithms=["RS256"]server-side - key recovery only enables algorithm confusion if the server accepts HS256 - This attack is entirely mitigated by strict algorithm enforcement; key recovery alone does not compromise RS256 verification
- Rotate signing keys periodically - limits the window during which recovered keys remain valid
- Use RSA-PSS (PS256) instead of PKCS#1v1.5 (RS256) - PSS randomises padding, though key recovery still works since e and n are the same