Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jwt RS256 signature verification failing #170

Closed
oscartrullols opened this issue Jun 25, 2018 · 9 comments
Closed

jwt RS256 signature verification failing #170

oscartrullols opened this issue Jun 25, 2018 · 9 comments

Comments

@oscartrullols
Copy link

I am getting error in JWT RS256 signature verification because the PEM generated from n,e keys is invalid.

jwt signature verification failed: Decode secret is not a valid cert/public key: ASN1 lib: public key decode error: RSA lib: nested asn1 error: bad object header: too long

trying to validate the token with the generated PEM (obtained from the logs) at https://jwt.io/ fails too.

Correct n,e are obtained from the jwk endpoint, but the function that converts it to the PEM public key has some bug. I have done the same conversion (RSA(n,e) ->PEM) using this tool and the obtained public key passes jwt.io validation.

There is only one char that is different between the key created by this library and the valid one,
while your keys always start with:

MIIBIjA...

in my case mine should start with

MIICIjA...

I have seen that this part of the key is hardcoded here:
--PEM KEY FROM PUBLIC KEYS, PASSING 64 BIT ENCODED RSA HEADER STRING WHICH IS SAME FOR ALL KEYS local pem = der2pem(encoded_key,"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A","PUBLIC KEY")

For some reason that string that "is same for all keys" doesn't apply to me?

I'm using Ory hydra as the oauth2 server, that is generating the keys.

Thanks!

@oscartrullols
Copy link
Author

