JWT woes - crypto issues?

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

JWT woes - crypto issues?

Igor Clark
Hi folks,

I'm trying to use the jwerl library (https://github.com/G-Corp/jwerl) to sign JWTs using the ES384 algorithm, which is required by the system for which I'm generating the token.

It seems to work fine internally; I sign something with my private key, verify the result straight back and it works:

> 30> Claims = #{ blah => <<"load of blah">>, exp => 1612639232 }.
> #{blah => <<"load of blah">>,exp => 1612639232}
> 31> jwerl:sign( Claims, es384, PrivateKey ).
> <<"eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJibGFoIjoibG9hZCBvZiBibGFoIiwiZXhwIjoxNjEyNjM5MjMyfQ.MGYCMQCSNwgjw_i4EVxhRxox"...>>
> 32> jwerl:verify( jwerl:sign( Claims, es384, PrivateKey ), es384, PublicKey ).
> {ok,#{blah => <<"load of blah">>,exp => 1612639232}}


However when the Python code at the other end tries to decode it, using the same public key, it says "Signature verification failed".

I try it the other way round, using the same private key to encode it on the Python side, and the same internal consistency check in the Python library works fine:

> >>> claims
> {'blah': 'load of blah', 'exp': 1612639232}
> >>> jwt.encode( claims, private_key, algorithm="ES384" )
> 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzM4NCJ9.eyJibGFoIjoibG9hZCBvZiBibGFoIiwiZXhwIjoxNjEyNjM5MjMyfQ.FxPVtSx0R8JjgYhoDYmuJKOyE7bY[...]f'
> >>> jwt.decode( jwt.encode( claims, private_key, algorithm="ES384" ), public_key, algorithms=["ES384"] )
> {'blah': 'load of blah', 'exp': 1612639232}


But when I copy the token from the Python output and try to decode it in Erlang/jwerl with the same public key:

> 38> jwerl:verify( PythonJwt, es384, PublicKey ).
> {error,invalid_signature}


So they both can encode and decode the JWT using ECDSASHA384 without problem, but when either of them tries to decode a JWT encoded by the other one, *using the same keys*, it fails.

The reason I'm posting this here rather than on a Python forum is that when I paste the Python-generated JWT into the debuggger at jwt.io, and paste in the public key, I get "Signature Verified". When I paste in the Erlang/jwerl-generated JWT into the same box, with the same key in there, I get "Invalid Signature".

It could obviously be a problem with the jwerl library, but it seems reasonably recently maintained, lots of downloads on hex.pm, etc, etc, and it seems at least internally consistent.

So I'm wondering if it's something to do with the underlying crypto or related packages, or their setup, in my Erlang/OTP? I'm running Erlang/OTP 23 [erts-11.1.7] on MacOS Catalina 10.15.7, and although jwerl compiles and runs, rebar3 shell shows a warning:

> _build/default/lib/jwerl/src/jwerl_hs.erl:7: Warning: crypto:hmac/3 is deprecated and will be removed in OTP 24; use use crypto:mac/4 instead

I've tried several other Erlang JWT libraries, which won't even seem to build because the compile fails with that same warning (I guess this is something to do with warnings as errors, maybe, but I don't know how to switch that off in rebar3) - I've even tried importing Elixir libs but I got nowhere quickly with that. The jwerl library seems to work and is apparently in decently wide use, so there must be something off about my setup or *something*, given that interoperability is pretty much the point of JWT, and this is falling at the first hurdle.

Anyone got any ideas? Would really appreciate a pointer on how to track down what's going wrong!

Thanks,
Igor
Reply | Threaded
Open this post in threaded view
|

Re: JWT woes - crypto issues?

Igor Clark
Thanks Łukasz,

I could have made a mistake for sure! But I'm as sure as I can be - that was pretty much the first thing I checked.

The Python is using the base64-encoded string copied from the PEM file, which works, generating JWTs that jwt.io validates successfully from the paired public key.

The Erlang jwerl code is using the same base64-encoded string in a binary (ie <<"-----BEGIN EC PRIVATE KEY-----\nMIGkAgEBBDAt8OrDBu"...>>), because that's the only way the library would accept it, and because when I looked in the code for jwerl I saw it was using public_key:decode_pem/1 directly on the passed-in key, so it seemed like that was the right format to use.

Cheers,
Igor

> On 5 Feb 2021, at 19:47, Łukasz Niemier <[hidden email]> wrote:
>
> Are you sure that the secret is the same and is passed in the format that both libraries expect? Because one may require Base64 encoded string and other will require to pass raw data.
>
> --
> Łukasz Jan Niemier

Reply | Threaded
Open this post in threaded view
|

Re: JWT woes - crypto issues?

Igor Clark
Yes just checked again to be 100% sure. Using identical keys, literally copy-pasted from one to the other, the Python library generates token signatures that it validates itself and which are validated by jwt.io with the public key, but which the erlang one says is invalid, with the same key; the erlang one generates token signatures that it validates itself, but which python and jwt.io say are invalid. I guess it's looking more and more like it's just the jwerl lib, or just the es384 routine, but that still makes me wonder if it's something about the underlying crypto stuff being used.

However, just to check, I ran the erlang version in a docker image with Debian 10, and that had exactly the same problem. So probably not to do with underlying OS crypto if it's the same on both ...

Really puzzled!

> On 5 Feb 2021, at 20:10, Igor Clark <[hidden email]> wrote:
>
> Thanks Łukasz,
>
> I could have made a mistake for sure! But I'm as sure as I can be - that was pretty much the first thing I checked.
>
> The Python is using the base64-encoded string copied from the PEM file, which works, generating JWTs that jwt.io validates successfully from the paired public key.
>
> The Erlang jwerl code is using the same base64-encoded string in a binary (ie <<"-----BEGIN EC PRIVATE KEY-----\nMIGkAgEBBDAt8OrDBu"...>>), because that's the only way the library would accept it, and because when I looked in the code for jwerl I saw it was using public_key:decode_pem/1 directly on the passed-in key, so it seemed like that was the right format to use.
>
> Cheers,
> Igor
>
>> On 5 Feb 2021, at 19:47, Łukasz Niemier <[hidden email]> wrote:
>>
>> Are you sure that the secret is the same and is passed in the format that both libraries expect? Because one may require Base64 encoded string and other will require to pass raw data.
>>
>> --
>> Łukasz Jan Niemier
>

Reply | Threaded
Open this post in threaded view
|

Aw: JWT woes - crypto issues?

Michael Schreckenbauer
In reply to this post by Igor Clark
Hi,
 
> I've tried several other Erlang JWT libraries, which won't even seem to build because the compile fails with that same warning (I guess this is something to do with warnings as errors, maybe, but I don't know how to switch that off in rebar3) - I've even tried importing Elixir libs but I got nowhere quickly with that. The > jwerl library seems to work and is apparently in decently wide use, so there must be something off about my setup or *something*, given that interoperability is pretty much the point of JWT, and this is falling at the first hurdle.

> Anyone got any ideas? Would really appreciate a pointer on how to track down what's going wrong!

> Thanks,
> Igor
 
I used https://github.com/artemeff/jwt about a year ago and it worked fine for me.

Michael
Reply | Threaded
Open this post in threaded view
|

Re: JWT woes - crypto issues?

Leonard Boyce-2
Michael, one small issue with https://github.com/artemeff/jwt

It does not support ES384
See: https://github.com/artemeff/jwt/blob/master/src/jwt.erl#L47

On Sat, Feb 6, 2021 at 2:02 PM <[hidden email]> wrote:

>
> Hi,
>
> > I've tried several other Erlang JWT libraries, which won't even seem to build because the compile fails with that same warning (I guess this is something to do with warnings as errors, maybe, but I don't know how to switch that off in rebar3) - I've even tried importing Elixir libs but I got nowhere quickly with that. The > jwerl library seems to work and is apparently in decently wide use, so there must be something off about my setup or *something*, given that interoperability is pretty much the point of JWT, and this is falling at the first hurdle.
>
> > Anyone got any ideas? Would really appreciate a pointer on how to track down what's going wrong!
>
> > Thanks,
> > Igor
>
> I used https://github.com/artemeff/jwt about a year ago and it worked fine for me.
>
> Michael
Reply | Threaded
Open this post in threaded view
|

Re: JWT woes - crypto issues?

Igor Clark
Thanks very much Michael and Leonard for your replies!

ES384 is mandated by the service I'm generating the tokens for ( Amazon IVS https://docs.aws.amazon.com/ivs/latest/userguide/private-channels-generate-tokens.html ).

On the assumption the problem not anything to do with the erlang/SSL version, or similar, but rather just an issue with jwerl, I've submitted an issue on jwerl's gitlab repo (as the Github one seems to be just a mirror), with sample code, keys and outputs: https://gitlab.com/glejeune/jwerl/-/issues/17

I'd be delighted if anybody here has any more light to throw on the matter, but hopefully will hear something back from the Gitlab issue. Will close the loop on this message FYI if so.

Thanks, all, for your time -
Igor

> On 6 Feb 2021, at 19:44, Leonard B <[hidden email]> wrote:
>
> Michael, one small issue with https://github.com/artemeff/jwt
>
> It does not support ES384
> See: https://github.com/artemeff/jwt/blob/master/src/jwt.erl#L47
>
> On Sat, Feb 6, 2021 at 2:02 PM <[hidden email]> wrote:
>>
>> Hi,
>>
>>> I've tried several other Erlang JWT libraries, which won't even seem to build because the compile fails with that same warning (I guess this is something to do with warnings as errors, maybe, but I don't know how to switch that off in rebar3) - I've even tried importing Elixir libs but I got nowhere quickly with that. The > jwerl library seems to work and is apparently in decently wide use, so there must be something off about my setup or *something*, given that interoperability is pretty much the point of JWT, and this is falling at the first hurdle.
>>
>>> Anyone got any ideas? Would really appreciate a pointer on how to track down what's going wrong!
>>
>>> Thanks,
>>> Igor
>>
>> I used https://github.com/artemeff/jwt about a year ago and it worked fine for me.
>>
>> Michael

Reply | Threaded
Open this post in threaded view
|

Re: JWT woes - crypto issues?

Igor Clark
Just to close the loop here, Leonard very kindly sent me a patch that makes the 'jwt' library support ES384, so I'm going to go ahead and use that instead. Wonderful.

Thanks Leonard, and thanks list,

best,
Igor

> On 7 Feb 2021, at 12:01, Igor Clark <[hidden email]> wrote:
>
> Thanks very much Michael and Leonard for your replies!
>
> ES384 is mandated by the service I'm generating the tokens for ( Amazon IVS https://docs.aws.amazon.com/ivs/latest/userguide/private-channels-generate-tokens.html ).
>
> On the assumption the problem not anything to do with the erlang/SSL version, or similar, but rather just an issue with jwerl, I've submitted an issue on jwerl's gitlab repo (as the Github one seems to be just a mirror), with sample code, keys and outputs: https://gitlab.com/glejeune/jwerl/-/issues/17
>
> I'd be delighted if anybody here has any more light to throw on the matter, but hopefully will hear something back from the Gitlab issue. Will close the loop on this message FYI if so.
>
> Thanks, all, for your time -
> Igor
>
>> On 6 Feb 2021, at 19:44, Leonard B <[hidden email]> wrote:
>>
>> Michael, one small issue with https://github.com/artemeff/jwt
>>
>> It does not support ES384
>> See: https://github.com/artemeff/jwt/blob/master/src/jwt.erl#L47
>>
>> On Sat, Feb 6, 2021 at 2:02 PM <[hidden email]> wrote:
>>>
>>> Hi,
>>>
>>>> I've tried several other Erlang JWT libraries, which won't even seem to build because the compile fails with that same warning (I guess this is something to do with warnings as errors, maybe, but I don't know how to switch that off in rebar3) - I've even tried importing Elixir libs but I got nowhere quickly with that. The > jwerl library seems to work and is apparently in decently wide use, so there must be something off about my setup or *something*, given that interoperability is pretty much the point of JWT, and this is falling at the first hurdle.
>>>
>>>> Anyone got any ideas? Would really appreciate a pointer on how to track down what's going wrong!
>>>
>>>> Thanks,
>>>> Igor
>>>
>>> I used https://github.com/artemeff/jwt about a year ago and it worked fine for me.
>>>
>>> Michael
>