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

XFESystem

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

公开
关注 0 Fork 0 Star 0
UTF-8
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.X509;
using XFESystem.Tls;

namespace XFESystem.NativeTls.Tests;

public sealed class TlsTrustStoreImportTests
{
    private static X509Certificate ReplacePublicKey(X509Certificate certificate, SubjectPublicKeyInfo info)
    {
        var original = (Asn1Sequence)certificate.CertificateStructure.TbsCertificate.ToAsn1Object();
        var fields = original.Cast<Asn1Encodable>().ToArray();
        // This fixture is v3, so its explicit version occupies index zero.
        Assert.IsAssignableFrom<Asn1TaggedObject>(fields[0]); fields[6] = info;
        var tbs = TbsCertificateStructure.GetInstance(new DerSequence(fields));
        var structure = new X509CertificateStructure(tbs, certificate.CertificateStructure.SignatureAlgorithm,
            certificate.CertificateStructure.Signature);
        return new X509Certificate(structure);
    }
    private static X509Certificate RsaRoot(X509Certificate original, BigInteger modulus, BigInteger exponent,
        Asn1Encodable? parameters = null) => ReplacePublicKey(original,
            new SubjectPublicKeyInfo(new AlgorithmIdentifier(PkcsObjectIdentifiers.RsaEncryption, parameters ?? DerNull.Instance),
                new DerSequence(new DerInteger(modulus), new DerInteger(exponent))));

    [Fact]
    public void RootImportDoesNotRunRsaKeyFactoryForEveryAnchor()
    {
        using var fixture = new CertificateFixtures();
        // Import must remain a cheap structural check, even for a large bundle.
        var root = new ObservedCertificate(RsaRoot(fixture.RootBc, BigInteger.One.ShiftLeft(2203).Subtract(BigInteger.One), BigInteger.ValueOf(65537)));
        for (int count = 0; count < 121; count++) _ = new TlsCertificateValidator([root]);
        Assert.Equal(0, root.KeyFactoryCalls);
    }
    [Theory]
    [InlineData(1024, 65537)]
    [InlineData(16385, 65537)]
    [InlineData(2048, 1)]
    [InlineData(2048, 2)]
    [InlineData(2048, 0)]
    [InlineData(2048, -3)]
    public void RootImportRejectsWeakStrengthAndInvalidExponent(int bits, long exponent)
    {
        using var fixture = new CertificateFixtures();
        var root = RsaRoot(fixture.RootBc, BigInteger.One.ShiftLeft(bits - 1).Add(BigInteger.One), BigInteger.ValueOf(exponent));
        Assert.Throws<InvalidOperationException>(() => new TlsCertificateValidator([root]));
    }
    [Fact]
    public void RootImportRejectsEvenModulusAndInvalidAlgorithmParameters()
    {
        using var fixture = new CertificateFixtures();
        var odd = BigInteger.One.ShiftLeft(2047).Add(BigInteger.One);
        var even = RsaRoot(fixture.RootBc, odd.Add(BigInteger.One), BigInteger.ValueOf(65537));
        var invalidParameters = RsaRoot(fixture.RootBc, odd, BigInteger.ValueOf(65537), DerInteger.ValueOf(7));
        Assert.Throws<InvalidOperationException>(() => new TlsCertificateValidator([even]));
        Assert.Throws<InvalidOperationException>(() => new TlsCertificateValidator([invalidParameters]));
    }
    [Fact]
    public void NegativeAsn1ModulusCannotBeNormalizedIntoAnAcceptedPositiveKey()
    {
        using var fixture = new CertificateFixtures();
        var negative = BigInteger.One.ShiftLeft(2203).Subtract(BigInteger.One).Negate();
        var root = RsaRoot(fixture.RootBc, negative, BigInteger.ValueOf(65537));
        Assert.Throws<InvalidOperationException>(() => new TlsCertificateValidator([root]));
    }
    [Fact]
    public void UnsupportedRootKeyAlgorithmIsNotAdmitted()
    {
        using var fixture = new CertificateFixtures();
        var root = ReplacePublicKey(fixture.RootBc, new SubjectPublicKeyInfo(
            new AlgorithmIdentifier(new DerObjectIdentifier("1.3.6.1.4.1.55555.77.1")), new DerBitString([1, 2, 3])));
        Assert.ThrowsAny<Exception>(() => new TlsCertificateValidator([root]));
    }
    [Fact]
    public void SelectedAnchorStillRunsFullRsaValidationAndRejectsPrimeModulus()
    {
        using var fixture = new CertificateFixtures(); using var leaf = fixture.Leaf();
        // 2^2203-1 is a known Mersenne prime, so it meets the structural bit
        // policy but cannot be an RSA modulus. The real BC factory must reject.
        var root = new ObservedCertificate(RsaRoot(fixture.RootBc, BigInteger.One.ShiftLeft(2203).Subtract(BigInteger.One), BigInteger.ValueOf(65537)));
        var validator = new TlsCertificateValidator([root]); Assert.Equal(0, root.KeyFactoryCalls);
        Assert.ThrowsAny<Exception>(() => validator.Validate("test.xfe.invalid", [leaf.RawData], fixture.Now));
        Assert.True(root.KeyFactoryCalls > 0);
        Assert.Contains("not composite", root.KeyFactoryError?.Message ?? "", StringComparison.OrdinalIgnoreCase);
    }
    private sealed class ObservedCertificate(X509Certificate source) : X509Certificate(source.CertificateStructure)
    {
        public int KeyFactoryCalls;
        public Exception? KeyFactoryError;
        public override AsymmetricKeyParameter GetPublicKey()
        {
            KeyFactoryCalls++;
            try { return base.GetPublicKey(); }
            catch (Exception error) { KeyFactoryError = error; throw; }
        }
    }
}