0

We need to handle requests from an API gateway. The identity of the user will be passed to us through and encrypted (by private key) JWT token and we received the public key (in Base64) to validate it.

For now I've been failing to do that. What I did manage to do is to encrypt and then again validate my own token using a self generated private/public key:

KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
kp = kpg.generateKeyPair();

//generate & sign simple token:
Map<String, Object> claims = new HashMap<>();
claims.put("id", "xxx");
claims.put("role", "user");
token = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.RS256, kp.getPrivate()).compact();

//now sign the thing
Claims claims = Jwts.parser().setSigningKey(kp.getPublicKey()).parseClaimsJws(base64EncodedToken).getBody();
System.out.println(claims.get("id")); //gives me xxx as expected

No issue here.

Next step was to externalise (file) those generated keys; e.g.:

out = new FileWriter("key.pub");
out.write(encoder.encodeToString(kp.getPublic().getEncoded()));
out.close();

And then instead of using a KeyPairGenerator create the Public/Private keys by reading them from the (Base64) file and decoding them:

public PrivateKey getPrivateKey() throws Exception {
    String base64PrivateKey = new String(Files.readAllBytes(Paths.get(ClassLoader.getSystemResource("private.key").toURI())));
    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec (Base64.getDecoder().decode(base64PrivateKey.getBytes()));
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    return keyFactory.generatePrivate(keySpec);
}

public PublicKey getPublicKey() throws Exception {
    String base64PublicKey = new String(Files.readAllBytes(Paths.get(ClassLoader.getSystemResource("public.key").toURI())));
    X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(base64PublicKey.getBytes()));
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    return keyFactory.generatePublic(keySpec);
}

When I then run the same process again (generate encrypted token & validate it):

Exception in thread "main" io.jsonwebtoken.SignatureException: JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.

I must be missing something since I have little experience with encryption.

P.S. The files are 1 liners likes this:

public.key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxetc3258...

private.key: MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEA...

Stijn Geukens
  • 15,454
  • 8
  • 66
  • 101
  • 5
    Just a note to avoid confusing wording: "decrypting" means **encryption**, but your source is using ""signing**. The **validation** of a (JWS) signature has to be done with the **Public key** and the signature itself is done with the **Private key**. – Michael Fehr May 26 '21 at 21:02
  • are you sure that you are signing /validating with the same keypair? (as already commented, please do not mix signing and encryption) – gusto2 May 26 '21 at 22:16
  • @MichaelFehr thanks for correcting me; what's the correct term to use to 'unsign' a signature? 'validation' does not fully cover this. – Stijn Geukens May 27 '21 at 09:19
  • Regarding your code: you are writing the public key with FileWriter("key.pub") but reading (another?) the key with ClassLoader.getSystemResource("public.key"). If it is another file it would explain the error. Second: a JWT gets **validated** with the public key. The data itself is usually **not encrypted** but **encoded** in Base64Url, so you would name it as **Base64UrlDecoding**. – Michael Fehr May 27 '21 at 11:24
  • Yes, I copy/pasted the key from one file to another during testing; sorry for the confusion – Stijn Geukens May 27 '21 at 15:35

0 Answers0