mirror of
https://github.com/jonasroussel/dart_jsonwebtoken.git
synced 2025-05-17 08:05:54 +08:00
feat: Add JWTKey.fromJWK method for parsing JWK to various key types
This commit is contained in:
@ -127,15 +127,24 @@ String curveOpenSSLToNIST(String curveName) {
|
||||
return "P-384";
|
||||
case "secp521r1":
|
||||
return "P-521";
|
||||
case "secp192r1":
|
||||
return "P-192";
|
||||
case "secp224r1":
|
||||
return "P-224";
|
||||
default:
|
||||
return curveName; // Return the original name if not found
|
||||
}
|
||||
}
|
||||
|
||||
String curveNISTToOpenSSL(String curveName) {
|
||||
switch (curveName) {
|
||||
case "P-256":
|
||||
return "prime256v1";
|
||||
case "P-384":
|
||||
return "secp384r1";
|
||||
case "P-521":
|
||||
return "secp521r1";
|
||||
default:
|
||||
return curveName;
|
||||
}
|
||||
}
|
||||
|
||||
ECDSAAlgorithm? ecCurveToAlgorithm(String curveName) {
|
||||
switch (curveName) {
|
||||
case "P-256":
|
||||
|
@ -3,6 +3,7 @@ import 'dart:typed_data';
|
||||
|
||||
import 'package:ed25519_edwards/ed25519_edwards.dart' as ed;
|
||||
import 'package:pointycastle/pointycastle.dart' as pc;
|
||||
import 'package:pointycastle/ecc/ecc_fp.dart' as ecc_fp;
|
||||
|
||||
import 'algorithms.dart';
|
||||
import 'exceptions.dart';
|
||||
@ -10,7 +11,114 @@ import 'helpers.dart';
|
||||
import 'key_parser.dart';
|
||||
|
||||
abstract class JWTKey {
|
||||
/// Convert the key to a JWK JSON object representation
|
||||
Map<String, dynamic> toJWK({String? keyID});
|
||||
|
||||
/// 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.
|
||||
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');
|
||||
}
|
||||
}
|
||||
|
||||
/// For HMAC algorithms
|
||||
|
@ -5,132 +5,180 @@ import 'keys_const.dart';
|
||||
|
||||
void main() {
|
||||
group('JWTKey', () {
|
||||
test('should convert SecretKey to JWK', () {
|
||||
final jwk = hsKey.toJWK();
|
||||
group('.toJWK', () {
|
||||
test('should convert SecretKey to JWK', () {
|
||||
final jwk = hsKey.toJWK();
|
||||
|
||||
expect(
|
||||
jwk,
|
||||
equals({
|
||||
'kty': 'oct',
|
||||
'use': 'sig',
|
||||
'k': 'c2VjcmV0IHBhc3NwaHJhc2U',
|
||||
}),
|
||||
);
|
||||
expect(
|
||||
jwk,
|
||||
equals({
|
||||
'kty': 'oct',
|
||||
'use': 'sig',
|
||||
'k': 'c2VjcmV0IHBhc3NwaHJhc2U',
|
||||
}),
|
||||
);
|
||||
|
||||
final jwkWithAlgorithm = hsKey.toJWK(algorithm: JWTAlgorithm.HS256);
|
||||
expect(jwkWithAlgorithm['alg'], equals('HS256'));
|
||||
final jwkWithAlgorithm = hsKey.toJWK(algorithm: JWTAlgorithm.HS256);
|
||||
expect(jwkWithAlgorithm['alg'], equals('HS256'));
|
||||
});
|
||||
|
||||
test('should convert RSAPrivateKey to JWK', () {
|
||||
final jwk = rsaPrivKey.toJWK();
|
||||
|
||||
expect(
|
||||
jwk,
|
||||
equals({
|
||||
'kty': 'RSA',
|
||||
'use': 'sig',
|
||||
'p':
|
||||
'8KNThCO2gsC2I9PQDM_8Cw0O983WCDY-oi-7JPiNAJwv5DYBqEZB1QYdj06YD16XlC_HAZMsMku1na2TN0driwenQQWzoev3g2S7gRDoS_FCJSI3jJ-kjgtaA7Qmzlgk1TxODN-G1H91HW7t0l7VnL27IWyYo2qRRK3jzxqUiPU',
|
||||
'q':
|
||||
'x0oQs2reBQGMVZnApD1jeq7n4MvNLcPvt8b_eU9iUv6Y4Mj0Suo_AU8lYZXm8ubbqAlwz2VSVunD2tOplHyMUrtCtObAfVDUAhCndKaA9gApgfb3xw1IKbuQ1u4IF1FJl3VtumfQn__LiH1B3rXhcdyo3_vIttEk48RakUKClU8',
|
||||
'd':
|
||||
'pOaNpLq2QrwGU9cKVNDa-nP83q7EN5LfmZempqyqyRWVoCJ2CD-xaqmNcNtev3ei0gwuVawz5fQKowOBJcp6MtLaPHgYOMjVlNeD77QAwnywnvilbNUM5-YIRD_vBezf5xudeEquI7xnTfqr3ZBzX43ztIjfyeQZrQAEf0I3zceZCq3h8HtR0fO4hF7-Z7Y8aEirlkHOPqHcGmg8bMQ_7HeX1iYry3_Vw3Smoj51DBh2B8aNpyQu7_aofzQwIXsjJBqx5lQ4nIqsIu1IP8iLG_-HMMRQ984KMUOBOnN_dzC1rz6gTjAcKjWIjX_hOU-TCZfHipJe2bDhpA_PsgNC8Q',
|
||||
'e': 'AQAB',
|
||||
'dp':
|
||||
'zV7W3COOlDDcQd935DdtKBFRAPRPAlspQUnzMi5eSHMD_ISLDY5IiQHbIH83D4bvXq0X7qQoSBSNP7Dvv3HYuqMhf0DaegrlBuJllFVVq9qPVRnKxt1Il2HgxOBvbhOT-9in1BzA-YJ99UzC85O0Qz06A-CmtHEy4aZ2kj5hHjE',
|
||||
'dq':
|
||||
'mNS4-A8Fkss8Js1RieK2LniBxMgmYml3pfVLKGnzmng7H2-cwPLhPIzIuwytXywh2bzbsYEfYx3EoEVgMEpPhoarQnYPukrJO4gwE2o5Te6T5mJSZGlQJQj9q4ZB2Dfzet6INsK0oG8XVGXSpQvQh3RUYekCZQkBBFcpqWpbIEs',
|
||||
'qi':
|
||||
'JzNw0H9xSaEp12jIa1QSKL4nOZdMRZBB7JAIxU3rzvOhbM9QtmknkSkqhhaDkNLZicwRLNUeiqpxyJ4nA00KyoQK4C11-L9wnXY300SZBVg2xPwpLymTTq3H9Z4Whgj7KUSY9ilJI9RYZfQp3HZ_0bGBDjW8EEoyHzD5L8RfvB0',
|
||||
'n':
|
||||
'u1SU1LfVLPHCozMxH2Mo4lgOEePzNm0tRgeLezV6ffAt0gunVTLw7onLRnrq0_IzW7yWR7QkrmBL7jTKEn5u-qKhbwKfBstIs-bMY2Zkp18gnTxKLxoS2tFczGkPLPgizskuemMghRniWaoLcyehkd3qqGElvW_VDL5AaWTg0nLVkjRo9z-40RQzuVaE8AkAFmxZzow3x-VJYKdjykkJ0iT9wCS0DRTXu269V264Vf_3jvredZiKRkgwlL9xNAwxXFg0x_XFw005UWVRIkdgcKWTjpBP2dPwVZ4WWC-9aGVd-Gyn1o0CLelf4rEjGoXbAAEgAqeGUxrcIlbjXfbcmw'
|
||||
}),
|
||||
);
|
||||
|
||||
final jwkWithAlgorithm = rsaPrivKey.toJWK(
|
||||
algorithm: JWTAlgorithm.RS256,
|
||||
);
|
||||
expect(jwkWithAlgorithm['alg'], equals('RS256'));
|
||||
});
|
||||
|
||||
test("should convert RSAPublicKey to JWK", () {
|
||||
final jwk = rsaPubKey.toJWK();
|
||||
|
||||
expect(
|
||||
jwk,
|
||||
equals({
|
||||
'kty': 'RSA',
|
||||
'use': 'sig',
|
||||
'e': 'AQAB',
|
||||
'n':
|
||||
'u1SU1LfVLPHCozMxH2Mo4lgOEePzNm0tRgeLezV6ffAt0gunVTLw7onLRnrq0_IzW7yWR7QkrmBL7jTKEn5u-qKhbwKfBstIs-bMY2Zkp18gnTxKLxoS2tFczGkPLPgizskuemMghRniWaoLcyehkd3qqGElvW_VDL5AaWTg0nLVkjRo9z-40RQzuVaE8AkAFmxZzow3x-VJYKdjykkJ0iT9wCS0DRTXu269V264Vf_3jvredZiKRkgwlL9xNAwxXFg0x_XFw005UWVRIkdgcKWTjpBP2dPwVZ4WWC-9aGVd-Gyn1o0CLelf4rEjGoXbAAEgAqeGUxrcIlbjXfbcmw'
|
||||
}),
|
||||
);
|
||||
|
||||
final jwkWithAlgorithm = rsaPubKey.toJWK(algorithm: JWTAlgorithm.RS256);
|
||||
expect(jwkWithAlgorithm['alg'], equals('RS256'));
|
||||
});
|
||||
|
||||
test("should convert ECPrivateKey to JWK", () {
|
||||
final jwk = ecPrivKey.toJWK();
|
||||
|
||||
expect(
|
||||
jwk,
|
||||
equals({
|
||||
'kty': 'EC',
|
||||
'use': 'sig',
|
||||
'crv': 'P-256',
|
||||
'd': 'evZzL1gdAFr88hb2OF_2NxApJCzGCEDdfSp6VQO30hw',
|
||||
'x': 'EVs_o5-uQbTjL3chynL4wXgUg2R9q9UU8I5mEovUf84',
|
||||
'y': 'kGe5DgSIycKp8w9aJmoHhB1sB3QTugfnRWm5nU_TzsY',
|
||||
'alg': 'ES256'
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test("should convert ECPublicKey to JWK", () {
|
||||
final jwk = ecPubKey.toJWK();
|
||||
|
||||
expect(
|
||||
jwk,
|
||||
equals({
|
||||
'kty': 'EC',
|
||||
'use': 'sig',
|
||||
'crv': 'P-256',
|
||||
'x': 'EVs_o5-uQbTjL3chynL4wXgUg2R9q9UU8I5mEovUf84',
|
||||
'y': 'kGe5DgSIycKp8w9aJmoHhB1sB3QTugfnRWm5nU_TzsY',
|
||||
'alg': 'ES256'
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test("should convert EdDSAPrivateKey to JWK", () {
|
||||
final jwk = edPrivKey.toJWK();
|
||||
|
||||
expect(
|
||||
jwk,
|
||||
equals({
|
||||
'kty': 'OKP',
|
||||
'use': 'sig',
|
||||
'crv': 'Ed25519',
|
||||
'd': 'JcKMEe-MCuNeq5QjmOjfHlIcjih9kDZrPAnf0gL9By0',
|
||||
'x': 'Ei7MNW0Q9T83UA3Rw-8DbspMgqeuxCqa2wXaWS-tHqY',
|
||||
'alg': 'EdDSA'
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test("should convert EdDSAPublicKey to JWK", () {
|
||||
final jwk = edPubKey.toJWK();
|
||||
|
||||
expect(
|
||||
jwk,
|
||||
equals({
|
||||
'kty': 'OKP',
|
||||
'use': 'sig',
|
||||
'crv': 'Ed25519',
|
||||
'x': 'Ei7MNW0Q9T83UA3Rw-8DbspMgqeuxCqa2wXaWS-tHqY',
|
||||
'alg': 'EdDSA'
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test('should convert RSAPrivateKey to JWK', () {
|
||||
final jwk = rsaPrivKey.toJWK();
|
||||
group('.fromJWK', () {
|
||||
test('should parse JWK to SecretKey', () {
|
||||
final jwk = hsKey.toJWK();
|
||||
final key = JWTKey.fromJWK(jwk);
|
||||
expect(key, isA<SecretKey>());
|
||||
});
|
||||
|
||||
expect(
|
||||
jwk,
|
||||
equals({
|
||||
'kty': 'RSA',
|
||||
'use': 'sig',
|
||||
'p':
|
||||
'8KNThCO2gsC2I9PQDM_8Cw0O983WCDY-oi-7JPiNAJwv5DYBqEZB1QYdj06YD16XlC_HAZMsMku1na2TN0driwenQQWzoev3g2S7gRDoS_FCJSI3jJ-kjgtaA7Qmzlgk1TxODN-G1H91HW7t0l7VnL27IWyYo2qRRK3jzxqUiPU',
|
||||
'q':
|
||||
'x0oQs2reBQGMVZnApD1jeq7n4MvNLcPvt8b_eU9iUv6Y4Mj0Suo_AU8lYZXm8ubbqAlwz2VSVunD2tOplHyMUrtCtObAfVDUAhCndKaA9gApgfb3xw1IKbuQ1u4IF1FJl3VtumfQn__LiH1B3rXhcdyo3_vIttEk48RakUKClU8',
|
||||
'd':
|
||||
'pOaNpLq2QrwGU9cKVNDa-nP83q7EN5LfmZempqyqyRWVoCJ2CD-xaqmNcNtev3ei0gwuVawz5fQKowOBJcp6MtLaPHgYOMjVlNeD77QAwnywnvilbNUM5-YIRD_vBezf5xudeEquI7xnTfqr3ZBzX43ztIjfyeQZrQAEf0I3zceZCq3h8HtR0fO4hF7-Z7Y8aEirlkHOPqHcGmg8bMQ_7HeX1iYry3_Vw3Smoj51DBh2B8aNpyQu7_aofzQwIXsjJBqx5lQ4nIqsIu1IP8iLG_-HMMRQ984KMUOBOnN_dzC1rz6gTjAcKjWIjX_hOU-TCZfHipJe2bDhpA_PsgNC8Q',
|
||||
'e': 'AQAB',
|
||||
'dp':
|
||||
'zV7W3COOlDDcQd935DdtKBFRAPRPAlspQUnzMi5eSHMD_ISLDY5IiQHbIH83D4bvXq0X7qQoSBSNP7Dvv3HYuqMhf0DaegrlBuJllFVVq9qPVRnKxt1Il2HgxOBvbhOT-9in1BzA-YJ99UzC85O0Qz06A-CmtHEy4aZ2kj5hHjE',
|
||||
'dq':
|
||||
'mNS4-A8Fkss8Js1RieK2LniBxMgmYml3pfVLKGnzmng7H2-cwPLhPIzIuwytXywh2bzbsYEfYx3EoEVgMEpPhoarQnYPukrJO4gwE2o5Te6T5mJSZGlQJQj9q4ZB2Dfzet6INsK0oG8XVGXSpQvQh3RUYekCZQkBBFcpqWpbIEs',
|
||||
'qi':
|
||||
'JzNw0H9xSaEp12jIa1QSKL4nOZdMRZBB7JAIxU3rzvOhbM9QtmknkSkqhhaDkNLZicwRLNUeiqpxyJ4nA00KyoQK4C11-L9wnXY300SZBVg2xPwpLymTTq3H9Z4Whgj7KUSY9ilJI9RYZfQp3HZ_0bGBDjW8EEoyHzD5L8RfvB0',
|
||||
'n':
|
||||
'u1SU1LfVLPHCozMxH2Mo4lgOEePzNm0tRgeLezV6ffAt0gunVTLw7onLRnrq0_IzW7yWR7QkrmBL7jTKEn5u-qKhbwKfBstIs-bMY2Zkp18gnTxKLxoS2tFczGkPLPgizskuemMghRniWaoLcyehkd3qqGElvW_VDL5AaWTg0nLVkjRo9z-40RQzuVaE8AkAFmxZzow3x-VJYKdjykkJ0iT9wCS0DRTXu269V264Vf_3jvredZiKRkgwlL9xNAwxXFg0x_XFw005UWVRIkdgcKWTjpBP2dPwVZ4WWC-9aGVd-Gyn1o0CLelf4rEjGoXbAAEgAqeGUxrcIlbjXfbcmw'
|
||||
}),
|
||||
);
|
||||
test('should parse JWK to RSAPrivateKey', () {
|
||||
final jwk = rsaPrivKey.toJWK();
|
||||
final key = JWTKey.fromJWK(jwk);
|
||||
expect(key, isA<RSAPrivateKey>());
|
||||
});
|
||||
|
||||
final jwkWithAlgorithm = rsaPrivKey.toJWK(algorithm: JWTAlgorithm.RS256);
|
||||
expect(jwkWithAlgorithm['alg'], equals('RS256'));
|
||||
});
|
||||
test('should parse JWK to RSAPublicKey', () {
|
||||
final jwk = rsaPubKey.toJWK();
|
||||
final key = JWTKey.fromJWK(jwk);
|
||||
expect(key, isA<RSAPublicKey>());
|
||||
});
|
||||
|
||||
test("should convert RSAPublicKey to JWK", () {
|
||||
final jwk = rsaPubKey.toJWK();
|
||||
test('should parse JWK to ECPrivateKey', () {
|
||||
final jwk = ecPrivKey.toJWK();
|
||||
final key = JWTKey.fromJWK(jwk);
|
||||
expect(key, isA<ECPrivateKey>());
|
||||
});
|
||||
|
||||
expect(
|
||||
jwk,
|
||||
equals({
|
||||
'kty': 'RSA',
|
||||
'use': 'sig',
|
||||
'e': 'AQAB',
|
||||
'n':
|
||||
'u1SU1LfVLPHCozMxH2Mo4lgOEePzNm0tRgeLezV6ffAt0gunVTLw7onLRnrq0_IzW7yWR7QkrmBL7jTKEn5u-qKhbwKfBstIs-bMY2Zkp18gnTxKLxoS2tFczGkPLPgizskuemMghRniWaoLcyehkd3qqGElvW_VDL5AaWTg0nLVkjRo9z-40RQzuVaE8AkAFmxZzow3x-VJYKdjykkJ0iT9wCS0DRTXu269V264Vf_3jvredZiKRkgwlL9xNAwxXFg0x_XFw005UWVRIkdgcKWTjpBP2dPwVZ4WWC-9aGVd-Gyn1o0CLelf4rEjGoXbAAEgAqeGUxrcIlbjXfbcmw'
|
||||
}),
|
||||
);
|
||||
test('should parse JWK to ECPublicKey', () {
|
||||
final jwk = ecPubKey.toJWK();
|
||||
final key = JWTKey.fromJWK(jwk);
|
||||
expect(key, isA<ECPublicKey>());
|
||||
});
|
||||
|
||||
final jwkWithAlgorithm = rsaPubKey.toJWK(algorithm: JWTAlgorithm.RS256);
|
||||
expect(jwkWithAlgorithm['alg'], equals('RS256'));
|
||||
});
|
||||
test('should parse JWK to EdDSAPrivateKey', () {
|
||||
final jwk = edPrivKey.toJWK();
|
||||
final key = JWTKey.fromJWK(jwk);
|
||||
expect(key, isA<EdDSAPrivateKey>());
|
||||
});
|
||||
|
||||
test("should convert ECPrivateKey to JWK", () {
|
||||
final jwk = ecPrivKey.toJWK();
|
||||
|
||||
expect(
|
||||
jwk,
|
||||
equals({
|
||||
'kty': 'EC',
|
||||
'use': 'sig',
|
||||
'crv': 'P-256',
|
||||
'd': 'evZzL1gdAFr88hb2OF_2NxApJCzGCEDdfSp6VQO30hw',
|
||||
'x': 'EVs_o5-uQbTjL3chynL4wXgUg2R9q9UU8I5mEovUf84',
|
||||
'y': 'kGe5DgSIycKp8w9aJmoHhB1sB3QTugfnRWm5nU_TzsY',
|
||||
'alg': 'ES256'
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test("should convert ECPublicKey to JWK", () {
|
||||
final jwk = ecPubKey.toJWK();
|
||||
|
||||
expect(
|
||||
jwk,
|
||||
equals({
|
||||
'kty': 'EC',
|
||||
'use': 'sig',
|
||||
'crv': 'P-256',
|
||||
'x': 'EVs_o5-uQbTjL3chynL4wXgUg2R9q9UU8I5mEovUf84',
|
||||
'y': 'kGe5DgSIycKp8w9aJmoHhB1sB3QTugfnRWm5nU_TzsY',
|
||||
'alg': 'ES256'
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test("should convert EdDSAPrivateKey to JWK", () {
|
||||
final jwk = edPrivKey.toJWK();
|
||||
|
||||
expect(
|
||||
jwk,
|
||||
equals({
|
||||
'kty': 'OKP',
|
||||
'use': 'sig',
|
||||
'crv': 'Ed25519',
|
||||
'd': 'JcKMEe-MCuNeq5QjmOjfHlIcjih9kDZrPAnf0gL9By0',
|
||||
'x': 'Ei7MNW0Q9T83UA3Rw-8DbspMgqeuxCqa2wXaWS-tHqY',
|
||||
'alg': 'EdDSA'
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test("should convert EdDSAPublicKey to JWK", () {
|
||||
final jwk = edPubKey.toJWK();
|
||||
|
||||
expect(
|
||||
jwk,
|
||||
equals({
|
||||
'kty': 'OKP',
|
||||
'use': 'sig',
|
||||
'crv': 'Ed25519',
|
||||
'x': 'Ei7MNW0Q9T83UA3Rw-8DbspMgqeuxCqa2wXaWS-tHqY',
|
||||
'alg': 'EdDSA'
|
||||
}),
|
||||
);
|
||||
test('should parse JWK to EdDSAPublicKey', () {
|
||||
final jwk = edPubKey.toJWK();
|
||||
final key = JWTKey.fromJWK(jwk);
|
||||
expect(key, isA<EdDSAPublicKey>());
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
Reference in New Issue
Block a user