SubjectPublicKeyInfo.decode constructor
SubjectPublicKeyInfo.decode(
- Uint8List bytes, {
- required PubTextSource? source,
Decode from a sequence of bytes.
Implementation
SubjectPublicKeyInfo.decode(Uint8List bytes, {required this.source}) {
String msg;
try {
// Parse the bytes as ASN.1
List<ASN1Object> objects;
try {
objects = _asn1parseAll(bytes);
} catch (e) {
throw _SpkiMsg('bad ASN.1 encoding: $e');
}
// There must be only one top-level object
if (objects.isEmpty) {
throw _SpkiMsg(
'no top-level objects (expecting 1, got ${objects.length})');
}
if (objects.length != 1) {
throw _SpkiMsg(
'too many top-level objects (expecting 1, got ${objects.length})');
}
// The top-level object must be a sequence of two items
if (objects.first is! ASN1Sequence) {
throw _SpkiMsg('top-level object is not a sequence');
}
// ignore: avoid_as
final topSequence = objects.first as ASN1Sequence;
if (topSequence.elements.length != 2) {
throw _SpkiMsg('top-level sequence does not contain 2 items');
}
// 1. Algorithm information
final a = topSequence.elements[0];
if (a is! ASN1Sequence) {
throw _SpkiMsg('algorithm-info is not a sequence');
}
final algorithmInfo = a;
if (algorithmInfo.elements.isEmpty) {
throw _SpkiMsg('algorithm-info is empty');
}
// First algorithm parameter is an OID that identifies the algorithm
final a1 = algorithmInfo.elements[0];
if (a1 is! ASN1ObjectIdentifier) {
throw _SpkiMsg('algorithm-info does not contain OID');
}
algorithmOid = a1.identifier!;
// Save rest of the algorithm parameters
algorithmParameters = <ASN1Object>[];
for (var i = 1; i < algorithmInfo.elements.length; i++) {
algorithmParameters.add(algorithmInfo.elements[i]);
}
// 2. The data
final bits = topSequence.elements[1];
if (bits is! ASN1BitString) {
throw _SpkiMsg('publicKey is not a bit string: ${bits.runtimeType}');
}
// ignore: avoid_as
data = Uint8List.fromList(bits.stringValue);
return; // success
} on _SpkiMsg catch (e) {
msg = e.message;
} catch (e) {
msg = 'unexpected: $e';
}
throw KeyBad('invalid public key: $msg');
}