Files
git.stella-ops.org/src/Attestor/StellaOps.Signer/StellaOps.Signer.Tests/Signing/Sm2SigningTests.cs

122 lines
4.1 KiB
C#

using System;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using StellaOps.Cryptography;
using StellaOps.Cryptography.Plugin.SmSoft;
using StellaOps.Signer.Core;
using StellaOps.Signer.Infrastructure.Signing;
using StellaOps.Signer.Tests.Fixtures;
using Xunit;
namespace StellaOps.Signer.Tests.Signing;
public class Sm2SigningTests : IDisposable
{
private readonly string? _gate;
public Sm2SigningTests()
{
_gate = Environment.GetEnvironmentVariable("SM_SOFT_ALLOWED");
Environment.SetEnvironmentVariable("SM_SOFT_ALLOWED", "1");
}
[Fact]
public async Task Sign_Sm2_Succeeds_WhenGateOn()
{
var registry = TestCryptoFactory.CreateSm2Registry();
var keyResolver = new StubKeyResolver("sm2-key", SignatureAlgorithms.Sm2, "cn.sm.soft");
var options = Options.Create(new DsseSignerOptions
{
KeylessAlgorithm = SignatureAlgorithms.Sm2,
KmsAlgorithm = SignatureAlgorithms.Sm2,
PreferredProvider = "cn.sm.soft"
});
var signer = new CryptoDsseSigner(
registry,
keyResolver,
options,
NullLogger<CryptoDsseSigner>.Instance);
var request = BuildRequest();
var entitlement = new ProofOfEntitlementResult("lic", "cust", "plan", 0, 0, 0, DateTimeOffset.UtcNow.AddHours(1));
var caller = BuildCaller();
var bundle = await signer.SignAsync(request, entitlement, caller, default);
Assert.Equal(SignatureAlgorithms.Sm2, bundle.Metadata.AlgorithmId);
Assert.Equal("cn.sm.soft", bundle.Metadata.ProviderName);
}
[Fact]
public async Task Sign_Sm2_Fails_WhenGateOff()
{
Environment.SetEnvironmentVariable("SM_SOFT_ALLOWED", null);
var registry = TestCryptoFactory.CreateSm2Registry();
var keyResolver = new StubKeyResolver("sm2-key", SignatureAlgorithms.Sm2, "cn.sm.soft");
var options = Options.Create(new DsseSignerOptions { KeylessAlgorithm = SignatureAlgorithms.Sm2 });
var signer = new CryptoDsseSigner(
registry,
keyResolver,
options,
NullLogger<CryptoDsseSigner>.Instance);
var request = BuildRequest();
var entitlement = new ProofOfEntitlementResult("lic", "cust", "plan", 0, 0, 0, DateTimeOffset.UtcNow.AddHours(1));
var caller = BuildCaller();
await Assert.ThrowsAsync<InvalidOperationException>(() => signer.SignAsync(request, entitlement, caller, default).AsTask());
}
private class StubKeyResolver : ISigningKeyResolver
{
private readonly string _keyId;
private readonly string _alg;
private readonly string _provider;
public StubKeyResolver(string keyId, string alg, string provider)
{
_keyId = keyId;
_alg = alg;
_provider = provider;
}
public ValueTask<SigningKeyResolution> ResolveKeyAsync(SigningMode mode, string tenant, CancellationToken cancellationToken)
{
var resolution = new SigningKeyResolution(_keyId, _provider, "https://sm.test", "sm2-subject");
return ValueTask.FromResult(resolution);
}
}
public void Dispose()
{
Environment.SetEnvironmentVariable("SM_SOFT_ALLOWED", _gate);
}
private static SigningRequest BuildRequest()
{
var subject = new SigningSubject("pkg", new Dictionary<string, string> { ["sha256"] = "00" });
return new SigningRequest(
new[] { subject },
"test-predicate",
JsonDocument.Parse("{}"),
"sha256:00",
new ProofOfEntitlement(SignerPoEFormat.Jwt, "stub"),
new SigningOptions(SigningMode.Keyless, null, "dsse"));
}
private static CallerContext BuildCaller() => new(
Subject: "subject-1",
Tenant: "tenant-1",
Scopes: Array.Empty<string>(),
Audiences: Array.Empty<string>(),
SenderBinding: string.Empty,
ClientCertificateThumbprint: string.Empty);
}