mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-07-29 12:12:54 +00:00
Migrate to ASN1 package
This commit is contained in:
@@ -1,31 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BinaryObjectScanner.ASN1
|
||||
{
|
||||
/// <summary>
|
||||
/// ASN.1 Parser
|
||||
/// </summary>
|
||||
public static class AbstractSyntaxNotationOne
|
||||
{
|
||||
/// <summary>
|
||||
/// Parse a byte array into a DER-encoded ASN.1 structure
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array representing the data</param>
|
||||
/// <param name="pointer">Current pointer into the data</param>
|
||||
/// <returns></returns>
|
||||
public static List<TypeLengthValue> Parse(byte[] data, int pointer)
|
||||
{
|
||||
// Create the output list to return
|
||||
var topLevelValues = new List<TypeLengthValue>();
|
||||
|
||||
// Loop through the data and return all top-level values
|
||||
while (pointer < data.Length)
|
||||
{
|
||||
var topLevelValue = new TypeLengthValue(data, ref pointer);
|
||||
topLevelValues.Add(topLevelValue);
|
||||
}
|
||||
|
||||
return topLevelValues;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net48;net6.0;net7.0</TargetFrameworks>
|
||||
<RuntimeIdentifiers>win-x86;win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Title>BinaryObjectScanner.ASN1</Title>
|
||||
<AssemblyName>BinaryObjectScanner.ASN1</AssemblyName>
|
||||
<Authors>Matt Nadareski</Authors>
|
||||
<Product>BurnOutSharp</Product>
|
||||
<Copyright>Copyright (c)2022 Matt Nadareski</Copyright>
|
||||
<RepositoryUrl>https://github.com/mnadareski/BurnOutSharp</RepositoryUrl>
|
||||
<Version>2.8</Version>
|
||||
<AssemblyVersion>2.8</AssemblyVersion>
|
||||
<FileVersion>2.8</FileVersion>
|
||||
<IncludeSource>true</IncludeSource>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BinaryObjectScanner.Utilities\BinaryObjectScanner.Utilities.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.IO" Version="1.1.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,55 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace BinaryObjectScanner.ASN1
|
||||
{
|
||||
/// <summary>
|
||||
/// ASN.1 type indicators
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum ASN1Type : byte
|
||||
{
|
||||
#region Modifiers
|
||||
|
||||
V_ASN1_UNIVERSAL = 0x00,
|
||||
V_ASN1_PRIMITIVE_TAG = 0x1F,
|
||||
V_ASN1_CONSTRUCTED = 0x20,
|
||||
V_ASN1_APPLICATION = 0x40,
|
||||
V_ASN1_CONTEXT_SPECIFIC = 0x80,
|
||||
V_ASN1_PRIVATE = 0xC0,
|
||||
|
||||
#endregion
|
||||
|
||||
#region Types
|
||||
|
||||
V_ASN1_EOC = 0x00,
|
||||
V_ASN1_BOOLEAN = 0x01,
|
||||
V_ASN1_INTEGER = 0x02,
|
||||
V_ASN1_BIT_STRING = 0x03,
|
||||
V_ASN1_OCTET_STRING = 0x04,
|
||||
V_ASN1_NULL = 0x05,
|
||||
V_ASN1_OBJECT = 0x06,
|
||||
V_ASN1_OBJECT_DESCRIPTOR = 0x07,
|
||||
V_ASN1_EXTERNAL = 0x08,
|
||||
V_ASN1_REAL = 0x09,
|
||||
V_ASN1_ENUMERATED = 0x0A,
|
||||
V_ASN1_UTF8STRING = 0x0C,
|
||||
V_ASN1_SEQUENCE = 0x10,
|
||||
V_ASN1_SET = 0x11,
|
||||
V_ASN1_NUMERICSTRING = 0x12,
|
||||
V_ASN1_PRINTABLESTRING = 0x13,
|
||||
V_ASN1_T61STRING = 0x14,
|
||||
V_ASN1_TELETEXSTRING = 0x14,
|
||||
V_ASN1_VIDEOTEXSTRING = 0x15,
|
||||
V_ASN1_IA5STRING = 0x16,
|
||||
V_ASN1_UTCTIME = 0x17,
|
||||
V_ASN1_GENERALIZEDTIME = 0x18,
|
||||
V_ASN1_GRAPHICSTRING = 0x19,
|
||||
V_ASN1_ISO64STRING = 0x1A,
|
||||
V_ASN1_VISIBLESTRING = 0x1A,
|
||||
V_ASN1_GENERALSTRING = 0x1B,
|
||||
V_ASN1_UNIVERSALSTRING = 0x1C,
|
||||
V_ASN1_BMPSTRING = 0x1E,
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
namespace BinaryObjectScanner.ASN1
|
||||
{
|
||||
#pragma warning disable IDE0011
|
||||
|
||||
/// <summary>
|
||||
/// Methods related to Object Identifiers (OID) and ASN.1 notation
|
||||
/// </summary>
|
||||
public static partial class ObjectIdentifier
|
||||
{
|
||||
/// <summary>
|
||||
/// Parse an OID in separated-value notation into ASN.1 notation
|
||||
/// </summary>
|
||||
/// <param name="values">List of values to check against</param>
|
||||
/// <param name="index">Current index into the list</param>
|
||||
/// <returns>ASN.1 formatted string, if possible</returns>
|
||||
/// <remarks>
|
||||
public static string ParseOIDToASN1Notation(ulong[] values, ref int index)
|
||||
{
|
||||
// TODO: Once the modified OID-IRI formatting is done, make an ASN.1 notation version
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore IDE0011
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,870 +0,0 @@
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace BinaryObjectScanner.ASN1
|
||||
{
|
||||
#pragma warning disable IDE0011
|
||||
|
||||
/// <summary>
|
||||
/// Methods related to Object Identifiers (OID) and OID-IRI formatting
|
||||
/// </summary>
|
||||
public static partial class ObjectIdentifier
|
||||
{
|
||||
/// <summary>
|
||||
/// Parse an OID in separated-value notation into OID-IRI notation
|
||||
/// </summary>
|
||||
/// <param name="values">List of values to check against</param>
|
||||
/// <param name="index">Current index into the list</param>
|
||||
/// <returns>OID-IRI formatted string, if possible</returns>
|
||||
/// <see href="http://www.oid-info.com/index.htm"/>
|
||||
public static string ParseOIDToOIDIRINotation(ulong[] values)
|
||||
{
|
||||
// If we have an invalid set of values, we can't do anything
|
||||
if (values == null || values.Length == 0)
|
||||
return null;
|
||||
|
||||
// Set the initial index
|
||||
int index = 0;
|
||||
|
||||
// Get a string builder for the path
|
||||
var nameBuilder = new StringBuilder();
|
||||
|
||||
// Try to parse the standard value
|
||||
string standard = ParseOIDToOIDIRINotation(values, ref index);
|
||||
if (standard == null)
|
||||
return null;
|
||||
|
||||
// Add the standard value to the output
|
||||
nameBuilder.Append(standard);
|
||||
|
||||
// If we have no more items
|
||||
if (index == values.Length)
|
||||
return nameBuilder.ToString();
|
||||
|
||||
// Add trailing items as just values
|
||||
nameBuilder.Append("/");
|
||||
nameBuilder.Append(string.Join("/", values.Skip(index)));
|
||||
|
||||
// Create and return the string
|
||||
return nameBuilder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse an OID in separated-value notation into OID-IRI notation
|
||||
/// </summary>
|
||||
/// <param name="values">List of values to check against</param>
|
||||
/// <param name="index">Current index into the list</param>
|
||||
/// <returns>OID-IRI formatted string, if possible</returns>
|
||||
/// <see href="http://www.oid-info.com/index.htm"/>
|
||||
private static string ParseOIDToOIDIRINotation(ulong[] values, ref int index)
|
||||
{
|
||||
// If we have an invalid set of values, we can't do anything
|
||||
if (values == null || values.Length == 0)
|
||||
return null;
|
||||
|
||||
// If we have an invalid index, we can't do anything
|
||||
if (index < 0 || index >= values.Length)
|
||||
return null;
|
||||
|
||||
#region Start
|
||||
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: goto oid_0;
|
||||
case 1: goto oid_1;
|
||||
case 2: goto oid_2;
|
||||
default: return $"/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// itu-t, ccitt, itu-r
|
||||
#region 0.*
|
||||
|
||||
oid_0:
|
||||
|
||||
if (index == values.Length) return "/ITU-T";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: goto oid_0_0;
|
||||
case 2: return "/ITU-T/Administration";
|
||||
case 3: return "/ITU-T/Network-Operator";
|
||||
case 4: return "/ITU-T/Identified-Organization";
|
||||
case 5: return "/ITU-R/R-Recommendation";
|
||||
case 9: return "/ITU-T/Data";
|
||||
default: return $"/ITU-T/{values[index - 1]}";
|
||||
};
|
||||
|
||||
// recommendation
|
||||
#region 0.0.*
|
||||
|
||||
oid_0_0:
|
||||
|
||||
if (index == values.Length) return "/ITU-T/Recommendation";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/ITU-T/Recommendation/A";
|
||||
case 2: return "/ITU-T/Recommendation/B";
|
||||
case 3: return "/ITU-T/Recommendation/C";
|
||||
case 4: return "/ITU-T/Recommendation/D";
|
||||
case 5: return "/ITU-T/Recommendation/E";
|
||||
case 6: return "/ITU-T/Recommendation/F";
|
||||
case 7: return "/ITU-T/Recommendation/G";
|
||||
case 8: return "/ITU-T/Recommendation/H";
|
||||
case 9: return "/ITU-T/Recommendation/I";
|
||||
case 10: return "/ITU-T/Recommendation/J";
|
||||
case 11: return "/ITU-T/Recommendation/K";
|
||||
case 12: return "/ITU-T/Recommendation/L";
|
||||
case 13: return "/ITU-T/Recommendation/M";
|
||||
case 14: return "/ITU-T/Recommendation/N";
|
||||
case 15: return "/ITU-T/Recommendation/O";
|
||||
case 16: return "/ITU-T/Recommendation/P";
|
||||
case 17: return "/ITU-T/Recommendation/Q";
|
||||
case 18: return "/ITU-T/Recommendation/R";
|
||||
case 19: return "/ITU-T/Recommendation/S";
|
||||
case 20: return "/ITU-T/Recommendation/T";
|
||||
case 21: return "/ITU-T/Recommendation/U";
|
||||
case 22: return "/ITU-T/Recommendation/V";
|
||||
case 24: return "/ITU-T/Recommendation/X";
|
||||
case 25: return "/ITU-T/Recommendation/Y";
|
||||
case 26: return "/ITU-T/Recommendation/Z";
|
||||
default: return $"/ITU-T/Recommendation/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
// iso
|
||||
#region 1.*
|
||||
|
||||
oid_1:
|
||||
|
||||
if (index == values.Length) return "/ISO";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: return "/ISO/Standard";
|
||||
case 1: return "/ISO/Registration-Authority";
|
||||
case 2: goto oid_1_2;
|
||||
case 3: return "/ISO/Identified-Organization";
|
||||
default: return $"/ISO/{values[index - 1]}";
|
||||
}
|
||||
|
||||
// member-body
|
||||
#region 1.2.*
|
||||
|
||||
oid_1_2:
|
||||
|
||||
if (index == values.Length) return "/ISO/Member-Body";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 36: return "/ISO/Member-Body/AU";
|
||||
case 40: return "/ISO/Member-Body/AT";
|
||||
case 56: return "/ISO/Member-Body/BE";
|
||||
case 124: return "/ISO/Member-Body/CA";
|
||||
case 156: return "/ISO/Member-Body/CN";
|
||||
case 203: return "/ISO/Member-Body/CZ";
|
||||
case 208: return "/ISO/Member-Body/DK";
|
||||
case 246: return "/ISO/Member-Body/FI";
|
||||
case 250: return "/ISO/Member-Body/FR";
|
||||
case 276: return "/ISO/Member-Body/DE";
|
||||
case 300: return "/ISO/Member-Body/GR";
|
||||
case 344: return "/ISO/Member-Body/HK";
|
||||
case 372: return "/ISO/Member-Body/IE";
|
||||
case 392: return "/ISO/Member-Body/JP";
|
||||
case 398: return "/ISO/Member-Body/KZ";
|
||||
case 410: return "/ISO/Member-Body/KR";
|
||||
case 498: return "/ISO/Member-Body/MD";
|
||||
case 528: return "/ISO/Member-Body/NL";
|
||||
case 566: return "/ISO/Member-Body/NG";
|
||||
case 578: return "/ISO/Member-Body/NO";
|
||||
case 616: return "/ISO/Member-Body/PL";
|
||||
case 643: return "/ISO/Member-Body/RU";
|
||||
case 702: return "/ISO/Member-Body/SG";
|
||||
case 752: return "/ISO/Member-Body/SE";
|
||||
case 804: return "/ISO/Member-Body/UA";
|
||||
case 826: return "/ISO/Member-Body/GB";
|
||||
case 840: return "/ISO/Member-Body/US";
|
||||
default: return $"/ISO/Member-Body/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
// joint-iso-itu-t, joint-iso-ccitt
|
||||
#region 2.*
|
||||
|
||||
oid_2:
|
||||
|
||||
if (index == values.Length) return "/Joint-ISO-ITU-T";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/ASN.1";
|
||||
case 16: goto oid_2_16;
|
||||
case 17: return "/Joint-ISO-ITU-T/Registration-Procedures";
|
||||
case 23: return "/Joint-ISO-ITU-T/International-Organizations";
|
||||
case 25: goto oid_2_25;
|
||||
case 27: return "/Tag-Based";
|
||||
case 28: return "/Joint-ISO-ITU-T/ITS";
|
||||
case 41: return "/BIP";
|
||||
case 42: goto oid_2_42;
|
||||
case 48: goto oid_2_48;
|
||||
case 49: goto oid_2_49;
|
||||
case 50: return "/OIDResolutionSystem";
|
||||
case 51: return "/GS1";
|
||||
case 52: return "/Joint-ISO-ITU-T/UAV";
|
||||
case 999: return "/Joint-ISO-ITU-T/Example";
|
||||
default: return $"/Joint-ISO-ITU-T/{values[index - 1]}";
|
||||
}
|
||||
|
||||
// country
|
||||
#region 2.16.*
|
||||
|
||||
oid_2_16:
|
||||
|
||||
if (index == values.Length) return "/Country";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 4: return "/Country/AF";
|
||||
case 8: return "/Country/AL";
|
||||
case 12: return "/Country/DZ";
|
||||
case 20: return "/Country/AD";
|
||||
case 24: return "/Country/AO";
|
||||
case 28: return "/Country/AG";
|
||||
case 31: return "/Country/AZ";
|
||||
case 32: return "/Country/AR";
|
||||
case 36: return "/Country/AU";
|
||||
case 40: return "/Country/AT";
|
||||
case 44: return "/Country/BS";
|
||||
case 48: return "/Country/BH";
|
||||
case 50: return "/Country/BD";
|
||||
case 51: return "/Country/AM";
|
||||
case 52: return "/Country/BB";
|
||||
case 56: return "/Country/BE";
|
||||
case 60: return "/Country/BM";
|
||||
case 64: return "/Country/BT";
|
||||
case 68: return "/Country/BO";
|
||||
case 70: return "/Country/BA";
|
||||
case 72: return "/Country/BW";
|
||||
case 76: return "/Country/BR";
|
||||
case 84: return "/Country/BZ";
|
||||
case 90: return "/Country/SB";
|
||||
case 96: return "/Country/BN";
|
||||
case 100: return "/Country/BG";
|
||||
case 104: return "/Country/MM";
|
||||
case 108: return "/Country/BI";
|
||||
case 112: return "/Country/BY";
|
||||
case 116: return "/Country/KH";
|
||||
case 120: return "/Country/CM";
|
||||
case 124: return "/Country/CA";
|
||||
case 132: return "/Country/CV";
|
||||
case 140: return "/Country/CF";
|
||||
case 144: return "/Country/LK";
|
||||
case 148: return "/Country/TD";
|
||||
case 152: return "/Country/CL";
|
||||
case 156: return "/Country/CN";
|
||||
case 158: return "/Country/TW";
|
||||
case 170: return "/Country/CO";
|
||||
case 174: return "/Country/KM";
|
||||
case 178: return "/Country/CG";
|
||||
case 180: return "/Country/CD";
|
||||
case 188: return "/Country/CR";
|
||||
case 191: return "/Country/HR";
|
||||
case 192: return "/Country/CU";
|
||||
case 196: return "/Country/CY";
|
||||
case 203: return "/Country/CZ";
|
||||
case 204: return "/Country/BJ";
|
||||
case 208: return "/Country/DK";
|
||||
case 212: return "/Country/DM";
|
||||
case 214: return "/Country/DO";
|
||||
case 218: return "/Country/EC";
|
||||
case 222: return "/Country/SV";
|
||||
case 226: return "/Country/GQ";
|
||||
case 231: return "/Country/ET";
|
||||
case 232: return "/Country/ER";
|
||||
case 233: return "/Country/EE";
|
||||
case 242: return "/Country/FJ";
|
||||
case 246: return "/Country/FI";
|
||||
case 250: return "/Country/FR";
|
||||
case 262: return "/Country/DJ";
|
||||
case 266: return "/Country/GA";
|
||||
case 268: return "/Country/GE";
|
||||
case 270: return "/Country/GM";
|
||||
case 275: return "/Country/PS";
|
||||
case 276: return "/Country/DE";
|
||||
case 288: return "/Country/GH";
|
||||
case 296: return "/Country/KI";
|
||||
case 300: return "/Country/GR";
|
||||
case 308: return "/Country/GD";
|
||||
case 320: return "/Country/GT";
|
||||
case 324: return "/Country/GN";
|
||||
case 328: return "/Country/GY";
|
||||
case 332: return "/Country/HT";
|
||||
case 336: return "/Country/VA";
|
||||
case 340: return "/Country/HN";
|
||||
case 344: return "/Country/HK";
|
||||
case 348: return "/Country/HU";
|
||||
case 352: return "/Country/IS";
|
||||
case 356: return "/Country/IN";
|
||||
case 360: return "/Country/ID";
|
||||
case 364: return "/Country/IR";
|
||||
case 368: return "/Country/IQ";
|
||||
case 372: return "/Country/IE";
|
||||
case 376: return "/Country/IL";
|
||||
case 380: return "/Country/IT";
|
||||
case 384: return "/Country/CI";
|
||||
case 388: return "/Country/JM";
|
||||
case 392: return "/Country/JP";
|
||||
case 398: return "/Country/KZ";
|
||||
case 400: return "/Country/JO";
|
||||
case 404: return "/Country/KE";
|
||||
case 408: return "/Country/KP";
|
||||
case 410: return "/Country/KR";
|
||||
case 414: return "/Country/KW";
|
||||
case 417: return "/Country/KG";
|
||||
case 418: return "/Country/LA";
|
||||
case 422: return "/Country/LB";
|
||||
case 426: return "/Country/LS";
|
||||
case 428: return "/Country/LV";
|
||||
case 430: return "/Country/LR";
|
||||
case 434: return "/Country/LY";
|
||||
case 438: return "/Country/LI";
|
||||
case 440: return "/Country/LT";
|
||||
case 442: return "/Country/LU";
|
||||
case 450: return "/Country/MG";
|
||||
case 454: return "/Country/MW";
|
||||
case 458: return "/Country/MY";
|
||||
case 462: return "/Country/MV";
|
||||
case 466: return "/Country/ML";
|
||||
case 470: return "/Country/MT";
|
||||
case 478: return "/Country/MR";
|
||||
case 480: return "/Country/MU";
|
||||
case 484: return "/Country/MX";
|
||||
case 492: return "/Country/MC";
|
||||
case 496: return "/Country/MN";
|
||||
case 498: return "/Country/MD";
|
||||
case 499: return "/Country/ME";
|
||||
case 504: return "/Country/MA";
|
||||
case 508: return "/Country/MZ";
|
||||
case 512: return "/Country/OM";
|
||||
case 516: return "/Country/NA";
|
||||
case 520: return "/Country/NR";
|
||||
case 524: return "/Country/NP";
|
||||
case 528: return "/Country/NL";
|
||||
case 530: return "/Country/AN";
|
||||
case 548: return "/Country/VU";
|
||||
case 554: return "/Country/NZ";
|
||||
case 558: return "/Country/NI";
|
||||
case 562: return "/Country/NE";
|
||||
case 566: return "/Country/NG";
|
||||
case 578: return "/Country/NO";
|
||||
case 583: return "/Country/FM";
|
||||
case 584: return "/Country/MH";
|
||||
case 585: return "/Country/PW";
|
||||
case 586: return "/Country/PK";
|
||||
case 591: return "/Country/PA";
|
||||
case 598: return "/Country/PG";
|
||||
case 600: return "/Country/PY";
|
||||
case 604: return "/Country/PE";
|
||||
case 608: return "/Country/PH";
|
||||
case 616: return "/Country/PL";
|
||||
case 620: return "/Country/PT";
|
||||
case 624: return "/Country/GW";
|
||||
case 626: return "/Country/TL";
|
||||
case 634: return "/Country/QA";
|
||||
case 642: return "/Country/RO";
|
||||
case 643: return "/Country/RU";
|
||||
case 646: return "/Country/RW";
|
||||
case 659: return "/Country/KN";
|
||||
case 662: return "/Country/LC";
|
||||
case 670: return "/Country/VC";
|
||||
case 674: return "/Country/SM";
|
||||
case 678: return "/Country/ST";
|
||||
case 682: return "/Country/SA";
|
||||
case 686: return "/Country/SN";
|
||||
case 688: return "/Country/RS";
|
||||
case 690: return "/Country/SC";
|
||||
case 694: return "/Country/SL";
|
||||
case 702: return "/Country/SG";
|
||||
case 703: return "/Country/SK";
|
||||
case 704: return "/Country/VN";
|
||||
case 705: return "/Country/SI";
|
||||
case 706: return "/Country/SO";
|
||||
case 710: return "/Country/ZA";
|
||||
case 716: return "/Country/ZW";
|
||||
case 724: return "/Country/ES";
|
||||
case 728: return "/Country/SS";
|
||||
case 729: return "/Country/SD";
|
||||
case 740: return "/Country/SR";
|
||||
case 748: return "/Country/SZ";
|
||||
case 752: return "/Country/SE";
|
||||
case 756: return "/Country/CH";
|
||||
case 760: return "/Country/SY";
|
||||
case 762: return "/Country/TJ";
|
||||
case 764: return "/Country/TH";
|
||||
case 768: return "/Country/TG";
|
||||
case 776: return "/Country/TO";
|
||||
case 780: return "/Country/TT";
|
||||
case 784: return "/Country/AE";
|
||||
case 788: return "/Country/TN";
|
||||
case 792: return "/Country/TR";
|
||||
case 795: return "/Country/TM";
|
||||
case 798: return "/Country/TV";
|
||||
case 800: return "/Country/UG";
|
||||
case 804: return "/Country/UA";
|
||||
case 807: return "/Country/MK";
|
||||
case 818: return "/Country/EG";
|
||||
case 826: return "/Country/GB";
|
||||
case 834: return "/Country/TZ";
|
||||
case 840: return "/Country/US";
|
||||
case 854: return "/Country/BF";
|
||||
case 858: return "/Country/UY";
|
||||
case 860: return "/Country/UZ";
|
||||
case 862: return "/Country/VE";
|
||||
case 882: return "/Country/WS";
|
||||
case 887: return "/Country/YE";
|
||||
case 894: return "/Country/ZM";
|
||||
default: return $"/Country/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// uuid [TODO: Requires 128-bit values]
|
||||
#region 2.25.*
|
||||
|
||||
oid_2_25:
|
||||
|
||||
if (index == values.Length) return "/Joint-ISO-ITU-T/UUID";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: return "/Joint-ISO-ITU-T/UUID/00000000-0000-0000-0000-000000000000";
|
||||
//case 288786655511405443130567505384701230: return "/Joint-ISO-ITU-T/UUID/00379e48-0a2b-1085-b288-0002a5d5fd2e";
|
||||
//case 987895962269883002155146617097157934: return "/Joint-ISO-ITU-T/UUID/00be4308-0c89-1085-8ea0-0002a5d5fd2e";
|
||||
//case 1858228783942312576083372383319475483: return "/Joint-ISO-ITU-T/UUID/0165e1c0-a655-11e0-95b8-0002a5d5c51b";
|
||||
//case 2474299330026746002885628159579243803: return "/Joint-ISO-ITU-T/UUID/01dc8860-25fb-11da-82b2-0002a5d5c51b";
|
||||
//case 3263645701162998421821186056373271854: return "/Joint-ISO-ITU-T/UUID/02748e28-08c4-1085-b21d-0002a5d5fd2e";
|
||||
//case 3325839809379844461264382260940242222: return "/Joint-ISO-ITU-T/UUID/02808890-0ad8-1085-9bdf-0002a5d5fd2e";
|
||||
// TODO: Left off at http://www.oid-info.com/get/2.25.3664154270495270126161055518190585115
|
||||
default: return $"/Joint-ISO-ITU-T/UUID/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// telebiometrics
|
||||
#region 2.42.*
|
||||
|
||||
oid_2_42:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: goto oid_2_42_0;
|
||||
case 1: goto oid_2_42_1;
|
||||
case 2: goto oid_2_42_2;
|
||||
case 3: goto oid_2_42_3;
|
||||
default: return $"/Telebiometrics/{values[index - 1]}";
|
||||
}
|
||||
|
||||
// modules
|
||||
#region 2.42.0.*
|
||||
|
||||
oid_2_42_0:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/Modules";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: goto oid_2_42_0_0;
|
||||
default: return $"/Telebiometrics/Modules/{values[index - 1]}";
|
||||
}
|
||||
|
||||
// main
|
||||
#region 2.42.0.0.*
|
||||
|
||||
oid_2_42_0_0:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/Modules/Main_Module";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/Telebiometrics/Modules/Main_Module/Version1";
|
||||
default: return $"/Telebiometrics/Modules/Main_Module/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
// tmm
|
||||
#region 2.42.1.*
|
||||
|
||||
oid_2_42_1:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/TMM";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: goto oid_2_42_1_0;
|
||||
case 1: goto oid_2_42_1_1;
|
||||
case 2: goto oid_2_42_1_2;
|
||||
case 3: goto oid_2_42_1_3;
|
||||
case 4: return "/Telebiometrics/TMM/Practitioners";
|
||||
default: return $"/Telebiometrics/TMM/{values[index - 1]}";
|
||||
}
|
||||
|
||||
// modules
|
||||
#region 2.42.1.0.*
|
||||
|
||||
oid_2_42_1_0:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/TMM/Modules";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: goto oid_2_42_1_0_0;
|
||||
default: return $"/Telebiometrics/TMM/Modules/{values[index - 1]}";
|
||||
}
|
||||
|
||||
// main
|
||||
#region 2.42.1.0.0.*
|
||||
|
||||
oid_2_42_1_0_0:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/TMM/Modules/Main";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: return "/Telebiometrics/TMM/Modules/Main/First_Version";
|
||||
default: return $"/Telebiometrics/TMM/Modules/Main/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
// measures, metric
|
||||
#region 2.42.1.1.*
|
||||
|
||||
oid_2_42_1_1:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/TMM/Measures";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: goto oid_2_42_1_1_1;
|
||||
case 2: return "/Telebiometrics/TMM/Measures/Units";
|
||||
case 3: return "/Telebiometrics/TMM/Measures/Symbols";
|
||||
case 4: return "/Telebiometrics/TMM/Measures/Conditions";
|
||||
case 5: goto oid_2_42_1_1_5;
|
||||
default: return $"/Telebiometrics/TMM/Measures/{values[index - 1]}";
|
||||
}
|
||||
|
||||
// quantities
|
||||
#region 2.42.1.1.1.*
|
||||
|
||||
oid_2_42_1_1_1:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/TMM/Measures/Quantities";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/Telebiometrics/TMM/Measures/Quantities/Physics";
|
||||
case 2: return "/Telebiometrics/TMM/Measures/Quantities/Chemistry";
|
||||
case 3: return "/Telebiometrics/TMM/Measures/Quantities/Biology";
|
||||
case 4: return "/Telebiometrics/TMM/Measures/Quantities/Culturology";
|
||||
case 5: return "/Telebiometrics/TMM/Measures/Quantities/Psychology";
|
||||
default: return $"/Telebiometrics/TMM/Measures/Quantities/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// methods
|
||||
#region 2.42.1.1.5.*
|
||||
|
||||
oid_2_42_1_1_5:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/TMM/Measures/Methods";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/Telebiometrics/TMM/Measures/Methods/Physics";
|
||||
case 2: return "/Telebiometrics/TMM/Measures/Methods/Chemistry";
|
||||
case 3: return "/Telebiometrics/TMM/Measures/Methods/Biology";
|
||||
case 4: return "/Telebiometrics/TMM/Measures/Methods/Culturology";
|
||||
case 5: return "/Telebiometrics/TMM/Measures/Methods/Psychology";
|
||||
default: return $"/Telebiometrics/TMM/Measures/Methods/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
// fields-of-study, scientific
|
||||
#region 2.42.1.2.*
|
||||
|
||||
oid_2_42_1_2:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/TMM/Fields_of_Study";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/Telebiometrics/TMM/Fields_of_Study/Physics";
|
||||
case 2: return "/Telebiometrics/TMM/Fields_of_Study/Chemistry";
|
||||
case 3: return "/Telebiometrics/TMM/Fields_of_Study/Biology";
|
||||
case 4: return "/Telebiometrics/TMM/Fields_of_Study/Culturology";
|
||||
case 5: return "/Telebiometrics/TMM/Fields_of_Study/Psychology";
|
||||
default: return $"/Telebiometrics/TMM/Fields_of_Study/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// modalities, sensory
|
||||
#region 2.42.1.3.*
|
||||
|
||||
oid_2_42_1_3:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/TMM/Modalities";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/Telebiometrics/TMM/Modalities/Tango";
|
||||
case 2: return "/Telebiometrics/TMM/Modalities/Video";
|
||||
case 3: return "/Telebiometrics/TMM/Modalities/Audio";
|
||||
case 4: return "/Telebiometrics/TMM/Modalities/Chemo";
|
||||
case 5: return "/Telebiometrics/TMM/Modalities/Radio";
|
||||
case 6: return "/Telebiometrics/TMM/Modalities/Calor";
|
||||
case 7: return "/Telebiometrics/TMM/Modalities/Electro";
|
||||
default: return $"/Telebiometrics/TMM/Modalities/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
// human-physiology
|
||||
#region 2.42.2.*
|
||||
|
||||
oid_2_42_2:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/Human_Physiology";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: goto oid_2_42_2_0;
|
||||
case 1: goto oid_2_42_2_1;
|
||||
case 2: return "/Telebiometrics/Human_Physiology/Symbol_Combinations";
|
||||
default: return $"/Telebiometrics/Human_Physiology/{values[index - 1]}";
|
||||
}
|
||||
|
||||
// modules
|
||||
#region 2.42.2.0.*
|
||||
|
||||
oid_2_42_2_0:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/Human_Physiology/Modules";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: goto oid_2_42_2_0_0;
|
||||
default: return $"/Telebiometrics/Human_Physiology/Modules/{values[index - 1]}";
|
||||
}
|
||||
|
||||
// main
|
||||
#region 2.42.2.0.0.*
|
||||
|
||||
oid_2_42_2_0_0:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/Human_Physiology/Modules/Main_Module";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: return "/Telebiometrics/Human_Physiology/Modules/Main_Module/First_Version";
|
||||
default: return $"/Telebiometrics/Human_Physiology/Modules/Main_Module/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
// symbols
|
||||
#region 2.42.2.1.*
|
||||
|
||||
oid_2_42_2_1:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/Human_Physiology/Symbols";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/Telebiometrics/Human_Physiology/Symbols/Tango_in";
|
||||
case 2: return "/Telebiometrics/Human_Physiology/Symbols/Video_in";
|
||||
case 3: return "/Telebiometrics/Human_Physiology/Symbols/Audio_in";
|
||||
case 4: return "/Telebiometrics/Human_Physiology/Symbols/Chemo_in";
|
||||
case 5: return "/Telebiometrics/Human_Physiology/Symbols/Radio_in";
|
||||
case 6: return "/Telebiometrics/Human_Physiology/Symbols/Calor_in";
|
||||
case 7: return "/Telebiometrics/Human_Physiology/Symbols/Tango_out";
|
||||
case 8: return "/Telebiometrics/Human_Physiology/Symbols/Video_out";
|
||||
case 9: return "/Telebiometrics/Human_Physiology/Symbols/Audio_out";
|
||||
case 10: return "/Telebiometrics/Human_Physiology/Symbols/Chemo_out";
|
||||
case 11: return "/Telebiometrics/Human_Physiology/Symbols/Radio_out";
|
||||
case 12: return "/Telebiometrics/Human_Physiology/Symbols/Calor_out";
|
||||
case 13: return "/Telebiometrics/Human_Physiology/Symbols/Safe";
|
||||
case 14: return "/Telebiometrics/Human_Physiology/Symbols/Threshold";
|
||||
default: return $"/Telebiometrics/Human_Physiology/Symbols/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
// obj-cat, telehealth, e-health-protocol, th
|
||||
#region 2.42.3.*
|
||||
|
||||
oid_2_42_3:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/E_Health_Protocol";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: goto oid_2_42_3_0;
|
||||
case 1: return "/Telebiometrics/E_Health_Protocol/[Patient schemes]";
|
||||
case 2: return "/Telebiometrics/E_Health_Protocol/[Medical staff schemes]";
|
||||
case 3: return "/Telebiometrics/E_Health_Protocol/[Observer schemes]";
|
||||
case 4: return "/Telebiometrics/E_Health_Protocol/[Pharmaceutical schemes]";
|
||||
case 5: return "/Telebiometrics/E_Health_Protocol/[Laboratory schemes]";
|
||||
case 6: return "/Telebiometrics/E_Health_Protocol/[Drug manufacturer schemes]";
|
||||
case 7: return "/Telebiometrics/E_Health_Protocol/[Medical device schemes]";
|
||||
case 8: return "/Telebiometrics/E_Health_Protocol/[Medical software schemes]";
|
||||
case 9: return "/Telebiometrics/E_Health_Protocol/[Medical insurance schemes]";
|
||||
case 10: return "/Telebiometrics/E_Health_Protocol/[Medical record schemes]";
|
||||
default: return $"/Telebiometrics/E_Health_Protocol/{values[index - 1]}";
|
||||
}
|
||||
|
||||
// obj-cat, telehealth, e-health-protocol, th
|
||||
#region 2.42.3.0.*
|
||||
|
||||
oid_2_42_3_0:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/E_Health_Protocol/Modules";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: goto oid_2_42_3_0_0;
|
||||
case 1: goto oid_2_42_3_0_1;
|
||||
case 2: goto oid_2_42_3_0_2;
|
||||
case 3: goto oid_2_42_3_0_3;
|
||||
case 4: goto oid_2_42_3_0_4;
|
||||
case 5: goto oid_2_42_3_0_5;
|
||||
default: return $"/Telebiometrics/E_Health_Protocol/Modules/{values[index - 1]}";
|
||||
}
|
||||
|
||||
// identification
|
||||
#region 2.42.3.0.0.*
|
||||
|
||||
oid_2_42_3_0_0:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/E_Health_Protocol/Modules/Identification";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/Telebiometrics/E_Health_Protocol/Modules/Identification/Version1";
|
||||
default: return $"/Telebiometrics/E_Health_Protocol/Modules/Identification/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// set-up
|
||||
#region 2.42.3.0.1.*
|
||||
|
||||
oid_2_42_3_0_1:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/E_Health_Protocol/Modules/Setup";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/Telebiometrics/E_Health_Protocol/Modules/Setup/Version1";
|
||||
default: return $"/Telebiometrics/E_Health_Protocol/Modules/Setup/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// send-and-ack
|
||||
#region 2.42.3.0.2.*
|
||||
|
||||
oid_2_42_3_0_2:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/E_Health_Protocol/Modules/Send-and-ack";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/Telebiometrics/E_Health_Protocol/Modules/Send-and-ack/Version1";
|
||||
default: return $"/Telebiometrics/E_Health_Protocol/Modules/Send-and-ack/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// command-response
|
||||
#region 2.42.3.0.3.*
|
||||
|
||||
oid_2_42_3_0_3:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/E_Health_Protocol/Modules/Command-response";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/Telebiometrics/E_Health_Protocol/Modules/Command-response/Version1";
|
||||
default: return $"/Telebiometrics/E_Health_Protocol/Modules/Command-response/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// quantity-and-units
|
||||
#region 2.42.3.0.4.*
|
||||
|
||||
oid_2_42_3_0_4:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/E_Health_Protocol/Modules/Quantities_And_Units";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/Telebiometrics/E_Health_Protocol/Modules/Quantities_And_Units/Version1";
|
||||
default: return $"/Telebiometrics/E_Health_Protocol/Modules/Quantities_And_Units/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// examples
|
||||
#region 2.42.3.0.5.*
|
||||
|
||||
oid_2_42_3_0_5:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/E_Health_Protocol/Modules/Examples";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: return "/Telebiometrics/E_Health_Protocol/Modules/Examples/Command_Response";
|
||||
case 1: return "/Telebiometrics/E_Health_Protocol/Modules/Examples/Data_Message";
|
||||
default: return $"/Telebiometrics/E_Health_Protocol/Modules/Examples/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
// cybersecurity
|
||||
#region 2.48.*
|
||||
|
||||
oid_2_48:
|
||||
|
||||
if (index == values.Length) return "/Cybersecurity";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/Cybersecurity/Country";
|
||||
case 2: return "/Cybersecurity/International-Org";
|
||||
default: return $"/Cybersecurity/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// alerting
|
||||
#region 2.49.*
|
||||
|
||||
oid_2_49:
|
||||
|
||||
if (index == values.Length) return "/Alerting";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: return "/Alerting/WMO";
|
||||
default: return $"/Alerting/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore IDE0011
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BinaryObjectScanner.ASN1
|
||||
{
|
||||
/// <summary>
|
||||
/// Methods related to Object Identifiers (OID)
|
||||
/// </summary>
|
||||
public static partial class ObjectIdentifier
|
||||
{
|
||||
// TODO: ulong[] isn't going to work. If we can use .NET 7, we can use UInt128
|
||||
// We might want to look into storing all values as GUID? I don't remember if
|
||||
// you can do value comparisions between an integral value and a GUID, though.
|
||||
|
||||
/// <summary>
|
||||
/// Parse an OID in DER-encoded byte notation into a list of values
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array representing the data to read</param>
|
||||
/// <param name="length">Total length of the data according to the DER TLV</param>
|
||||
/// <returns>Array of values representing the OID</returns>
|
||||
public static ulong[] ParseDERIntoArray(byte[] data, ulong length)
|
||||
{
|
||||
// The first byte contains nodes 1 and 2
|
||||
int firstNode = Math.DivRem(data[0], 40, out int secondNode);
|
||||
|
||||
// Create a list for all nodes
|
||||
List<ulong> nodes = new List<ulong> { (ulong)firstNode, (ulong)secondNode };
|
||||
|
||||
// All other nodes are encoded uniquely
|
||||
int offset = 1;
|
||||
while (offset < (long)length)
|
||||
{
|
||||
// If bit 7 is not set
|
||||
if ((data[offset] & 0x80) == 0)
|
||||
{
|
||||
nodes.Add(data[offset]);
|
||||
offset++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise, read the encoded value in a loop
|
||||
ulong dotValue = 0;
|
||||
bool doneProcessing = false;
|
||||
|
||||
do
|
||||
{
|
||||
// Shift the current encoded value
|
||||
dotValue <<= 7;
|
||||
|
||||
// If we have a leading zero byte, we're at the end
|
||||
if ((data[offset] & 0x80) == 0)
|
||||
doneProcessing = true;
|
||||
|
||||
// Clear the top byte
|
||||
unchecked { data[offset] &= (byte)~0x80; }
|
||||
|
||||
// Add the new value to the result
|
||||
dotValue |= data[offset];
|
||||
|
||||
// Increment the offset
|
||||
offset++;
|
||||
} while (offset < data.Length && !doneProcessing);
|
||||
|
||||
// Add the parsed value to the output
|
||||
nodes.Add(dotValue);
|
||||
}
|
||||
|
||||
return nodes.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
namespace BinaryObjectScanner.ASN1
|
||||
{
|
||||
#pragma warning disable IDE0011
|
||||
|
||||
/// <summary>
|
||||
/// Methods related to Object Identifiers (OID) and dot notation
|
||||
/// </summary>
|
||||
public static partial class ObjectIdentifier
|
||||
{
|
||||
/// <summary>
|
||||
/// Parse an OID in separated-value notation into dot notation
|
||||
/// </summary>
|
||||
/// <param name="values">List of values to check against</param>
|
||||
/// <returns>List of values representing the dot notation</returns>
|
||||
public static string ParseOIDToDotNotation(ulong[] values)
|
||||
{
|
||||
// If we have an invalid set of values, we can't do anything
|
||||
if (values == null || values.Length == 0)
|
||||
return null;
|
||||
|
||||
return string.Join(".", values);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore IDE0011
|
||||
}
|
||||
@@ -1,259 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using SabreTools.IO;
|
||||
|
||||
namespace BinaryObjectScanner.ASN1
|
||||
{
|
||||
/// <summary>
|
||||
/// ASN.1 type/length/value class that all types are based on
|
||||
/// </summary>
|
||||
public class TypeLengthValue
|
||||
{
|
||||
/// <summary>
|
||||
/// The ASN.1 type
|
||||
/// </summary>
|
||||
public ASN1Type Type { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Length of the value
|
||||
/// </summary>
|
||||
public ulong Length { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Generic value associated with <see cref="Type"/>
|
||||
/// </summary>
|
||||
public object Value { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Read from the source data array at an index
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array representing data to read</param>
|
||||
/// <param name="index">Index within the array to read at</param>
|
||||
public TypeLengthValue(byte[] data, ref int index)
|
||||
{
|
||||
// Get the type and modifiers
|
||||
this.Type = (ASN1Type)data[index++];
|
||||
|
||||
// If we have an end indicator, we just return
|
||||
if (this.Type == ASN1Type.V_ASN1_EOC)
|
||||
return;
|
||||
|
||||
// Get the length of the value
|
||||
this.Length = ReadLength(data, ref index);
|
||||
|
||||
// Read the value
|
||||
if (this.Type.HasFlag(ASN1Type.V_ASN1_CONSTRUCTED))
|
||||
{
|
||||
var valueList = new List<TypeLengthValue>();
|
||||
|
||||
int currentIndex = index;
|
||||
while (index < currentIndex + (int)this.Length)
|
||||
{
|
||||
valueList.Add(new TypeLengthValue(data, ref index));
|
||||
}
|
||||
|
||||
this.Value = valueList.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Get more granular based on type
|
||||
this.Value = data.ReadBytes(ref index, (int)this.Length);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Format the TLV as a string
|
||||
/// </summary>
|
||||
/// <param name="paddingLevel">Padding level of the item when formatting</param>
|
||||
/// <returns>String representing the TLV, if possible</returns>
|
||||
public string Format(int paddingLevel = 0)
|
||||
{
|
||||
// Create the left-padding string
|
||||
string padding = new string(' ', paddingLevel);
|
||||
|
||||
// If we have an invalid item
|
||||
if (this.Type == 0)
|
||||
return $"{padding}UNKNOWN TYPE";
|
||||
|
||||
// Create the string builder
|
||||
StringBuilder formatBuilder = new StringBuilder();
|
||||
|
||||
// Append the type
|
||||
formatBuilder.Append($"{padding}Type: {this.Type}");
|
||||
if (this.Type == ASN1Type.V_ASN1_EOC)
|
||||
return formatBuilder.ToString();
|
||||
|
||||
// Append the length
|
||||
formatBuilder.Append($", Length: {this.Length}");
|
||||
if (this.Length == 0)
|
||||
return formatBuilder.ToString();
|
||||
|
||||
// If we have a constructed type
|
||||
if (this.Type.HasFlag(ASN1Type.V_ASN1_CONSTRUCTED))
|
||||
{
|
||||
var valueAsObjectArray = this.Value as TypeLengthValue[];
|
||||
if (valueAsObjectArray == null)
|
||||
{
|
||||
formatBuilder.Append(", Value: [INVALID DATA TYPE]");
|
||||
return formatBuilder.ToString();
|
||||
}
|
||||
|
||||
formatBuilder.Append(", Value:\n");
|
||||
for (int i = 0; i < valueAsObjectArray.Length; i++)
|
||||
{
|
||||
var child = valueAsObjectArray[i];
|
||||
string childString = child.Format(paddingLevel + 1);
|
||||
formatBuilder.Append($"{childString}\n");
|
||||
}
|
||||
|
||||
return formatBuilder.ToString().TrimEnd('\n');
|
||||
}
|
||||
|
||||
// Get the value as a byte array
|
||||
byte[] valueAsByteArray = this.Value as byte[];
|
||||
if (valueAsByteArray == null)
|
||||
{
|
||||
formatBuilder.Append(", Value: [INVALID DATA TYPE]");
|
||||
return formatBuilder.ToString();
|
||||
}
|
||||
|
||||
// If we have a primitive type
|
||||
switch (this.Type)
|
||||
{
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-boolean"/>
|
||||
case ASN1Type.V_ASN1_BOOLEAN:
|
||||
if (this.Length > 1 || valueAsByteArray.Length > 1)
|
||||
formatBuilder.Append($" [Expected length of 1]");
|
||||
|
||||
bool booleanValue = valueAsByteArray[0] == 0x00 ? false : true;
|
||||
formatBuilder.Append($", Value: {booleanValue}");
|
||||
break;
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-integer"/>
|
||||
case ASN1Type.V_ASN1_INTEGER:
|
||||
Array.Reverse(valueAsByteArray);
|
||||
BigInteger integerValue = new BigInteger(valueAsByteArray);
|
||||
formatBuilder.Append($", Value: {integerValue}");
|
||||
break;
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-bit-string"/>
|
||||
case ASN1Type.V_ASN1_BIT_STRING:
|
||||
// TODO: Read into a BitArray and print that out instead?
|
||||
int unusedBits = valueAsByteArray[0];
|
||||
formatBuilder.Append($", Value with {unusedBits} unused bits: {BitConverter.ToString(valueAsByteArray.Skip(1).ToArray()).Replace('-', ' ')}");
|
||||
break;
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-octet-string"/>
|
||||
case ASN1Type.V_ASN1_OCTET_STRING:
|
||||
formatBuilder.Append($", Value: {BitConverter.ToString(valueAsByteArray).Replace('-', ' ')}");
|
||||
break;
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-object-identifier"/>
|
||||
/// <see cref="http://snmpsharpnet.com/index.php/2009/03/02/ber-encoding-and-decoding-oid-values/"/>
|
||||
case ASN1Type.V_ASN1_OBJECT:
|
||||
// Derive array of values
|
||||
ulong[] objectNodes = ObjectIdentifier.ParseDERIntoArray(valueAsByteArray, this.Length);
|
||||
|
||||
// Append the dot and modified OID-IRI notations
|
||||
string dotNotationString = ObjectIdentifier.ParseOIDToDotNotation(objectNodes);
|
||||
string oidIriString = ObjectIdentifier.ParseOIDToOIDIRINotation(objectNodes);
|
||||
formatBuilder.Append($", Value: {dotNotationString} ({oidIriString})");
|
||||
break;
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-utf8string"/>
|
||||
case ASN1Type.V_ASN1_UTF8STRING:
|
||||
formatBuilder.Append($", Value: {Encoding.UTF8.GetString(valueAsByteArray)}");
|
||||
break;
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-printablestring"/>
|
||||
case ASN1Type.V_ASN1_PRINTABLESTRING:
|
||||
formatBuilder.Append($", Value: {Encoding.ASCII.GetString(valueAsByteArray)}");
|
||||
break;
|
||||
|
||||
//case ASN1Type.V_ASN1_T61STRING:
|
||||
case ASN1Type.V_ASN1_TELETEXSTRING:
|
||||
formatBuilder.Append($", Value: {Encoding.ASCII.GetString(valueAsByteArray)}");
|
||||
break;
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-ia5string"/>
|
||||
case ASN1Type.V_ASN1_IA5STRING:
|
||||
formatBuilder.Append($", Value: {Encoding.ASCII.GetString(valueAsByteArray)}");
|
||||
break;
|
||||
|
||||
case ASN1Type.V_ASN1_UTCTIME:
|
||||
string utctimeString = Encoding.ASCII.GetString(valueAsByteArray);
|
||||
if (DateTime.TryParse(utctimeString, out DateTime utctimeDateTime))
|
||||
formatBuilder.Append($", Value: {utctimeDateTime}");
|
||||
else
|
||||
formatBuilder.Append($", Value: {utctimeString}");
|
||||
break;
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-bmpstring"/>
|
||||
case ASN1Type.V_ASN1_BMPSTRING:
|
||||
formatBuilder.Append($", Value: {Encoding.Unicode.GetString(valueAsByteArray)}");
|
||||
break;
|
||||
|
||||
default:
|
||||
formatBuilder.Append($", Value (Unknown Format): {BitConverter.ToString(this.Value as byte[]).Replace('-', ' ')}");
|
||||
break;
|
||||
}
|
||||
|
||||
// Return the formatted string
|
||||
return formatBuilder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the length field for a type
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array representing data to read</param>
|
||||
/// <param name="index">Index within the array to read at</param>
|
||||
/// <returns>The length value read from the array</returns>
|
||||
private static ulong ReadLength(byte[] data, ref int index)
|
||||
{
|
||||
// If we have invalid data, throw an exception
|
||||
if (data == null || index < 0 && index >= data.Length)
|
||||
throw new ArgumentException();
|
||||
|
||||
// Read the first byte, assuming it's the length
|
||||
byte length = data[index++];
|
||||
|
||||
// If the bit 7 is not set, then use the value as it is
|
||||
if ((length & 0x80) == 0)
|
||||
return length;
|
||||
|
||||
// Otherwise, use the value as the number of remaining bytes to read
|
||||
int bytesToRead = length & ~0x80;
|
||||
byte[] bytesRead = data.ReadBytes(ref index, bytesToRead);
|
||||
|
||||
// TODO: Write extensions to read big-endian
|
||||
|
||||
// Reverse the bytes to be in big-endian order
|
||||
Array.Reverse(bytesRead);
|
||||
|
||||
switch (bytesRead.Length)
|
||||
{
|
||||
case 1:
|
||||
return bytesRead[0];
|
||||
case 2:
|
||||
return BitConverter.ToUInt16(bytesRead, 0);
|
||||
case 3:
|
||||
Array.Resize(ref bytesRead, 4);
|
||||
goto case 4;
|
||||
case 4:
|
||||
return BitConverter.ToUInt32(bytesRead, 0);
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
Array.Resize(ref bytesRead, 8);
|
||||
goto case 8;
|
||||
case 8:
|
||||
return BitConverter.ToUInt64(bytesRead, 0);
|
||||
default:
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,11 +25,11 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BinaryObjectScanner.ASN1\BinaryObjectScanner.ASN1.csproj" />
|
||||
<ProjectReference Include="..\BinaryObjectScanner.Compression\BinaryObjectScanner.Compression.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.ASN1" Version="1.1.0" />
|
||||
<PackageReference Include="SabreTools.IO" Version="1.1.1" />
|
||||
<PackageReference Include="SabreTools.Models" Version="1.1.1" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="1.1.1" />
|
||||
|
||||
@@ -24,8 +24,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "psxt001z", "psxt001z\psxt00
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BinaryObjectScanner.Utilities", "BinaryObjectScanner.Utilities\BinaryObjectScanner.Utilities.csproj", "{3C1D1FE2-7E7C-4EC1-96B1-FE68B73282CD}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BinaryObjectScanner.ASN1", "BinaryObjectScanner.ASN1\BinaryObjectScanner.ASN1.csproj", "{D5407F3A-236C-45B5-BE3A-1505412DCB22}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BinaryObjectScanner.Compression", "BinaryObjectScanner.Compression\BinaryObjectScanner.Compression.csproj", "{B55206B2-58FD-4A47-AADC-74982FEA8FAD}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BinaryObjectScanner.Interfaces", "BinaryObjectScanner.Interfaces\BinaryObjectScanner.Interfaces.csproj", "{7193566B-8071-437F-9B42-9A009AAA22DC}"
|
||||
@@ -68,10 +66,6 @@ Global
|
||||
{3C1D1FE2-7E7C-4EC1-96B1-FE68B73282CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3C1D1FE2-7E7C-4EC1-96B1-FE68B73282CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3C1D1FE2-7E7C-4EC1-96B1-FE68B73282CD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D5407F3A-236C-45B5-BE3A-1505412DCB22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D5407F3A-236C-45B5-BE3A-1505412DCB22}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D5407F3A-236C-45B5-BE3A-1505412DCB22}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D5407F3A-236C-45B5-BE3A-1505412DCB22}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B55206B2-58FD-4A47-AADC-74982FEA8FAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B55206B2-58FD-4A47-AADC-74982FEA8FAD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B55206B2-58FD-4A47-AADC-74982FEA8FAD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
||||
@@ -40,10 +40,6 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BinaryObjectScanner.ASN1\BinaryObjectScanner.ASN1.csproj">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\BinaryObjectScanner.Compression\BinaryObjectScanner.Compression.csproj">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
|
||||
Reference in New Issue
Block a user