fromJWK static method

JWTKey fromJWK(
  1. Map<String, dynamic> jwk
)

Parse a JWK JSON object into any valid JWTKey,

Including SecretKey, RSAPrivateKey, RSAPublicKey, ECPrivateKey, ECPublicKey, EdDSAPrivateKey and EdDSAPublicKey.

Throws a JWTParseException if the JWK is invalid or unsupported.

Implementation

static JWTKey fromJWK(Map<String, dynamic> jwk) {
  if (jwk['kty'] == 'oct') {
    final key = base64Padded(jwk['k']);

    return SecretKey(key, isBase64Encoded: true);
  }

  if (jwk['kty'] == 'RSA') {
    // Private key
    if (jwk['p'] != null &&
        jwk['q'] != null &&
        jwk['d'] != null &&
        jwk['n'] != null) {
      final p = bigIntFromBytes(base64Url.decode(base64Padded(jwk['p'])));
      final q = bigIntFromBytes(base64Url.decode(base64Padded(jwk['q'])));
      final d = bigIntFromBytes(base64Url.decode(base64Padded(jwk['d'])));
      final n = bigIntFromBytes(base64Url.decode(base64Padded(jwk['n'])));

      return RSAPrivateKey.raw(pc.RSAPrivateKey(n, d, p, q));
    }

    // Public key
    if (jwk['e'] != null && jwk['n'] != null) {
      final e = bigIntFromBytes(base64Url.decode(base64Padded(jwk['e'])));
      final n = bigIntFromBytes(base64Url.decode(base64Padded(jwk['n'])));

      return RSAPublicKey.raw(pc.RSAPublicKey(n, e));
    }

    throw JWTParseException('Invalid JWK');
  }

  if (jwk['kty'] == 'EC') {
    final crv = jwk['crv'];

    if (!['P-256', 'P-384', 'P-521', 'secp256k1'].contains(crv)) {
      throw JWTParseException('Unsupported curve');
    }

    // Private key
    if (jwk['d'] != null) {
      final d = bigIntFromBytes(base64Url.decode(base64Padded(jwk['d'])));

      return ECPrivateKey.raw(pc.ECPrivateKey(
        d,
        pc.ECDomainParameters(curveNISTToOpenSSL(crv)),
      ));
    }

    // Public key
    if (jwk['x'] != null && jwk['y'] != null) {
      final x = bigIntFromBytes(base64Url.decode(base64Padded(jwk['x'])));
      final y = bigIntFromBytes(base64Url.decode(base64Padded(jwk['y'])));

      final params = pc.ECDomainParameters(curveNISTToOpenSSL(crv));

      return ECPublicKey.raw(pc.ECPublicKey(
        ecc_fp.ECPoint(
          params.curve as ecc_fp.ECCurve,
          params.curve.fromBigInteger(x) as ecc_fp.ECFieldElement?,
          params.curve.fromBigInteger(y) as ecc_fp.ECFieldElement?,
          false,
        ),
        params,
      ));
    }

    throw JWTParseException('Invalid JWK');
  }

  if (jwk['kty'] == 'OKP') {
    final crv = jwk['crv'];

    if (crv != 'Ed25519') throw JWTParseException('Unsupported curve');

    // Private key
    if (jwk['d'] != null && jwk['x'] != null) {
      final d = base64Url.decode(base64Padded(jwk['d']));
      final x = base64Url.decode(base64Padded(jwk['x']));

      return EdDSAPrivateKey(
        Uint8List(d.length + x.length)
          ..setAll(0, d)
          ..setAll(d.length, x),
      );
    }

    // Public key
    if (jwk['x'] != null) {
      final x = base64Url.decode(base64Padded(jwk['x']));

      return EdDSAPublicKey(x);
    }

    throw JWTParseException('Invalid JWK');
  }

  throw JWTParseException('Unsupported key type');
}