"id_token":"eyJhbGciOiJSUzI1NiIsImtpZCI6InB1YmxpYzplMDEzYWUwOS03MDA1LTQ4MTgtYjA2Zi03Nzc3YmMyYWQ4NjEiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOlsicHJveHktY2xpZW50Il0sImF1dGhfdGltZSI6MTUyOTkzMTY5NywiZXhwIjoxNTI5OTM1MzAxLCJpYXQiOjE1Mjk5MzE3MDEsImlzcyI6Imh0dHA6Ly9oeWRyYTo0NDQ0LyIsImp0aSI6Ijk5NWNlMjUzLTBhMzMtNDRjMi04ZGQ0LWZiOTc2MTM3YTcyMyIsIm5vbmNlIjoiYjg3ZDBhYWFkMzYxNTZjZGQwODcyZWU0NGE5OTFhNDciLCJyYXQiOjE1Mjk5MzE2OTUsInN1YiI6ImZvb0BiYXIuY29tIn0.jVt6pjOXhEdHSM1RTceSoZiw6Wh5qcBIwGZf1GwLkl66V_UPdVXZ4iEevnlQketK9Swfk6Ppc-pycBXm7gxC3HtON5h_aqTpYWdAtEV994d4JQbiTb44ikhN8VWiMBsnVc8Dvqhes6Pa_gtc8m8SWv-fjd7aqr5pe8F_mUcjxqnC_eYyeKzXBZnkLciL565nBcLAKDbUT6mdE0vdROUmLiD2tEnmF659NT4fAd0AEGDULmuCyc5B58kGh0EfnfCYs1ZvuS8CP7oIbb9bf32YjYufqUonZBncOKBTg-mafoVi-hPVo5heHU92P4axMXfoQKr_TCSh-gKK-sRtG6yDSSdoTD7n48fJ9WAVBzeieQ972oM15_VvnBZL7eehTvtnTVo3QBzgDzHlvBIcmaL4C5KgZ-5NMSMPQsT2OYSWslylUl8zmcxaoWnRluKkmQ9s32uNEnbHYlxxghAOMHuTmhZKYLCl6KckONLfpJmUoLVVfmIjxo_SrRI27w9gpBETf_mjIAackKJPWAWbQwdUbqSSrcjw_gpaG0DlPIdQJ2s3HrNENQSzyddB7FxnDJvPeOyHjdZD9yecE-Y164IqByptMaVFjVndpzYyeIUaEHfAE8plz9Ia38rZly_1hqIMyOIBpN9SZcFJ9BFLCWg7tfziS6nr3xQxkZ7FM-8yePY"
n,e:
response data: {"keys":[{"use":"sig","kty":"RSA","kid":"public:e013ae09-7005-4818-b06f-7777bc2ad861","alg":"RS256","n":"quTaXkvbuLcXs1YzBIZCwpGEVKmjfTjpM7PqL68nCRa69snTolO2PzsE3J5GB6LPVuvJza7t8bTd2xGj0dKBiTxnN_Cs4FDkY3-1dczMyUA-iX3kKQY17DA4ySvsTe1dPoxs2vvhWM7XILq_EeeDPSTtuSw2AcJlSwu9jbIkPUzim-vx2niDLJaGR3z_tYWmczkAumtOeSEOL1tBDz68PfRZ7ngNvBcZ8g9Y4mZkLKQ0Sx0Zmr9IFL-n7TNs9vtXvp3NLdDtp2H3hQXd2vRzuKhJBJ99EX6h7M9XL0yfYd3PTC2N0gD3ryZHckak2OYgD6Nv9T-YuEaqG1FJm8JZOJDQnQ5W2Oo4tb84FSzVwdWk5acDjWkBy-bW3O3O1mxv4ZMY2Q_NnwY-AYvBnejWGb_UGtqjJXVTulw2I_mMlY7wekK7vrCekMf4VgjZ4wvgKdXX-l8qHU7Iv0NCK-2lqmyHxDivtE8QyJs_3tkZGmdrsIE4oNlhffoqw4GppjZrkg-_5OTlPuvhVjyYtp3S1m2V8_P4yDlqzgT0-3K2ce_bRASK-rBgmfP_t1k1JpZdkz8iW6YyWzcCVok34mq687cijLyHyHPBWcstwDh5xXhzRgk-K5ZwK6ECPPTzIosCVTmWb84Rln193148qsu86eAsIVCzNp-p6fOLxhD-IdE","e":"AQAB"}]}
Generated pem key from n and e: -----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIICCgKCAgEAquTaXkvbuLcXs1YzBIZC
wpGEVKmjfTjpM7PqL68nCRa69snTolO2PzsE3J5GB6LPVuvJza7t8bTd2xGj0dKB
iTxnN/Cs4FDkY3+1dczMyUA+iX3kKQY17DA4ySvsTe1dPoxs2vvhWM7XILq/EeeD
PSTtuSw2AcJlSwu9jbIkPUzim+vx2niDLJaGR3z/tYWmczkAumtOeSEOL1tBDz68
PfRZ7ngNvBcZ8g9Y4mZkLKQ0Sx0Zmr9IFL+n7TNs9vtXvp3NLdDtp2H3hQXd2vRz
uKhJBJ99EX6h7M9XL0yfYd3PTC2N0gD3ryZHckak2OYgD6Nv9T+YuEaqG1FJm8JZ
OJDQnQ5W2Oo4tb84FSzVwdWk5acDjWkBy+bW3O3O1mxv4ZMY2Q/NnwY+AYvBnejW
Gb/UGtqjJXVTulw2I/mMlY7wekK7vrCekMf4VgjZ4wvgKdXX+l8qHU7Iv0NCK+2l
qmyHxDivtE8QyJs/3tkZGmdrsIE4oNlhffoqw4GppjZrkg+/5OTlPuvhVjyYtp3S
1m2V8/P4yDlqzgT0+3K2ce/bRASK+rBgmfP/t1k1JpZdkz8iW6YyWzcCVok34mq6
87cijLyHyHPBWcstwDh5xXhzRgk+K5ZwK6ECPPTzIosCVTmWb84Rln193148qsu8
6eAsIVCzNp+p6fOLxhD+IdECAwEAAQ==
-----END PUBLIC KEY-----
valid Public key (works fine at jwt.io, the only difference is 4th char B->C ):
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAquTaXkvbuLcXs1YzBIZC
wpGEVKmjfTjpM7PqL68nCRa69snTolO2PzsE3J5GB6LPVuvJza7t8bTd2xGj0dKB
iTxnN/Cs4FDkY3+1dczMyUA+iX3kKQY17DA4ySvsTe1dPoxs2vvhWM7XILq/EeeD
PSTtuSw2AcJlSwu9jbIkPUzim+vx2niDLJaGR3z/tYWmczkAumtOeSEOL1tBDz68
PfRZ7ngNvBcZ8g9Y4mZkLKQ0Sx0Zmr9IFL+n7TNs9vtXvp3NLdDtp2H3hQXd2vRz
uKhJBJ99EX6h7M9XL0yfYd3PTC2N0gD3ryZHckak2OYgD6Nv9T+YuEaqG1FJm8JZ
OJDQnQ5W2Oo4tb84FSzVwdWk5acDjWkBy+bW3O3O1mxv4ZMY2Q/NnwY+AYvBnejW
Gb/UGtqjJXVTulw2I/mMlY7wekK7vrCekMf4VgjZ4wvgKdXX+l8qHU7Iv0NCK+2l
qmyHxDivtE8QyJs/3tkZGmdrsIE4oNlhffoqw4GppjZrkg+/5OTlPuvhVjyYtp3S
1m2V8/P4yDlqzgT0+3K2ce/bRASK+rBgmfP/t1k1JpZdkz8iW6YyWzcCVok34mq6
87cijLyHyHPBWcstwDh5xXhzRgk+K5ZwK6ECPPTzIosCVTmWb84Rln193148qsu8
6eAsIVCzNp+p6fOLxhD+IdECAwEAAQ==
-----END PUBLIC KEY-----

