Jak ASN.1 zakodować identyfikator obiektu?

Mam problem ze zrozumieniem podstawowych pojęć ASN.1.

Jeśli typ jest OID, czy odpowiednia liczba jest faktycznie zakodowana w danych binarnych?

Na przykład w tej definicji:

id-ad-ocsp         OBJECT IDENTIFIER ::= { id-ad 1 }

Czy odpowiedni 1.3.6.1.5.5.7.48.1 jest kodowany w binarnym dokładnie tak?

Pytam o to, ponieważ próbuję zrozumieć konkretną wartość, którą widzę w pliku DER (certyfikacie), czyli 04020500, i nie jestem pewien, jak interpretować to.

Author: Paŭlo Ebermann, 2011-05-08

3 answers

Tak, OID jest zakodowany w danych binarnych. OID 1.3.6.1.5.5.7.48.1 wspominasz staje się 2b 06 01 05 05 07 30 01 (pierwsze dwie liczby są zakodowane w jednym bajcie, wszystkie pozostałe liczby są zakodowane w jednym bajcie, ponieważ wszystkie są mniejsze niż 128).

Ładny opis kodowania OID znajduje się tutaj .

Ale najlepszym sposobem analizy ASN.1 Dane należy wkleić do dekodera internetowego, np. http://lapo.it/asn1js/.

 28
Author: Codo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-08 17:57:11

Jeśli wszystkie Twoje cyfry są mniejsze lub równe 127, to masz bardzo szczęście, ponieważ mogą być reprezentowane przez jeden oktet każdy. Najtrudniejsze jest to, gdy masz większe liczby, które są wspólne, takie jak 1.2.840.113549.1.1.5 (sha1WithRsaEncryption). Przykłady te koncentrują się na dekodowaniu, ale kodowanie jest dokładnie odwrotnie.

1. Pierwsze dwie 'cyfry' reprezentowane są pojedynczym bajtem

Możesz dekodować, odczytując pierwszy bajt do liczby całkowitej

var firstByteNumber = 42;
var firstDigit = firstByteNumber / 40;
var secondDigit = firstByteNumber % 40;

Produkuje wartości

1.2

2. Kolejne bajty są reprezentowane za pomocą zmiennej długości , zwanej również bazą 128.

VLQ ma dwie formy,

Krótka forma - Jeśli oktet zaczyna się od 0, to jest po prostu reprezentowany za pomocą pozostałych 7 bitów.

Długa Forma - jeśli oktet zaczyna się od 1 (najbardziej znaczącego bitu), połącz następne 7 bitów tego oktetu z 7 bitami każdego następnego oktetu, aż natkniesz się na oktet z 0 jako najbardziej znaczącym bit (oznacza to ostatni oktet).

Wartość 840 będzie reprezentowana przez następujące dwa bajty,

10000110
01001000

Combine to 00001101001000 and read as int.

Świetny zasób do kodowania BER, http://luca.ntop.org/Teaching/Appunti/asn1.html

Pierwszy oktet ma wartość 40 * wartość 1 + wartość 2. (Jest to jednoznaczne, ponieważ wartość 1 jest ograniczona do wartości 0, 1 i 2; wartość 2 jest ograniczona do zakres od 0 do 39, gdy wartość 1 wynosi 0 LUB 1; oraz, zgodnie z X. 208, N wynosi zawsze co najmniej 2.)

Następujące oktety, jeśli istnieją, kodują wartość 3, ..., valuen. Każda wartość jest zakodowana baza 128, najważniejsza cyfra pierwsza, z jak najmniejszą liczbą cyfr i najbardziej znaczącym bitem każdego oktet z wyjątkiem ostatniego w kodowaniu wartości ustawionego na "1."Przykład: The pierwszy oktet kodowania BER RSA Data Security, Inc."s object IDENTYFIKATOR to 40 * 1 + 2 = 42 = 2a16. Kodowanie 840 = 6 * 128 + 4816 to 86 48 i kodowanie 113549 = 6 * 1282 + 7716 * 128 + d16 is 86 f7 0d. prowadzi to do następującego kodowania BER:

06 06 2A 86 48 86 f7 0D


Na koniec, oto dekoder OID, który właśnie napisałem w Perlu.

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;
    }

}
 14
Author: Despertar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-14 03:16:43

Kodowanie OID dla manekinów :):

  • każdy komponent OID jest kodowany do jednego lub więcej bajtów (oktetów)
  • kodowanie OID jest tylko konkatenacją tych kodowań składowych OID
  • pierwsze dwa komponenty są kodowane w specjalny sposób (patrz niżej)
  • Jeśli wartość binarna komponentu OID ma mniej niż 7 bitów, kodowanie jest tylko jednym oktetem, trzymającym wartość komponentu (Uwaga, najbardziej znaczący bit, lewy, zawsze będzie 0)
  • w przeciwnym razie, jeśli ma 8 i więcej bitów, wartość jest "rozłożona" na wiele oktetów - dzieli reprezentację binarną na 7 bitów (od prawej), w razie potrzeby pierwszy z zerami, i tworzy oktety z tych septetów, dodając najbardziej znaczący (lewy) bit 1, z wyjątkiem ostatniego fragmentu, który będzie miał tam bit 0.
  • pierwsze dwa komponenty (X. Y) są kodowane tak, jakby były pojedynczym komponentem o wartości 40*X + Y

Jest to przeredagowanie zalecenia ITU-T X. 690 , rozdział 8.19

 8
Author: mykhal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-11 11:54:04