SafeSign 1.0.0

dotnet tool install --global SafeSign --version 1.0.0
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local SafeSign --version 1.0.0
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=SafeSign&version=1.0.0
                    
nuke :add-package SafeSign --version 1.0.0
                    

CI Build Coverage Reliability Rating Duplicated Lines (%) Vulnerabilities Security Rating NuGet Downloads GitHub stars License: MIT

<br> <a href="https://github.com/glennawatson/SafeSign"> <img width="160" height="160" src="https://raw.githubusercontent.com/glennawatson/SafeSign/main/icons/icon.png" alt="SafeSign"> </a> <br>

SafeSign

SafeSign is a fast, cross-platform .NET 10 and .NET 11 code-signing command-line tool (safesign) and modular library suite with standalone Native AOT binaries for Linux, macOS, and Windows.

SafeSign implements binary format parsing, Authenticode/CMS ASN.1 DER encoding, RFC 3161 timestamping, and cloud KMS / HSM remote digest signing directly in managed C# without requiring SignTool.exe, Windows-only CryptoAPI/CNG Subject Interface Packages (SIPs), or native PKCS #11 middleware.

  • Digest-Only Remote Signing: Only the cryptographic digest of the CMS signed attributes leaves your machine. Large binaries and installers are streamed locally and never uploaded over the network.
  • Atomic File Output: Every file format is signed into a sibling temporary file and atomically moved into place only after the provider signature verifies against the X.509 public key and any RFC 3161 timestamp succeeds.
  • Zero-Allocation Hot Paths & Native AOT: Built with SIMD-accelerated PE checksums (Vector256<ushort> / Vector128<ushort>), pooled streaming I/O, and source-generated System.Text.Json serialization for trimming-safe Native AOT compilation.
  • First-Class Certum SimplySign Support: Authenticates directly with Certum SimplySign Cloud (cloudsign.webnotarius.pl) using user credentials and either a current 6-digit TOTP code or a base32/hex TOTP shared secret, with no desktop tray app or PKCS #11 library required.

Installation

.NET Global Tool

dotnet tool install --global SafeSign

Once installed, invoke the tool via safesign:

safesign --help
safesign providers
safesign formats

Standalone Native AOT Binaries

Standalone Native AOT executables (requiring no .NET runtime installation) are published on net11.0 for:

  • linux-x64
  • osx-arm64
  • win-x64

Library Packages

You can also embed SafeSign's signing engine directly in your own .NET applications:

Package Purpose
SafeSign.Signing Core abstractions (ISigningProvider, IFileFormatSigner, SigningSession), ASN.1 DER CMS / Authenticode builder, RFC 3161 timestamp client, and PE32/PE32+/EFI signer
SafeSign.Formats Native format signers for .msi/.msp/.mst, .cab, .cat, .appx/.msix, .navx, .nupkg/.snupkg, PowerShell/WSH scripts, and .rpm v4
SafeSign.Providers Local (file, store), Certum SimplySign Cloud (certum), and 15 cloud KMS / enterprise signing providers

Command-Line Interface

Commands

safesign sign <files>... [options]   Sign one or more files in place (or to --output)
safesign providers                   List all supported signing providers and their status
safesign formats                     List all supported file formats and their status

safesign sign Options

Option Alias Description
<files>... — One or more files to sign. Format is auto-detected from file extension and magic bytes.
--provider <name> -p Required. Signing provider name (see Supported Signing Providers).
--provider-option <name=value> -o Repeatable provider-specific key/value option (e.g. -o email=dev@example.com -o totp-secret=JBSWY3DPEHPK3PXP). All provider options also fall back to provider environment variables.
--output <path> — Output file path. Only valid when signing a single input file; defaults to signing in place.
--hash <alg> -f File and CMS digest algorithm: SHA256 (default), SHA384, or SHA512.
--timestamp-url <uri> -t RFC 3161 timestamp authority URL (e.g. http://time.certum.pl or http://timestamp.digicert.com).
--timestamp-hash <alg> — Digest algorithm for the RFC 3161 timestamp request: SHA256 (default), SHA384, or SHA512.
--description <text> -d Program description embedded in Authenticode SpcSpOpusInfo.
--description-url <uri> -u Program URL embedded in Authenticode SpcSpOpusInfo.

Supported Signing Providers

Run safesign providers at any time to inspect the built-in provider catalog. All 18 providers below are fully implemented (Working) and configured via --provider-option (-o) or environment variables:

Provider ID Platform / Service Options (-o name=value) & Environment Fallbacks
certum Certum SimplySign Cloud (cloudsign.webnotarius.pl) email (CERTUM_SIMPLYSIGN_EMAIL / CERTUM_USER_ID), and totp-secret (CERTUM_SIMPLYSIGN_TOTP_SECRET / CERTUM_OTP_URI — Base32 seed or otpauth:// URI) or otp (CERTUM_SIMPLYSIGN_OTP), or refresh-token (CERTUM_SIMPLYSIGN_REFRESH_TOKEN), or access-token (CERTUM_SIMPLYSIGN_ACCESS_TOKEN). Optional: card-serial, certificate-chain-path, endpoint.
file Local PKCS #12 / PFX File (.pfx, .p12) path (SAFESIGN_FILE_PATH), optional password (SAFESIGN_FILE_PASSWORD)
store Local X.509 Certificate Store (CurrentUser / LocalMachine) thumbprint (SAFESIGN_STORE_THUMBPRINT), optional store-name (My), store-location (CurrentUser / LocalMachine)
aws-kms AWS Key Management Service (KMS) key-id (AWS_KMS_KEY_ID), certificate-path (AWS_KMS_CERTIFICATE_PATH), region (AWS_REGION / AWS_DEFAULT_REGION), access-key-id (AWS_ACCESS_KEY_ID), secret-access-key (AWS_SECRET_ACCESS_KEY), optional session-token (AWS_SESSION_TOKEN)
azure-artifact-signing Azure Artifact Signing (formerly Azure Trusted Signing) endpoint (AZURE_CODESIGNING_ENDPOINT), account (AZURE_CODESIGNING_ACCOUNT), profile (AZURE_CODESIGNING_PROFILE), and access-token (AZURE_CODESIGNING_ACCESS_TOKEN) or tenant-id + client-id + client-secret (AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET)
azure-key-vault Azure Key Vault vault-url (AZURE_KEYVAULT_URL), key-name (AZURE_KEYVAULT_KEY_NAME), and access-token (AZURE_KEYVAULT_ACCESS_TOKEN) or tenant-id + client-id + client-secret. Optional: certificate-name, certificate-path, key-version.
google-cloud-kms Google Cloud KMS key-version-name (GOOGLE_KMS_KEY_VERSION), certificate-path (GOOGLE_KMS_CERTIFICATE_PATH), and access-token (GOOGLE_OAUTH_ACCESS_TOKEN)
hashicorp-vault HashiCorp Vault Transit Engine address (VAULT_ADDR), key-name (VAULT_TRANSIT_KEY), certificate-path (VAULT_CERTIFICATE_PATH), and token (VAULT_TOKEN; optional mount=transit, namespace)
oracle-kms Oracle Cloud Infrastructure (OCI) KMS crypto-endpoint (OCI_KMS_CRYPTO_ENDPOINT), key-id (OCI_KMS_KEY_ID), certificate-path (OCI_KMS_CERTIFICATE_PATH), tenancy-ocid (OCI_TENANCY_OCID), user-ocid (OCI_USER_OCID), fingerprint (OCI_FINGERPRINT), private-key-path (OCI_PRIVATE_KEY_PATH)
digicert-keylocker DigiCert ONE / KeyLocker keypair-id (DIGICERT_KEYPAIR_ID), api-key (DIGICERT_API_KEY), and certificate-id (DIGICERT_CERTIFICATE_ID) or certificate-path (optional endpoint)
sslcom-esigner SSL.com eSigner (CSC API) credential-id (SSLCOM_CREDENTIAL_ID), username (SSLCOM_USERNAME), password (SSLCOM_PASSWORD), and totp-secret (SSLCOM_TOTP_SECRET) or otp (SSLCOM_OTP)
csc Cloud Signature Consortium (CSC) v1/v2 (Sectigo, Entrust, GlobalSign, SwissSign, CertEurope) endpoint (CSC_ENDPOINT), credential-id (CSC_CREDENTIAL_ID), access-token (CSC_ACCESS_TOKEN) or client-id + client-secret, and pin (CSC_PIN) / otp (CSC_OTP) / sad (CSC_SAD)
keyfactor-signserver Keyfactor SignServer endpoint (SIGNSERVER_ENDPOINT), worker (SIGNSERVER_WORKER), certificate-path (SIGNSERVER_CERTIFICATE_PATH), optional access-token (SIGNSERVER_ACCESS_TOKEN)
fortanix-dsm Fortanix Data Security Manager (DSM) endpoint (FORTANIX_ENDPOINT), key-id (FORTANIX_KEY_ID), certificate-path (FORTANIX_CERTIFICATE_PATH), and api-key (FORTANIX_API_KEY)
encryption-consulting Encryption Consulting CodeSign Secure endpoint (CODESIGNSECURE_ENDPOINT), key-name (CODESIGNSECURE_KEY_NAME), certificate-path (CODESIGNSECURE_CERTIFICATE_PATH), api-key (CODESIGNSECURE_API_KEY)
garasign GaraSign (Garantir) endpoint (GARASIGN_ENDPOINT), key-name (GARASIGN_KEY_NAME), username (GARASIGN_USERNAME), password (GARASIGN_PASSWORD), optional certificate-path
signpath SignPath organization-id (SIGNPATH_ORGANIZATION_ID), project-slug (SIGNPATH_PROJECT_SLUG), signing-policy-slug (SIGNPATH_SIGNING_POLICY_SLUG), api-token (SIGNPATH_API_TOKEN), certificate-path (SIGNPATH_CERTIFICATE_PATH)
venafi-codesign Venafi CodeSign Protect (TPP) endpoint (VENAFI_ENDPOINT), environment-dn (VENAFI_ENVIRONMENT_DN), certificate-path (VENAFI_CERTIFICATE_PATH), and access-token (VENAFI_ACCESS_TOKEN)

Usage Examples

1. Sign a Windows PE executable, MSI installer, and NuGet package with Certum SimplySign Cloud
export CERTUM_USER_ID="developer@example.com"
export CERTUM_OTP_URI="otpauth://totp/Certum:developer@example.com?secret=JBSWY3DPEHPK3PXP&algorithm=SHA256&digits=6&period=30"

safesign sign artifacts/MyApp.exe artifacts/MyAppSetup.msi artifacts/MyPackage.1.0.0.nupkg \
  --provider certum \
  --hash SHA256 \
  --timestamp-url http://time.certum.pl \
  --description "MyApp" \
  --description-url https://example.com
2. Sign with Azure Artifact Signing (formerly Azure Trusted Signing)
safesign sign bin/Release/net11.0/win-x64/publish/MyApp.exe \
  --provider azure-artifact-signing \
  -o endpoint=https://eus.codesigning.azure.net \
  -o account=my-signing-account \
  -o profile=my-public-trust-profile \
  -o access-token="$AZURE_CODESIGNING_ACCESS_TOKEN" \
  --timestamp-url http://timestamp.acs.microsoft.com
3. Sign a NuGet package, MSIX bundle, and PowerShell script with a local PFX certificate
safesign sign MyLibrary.1.0.0.nupkg MyApp.msix Deploy.ps1 \
  --provider file \
  -o path=certs/codesign.pfx \
  -o password="$PFX_PASSWORD" \
  --timestamp-url http://timestamp.digicert.com
4. Sign an RPM package with AWS KMS
safesign sign dist/myapp-1.0.0-1.x86_64.rpm \
  --provider aws-kms \
  -o region=us-east-1 \
  -o key-id=arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012 \
  -o certificate-path=certs/aws-codesign.cer

Supported File Formats

Run safesign formats to view all registered format handlers. SafeSign implements native format signing for each format below (never substituting detached signatures for embedded format signatures):

Format Extensions Implementation Details Status
PE / UEFI .exe, .dll, .efi Authenticode SPC_PE_IMAGE_DATA PKCS #7 signature in the PE Certificate Table (IMAGE_DIRECTORY_ENTRY_SECURITY) with 8-byte alignment and SIMD PE header checksum update Working
Windows Installer .msi, .msp, .mst OLE Compound File Binary (CFB v3/v4) parser/writer embedding \x05DigitalSignature (SPC_SIPINFO GUID 000C10F1-0000-0000-C000-000000000046) and \x05MsiDigitalSignatureEx Working
Cabinet .cab Microsoft Cabinet (MSCF) header CFHEADER_RESERVE_PRESENT (20-byte reserve) and WIN_CERTIFICATE Authenticode SPC_CAB_DATA structure Working
Security Catalog .cat ASN.1 DER CertTrustList (1.3.6.1.4.1.311.10.1) re-signing inside outer CMS SignedData while preserving catalog member hashes and attributes Working
AppX / MSIX .appx, .msix, .appxbundle, .msixbundle AppxBlockMap.xml, AppxMetadata/CodeIntegrity.cat, and [Content_Types].xml APPX_AXPC/APPX_AXCD/APPX_AXCI/APPX_AXCT digest calculation and AppxSignature.p7x (PKCX prefix + Authenticode SPC_SIPINFO) Working
Dynamics 365 NAVX .navx NAVX 40-byte package header + OPC ZIP payload digest and NVSG signature trailer (SPC_SIPINFO GUID F5256E31-BA25-4468-ABA9-AB9B38F6F138) Working
NuGet Package .nupkg, .snupkg NuGet v1 .signature.p7s Primary Author Signature with RFC 5035 SigningCertificateV2 (1.2.840.113549.1.9.16.2.47), commitment-type-indication (1.2.840.113549.1.9.16.6.1), and Central Directory hash Working
Scripts .ps1, .psm1, .psd1, .ps1xml, .cdxml, .psc1, .vbs, .vbe, .js, .wsf UTF-16LE Authenticode SPC_SIPINFO digest and native # SIG # / `` / '' SIG '' / // SIG // base64 signature blocks preserving BOM and encoding Working
RPM v4 .rpm RPM v4 Lead + Signature Header reconstruction embedding CMS/PKCS #7 DER signatures in tags 268 (RPMSIGTAG_RSA / header-only) and 269 (RPMSIGTAG_PGP / header+payload) Working
Debian Package .deb, .udeb Uses ar archives (debsigs / dpkg-sig) with OpenPGP (RFC 4880) signatures rather than X.509/CMS. OpenPGP is out of scope for SafeSign. OutOfScope

Programmatic Usage

using System.Security.Cryptography;
using Refit;
using SafeSign.Formats;
using SafeSign.Providers.Certum;
using SafeSign.Signing;
using SafeSign.Signing.Cms;

var provider = new CertumSimplySignProvider(
    new RefitSettings(),
    new CertumOptions
    {
        Email = "developer@example.com",
        TotpSecret = "JBSWY3DPEHPK3PXP",
    },
    TimeProvider.System);

var certificate = await provider.GetCertificateAsync(CancellationToken.None);
var timestampApi = RestService.ForGenerated<IRfc3161TimestampApi>("http://time.certum.pl");
var session = new SigningSession(
    provider,
    certificate,
    HashAlgorithmName.SHA256,
    new TimestampSettings(new Uri("http://time.certum.pl"), HashAlgorithmName.SHA256, timestampApi),
    Description: "My Application",
    DescriptionUrl: new Uri("https://example.com"),
    TimeProvider.System);

var signer = await FormatCatalog.ResolveSignerAsync("MyApp.exe", CancellationToken.None);
await signer.SignAsync(new FileSignRequest("MyApp.exe", "MyApp.exe", session), CancellationToken.None);

Repository Layout

Project Purpose
src/SafeSign.Signing Core signing abstractions, CMS / Authenticode DER encoder, RFC 3161 client, and PE/EFI signer
src/SafeSign.Formats Native format signers for MSI, CAB, CAT, AppX/MSIX, NAVX, NuGet, Scripts, and RPM
src/SafeSign.Providers Local (file, store), Certum SimplySign Cloud, and 15 cloud KMS / enterprise signing providers
src/SafeSign safesign CLI global tool and standalone Native AOT entry point
src/tests/* TUnit test suites across net10.0 and net11.0
src/benchmarks/SafeSign.Benchmarks BenchmarkDotNet speed benchmarks and thread/heap allocation justification audit (--alloc)

Building, Testing, and Benchmarking

Run these commands from src/:

# Build all projects across net10.0 and net11.0
dotnet build SafeSign.slnx -c Release

# Run TUnit test suites
dotnet test --project tests/SafeSign.Signing.Tests/SafeSign.Signing.Tests.csproj -c Release
dotnet test --project tests/SafeSign.Formats.Tests/SafeSign.Formats.Tests.csproj -c Release
dotnet test --project tests/SafeSign.Providers.Tests/SafeSign.Providers.Tests.csproj -c Release
dotnet test --project tests/SafeSign.Tests/SafeSign.Tests.csproj -c Release

# Run the allocation justification audit (verifies against allocations-explained.json)
dotnet run --project benchmarks/SafeSign.Benchmarks/SafeSign.Benchmarks.csproj -c Release -f net11.0 -- --alloc

# Run BenchmarkDotNet speed benchmarks
dotnet run --project benchmarks/SafeSign.Benchmarks/SafeSign.Benchmarks.csproj -c Release -f net11.0 -- --filter 'SafeSign.Benchmarks.SafeSignBenchmarks.*' --job short

# Publish a standalone Native AOT executable (net11.0)
dotnet publish SafeSign/SafeSign.csproj -c Release -f net11.0 -r linux-x64 -p:PublishAot=true

License

MIT — see LICENSE.

Acknowledgements

SafeSign was implemented independently from Microsoft Authenticode, PKCS #7 / CMS (RFC 5652), RFC 3161, OPC, OLE CFB, RPM v4, and vendor REST API specifications. The following projects provided inspiration:

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  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.  net11.0 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated
1.0.0 57 10/17/2026