mirror of
https://github.com/SabreTools/SabreTools.Serialization.git
synced 2026-02-04 05:36:12 +00:00
Simplify ASN.1 integration
This commit is contained in:
@@ -1,62 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using SabreTools.Serialization.ASN1;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.Serialization.Test.ASN1
|
||||
{
|
||||
public class AbstractSyntaxNotationOneTests
|
||||
{
|
||||
[Fact]
|
||||
public void Parse_EmptyArray_Throws()
|
||||
{
|
||||
byte[] data = [];
|
||||
Assert.Throws<InvalidDataException>(() => AbstractSyntaxNotationOne.Parse(data, 0));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_ValidArrayNegativeIndex_Throws()
|
||||
{
|
||||
byte[] data = [0x00];
|
||||
Assert.Throws<IndexOutOfRangeException>(() => AbstractSyntaxNotationOne.Parse(data, -1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_ValidArrayOverIndex_Throws()
|
||||
{
|
||||
byte[] data = [0x00];
|
||||
Assert.Throws<IndexOutOfRangeException>(() => AbstractSyntaxNotationOne.Parse(data, 10));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_ValidMinimalArray()
|
||||
{
|
||||
byte[] data = [0x00];
|
||||
var tlvs = AbstractSyntaxNotationOne.Parse(data, 0);
|
||||
|
||||
var tlv = Assert.Single(tlvs);
|
||||
Assert.Equal(ASN1Type.V_ASN1_EOC, tlv.Type);
|
||||
Assert.Equal(default, tlv.Length);
|
||||
Assert.Null(tlv.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_EmptyStream_Throws()
|
||||
{
|
||||
Stream data = new MemoryStream([], 0, 0, false, false);
|
||||
Assert.Throws<InvalidDataException>(() => AbstractSyntaxNotationOne.Parse(data));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_ValidMinimalStream()
|
||||
{
|
||||
Stream data = new MemoryStream([0x00]);
|
||||
var tlvs = AbstractSyntaxNotationOne.Parse(data);
|
||||
|
||||
var tlv = Assert.Single(tlvs);
|
||||
Assert.Equal(ASN1Type.V_ASN1_EOC, tlv.Type);
|
||||
Assert.Equal(default, tlv.Length);
|
||||
Assert.Null(tlv.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,14 +6,14 @@ using Xunit;
|
||||
|
||||
namespace SabreTools.Serialization.Test.Deserializers
|
||||
{
|
||||
public class ASN1TypeLengthValueTests
|
||||
public class AbstractSyntaxNotationOneTests
|
||||
{
|
||||
[Fact]
|
||||
public void NullArray_Null()
|
||||
{
|
||||
byte[]? data = null;
|
||||
int offset = 0;
|
||||
var deserializer = new ASN1TypeLengthValue();
|
||||
var deserializer = new AbstractSyntaxNotationOne();
|
||||
|
||||
var actual = deserializer.Deserialize(data, offset);
|
||||
Assert.Null(actual);
|
||||
@@ -24,7 +24,7 @@ namespace SabreTools.Serialization.Test.Deserializers
|
||||
{
|
||||
byte[]? data = [];
|
||||
int offset = 0;
|
||||
var deserializer = new ASN1TypeLengthValue();
|
||||
var deserializer = new AbstractSyntaxNotationOne();
|
||||
|
||||
var actual = deserializer.Deserialize(data, offset);
|
||||
Assert.Null(actual);
|
||||
@@ -35,7 +35,7 @@ namespace SabreTools.Serialization.Test.Deserializers
|
||||
{
|
||||
byte[]? data = [.. Enumerable.Repeat<byte>(0xFF, 1024)];
|
||||
int offset = 0;
|
||||
var deserializer = new ASN1TypeLengthValue();
|
||||
var deserializer = new AbstractSyntaxNotationOne();
|
||||
|
||||
var actual = deserializer.Deserialize(data, offset);
|
||||
Assert.Null(actual);
|
||||
@@ -45,7 +45,7 @@ namespace SabreTools.Serialization.Test.Deserializers
|
||||
public void NullStream_Null()
|
||||
{
|
||||
Stream? data = null;
|
||||
var deserializer = new ASN1TypeLengthValue();
|
||||
var deserializer = new AbstractSyntaxNotationOne();
|
||||
|
||||
var actual = deserializer.Deserialize(data);
|
||||
Assert.Null(actual);
|
||||
@@ -55,7 +55,7 @@ namespace SabreTools.Serialization.Test.Deserializers
|
||||
public void EmptyStream_Null()
|
||||
{
|
||||
Stream? data = new MemoryStream([]);
|
||||
var deserializer = new ASN1TypeLengthValue();
|
||||
var deserializer = new AbstractSyntaxNotationOne();
|
||||
|
||||
var actual = deserializer.Deserialize(data);
|
||||
Assert.Null(actual);
|
||||
@@ -65,7 +65,7 @@ namespace SabreTools.Serialization.Test.Deserializers
|
||||
public void InvalidStream_Null()
|
||||
{
|
||||
Stream? data = new MemoryStream([.. Enumerable.Repeat<byte>(0xFF, 1024)]);
|
||||
var deserializer = new ASN1TypeLengthValue();
|
||||
var deserializer = new AbstractSyntaxNotationOne();
|
||||
|
||||
var actual = deserializer.Deserialize(data);
|
||||
Assert.Null(actual);
|
||||
@@ -75,28 +75,32 @@ namespace SabreTools.Serialization.Test.Deserializers
|
||||
public void ValidMinimalStream_NotNull()
|
||||
{
|
||||
Stream data = new MemoryStream([0x00]);
|
||||
var deserializer = new ASN1TypeLengthValue();
|
||||
var deserializer = new AbstractSyntaxNotationOne();
|
||||
|
||||
var actual = deserializer.Deserialize(data);
|
||||
Assert.NotNull(actual);
|
||||
Assert.Equal(ASN1Type.V_ASN1_EOC, actual.Type);
|
||||
Assert.Equal(default, actual.Length);
|
||||
Assert.Null(actual.Value);
|
||||
|
||||
var actualSingle = Assert.Single(actual);
|
||||
Assert.Equal(ASN1Type.V_ASN1_EOC, actualSingle.Type);
|
||||
Assert.Equal(default, actualSingle.Length);
|
||||
Assert.Null(actualSingle.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ValidBoolean_NotNull()
|
||||
{
|
||||
Stream data = new MemoryStream([0x01, 0x01, 0x01]);
|
||||
var deserializer = new ASN1TypeLengthValue();
|
||||
var deserializer = new AbstractSyntaxNotationOne();
|
||||
|
||||
var actual = deserializer.Deserialize(data);
|
||||
Assert.NotNull(actual);
|
||||
Assert.Equal(ASN1Type.V_ASN1_BOOLEAN, actual.Type);
|
||||
Assert.Equal(1UL, actual.Length);
|
||||
Assert.NotNull(actual.Value);
|
||||
|
||||
byte[]? valueAsArray = actual.Value as byte[];
|
||||
var actualSingle = Assert.Single(actual);
|
||||
Assert.Equal(ASN1Type.V_ASN1_BOOLEAN, actualSingle.Type);
|
||||
Assert.Equal(1UL, actualSingle.Length);
|
||||
Assert.NotNull(actualSingle.Value);
|
||||
|
||||
byte[]? valueAsArray = actualSingle.Value as byte[];
|
||||
Assert.NotNull(valueAsArray);
|
||||
byte actualValue = Assert.Single(valueAsArray);
|
||||
Assert.Equal(0x01, actualValue);
|
||||
@@ -114,15 +118,17 @@ namespace SabreTools.Serialization.Test.Deserializers
|
||||
public void ComplexValue_NotNull(byte[] arr)
|
||||
{
|
||||
Stream data = new MemoryStream(arr);
|
||||
var deserializer = new ASN1TypeLengthValue();
|
||||
var deserializer = new AbstractSyntaxNotationOne();
|
||||
|
||||
var actual = deserializer.Deserialize(data);
|
||||
Assert.NotNull(actual);
|
||||
Assert.Equal(ASN1Type.V_ASN1_CONSTRUCTED | ASN1Type.V_ASN1_OBJECT, actual.Type);
|
||||
Assert.Equal(3UL, actual.Length);
|
||||
Assert.NotNull(actual.Value);
|
||||
|
||||
TypeLengthValue[]? valueAsArray = actual.Value as TypeLengthValue[];
|
||||
var actualSingle = Assert.Single(actual);
|
||||
Assert.Equal(ASN1Type.V_ASN1_CONSTRUCTED | ASN1Type.V_ASN1_OBJECT, actualSingle.Type);
|
||||
Assert.Equal(3UL, actualSingle.Length);
|
||||
Assert.NotNull(actualSingle.Value);
|
||||
|
||||
TypeLengthValue[]? valueAsArray = actualSingle.Value as TypeLengthValue[];
|
||||
Assert.NotNull(valueAsArray);
|
||||
TypeLengthValue actualSub = Assert.Single(valueAsArray);
|
||||
|
||||
@@ -134,13 +140,14 @@ namespace SabreTools.Serialization.Test.Deserializers
|
||||
[Theory]
|
||||
[InlineData(new byte[] { 0x26, 0x80 })]
|
||||
[InlineData(new byte[] { 0x26, 0x89 })]
|
||||
public void ComplexValueInvalidLength_Null(byte[] arr)
|
||||
public void ComplexValueInvalidLength_Empty(byte[] arr)
|
||||
{
|
||||
Stream data = new MemoryStream(arr);
|
||||
var deserializer = new ASN1TypeLengthValue();
|
||||
var deserializer = new AbstractSyntaxNotationOne();
|
||||
|
||||
var actual = deserializer.Deserialize(data);
|
||||
Assert.Null(actual);
|
||||
Assert.NotNull(actual);
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SabreTools.Serialization.Deserializers;
|
||||
|
||||
namespace SabreTools.Serialization.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>
|
||||
public static List<TypeLengthValue> Parse(byte[] data, int pointer)
|
||||
{
|
||||
// If the data is invalid
|
||||
if (data.Length == 0)
|
||||
throw new InvalidDataException(nameof(data));
|
||||
if (pointer < 0 || pointer >= data.Length)
|
||||
throw new IndexOutOfRangeException(nameof(pointer));
|
||||
|
||||
using var stream = new MemoryStream(data);
|
||||
stream.Seek(pointer, SeekOrigin.Begin);
|
||||
return Parse(stream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a stream into a DER-encoded ASN.1 structure
|
||||
/// </summary>
|
||||
/// <param name="data">Stream representing the data</param>
|
||||
public static List<TypeLengthValue> Parse(Stream data)
|
||||
{
|
||||
// If the data is invalid
|
||||
if (data.Length == 0 || !data.CanRead)
|
||||
throw new InvalidDataException(nameof(data));
|
||||
if (data.Position < 0 || data.Position >= data.Length)
|
||||
throw new IndexOutOfRangeException(nameof(data));
|
||||
|
||||
// Create the deserializer
|
||||
var deserializer = new ASN1TypeLengthValue();
|
||||
|
||||
// Loop through the data and return all top-level values
|
||||
var topLevelValues = new List<TypeLengthValue>();
|
||||
while (data.Position < data.Length)
|
||||
{
|
||||
var topLevelValue = deserializer.Deserialize(data);
|
||||
if (topLevelValue == null)
|
||||
break;
|
||||
|
||||
topLevelValues.Add(topLevelValue);
|
||||
}
|
||||
|
||||
return topLevelValues;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,10 @@ using SabreTools.IO.Extensions;
|
||||
|
||||
namespace SabreTools.Serialization.Deserializers
|
||||
{
|
||||
public class ASN1TypeLengthValue : BaseBinaryDeserializer<ASN1.TypeLengthValue>
|
||||
public class AbstractSyntaxNotationOne : BaseBinaryDeserializer<ASN1.TypeLengthValue[]>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override ASN1.TypeLengthValue? Deserialize(Stream? data)
|
||||
public override ASN1.TypeLengthValue[]? Deserialize(Stream? data)
|
||||
{
|
||||
// If the data is invalid
|
||||
if (data == null || !data.CanRead)
|
||||
@@ -18,12 +18,19 @@ namespace SabreTools.Serialization.Deserializers
|
||||
// Cache the current offset
|
||||
long initialOffset = data.Position;
|
||||
|
||||
var tlv = ParseTypeLengthValue(data);
|
||||
if (tlv == null)
|
||||
return null;
|
||||
// Loop through the data and return all top-level values
|
||||
var topLevelValues = new List<ASN1.TypeLengthValue>();
|
||||
while (data.Position < data.Length)
|
||||
{
|
||||
var topLevelValue = ParseTypeLengthValue(data);
|
||||
if (topLevelValue == null)
|
||||
break;
|
||||
|
||||
// Return the Type/Length/Value
|
||||
return tlv;
|
||||
topLevelValues.Add(topLevelValue);
|
||||
}
|
||||
|
||||
// Return the top-level values
|
||||
return [.. topLevelValues];
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -451,6 +451,9 @@ namespace SabreTools.Serialization.Printers
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the deserializer
|
||||
var deserializer = new Deserializers.AbstractSyntaxNotationOne();
|
||||
|
||||
for (int i = 0; i < entries.Length; i++)
|
||||
{
|
||||
var entry = entries[i];
|
||||
@@ -470,7 +473,7 @@ namespace SabreTools.Serialization.Printers
|
||||
}
|
||||
else
|
||||
{
|
||||
var topLevelValues = AbstractSyntaxNotationOne.Parse(entry.Certificate, 0);
|
||||
var topLevelValues = deserializer.Deserialize(entry.Certificate, 0);
|
||||
if (topLevelValues == null)
|
||||
{
|
||||
builder.AppendLine(" INVALID DATA FOUND");
|
||||
|
||||
Reference in New Issue
Block a user