< 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: 68
Uncovered lines: 0
Coverable lines: 68
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_NoSignature()100%11100%
get_SigningHash()100%11100%
get_HashAlgorithm()100%11100%
get_Signature()100%11100%
get_SignatureAlgorithm()100%11100%
get_KeyId()100%11100%
get_KeyVersion()100%11100%
get_Provider()100%11100%
get_SignedUtc()100%11100%
get_Metadata()100%11100%
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{
 513    private static readonly IReadOnlyDictionary<string, string> EmptyMetadata =
 514        new ReadOnlyDictionary<string, string>(
 515            new Dictionary<string, string>(StringComparer.Ordinal));
 16
 29517    private SigningMetadata(
 29518        string? signingHash,
 29519        string? hashAlgorithm,
 29520        string? signature,
 29521        string? signatureAlgorithm,
 29522        string? keyId,
 29523        string? keyVersion,
 29524        string? provider,
 29525        DateTimeOffset? signedUtc,
 29526        IReadOnlyDictionary<string, string> metadata)
 27    {
 29528        SigningHash = NormalizeOptional(signingHash);
 29529        HashAlgorithm = NormalizeOptional(hashAlgorithm);
 29530        Signature = NormalizeOptional(signature);
 29531        SignatureAlgorithm = NormalizeOptional(signatureAlgorithm);
 29532        KeyId = NormalizeOptional(keyId);
 29533        KeyVersion = NormalizeOptional(keyVersion);
 29534        Provider = NormalizeOptional(provider);
 29535        SignedUtc = signedUtc?.ToUniversalTime();
 29536        Metadata = metadata;
 29537    }
 38
 39    /// <summary>
 40    /// Gets metadata with no hash, key reference, signature, provider, or signed timestamp.
 41    /// </summary>
 1442    public static SigningMetadata NoSignature { get; } = new(
 543        null,
 544        null,
 545        null,
 546        null,
 547        null,
 548        null,
 549        null,
 550        null,
 551        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>
 19756    public string? SigningHash { get; }
 57
 58    /// <summary>
 59    /// Gets the hash algorithm or hash descriptor associated with <see cref="SigningHash" />, when supplied.
 60    /// </summary>
 18061    public string? HashAlgorithm { get; }
 62
 63    /// <summary>
 64    /// Gets the provider-neutral signature value or encoded signature reference, when supplied.
 65    /// </summary>
 17566    public string? Signature { get; }
 67
 68    /// <summary>
 69    /// Gets the provider-neutral signature algorithm descriptor, when supplied.
 70    /// </summary>
 14371    public string? SignatureAlgorithm { get; }
 72
 73    /// <summary>
 74    /// Gets the signing key identifier, when supplied by a host or signing provider.
 75    /// </summary>
 14876    public string? KeyId { get; }
 77
 78    /// <summary>
 79    /// Gets the signing key version, when supplied by a host or signing provider.
 80    /// </summary>
 14081    public string? KeyVersion { get; }
 82
 83    /// <summary>
 84    /// Gets the provider or key-management system descriptor, when supplied.
 85    /// </summary>
 13386    public string? Provider { get; }
 87
 88    /// <summary>
 89    /// Gets the UTC timestamp when the signature was produced, when supplied.
 90    /// </summary>
 12791    public DateTimeOffset? SignedUtc { get; }
 92
 93    /// <summary>
 94    /// Gets additional provider-neutral signing metadata.
 95    /// </summary>
 31396    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>
 80101    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>
 24111    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    {
 290132        return new SigningMetadata(
 290133            signingHash,
 290134            hashAlgorithm,
 290135            signature,
 290136            signatureAlgorithm,
 290137            keyId,
 290138            keyVersion,
 290139            provider,
 290140            signedUtc,
 290141            NormalizeMetadata(metadata));
 142    }
 143
 144    private static string? NormalizeOptional(string? value)
 145    {
 2065146        return string.IsNullOrWhiteSpace(value)
 2065147            ? null
 2065148            : value.Trim();
 149    }
 150
 151    private static IReadOnlyDictionary<string, string> NormalizeMetadata(
 152        IReadOnlyDictionary<string, string>? metadata)
 153    {
 290154        if (metadata is null || metadata.Count == 0)
 155        {
 117156            return EmptyMetadata;
 157        }
 158
 173159        Dictionary<string, string> normalizedMetadata = new(StringComparer.Ordinal);
 160
 2030161        foreach (KeyValuePair<string, string> item in metadata)
 162        {
 842163            if (string.IsNullOrWhiteSpace(item.Key))
 164            {
 165                continue;
 166            }
 167
 841168            normalizedMetadata[item.Key.Trim()] = item.Value?.Trim() ?? string.Empty;
 169        }
 170
 173171        return normalizedMetadata.Count == 0
 173172            ? EmptyMetadata
 173173            : new ReadOnlyDictionary<string, string>(normalizedMetadata);
 174    }
 175}