Decrypting JWT signatures

I’m going to ask forgiveness if this is only barely related to keycloak however I’m encountering this problem in the context of keycloak JWTs and figured that people here would probably be well familiar with JWTs in general. Someone asked me to write some documentation explaining the steps of how to manually verify a jwt (in the specific context of a JWT returned from keycloak) and provide coding examples so that we can provide documentation to developers using our keycloak. I didn’t think much of it as I thought I understood how signature verification in general worked and had done things with it in the past. However as I began working on it I started to run into odd issues that lead me to believe that I must have some basic misunderstanding of how this process works.

The challenge comes from the fact that I’d always largely allowed various programing libraries to handle the verification for me but my requirements specify that I must go through the steps in as individual a fashion as possible (the idea being that this will make it easier for the process to be replicated in whatever language the clients developers prefer). So while I might have in previous efforts I might have just used something like pythons jwt.verify() I’m supposed to break it down further incase that’s not an option.

My basic understanding of these basic steps of verification is that it goes something like this:
–Decode the JWTs body and header (they’re typically base64 encoded). Take a hash of the decoded body/header
–Use the public key to decrypt the signature (if using a library that doesn’t let you decrypt with a public key just use the encryption method instead, it should have the same effect on something encrypted with the private key)
–Compare the hash you calculated against the decrypted signature, if they match you’ve verified the sender.
–At this point you also verify expiration date and other claims as required by circumstance.

The issue I’m having is that my attempts to decrypt the signature I keep running into issues. I have a keycloak running and I can get access token JWTs from it without issue. I have verified with jwt.io and jwt.verify() that these jwt are signed by the RSA key I can see in the admin panel for keycloak. However in my numerous attempts to employ various encrypt/decrypt methods based on the public key I get from the GUI I get told things along the lines of ‘The Plaintext is too long’ or otherwise indications that the key I’m using isn’t large enough to encrypt the signature I’m feeding the code.
–I considered that maybe I’d been misremembering and the signature was base64 encoded as well but when I tried decoding it the outputs I was getting either told me that the input was invalid or gave results that didn’t look like a hash.
–Obviously it is possible to verify the JWT with the public key (else how would jwt.verify() or jwt.io do it) however after a considerable amount of searching I haven’t been able to find anything on why I am not able to directly decrypt the signature or what other steps I might need to take first.

If anyone knows what I’m missing, I’d appreciate hearing about it.

The JWT’s three parts are not base64 encoded. They are base64URL encoded. Thats a small but relevant difference:

Do you have the source code of python jwt.verify()? With that, you could watch what the library is doing…