解决MySql布尔型新旧版本兼容问题,采用枚举来表示布尔型的数据表。由正向工程赋值
大石头 authored at 2018-05-15 21:21:05
6.17 KiB
X
using System.Security.Cryptography;
using NewLife.Security;
using Xunit;

namespace XUnitTest.Security;

/// <summary>ASN.1编解码测试</summary>
public class Asn1Tests
{
    [Fact(DisplayName = "读取Integer类型")]
    public void ReadInteger()
    {
        // TLV: Tag=0x02(Integer), Length=0x01, Value=0x05
        var data = new Byte[] { 0x02, 0x01, 0x05 };
        var asn = Asn1.Read(data);

        Assert.NotNull(asn);
        Assert.Equal(Asn1Tags.Integer, asn.Tag);
        Assert.Equal(1, asn.Length);
        var val = asn.Value as Byte[];
        Assert.NotNull(val);
        Assert.Equal(0x05, val[0]);
    }

    [Fact(DisplayName = "读取Null类型")]
    public void ReadNull()
    {
        // TLV: Tag=0x05(Null), Length=0x00
        var data = new Byte[] { 0x05, 0x00 };
        var asn = Asn1.Read(data);

        Assert.NotNull(asn);
        Assert.Equal(Asn1Tags.Null, asn.Tag);
        Assert.Equal(0, asn.Length);
    }

    [Fact(DisplayName = "读取OctetString类型")]
    public void ReadOctetString()
    {
        // Tag=0x04(OctetString), Length=3, Value=0x01,0x02,0x03
        var data = new Byte[] { 0x04, 0x03, 0x01, 0x02, 0x03 };
        var asn = Asn1.Read(data);

        Assert.NotNull(asn);
        Assert.Equal(Asn1Tags.OctetString, asn.Tag);
        var val = asn.Value as Byte[];
        Assert.NotNull(val);
        Assert.Equal(3, val.Length);
        Assert.Equal(new Byte[] { 0x01, 0x02, 0x03 }, val);
    }

    [Fact(DisplayName = "读取Sequence类型")]
    public void ReadSequence()
    {
        // Sequence containing Integer(5) and Null
        // 30 05 02 01 05 05 00
        var data = new Byte[] { 0x30, 0x05, 0x02, 0x01, 0x05, 0x05, 0x00 };
        var asn = Asn1.Read(data);

        Assert.NotNull(asn);
        Assert.Equal(Asn1Tags.Sequence, asn.Tag);
        var children = asn.Value as Asn1[];
        Assert.NotNull(children);
        Assert.Equal(2, children.Length);
        Assert.Equal(Asn1Tags.Integer, children[0].Tag);
        Assert.Equal(Asn1Tags.Null, children[1].Tag);
    }

    [Fact(DisplayName = "读取ObjectIdentifier")]
    public void ReadOid()
    {
        // OID 1.2.840.113549.1.1.1 (RSA encryption)
        var data = new Byte[] { 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 };
        var asn = Asn1.Read(data);

        Assert.NotNull(asn);
        Assert.Equal(Asn1Tags.ObjectIdentifier, asn.Tag);
        var oid = asn.Value as Oid;
        Assert.NotNull(oid);
        Assert.Equal("1.2.840.113549.1.1.1", oid.Value);
    }

    [Fact(DisplayName = "GetOids从嵌套结构提取")]
    public void GetOidsFromNestedStructure()
    {
        // Sequence { OID(1.2.840.113549.1.1.1), Null }
        var data = new Byte[] { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
        var asn = Asn1.Read(data);
        Assert.NotNull(asn);

        var oids = asn.GetOids();
        Assert.NotNull(oids);
        Assert.True(oids.Length >= 1);
        Assert.Equal("1.2.840.113549.1.1.1", oids[0].Value);
    }

    [Fact(DisplayName = "读取长格式长度(0x83)")]
    public void ReadLongLength83()
    {
        // OctetString,0x83 三字节长格式 = 256 字节
        var value = new Byte[256];
        for (var i = 0; i < value.Length; i++) value[i] = (Byte)i;

        var data = new List<Byte> { 0x04, 0x83, 0x00, 0x01, 0x00 };
        data.AddRange(value);

        var asn = Asn1.Read(data.ToArray());

        Assert.NotNull(asn);
        Assert.Equal(Asn1Tags.OctetString, asn.Tag);
        Assert.Equal(256, asn.Length);
        var val = asn.Value as Byte[];
        Assert.NotNull(val);
        Assert.Equal(256, val.Length);
        Assert.Equal(0xFF, val[255]);
    }

    [Fact(DisplayName = "BER不定长(0x80)抛异常")]
    public void ReadIndefiniteLengthThrows()
    {
        // OctetString + 不定长标记 0x80。BER 才允许不定长,DER 禁止,此处应显式报错而非静默错解
        var data = new Byte[] { 0x04, 0x80 };

        Assert.Throws<NotSupportedException>(() => Asn1.Read(data));
    }

    [Fact(DisplayName = "GetByteArray返回值")]
    public void GetByteArray()
    {
        var data = new Byte[] { 0x04, 0x03, 0x01, 0x02, 0x03 };
        var asn = Asn1.Read(data);
        Assert.NotNull(asn);

        var bytes = asn.GetByteArray();
        Assert.NotNull(bytes);
        Assert.Equal(new Byte[] { 0x01, 0x02, 0x03 }, bytes);
    }

    [Fact(DisplayName = "GetByteArray去除前导零")]
    public void GetByteArrayTrimZero()
    {
        // 手动构造
        var asn = new Asn1 { Tag = Asn1Tags.Integer, Value = new Byte[] { 0x00, 0x01, 0x02 } };
        var bytes = asn.GetByteArray(true);

        Assert.NotNull(bytes);
        Assert.Equal(2, bytes.Length);
        Assert.Equal(new Byte[] { 0x01, 0x02 }, bytes);
    }

    [Fact(DisplayName = "BitString去除前导零")]
    public void ReadBitString()
    {
        // Tag=0x03(BitString), Length=3, unused_bits=0, data=0xAB,0xCD
        var data = new Byte[] { 0x03, 0x03, 0x00, 0xAB, 0xCD };
        var asn = Asn1.Read(data);

        Assert.NotNull(asn);
        Assert.Equal(Asn1Tags.BitString, asn.Tag);
        var val = asn.Value as Byte[];
        Assert.NotNull(val);
        // 去除前导0x00后应该是{ 0xAB, 0xCD }
        Assert.Equal(new Byte[] { 0xAB, 0xCD }, val);
    }

    [Fact(DisplayName = "ToString格式化输出")]
    public void ToStringFormatted()
    {
        var data = new Byte[] { 0x05, 0x00 };
        var asn = Asn1.Read(data);
        Assert.NotNull(asn);
        Assert.Equal("Null", asn.ToString());
    }

    [Fact(DisplayName = "读取Stream")]
    public void ReadFromStream()
    {
        var data = new Byte[] { 0x02, 0x01, 0x0A };
        using var ms = new MemoryStream(data);
        var asn = Asn1.Read(ms);

        Assert.NotNull(asn);
        Assert.Equal(Asn1Tags.Integer, asn.Tag);
    }

    [Fact(DisplayName = "GetByteArray空缓冲不越界")]
    public void GetByteArrayEmptyBuffer()
    {
        // 空数组时 trimZero 不应访问 buf[0] 导致越界
        var asn = new Asn1 { Tag = Asn1Tags.Integer, Value = Array.Empty<Byte>() };
        var bytes = asn.GetByteArray(true);

        Assert.NotNull(bytes);
        Assert.Empty(bytes);
    }
}