commit
c7796444a0
3 changed files with 255 additions and 0 deletions
@ -0,0 +1,46 @@ |
|||
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<PropertyGroup> |
|||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
|||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
|||
<ProjectGuid>{5BE0072A-D18A-4B04-8BAD-3A4E3989924C}</ProjectGuid> |
|||
<ProductVersion>9.0.21022</ProductVersion> |
|||
<SchemaVersion>2.0</SchemaVersion> |
|||
<OutputType>Exe</OutputType> |
|||
<NoStandardLibraries>false</NoStandardLibraries> |
|||
<AssemblyName>ASN.1 Parser</AssemblyName> |
|||
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion> |
|||
<FileAlignment>512</FileAlignment> |
|||
<RootNamespace>ASN._1_Parser</RootNamespace> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
|||
<DebugSymbols>true</DebugSymbols> |
|||
<DebugType>full</DebugType> |
|||
<Optimize>false</Optimize> |
|||
<OutputPath>bin\Debug\</OutputPath> |
|||
<DefineConstants>DEBUG;TRACE</DefineConstants> |
|||
<ErrorReport>prompt</ErrorReport> |
|||
<WarningLevel>4</WarningLevel> |
|||
<DocumentationFile>bin\Debug\ASN.1 Parser.XML</DocumentationFile> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> |
|||
<DebugType>pdbonly</DebugType> |
|||
<Optimize>true</Optimize> |
|||
<OutputPath>bin\Release\</OutputPath> |
|||
<DefineConstants>TRACE</DefineConstants> |
|||
<ErrorReport>prompt</ErrorReport> |
|||
<WarningLevel>4</WarningLevel> |
|||
<DocumentationFile>bin\Release\ASN.1 Parser.XML</DocumentationFile> |
|||
</PropertyGroup> |
|||
<ItemGroup> |
|||
<Reference Include="System" /> |
|||
<Reference Include="System.Data" /> |
|||
<Reference Include="System.Xml" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<Compile Include="PoorManAsn1Parser.cs" /> |
|||
</ItemGroup> |
|||
<Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" /> |
|||
<ProjectExtensions> |
|||
<VisualStudio AllowExistingFolder="true" /> |
|||
</ProjectExtensions> |
|||
</Project> |
|||
@ -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 |
|||
@ -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 <file>"); |
|||
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}<unknown> {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 = "<Integer>"; // 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 = "<OID>"; // 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; |
|||
} |
|||
|
|||
} |
|||
Loading…
Reference in new issue