commit c7796444a072abf44f202ea7d617ec4512b6d239 Author: Nicolas MASSE Date: Wed Sep 11 11:47:48 2019 +0200 migration from svn diff --git a/ASN.1 Parser.csproj b/ASN.1 Parser.csproj new file mode 100644 index 0000000..44a7f5f --- /dev/null +++ b/ASN.1 Parser.csproj @@ -0,0 +1,46 @@ + + + Debug + AnyCPU + {5BE0072A-D18A-4B04-8BAD-3A4E3989924C} + 9.0.21022 + 2.0 + Exe + false + ASN.1 Parser + v2.0 + 512 + ASN._1_Parser + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + bin\Debug\ASN.1 Parser.XML + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + bin\Release\ASN.1 Parser.XML + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ASN.1 Parser.sln b/ASN.1 Parser.sln new file mode 100644 index 0000000..4be5488 --- /dev/null +++ b/ASN.1 Parser.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ASN.1 Parser", "ASN.1 Parser.csproj", "{5BE0072A-D18A-4B04-8BAD-3A4E3989924C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5BE0072A-D18A-4B04-8BAD-3A4E3989924C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5BE0072A-D18A-4B04-8BAD-3A4E3989924C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5BE0072A-D18A-4B04-8BAD-3A4E3989924C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5BE0072A-D18A-4B04-8BAD-3A4E3989924C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/PoorManAsn1Parser.cs b/PoorManAsn1Parser.cs new file mode 100644 index 0000000..0b12935 --- /dev/null +++ b/PoorManAsn1Parser.cs @@ -0,0 +1,189 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +public class PoorManAsn1ParserTest +{ + static public void Main(String[] args) + { + if (args.Length != 1) { + Console.WriteLine("Usage: PoorManAsn1ParserTest.exe "); + return; + } + + try + { + FileStream f = File.Open(args[0], FileMode.Open); + int length = Convert.ToInt32(f.Length); + byte[] rawasn1 = new byte[length]; + f.Read(rawasn1, 0, length); + + PoorManAsn1Parser parser = new PoorManAsn1Parser(); + Object obj = parser.Parse(rawasn1, 0); + Dump(obj, ""); + } + catch (Exception e) + { + Console.WriteLine(e.Message); + Console.WriteLine(e.StackTrace); + } + } + + static private void Dump(Object o, String indent) { + if (o == null) + { + Console.WriteLine("{0}null", indent); + } + else if (o is String) + { + Console.WriteLine("{0}{1}", indent, o as String); + } + else if (o is byte[]) + { + StringBuilder sb = new StringBuilder(indent); + sb.Append("["); + foreach (byte b in (o as byte[])) + { + sb.AppendFormat("{0:x}", b); + } + sb.Append("]"); + Console.WriteLine(sb.ToString()); + } + else if (o is IEnumerable) + { + Console.WriteLine(indent + "{"); + String indent2 = indent + " "; + foreach (Object elem in (o as IEnumerable)) + { + Dump(elem, indent2); + } + Console.WriteLine(indent + "}"); + } + else + { + Console.WriteLine("{0} {1}", indent, o.GetType().FullName); + } + } +} + +internal class PoorManAsn1Parser +{ + public PoorManAsn1Parser() + { + } + + private void Length(byte[] rawasn1, int offset, out int length, out int lengthLength) + { + length = 0; + lengthLength = 0; + + byte tag = rawasn1[offset]; + if ((tag & 0x1F) == 0x1F) + { + throw new NotImplementedException("Tag too long"); + } + offset++; + + if (rawasn1[offset] == 0x80) + { + throw new NotImplementedException("Length not defined"); + } + + if ((rawasn1[offset] & 0x80) == 0) // Length on one byte + { + length = rawasn1[offset]; + lengthLength = 1; + } + else + { + lengthLength = rawasn1[offset] & 0x7F; + if (lengthLength > 4) // Overflow ? + { + throw new NotImplementedException("Length too long"); + } + + for (int i = 1; i < lengthLength + 1; i++) + { + length <<= 7; + length |= rawasn1[offset + i]; + } + + lengthLength++; + } + } + + public Object Parse(byte[] rawasn1, int offset) + { + Object value = null; + + byte tag = rawasn1[offset]; + bool isPrimitive = ((tag & 0x20) == 0); + byte label = (byte) (tag & 0x17); + + int dataLength; + int lengthLength; + Length(rawasn1, offset, out dataLength, out lengthLength); + + Console.WriteLine("offset = {0}, tag = {1:x}, length = {2}, lengthLength = {3}", offset, tag, dataLength, lengthLength); + + int dataOffset = offset + lengthLength + 1; + + if (label == 0x1F) + { + throw new NotImplementedException("Tag too long"); + } + + if (isPrimitive) + { + switch (label) + { + case 0x01: // Bool + value = (rawasn1[dataOffset] != 0); + break; + case 0x02: // Integer + value = ""; // TODO + break; + case 0x03: // Bitstring + byte[] bitString = new byte[dataLength - 1]; + Array.Copy(rawasn1, dataOffset + 1, bitString, 0, dataLength - 1); + value = bitString; + break; + case 0x04: // Octet string + byte[] octetString = new byte[dataLength]; + Array.Copy(rawasn1, dataOffset, octetString, 0, dataLength); + value = octetString; + break; + case 0x05: // Null + break; + case 0x06: // OID + value = ""; // TODO + break; + case 0x13: // PrintableString + case 0x16: // IA5String + value = Encoding.ASCII.GetString(rawasn1, dataOffset, dataLength); + break; + default: + throw new NotImplementedException(String.Format("Unknown type: {0}", label)); + } + } + else + { + IList list = new ArrayList(); + int thisObjectOffset = dataOffset; + do + { + int thisObjectLength; + int thisObjectLengthLength; + Length(rawasn1, thisObjectOffset, out thisObjectLength, out thisObjectLengthLength); + list.Add(Parse(rawasn1, thisObjectOffset)); + thisObjectOffset += thisObjectLength + thisObjectLengthLength + 1; + } while (thisObjectOffset < dataOffset + dataLength); + + value = list; + } + + return value; + } + +}