import 'dart:typed_data'; import 'package:pointycastle/asn1/asn1_encoding_rule.dart'; import 'package:pointycastle/asn1/asn1_object.dart'; import 'package:pointycastle/asn1/asn1_tags.dart'; import 'package:pointycastle/asn1/object_identifiers.dart'; import 'package:pointycastle/asn1/unsupported_asn1_encoding_rule_exception.dart'; import 'package:pointycastle/asn1/unsupported_object_identifier_exception.dart'; class ASN1ObjectIdentifier extends ASN1Object { /// /// The object identifier integer values /// List? objectIdentifier; /// /// The String representation of the [objectIdentifier] /// String? objectIdentifierAsString; /// /// The readable representation of the [objectIdentifier] /// String? readableName; /// /// Create an [ASN1ObjectIdentifier] entity with the given [objectIdentifier]. /// ASN1ObjectIdentifier(this.objectIdentifier, {int tag = ASN1Tags.OBJECT_IDENTIFIER}) : super(tag: tag) { objectIdentifierAsString = objectIdentifier!.join('.'); } /// /// Creates an [ASN1ObjectIdentifier] entity from the given [encodedBytes]. /// ASN1ObjectIdentifier.fromBytes(Uint8List super.encodedBytes) : super.fromBytes() { var value = 0; var first = true; BigInt? bigValue; var list = []; var sb = StringBuffer(); for (var element in valueBytes!) { var b = element & 0xff; if (value < 0x80000000000000) { value = value * 128 + (b & 0x7f); if ((b & 0x80) == 0) { if (first) { var truncated = value ~/ 40; if (truncated < 2) { list.add(truncated); sb.write(truncated); value -= truncated * 40; } else { list.add(2); sb.write('2'); value -= 80; } first = false; } list.add(value); sb.write('.$value'); value = 0; } } else { bigValue ??= BigInt.from(value); bigValue = bigValue << (7); bigValue = bigValue | BigInt.from(b & 0x7f); if ((b & 0x80) == 0) { sb.write('.$bigValue'); bigValue = null; value = 0; } } } objectIdentifierAsString = sb.toString(); objectIdentifier = Uint8List.fromList(list); var identifier = ObjectIdentifiers.getIdentifierByIdentifier(objectIdentifierAsString); if (identifier != null) { readableName = identifier['readableName'] as String?; } } /// /// Creates an [ASN1ObjectIdentifier] entity from the given [name]. /// /// Example: /// ``` /// var oi = ASN1ObjectIdentifier.fromName('ecdsaWithSHA256'); /// ``` /// /// Throws an [UnsupportedObjectIdentifierException] if the given [name] is not supported /// ASN1ObjectIdentifier.fromName(String name) { tag = ASN1Tags.OBJECT_IDENTIFIER; var identifier = ObjectIdentifiers.getIdentifierByName(name); if (identifier == null) { throw UnsupportedObjectIdentifierException(name); } objectIdentifierAsString = identifier['identifierString'] as String?; readableName = identifier['readableName'] as String?; objectIdentifier = identifier['identifier'] as List?; } /// /// Creates an [ASN1ObjectIdentifier] entity from the given [objectIdentifierAsString]. /// /// Example: /// ``` /// var oi = ASN1ObjectIdentifier.fromName('2.5.4.3'); /// ``` /// /// Throws an [UnsupportedObjectIdentifierException] if the given [objectIdentifierAsString] is not supported /// ASN1ObjectIdentifier.fromIdentifierString(this.objectIdentifierAsString, {int tag = ASN1Tags.OBJECT_IDENTIFIER}) : super(tag: tag) { var identifier = ObjectIdentifiers.getIdentifierByIdentifier(objectIdentifierAsString); if (identifier != null) { objectIdentifierAsString = identifier['identifierString'] as String?; readableName = identifier['readableName'] as String?; objectIdentifier = identifier['identifier'] as List?; } else { var splittedInts = objectIdentifierAsString!.split('.'); objectIdentifier = []; for (var i in splittedInts) { objectIdentifier!.add(int.parse(i)); } } } /// /// Encodes this ASN1Object depending on the given [encodingRule] /// /// If no [ASN1EncodingRule] is given, ENCODING_DER will be used. /// /// Supported encoding rules are : /// * [ASN1EncodingRule.ENCODING_DER] /// /// Throws an [UnsupportedAsn1EncodingRuleException] if the given [encodingRule] is not supported. /// @override Uint8List encode( {ASN1EncodingRule encodingRule = ASN1EncodingRule.ENCODING_DER}) { if (encodingRule != ASN1EncodingRule.ENCODING_DER) { throw UnsupportedAsn1EncodingRuleException(encodingRule); } var oi = []; oi.add(objectIdentifier![0] * 40 + objectIdentifier![1]); for (var ci = 2; ci < objectIdentifier!.length; ci++) { var position = oi.length; var v = objectIdentifier![ci]; assert(v >= 0); var first = true; do { var remainder = v & 127; v = v >> 7; if (first) { first = false; } else { remainder |= 0x80; } oi.insert(position, remainder); } while (v > 0); } valueBytes = Uint8List.fromList(oi); valueByteLength = oi.length; return super.encode(); } @override String dump({int spaces = 0}) { var sb = StringBuffer(); for (var i = 0; i < spaces; i++) { sb.write(' '); } sb.write('OBJECT IDENTIFIER $objectIdentifierAsString $readableName'); return sb.toString(); } }