2 // ASN1.cs: Abstract Syntax Notation 1 - micro-parser and generator
5 // Sebastien Pouliot (spouliot@motus.com)
7 // (C) 2002 Motus Technologies Inc. (http://www.motus.com)
11 using System.Collections;
12 using System.Security.Cryptography;
14 namespace Mono.Security.ASN1 {
17 // a. ITU ASN.1 standards (free download)
18 // http://www.itu.int/ITU-T/studygroups/com17/languages/
21 protected byte m_nTag;
22 protected byte[] m_aValue;
23 protected ArrayList elist;
25 public ASN1 () : this (0x00, null) {}
27 public ASN1 (byte tag) : this (tag, null) {}
29 public ASN1 (byte tag, byte[] data)
33 elist = new ArrayList ();
36 public ASN1 (byte[] data)
38 elist = new ArrayList ();
42 int nLength = data [1];
46 nLenLength = nLength - 0x80;
48 for (int i = 0; i < nLenLength; i++) {
50 nLength += data [i + 2];
54 m_aValue = new byte [nLength];
55 Array.Copy (data, (2 + nLenLength), m_aValue, 0, nLength);
58 Decode (data, ref nStart, data.Length);
62 get { return elist.Count; }
66 get { return m_nTag; }
72 return m_aValue.Length;
79 get { return (byte[]) m_aValue.Clone (); }
82 m_aValue = (byte[]) value.Clone ();
86 public bool CompareValue (byte[] aValue)
88 bool bResult = (m_aValue.Length == aValue.Length);
90 for (int i = 0; i < m_aValue.Length; i++) {
91 if (m_aValue[i] != aValue[i])
98 public virtual void Add (ASN1 asn1)
104 public virtual byte[] GetBytes ()
107 if (m_aValue != null) {
110 else if (elist.Count > 0) {
112 ArrayList al = new ArrayList ();
113 foreach (ASN1 a in elist) {
114 byte[] item = a.GetBytes ();
116 esize += item.Length;
118 val = new byte [esize];
120 for (int i=0; i < elist.Count; i++) {
121 byte[] item = (byte[]) al[i];
122 Array.Copy (item, 0, val, pos, item.Length);
131 int nLength = val.Length;
132 // special for length > 127
135 der = new byte [3 + nLength];
136 Array.Copy (val, 0, der, 3, nLength);
138 der[2] = (byte)(nLength);
141 der = new byte [4 + nLength];
142 Array.Copy (val, 0, der, 4, nLength);
144 der[2] = (byte)(nLength / 256);
145 der[3] = (byte)(nLength % 256);
149 der = new byte [2 + nLength];
150 Array.Copy (val, 0, der, 2, nLength);
151 nLengthLen = nLength;
158 der[1] = (byte)nLengthLen;
164 protected void Decode (byte[] asn1, ref int anPos, int anLength)
170 // minimum is 2 bytes (tag + length of 0)
171 while (anPos < anLength - 1) {
173 DecodeTLV (asn1, ref anPos, out nTag, out nLength, out aValue);
175 ASN1 elm = new ASN1 (nTag, aValue);
178 if ((nTag & 0x20) == 0x20) {
179 int nConstructedPos = anPos;
180 elm.Decode (asn1, ref nConstructedPos, nConstructedPos + nLength);
182 anPos += nLength; // value length
186 // TLV : Tag - Length - Value
187 protected void DecodeTLV (byte[] asn1, ref int anPos, out byte anTag, out int anLength, out byte[] aValue)
189 anTag = asn1 [anPos++];
190 anLength = asn1 [anPos++];
192 // special case where L contains the Length of the Length + 0x80
193 if ((anLength & 0x80) == 0x80) {
194 int nLengthLen = anLength & 0x7F;
196 for (int i = 0; i < nLengthLen; i++) {
197 anLength = anLength * 256 + asn1 [anPos++];
201 aValue = new byte [anLength];
202 Array.Copy (asn1, anPos, aValue, 0, anLength);
205 public ASN1 Element (int index)
208 return (ASN1) elist [index];
215 public ASN1 Element (int anIndex, byte anTag)
218 ASN1 elm = (ASN1) elist [anIndex];
219 if (elm.Tag == anTag)
230 internal class OID : ASN1 {
231 public OID (string oid) : base (CryptoConfig.EncodeOID (oid)) {}