Как АСН.1 кодируют идентификатор объекта?
У меня возникли проблемы с пониманием основных понятий ASN.1.
Если тип является OID, действительно ли соответствующее число кодируется в двоичных данных?
например, в этом определении:
id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 }
соответствующий 1.3.6.1.5.5.7.48.1 кодируется в двоичном именно такой?
Я спрашиваю это, потому что я пытаюсь понять конкретное значение, которое я вижу в файле DER (сертификат), который является 04020500, и я не знаю, как это интерпретировать.
3 ответов
да, OID кодируется в двоичных данных. OID 1.3.6.1.5.5.7.48.1, который вы упоминаете, становится 2b 06 01 05 05 07 30 01 (первые два числа кодируются в одном байте, все остальные номера кодируются в одном байте, потому что все они меньше 128).
найдено хорошее описание кодировки OID здесь.
но лучший способ проанализировать ваш ASN.1 Данные должны вставляться в онлайн-декодер, например http://lapo.it/asn1js/.
если все ваши цифры меньше или равно 127, то вы очень повезло, потому что они могут быть представлены с помощью одного восьмиразрядного байта каждый. Хитрая часть, когда у вас есть большие числа, которые являются общими, такие как 1.2.840.113549.1.1.5 (sha1WithRsaEncryption)
. Эти примеры сосредоточены на декодировании, но кодирование как раз наоборот.
1. Первые две "цифры" представлены одним байтом
вы можете расшифровать путем чтение первого байта в целое число
var firstByteNumber = 42;
var firstDigit = firstByteNumber / 40;
var secondDigit = firstByteNumber % 40;
производит значения
1.2
2. Последующие байты представлены с помощью Количество Переменной Длины, также называемый базой 128.
VLQ имеет две формы,
Short Form - если октет начинается с 0, то он просто представлен с использованием оставшихся 7 бит.
длинная форма-Если октет начинается с 1 (самый значительный бит), объедините следующие 7 бит этого октета плюс 7 бит каждого последующего октета, пока вы не столкнетесь с октетом с 0 в качестве наиболее значимого бита (это отмечает последний октет).
значение 840 будет представлено следующими двумя байтами,
10000110
01001000
Combine to 00001101001000 and read as int.
отличный ресурс для кодирования BER,http://luca.ntop.org/Teaching/Appunti/asn1.html
первый октет имеет значение 40 * value1 + value2. (Это однозначно, поскольку value1 ограничено значениями 0, 1 и 2; value2 ограничено диапазон от 0 до 39, когда значение 1 равно 0 или 1; и, согласно X. 208, n равно всегда как минимум 2.)
следующие октеты, если таковые имеются, кодируют value3,..., valuen. Каждое значение кодируется базой 128, наиболее значимая цифра первая, с как можно меньшим количеством цифр и самым значительным битом каждого октет, за исключением последнего в кодировке значения, установлен в "1."Пример: первый октет BER-кодировки RSA Data Security, Inc.'ы объект идентификатор 40 * 1 + 2 = 42 = 2a16. Кодировка 840 = 6 * 128 + 4816 является 86 48 и кодирование 113549 = 6 * 1282 + 7716 * 128 + d16 это 86 0d с ф7. Это приводит к следующим BER кодировка:
06 06 В 2A 86 48 86 F7 и 0d с
наконец, вот декодер OID, который я только что написал в 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;
}
}
кодировка OID для чайников :):
- каждый компонент OID кодируется в один или несколько байтов (октетов)
- кодировка OID-это просто конкатенация этих кодировок компонентов OID
- первые два компонента кодируются особым образом (см. ниже)
- Если двоичное значение компонента OID имеет менее 7 бит, кодировка представляет собой всего один октет, содержащий значение компонента (обратите внимание, самый значительный бит, самый левый, всегда будет 0)
- в противном случае, если он имеет 8 и более бит, значение "разбивается" на несколько октетов - разбейте двоичное представление на 7 битных кусков (справа), слева-поместите первый с нулями, если это необходимо, и сформируйте октеты из этих септетов, добавив самый значительный (левый) бит 1, за исключением последнего куска, который будет иметь бит 0.
- первые два компонента (X. Y) кодируются как один компонент со значением 40*X + Y
Это переформулировать рекомендации МСЭ-Т Х. 690, глава 8.19