private static void ParseTlv(byte[] rawTlv, ICollection <Tlv> result) { for (int i = 0, start = 0; i < rawTlv.Length; start = i) { // 0x00 and 0xFF can be used as padding before, between, and after tags if (rawTlv[i] == 0x00) { i++; continue; } // bit6 being 1 indicates that the tag is 'constructed' (contains more tags within it) bool constructedTlv = (rawTlv[i] & 0x20) != 0; // bit1 through 5 being 1 indicates that the tag is more than one byte long // recognize this and keep looking until we find the last byte of the tag, indicated by bit8 being 0 bool multiByteTag = (rawTlv[i] & 0x1F) == 0x1F; while (multiByteTag && (rawTlv[++i] & 0x80) != 0) { ; } // i is on the last byte of the tag, so move it forward one and // retreve the tag value from the raw tlv i++; int tag = GetInt(rawTlv, start, i - start); // bit8 being 1 indicates that the length is multiple bytes long bool multiByteLength = (rawTlv[i] & 0x80) != 0; int length = multiByteLength ? GetInt(rawTlv, i + 1, rawTlv[i] & 0x1F) : rawTlv[i]; i = multiByteLength ? i + (rawTlv[i] & 0x1F) + 1 : i + 1; // i is on the last byte of the length, so move it forward by the length we found i += length; // now that we know the start position and length of the data, retrieve it // then create the Tlv object and add it to the list byte[] rawData = new byte[i - start]; Array.Copy(rawTlv, start, rawData, 0, i - start); var tlv = new Tlv(tag, length, rawData.Length - length, rawData); result.Add(tlv); // if this was a constructed tag, parse its value into individual Tlv children as well if (constructedTlv) { ParseTlv(tlv.Value, tlv.Children); } } }
private static void ParseTlv(byte[] rawTlv, ICollection<Tlv> result) { for(int i = 0, start = 0; i < rawTlv.Length; start = i) { // parse Tag bool constructedTlv = (rawTlv[i] & 0x20) != 0; bool moreBytes = (rawTlv[i] & 0x1F) == 0x1F; while(moreBytes && (rawTlv[++i] & 0x80) != 0) ; i++; int tag = GetInt(rawTlv, start, i - start); // parse Length bool multiByteLength = (rawTlv[i] & 0x80) != 0; int length = multiByteLength ? GetInt(rawTlv, i + 1, rawTlv[i] & 0x1F) : rawTlv[i]; i = multiByteLength ? i + (rawTlv[i] & 0x1F) + 1 : i + 1; i += length; byte[] rawData = new byte[i - start]; Array.Copy(rawTlv, start, rawData, 0, i - start); var tlv = new Tlv(tag, length, rawData.Length - length, rawData); result.Add(tlv); if(constructedTlv) { ParseTlv(tlv.Value, tlv.Children); } } }