jwt icon indicating copy to clipboard operation
jwt copied to clipboard

Invalid signing with SHA256 alg using secp521r1 curve

Open KartaviK opened this issue 4 years ago • 8 comments

Generate key with next command

/: openssl ecparam -name secp521r1 -genkey -noout -out key.pem

With package i use sha256 to sign the payload

use Lcobucci\JWT\Signer\Ecdsa\Sha256;
use Lcobucci\JWT\Signer\Key\InMemory;

$payload = 'data';
$signer = Sha256::create();
$key = InMemory::file('/key.pem');

$sign = $signer->sign($payload, $key);

echo mb_strlen(bin2hex($sig), '8bit'); // by python libraries always 264, here can be 260/262/264

echo $signer->verify($sign, $message, $payload); // must be true, exception throws instead that signature has invalid length

But interesting thing, when out signature has length 264, python package validates its successfully, when the $signer always failing it

KartaviK avatar Mar 17 '21 13:03 KartaviK

That sounds quite weird. Let's try to reproduce this in the functional test suite and take it from there.

Would you be able to send a PR?

lcobucci avatar Mar 17 '21 18:03 lcobucci

Ok, ill make a pr next day

KartaviK avatar Mar 27 '21 21:03 KartaviK

I've managed to reproduce this... The openssl signature is matching the key curve... so OPENSSL_ALGO_SHA??? is creating some funky behaviour in OpenSSL.

lcobucci avatar Aug 05 '22 13:08 lcobucci

I've found the issue... The implementation is using a fixed length based on the hashing algorithm for the signature and based on the python implementation, this comes from the key instead: https://github.com/lepture/authlib/blob/5dabbdd83801708ca9d81b4c1dda203a37ddf11f/authlib/jose/rfc7518/jws_algs.py#L131

lcobucci avatar Aug 09 '22 21:08 lcobucci

What I wonder here is if the premise makes sense...

As per https://www.rfc-editor.org/rfc/rfc7518#section-3.4:

The following "alg" (algorithm) Header Parameter values are used to indicate that the JWS Signature is a digital signature value computed using the corresponding algorithm:

"alg" Param Value Digital Signature Algorithm
ES256 ECDSA using P-256 and SHA-256
ES384 ECDSA using P-384 and SHA-384
ES512 ECDSA using P-521 and SHA-512

So, in theory, SHA-256 should only accept keys using P-256 keys.

@Spomky what's your take on this? I reckon we share the same implementation for the conversion so this is probably affecting you too :smile:

lcobucci avatar Aug 09 '22 21:08 lcobucci

@Slamdunk I'm holding 4.2.0 because of this... we may have introduced the wrong validation for ECDSA :)

lcobucci avatar Aug 09 '22 21:08 lcobucci

So, in theory, SHA-256 should only accept keys using P-256 keys.

Correct. This comes from the RFC5480 section 4 where "It is recommended that the bits of security provided by each choice are roughly équivalent". MD5 hash function could be used with curve P-521 keys, but with the RFC7518 it is not permitted to use other hashing function than SHA-512 with a P-521 key (sha-256 with P-256 and sha-384 with P-384).

Spomky avatar Aug 09 '22 22:08 Spomky

Thanks, @Spomky!

I'll update the key validation for the ES-* family then :+1:

lcobucci avatar Aug 09 '22 22:08 lcobucci