ctxsignlib 1.1.7
dotnet add package ctxsignlib --version 1.1.7
NuGet\Install-Package ctxsignlib -Version 1.1.7
<PackageReference Include="ctxsignlib" Version="1.1.7" />
<PackageVersion Include="ctxsignlib" Version="1.1.7" />
<PackageReference Include="ctxsignlib" />
paket add ctxsignlib --version 1.1.7
#r "nuget: ctxsignlib, 1.1.7"
#:package ctxsignlib@1.1.7
#addin nuget:?package=ctxsignlib&version=1.1.7
#tool nuget:?package=ctxsignlib&version=1.1.7
CtxSignlib
Portable CMS / PKCS#7 detached signing and verification library for .NET.
CtxSignlib is a deterministic manifest-based trust model for verifying distributed software content.
CtxSignlib provides a deterministic, cross-platform CMS (Cryptographic Message Syntax) signing and verification library built on .NET 8.
It is designed for portable verification workflows such as:
- Detached signature validation
- Signed manifest distribution
- Secure file integrity enforcement
- Deterministic public-key pinning
CtxSignlib performs crypto-only verification and does not rely on OS trust stores. Signer identity is validated through explicit pinning.
Repository: https://github.com/mywebext/ctxsignlib
Installation
dotnet add package ctxsignlib
Quick Start
Verify a file signed with a detached CMS signature using a pinned public key hash.
Example:
using CtxSignlib.Verify;
bool ok = SingleFileVerification.VerifyFileByPublicKey( contentPath: "MyApp.zip", sigPath: "MyApp.sig", pinnedPublicKeySha256: "YOUR_PUBPIN_HEX", out var result);
Console.WriteLine(ok ? "Verified" : $"Failed: {result}");
Using Embedded Public Keys
--pin represents the signer public key in SPKI format. This corresponds to the key contained in a PEM block.
Example PEM:
-----BEGIN PUBLIC KEY----- ... -----END PUBLIC KEY-----
Applications can embed this key as a resource and load it during verification.
Example:
using System.Reflection; using System.Text; using CtxSignlib.Verify;
static string ReadEmbeddedText(string resourceName) { var asm = Assembly.GetExecutingAssembly();
using var stream = asm.GetManifestResourceStream(resourceName)
?? throw new InvalidOperationException($"Resource not found: {resourceName}");
using var reader = new StreamReader(stream, Encoding.ASCII);
return reader.ReadToEnd();
}
string pem = ReadEmbeddedText("MyApp.security.pem");
bool ok = SingleFileVerification.VerifyFileByRawPublicKey( contentPath: "MyApp.zip", sigPath: "MyApp.sig", rawPublicKey: pem, out var result);
Console.WriteLine(ok ? "Verified" : $"Failed: {result}");
Notes:
- The PEM contains public key material only
- The private signing key must never be embedded in applications
Signer Identity Model
CtxSignlib supports three explicit pinning modes.
--thumb Pins the exact certificate instance
--pin Raw SPKI public key
--pubpin SHA-256 hash of the SPKI public key (recommended)
Relationship:
SPKI Public Key (--pin) ↓ SHA256(SPKI) ↓ --pubpin
Public-key pinning allows identity continuity across certificate renewals that reuse the same key pair.
Architecture
Signing
CMSWriter
Creates detached CMS / PKCS#7 signatures.
Core Verification
CMSVerifier
Low-level CMS verification engine.
SingleFileVerification
Convenience helpers for verifying individual files.
Manifest System
CtxSignlib includes a deterministic manifest verification system designed for software distribution and package integrity.
Core components:
- ManifestBuilder
- ManifestVerifier
- SignedManifestVerifier
- ManifestFileVerification
- ManifestPartialVerifier
- SignedManifestPartialVerifier
- DetailedManifestFileVerification
These enable workflows such as:
- verifying downloaded binaries
- verifying software packages before execution
- secure update distribution
- repairing corrupted installations
- verifying partial package states
Verification Modes
CtxSignlib provides multiple verification policies built on the same manifest engine.
Strict Verification
All manifest files must exist and verify.
Failure conditions:
- Missing file
- Hash mismatch
- Unreadable file
- Invalid syntax for a per-file verification rule
Used for:
- full installs
- archive validation
- final package verification
Partial Verification
Allows missing files but verifies everything that exists.
Failure conditions:
- Hash mismatch
- Unreadable file
- Invalid syntax for a per-file verification rule
Used for:
- incremental downloads
- patch installs
- optional modules
- repair operations
Signed Manifest Verification
Signed manifest verification authenticates the manifest first using a pinned public key, then evaluates file integrity.
Workflow:
Verify CMS Signature ↓ Authenticate Manifest ↓ Evaluate File Integrity
Single-file signed manifest verification also supports exact-path regex-filtered hashing rules recorded in excludes[].
Detailed Verification Results
CtxSignlib includes a structured result type for manifest verification:
ManifestPartialVerificationResult
This type provides categorized file state information.
Fields:
- PassedFiles
- MissingFiles
- FailedFiles
- UnreadableFiles
- InvalidSyntaxFiles
Policy evaluation helpers:
- IsStrictlyValid
- IsPartiallyValid
InvalidSyntaxFiles represents files whose verification could not be safely completed because a rule or instruction associated with that file was malformed, such as an invalid regex or regex-filtered content that is not valid UTF-8 text.
This allows higher-level systems to evaluate installation state and determine corrective actions such as repairing or requesting missing files.
Error Model
CtxSignlib includes a structured custom exception model for operational and validation failures.
Core components:
- CtxException
- ErrorTarget
- ErrorDetail
This model is used to distinguish categories such as:
- argument validation failures
- filesystem failures
- manifest validation failures
- certificate and cryptography failures
- signing and verification failures
Result-based verification APIs still use explicit result contracts where appropriate, while operational failures and invalid inputs use CtxException for more precise error handling.
Package Identity
CtxSignlib provides a deterministic PackageId generator.
A PackageId represents the identity of the full expected package content defined by a manifest.
The ID is generated from the canonical representation of each expected file:
normalized/path|EXPECTED_SHA256
Algorithm:
- Normalize manifest path
- Normalize SHA-256 hex
- Build canonical entries
- Remove duplicates
- Sort using StringComparer.Ordinal
- Join entries using LF
- SHA-256 hash the UTF-8 payload
Example:
using CtxSignlib.Verify;
string id = PackageId.Generate(result);
Two packages with identical file paths and expected hashes will always produce the same PackageId across platforms.
Deterministic Repair Package IDs
CtxSignlib also includes a deterministic repair identity generator:
RepairPackageId
This feature derives a stable identifier for the subset of files that must be repaired or downloaded.
The ID is generated from the canonical entries of files that failed verification:
normalized/path|EXPECTED_SHA256
Important properties:
- Failure reason does not affect the ID
- Missing / corrupted / unreadable files produce the same ID if the required content is identical
- Two machines with the same repair state will generate the same RepairPackageId
Example:
using CtxSignlib.Verify;
var result = ManifestPartialVerifier.VerifyManifestPartialDetailed( rootDir: "MyPackage", manifestPath: "package.manifest.json");
string repairId = RepairPackageId.Generate(result);
Console.WriteLine($"Repair package id: {repairId}");
This enables deterministic repair distribution systems and patch delivery.
Security Model
CtxSignlib is designed for deterministic, portable verification of signed content.
Cryptographic Authentication
Signed content is verified using CMS / PKCS#7 detached signatures.
Signer identity is validated through explicit pinning:
- certificate thumbprint
- raw SPKI public key
- SHA-256 hash of the public key
CtxSignlib does not rely on OS trust stores.
Deterministic File Integrity
File integrity is validated using SHA-256 hashes stored in a signed manifest.
For exact-path regex-filtered manifest entries, verification hashes filtered UTF-8 content using the same exclude semantics used during manifest creation.
Path Boundary Enforcement
Manifest entries are validated to ensure they resolve only inside the specified root directory.
This prevents path traversal attacks such as:
../../escape/file.dll
Policy-Based Verification
Policy Missing Files Hash Mismatch Unreadable Invalid Syntax Strict Fail Fail Fail Fail Partial Allowed Fail Fail Fail
This allows secure support for:
- full installs
- patch installs
- incremental downloads
- repair workflows
Portable Verification
CtxSignlib performs crypto-only verification and does not depend on:
- platform certificate stores
- network services
- external trust authorities
Determinism Model
Deterministic elements:
- File SHA-256 hashing
- Manifest hashing
- SPKI public key hashing
- Thumbprint normalization
- Fixed-time comparisons
- Canonical entry sorting
Non-deterministic elements:
- CMS signature bytes
Although CMS signatures vary between signing operations, verification remains deterministic because content hashes and signer identity are validated.
CtxSignlib also supports excluding partial file contents via regex in manifest rules. This makes it possible to strip localized or personal data before hashing in narrowly defined manifest workflows.
Release Notes (v1.1.3)
- Fixed major drift between the thumbprint and pinning verification methods
- Source repository is now maintained at https://github.com/mywebext/ctxsignlib.
Release Notes (v1.1.4)
- Fixed manifest verification drift for files included in files[] but hashed using exact-path regex filtering from excludes[].
- Unified thumbprint-based and public-key-based single-file signed manifest verification behavior.
- Added shared manifest entry hash resolution logic to prevent verification drift.
- Added InvalidSyntaxFiles to partial verification results.
- Categorized malformed regex and non-UTF-8 regex-filtered files as syntax failures rather than ordinary mismatches.
- Added locked-read handling for regex-filtered verification to improve TOCTOU hardening.
- Expanded the custom CtxException-based error model across more library surfaces.
- Source repository is now maintained at https://github.com/mywebext/ctxsignlib.
Release Notes (v1.1.5)
- Added a custom CtxException-based error model for more precise diagnostics, safer caller handling.
- Structured both the error and return models so the ability to add language translations would be easier.
Release Notes (v1.1.6)
- Removed unessasary usings from Functions.cs
- Rebuilt with version bump and submit since public namespace for CtxSignlib.Diagnostics wasn't showing
Release Notes (v1.1.7)
- Polished up the CtxException throw in ManifestBuilder.cs so it is more inline with intended function
- Completed code optimization to begin building CtxSigntool starting at version 1.1.7
Target Framework
.NET 8.0
License
Copyright © Kenneth Poston Licensed under the Apache License 2.0
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- System.Security.Cryptography.Pkcs (>= 8.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Polished up the CtxException throw in ManifestBuilder.cs so it is more inline with intended function