31 Commits
1.2.0 ... 1.4.2

Author SHA1 Message Date
Matt Nadareski
e632f8537b Bump version 2024-11-20 15:55:54 -05:00
Matt Nadareski
ce8c4b1831 Fix issue with 0 unused bits 2024-11-20 15:03:26 -05:00
Matt Nadareski
2bdb56aca2 Bump version 2024-11-15 20:51:12 -05:00
Matt Nadareski
ce6ffd3f7f Framework only matters for executable 2024-11-15 20:48:13 -05:00
Matt Nadareski
c06618c66c Update IO to 1.5.1 2024-11-15 20:46:27 -05:00
Matt Nadareski
eb356483b4 Fix path in GHA 2024-11-13 11:58:19 -05:00
Matt Nadareski
0e76552df8 Fix path in GHA 2024-11-13 11:55:55 -05:00
Matt Nadareski
070274e33f Bump version 2024-11-13 00:50:36 -05:00
Matt Nadareski
dd64d6f843 Add .NET 9 to target frameworks 2024-11-13 00:50:16 -05:00
Matt Nadareski
69992f64be Add proper multi-framework support 2024-11-05 19:40:49 -05:00
Matt Nadareski
e63921fbc2 Linq just isn't needed 2024-11-05 19:38:24 -05:00
Matt Nadareski
69dc21c814 Bump version 2024-10-01 13:32:24 -04:00
Matt Nadareski
4c07f24e3c Update IO to 1.4.12 2024-10-01 13:31:41 -04:00
Matt Nadareski
b6b43d9e1b Fix README location for package 2024-10-01 13:09:54 -04:00
Matt Nadareski
7c972c1ea2 Move project to subfolder 2024-10-01 13:07:45 -04:00
Matt Nadareski
7c40583898 Some old .NET simplification 2024-10-01 12:41:53 -04:00
Matt Nadareski
ef479c783a Remove Linq requirement from old .NET 2024-10-01 01:53:26 -04:00
Matt Nadareski
1ebd9f82ee Update IO to 1.4.11 2024-09-25 10:54:48 -04:00
Matt Nadareski
774597b17c Bump version 2024-04-26 21:22:20 -04:00
Matt Nadareski
29437475fb Make Linux publish script executable 2024-04-26 21:21:19 -04:00
Matt Nadareski
214d4e4f9e Add publish scripts 2024-04-26 21:20:50 -04:00
Matt Nadareski
06c742cd15 Update SabreTools.IO 2024-04-26 21:18:34 -04:00
Matt Nadareski
bc591f367f Bump version 2024-03-05 11:07:01 -05:00
Matt Nadareski
8c6b962bd6 Update SabreTools.IO 2024-03-05 10:47:16 -05:00
Matt Nadareski
306b9a49ee Use "main" instead of "master" 2024-02-27 19:07:03 -05:00
Matt Nadareski
21ad30e65c Update copyright date 2024-02-27 17:20:37 -05:00
Matt Nadareski
50b8df07f1 Add nuget package and PR workflows 2024-02-27 17:20:20 -05:00
Matt Nadareski
fb33b1be85 Bump version 2023-11-22 09:11:08 -05:00
Matt Nadareski
965a8a5187 Use switch expression for leaves 2023-11-22 02:19:55 -05:00
Matt Nadareski
513e03c124 Support .NET Framework 2.0 2023-11-21 11:40:25 -05:00
Matt Nadareski
6d78f1f779 Update SabreTools.IO to 1.3.0 2023-11-21 11:30:00 -05:00
17 changed files with 19145 additions and 18106 deletions

43
.github/workflows/build_nupkg.yml vendored Normal file
View File

@@ -0,0 +1,43 @@
name: Nuget Pack
on:
push:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 9.0.x
- name: Restore dependencies
run: dotnet restore
- name: Pack
run: dotnet pack
- name: Upload build
uses: actions/upload-artifact@v4
with:
name: 'Nuget Package'
path: 'SabreTools.ASN1/bin/Release/*.nupkg'
- name: Upload to rolling
uses: ncipollo/release-action@v1.14.0
with:
allowUpdates: True
artifacts: 'SabreTools.ASN1/bin/Release/*.nupkg'
body: 'Last built commit: ${{ github.sha }}'
name: 'Rolling Release'
prerelease: True
replacesArtifacts: True
tag: "rolling"
updateOnlyUnreleased: True

17
.github/workflows/check_pr.yml vendored Normal file
View File

@@ -0,0 +1,17 @@
name: Build PR
on: [pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 9.0.x
- name: Build
run: dotnet build

File diff suppressed because it is too large Load Diff

View File

@@ -1,866 +0,0 @@
using System.Linq;
using System.Text;
namespace SabreTools.ASN1
{
/// <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
}
}
}

View File

