XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESystem

【Rust】XFE系统,基于Rust和汇编

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Security.Cryptography;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto.Operators;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
using XFESystem.Tls;

namespace XFESystem.NativeTls.Tests;

public sealed class TlsPlatformIntegrationTests
{
    [Fact]
    public void PlatformContextUsesOnlyTheSuppliedUtcAndRandomProviders()
    {
        int reads = 0, fills = 0;
        DateTime now = new(2031, 2, 3, 4, 5, 6, DateTimeKind.Utc);
        var platform = new TlsPlatformSecurityContext(() => { reads++; return now; }, destination => { fills++; destination.Fill(0xA7); });
        Assert.Equal(now, platform.UtcNow);
        Span<byte> bytes = stackalloc byte[17]; platform.FillRandom(bytes);
        Assert.True(bytes.SequenceEqual(Enumerable.Repeat((byte)0xA7, 17).ToArray()));
        Assert.Equal(1, reads); Assert.Equal(1, fills);
    }

    [Fact]
    public void FailedPlatformRandomClearsPartialOutputAndPropagatesFailure()
    {
        var platform = new TlsPlatformSecurityContext(() => DateTime.UtcNow, destination =>
        {
            destination.Fill(0xA7); throw new InvalidOperationException("Kernel entropy source failed its health check.");
        });
        byte[] bytes = Enumerable.Repeat((byte)0x55, 32).ToArray();
        Assert.Throws<InvalidOperationException>(() => platform.FillRandom(bytes));
        Assert.All(bytes, value => Assert.Equal(0, value));
    }

    [Theory]
    [InlineData(false)]
    [InlineData(true)]
    public void MissingOrNonUtcPlatformTimeDoesNotFallBackToHost(bool unspecified)
    {
        var platform = new TlsPlatformSecurityContext(() => unspecified ? DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Unspecified) : DateTime.UnixEpoch,
            destination => throw new InvalidOperationException("No source"));
        Assert.Throws<InvalidOperationException>(() => platform.UtcNow);
    }

    [Theory]
    [InlineData(".xfe.invalid", null, true)]
    [InlineData(".other.invalid", null, false)]
    [InlineData(null, ".xfe.invalid", false)]
    [InlineData(".xfe.invalid", ".other.invalid", true)]
    public void ExplicitAnchorNameConstraintsReallyRestrictSelectedPath(string? permitted, string? excluded, bool accepted)
    {
        using var fixture = new CertificateFixtures(permitted, excluded); using var leaf = fixture.Leaf();
        var validator = new TlsCertificateValidator([fixture.RootBc]);
        Action validate = () => validator.Validate("test.xfe.invalid", [leaf.RawData], fixture.Now);
        if (accepted) validate(); else Assert.ThrowsAny<Exception>(validate);
    }

    [Fact]
    public void ExplicitRootCannotRestrictChainToClientAuthentication()
    {
        using var fixture = new CertificateFixtures(serverAuthRoot: false); using var leaf = fixture.Leaf();
        Assert.Throws<InvalidOperationException>(() => new TlsCertificateValidator([fixture.RootBc]).Validate("test.xfe.invalid", [leaf.RawData], fixture.Now));
    }

    [Fact]
    public void ExplicitRootMustPermitCertificateSigning()
    {
        using var fixture = new CertificateFixtures(certificateSigning: false);
        Assert.Throws<ArgumentException>(() => new TlsCertificateValidator([fixture.RootBc]));
    }

    [Theory]
    [InlineData("SHA1WITHECDSA", false)]
    [InlineData("SHA256WITHECDSA", true)]
    public void ActualSignedPathCannotUseWeakCertificateDigest(string algorithm, bool accepted)
    {
        using var fixture = new CertificateFixtures();
        using var leafKey = ECDsa.Create(ECCurve.NamedCurves.nistP256);
        var generator = new X509V3CertificateGenerator();
        generator.SetSerialNumber(Org.BouncyCastle.Math.BigInteger.ValueOf(491));
        generator.SetIssuerDN(fixture.RootBc.SubjectDN); generator.SetSubjectDN(new X509Name("CN=test.xfe.invalid"));
        generator.SetNotBefore(fixture.Now.AddHours(-1)); generator.SetNotAfter(fixture.Now.AddHours(1));
        generator.SetPublicKey(PublicKeyFactory.CreateKey(leafKey.ExportSubjectPublicKeyInfo()));
        generator.AddExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(false));
        generator.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.DigitalSignature));
        generator.AddExtension(X509Extensions.ExtendedKeyUsage, false, new ExtendedKeyUsage(KeyPurposeID.id_kp_serverAuth));
        generator.AddExtension(X509Extensions.SubjectAlternativeName, false, new GeneralNames(new GeneralName(GeneralName.DnsName, "test.xfe.invalid")));
        var leaf = generator.Generate(new Asn1SignatureFactory(algorithm, PrivateKeyFactory.CreateKey(fixture.RootKey.ExportPkcs8PrivateKey())));
        Action validate = () => new TlsCertificateValidator([fixture.RootBc]).Validate("test.xfe.invalid", [leaf.GetEncoded()], fixture.Now);
        if (accepted) validate(); else Assert.Throws<InvalidOperationException>(validate);
    }
}