Мне нужен пример, чтобы понять неявные теги в ASN.1 - PullRequest
9 голосов
/ 21 июля 2010

Я прошел следующий урок

http://www.obj -sys.com / asn1tutorial / node12.html

Можете ли вы помочь мне понять неявные теги на примере?

Ответы [ 3 ]

38 голосов
/ 03 июня 2015

В тегах ASN.1 фактически есть две цели: печатать и называть.Типизирование означает, что он сообщает энкодеру / декодеру, какой это тип данных (это строка, целое число, логическое значение, набор и т. Д.), А именование означает, что если имеется несколько полей одного типа и несколько (или все они) являются необязательными, они указывают en / decoder, для какого поля это значение имеет значение.

Если вы сравниваете ASN.1, скажем, с JSON, и смотрите следующие данные JSON:

"Image": {
    "Width":  800,
    "Height": 600,
    "Title":  "View from 15th Floor"
}

Вы заметите, что в JSON каждое поле всегда имеет явное имя («Изображение», «Ширина», «Высота», «Заголовок») и имеет явную или неявную типизацию («Заголовок» - этострока, так как ее значение заключено в кавычки, "Width" является целым числом, потому что в нем нет кавычек, только цифр, это не "null", "true" или "false", и у него нет десятичного периода).

В ASN.1 этот фрагмент данных будет:

Image ::= SEQUENCE { 
    Width  INTEGER,
    Height INTEGER,
    Title  UTF8String
 }

Это будет работать без каких-либо специальных тегов, здесь требуются только универсальные теги. Универсальные теги не называют данные, они просто вводят данные, поэтому en / decoder знает, что первые два значения являются целыми числами, а последнее - строкой.То, что первое целое число является шириной, а второе - высотой, не нужно кодировать в потоке байтов, оно определяется их порядком (последовательности имеют фиксированный порядок, наборы - нет. На странице, на которую вы ссылались наборы,используется).

Теперь измените схему следующим образом:

Image ::= SEQUENCE { 
    Width  INTEGER OPTIONAL,
    Height INTEGER OPTIONAL,
    Title  UTF8String
 }

Хорошо, теперь у нас проблема.Предположим, что получены следующие данные:

INTEGER(750), UTF8String("A funny kitten")

Что такое 750?Ширина или Высота?Может быть Width (и Height отсутствует) или может быть Height (и Width отсутствует), оба будут выглядеть так же, как двоичный поток.В JSON это будет понятно, поскольку каждый фрагмент данных назван, а в ASN.1 - нет.Теперь одного типа недостаточно, теперь нам также нужно имя.Вот где в игру вступают неуниверсальные теги.Измените его на:

Image ::= SEQUENCE { 
    Width  [0] INTEGER OPTIONAL,
    Height [1] INTEGER OPTIONAL,
    Title  UTF8String
 }

И если вы получите следующие данные:

[1]INTEGER(750), UTF8String("A funny kitten")

Вы знаете, что 750 - это высота, а не ширина (просто нет ширины).Здесь вы объявляете новый тег (в данном случае специфичный для контекста), который служит двум целям: он сообщает en / decoder, что это целочисленное значение (типирование), и сообщает ему, какое целочисленное значение (naming).

Но в чем разница между неявной и явной пометкой? Разница в том, что неявная пометка просто именует данные, en / декодер должен неявно знать тип для этого имени, в то время как явные теговые имена и явно вводят данные .

Если тегирование является явным, данные будут отправлены как:

[1]INTEGER(xxx), UTF8String(yyy)

, так что даже еслидекодер не знает, что [1] означает «высота», он знает, что байты «xxx» должны быть проанализированы / интерпретированы как целочисленное значение.Другое важное преимущество явного тегирования заключается в том, что тип может быть изменен в будущем без изменения тега.Например,

Length ::= [0] INTEGER

можно изменить на

Length ::= [0] CHOICE { 
    integer INTEGER,
    real    REAL 
}

. Тег [0] по-прежнему означает длину, но теперь длина может быть целым числом или значением с плавающей запятой.Поскольку тип кодируется явно, декодеры всегда будут знать, как правильно декодировать значение, и, следовательно, это изменение является прямой и обратной совместимостью (по крайней мере, на уровне декодера, не обязательно обратной совместимостью на уровне приложения).

Если тегированиенеявно, данные будут отправлены как:

[1](xxx), UTF8String(yyy)

Декодер, который не знает, что такое [1], не будет знать тип «xxx» и, следовательно, не сможет правильно проанализировать / интерпретировать эти данные,В отличие от JSON, значения в ASN.1 являются просто байтами.Таким образом, «xxx» может быть одним, двумя, тремя или, может быть, четырьмя байтами, и то, как декодировать эти байты, зависит от их типа данных, который не предусмотрен в самом потоке данных.Также изменение типа [1] наверняка сломает существующие декодеры.

Хорошо, но зачем кому-то использовать неявные теги? Разве не лучше всегда использовать явные теги? При явном тегировании тип также должен быть закодирован в потоке данных, и для этого потребуется два дополнительных байта на тег. Для передач данных, содержащих несколько тысяч (может быть, даже миллионов) тегов и где, возможно, учитывается каждый отдельный байт (очень медленное соединение, крошечные пакеты, высокая потеря пакетов, очень слабые устройства обработки) и где обе стороны в любом случае знают все пользовательские теги, зачем тратить пропускную способность , память, время хранения и / или обработки для кодирования, передачи и декодирования ненужной информации типа?

Имейте в виду, что ASN.1 является довольно старым стандартом и предназначался для обеспечения очень компактного представления данных в то время, когда пропускная способность сети была очень дорогой, а процессоры - в несколько сотен раз медленнее, чем сегодня. Если вы посмотрите на все передачи данных XML и JSON на сегодняшний день, даже смешно думать о том, чтобы сэкономить два байта на тег.

2 голосов
/ 03 февраля 2011

Я нахожу этот поток достаточно понятным, он также содержит (маленькие) примеры, даже если они довольно "экстремальные" примеры. Более «реалистичные» примеры с использованием тэгов IMPLICIT можно найти на этой странице .

0 голосов
/ 31 мая 2019

Использование принятого ответа в качестве примера кодировки:

Image ::= SEQUENCE { 
    Width  INTEGER,
    Height INTEGER,
    Title  UTF8String
}

Примером кодировки будет:

enter image description here

Внутренняя последовательность разбивается на:

enter image description here

Явный Необязательный

Если у вас есть EXPLICIT OPTIONAL значения:

Image ::= SEQUENCE { 
    Width  [0] EXPLICIT INTEGER OPTIONAL,
    Height [1] EXPLICIT INTEGER OPTIONAL,
    Title  UTF8String
}

Кодированная последовательность может быть:

  • ПОСЛЕДОВАТЕЛЬНОСТЬ 30 15 A1 02 02 02 EE 0C 0E 41 20 66 75 6E 6E 79 20 6B 69 74 74 65 6E (21 байт)

И внутренняя последовательность разбивается на:

  • КОНТЕКСТ [1] INTEGER : A1 02 02 02 EE 750 (2 байта)
  • UTF8STRING : 0C 0E 41 20 66 75 6E 6E 79 20 6B 69 74 74 65 6E "Смешной котенок" (14 байтов)
...