- PVSM.RU - https://www.pvsm.ru -
Продолжаю публикацию на Хабре глав из своей статьи "ASN.1 простыми словами". Предыдущая часть может быть найдена по адресу ASN.1 простыми словами (кодирование типа REAL) [1].
Общее описание типа:
Сам по себе OBJECT IDENTIFIER представляет собой набор целых без знаковых чисел, разделенных знаком ".". Примеры возможных OBJECT IDENTIFIER: 0.1.1, 1.1.1, 2.1234.1234.1234.1234.
Кодирование OBJECT IDENTIFIER (OID) состоит из последовательного кодирования всех составляющих данный OID без знаковых целых (SID — sub identifier).
Для уменьшения общего размера закодированного OID к первым двум SID применяются следующие правила:
Примеры кодирования первых двух октетов:
Каждый SID кодируется не зависимо от остальных. Все SID кодируются друг за другом без дополнительных разделителей. Правила кодирования SID одинаковы для всех SID кроме первых двух (см. выше).
Нужно отметить, что теоретически каждый SID может иметь сколько угодно большое целое значение. Следовательно каждый отдельный SID может кодироваться произвольным, сколь угодно большим, количеством октетов. Обычно для кодирования переменного количества октетов применяется дополнительное кодирование количества этих октетов (перед последовательностью закодированных октетов кодируется октет, содержащий количество закодированных октетов). Однако в случае кодирования SID применяется другой подход — самый старший бит каждого из октетов, кодирующих отдельный SID, является своеобразным флагом, по которому можно судить последний ли это октет для данного SID или нет. То есть так как один SID может быть закодирован с помощью более чем одного октета (в случае большого целого числа), то применяется следующее правило: во всех октетах, кодирующих значение SID, кроме последнего (младшего) октета значение самого старшего бита должно быть установлено в 1. Таким образом получается, что значащими для кодирования SID битами в 8-ми битовом октете являются только младшие 7 бит, старший бит в каждом октете используется как флаг, указывающий на последний октет. В связи с этим перед кодированием каждый SID переводится из десятичной формы форму разложения по основанию 128 (группируется по 7 бит).
Примеры кодирования SID:
При кодировании SID должно использоваться минимальное количество октетов. То есть SID = 643 не должен быть представлен как ( 0*1282 + 5*1281 + 3*1280 ) = ( 00 05 03 )256 и, следовательно, не должен быть закодирован как ( 80 85 03 )256. Простейшая проверка на правильность кодирования SID — первый октет закодированного SID не должен быть равен 80256.
Общее описание типа:
Вопросы кодирования целых (INTEGER) уже рассматривался ранее (в главе про кодирование типа REAL). Однако еще раз напомним основные особенности этого кодирования.
В ASN.1 могут быть закодированы как положительные, так и отрицательные числа. Каждое целое число практически не ограничено в своей величине (то есть в ASN.1 могут быть закодированы сколь угодно большие (по модулю) целые числа).
Каждое целое число кодируется последовательностью октетов, каждый октет представляет собой 8 бит информации. Каждый октет представляет собой «вес» перед соответствующей степенью числа 256, участвующий в разложении кодируемого числа по основанию 256. То есть для кодирования числа исходное число сначала разлагается по основанию 256, и затем значения «весов» перед соответствующими степенями 256 кодируются в качестве октетов. Например число 8388607 будет кодироваться по следующей схеме:
Кодирование отрицательных целых значений осуществляется по отдельным правилам. Фактически в закодированном отрицательном целом хранится не одно, а два целых числа: основное число и число, которое нужно вычесть из основного числа, чтобы при декодировании получить изначально закодированное отрицательное число. То есть при декодировании изначальное отрицательное число получается по формуле: N = X — Y, где X — основное число, а Y — вычитаемое число. Не трудно понять, что для того, чтобы N получилось отрицательным, необходимо чтобы выполнялось условие Y > X.
Подробные правила формирования как основного, так и вычитаемого числа уже были описаны ранее, поэтому отсылаю читателя к главе о кодировании типа REAL.
Примеры кодирования целых чисел:
Фактически к кодируемому целому числу предъявляется требование: старшие 9 бит закодированного числа не должны все быть равны 1, и не должны все быть равны 0 (старшие 9 бит закодированного числа не должны быть равны между собой). Если первые 9 бит закодированного числа равны 0, то значит без ущерба для закодированного значения старший октет (старшие 8 бит) можно отбросить (при декодировании он бы просто добавил слагаемое 0*256n, что никак не повлияет на значение числа). Если же старшие 9 бит закодированного числа равны 1 то закодированное число отрицательное и может быть перекодировано с применением меньшего числа октетов (при кодировании были добавлены лишние нулевые октеты в вычитаемое число).
Пример добавления лишних нулевых октетов в вычитаемое число. Возьмем для кодирования число (-128). Положим вычитаемое число будет равно: (80 00)256 = 3276810, и основное значение вычисляется после решения уравнения ( x — 32768 ) = -128. Следовательно x = 3264010 = ( 7F 80 )256. Устанавливая старший бит получаем окончательное кодирование (FF 80)256 (здесь равны между собой 9 старших бит). Но ранее мы уже кодировали число (-128) и знаем, что кодирование этого числа в ASN.1 может быть представлено в более короткой форме — в виде только одного октета (80)256;
Ну и в конце этой главы ещё раз напомним читателю, что в современных компьютерных системах кодирование целых чисел уже (автоматически) осуществляется по выше описанным правилам. Правда с одной оговоркой: для кодирования отрицательных чисел все-таки применяется «добавление лишних нулевых октетов в вычитаемое число» (см. предыдущий параграф). То есть если количество октетов (байт) для хранения целого числа составляет 4, то число (-128) будет закодировано в виде FF FF FF 80 (то есть при кодировании было применено «вычитаемое число» равное (80 00 00 00)256 = 2147483648).
В ASN.1 применяется кодирование для достаточно широкого набора строковых типов. Вот их полный перечень:
Некоторые из них уже являются устаревшими и не применяемыми типами строк (например VideotexString). Каждый тип строк описывает некий набор символов, которые можно применять в строках с данным типом. Дополнительно в используемых строках также могут применяться так называемые «управляющие последовательности», позволяющие автоматически настраивать обработку отдельно выделенной строки на поддерживающих эту возможность терминалах. Тот, кто программировал на СС++ наверняка часто использовал «управляющую последовательность» n — перевод строки. На самом деле управляющих последовательностей очень много уже в стандарте, кроме того можно создавать собственные управляющие последовательности, которые будут обрабатываться только на специализированных терминалах (например переключать цвет выделенных строк на красный, подчеркивать строки и т.п.).
Наиболее продвинутыми и современными форматами являются форматы строк, основанные на стандарте Unicode. Основу стандарта составляет документ ISO 10646.
Тип UniversalString (класс тэга UNIVERSAL, номер тэга 28, форма кодирования — примитивная). Кодирует Unicode строки, где каждый символ кодируется 4-мя байтами (октетами).
Тип BMPString (класс тэга UNIVERSAL, номер тэга 30, форма кодирования — примитивная). Подмножество символов Unicode, каждый символ кодируется всегда 2-мя байтами (октетами).
Тип UTF8String (класс тэга UNIVERSAL, номер тэга 12, форма кодирования — примитивная). Представление символов Unicode, но с дополнительной обработкой, позволяющей кодировать каждый символ в последовательность байт переменной длины (от 1 до 7-ми байт).
Все типы описывающие дату и время в ASN.1 являются обыкновенными UTF-8 строками, где значения для года, месяца и так далее кодируется в определенном формате. Форматы для представления каждого типа описываются в свободно доступном стандарте ISO 8601.
Тип UTCTime. Простейший временной тип. Может кодировать только дату и UTC (Universal Coordinated Time) время. Формат строки, кодирующей UTCTime, может иметь либо вид YYMMDDHHMMSSZ (где YY — две последние цифры года, MM — две цифры месяца, DD — две цифры дня, HH — две цифры часа (формат 24-х часовой), MM — две цифры минут, SS — две цифры секунд), либо может также кодировать UTC время вместе с относительным смещением для соответствующего часового пояса в виде YYMMDDHHMMSS+hhmm (или YYMMDDHHMMSS-hhmm).
Тип GeneralizedTime. Расширение типа UTCTime, использующее уже 4 цифры для обозначения года, плюс тип GeneralizedTime позволяет использовать дробные значения для любой из временных составляющих (часа, минуты или секунды). Соответственно форматы могут быть следующими:
Все описанные ниже типы являются новыми для последней версии стандарта X.680:2008.
Тип TIME. Описывает только время в формата HH:MM:SS, либо в формате HHMMSS.
Тип TIME-OF-DAY. То же самое, что и тип TIME, за исключением того, что формат может быть только HHMMSS.
Тип DATE. Описывает только дату в формате YYYYMMDD.
Тип DATE-TIME. Описывает как дату, так и время для этой даты. Формат представления YYYYMMDDHHMMSS. В случае если значение крайних фракций времени равно 0 (то есть например 0 секунд), то нулевое значение может быть исключено (строка сокращена).
Тип DURATION. Описывает разность между двумя временными промежутками. Формат представления nnYnnMnnDTnnHnnMnnS.
Автор: ystr
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/setevy-e-tehnologii/14409
Ссылки в тексте:
[1] ASN.1 простыми словами (кодирование типа REAL): http://habrahabr.ru/post/150757/
Нажмите здесь для печати.