@zandbelt
Copy link
Contributor

zandbelt commented Jun 25, 2018

the difference is in that your public RSA key 4096 bits whereas lua-resty-openidc by default expects 2048 bits; @bodewig we should fix/enhance that indeed

I seem to remember that the original PR had some commented out text to generate that part dynamically but the author couldn't get that to work

@bodewig
Copy link
Collaborator

bodewig commented Jun 25, 2018

Fully agree we should get that fixed, but I'd first need to read up on the format to be of any help.You probably recall https://github.com/zmartzone/lua-resty-openidc/pull/82/files#diff-1c5839bc51fa1aa064c7206dce60fb3eR582

@bodewig
Copy link
Collaborator

bodewig commented Jun 26, 2018

OK, I've dug into it a bit and have tried to understand what the string MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A actually means.

The first few bytes say "this is a sequence of length 290 bytes". For the longer key the "correct" value says "546 bytes" and this is exactly the length of the decoded data following this prefix.

This bitstring then contains a new ASN.1 message that starts with "This is a sequence of length 13 bytes" followed by the "an OID of length 9" and the 9 byte OID assigned to ":rsaEncryption" and an ASN.1 "NULL" with length 0. Next comes a the header that says "a bitstring of length 271 bytes" and in the "correct version" it is "527 bytes".

I'm not sure what the ASN.1 NULL actually does but think we can reconstruct the rest well enough to create the "header" dynamically. I'll give it a try.

bodewig added a commit that referenced this issue Jun 26, 2018
@oscartrullols
Copy link
Author

after applying your commit lua-resty-openidc works fine with Ory hidra's RSA 4096 bits key
Thanks @bodewig @zandbelt for solving it that fast.

@bodewig
Copy link
Collaborator

bodewig commented Jun 26, 2018

Great!

I intend to add a test case which means creating a 4k key and fiddling with openssl to turn it into a JWK which may take some time. Also I think I've got one real test environment where the server returns n/e keys instead of an x5c key claim - I want to test against that before merging to master.

@bodewig
Copy link
Collaborator

bodewig commented Jun 26, 2018

BTW the NULL is the Parameters part of the "AlgorithmIdentifier" defined for PKCS 1 and there was a 0 byte in front of the encoded key that signals "the bitstring uses all bits of the following bytes" in BER's "primitive" encoding.
I've learned quite a bit about ASN.1, BER, DER and PEM along the way, which is a nice side effect.

bodewig added a commit that referenced this issue Jun 26, 2018
@bodewig
Copy link
Collaborator

bodewig commented Jun 26, 2018

Things worked just fine with my test environment so I merged the fix.

@anshudutta
Copy link

Hi guys, I am having the same issue again. I am using kong plugin oidc with ory/hydr as my Oauth sever.
The bug : - #301

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants