< Summary

Information
Class: AsiBackbone.Core.Signing.SigningMetadata
Assembly: AsiBackbone.Core
File(s): /home/runner/work/AsiBackbone/AsiBackbone/src/AsiBackbone.Core/Signing/SigningMetadata.cs
Line coverage
100%
Covered lines: 49
Uncovered lines: 0
Coverable lines: 49
Total lines: 175
Line coverage: 100%
Branch coverage
83%
Covered branches: 20
Total branches: 24
Branch coverage: 83.3%
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%22100%
get_HasSignature()100%11100%
get_HasKeyReference()50%22100%
get_IsSigned()100%44100%
get_HasMetadata()100%11100%
Create(...)100%11100%
NormalizeOptional(...)100%22100%
NormalizeMetadata(...)78.57%1414100%

File(s)

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

#LineLine coverage
 1using System.Collections.ObjectModel;
 2
 3namespace AsiBackbone.Core.Signing;
 4
 5/// <summary>
 6/// Represents provider-neutral signing metadata that can be carried by audit receipts, emission records, or provider ad
 7/// </summary>
 8/// <remarks>
 9/// The metadata stores key references and signature descriptors only. It must not contain raw signing secrets, private 
 10/// </remarks>
 11public sealed class SigningMetadata
 12{
 413    private static readonly IReadOnlyDictionary<string, string> EmptyMetadata =
 414        new ReadOnlyDictionary<string, string>(
 415            new Dictionary<string, string>(StringComparer.Ordinal));
 16
 58817    private SigningMetadata(
 58818        string? signingHash,
 58819        string? hashAlgorithm,
 58820        string? signature,
 58821        string? signatureAlgorithm,
 58822        string? keyId,
 58823        string? keyVersion,
 58824        string? provider,
 58825        DateTimeOffset? signedUtc,
 58826        IReadOnlyDictionary<string, string> metadata)
 27    {
 58828        SigningHash = NormalizeOptional(signingHash);
 58829        HashAlgorithm = NormalizeOptional(hashAlgorithm);
 58830        Signature = NormalizeOptional(signature);
 58831        SignatureAlgorithm = NormalizeOptional(signatureAlgorithm);
 58832        KeyId = NormalizeOptional(keyId);
 58833        KeyVersion = NormalizeOptional(keyVersion);
 58834        Provider = NormalizeOptional(provider);
 58835        SignedUtc = signedUtc?.ToUniversalTime();
 58836        Metadata = metadata;
 58837    }
 38
 39    /// <summary>
 40    /// Gets metadata with no hash, key reference, signature, provider, or signed timestamp.
 41    /// </summary>
 42    public static SigningMetadata NoSignature { get; } = new(
 43        null,
 44        null,
 45        null,
 46        null,
 47        null,
 48        null,
 49        null,
 50        null,
 51        EmptyMetadata);
 52
 53    /// <summary>
 54    /// Gets the hash that was signed or is intended to be signed, when supplied by the host or signing provider.
 55    /// </summary>
 56    public string? SigningHash { get; }
 57
 58    /// <summary>
 59    /// Gets the hash algorithm or hash descriptor associated with <see cref="SigningHash" />, when supplied.
 60    /// </summary>
 61    public string? HashAlgorithm { get; }
 62
 63    /// <summary>
 64    /// Gets the provider-neutral signature value or encoded signature reference, when supplied.
 65    /// </summary>
 66    public string? Signature { get; }
 67
 68    /// <summary>
 69    /// Gets the provider-neutral signature algorithm descriptor, when supplied.
 70    /// </summary>
 71    public string? SignatureAlgorithm { get; }
 72
 73    /// <summary>
 74    /// Gets the signing key identifier, when supplied by a host or signing provider.
 75    /// </summary>
 76    public string? KeyId { get; }
 77
 78    /// <summary>
 79    /// Gets the signing key version, when supplied by a host or signing provider.
 80    /// </summary>
 81    public string? KeyVersion { get; }
 82
 83    /// <summary>
 84    /// Gets the provider or key-management system descriptor, when supplied.
 85    /// </summary>
 86    public string? Provider { get; }
 87
 88    /// <summary>
 89    /// Gets the UTC timestamp when the signature was produced, when supplied.
 90    /// </summary>
 91    public DateTimeOffset? SignedUtc { get; }
 92
 93    /// <summary>
 94    /// Gets additional provider-neutral signing metadata.
 95    /// </summary>
 96    public IReadOnlyDictionary<string, string> Metadata { get; }
 97
 98    /// <summary>
 99    /// Gets a value indicating whether a signature value or signature reference is present.
 100    /// </summary>
 152101    public bool HasSignature => Signature is not null;
 102
 103    /// <summary>
 104    /// Gets a value indicating whether any signing key reference is present.
 105    /// </summary>
 3106    public bool HasKeyReference => KeyId is not null || KeyVersion is not null;
 107
 108    /// <summary>
 109    /// Gets a value indicating whether this metadata represents a signed artifact.
 110    /// </summary>
 83111    public bool IsSigned => Signature is not null && SignatureAlgorithm is not null && KeyId is not null;
 112
 113    /// <summary>
 114    /// Gets a value indicating whether additional signing metadata is present.
 115    /// </summary>
 2116    public bool HasMetadata => Metadata.Count > 0;
 117
 118    /// <summary>
 119    /// Creates provider-neutral signing metadata.
 120    /// </summary>
 121    public static SigningMetadata Create(
 122        string? signingHash = null,
 123        string? hashAlgorithm = null,
 124        string? signature = null,
 125        string? signatureAlgorithm = null,
 126        string? keyId = null,
 127        string? keyVersion = null,
 128        string? provider = null,
 129        DateTimeOffset? signedUtc = null,
 130        IReadOnlyDictionary<string, string>? metadata = null)
 131    {
 584132        return new SigningMetadata(
 584133            signingHash,
 584134            hashAlgorithm,
 584135            signature,
 584136            signatureAlgorithm,
 584137            keyId,
 584138            keyVersion,
 584139            provider,
 584140            signedUtc,
 584141            NormalizeMetadata(metadata));
 142    }
 143
 144    private static string? NormalizeOptional(string? value)
 145    {
 4116146        return string.IsNullOrWhiteSpace(value)
 4116147            ? null
 4116148            : value.Trim();
 149    }
 150
 151    private static IReadOnlyDictionary<string, string> NormalizeMetadata(
 152        IReadOnlyDictionary<string, string>? metadata)
 153    {
 584154        if (metadata is null || metadata.Count == 0)
 155        {
 160156            return EmptyMetadata;
 157        }
 158
 424159        Dictionary<string, string> normalizedMetadata = new(StringComparer.Ordinal);
 160
 5736161        foreach (KeyValuePair<string, string> item in metadata)
 162        {
 2444163            if (string.IsNullOrWhiteSpace(item.Key))
 164            {
 165                continue;
 166            }
 167
 2443168            normalizedMetadata[item.Key.Trim()] = item.Value?.Trim() ?? string.Empty;
 169        }
 170
 424171        return normalizedMetadata.Count == 0
 424172            ? EmptyMetadata
 424173            : new ReadOnlyDictionary<string, string>(normalizedMetadata);
 174    }
 175}