- []
- []
**ASN.1** (англ. //Abstract Syntax Notation One//)
В области телекоммуникаций и компьютерных сетей язык для описания абстрактного синтаксиса данных (ASN.1), используемый OSI. Стандарт записи, описывающий структуры данных для представления, кодирования, передачи и декодирования данных. Он обеспечивает набор формальных правил для описания структуры объектов, которые не зависят от конкретной машины. ASN.1 является ISO и ITU-T совместимым стандартом, первоначально был определён в 1984 году в рамках CCITT X.409:1984. Из-за широкого применения ASN.1 в 1988 году перешёл в свой собственный стандарт X.208. Начиная с 1995 года, существенно пересмотренный ASN.1 описывается стандартом X.680.
В России ASN.1 стандартизирован по ГОСТ Р ИСО/МЭК 8824-1-2001 и ГОСТ Р ИСО/МЭК 8825-93
В Ниже приведен список часто используемых стандартов для Windows, которые написаны на языке ASN.1.
- X.400 (обмена электронными сообщениями)
- X.500 (Directory Services)
- X.200 (связи сеть)
- Протокол доступа к каталогам или LDAP
ASN.1 синтаксис представлен в виде нотаций ASN.1:1988,ASN.1:1990, ASN.1:1997, и ASN.1:2002 , и следующими правилами кодирования BER, CER, DER, PER (aligned или unaligned), XER, CXER, и E-XER.
В общем виде такое описание имеет вид:
data type value name | data type identifier ::= data value
или
{data type identifier (data value)}
Пример определения сообщения в нотации ASN.1:
REPORT DEFINITIONS ::= BEGIN Report ::= SEQUENCE { author OCTET STRING, title OCTET STRING, body OCTET STRING, biblio Bibliography } Bibliography ::= SEQUENCE { author OCTET STRING, title OCTET STRING, publisher OCTET STRING, year OCTET STRING } END
В этом примере «Report» - имя типа сообщения. SEQUENCE означает, что сообщение является последовательностью элементов данных. Первые четыре элемента имеют тип данных OCTET STRING, т.е. каждый является строкой из восьмибитных байтов (применён термин OCTET (октет), а не BYTE (байт), т.к. на некоторых компьютерах байт состоит не из восьми бит). Элемент «biblio» есть другое определение с именем «Bibliography».
Данный ANS.1 файл report.asn после компиляции:
"C:\ans1-acv644\bin\asn1c" "C:/ans1-acv644/my-2/report.asn" -I ..\csharp\vs2008 -O "C:/ans1-acv644/my-2" -ber -asnstd x208 -xsd -html -c# -depends -compat 6.3 -writer -reader -test -noUniqueNames -dirs -list -warnings
// // This file was generated by the Objective Systems ASN1C Compiler // (http://www.obj-sys.com). Version: 6.4.4, Date: 05-Oct-2011. // using System; using Com.Objsys.Asn1.Runtime; namespace REPORT { public class Report : Asn1Type { public Asn1OctetString author; public Asn1OctetString title; public Asn1OctetString body; public Bibliography biblio; static Report () { Asn1Type.SetKey2 (_REPORTValues._rtkey); } public Report () : base() { Init(); } /// <summary> /// This constructor sets all elements to references to the /// given objects /// </summary> public Report ( Asn1OctetString author_, Asn1OctetString title_, Asn1OctetString body_, Bibliography biblio_ ) : base () { author = author_; title = title_; body = body_; biblio = biblio_; } /// <summary> /// This constructor allows primitive data to be passed for all /// primitive elements. It will create new object wrappers for /// the primitive data and set other elements to references to /// the given objects /// </summary> public Report (byte[] author_, byte[] title_, byte[] body_, Bibliography biblio_ ) : base () { author = new Asn1OctetString (author_); title = new Asn1OctetString (title_); body = new Asn1OctetString (body_); biblio = biblio_; } public void Init () { author = null; title = null; body = null; biblio = null; } public override void Decode (Asn1BerDecodeBuffer buffer, bool explicitTagging, int implicitLength) { int llen = (explicitTagging) ? MatchTag (buffer, Asn1Tag.SEQUENCE) : implicitLength; Init (); // decode SEQUENCE Asn1BerDecodeContext _context = new Asn1BerDecodeContext (buffer, llen); IntHolder elemLen = new IntHolder(); // decode author if (_context.MatchElemTag (Asn1Tag.UNIV, Asn1Tag.PRIM, 4, elemLen, false)) { buffer.Context.EventDispatcher.StartElement("author", -1); author = new Asn1OctetString(); author.Decode (buffer, true, elemLen.mValue); buffer.InvokeCharacters(author.ToString()); buffer.Context.EventDispatcher.EndElement("author", -1); } else throw new Asn1MissingRequiredException (buffer); // decode title if (_context.MatchElemTag (Asn1Tag.UNIV, Asn1Tag.PRIM, 4, elemLen, false)) { buffer.Context.EventDispatcher.StartElement("title", -1); title = new Asn1OctetString(); title.Decode (buffer, true, elemLen.mValue); buffer.InvokeCharacters(title.ToString()); buffer.Context.EventDispatcher.EndElement("title", -1); } else throw new Asn1MissingRequiredException (buffer); // decode body if (_context.MatchElemTag (Asn1Tag.UNIV, Asn1Tag.PRIM, 4, elemLen, false)) { buffer.Context.EventDispatcher.StartElement("body", -1); body = new Asn1OctetString(); body.Decode (buffer, true, elemLen.mValue); buffer.InvokeCharacters(body.ToString()); buffer.Context.EventDispatcher.EndElement("body", -1); } else throw new Asn1MissingRequiredException (buffer); // decode biblio if (_context.MatchElemTag (Asn1Tag.UNIV, Asn1Tag.CONS, 16, elemLen, false)) { buffer.Context.EventDispatcher.StartElement("biblio", -1); biblio = new Bibliography(); biblio.Decode (buffer, true, elemLen.mValue); buffer.Context.EventDispatcher.EndElement("biblio", -1); } else throw new Asn1MissingRequiredException (buffer); if (explicitTagging && llen == Asn1Status.INDEFLEN) { MatchTag (buffer, Asn1Tag.EOC); } } public override int Encode (Asn1BerEncodeBuffer buffer, bool explicitTagging) { int _aal = 0, len; // encode biblio buffer.Context.EventDispatcher.StartElement("biblio", -1); len = biblio.Encode (buffer, true); _aal += len; buffer.Context.EventDispatcher.EndElement("biblio", -1); // encode body buffer.Context.EventDispatcher.StartElement("body", -1); len = body.Encode (buffer, true); _aal += len; buffer.Context.EventDispatcher.EndElement("body", -1); // encode title buffer.Context.EventDispatcher.StartElement("title", -1); len = title.Encode (buffer, true); _aal += len; buffer.Context.EventDispatcher.EndElement("title", -1); // encode author buffer.Context.EventDispatcher.StartElement("author", -1); len = author.Encode (buffer, true); _aal += len; buffer.Context.EventDispatcher.EndElement("author", -1); if (explicitTagging) { _aal += buffer.EncodeTagAndLength (Asn1Tag.SEQUENCE, _aal); } return (_aal); } } }
После работы парсера создается каталог с необходимыми для компиляции исходных файлов в Visual Studio. C VS2008 проблем не будет. В VS2010 проект необходимо будет собрать вручную. При построении проекта используется ans1rt.dll, которая поставляется вместе с парсером, все стальное создается в результате компиляции из файлов:
Bibliography.cs Report.cs REPORT.mk _REPORTValues.cs Reader.cs Writer.cs report.ans
Если есть желание получить готовый проект пишите и задавайте вопросы в форуме. Наша цель, сформировать из выше приведенного файла report.ans программу кодирования (Writer.exe) и декодрования (Reader.exe)
C:\ans1-acv644\my-2\REPORT\writer\bin\Debug>writer.exe -v -o report Encoding was successful Hex dump of encoded record: 30 41 04 09 76 40 a9 cf 43 4b 84 37 de 04 03 31 0A..v@..CK.7...1 6f d3 04 09 e8 41 b1 58 05 c5 fd 46 b0 30 24 04 o....A.X...F.0$. 05 24 fc 7f 8a b7 04 09 4a 97 16 dd 9f a2 48 fb .$.⌂....J.....H. 25 04 05 26 58 aa 25 a5 04 09 61 31 52 b9 e3 c0 %..&X.%...a1R... 59 fd 10 Y.. Binary dump: 0000 : 30 41 : C [UNIVERSAL 16] 65 0002 : 04 09 : P [UNIVERSAL 4] 9 0004 : 76 40 a9 cf 43 4b 84 37 de : v@..CK.7. 0013 : 04 03 : P [UNIVERSAL 4] 3 0015 : 31 6f d3 : 1o. 0018 : 04 09 : P [UNIVERSAL 4] 9 0020 : e8 41 b1 58 05 c5 fd 46 b0 : .A.X...F. 0029 : 30 24 : C [UNIVERSAL 16] 36 0031 : 04 05 : P [UNIVERSAL 4] 5 0033 : 24 fc 7f 8a b7 : $.⌂.. 0038 : 04 09 : P [UNIVERSAL 4] 9 0040 : 4a 97 16 dd 9f a2 48 fb 25 : J.....H.% 0049 : 04 05 : P [UNIVERSAL 4] 5 0051 : 26 58 aa 25 a5 : &X.%. 0056 : 04 09 : P [UNIVERSAL 4] 9 0058 : 61 31 52 b9 e3 c0 59 fd 10 : a1R...Y..
В результате создается бинарный файл report
0000000000: 30 41 04 09 76 40 A9 CF │ 43 4B 84 37 DE 04 03 31 0A♦○v@cПCK"7Ю♦♥1 0000000010: 6F D3 04 09 E8 41 B1 58 │ 05 C5 FD 46 B0 30 24 04 oУ♦○иA+X♣ЕэF°0$♦ 0000000020: 05 24 FC 7F 8A B7 04 09 │ 4A 97 16 DD 9F A2 48 FB ♣$ь⌂?•♦○J-■Э?ўHы 0000000030: 25 04 05 26 58 AA 25 A5 │ 04 09 61 31 52 B9 E3 C0 %♦♣&XЄ%?♦○a1R№гА 0000000040: 59 FD 10 │ Yэ►
Это то что будет в итоге формировать PDU пакет. Затем пробуем прочитать этот бинарный файл (декодируем)
C:\ans1-acv644\my-2\REPORT\reader\bin\Debug>reader.exe -v -i report Decode was successful value = REPORT.Report