mirror of
https://github.com/jonasroussel/dart_jsonwebtoken.git
synced 2025-05-17 16:15:52 +08:00
v2.11.0
This commit is contained in:
@ -1,3 +1,9 @@
|
||||
## 2.11.0
|
||||
|
||||
- Removing `basic_utils` package that was incompatible with flutter web
|
||||
- Moving utils to `helpers.dart` and key parsing functions into `key_parser.dart`
|
||||
- Adding some new examples in `example/example.dart`
|
||||
|
||||
## 2.10.0
|
||||
|
||||
- New ECDSA algorithm (ES256K)
|
||||
|
@ -22,6 +22,10 @@ void main() {
|
||||
print('----- RSA-PSS SHA-256 -----');
|
||||
ps256();
|
||||
print('---------------------------\n');
|
||||
|
||||
print('----- RSA Certificate -----');
|
||||
rsaCert();
|
||||
print('---------------------------\n');
|
||||
}
|
||||
|
||||
// HMAC SHA-256 algorithm
|
||||
@ -232,3 +236,46 @@ void ps256() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RSA Certificate
|
||||
void rsaCert() {
|
||||
String token;
|
||||
|
||||
/* Sign */ {
|
||||
// Create a json web token
|
||||
final jwt = JWT(
|
||||
{
|
||||
'id': 123,
|
||||
'server': {
|
||||
'id': '3e4fc296',
|
||||
'loc': 'euw-2',
|
||||
}
|
||||
},
|
||||
issuer: 'https://github.com/jonasroussel/dart_jsonwebtoken',
|
||||
);
|
||||
|
||||
// Sign it
|
||||
final pem = File('./example/rsa_cert_private.pem').readAsStringSync();
|
||||
final key = RSAPrivateKey(pem);
|
||||
|
||||
token = jwt.sign(key, algorithm: JWTAlgorithm.RS256);
|
||||
|
||||
print('Signed token: $token\n');
|
||||
}
|
||||
|
||||
/* Verify */ {
|
||||
try {
|
||||
// Verify a token
|
||||
final pem = File('./example/rsa_certificate.pem').readAsStringSync();
|
||||
final key = RSAPublicKey.cert(pem);
|
||||
|
||||
final jwt = JWT.verify(token, key);
|
||||
|
||||
print('Payload: ${jwt.payload}');
|
||||
} on JWTExpiredException {
|
||||
print('jwt expired');
|
||||
} on JWTException catch (ex) {
|
||||
print(ex.message); // ex: invalid signature
|
||||
}
|
||||
}
|
||||
}
|
||||
|
28
example/rsa_cert_private.pem
Normal file
28
example/rsa_cert_private.pem
Normal file
@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDHr1vavB+pZ0e/
|
||||
0vp7fzElDST0TffrAGvLvo6QUmn8AdzNGEiytW2GeYGBMEGni/I89/S6e0SWsVqa
|
||||
XJjqDlXqefZUzPzbyfd9URwah0vcHFKk+bM7ZsvOxvlRhKYwx3waNzOlcfetlB5h
|
||||
pFCiHotoUJL9sbVjoByMbs3BQP87gDSRAfkgdNhyt73Qe4mxlXBo7Ay+3dRLJZmV
|
||||
IegJDQ2Ktxlsg25nYn84fpOQHlzoU4BMSKRZvVflKUblJllpwXETDvD52FlvITeo
|
||||
2qdeTaerBUlOWVAYD31hJzfPUIynt4LZ7k6of73lkBH93ZOcVfYeyCGtt4fGMNJi
|
||||
JxxjHkVnAgMBAAECggEAEPikc+i9QCaZAIKr60caJC4D0Ae4ZG66uqxNbZKzk0mN
|
||||
PJktxJKK5nz5NsOlMNpCElB4qkjDwZL9QlVQYcQqJS2MdBSgAQYfVLVKEC8jkWeO
|
||||
1pqqUwgflklu8zC09zxdHdVHPG59QHFwS5gtijnSW2FNvOYXpon7IyxfrGcbyjCq
|
||||
vsEo4DkrTs2ZALkONSfYuRVMtMyWOZcOET8MKFYy6LtFzQaEB9TUPXwauF5oMxab
|
||||
+S1iJLb4yPBos84Y1ooGQGl72neTueNF35qNHndkybSH0zcFFC48kdkc/PjkTfSt
|
||||
ubgHDNmMEZDWgNdAK7igoLcwyS0lZiQgfVDfylbmcQKBgQDzAat/eZtBrdL4Gajk
|
||||
oz2sFJQsftwX49T7xl3cKHBNKzc1J9SZHIqix8/Tajqtz5nHf8bwLkn9Z830BEjc
|
||||
OM80hYh2vM1J9j1z7mo304+w3Y1tc+29rP+R65pJprMNiBEaTtPihtWBluL68hzi
|
||||
f2Gl3pjJUA96KvCWL9LUiDDsswKBgQDSXLGV/eWm8tAB0NVzl8Mi35pAq63D107L
|
||||
M+tqfg5+DiQhSkaL1N554uyyJ33+Q4YDctJB/9QrVppl5WysIjMBJtyYZAs8Qylz
|
||||
n/JJcJzoIvxuNAEdKevxtLb934slRyGBWAGpCOkoxNhKKzN0ZovgC51OPNgCbMK7
|
||||
5oYND9eGfQKBgQDSijbZKjY+0GiBtlGjTl+nkOjUKFFujWHBhhtaHNs3sOKTNmA3
|
||||
DAh9glrolBgk8UIOHAHzpFdMqzxAV9n8m2fC3JLgNTI0C5kwsXbryWusVDgthYyM
|
||||
kq+W8KbreveVGLegsH1ZvXKMZXtg6pXmE3E58cM0YB4Yvc1WgjbLFvg0iwKBgQCY
|
||||
2TdD1/b9BmLzXs0pr3TfKv+Gy/d3XENpTLFacHuRRi8kbTazNZntkGAR1rYqgN+o
|
||||
M87om72LO+L19Oywai0LQjR5GgA76kT9OZOvnv6zgXBPlsPUb/h7aKap8rrE/Fkx
|
||||
BUQ3kTzxHY5W3esGQdiSk33aMkV2BZa9NvPiG8erdQKBgDlpbRVv3ypjDQxdgccT
|
||||
4K0zyWgG0597PXF+wBCV3+1FryarzlBCaSN53daE/s+XzJh8pZEN5zV8SkjKdI+W
|
||||
ccDgCZ/FL15OB/AuE6I6/T4g5NWXDqqWt5qMP+SU7oK+IpzpRZyq56SSLCXzvMzk
|
||||
+PD5J7pSXLRdv9DJURCvZ2ny
|
||||
-----END PRIVATE KEY-----
|
9
example/rsa_cert_public.pem
Normal file
9
example/rsa_cert_public.pem
Normal file
@ -0,0 +1,9 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx69b2rwfqWdHv9L6e38x
|
||||
JQ0k9E336wBry76OkFJp/AHczRhIsrVthnmBgTBBp4vyPPf0untElrFamlyY6g5V
|
||||
6nn2VMz828n3fVEcGodL3BxSpPmzO2bLzsb5UYSmMMd8GjczpXH3rZQeYaRQoh6L
|
||||
aFCS/bG1Y6AcjG7NwUD/O4A0kQH5IHTYcre90HuJsZVwaOwMvt3USyWZlSHoCQ0N
|
||||
ircZbINuZ2J/OH6TkB5c6FOATEikWb1X5SlG5SZZacFxEw7w+dhZbyE3qNqnXk2n
|
||||
qwVJTllQGA99YSc3z1CMp7eC2e5OqH+95ZAR/d2TnFX2HsghrbeHxjDSYiccYx5F
|
||||
ZwIDAQAB
|
||||
-----END PUBLIC KEY-----
|
20
example/rsa_certificate.pem
Normal file
20
example/rsa_certificate.pem
Normal file
@ -0,0 +1,20 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDMjCCAhoCCQD3O5GD6JcncDANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJG
|
||||
UjEWMBQGA1UECAwNSWxlLWRlLUZyYW5jZTEOMAwGA1UEBwwFUGFyaXMxJDAiBgkq
|
||||
hkiG9w0BCQEWFWdvLmpyb3Vzc2VsQGdtYWlsLmNvbTAeFw0yMzA4MjMxODU3MTJa
|
||||
Fw0yNDA4MjIxODU3MTJaMFsxCzAJBgNVBAYTAkZSMRYwFAYDVQQIDA1JbGUtZGUt
|
||||
RnJhbmNlMQ4wDAYDVQQHDAVQYXJpczEkMCIGCSqGSIb3DQEJARYVZ28uanJvdXNz
|
||||
ZWxAZ21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx69b
|
||||
2rwfqWdHv9L6e38xJQ0k9E336wBry76OkFJp/AHczRhIsrVthnmBgTBBp4vyPPf0
|
||||
untElrFamlyY6g5V6nn2VMz828n3fVEcGodL3BxSpPmzO2bLzsb5UYSmMMd8Gjcz
|
||||
pXH3rZQeYaRQoh6LaFCS/bG1Y6AcjG7NwUD/O4A0kQH5IHTYcre90HuJsZVwaOwM
|
||||
vt3USyWZlSHoCQ0NircZbINuZ2J/OH6TkB5c6FOATEikWb1X5SlG5SZZacFxEw7w
|
||||
+dhZbyE3qNqnXk2nqwVJTllQGA99YSc3z1CMp7eC2e5OqH+95ZAR/d2TnFX2Hsgh
|
||||
rbeHxjDSYiccYx5FZwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAAN08vxGGcZYKq
|
||||
/5lPRUYr7+KzMr5wHQdEUluPVtMiYjpOeuP+vXtO+tgmabCJqlXGg/O0H/GhczGX
|
||||
cGYEPye5ftjiRPYLjvAgHotJH2gnJ5w5y5bRYw3+r/JQkueEd617iHFNL2j0atxf
|
||||
ULgfOfPXjLu+2Ch8c8z/J5u52H6xpXBNDRNCnfm2nqwMcsRXCitLMENxMv9IBmJD
|
||||
y5hfMtlcFb7XOmlHr0eRuR1U4IVF4k9v2b1vCWYWJLhJHRWQFaLQPGm0Y/1KL1F3
|
||||
eXA81iNBFKIzqgiB0SSRxIt+mx4ZHg7QCwAYqzLFK8m59KRCz+eD1Ho/cO9NC/rZ
|
||||
vwLdy6e2
|
||||
-----END CERTIFICATE-----
|
@ -8,7 +8,7 @@ import 'package:pointycastle/pointycastle.dart' as pc;
|
||||
|
||||
import 'exceptions.dart';
|
||||
import 'keys.dart';
|
||||
import 'utils.dart';
|
||||
import 'helpers.dart';
|
||||
|
||||
abstract class JWTAlgorithm {
|
||||
/// HMAC using SHA-256 hash algorithm
|
||||
|
@ -1,5 +1,4 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'dart:typed_data';
|
||||
|
||||
final jsonBase64 = json.fuse(utf8.fuse(base64Url));
|
||||
@ -90,18 +89,11 @@ BigInt bigIntFromBytes(Uint8List bytes) {
|
||||
return bytes.fold(BigInt.zero, (a, b) => a * _b256 + BigInt.from(b));
|
||||
}
|
||||
|
||||
Uint8List hexToUint8List(String hex) {
|
||||
if (hex.length % 2 != 0) {
|
||||
throw 'Odd number of hex digits';
|
||||
List<String> chunkString(String s, int chunkSize) {
|
||||
var chunked = <String>[];
|
||||
for (var i = 0; i < s.length; i += chunkSize) {
|
||||
var end = (i + chunkSize < s.length) ? i + chunkSize : s.length;
|
||||
chunked.add(s.substring(i, end));
|
||||
}
|
||||
var l = hex.length ~/ 2;
|
||||
var result = Uint8List(l);
|
||||
for (var i = 0; i < l; ++i) {
|
||||
var x = int.parse(hex.substring(2 * i, 2 * (i + 1)), radix: 16);
|
||||
if (x.isNaN) {
|
||||
throw 'Expected hex string';
|
||||
}
|
||||
result[i] = x;
|
||||
}
|
||||
return result;
|
||||
return chunked;
|
||||
}
|
@ -7,7 +7,7 @@ import 'package:collection/collection.dart';
|
||||
import 'algorithms.dart';
|
||||
import 'exceptions.dart';
|
||||
import 'keys.dart';
|
||||
import 'utils.dart';
|
||||
import 'helpers.dart';
|
||||
|
||||
class JWT {
|
||||
/// Verify a token.
|
||||
|
299
lib/src/key_parser.dart
Normal file
299
lib/src/key_parser.dart
Normal file
@ -0,0 +1,299 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:pointycastle/asn1/object_identifiers.dart';
|
||||
import 'package:pointycastle/pointycastle.dart';
|
||||
import 'package:pointycastle/ecc/ecc_fp.dart' as ecc_fp;
|
||||
|
||||
import 'helpers.dart';
|
||||
|
||||
abstract class KeyParser {
|
||||
static const BEGIN_PRIVATE_KEY = '-----BEGIN PRIVATE KEY-----';
|
||||
static const END_PRIVATE_KEY = '-----END PRIVATE KEY-----';
|
||||
|
||||
static const BEGIN_PUBLIC_KEY = '-----BEGIN PUBLIC KEY-----';
|
||||
static const END_PUBLIC_KEY = '-----END PUBLIC KEY-----';
|
||||
|
||||
static const BEGIN_EC_PRIVATE_KEY = '-----BEGIN EC PRIVATE KEY-----';
|
||||
static const END_EC_PRIVATE_KEY = '-----END EC PRIVATE KEY-----';
|
||||
|
||||
static const BEGIN_EC_PUBLIC_KEY = '-----BEGIN PUBLIC KEY-----';
|
||||
static const END_EC_PUBLIC_KEY = '-----END PUBLIC KEY-----';
|
||||
|
||||
static const BEGIN_RSA_PRIVATE_KEY = '-----BEGIN RSA PRIVATE KEY-----';
|
||||
static const END_RSA_PRIVATE_KEY = '-----END RSA PRIVATE KEY-----';
|
||||
|
||||
static const BEGIN_RSA_PUBLIC_KEY = '-----BEGIN RSA PUBLIC KEY-----';
|
||||
static const END_RSA_PUBLIC_KEY = '-----END RSA PUBLIC KEY-----';
|
||||
|
||||
//-------------//
|
||||
// RSA Parsing //
|
||||
//-------------//
|
||||
|
||||
static RSAPrivateKey rsaPrivateKeyFromPEM(String pem, {bool pkcs1 = false}) {
|
||||
var bytes = bytesFromPEM(pem);
|
||||
|
||||
if (pkcs1) {
|
||||
return rsaPrivateKeyPKCS1(bytes);
|
||||
} else {
|
||||
return rsaPrivateKey(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
static RSAPrivateKey rsaPrivateKey(Uint8List bytes) {
|
||||
var asn1Parser = ASN1Parser(bytes);
|
||||
final topLevelSeq = asn1Parser.nextObject() as ASN1Sequence;
|
||||
final privateKey = topLevelSeq.elements![2];
|
||||
|
||||
asn1Parser = ASN1Parser(privateKey.valueBytes);
|
||||
final pkSeq = asn1Parser.nextObject() as ASN1Sequence;
|
||||
|
||||
final modulus = pkSeq.elements![1] as ASN1Integer;
|
||||
final privateExponent = pkSeq.elements![3] as ASN1Integer;
|
||||
final p = pkSeq.elements![4] as ASN1Integer;
|
||||
final q = pkSeq.elements![5] as ASN1Integer;
|
||||
|
||||
return RSAPrivateKey(
|
||||
modulus.integer!,
|
||||
privateExponent.integer!,
|
||||
p.integer,
|
||||
q.integer,
|
||||
);
|
||||
}
|
||||
|
||||
static RSAPrivateKey rsaPrivateKeyPKCS1(Uint8List bytes) {
|
||||
var asn1Parser = ASN1Parser(bytes);
|
||||
var pkSeq = asn1Parser.nextObject() as ASN1Sequence;
|
||||
|
||||
var modulus = pkSeq.elements![1] as ASN1Integer;
|
||||
var privateExponent = pkSeq.elements![3] as ASN1Integer;
|
||||
var p = pkSeq.elements![4] as ASN1Integer;
|
||||
var q = pkSeq.elements![5] as ASN1Integer;
|
||||
|
||||
return RSAPrivateKey(
|
||||
modulus.integer!,
|
||||
privateExponent.integer!,
|
||||
p.integer,
|
||||
q.integer,
|
||||
);
|
||||
}
|
||||
|
||||
static RSAPublicKey rsaPublicKeyFromPEM(String pem, {bool pkcs1 = false}) {
|
||||
var bytes = bytesFromPEM(pem);
|
||||
|
||||
if (pkcs1) {
|
||||
return rsaPublicKeyPKCS1(bytes);
|
||||
} else {
|
||||
return rsaPublicKey(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
static RSAPublicKey rsaPublicKey(Uint8List bytes) {
|
||||
final asn1Parser = ASN1Parser(bytes);
|
||||
final topLevelSeq = asn1Parser.nextObject() as ASN1Sequence;
|
||||
|
||||
ASN1Sequence publicKeySeq;
|
||||
if (topLevelSeq.elements![1].runtimeType == ASN1BitString) {
|
||||
final publicKeyBitString = topLevelSeq.elements![1] as ASN1BitString;
|
||||
|
||||
final publicKeyAsn = ASN1Parser(
|
||||
publicKeyBitString.stringValues as Uint8List?,
|
||||
);
|
||||
publicKeySeq = publicKeyAsn.nextObject() as ASN1Sequence;
|
||||
} else {
|
||||
publicKeySeq = topLevelSeq;
|
||||
}
|
||||
|
||||
final modulus = publicKeySeq.elements![0] as ASN1Integer;
|
||||
final exponent = publicKeySeq.elements![1] as ASN1Integer;
|
||||
|
||||
return RSAPublicKey(modulus.integer!, exponent.integer!);
|
||||
}
|
||||
|
||||
static RSAPublicKey rsaPublicKeyPKCS1(Uint8List bytes) {
|
||||
final publicKeyAsn = ASN1Parser(bytes);
|
||||
final publicKeySeq = publicKeyAsn.nextObject() as ASN1Sequence;
|
||||
final modulus = publicKeySeq.elements![0] as ASN1Integer;
|
||||
final exponent = publicKeySeq.elements![1] as ASN1Integer;
|
||||
|
||||
return RSAPublicKey(modulus.integer!, exponent.integer!);
|
||||
}
|
||||
|
||||
//---------------//
|
||||
// ECDSA Parsing //
|
||||
//---------------//
|
||||
|
||||
static ECPrivateKey ecPrivateKeyFromPEM(String pem, {bool pkcs1 = false}) {
|
||||
final bytes = bytesFromPEM(pem);
|
||||
|
||||
if (pkcs1) {
|
||||
return ecPrivateKeyPKCS1(bytes);
|
||||
} else {
|
||||
return ecPrivateKey(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
static ECPrivateKey ecPrivateKey(Uint8List bytes) {
|
||||
var asn1Parser = ASN1Parser(bytes);
|
||||
var topLevelSeq = asn1Parser.nextObject() as ASN1Sequence;
|
||||
|
||||
String? curveName;
|
||||
|
||||
// Parse the PKCS8 format
|
||||
var innerSeq = topLevelSeq.elements!.elementAt(1) as ASN1Sequence;
|
||||
var b2 = innerSeq.elements!.elementAt(1) as ASN1ObjectIdentifier;
|
||||
var b2Data = b2.objectIdentifierAsString;
|
||||
var b2Curvedata = ObjectIdentifiers.getIdentifierByIdentifier(b2Data);
|
||||
if (b2Curvedata != null) {
|
||||
curveName = b2Curvedata['readableName'];
|
||||
}
|
||||
|
||||
var octetString = topLevelSeq.elements!.elementAt(2) as ASN1OctetString;
|
||||
asn1Parser = ASN1Parser(octetString.valueBytes);
|
||||
var octetStringSeq = asn1Parser.nextObject() as ASN1Sequence;
|
||||
var octetStringKeyData =
|
||||
octetStringSeq.elements!.elementAt(1) as ASN1OctetString;
|
||||
|
||||
final x = octetStringKeyData.valueBytes!;
|
||||
|
||||
return ECPrivateKey(
|
||||
osp2i(x),
|
||||
ECDomainParameters(curveName ?? 'prime256v1'),
|
||||
);
|
||||
}
|
||||
|
||||
static ECPrivateKey ecPrivateKeyPKCS1(Uint8List bytes) {
|
||||
var asn1Parser = ASN1Parser(bytes);
|
||||
var topLevelSeq = asn1Parser.nextObject() as ASN1Sequence;
|
||||
|
||||
String? curveName;
|
||||
|
||||
// Parse the SEC1 format
|
||||
var privateKeyAsOctetString =
|
||||
topLevelSeq.elements!.elementAt(1) as ASN1OctetString;
|
||||
var choice = topLevelSeq.elements!.elementAt(2);
|
||||
var s = ASN1Sequence();
|
||||
var parser = ASN1Parser(choice.valueBytes);
|
||||
while (parser.hasNext()) {
|
||||
s.add(parser.nextObject());
|
||||
}
|
||||
var curveNameOi = s.elements!.elementAt(0) as ASN1ObjectIdentifier;
|
||||
var data = ObjectIdentifiers.getIdentifierByIdentifier(
|
||||
curveNameOi.objectIdentifierAsString,
|
||||
);
|
||||
if (data != null) {
|
||||
curveName = data['readableName'];
|
||||
}
|
||||
|
||||
final x = privateKeyAsOctetString.valueBytes!;
|
||||
|
||||
return ECPrivateKey(
|
||||
osp2i(x),
|
||||
ECDomainParameters(curveName ?? 'prime256v1'),
|
||||
);
|
||||
}
|
||||
|
||||
static ECPublicKey ecPublicKeyFromPEM(String pem) {
|
||||
final bytes = bytesFromPEM(pem);
|
||||
|
||||
return ecPublicKey(bytes);
|
||||
}
|
||||
|
||||
static ECPublicKey ecPublicKey(Uint8List bytes) {
|
||||
if (bytes.elementAt(0) == 0) {
|
||||
bytes = bytes.sublist(1);
|
||||
}
|
||||
var asn1Parser = ASN1Parser(bytes);
|
||||
var topLevelSeq = asn1Parser.nextObject() as ASN1Sequence;
|
||||
|
||||
var algorithmIdentifierSequence = topLevelSeq.elements![0] as ASN1Sequence;
|
||||
var curveNameOi = algorithmIdentifierSequence.elements!.elementAt(1)
|
||||
as ASN1ObjectIdentifier;
|
||||
String? curveName;
|
||||
var data = ObjectIdentifiers.getIdentifierByIdentifier(
|
||||
curveNameOi.objectIdentifierAsString);
|
||||
if (data != null) {
|
||||
curveName = data['readableName'];
|
||||
}
|
||||
|
||||
var subjectPublicKey = topLevelSeq.elements![1] as ASN1BitString;
|
||||
var compressed = false;
|
||||
var pubBytes = subjectPublicKey.valueBytes!;
|
||||
if (pubBytes.elementAt(0) == 0) {
|
||||
pubBytes = pubBytes.sublist(1);
|
||||
}
|
||||
|
||||
// Looks good so far!
|
||||
var firstByte = pubBytes.elementAt(0);
|
||||
if (firstByte != 4) {
|
||||
compressed = true;
|
||||
}
|
||||
var x = pubBytes.sublist(1, (pubBytes.length / 2).round());
|
||||
var y = pubBytes.sublist(1 + x.length, pubBytes.length);
|
||||
var params = ECDomainParameters(curveName ?? 'prime256v1');
|
||||
var bigX = decodeBigIntWithSign(1, x);
|
||||
var bigY = decodeBigIntWithSign(1, y);
|
||||
var pubKey = ECPublicKey(
|
||||
ecc_fp.ECPoint(
|
||||
params.curve as ecc_fp.ECCurve,
|
||||
params.curve.fromBigInteger(bigX) as ecc_fp.ECFieldElement?,
|
||||
params.curve.fromBigInteger(bigY) as ecc_fp.ECFieldElement?,
|
||||
compressed,
|
||||
),
|
||||
params,
|
||||
);
|
||||
return pubKey;
|
||||
}
|
||||
|
||||
//--------------//
|
||||
// PEM to Bytes //
|
||||
//--------------//
|
||||
|
||||
static Uint8List publicKeyBytesFromCertificate(String pem) {
|
||||
var bytes = bytesFromPEM(pem);
|
||||
var asn1Parser = ASN1Parser(bytes);
|
||||
|
||||
var topLevelSeq = asn1Parser.nextObject() as ASN1Sequence;
|
||||
var certSq = topLevelSeq.elements!.elementAt(0) as ASN1Sequence;
|
||||
|
||||
int element;
|
||||
if (certSq.elements!.elementAt(0) is ASN1Integer) {
|
||||
element = -1;
|
||||
} else {
|
||||
element = 0;
|
||||
}
|
||||
|
||||
final pubKeySequence = certSq.elements!.elementAt(element + 6);
|
||||
|
||||
return pubKeySequence.encodedBytes ?? Uint8List(0);
|
||||
}
|
||||
|
||||
static Uint8List bytesFromPEM(String pem) {
|
||||
final lines = LineSplitter.split(pem)
|
||||
.map((line) => line.trim())
|
||||
.where((line) => line.isNotEmpty)
|
||||
.toList();
|
||||
|
||||
final base64Data = lines.sublist(1, lines.length - 1).join('');
|
||||
|
||||
return Uint8List.fromList(base64Decode(base64Data));
|
||||
}
|
||||
|
||||
//------------------//
|
||||
// Helper Functions //
|
||||
//------------------//
|
||||
|
||||
static BigInt osp2i(Iterable<int> bytes, {Endian endian = Endian.big}) {
|
||||
var result = BigInt.from(0);
|
||||
if (endian == Endian.little) {
|
||||
bytes = bytes.toList().reversed;
|
||||
}
|
||||
|
||||
for (var byte in bytes) {
|
||||
result = result << 8;
|
||||
result |= BigInt.from(byte);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
@ -1,11 +1,10 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:basic_utils/basic_utils.dart';
|
||||
import 'package:dart_jsonwebtoken/src/utils.dart';
|
||||
import 'package:ed25519_edwards/ed25519_edwards.dart' as ed;
|
||||
import 'package:pointycastle/pointycastle.dart' as pc;
|
||||
|
||||
import 'exceptions.dart';
|
||||
import 'key_parser.dart';
|
||||
|
||||
abstract class JWTKey {}
|
||||
|
||||
@ -21,17 +20,15 @@ class RSAPrivateKey extends JWTKey {
|
||||
late pc.RSAPrivateKey key;
|
||||
|
||||
RSAPrivateKey(String pem) {
|
||||
if (pem.startsWith(CryptoUtils.BEGIN_RSA_PRIVATE_KEY)) {
|
||||
key = CryptoUtils.rsaPrivateKeyFromPemPkcs1(pem);
|
||||
} else {
|
||||
key = CryptoUtils.rsaPrivateKeyFromPem(pem);
|
||||
}
|
||||
key = KeyParser.rsaPrivateKeyFromPEM(
|
||||
pem,
|
||||
pkcs1: pem.startsWith(KeyParser.BEGIN_RSA_PRIVATE_KEY),
|
||||
);
|
||||
}
|
||||
|
||||
RSAPrivateKey.raw(pc.RSAPrivateKey _key) : key = _key;
|
||||
RSAPrivateKey.clone(RSAPrivateKey _key) : key = _key.key;
|
||||
RSAPrivateKey.bytes(Uint8List bytes)
|
||||
: key = CryptoUtils.rsaPrivateKeyFromDERBytes(bytes);
|
||||
RSAPrivateKey.bytes(Uint8List bytes) : key = KeyParser.rsaPrivateKey(bytes);
|
||||
}
|
||||
|
||||
/// For RSA algorithm, in verify method
|
||||
@ -39,34 +36,25 @@ class RSAPublicKey extends JWTKey {
|
||||
late pc.RSAPublicKey key;
|
||||
|
||||
RSAPublicKey(String pem) {
|
||||
if (pem.startsWith(CryptoUtils.BEGIN_RSA_PUBLIC_KEY)) {
|
||||
key = CryptoUtils.rsaPublicKeyFromPemPkcs1(pem);
|
||||
} else {
|
||||
key = CryptoUtils.rsaPublicKeyFromPem(pem);
|
||||
}
|
||||
key = KeyParser.rsaPublicKeyFromPEM(
|
||||
pem,
|
||||
pkcs1: pem.startsWith(KeyParser.BEGIN_RSA_PUBLIC_KEY),
|
||||
);
|
||||
}
|
||||
|
||||
RSAPublicKey.raw(pc.RSAPublicKey _key) : key = _key;
|
||||
RSAPublicKey.clone(RSAPublicKey _key) : key = _key.key;
|
||||
RSAPublicKey.bytes(Uint8List bytes) {
|
||||
try {
|
||||
key = CryptoUtils.rsaPublicKeyFromDERBytesPkcs1(bytes);
|
||||
key = KeyParser.rsaPublicKey(bytes);
|
||||
} catch (_) {
|
||||
key = CryptoUtils.rsaPublicKeyFromDERBytes(bytes);
|
||||
key = KeyParser.rsaPublicKeyPKCS1(bytes);
|
||||
}
|
||||
}
|
||||
RSAPublicKey.cert(String pem) {
|
||||
final x509 = X509Utils.x509CertificateFromPem(pem);
|
||||
final bytes = x509.tbsCertificate?.subjectPublicKeyInfo.bytes;
|
||||
if (bytes == null) {
|
||||
throw JWTParseException('x509 Certificate parsing failed');
|
||||
}
|
||||
final bytes = KeyParser.publicKeyBytesFromCertificate(pem);
|
||||
|
||||
try {
|
||||
key = CryptoUtils.rsaPublicKeyFromDERBytesPkcs1(hexToUint8List(bytes));
|
||||
} catch (_) {
|
||||
key = CryptoUtils.rsaPublicKeyFromDERBytes(hexToUint8List(bytes));
|
||||
}
|
||||
key = RSAPublicKey.bytes(bytes).key;
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,7 +64,10 @@ class ECPrivateKey extends JWTKey {
|
||||
late int size;
|
||||
|
||||
ECPrivateKey(String pem) {
|
||||
final _key = CryptoUtils.ecPrivateKeyFromPem(pem);
|
||||
final _key = KeyParser.ecPrivateKeyFromPEM(
|
||||
pem,
|
||||
pkcs1: pem.startsWith(KeyParser.BEGIN_EC_PRIVATE_KEY),
|
||||
);
|
||||
final _params = _key.parameters;
|
||||
|
||||
if (_params == null) {
|
||||
@ -100,8 +91,7 @@ class ECPrivateKey extends JWTKey {
|
||||
ECPrivateKey.clone(ECPrivateKey _key)
|
||||
: key = _key.key,
|
||||
size = _key.size;
|
||||
ECPrivateKey.bytes(Uint8List bytes)
|
||||
: key = CryptoUtils.ecPrivateKeyFromDerBytes(bytes);
|
||||
ECPrivateKey.bytes(Uint8List bytes) : key = KeyParser.ecPrivateKey(bytes);
|
||||
}
|
||||
|
||||
/// For ECDSA algorithm, in verify method
|
||||
@ -109,21 +99,16 @@ class ECPublicKey extends JWTKey {
|
||||
late pc.ECPublicKey key;
|
||||
|
||||
ECPublicKey(String pem) {
|
||||
key = CryptoUtils.ecPublicKeyFromPem(pem);
|
||||
key = KeyParser.ecPublicKeyFromPEM(pem);
|
||||
}
|
||||
|
||||
ECPublicKey.raw(pc.ECPublicKey _key) : key = _key;
|
||||
ECPublicKey.clone(ECPublicKey _key) : key = _key.key;
|
||||
ECPublicKey.bytes(Uint8List bytes)
|
||||
: key = CryptoUtils.ecPublicKeyFromDerBytes(bytes);
|
||||
ECPublicKey.bytes(Uint8List bytes) : key = KeyParser.ecPublicKey(bytes);
|
||||
ECPublicKey.cert(String pem) {
|
||||
final x509 = X509Utils.x509CertificateFromPem(pem);
|
||||
final bytes = x509.tbsCertificate?.subjectPublicKeyInfo.bytes;
|
||||
if (bytes == null) {
|
||||
throw JWTParseException('x509 Certificate parsing failed');
|
||||
}
|
||||
final bytes = KeyParser.publicKeyBytesFromCertificate(pem);
|
||||
|
||||
key = CryptoUtils.ecPublicKeyFromDerBytes(hexToUint8List(bytes));
|
||||
key = ECPublicKey.bytes(bytes).key;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
name: dart_jsonwebtoken
|
||||
description: A dart implementation of the famous javascript library 'jsonwebtoken' (JWT).
|
||||
version: 2.10.0
|
||||
version: 2.11.0
|
||||
repository: https://github.com/jonasroussel/dart_jsonwebtoken
|
||||
homepage: https://github.com/jonasroussel/dart_jsonwebtoken#readme
|
||||
|
||||
@ -16,7 +16,6 @@ dependencies:
|
||||
convert: ^3.1.1
|
||||
collection: ^1.17.1
|
||||
ed25519_edwards: ^0.3.1
|
||||
basic_utils: ^5.6.1
|
||||
|
||||
dev_dependencies:
|
||||
lints: ^2.1.1
|
||||
|
Reference in New Issue
Block a user