@@ -1,32 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Assembly Properties -->
<TargetFrameworks>net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0</TargetFrameworks>
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Version>1.2.0</Version>
<!-- Package Properties -->
<Authors>Matt Nadareski</Authors>
<Description>Serialization and deserialization helpers for various types</Description>
<Copyright>Copyright (c) Matt Nadareski 2022-2023</Copyright>
<PackageProjectUrl>https://github.com/SabreTools/</PackageProjectUrl>
<PackageReadmeFile>README.md</PackageReadmeFile>
<RepositoryUrl>https://github.com/SabreTools/SabreTools.ASN1</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageTags>asn asn1 dot oid</PackageTags>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
</PropertyGroup>
<ItemGroup>
<None Include="README.md" Pack="true" PackagePath=""/>
</ItemGroup>
<ItemGroup>
<PackageReference Include="SabreTools.IO" Version="1.2.0" />
</ItemGroup>
</Project>

View File

@@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SabreTools.ASN1", "SabreTools.ASN1.csproj", "{88EA40DD-E313-479C-94EA-0AB948DB4720}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SabreTools.ASN1", "SabreTools.ASN1\SabreTools.ASN1.csproj", "{88EA40DD-E313-479C-94EA-0AB948DB4720}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,906 @@
using System;
using System.Text;
namespace SabreTools.ASN1
{
/// <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("/");
// Get the remaining values in a new array
var remainingValues = new ulong[values.Length - index];
Array.Copy(values, index, remainingValues, 0, remainingValues.Length);
// Convert the values and append to the builder
var stringValues = Array.ConvertAll(remainingValues, v => v.ToString());
nameBuilder.Append(string.Join("/", stringValues));
// 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
var oidPath = $"/{values[index]}";
switch (values[index++])
{
case 0: goto oid_0;
case 1: goto oid_1;
case 2: goto oid_2;
default: return oidPath;
}
#endregion
// itu-t, ccitt, itu-r
#region 0.*
oid_0:
oidPath += "/ITU-T";
if (index == values.Length) return oidPath;
switch (values[index++])
{
case 0: goto oid_0_0;
case 2: return $"{oidPath}/Administration";
case 3: return $"{oidPath}/Network-Operator";
case 4: return $"{oidPath}/Identified-Organization";
case 5: return "/ITU-R/R-Recommendation";
case 9: return $"{oidPath}/Data";
default: return $"{oidPath}/{values[index - 1]}";
};
// recommendation
#region 0.0.*
oid_0_0:
oidPath += "/Recommendation";
if (index == values.Length) return oidPath;
return values[index++] switch
{
1 => $"{oidPath}/A",
2 => $"{oidPath}/B",
3 => $"{oidPath}/C",
4 => $"{oidPath}/D",
5 => $"{oidPath}/E",
6 => $"{oidPath}/F",
7 => $"{oidPath}/G",
8 => $"{oidPath}/H",
9 => $"{oidPath}/I",
10 => $"{oidPath}/J",
11 => $"{oidPath}/K",
12 => $"{oidPath}/L",
13 => $"{oidPath}/M",
14 => $"{oidPath}/N",
15 => $"{oidPath}/O",
16 => $"{oidPath}/P",
17 => $"{oidPath}/Q",
18 => $"{oidPath}/R",
19 => $"{oidPath}/S",
20 => $"{oidPath}/T",
21 => $"{oidPath}/U",
22 => $"{oidPath}/V",
24 => $"{oidPath}/X",
25 => $"{oidPath}/Y",
26 => $"{oidPath}/Z",
_ => $"{oidPath}/{values[index - 1]}",
};
#endregion
#endregion
// iso
#region 1.*
oid_1:
oidPath += "/ISO";
if (index == values.Length) return oidPath;
switch (values[index++])
{
case 0: return $"{oidPath}/Standard";
case 1: return $"{oidPath}/Registration-Authority";
case 2: goto oid_1_2;
case 3: return $"{oidPath}/Identified-Organization";
default: return $"{oidPath}/{values[index - 1]}";
}
// member-body
#region 1.2.*
oid_1_2:
oidPath += "/Member-Body";
if (index == values.Length) return oidPath;
return values[index++] switch
{
36 => $"{oidPath}/AU",
40 => $"{oidPath}/AT",
56 => $"{oidPath}/BE",
124 => $"{oidPath}/CA",
156 => $"{oidPath}/CN",
203 => $"{oidPath}/CZ",
208 => $"{oidPath}/DK",
246 => $"{oidPath}/FI",
250 => $"{oidPath}/FR",
276 => $"{oidPath}/DE",
300 => $"{oidPath}/GR",
344 => $"{oidPath}/HK",
372 => $"{oidPath}/IE",
392 => $"{oidPath}/JP",
398 => $"{oidPath}/KZ",
410 => $"{oidPath}/KR",
498 => $"{oidPath}/MD",
528 => $"{oidPath}/NL",
566 => $"{oidPath}/NG",
578 => $"{oidPath}/NO",
616 => $"{oidPath}/PL",
643 => $"{oidPath}/RU",
702 => $"{oidPath}/SG",
752 => $"{oidPath}/SE",
804 => $"{oidPath}/UA",
826 => $"{oidPath}/GB",
840 => $"{oidPath}/US",
_ => $"{oidPath}/{values[index - 1]}",
};
#endregion
#endregion
// joint-iso-itu-t, joint-iso-ccitt
#region 2.*
oid_2:
oidPath += "/Joint-ISO-ITU-T";
if (index == values.Length) return oidPath;
switch (values[index++])
{
case 1: return "/ASN.1";
case 16: oidPath = string.Empty; goto oid_2_16;
case 17: return $"{oidPath}/Registration-Procedures";
case 23: return $"{oidPath}/International-Organizations";
case 25: goto oid_2_25;
case 27: return "/Tag-Based";
case 28: return $"{oidPath}/ITS";
case 41: return "/BIP";
case 42: oidPath = string.Empty; goto oid_2_42;
case 48: oidPath = string.Empty; goto oid_2_48;
case 49: oidPath = string.Empty; goto oid_2_49;
case 50: return "/OIDResolutionSystem";
case 51: return "/GS1";
case 52: return $"{oidPath}/UAV";
case 999: return $"{oidPath}/Example";
default: return $"{oidPath}/{values[index - 1]}";
}
// country
#region 2.16.*
oid_2_16:
oidPath += "/Country";
if (index == values.Length) return oidPath;
return values[index++] switch
{
4 => $"{oidPath}AF",
8 => $"{oidPath}AL",
12 => $"{oidPath}DZ",
20 => $"{oidPath}AD",
24 => $"{oidPath}AO",
28 => $"{oidPath}AG",
31 => $"{oidPath}AZ",
32 => $"{oidPath}AR",
36 => $"{oidPath}AU",
40 => $"{oidPath}AT",
44 => $"{oidPath}BS",
48 => $"{oidPath}BH",
50 => $"{oidPath}BD",
51 => $"{oidPath}AM",
52 => $"{oidPath}BB",
56 => $"{oidPath}BE",
60 => $"{oidPath}BM",
64 => $"{oidPath}BT",
68 => $"{oidPath}BO",
70 => $"{oidPath}BA",
72 => $"{oidPath}BW",
76 => $"{oidPath}BR",
84 => $"{oidPath}BZ",
90 => $"{oidPath}SB",
96 => $"{oidPath}BN",
100 => $"{oidPath}BG",
104 => $"{oidPath}MM",
108 => $"{oidPath}BI",
112 => $"{oidPath}BY",
116 => $"{oidPath}KH",
120 => $"{oidPath}CM",
124 => $"{oidPath}CA",
132 => $"{oidPath}CV",
140 => $"{oidPath}CF",
144 => $"{oidPath}LK",
148 => $"{oidPath}TD",
152 => $"{oidPath}CL",
156 => $"{oidPath}CN",
158 => $"{oidPath}TW",
170 => $"{oidPath}CO",
174 => $"{oidPath}KM",
178 => $"{oidPath}CG",
180 => $"{oidPath}CD",
188 => $"{oidPath}CR",
191 => $"{oidPath}HR",
192 => $"{oidPath}CU",
196 => $"{oidPath}CY",
203 => $"{oidPath}CZ",
204 => $"{oidPath}BJ",
208 => $"{oidPath}DK",
212 => $"{oidPath}DM",
214 => $"{oidPath}DO",
218 => $"{oidPath}EC",
222 => $"{oidPath}SV",
226 => $"{oidPath}GQ",
231 => $"{oidPath}ET",
232 => $"{oidPath}ER",
233 => $"{oidPath}EE",
242 => $"{oidPath}FJ",
246 => $"{oidPath}FI",
250 => $"{oidPath}FR",
262 => $"{oidPath}DJ",
266 => $"{oidPath}GA",
268 => $"{oidPath}GE",
270 => $"{oidPath}GM",
275 => $"{oidPath}PS",
276 => $"{oidPath}DE",
288 => $"{oidPath}GH",
296 => $"{oidPath}KI",
300 => $"{oidPath}GR",
308 => $"{oidPath}GD",
320 => $"{oidPath}GT",
324 => $"{oidPath}GN",
328 => $"{oidPath}GY",
332 => $"{oidPath}HT",
336 => $"{oidPath}VA",
340 => $"{oidPath}HN",
344 => $"{oidPath}HK",
348 => $"{oidPath}HU",
352 => $"{oidPath}IS",
356 => $"{oidPath}IN",
360 => $"{oidPath}ID",
364 => $"{oidPath}IR",
368 => $"{oidPath}IQ",
372 => $"{oidPath}IE",
376 => $"{oidPath}IL",
380 => $"{oidPath}IT",
384 => $"{oidPath}CI",
388 => $"{oidPath}JM",
392 => $"{oidPath}JP",
398 => $"{oidPath}KZ",
400 => $"{oidPath}JO",
404 => $"{oidPath}KE",
408 => $"{oidPath}KP",
410 => $"{oidPath}KR",
414 => $"{oidPath}KW",
417 => $"{oidPath}KG",
418 => $"{oidPath}LA",
422 => $"{oidPath}LB",
426 => $"{oidPath}LS",
428 => $"{oidPath}LV",
430 => $"{oidPath}LR",
434 => $"{oidPath}LY",
438 => $"{oidPath}LI",
440 => $"{oidPath}LT",
442 => $"{oidPath}LU",
450 => $"{oidPath}MG",
454 => $"{oidPath}MW",
458 => $"{oidPath}MY",
462 => $"{oidPath}MV",
466 => $"{oidPath}ML",
470 => $"{oidPath}MT",
478 => $"{oidPath}MR",
480 => $"{oidPath}MU",
484 => $"{oidPath}MX",
492 => $"{oidPath}MC",
496 => $"{oidPath}MN",
498 => $"{oidPath}MD",
499 => $"{oidPath}ME",
504 => $"{oidPath}MA",
508 => $"{oidPath}MZ",
512 => $"{oidPath}OM",
516 => $"{oidPath}NA",
520 => $"{oidPath}NR",
524 => $"{oidPath}NP",
528 => $"{oidPath}NL",
530 => $"{oidPath}AN",
548 => $"{oidPath}VU",
554 => $"{oidPath}NZ",
558 => $"{oidPath}NI",
562 => $"{oidPath}NE",
566 => $"{oidPath}NG",
578 => $"{oidPath}NO",
583 => $"{oidPath}FM",
584 => $"{oidPath}MH",
585 => $"{oidPath}PW",
586 => $"{oidPath}PK",
591 => $"{oidPath}PA",
598 => $"{oidPath}PG",
600 => $"{oidPath}PY",
604 => $"{oidPath}PE",
608 => $"{oidPath}PH",
616 => $"{oidPath}PL",
620 => $"{oidPath}PT",
624 => $"{oidPath}GW",
626 => $"{oidPath}TL",
634 => $"{oidPath}QA",
642 => $"{oidPath}RO",
643 => $"{oidPath}RU",
646 => $"{oidPath}RW",
659 => $"{oidPath}KN",
662 => $"{oidPath}LC",
670 => $"{oidPath}VC",
674 => $"{oidPath}SM",
678 => $"{oidPath}ST",
682 => $"{oidPath}SA",
686 => $"{oidPath}SN",
688 => $"{oidPath}RS",
690 => $"{oidPath}SC",
694 => $"{oidPath}SL",
702 => $"{oidPath}SG",
703 => $"{oidPath}SK",
704 => $"{oidPath}VN",
705 => $"{oidPath}SI",
706 => $"{oidPath}SO",
710 => $"{oidPath}ZA",
716 => $"{oidPath}ZW",
724 => $"{oidPath}ES",
728 => $"{oidPath}SS",
729 => $"{oidPath}SD",
740 => $"{oidPath}SR",
748 => $"{oidPath}SZ",
752 => $"{oidPath}SE",
756 => $"{oidPath}CH",
760 => $"{oidPath}SY",
762 => $"{oidPath}TJ",
764 => $"{oidPath}TH",
768 => $"{oidPath}TG",
776 => $"{oidPath}TO",
780 => $"{oidPath}TT",
784 => $"{oidPath}AE",
788 => $"{oidPath}TN",
792 => $"{oidPath}TR",
795 => $"{oidPath}TM",
798 => $"{oidPath}TV",
800 => $"{oidPath}UG",
804 => $"{oidPath}UA",
807 => $"{oidPath}MK",
818 => $"{oidPath}EG",
826 => $"{oidPath}GB",
834 => $"{oidPath}TZ",
840 => $"{oidPath}US",
854 => $"{oidPath}BF",
858 => $"{oidPath}UY",
860 => $"{oidPath}UZ",
862 => $"{oidPath}VE",
882 => $"{oidPath}WS",
887 => $"{oidPath}YE",
894 => $"{oidPath}ZM",
_ => $"{oidPath}{values[index - 1]}",
};
#endregion
// uuid [TODO: Requires 128-bit values]
#region 2.25.*
oid_2_25:
oidPath += "/UUID";
if (index == values.Length) return oidPath;
return values[index++] switch
{
0 => $"{oidPath}/00000000-0000-0000-0000-000000000000",
//case 288786655511405443130567505384701230: return $"{oidPath}/00379e48-0a2b-1085-b288-0002a5d5fd2e";
//case 987895962269883002155146617097157934: return $"{oidPath}/00be4308-0c89-1085-8ea0-0002a5d5fd2e";
//case 1858228783942312576083372383319475483: return $"{oidPath}/0165e1c0-a655-11e0-95b8-0002a5d5c51b";
//case 2474299330026746002885628159579243803: return $"{oidPath}/01dc8860-25fb-11da-82b2-0002a5d5c51b";
//case 3263645701162998421821186056373271854: return $"{oidPath}/02748e28-08c4-1085-b21d-0002a5d5fd2e";
//case 3325839809379844461264382260940242222: return $"{oidPath}/02808890-0ad8-1085-9bdf-0002a5d5fd2e";
// TODO: Left off at http://www.oid-info.com/get/2.25.3664154270495270126161055518190585115
_ => $"{oidPath}/{values[index - 1]}",
};
#endregion
// telebiometrics
#region 2.42.*
oid_2_42:
oidPath += "/Telebiometrics";
if (index == values.Length) return oidPath;
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 $"{oidPath}/{values[index - 1]}";
}
// modules
#region 2.42.0.*
oid_2_42_0:
oidPath += "/Modules";
if (index == values.Length) return oidPath;
switch (values[index++])
{
case 0: goto oid_2_42_0_0;
default: return $"{oidPath}/{values[index - 1]}";
}
// main
#region 2.42.0.0.*
oid_2_42_0_0:
oidPath += "/Main_Module";
if (index == values.Length) return oidPath;
return values[index++] switch
{
1 => $"{oidPath}/Version1",
_ => $"{oidPath}/{values[index - 1]}",
};
#endregion
#endregion
// tmm
#region 2.42.1.*
oid_2_42_1:
oidPath += "/TMM";
if (index == values.Length) return oidPath;
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 $"{oidPath}/Practitioners";
default: return $"{oidPath}/{values[index - 1]}";
}
// modules
#region 2.42.1.0.*
oid_2_42_1_0:
oidPath += "/Modules";
if (index == values.Length) return oidPath;
switch (values[index++])
{
case 0: goto oid_2_42_1_0_0;
default: return $"{oidPath}/{values[index - 1]}";
}
// main
#region 2.42.1.0.0.*
oid_2_42_1_0_0:
oidPath += "/Main";
if (index == values.Length) return oidPath;
return values[index++] switch
{
0 => $"{oidPath}/First_Version",
_ => $"{oidPath}/{values[index - 1]}",
};
#endregion
#endregion
// measures, metric
#region 2.42.1.1.*
oid_2_42_1_1:
oidPath += "/Measures";
if (index == values.Length) return oidPath;
switch (values[index++])
{
case 1: goto oid_2_42_1_1_1;
case 2: return $"{oidPath}/Units";
case 3: return $"{oidPath}";
case 4: return $"{oidPath}/Conditions";
case 5: goto oid_2_42_1_1_5;
default: return $"{oidPath}/{values[index - 1]}";
}
// quantities
#region 2.42.1.1.1.*
oid_2_42_1_1_1:
oidPath += "/Quantities";
if (index == values.Length) return oidPath;
return values[index++] switch
{
1 => $"{oidPath}/Physics",
2 => $"{oidPath}/Chemistry",
3 => $"{oidPath}/Biology",
4 => $"{oidPath}/Culturology",
5 => $"{oidPath}/Psychology",
_ => $"{oidPath}/{values[index - 1]}",
};
#endregion
// methods
#region 2.42.1.1.5.*
oid_2_42_1_1_5:
oidPath += "/Methods";
if (index == values.Length) return oidPath;
return values[index++] switch
{
1 => $"{oidPath}/Physics",
2 => $"{oidPath}/Chemistry",
3 => $"{oidPath}/Biology",
4 => $"{oidPath}/Culturology",
5 => $"{oidPath}/Psychology",
_ => $"{oidPath}/{values[index - 1]}",
};
#endregion
#endregion
// fields-of-study, scientific
#region 2.42.1.2.*
oid_2_42_1_2:
oidPath += "/Fields_of_Study";
if (index == values.Length) return oidPath;
return values[index++] switch
{
1 => $"{oidPath}/Physics",
2 => $"{oidPath}/Chemistry",
3 => $"{oidPath}/Biology",
4 => $"{oidPath}/Culturology",
5 => $"{oidPath}/Psychology",
_ => $"{oidPath}/{values[index - 1]}",
};
#endregion
// modalities, sensory
#region 2.42.1.3.*
oid_2_42_1_3:
oidPath += "/Modalities";
if (index == values.Length) return oidPath;
return values[index++] switch
{
1 => $"{oidPath}/Tango",
2 => $"{oidPath}/Video",
3 => $"{oidPath}/Audio",
4 => $"{oidPath}/Chemo",
5 => $"{oidPath}/Radio",
6 => $"{oidPath}/Calor",
7 => $"{oidPath}/Electro",
_ => $"{oidPath}/{values[index - 1]}",
};
#endregion
#endregion
// human-physiology
#region 2.42.2.*
oid_2_42_2:
oidPath += "/Human_Physiology";
if (index == values.Length) return oidPath;
switch (values[index++])
{
case 0: goto oid_2_42_2_0;
case 1: goto oid_2_42_2_1;
case 2: return $"{oidPath}/Symbol_Combinations";
default: return $"{oidPath}/{values[index - 1]}";
}
// modules
#region 2.42.2.0.*
oid_2_42_2_0:
oidPath += "/Modules";
if (index == values.Length) return oidPath;
switch (values[index++])
{
case 0: goto oid_2_42_2_0_0;
default: return $"{oidPath}/{values[index - 1]}";
}
// main
#region 2.42.2.0.0.*
oid_2_42_2_0_0:
oidPath += "/Main_Module";
if (index == values.Length) return oidPath;
return values[index++] switch
{
0 => $"{oidPath}/First_Version",
_ => $"{oidPath}/{values[index - 1]}",
};
#endregion
#endregion
// symbols
#region 2.42.2.1.*
oid_2_42_2_1:
oidPath += "/Symbols";
if (index == values.Length) return oidPath;
return values[index++] switch
{
1 => $"{oidPath}/Tango_in",
2 => $"{oidPath}/Video_in",
3 => $"{oidPath}/Audio_in",
4 => $"{oidPath}/Chemo_in",
5 => $"{oidPath}/Radio_in",
6 => $"{oidPath}/Calor_in",
7 => $"{oidPath}/Tango_out",
8 => $"{oidPath}/Video_out",
9 => $"{oidPath}/Audio_out",
10 => $"{oidPath}/Chemo_out",
11 => $"{oidPath}/Radio_out",
12 => $"{oidPath}/Calor_out",
13 => $"{oidPath}/Safe",
14 => $"{oidPath}/Threshold",
_ => $"{oidPath}/{values[index - 1]}",
};
#endregion
#endregion
// obj-cat, telehealth, e-health-protocol, th
#region 2.42.3.*
oid_2_42_3:
oidPath += "/E_Health_Protocol";
if (index == values.Length) return oidPath;
switch (values[index++])
{
case 0: goto oid_2_42_3_0;
case 1: return $"{oidPath}/[Patient schemes]";
case 2: return $"{oidPath}/[Medical staff schemes]";
case 3: return $"{oidPath}/[Observer schemes]";
case 4: return $"{oidPath}/[Pharmaceutical schemes]";
case 5: return $"{oidPath}/[Laboratory schemes]";
case 6: return $"{oidPath}/[Drug manufacturer schemes]";
case 7: return $"{oidPath}/[Medical device schemes]";
case 8: return $"{oidPath}/[Medical software schemes]";
case 9: return $"{oidPath}/[Medical insurance schemes]";
case 10: return $"{oidPath}/[Medical record schemes]";
default: return $"{oidPath}/{values[index - 1]}";
}
// obj-cat, telehealth, e-health-protocol, th
#region 2.42.3.0.*
oid_2_42_3_0:
oidPath += "/Modules";
if (index == values.Length) return oidPath;
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 $"{oidPath}/{values[index - 1]}";
}
// identification
#region 2.42.3.0.0.*
oid_2_42_3_0_0:
oidPath += "/Identification";
if (index == values.Length) return oidPath;
return values[index++] switch
{
1 => $"{oidPath}/Version1",
_ => $"{oidPath}/{values[index - 1]}",
};
#endregion
// set-up
#region 2.42.3.0.1.*
oid_2_42_3_0_1:
oidPath += "/Setup";
if (index == values.Length) return oidPath;
return values[index++] switch
{
1 => $"{oidPath}/Version1",
_ => $"{oidPath}/{values[index - 1]}",
};
#endregion
// send-and-ack
#region 2.42.3.0.2.*
oid_2_42_3_0_2:
oidPath += "/Send-and-ack";
if (index == values.Length) return oidPath;
return values[index++] switch
{
1 => $"{oidPath}/Version1",
_ => $"{oidPath}/{values[index - 1]}",
};
#endregion
// command-response
#region 2.42.3.0.3.*
oid_2_42_3_0_3:
oidPath += "/Command-response";
if (index == values.Length) return oidPath;
return values[index++] switch
{
1 => $"{oidPath}/Version1",
_ => $"{oidPath}/{values[index - 1]}",
};
#endregion
// quantity-and-units
#region 2.42.3.0.4.*
oid_2_42_3_0_4:
oidPath += "/Quantities_And_Units";
if (index == values.Length) return oidPath;
return values[index++] switch
{
1 => $"{oidPath}/Version1",
_ => $"{oidPath}/{values[index - 1]}",
};
#endregion
// examples
#region 2.42.3.0.5.*
oid_2_42_3_0_5:
oidPath += "/Examples";
if (index == values.Length) return oidPath;
return values[index++] switch
{
0 => $"{oidPath}/Command_Response",
1 => $"{oidPath}/Data_Message",
_ => $"{oidPath}/{values[index - 1]}",
};
#endregion
#endregion
#endregion
#endregion
// cybersecurity
#region 2.48.*
oid_2_48:
oidPath += "/Cybersecurity";
if (index == values.Length) return oidPath;
return values[index++] switch
{
1 => $"{oidPath}/Country",
2 => $"{oidPath}/International-Org",
_ => $"{oidPath}/{values[index - 1]}",
};
#endregion
// alerting
#region 2.49.*
oid_2_49:
oidPath += "/Alerting";
if (index == values.Length) return oidPath;
return values[index++] switch
{
0 => $"{oidPath}/WMO",
_ => $"{oidPath}/{values[index - 1]}",
};
#endregion
#endregion
}
}
}

