Parser code for TLV format
Program for encoding/decoding TLV format is written in .NET C#
Please create a blank .NET project with following files and run the program.
Input string is a string storing BER TLV fomat.
FILE1 # Program.cs
File containing main function
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using BerTlv; namespace TLVPersing { class Program { public static String value2 = @"FA82015CDFDF250F423431304635303033303631384141F4820145DFDF300100DFDF313D254137303834303739303037383330303031325E41564655454C2043462054455354204341524420414343545E32303031303030414E59205441494C3FDFDF320100DFDF33273B37303834303030303330303030303031323D323030313030303030303030303030303030303FDFDF340100DFDF3500DFDF37408C9CC0A6CC1EA15F559B064942361EFA328882B4EBB63F93E67D30421448C0B59E658E5CE22B73763AD0D1825A365B76E3AD2B92CF9CC2E09F6FDAD168139FA7DFDF3928A7345957BEDB693968136F15FB3B261E2AD27A7E447EA8BF764FA6449D69029039411E783F49D3F9DFDF3B00DFDF3C38F7B2B37CE359E33110787CABC3B2ED8DE5751B0594687E100E041040BB2DDEB2769F3D61EF32C3EF8B92C87FE593B194F1DD45FFE95B0A6CDFDF430461401000DFDF500A9011880B410F50000048"; public static string value1 [email protected]"F98201EEDFDF540A00000000000000000000DFDF550182DFDF250F423431304635303033303631384141FA8201C4F08201C0F105DFDF1A0100F8820116DFDF598200F8E0DD979C1B3E0D20E88A5EDEC2DC66636A922C2C5612503A6D13C8A2D636952429259AA7C801B7744D11AF5A9A79BFEE9699F552E87BD8E6671E697C58FBA3F3B856F8604BD9DC792956D1F6F698481D1E2E4C8E971B176F1D9FE02D05AF74968CD8BDAB143D7EF0969C2CA2E4231DA1A37CD007088301183E046807492949E80D90079D27A3BFF0F9C345AA2FC64FB9A15F8E81482943CAA805E81F7A90BDA5E802A921BDF37E6402AE2482AD4121B2925194EC449797926AB3B930CE88808192E906EF336DD1EA8CE2C1FCF57D9B6BAC2E53950D4F4F92F4928A9B0F7570D0531A9D222676EB63B40834220A0C39624DE4E4C8F6EBADACDFDF560A9011880B410F50000049DFDF570180DFDF580103F782009B5F25031601015F24032212315F2A0208409F02060000000099999F03060000000009999F0607A00000000310109F120B56697361204372656469749F1C0831313232333334349F3901059C01009F34035E03005F201A554154205553412F546573742043617264203031202020202020DFDF4D273B343736313030303039303030303131393D32323132323031303030303030303030303030303F00000000000011223344"; public static string value3 = "5F201A54444320424C41434B20554E4C494D49544544205649534120204F07A00000000310105F24032307319F160F4243544553542031323334353637389F21031826509A031406179F02060000000000019F03060000000000009F34030203009F120C56495341204352454449544F9F0607A00000000310105F300202019F4E0F616263640000000000000000000000C408491573FFFFFF1097C00A09117101800165E0000AC2820168D9DE289AAD770BE408F6B1D4E0A2576CEA7F03CD479CE3A1827375D6C4D4959ACDB5D3B6F84CD83430F4346C35E48A77A0D5F36FBEA444C2D8701C07FFC7AF06C0485D68F7A83FC30840D3C0766EC4EE669BE5A42BAD4C7459680FAAAE9C4EFEFFEB5A590E53B3E91B3CD28A415C2C9484E26DA5A15592BBCD1F45CF49D27A9D480B031957DF8C790C55FF60DB192CCD070FA4F7BCDC99E7F7567C2F991B5536F9336BA66D68115D54BC3642A9CA47FDD162FCDC33E455AAC283975DACC98CBE9A6611E996F0740072CF8E32D3D9F39F4BB25568F5CC3E7F5DE158E4D62BF4E7185CF13BD068C4F062C26A3BBF88E056F249130E89AA29E52A1EBB6BAD98296822F10949F0C825D1449DA7EF4431AB846D0DDB916F2901359DD9A3B3395BAC9F9BE4D24657F65B030DDADA53577A14D9F5F776B6FF7EAB99D8C4BB08BEF2016C72D94B1DB91BCF0238405B7857646DCE5F79871D96B6A6652090FD8CFCC59973433919A6D0533DFE"; static void Main(string[] args) { string tag ; string length ; string value ; //byte[] bytes = Encoding.ASCII.GetBytes(value); try { ICollection<TLVPersing.Tlv> tlv = Tlv.ParseTlv(value1); foreach (var item in tlv) { tag = item.HexTag.ToString(); length = item.Length.ToString(); value = item.HexValue.ToString(); Console.WriteLine(tag + "-" + length + "-" + value); foreach (var child in item.Children) { tag = child.HexTag.ToString(); length = child.Length.ToString(); value = child.HexValue.ToString(); Console.WriteLine(tag + "-" + length + "-" + value); foreach (var list in child.Children) { tag = list.HexTag.ToString(); length = list.Length.ToString(); value = list.HexValue.ToString(); Console.WriteLine(tag + "-" + length + "-" + value); } } } } catch (Exception ex) { string msg = ex.ToString(); } Console.ReadLine(); } } }
File2 #
TLV.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace TLVPersing { /// <summary> /// TLV data. /// </summary> public class Tlv { private readonly int _valueOffset; private Tlv(int tag, int length, int valueOffset, byte[] data) { Tag = tag; Length = length; Data = data; Children = new List<Tlv>(); _valueOffset = valueOffset; } /// <summary> /// The raw TLV data. /// </summary> public byte[] Data { get; private set; } /// <summary> /// The raw TLV data. /// </summary> public string HexData { get { return GetHexString(Data); } } /// <summary> /// The TLV tag. /// </summary> public int Tag { get; private set; } /// <summary> /// The TLV tag. /// </summary> public string HexTag { get { return Tag.ToString("X"); } } /// <summary> /// The length of the TLV value. /// </summary> public int Length { get; private set; } /// <summary> /// The length of the TLV value. /// </summary> public string HexLength { get { return Length.ToString("X"); } } /// <summary> /// The TLV value. /// </summary> public byte[] Value { get { byte[] result = new byte[Length]; Array.Copy(Data, _valueOffset, result, 0, Length); return result; } } /// <summary> /// The TLV value. /// </summary> public string HexValue { get { return GetHexString(Value); } } /// <summary> /// TLV children. /// </summary> public ICollection<Tlv> Children { get; set; } /// <summary> /// Parse TLV data. /// </summary> /// <param name="tlv">The hex TLV blob.</param> /// <returns>A collection of TLVs.</returns> public static ICollection<Tlv> ParseTlv(string tlv) { if (string.IsNullOrWhiteSpace(tlv)) { throw new ArgumentException("tlv"); } return ParseTlv(GetBytes(tlv)); } /// <summary> /// Parse TLV data. /// </summary> /// <param name="tlv">The byte array TLV blob.</param> /// <returns>A collection of TLVs.</returns> public static ICollection<Tlv> ParseTlv(byte[] tlv) { if (tlv == null || tlv.Length == 0) { throw new ArgumentException("tlv"); } var result = new List<Tlv>(); ParseTlv(tlv, result); return result; } private static void ParseTlv(byte[] rawTlv, ICollection<Tlv> result) { for (int i = 0, start = 0; i < rawTlv.Length; start = i) { //Make sure that any data up to end-of - file is all 0x00 or 0xFF padding bytes (Book 3 Annex B 1.1) if ((rawTlv.Length > i) && ((rawTlv[i] == 0x00) || (rawTlv[i] == 0xFF))) { int iPad = i; byte PaddedByte = rawTlv[i]; while (rawTlv.Length > iPad && rawTlv[iPad] == PaddedByte) iPad++; if (iPad == rawTlv.Length) break; } // 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]; //Console.WriteLine(rawTlv +"-" + start + "-"+ rawData +"-" + "0"+ "-" + (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); } } //Console.ReadLine(); } private static string GetHexString(byte[] arr) { var sb = new StringBuilder(arr.Length * 2); foreach (byte b in arr) { sb.AppendFormat("{0:X2}", b); } return sb.ToString(); } private static byte[] GetBytes(string hexString) { return Enumerable .Range(0, hexString.Length) .Where(x => x % 2 == 0) .Select(x => Convert.ToByte(hexString.Substring(x, 2), 16)) .ToArray(); } private static int GetInt(byte[] data, int offset, int length) { var result = 0; for (var i = 0; i < length; i++) { result = (result << 8) | data[offset + i]; } return result; } } }