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

Token signature with ES512 is invalid #51

Closed
nassbe opened this issue Jan 22, 2024 · 3 comments
Closed

Token signature with ES512 is invalid #51

nassbe opened this issue Jan 22, 2024 · 3 comments

Comments

@nassbe
Copy link

nassbe commented Jan 22, 2024

Hi Guys,
i'm currently implementing a test app that creates JWT for testing purposes. I want to use ES512 algorithm and a given private key and certChain from my "counterpart" for first testing. This key has a size of 521 bits as it is the standard for ES512.

My Problem

The problem is, that JWT.sign() constantly returns tokens with invalid signatures according to jwt.io and also (in perhaps 3 out of 4 cases) according to JWT.verify(). I checked multiple times that the key and certChain are a valid pair and the header and payload are handed over correctly.

My Analysis

I took a closer look at the difference between the signatures and the first thing i noticed was that the signature from jwt.io is constantly 176 characters long while the signature from my app had only 174 characters. After taking a closer look into the implementation of the ECDSAAlgorithm's sign function in algorithms.dart, i noticed that the signature get's "cut" to privateKey.size*2 bytes
image
(in this case 130 bytes), although it should be 132 bytes (at least that's how it worked fine). I guess this is because the size of the key is actually 65.125 bytes so the S and R part of the signature that's returned by signer.generateSignature() can have a length of 66 bytes (that can be observed by using different payloads), but i'm really not an expert at this topic ;)

My Fix

I set the size of my bytes list to 132 (using (privateKey.key.parameters!.curve.fieldSize/8).ceil()*2, probably not the best way but it worked out for me). Because the bigInts that are returned by signer.generateSignature() can have a length of 65 or 66 bytes after converting them into Uint8Lists, i filled the byte-List like that:
image

This way i got signatures with always the same length that are simply filled with 0 at the first (or middle) position if the rBytes or sBytes isn't long enough. The created tokens are always valid according to jwt.io and jwt.verify() now.

I hope i provided you enough information to understand my problem :)
Unfortunately i could really not use the library with my key to get valid tokens so maybe this issue is relevant for other people as well

@jonasroussel
Copy link
Owner

jonasroussel commented Feb 11, 2024

Hi @nassbe,

Thank you for your detailed analysis. I have reviewed your findings, and your approach seems to work well. In fact, 3 years ago when implementing the signature process to follow the RFC 7519, I realized that I forgot to implement the padding required for keys that are not a multiple of 8.

I will publish a new patch with your fix soon. Once the patch is deployed, please feel free to test it on your end and let me know if everything is working as expected.

@jonasroussel
Copy link
Owner

And this is the new published version: https://pub.dev/packages/dart_jsonwebtoken/versions/2.13.0

@nassbe
Copy link
Author

nassbe commented Feb 12, 2024

After a few tests, it looks like everything is working perfectly. Thanks! 😄

@nassbe nassbe closed this as completed Feb 12, 2024
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

2 participants