Skip to content

Commit f244dbc

Browse files
committed
dotnet: add XML doc comments to pcf-sig public surface
The .NET CI failed CS1591 (\"Missing XML comment for publicly visible type or member\") on every public field, property and factory method that I had left undocumented. Pcf.Sig.csproj enables <GenerateDocumentationFile>true</GenerateDocumentationFile> the same way PCF does, and PCF achieves full coverage by documenting everything; match that bar here rather than suppressing the warning. Added missing summaries on: - KeyRecord: VersionMajor/Minor, KeyFormat, Fingerprint, KeyData, Metadata - KeyMetadata: Tag, Value, constructor - SignedEntry: Uid, PartitionType, Label, UsedBytes, DataHashAlgo, DataHash - Manifest: VersionMajor/Minor, SigAlgo, ManifestHashAlgo, Flags, SignerKeyFingerprint, SignedAtUnixSeconds, SignedEntries - SignaturePartition: Manifest, ManifestBytes, Signature, Trailer - SigningMaterial: SigAlgo, KeyFormat, PublicKeyBytes properties - PcfSigException: Kind property, constructor, and all 23 static factory methods; PcfSigErrorKind: all 23 enum members - SigAlgoExtensions/KeyFormatExtensions: FromId/Id/IsImplemented - Verify.cs: EntryVerdict + ManifestVerdict + UnverifiableReason + DataRecheck enum members; EntryReport.Uid/Verdict/ctor; SignatureReport.SigPartitionUid/SignerKeyFingerprint/SignedAtUnixSeconds/Verdict/UnverifiableReason/UnverifiableId/Entries LittleEndian remains internal so its public methods don't count as publicly visible and need no docs. https://claude.ai/code/session_01ST4PcjqvobURus32WuyEi5
1 parent d321615 commit f244dbc

7 files changed

Lines changed: 143 additions & 0 deletions

File tree

implementations/dotnet/pcf-sig/src/Pcf.Sig/KeyRecord.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,13 @@ namespace Pcf.Sig;
88
/// <summary>One metadata TLV entry (spec Section 6.4).</summary>
99
public sealed class KeyMetadata
1010
{
11+
/// <summary>16-bit tag from the metadata registry (spec Appendix B).</summary>
1112
public ushort Tag { get; }
13+
14+
/// <summary>Value bytes; interpretation depends on <see cref="Tag"/>.</summary>
1215
public byte[] Value { get; }
1316

17+
/// <summary>Construct a metadata entry from a tag and a value.</summary>
1418
public KeyMetadata(ushort tag, byte[] value)
1519
{
1620
Tag = tag;
@@ -21,11 +25,22 @@ public KeyMetadata(ushort tag, byte[] value)
2125
/// <summary>A parsed Key Record (spec Section 6).</summary>
2226
public sealed class KeyRecord
2327
{
28+
/// <summary><c>record_version_major</c>. v1.0 implementations require 1.</summary>
2429
public ushort VersionMajor { get; set; }
30+
31+
/// <summary><c>record_version_minor</c>.</summary>
2532
public ushort VersionMinor { get; set; }
33+
34+
/// <summary><c>key_format_id</c> (spec Section 6.2).</summary>
2635
public KeyFormat KeyFormat { get; set; }
36+
37+
/// <summary>32-byte SHA-256 fingerprint of <see cref="KeyData"/> (spec Section 6.3).</summary>
2738
public byte[] Fingerprint { get; set; } = new byte[Constants.FingerprintSize];
39+
40+
/// <summary>Raw key material in the encoding named by <see cref="KeyFormat"/>.</summary>
2841
public byte[] KeyData { get; set; } = new byte[0];
42+
43+
/// <summary>Optional metadata entries (spec Section 6.4).</summary>
2944
public List<KeyMetadata> Metadata { get; set; } = new();
3045

3146
/// <summary>Build a Key Record from raw key bytes; fills version + fingerprint.</summary>

implementations/dotnet/pcf-sig/src/Pcf.Sig/Manifest.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,22 @@ namespace Pcf.Sig;
77
/// <summary>One Signed Entry inside a Manifest (spec Section 7.2).</summary>
88
public sealed class SignedEntry
99
{
10+
/// <summary>PCF uid of the covered partition (verbatim).</summary>
1011
public byte[] Uid { get; set; } = new byte[Pcf.Constants.UidSize];
12+
13+
/// <summary>PCF type of the covered partition (verbatim).</summary>
1114
public uint PartitionType { get; set; }
15+
16+
/// <summary>PCF label of the covered partition (verbatim 32-byte field).</summary>
1217
public byte[] Label { get; set; } = new byte[Pcf.Constants.LabelSize];
18+
19+
/// <summary>PCF <c>used_bytes</c> of the covered partition.</summary>
1320
public ulong UsedBytes { get; set; }
21+
22+
/// <summary>PCF <c>data_hash_algo_id</c>. MUST be cryptographic in v1.0 (16/17/18).</summary>
1423
public HashAlgo DataHashAlgo { get; set; }
24+
25+
/// <summary>PCF <c>data_hash</c> field bytes (verbatim 64-byte field).</summary>
1526
public byte[] DataHash { get; set; } = new byte[Pcf.Constants.HashFieldSize];
1627

1728
/// <summary>Serialise to the on-disk 218-byte layout.</summary>
@@ -93,13 +104,31 @@ private static bool IsAllZero(byte[] b)
93104
/// <summary>A parsed Manifest (spec Section 7.1).</summary>
94105
public sealed class Manifest
95106
{
107+
/// <summary><c>manifest_version_major</c>.</summary>
96108
public ushort VersionMajor { get; set; }
109+
110+
/// <summary><c>manifest_version_minor</c>.</summary>
97111
public ushort VersionMinor { get; set; }
112+
113+
/// <summary><c>sig_algo_id</c>.</summary>
98114
public SigAlgo SigAlgo { get; set; }
115+
116+
/// <summary>
117+
/// <c>manifest_hash_algo_id</c>. MUST be cryptographic (16/17/18) and MUST
118+
/// satisfy the binding required by <see cref="SigAlgo"/>.
119+
/// </summary>
99120
public HashAlgo ManifestHashAlgo { get; set; }
121+
122+
/// <summary>Reserved <c>flags</c> field; v1.0 MUST be 0.</summary>
100123
public ushort Flags { get; set; }
124+
125+
/// <summary>Signer key fingerprint (SHA-256 of the matching PCFSIG_KEY's <c>key_data</c>).</summary>
101126
public byte[] SignerKeyFingerprint { get; set; } = new byte[Constants.FingerprintSize];
127+
128+
/// <summary><c>signed_at_unix_seconds</c> (i64).</summary>
102129
public long SignedAtUnixSeconds { get; set; }
130+
131+
/// <summary><c>signed_entries</c>, packed in writer-chosen order.</summary>
103132
public List<SignedEntry> SignedEntries { get; set; } = new();
104133

105134
/// <summary>Construct a Manifest from its component parts.</summary>

implementations/dotnet/pcf-sig/src/Pcf.Sig/PcfSigException.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,118 +5,166 @@ namespace Pcf.Sig;
55
/// <summary>Discriminant identifying which kind of <see cref="PcfSigException"/> occurred.</summary>
66
public enum PcfSigErrorKind
77
{
8+
/// <summary>A Key Record did not begin with <c>"PCFKEY\0\0"</c>.</summary>
89
BadKeyMagic,
10+
/// <summary>A Manifest did not begin with <c>"PCFSIG\0\0"</c>.</summary>
911
BadManifestMagic,
12+
/// <summary>A record's profile major version is not implemented by this library.</summary>
1013
UnsupportedMajor,
14+
/// <summary>A Key Record's <c>key_format_id</c> is unknown or reserved (0).</summary>
1115
UnknownKeyFormat,
16+
/// <summary>A Key Record's <c>key_data_length</c> is zero.</summary>
1217
EmptyKeyData,
18+
/// <summary>A Key Record's reserved bytes are non-zero in v1.0.</summary>
1319
NonZeroKeyReserved,
20+
/// <summary><c>fingerprint</c> does not equal <c>SHA-256(key_data)</c>.</summary>
1421
FingerprintMismatch,
22+
/// <summary>A Manifest's <c>sig_algo_id</c> is reserved (0) or unknown.</summary>
1523
UnknownSigAlgo,
24+
/// <summary>A Manifest's <c>manifest_hash_algo_id</c> is not cryptographic.</summary>
1625
NonCryptoManifestHash,
26+
/// <summary><c>manifest_hash_algo_id</c> does not match the binding required by <c>sig_algo_id</c>.</summary>
1727
HashAlgoBindingMismatch,
28+
/// <summary><c>flags</c> carries bits not defined in v1.0.</summary>
1829
NonZeroFlags,
30+
/// <summary><c>signed_count</c> is 0.</summary>
1931
EmptyManifest,
32+
/// <summary><c>trailer_length</c> is non-zero (reserved in v1.0).</summary>
2033
NonZeroTrailer,
34+
/// <summary>A SignedEntry's reserved span is non-zero.</summary>
2135
NonZeroEntryReserved,
36+
/// <summary>A SignedEntry's <c>data_hash_algo_id</c> is not cryptographic (spec Section 9).</summary>
2237
NonCryptoEntryHash,
38+
/// <summary>A SignedEntry references the PCF NIL UID.</summary>
2339
EntryNilUid,
40+
/// <summary>A SignedEntry uses PCF reserved type <c>0x00000000</c>.</summary>
2441
EntryReservedType,
42+
/// <summary>Two SignedEntry records share the same uid.</summary>
2543
DuplicateSignedUid,
44+
/// <summary>A SignedEntry references the enclosing PCFSIG_SIG partition's own uid.</summary>
2645
SelfSignedEntry,
46+
/// <summary>A truncation, short read, or length-field mismatch in the partition payload.</summary>
2747
MalformedSignaturePartition,
48+
/// <summary>Length of <c>sig_bytes</c> does not match the algorithm's natural size.</summary>
2849
SignatureLengthMismatch,
50+
/// <summary>The Writer was asked to sign a partition whose <c>data_hash_algo_id</c> is not cryptographic.</summary>
2951
NonCryptoTargetHash,
52+
/// <summary>The Writer was asked to sign a partition that does not exist in the supplied container.</summary>
3053
TargetPartitionMissing,
3154
}
3255

3356
/// <summary>All ways a PCF-SIG operation can fail.</summary>
3457
public sealed class PcfSigException : Exception
3558
{
59+
/// <summary>The kind of failure.</summary>
3660
public PcfSigErrorKind Kind { get; }
3761

62+
/// <summary>Construct an exception of the given kind with the given message.</summary>
3863
public PcfSigException(PcfSigErrorKind kind, string message)
3964
: base(message)
4065
{
4166
Kind = kind;
4267
}
4368

69+
/// <summary>Construct a <see cref="PcfSigErrorKind.BadKeyMagic"/> exception.</summary>
4470
public static PcfSigException BadKeyMagic() =>
4571
new(PcfSigErrorKind.BadKeyMagic, "bad PCFSIG_KEY magic");
4672

73+
/// <summary>Construct a <see cref="PcfSigErrorKind.BadManifestMagic"/> exception.</summary>
4774
public static PcfSigException BadManifestMagic() =>
4875
new(PcfSigErrorKind.BadManifestMagic, "bad PCFSIG_SIG manifest magic");
4976

77+
/// <summary>Construct an <see cref="PcfSigErrorKind.UnsupportedMajor"/> exception.</summary>
5078
public static PcfSigException UnsupportedMajor(int v) =>
5179
new(PcfSigErrorKind.UnsupportedMajor, $"unsupported PCF-SIG major version {v}");
5280

81+
/// <summary>Construct an <see cref="PcfSigErrorKind.UnknownKeyFormat"/> exception.</summary>
5382
public static PcfSigException UnknownKeyFormat(int id) =>
5483
new(PcfSigErrorKind.UnknownKeyFormat, $"unknown key_format_id {id}");
5584

85+
/// <summary>Construct an <see cref="PcfSigErrorKind.EmptyKeyData"/> exception.</summary>
5686
public static PcfSigException EmptyKeyData() =>
5787
new(PcfSigErrorKind.EmptyKeyData, "key_data_length is zero");
5888

89+
/// <summary>Construct a <see cref="PcfSigErrorKind.NonZeroKeyReserved"/> exception.</summary>
5990
public static PcfSigException NonZeroKeyReserved() =>
6091
new(PcfSigErrorKind.NonZeroKeyReserved, "key record reserved bytes are non-zero");
6192

93+
/// <summary>Construct a <see cref="PcfSigErrorKind.FingerprintMismatch"/> exception.</summary>
6294
public static PcfSigException FingerprintMismatch() =>
6395
new(PcfSigErrorKind.FingerprintMismatch,
6496
"stored key fingerprint does not match SHA-256(key_data)");
6597

98+
/// <summary>Construct an <see cref="PcfSigErrorKind.UnknownSigAlgo"/> exception.</summary>
6699
public static PcfSigException UnknownSigAlgo(int id) =>
67100
new(PcfSigErrorKind.UnknownSigAlgo, $"unknown or reserved sig_algo_id {id}");
68101

102+
/// <summary>Construct a <see cref="PcfSigErrorKind.NonCryptoManifestHash"/> exception.</summary>
69103
public static PcfSigException NonCryptoManifestHash(int id) =>
70104
new(PcfSigErrorKind.NonCryptoManifestHash,
71105
$"manifest_hash_algo_id {id} is not cryptographic");
72106

107+
/// <summary>Construct a <see cref="PcfSigErrorKind.HashAlgoBindingMismatch"/> exception.</summary>
73108
public static PcfSigException HashAlgoBindingMismatch() =>
74109
new(PcfSigErrorKind.HashAlgoBindingMismatch,
75110
"manifest_hash_algo_id does not match the binding required by sig_algo_id");
76111

112+
/// <summary>Construct a <see cref="PcfSigErrorKind.NonZeroFlags"/> exception.</summary>
77113
public static PcfSigException NonZeroFlags() =>
78114
new(PcfSigErrorKind.NonZeroFlags, "manifest flags are non-zero in v1.0");
79115

116+
/// <summary>Construct an <see cref="PcfSigErrorKind.EmptyManifest"/> exception.</summary>
80117
public static PcfSigException EmptyManifest() =>
81118
new(PcfSigErrorKind.EmptyManifest, "manifest signed_count is 0");
82119

120+
/// <summary>Construct a <see cref="PcfSigErrorKind.NonZeroTrailer"/> exception.</summary>
83121
public static PcfSigException NonZeroTrailer() =>
84122
new(PcfSigErrorKind.NonZeroTrailer, "trailer_length is non-zero in v1.0");
85123

124+
/// <summary>Construct a <see cref="PcfSigErrorKind.NonZeroEntryReserved"/> exception.</summary>
86125
public static PcfSigException NonZeroEntryReserved() =>
87126
new(PcfSigErrorKind.NonZeroEntryReserved,
88127
"SignedEntry reserved span contains non-zero bytes");
89128

129+
/// <summary>Construct a <see cref="PcfSigErrorKind.NonCryptoEntryHash"/> exception.</summary>
90130
public static PcfSigException NonCryptoEntryHash(int id) =>
91131
new(PcfSigErrorKind.NonCryptoEntryHash,
92132
$"SignedEntry data_hash_algo_id {id} is not cryptographic");
93133

134+
/// <summary>Construct an <see cref="PcfSigErrorKind.EntryNilUid"/> exception.</summary>
94135
public static PcfSigException EntryNilUid() =>
95136
new(PcfSigErrorKind.EntryNilUid, "SignedEntry uses the NIL UID");
96137

138+
/// <summary>Construct an <see cref="PcfSigErrorKind.EntryReservedType"/> exception.</summary>
97139
public static PcfSigException EntryReservedType() =>
98140
new(PcfSigErrorKind.EntryReservedType,
99141
"SignedEntry uses PCF reserved type 0x00000000");
100142

143+
/// <summary>Construct a <see cref="PcfSigErrorKind.DuplicateSignedUid"/> exception.</summary>
101144
public static PcfSigException DuplicateSignedUid() =>
102145
new(PcfSigErrorKind.DuplicateSignedUid, "duplicate uid in manifest");
103146

147+
/// <summary>Construct a <see cref="PcfSigErrorKind.SelfSignedEntry"/> exception.</summary>
104148
public static PcfSigException SelfSignedEntry() =>
105149
new(PcfSigErrorKind.SelfSignedEntry,
106150
"SignedEntry references the PCFSIG_SIG partition itself");
107151

152+
/// <summary>Construct a <see cref="PcfSigErrorKind.MalformedSignaturePartition"/> exception.</summary>
108153
public static PcfSigException MalformedSignaturePartition() =>
109154
new(PcfSigErrorKind.MalformedSignaturePartition,
110155
"PCFSIG_SIG partition layout is malformed");
111156

157+
/// <summary>Construct a <see cref="PcfSigErrorKind.SignatureLengthMismatch"/> exception.</summary>
112158
public static PcfSigException SignatureLengthMismatch() =>
113159
new(PcfSigErrorKind.SignatureLengthMismatch,
114160
"sig_bytes length does not match the algorithm");
115161

162+
/// <summary>Construct a <see cref="PcfSigErrorKind.NonCryptoTargetHash"/> exception.</summary>
116163
public static PcfSigException NonCryptoTargetHash() =>
117164
new(PcfSigErrorKind.NonCryptoTargetHash,
118165
"cannot sign a partition whose data_hash_algo_id is not cryptographic");
119166

167+
/// <summary>Construct a <see cref="PcfSigErrorKind.TargetPartitionMissing"/> exception.</summary>
120168
public static PcfSigException TargetPartitionMissing() =>
121169
new(PcfSigErrorKind.TargetPartitionMissing,
122170
"partition to sign is not present in the container");

implementations/dotnet/pcf-sig/src/Pcf.Sig/SigAlgo.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ public enum KeyFormat : byte
9292
/// <summary>Registry behaviour for <see cref="KeyFormat"/>.</summary>
9393
public static class KeyFormatExtensions
9494
{
95+
/// <summary>Map a registry id byte to a key format.</summary>
9596
public static KeyFormat FromId(byte id)
9697
{
9798
switch (id)
@@ -105,7 +106,9 @@ public static KeyFormat FromId(byte id)
105106
}
106107
}
107108

109+
/// <summary>The registry id byte for this format.</summary>
108110
public static byte Id(this KeyFormat f) => (byte)f;
109111

112+
/// <summary>Whether this library can extract a verification key from records of this format.</summary>
110113
public static bool IsImplemented(this KeyFormat f) => f == KeyFormat.Ed25519Raw;
111114
}

implementations/dotnet/pcf-sig/src/Pcf.Sig/SignaturePartition.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,19 @@ namespace Pcf.Sig;
88
/// </summary>
99
public sealed class SignaturePartition
1010
{
11+
/// <summary>Parsed Manifest.</summary>
1112
public Manifest Manifest { get; set; }
13+
14+
/// <summary>
15+
/// Raw bytes of the Manifest as serialised in the partition. This is the
16+
/// signing input and MUST be byte-exact, so the parser caches it.
17+
/// </summary>
1218
public byte[] ManifestBytes { get; set; }
19+
20+
/// <summary>Raw signature bytes (the algorithm's natural output).</summary>
1321
public byte[] Signature { get; set; }
22+
23+
/// <summary>Trailer bytes; MUST be empty in v1.0.</summary>
1424
public byte[] Trailer { get; set; } = new byte[0];
1525

1626
/// <summary>Compose a partition payload from a manifest + signature.</summary>

implementations/dotnet/pcf-sig/src/Pcf.Sig/SigningMaterial.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,15 @@ namespace Pcf.Sig;
1111
/// </summary>
1212
public sealed class SigningMaterial
1313
{
14+
/// <summary>The signature algorithm id this signer produces.</summary>
1415
public SigAlgo SigAlgo { get; }
16+
17+
/// <summary>The key format id of the signer's public material.</summary>
1518
public KeyFormat KeyFormat { get; }
19+
20+
/// <summary>The signer's public key bytes in the encoding named by <see cref="KeyFormat"/>.</summary>
1621
public byte[] PublicKeyBytes { get; }
22+
1723
private readonly byte[] _secretSeed;
1824

1925
private SigningMaterial(SigAlgo sigAlgo, KeyFormat keyFormat, byte[] secretSeed, byte[] publicKeyBytes)

0 commit comments

Comments
 (0)