View File

@@ -1,3 +1,5 @@
using System;
namespace SabreTools.ASN1
{
/// <summary>
@@ -16,7 +18,8 @@ namespace SabreTools.ASN1
if (values == null || values.Length == 0)
return null;
return string.Join(".", values);
var stringValues = Array.ConvertAll(values, v => v.ToString());
return string.Join(".", [.. stringValues]);
}
}
}

View File

@@ -0,0 +1,36 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Assembly Properties -->
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Version>1.4.2</Version>
<!-- Package Properties -->
<Authors>Matt Nadareski</Authors>
<Description>Serialization and deserialization helpers for various types</Description>
<Copyright>Copyright (c) Matt Nadareski 2022-2024</Copyright>
<PackageProjectUrl>https://github.com/SabreTools/</PackageProjectUrl>
<PackageReadmeFile>README.md</PackageReadmeFile>
<RepositoryUrl>https://github.com/SabreTools/SabreTools.ASN1</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageTags>asn asn1 dot oid</PackageTags>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
</PropertyGroup>
<ItemGroup>
<None Include="../README.md" Pack="true" PackagePath="" />
</ItemGroup>
<!-- Support for old .NET versions -->
<ItemGroup Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`))">
<PackageReference Include="NetLegacySupport.Numerics" Version="1.0.1" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SabreTools.IO" Version="1.5.1" />
</ItemGroup>
</Project>

View File

@@ -1,9 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using SabreTools.IO;
using SabreTools.IO.Extensions;
namespace SabreTools.ASN1
{
@@ -35,32 +34,36 @@ namespace SabreTools.ASN1
public TypeLengthValue(byte[] data, ref int index)
{
// Get the type and modifiers
this.Type = (ASN1Type)data[index++];
Type = (ASN1Type)data[index++];
// If we have an end indicator, we just return
if (this.Type == ASN1Type.V_ASN1_EOC)
if (Type == ASN1Type.V_ASN1_EOC)
return;
// Get the length of the value
this.Length = ReadLength(data, ref index);
Length = ReadLength(data, ref index);
// Read the value
if (this.Type.HasFlag(ASN1Type.V_ASN1_CONSTRUCTED))
#if NET20 || NET35
if ((Type & ASN1Type.V_ASN1_CONSTRUCTED) != 0)
#else
if (Type.HasFlag(ASN1Type.V_ASN1_CONSTRUCTED))
#endif
{
var valueList = new List<TypeLengthValue>();
int currentIndex = index;
while (index < currentIndex + (int)this.Length)
while (index < currentIndex + (int)Length)
{
valueList.Add(new TypeLengthValue(data, ref index));
}
this.Value = valueList.ToArray();
Value = valueList.ToArray();
}
else
{
// TODO: Get more granular based on type
this.Value = data.ReadBytes(ref index, (int)this.Length);
Value = data.ReadBytes(ref index, (int)Length);
}
}
@@ -72,30 +75,33 @@ namespace SabreTools.ASN1
public string Format(int paddingLevel = 0)
{
// Create the left-padding string
string padding = new string(' ', paddingLevel);
string padding = new(' ', paddingLevel);
// If we have an invalid item
if (this.Type == 0)
if (Type == 0)
return $"{padding}UNKNOWN TYPE";
// Create the string builder
StringBuilder formatBuilder = new StringBuilder();
var formatBuilder = new StringBuilder();
// Append the type
formatBuilder.Append($"{padding}Type: {this.Type}");
if (this.Type == ASN1Type.V_ASN1_EOC)
formatBuilder.Append($"{padding}Type: {Type}");
if (Type == ASN1Type.V_ASN1_EOC)
return formatBuilder.ToString();
// Append the length
formatBuilder.Append($", Length: {this.Length}");
if (this.Length == 0)
formatBuilder.Append($", Length: {Length}");
if (Length == 0)
return formatBuilder.ToString();
// If we have a constructed type
if (this.Type.HasFlag(ASN1Type.V_ASN1_CONSTRUCTED))
#if NET20 || NET35
if ((Type & ASN1Type.V_ASN1_CONSTRUCTED) != 0)
#else
if (Type.HasFlag(ASN1Type.V_ASN1_CONSTRUCTED))
#endif
{
var valueAsObjectArray = this.Value as TypeLengthValue[];
if (valueAsObjectArray == null)
if (Value is not TypeLengthValue[] valueAsObjectArray)
{
formatBuilder.Append(", Value: [INVALID DATA TYPE]");
return formatBuilder.ToString();
@@ -113,29 +119,28 @@ namespace SabreTools.ASN1
}
// Get the value as a byte array
byte[]? valueAsByteArray = this.Value as byte[];
if (valueAsByteArray == null)
if (Value is not byte[] valueAsByteArray)
{
formatBuilder.Append(", Value: [INVALID DATA TYPE]");
return formatBuilder.ToString();
}
// If we have a primitive type
switch (this.Type)
switch (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)
if (Length > 1 || valueAsByteArray.Length > 1)
formatBuilder.Append($" [Expected length of 1]");
bool booleanValue = valueAsByteArray[0] == 0x00 ? false : true;
bool booleanValue = valueAsByteArray[0] != 0x00;
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);
var integerValue = new BigInteger(valueAsByteArray);
formatBuilder.Append($", Value: {integerValue}");
break;
@@ -143,7 +148,10 @@ namespace SabreTools.ASN1
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('-', ' ')}");
if (unusedBits == 0)
formatBuilder.Append($", Value with {unusedBits} unused bits");
else
formatBuilder.Append($", Value with {unusedBits} unused bits: {BitConverter.ToString(valueAsByteArray, 1).Replace('-', ' ')}");
break;
/// <see href="https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-octet-string"/>
@@ -155,7 +163,7 @@ namespace SabreTools.ASN1
/// <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);
ulong[] objectNodes = ObjectIdentifier.ParseDERIntoArray(valueAsByteArray, Length);
// Append the dot and modified OID-IRI notations
string? dotNotationString = ObjectIdentifier.ParseOIDToDotNotation(objectNodes);
@@ -197,11 +205,7 @@ namespace SabreTools.ASN1
break;
default:
#if NET40 || NET452
formatBuilder.Append($", Value (Unknown Format): {BitConverter.ToString(this.Value as byte[] ?? new byte[0]).Replace('-', ' ')}");
#else
formatBuilder.Append($", Value (Unknown Format): {BitConverter.ToString(this.Value as byte[] ?? Array.Empty<byte>()).Replace('-', ' ')}");
#endif
formatBuilder.Append($", Value (Unknown Format): {BitConverter.ToString(Value as byte[] ?? []).Replace('-', ' ')}");
break;
}
@@ -230,9 +234,7 @@ namespace SabreTools.ASN1
// Otherwise, use the value as the number of remaining bytes to read
int bytesToRead = length & ~0x80;
byte[]? bytesRead = data.ReadBytes(ref index, bytesToRead);
if (bytesRead == null)
throw new InvalidOperationException();
byte[]? bytesRead = data.ReadBytes(ref index, bytesToRead) ?? throw new InvalidOperationException();
// TODO: Write extensions to read big-endian

36
publish-nix.sh Executable file
View File

@@ -0,0 +1,36 @@
#! /bin/bash
# This batch file assumes the following:
# - .NET 9.0 (or newer) SDK is installed and in PATH
#
# If any of these are not satisfied, the operation may fail
# in an unpredictable way and result in an incomplete output.
# Optional parameters
NO_BUILD=false
while getopts "b" OPTION
do
case $OPTION in
b)
NO_BUILD=true
;;
*)
echo "Invalid option provided"
exit 1
;;
esac
done
# Set the current directory as a variable
BUILD_FOLDER=$PWD
# Only build if requested
if [ $NO_BUILD = false ]
then
# Restore Nuget packages for all builds
echo "Restoring Nuget packages"
dotnet restore
# Create Nuget Package
dotnet pack SabreTools.ASN1/SabreTools.ASN1.csproj --output $BUILD_FOLDER
fi

26
publish-win.ps1 Normal file
View File

@@ -0,0 +1,26 @@
# This batch file assumes the following:
# - .NET 9.0 (or newer) SDK is installed and in PATH
#
# If any of these are not satisfied, the operation may fail
# in an unpredictable way and result in an incomplete output.
# Optional parameters
param(
[Parameter(Mandatory = $false)]
[Alias("NoBuild")]
[switch]$NO_BUILD
)
# Set the current directory as a variable
$BUILD_FOLDER = $PSScriptRoot
# Only build if requested
if (!$NO_BUILD.IsPresent)
{
# Restore Nuget packages for all builds
Write-Host "Restoring Nuget packages"
dotnet restore
# Create Nuget Package
dotnet pack SabreTools.ASN1\SabreTools.ASN1.csproj --output $BUILD_FOLDER
}