Si todos los dígitos son inferiores o iguales a 127, entonces son muy suerte, ya que pueden ser representados con un solo octeto cada uno. La parte difícil es cuando tienes números más grandes que son comunes, como 1.2.840.113549.1.1.5 (sha1WithRsaEncryption)
. Estos ejemplos se centran en la decodificación, pero la codificación es todo lo contrario.
1. Los primeros dos dígitos '' se representan con un solo byte
Puede decodificar mediante la lectura del primer byte en un entero
var firstByteNumber = 42;
var firstDigit = firstByteNumber/40;
var secondDigit = firstByteNumber % 40;
produce los valores
1.2
2. Los bytes subsiguientes se representan utilizando Variable Length Quantity, también llamada base 128.
VLQ tiene dos formas,
forma corta - Si el octeto comienza con 0, entonces simplemente se representa usando los 7 bits restantes.
Forma larga: si el octeto comienza con 1 (el bit más significativo), combine los siguientes 7 bits de ese octeto más los 7 bits de cada octeto subsiguiente hasta que encuentre un octeto con un 0 como el bit más significativo (esto marca el último octeto).
El valor 840 estaría representado con los dos bytes siguientes,
10000110
01001000
Combine to 00001101001000 and read as int.
gran recurso para codificación BER, http://luca.ntop.org/Teaching/Appunti/asn1.html
El primer octeto tiene un valor 40 * valor1 + valor2.(Esto no es ambiguo, ya que value1 está limitado a los valores 0, 1 y 2; value2 está limitado a el rango 0 a 39 cuando value1 es 0 o 1; y, de acuerdo con X.208, n es siempre al menos 2.)
Los siguientes octetos, si los hay, codifican value3, ..., valuen. Cada valor está codificado en la base 128, el dígito más significativo primero, con el menor número posible de dígitos, y el bit más significativo de cada octeto, excepto el último en la codificación del valor establecido en "1". Ejemplo: El primer octeto de la codificación BER del identificador del objeto de RSA Data Security, Inc. es 40 * 1 + 2 = 42 = 2a16. La codificación de 840 = 6 * 128 + 4816 es 86 48 y la codificación de 113549 = 6 * 1282 + 7716 * 128 + d16 es 86 f7 0d. Esto lleva a la siguiente codificación BER:
06 06 86 48 86 2a f7 0d
Por último, aquí es un decodificador OID que acabo de escribir en Perl.
sub getOid {
my $bytes = shift;
#first 2 nodes are 'special';
use integer;
my $firstByte = shift @$bytes;
my $number = unpack "C", $firstByte;
my $nodeFirst = $number/40;
my $nodeSecond = $number % 40;
my @oidDigits = ($nodeFirst, $nodeSecond);
while (@$bytes) {
my $num = convertFromVLQ($bytes);
push @oidDigits, $num;
}
return join '.', @oidDigits;
}
sub convertFromVLQ {
my $bytes = shift;
my $firstByte = shift @$bytes;
my $bitString = unpack "B*", $firstByte;
my $firstBit = substr $bitString, 0, 1;
my $remainingBits = substr $bitString, 1, 7;
my $remainingByte = pack "B*", '0' . $remainingBits;
my $remainingInt = unpack "C", $remainingByte;
if ($firstBit eq '0') {
return $remainingInt;
}
else {
my $bitBuilder = $remainingBits;
my $nextFirstBit = "1";
while ($nextFirstBit eq "1") {
my $nextByte = shift @$bytes;
my $nextBits = unpack "B*", $nextByte;
$nextFirstBit = substr $nextBits, 0, 1;
my $nextSevenBits = substr $nextBits, 1, 7;
$bitBuilder .= $nextSevenBits;
}
my $MAX_BITS = 32;
my $missingBits = $MAX_BITS - (length $bitBuilder);
my $padding = 0 x $missingBits;
$bitBuilder = $padding . $bitBuilder;
my $finalByte = pack "B*", $bitBuilder;
my $finalNumber = unpack "N", $finalByte;
return $finalNumber;
}
}
+1 para el decodificador asn.1. Gracias. si solo hubiera sabido entonces ... :-) –
Pero, ¿cómo puedo saber cuál es un valor válido para un OID específico? En mi caso para OID 1.3.6.1.5.5.7.48.1.5 el valor (según entiendo) es 04020500. ¿Tiene una interpretación específica? – Cratylus
Fuera del contexto, es muy difícil decir qué es 04020500. No parece un OID en absoluto. – Codo