twonly-app-dependencies/pointycastle/lib/asn1/primitives/asn1_object_identifier.dart
2025-12-07 16:10:41 +01:00

189 lines
5.6 KiB
Dart

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<int>? 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 = <int>[];
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<int>?;
}
///
/// 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<int>?;
} else {
var splittedInts = objectIdentifierAsString!.split('.');
objectIdentifier = <int>[];
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 = <int>[];
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();
}
}