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