< 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{
 813    private static readonly IReadOnlyDictionary<string, string> EmptyMetadata =
 814        new ReadOnlyDictionary<string, string>(
 815            new Dictionary<string, string>(StringComparer.Ordinal));
 16
 75817    private SigningMetadata(
 75818        string? signingHash,
 75819        string? hashAlgorithm,
 75820        string? signature,
 75821        string? signatureAlgorithm,
 75822        string? keyId,
 75823        string? keyVersion,
 75824        string? provider,
 75825        DateTimeOffset? signedUtc,
 75826        IReadOnlyDictionary<string, string> metadata)
 27    {
 75828        SigningHash = NormalizeOptional(signingHash);
 75829        HashAlgorithm = NormalizeOptional(hashAlgorithm);
 75830        Signature = NormalizeOptional(signature);
 75831        SignatureAlgorithm = NormalizeOptional(signatureAlgorithm);
 75832        KeyId = NormalizeOptional(keyId);
 75833        KeyVersion = NormalizeOptional(keyVersion);
 75834        Provider = NormalizeOptional(provider);
 75835        SignedUtc = signedUtc?.ToUniversalTime();
 75836        Metadata = metadata;
 75837    }
 38
 39    /// <summary>
 40    /// Gets metadata with no hash, key reference, signature, provider, or signed timestamp.
 41    /// </summary>
 3242    public static SigningMetadata NoSignature { get; } = new(
 843        null,
 844        null,
 845        null,
 846        null,
 847        null,
 848        null,
 849        null,
 850        null,
 851        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>
 50256    public string? SigningHash { get; }
 57
 58    /// <summary>
 59    /// Gets the hash algorithm or hash descriptor associated with <see cref="SigningHash" />, when supplied.
 60    /// </summary>
 45461    public string? HashAlgorithm { get; }
 62
 63    /// <summary>
 64    /// Gets the provider-neutral signature value or encoded signature reference, when supplied.
 65    /// </summary>
 49266    public string? Signature { get; }
 67
 68    /// <summary>
 69    /// Gets the provider-neutral signature algorithm descriptor, when supplied.
 70    /// </summary>
 36671    public string? SignatureAlgorithm { get; }
 72
 73    /// <summary>
 74    /// Gets the signing key identifier, when supplied by a host or signing provider.
 75    /// </summary>
 38676    public string? KeyId { get; }
 77
 78    /// <summary>
 79    /// Gets the signing key version, when supplied by a host or signing provider.
 80    /// </summary>
 34881    public string? KeyVersion { get; }
 82
 83    /// <summary>
 84    /// Gets the provider or key-management system descriptor, when supplied.
 85    /// </summary>
 32686    public string? Provider { get; }
 87
 88    /// <summary>
 89    /// Gets the UTC timestamp when the signature was produced, when supplied.
 90    /// </summary>
 31091    public DateTimeOffset? SignedUtc { get; }
 92
 93    /// <summary>
 94    /// Gets additional provider-neutral signing metadata.
 95    /// </summary>
 98696    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>
 190101    public bool HasSignature => Signature is not null;
 102
 103    /// <summary>
 104    /// Gets a value indicating whether any signing key reference is present.
 105    /// </summary>
 6106    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>
 122111    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>
 4116    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    {
 750132        return new SigningMetadata(
 750133            signingHash,
 750134            hashAlgorithm,
 750135            signature,
 750136            signatureAlgorithm,
 750137            keyId,
 750138            keyVersion,
 750139            provider,
 750140            signedUtc,
 750141            NormalizeMetadata(metadata));
 142    }
 143
 144    private static string? NormalizeOptional(string? value)
 145    {
 5306146        return string.IsNullOrWhiteSpace(value)
 5306147            ? null
 5306148            : value.Trim();
 149    }
 150
 151    private static IReadOnlyDictionary<string, string> NormalizeMetadata(
 152        IReadOnlyDictionary<string, string>? metadata)
 153    {
 750154        if (metadata is null || metadata.Count == 0)
 155        {
 228156            return EmptyMetadata;
 157        }
 158
 522159        Dictionary<string, string> normalizedMetadata = new(StringComparer.Ordinal);
 160
 7364161        foreach (KeyValuePair<string, string> item in metadata)
 162        {
 3160163            if (string.IsNullOrWhiteSpace(item.Key))
 164            {
 165                continue;
 166            }
 167
 3158168            normalizedMetadata[item.Key.Trim()] = item.Value?.Trim() ?? string.Empty;
 169        }
 170
 522171        return normalizedMetadata.Count == 0
 522172            ? EmptyMetadata
 522173            : new ReadOnlyDictionary<string, string>(normalizedMetadata);
 174    }
 175}