Repository navigation
What's changed
Fixed
-
Verification of renewed containers. Chain order came from an alphabetical sort of entry names, and since
-(0x2D) sorts before.(0x2E),META-INF/timestamp-002.tstprecededMETA-INF/timestamp.tst— the original token sorted last. Every renewed container failed verification, the reported instant came from an archive timestamp rather than the original (contradicting ETSI EN 319 162-1 §5.4), and a second renewal forked the chain instead of extending it. Order now derives from the sequence number in the entry name. -
ASiC-E entries the manifest never referenced were extractable as though timestamped. An ASiC-E timestamp covers the ASiCManifest, so a ZIP entry the manifest does not list carries no proof of existence — yet the container still verifies, because the referenced files' proofs are intact.
Extractreturned whichever data entry came first in ZIP order (which whoever rebuilt the ZIP chooses) andExtractAllreturned every entry. Both now hand back only manifest-referenced entries. (#25)Behaviour change: if you relied on
ExtractAllreturning every ZIP entry irrespective of the manifest, useUnreferencedFileNamesbelow to see what is now filtered out.
New
AsicVerifyResult.UnreferencedFileNames— the ASiC-E entries no timestamp covers. Empty when every entry is referenced,nullfor ASiC-S. Informational by design: it does not affectIsValid, since third-party containers may legitimately carry extra entries. If your policy is that every byte must be covered, enforce it on this list. A new always-passingManifest completenessstep reports the same thing inverify -v, andasicts verifyprints a! Not covered by the timestamp:block. (#25)AsicCreateResult.FileNamesand.FileHashes— what went into the container, and each file's digest taken from the values actually written to the ASiCManifest, so the two cannot drift. Bothnullafter a renewal.asicts stampnow lists per-file hashes for ASiC-E. (#9)- Genuinely streaming ASiC-S —
CreateToStreamAsync,Verify(Stream),ExtractToStreamAsync, and the newAsicStreamCreateResult. The payload is hashed in chunks and copied straight into the container: a 64 MB payload allocates roughly 300 KB, against 128 MB+ for thebyte[]path (pinned by a test). All three require a seekable stream and throwArgumentExceptionotherwise — create reads the payload twice because the TSA must see its hash before the first byte is written, and on the read sideZipArchivesilently buffers a forward-only stream rather than failing.CreateToStreamAsyncthrowsNotSupportedExceptionwhenSigningCertificateis set, since a CAdES signature has no streaming form. The olderCreateAsync(Stream, ...)is not one of these — it buffers into abyte[]internally. ASiC-E creation and renewal remainbyte[]-only. (#4)
Docs
- README gained a streaming section, TSA fallback via
TimestampAuthorityUrls, a full options table, theIsValidrules (and why valid is not trusted), what a valid ASiC-E container does not tell you, and an errors section covering the exception tree and what does not throw.<param>/<returns>/<exception>completed acrossIAsicService. (#6) - Per-domain living specs under
docs/(container, timestamping, verification, renewal) and aUBIQUITOUS_LANGUAGE.mdglossary.
Dependencies
- Runtime deps to 10.0.11:
System.Security.Cryptography.Pkcsand theMicrosoft.Extensions.*packages.
Internal (not shipped to consumers)
- Repo-level
NuGet.configpinning restore to nuget.org, so central package management no longer tripsNU1507on machines carrying extra feeds. - STRIDE threat model to 1.7: T-9 partially mitigated, and D-3 corrected — its mitigation had credited
CreateAsync(Stream, ...)for memory efficiency, which copies tobyte[]internally. - Test/CI bumps: NSubstitute v6, xunit.runner.visualstudio v4, AwesomeAssertions 9.6.0, Microsoft.NET.Test.Sdk 18.9.0, ThisAssembly 2.1.5, actions/setup-dotnet v6.
Full changelog: 1.2.0...1.3.0
🤖 Release prepared with Claude Code