jonasroussel / dart_jsonwebtoken

A dart implementation of the famous javascript library 'jsonwebtoken'
MIT License
87 stars 29 forks source link

Invalid JWT signature for ES256 depending on the generated private key (50% success chance) #34

Closed nblum37 closed 1 year ago

nblum37 commented 1 year ago

Hi,

the following code runs successfully with a chance of around 50%. During every run, a new key pair is generated. It seems to be the sign function, that produces invalid JWT signatures. The generated key pairs are all valid (tested with a python tool chain). If I use the same key pair, then I will also get a deterministic result.

I'm using version 2.6.2

import 'package:basic_utils/basic_utils.dart' as utils;
import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  group('Test jwt generation', () {
    test('Dynamic key pair', () {
      utils.AsymmetricKeyPair<utils.PublicKey, utils.PrivateKey> keyPair = utils.CryptoUtils.generateEcKeyPair();
      utils.ECPublicKey publicKeyNew = keyPair.publicKey as utils.ECPublicKey;
      utils.ECPrivateKey privateKeyNew = keyPair.privateKey as utils.ECPrivateKey;

      // Create a json web token
      var jwt = JWT(
        {'test': 'test'},
      );

      // Get private Key
      var privateKey = ECPrivateKey(utils.CryptoUtils.encodeEcPrivateKeyToPem(privateKeyNew));

      // Sign
      String token = jwt.sign(
        privateKey,
        algorithm: JWTAlgorithm.ES256,
      );
      print('Signed token: $token\n');

      // Get public key
      ECPublicKey publicKey = ECPublicKey(utils.CryptoUtils.encodeEcPublicKeyToPem(publicKeyNew));

      // Verify
      JWT.verify(token, publicKey);
      print('JWT is valid');
    });
  });
}
nblum37 commented 1 year ago

Update: If I replace the import of the PEM by

        String privatePem = utils.CryptoUtils.encodeEcPrivateKeyToPem(privateKeyNew);
        utils.ECPrivateKey loadedKey = utils.CryptoUtils.ecPrivateKeyFromPem(privatePem);
        ECPrivateKey privateKey = ECPrivateKey.raw(loadedKey);

it seems to work. So the internal PEM conversion at the framework seems to cause the issue. A possibility would be to replace the framework's parser parseECPrivateKeyPEM with CryptoUtils.ecPrivateKeyFromPem if it is too hard to find the issue.

jonasroussel commented 1 year ago

Nice ! Thanks for the tip ! Updated in this version : https://pub.dev/packages/dart_jsonwebtoken/versions/2.7.1