Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Verifying JWT (RS256) using OpenSSL

My requirement is verifying a JWT using public key (RS256). The check should be based on native OpenSSL only.

I use JWT.IO initial content for testing. This token was generated:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.POstGetfAytaZS82wHcjoTyoqhMyxXiWdR7Nn7A29DNSl0EiXLdwJ6xC6AfgZWF1bOsS_TuYI3OG85AmiExREkrS6tDfTQ2B3WXlrr-wp5AokiRbz3_oB4OxG-W9KcEEbDRcZc0nH3L7LzYptiy1PtAylQGxHTWZXtGz4ht0bAecBgmpdgXMguEIcoqPJ1n3pIWk_dUZegpqx0Lka21H6XxUTxiy8OcaarA8zdnPUnV6AmNP3ecFawIFYdvJB_cm-GvpCSbr8G8y_Mllj8f4x9nBH8pQux89_6gUY618iYv7tuPWBFfEbLxtF2pZS6YC1aSfLQxeNe8djT9YjpvRZA

When I enter Header + Payload + Signature (items 1 and 2 in the picture below) with points between them. Next, I enter a Public key (item 3 in the picture). As result I see message ‘Signature verified’ (item 4 in the picture).

Now I want to get same result using OpenSSL.

I have performed steps:

  1. Create text file /tmp/pub.pem and past below content into it (copied from JWT.IO test case):

-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSv vkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHc aT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIy tvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0 e+lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWb V6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9 MwIDAQAB -----END PUBLIC KEY-----

  1. Create text file data /tmp/data.txt and past below content into it. This is Header and Payload separated by point (item 1 from picture) :

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0

  1. Create text file data /tmp/signature.txt and past below content into it (this is item 2 from picture):

POstGetfAytaZS82wHcjoTyoqhMyxXiWdR7Nn7A29DNSl0EiXLdwJ6xC6AfgZWF1bOsS_TuYI3OG85AmiExREkrS6tDfTQ2B3WXlrr-wp5AokiRbz3_oB4OxG-W9KcEEbDRcZc0nH3L7LzYptiy1PtAylQGxHTWZXtGz4ht0bAecBgmpdgXMguEIcoqPJ1n3pIWk_dUZegpqx0Lka21H6XxUTxiy8OcaarA8zdnPUnV6AmNP3ecFawIFYdvJB_cm-GvpCSbr8G8y_Mllj8f4x9nBH8pQux89_6gUY618iYv7tuPWBFfEbLxtF2pZS6YC1aSfLQxeNe8djT9YjpvRZA

  1. I run OpenSSL command:

    openssl dgst -verify /tmp/pub.pem -keyform PEM -sha256 -signature /tmp/signature.txt -binary /tmp/data.txt
    

    But get result:

    Verification Failure.

What exactly am I doing wrong ?

like image 368
Igor Avatar asked Oct 31 '25 15:10

Igor


1 Answers

I found this gist quite useful in going from a starting JWT to breaking it into parts, decoding certain bits, and then verifying the payload against the signature. It uses openssl and perl which should come with most Bash implementations.

I'll paste my 'short' version of the same thing. In my case I'm verifying a JWT from Auth0.

# The JWT itself
jwt=eyJ...

# Get Auth0's public certificate
curl https://your_auth0_domain/pem > auth0publiccert.pem

# Extract the public key from the public certificate
openssl x509 -pubkey -noout -in auth0publiccert.pem > auth0publickey.pem

# Extract the input payload
input=${jwt%.*}
echo -n $input > payload.txt

# Extract the signature portion
encSig=${jwt##*.}

# Decode the signature
echo -n $encSig | perl -ne 'tr|-_|+/|; print "$1\n" while length>76 and s/(.{0,76})//; $_ .= ("", "", "==", "=")[length($_) % 4]; print' | openssl enc -base64 -d > signature.dat

# Finally, verify
openssl dgst -sha256 -verify auth0publickey.pem -signature signature.dat payload.txt
#Output should be "Verified OK"
like image 83
Mendhak Avatar answered Nov 04 '25 02:11

Mendhak



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!