< Summary

Information
Class: AsiBackbone.Core.Signing.SignatureVerificationRequest
Assembly: AsiBackbone.Core
File(s): /home/runner/work/AsiBackbone/AsiBackbone/src/AsiBackbone.Core/Signing/SignatureVerificationRequest.cs
Line coverage
96%
Covered lines: 30
Uncovered lines: 1
Coverable lines: 31
Total lines: 114
Line coverage: 96.7%
Branch coverage
95%
Covered branches: 19
Total branches: 20
Branch coverage: 95%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
.ctor(...)100%11100%
get_HasMetadata()100%11100%
get_SignatureInput()100%22100%
set_SignatureInput(...)50%22100%
get_UsesLegacySignatureInput()100%210%
NormalizeOptional(...)100%22100%
NormalizeMetadata(...)100%1414100%

File(s)

/home/runner/work/AsiBackbone/AsiBackbone/src/AsiBackbone.Core/Signing/SignatureVerificationRequest.cs

#LineLine coverage
 1using System.Collections.ObjectModel;
 2
 3namespace AsiBackbone.Core.Signing;
 4
 5/// <summary>
 6/// Represents a provider-neutral request to verify signing metadata against a precomputed artifact hash.
 7/// </summary>
 8public sealed class SignatureVerificationRequest
 9{
 10    private readonly byte[]? signatureInput;
 11
 212    private static readonly IReadOnlyDictionary<string, string> EmptyMetadata =
 213        new ReadOnlyDictionary<string, string>(
 214            new Dictionary<string, string>(StringComparer.Ordinal));
 15
 16    /// <summary>
 17    /// Initializes a new instance of the <see cref="SignatureVerificationRequest" /> class.
 18    /// </summary>
 5119    public SignatureVerificationRequest(
 5120        string signingHash,
 5121        SigningMetadata signingMetadata,
 5122        string? purpose = null,
 5123        IReadOnlyDictionary<string, string>? metadata = null)
 24    {
 5125        ArgumentException.ThrowIfNullOrWhiteSpace(signingHash);
 5126        ArgumentNullException.ThrowIfNull(signingMetadata);
 27
 5128        SigningHash = signingHash.Trim();
 5129        SigningMetadata = signingMetadata;
 5130        Purpose = NormalizeOptional(purpose);
 5131        Metadata = NormalizeMetadata(metadata);
 5132    }
 33
 34    /// <summary>
 35    /// Gets the precomputed artifact hash expected to have been signed.
 36    /// </summary>
 37    public string SigningHash { get; }
 38
 39    /// <summary>
 40    /// Gets the provider-neutral signing metadata to verify.
 41    /// </summary>
 42    public SigningMetadata SigningMetadata { get; }
 43
 44    /// <summary>
 45    /// Gets the host-defined verification purpose, when supplied.
 46    /// </summary>
 47    public string? Purpose { get; }
 48
 49    /// <summary>
 50    /// Gets additional provider-neutral request metadata.
 51    /// </summary>
 52    public IReadOnlyDictionary<string, string> Metadata { get; }
 53
 54    /// <summary>
 55    /// Gets a value indicating whether metadata is present.
 56    /// </summary>
 357    public bool HasMetadata => Metadata.Count > 0;
 58
 59    /// <summary>
 60    /// Gets the exact bytes the verification provider must verify the signature against.
 61    /// </summary>
 62    /// <remarks>
 63    /// <see cref="GovernanceArtifactVerifier" /> sets this to the version 1 input rebuilt from the artifact and its sig
 64    /// metadata, or to the pre-6.0 input when the verification context explicitly allows it. Verification providers mus
 65    /// verify these bytes rather than <see cref="SigningHash" />; verifying the hash text instead leaves the signing po
 66    /// context unauthenticated. When no input was supplied, this returns the pre-6.0 input from
 67    /// <see cref="GovernanceSignatureInput.CreateLegacy" />. The supplied value is copied.
 68    /// </remarks>
 69    public ReadOnlyMemory<byte> SignatureInput
 70    {
 71#pragma warning disable ASIB902 // Retained internal fallback for pre-6.0 provider-request compatibility.
 1572        get => signatureInput ?? GovernanceSignatureInput.CreateLegacy(SigningHash);
 73#pragma warning restore ASIB902
 4374        init => signatureInput = value.IsEmpty ? null : [.. value.Span];
 75    }
 76
 77    /// <summary>
 78    /// Gets a value indicating whether no explicit signature input was supplied, so <see cref="SignatureInput" /> is th
 79    /// pre-6.0 hash-only input.
 80    /// </summary>
 081    public bool UsesLegacySignatureInput => signatureInput is null;
 82
 83    private static string? NormalizeOptional(string? value)
 84    {
 5185        return string.IsNullOrWhiteSpace(value)
 5186            ? null
 5187            : value.Trim();
 88    }
 89
 90    private static IReadOnlyDictionary<string, string> NormalizeMetadata(
 91        IReadOnlyDictionary<string, string>? metadata)
 92    {
 5193        if (metadata is null || metadata.Count == 0)
 94        {
 4995            return EmptyMetadata;
 96        }
 97
 298        Dictionary<string, string> normalizedMetadata = new(StringComparer.Ordinal);
 99
 12100        foreach (KeyValuePair<string, string> item in metadata)
 101        {
 4102            if (string.IsNullOrWhiteSpace(item.Key))
 103            {
 104                continue;
 105            }
 106
 2107            normalizedMetadata[item.Key.Trim()] = item.Value?.Trim() ?? string.Empty;
 108        }
 109
 2110        return normalizedMetadata.Count == 0
 2111            ? EmptyMetadata
 2112            : new ReadOnlyDictionary<string, string>(normalizedMetadata);
 113    }
 114}