PKI Signing Service
Pure Rust code signing engine. Authenticode for Windows PE executables, detached CMS/PKCS#7 for any file, PowerShell script signing, and RFC 3161 timestamping. No OpenSSL. No signtool.exe. One binary.
Version 0.5.3 — One binary handles CLI signing, a REST API server, and a standalone TSA server. 611 tests, 0 warnings. Deploy however you need it.
Overview
| Capability | Description | Status |
| PE Authenticode | Sign EXE, DLL, SYS, OCX, SCR, CPL, DRV with embedded PKCS#7 | Complete |
| Detached CMS | Sign any file with a .p7s detached PKCS#7 signature | Complete |
| PowerShell | PS1 scripts with Base64-encoded PKCS#7 signature blocks | Complete |
| RFC 3161 TSA | Built-in Time-Stamp Authority server on port 3318 | Complete |
| Verification | Validate Authenticode, detached CMS, and PowerShell signatures | Complete |
| Web Service | REST API for Code Signing as a Service with LDAP auth | Complete |
| MSI/CAB | Windows Installer and Cabinet archive signing | Planned |
How It Works
One binary, three modes. The same pki-sign binary runs as a CLI tool, a REST API server, or a standalone RFC 3161 TSA server.
pki-sign (single binary)
┌─────────────────────────────────────────────────────────┐
│ │
│ ┌───────────┐ ┌──────────────┐ ┌────────────┐ │
│ │ CLI │ │ Web API │ │ TSA Server │ │
│ │ │ │ (axum) │ │ (RFC 3161) │ │
│ │ sign │ │ :6447 │ │ :3318 │ │
│ │ verify │ │ │ │ │ │
│ └─────┬─────┘ └──────┬───────┘ └─────┬──────┘ │
│ │ │ │ │
│ └────────┬────────┘ │ │
│ │ │ │
│ ┌────────▼─────────┐ ┌────────────▼──────┐ │
│ │ Signer Engine │ │ TSA Token Engine │ │
│ │ │ │ │ │
│ │ PFX ──▶ key │ │ Nonce cache │ │
│ │ key ──▶ hash │ │ Serial tracking │ │
│ │ hash ─▶ sign │ │ Policy OID │ │
│ └──┬────┬────┬─────┘ └───────────────────┘ │
│ │ │ │ │
│ ┌───────┘ │ └──────────┐ │
│ │ │ │ │
│ ┌─▼──────┐ ┌──▼────────┐ ┌──▼──────────┐ │
│ │ PE │ │ PKCS#7 │ │ Timestamper │ │
│ │ Parser │ │ Builder │ │ (RFC 3161 │ │
│ │ │ │ │ │ client) │ │
│ │ parse │ │ SignedData│ │ │ │
│ │ hash │ │ DER enc │ │ failover │ │
│ │ embed │ │ sign │ │ across TSAs │ │
│ └────────┘ └───────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────┘
Signing Pipeline (6 stages)
Every signing operation follows the same pipeline. Here's what happens when you run pki-sign sign --pfx cert.pfx input.exe:
input.exe + cert.pfx
│
▼
┌──────────────────────────────────────────────────────┐
│ 1. LOAD CREDENTIALS │
│ Parse PFX ──▶ extract private key + cert chain │
│ Validate: codeSigning EKU, key usage, expiry │
│ Support: RSA, ECDSA P-256/P-384, Ed25519, ML-DSA │
└──────────────────────────┬───────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────┐
│ 2. DETECT FILE TYPE │
│ .exe/.dll/.sys ──▶ PE Authenticode │
│ .ps1 ──▶ PowerShell SIP │
│ .msi/.cab ──▶ MSI/CAB (planned) │
│ anything else ──▶ Detached CMS (.p7s) │
└──────────────────────────┬───────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────┐
│ 3. COMPUTE HASH │
│ │
│ PE files: Authenticode hash (RFC-compliant) │
│ ┌─────────────────────────────────────────┐ │
│ │ Hash entire PE, EXCLUDING: │ │
│ │ • PE checksum field (4 bytes) │ │
│ │ • Certificate table entry (8 bytes) │ │
│ │ • Data after end-of-image │ │
│ │ Pad to 8-byte alignment boundary │ │
│ └─────────────────────────────────────────┘ │
│ │
│ Other files: SHA-256 of entire content │
└──────────────────────────┬───────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────┐
│ 4. BUILD PKCS#7 SignedData │
│ │
│ ContentInfo │
│ └─ SignedData │
│ ├─ digestAlgorithms: { SHA-256 } │
│ ├─ contentInfo: SpcIndirectDataContent │
│ ├─ certificates: [ signer + chain ] │
│ └─ signerInfos: │
│ ├─ signedAttrs: │
│ │ ├─ contentType │
│ │ ├─ messageDigest │
│ │ ├─ signingTime │
│ │ └─ CMSAlgorithmProtection │
│ ├─ signature: RSA/ECDSA/Ed25519/ML-DSA │
│ └─ unsignedAttrs: (timestamp ──▶ stage 5) │
└──────────────────────────┬───────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────┐
│ 5. TIMESTAMP (optional, RFC 3161) │
│ │
│ SHA-256(signature bytes) ──▶ TimeStampReq │
│ │ │
│ ├──▶ POST to TSA server │
│ │ (DigiCert, Comodo, or built-in) │
│ │ │
│ └──▶ TimeStampToken embedded in │
│ unsignedAttrs of SignerInfo │
└──────────────────────────┬───────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────┐
│ 6. EMBED OUTPUT │
│ │
│ PE: WIN_CERTIFICATE struct at 8-byte │
│ boundary, update cert table RVA, │
│ recalculate PE checksum │
│ │
│ Detached: Write .p7s file (DER-encoded) │
│ │
│ PowerShell: Base64 PKCS#7 block appended │
│ to script text │
└──────────────────────────┬───────────────────────────┘
│
▼
signed.exe
Web API Request Flow
When running as a web service (pki-sign serve), a signing request flows through middleware layers before hitting the signer engine:
curl -F "file=@app.exe" https://sign.quantumnexus.com/api/v1/sign
│
▼
┌─ Security Headers ────────────────────────────────────┐
│ CSP, X-Content-Type-Options, X-Frame-Options │
└───────────────────────────┬───────────────────────────┘
│
┌─ LDAP Auth Middleware ────▼───────────────────────────┐
│ Extract X-Remote-User, X-Remote-Groups headers │
│ Validate user belongs to cert-group for requested │
│ signing certificate │
└───────────────────────────┬───────────────────────────┘
│
┌─ Sign Handler ────────────▼───────────────────────────┐
│ 1. Parse multipart upload (file bytes + filename) │
│ 2. Validate: size limit, allowed extension, MZ magic │
│ 3. Write to temp file (prefer /dev/shm for speed) │
│ 4. Load credentials via RwLock (hot-reloadable) │
│ 5. Call signer::sign_file_with_options() │
│ 6. Update atomic stats (files_signed, bytes, time) │
│ 7. Write audit log entry (request_id, hash, signer) │
└───────────────────────────┬───────────────────────────┘
│
▼
HTTP 200: signed binary + metadata headers
X-PKI-Sign-Hash, X-PKI-Sign-Algorithm,
X-PKI-Sign-Certificate, X-PKI-Sign-Timestamp,
X-PKI-Sign-Duration-Ms
Rust Modules (13,263 lines)
crates/pki-sign/src/
├── main.rs CLI entry point, 3 mode dispatch
├── signer.rs Signing orchestrator (1,030 lines)
├── verifier.rs Signature validation (4,500 lines)
├── config.rs TOML config loader
│
├── pe/
│ ├── parser.rs PE/COFF header parsing
│ ├── authenticode.rs Authenticode hash computation
│ └── embed.rs WIN_CERTIFICATE embedding
│
├── pkcs7/
│ ├── builder.rs CMS/PKCS#7 SignedData (hand-rolled DER)
│ ├── asn1.rs ASN.1 primitives
│ ├── enveloped.rs EnvelopedData (encryption)
│ ├── ecdh.rs ECDH key agreement
│ └── ess.rs ESS signing-certificate-v2
│
├── timestamp.rs RFC 3161 TSA client + failover
├── tsa_server.rs TSA token generation engine
├── powershell.rs PowerShell .ps1 SIP signing
│
├── web/
│ ├── mod.rs axum server setup + router
│ ├── handlers.rs Request handlers (sign, verify, admin)
│ ├── middleware.rs Auth + security middleware
│ └── audit.rs Structured audit logging
│
└── crypto/
├── hkdf.rs Key derivation
└── rsa_oaep.rs RSA-OAEP encryption
Download
Download & Install
$ curl -LO https://github.com/rayketcham-lab/PKI-Signing-Service/releases/latest/download/pki-sign
$ chmod +x pki-sign
$ sudo mv pki-sign /usr/local/bin/
$ pki-sign --version
pki-sign 0.3.0-beta.2
Or build from source:
Build from Source
$ git clone https://github.com/rayketcham-lab/PKI-Signing-Service.git
$ cd PKI-Signing-Service
$ cargo build --release
Compiling pki-sign v0.3.0-beta.2
Finished `release` profile [optimized] target(s)
$ # Static binary (musl)
$ rustup target add x86_64-unknown-linux-musl
$ cargo build --release --target x86_64-unknown-linux-musl
Quick Start
Sign a File (Authenticode)
Authenticode Signing
# Set the PFX password
$ export PKI_SIGN_PFX_PASSWORD="your-password"
# Sign a Windows executable
$ pki-sign sign --pfx cert.pfx input.exe -o signed.exe
Signed: signed.exe
Certificate: CN=QuantumNexus Code Signing, O=QuantumNexus
Algorithm: RSA-SHA256
Timestamped: true (DigiCert)
Duration: 342ms
# Sign a DLL without timestamping (offline/testing)
$ pki-sign sign --pfx cert.pfx --no-timestamp input.dll -o signed.dll
Signed: signed.dll
Timestamped: false
# Sign with a custom TSA server
$ pki-sign sign --pfx cert.pfx --tsa https://timestamp.digicert.com input.exe
Supported PE extensions: .exe, .dll, .sys, .ocx, .scr, .cpl, .drv
Verify a Signature
Signature Verification
$ pki-sign verify signed.exe
Verifying: signed.exe
Signature: VALID
Timestamped: true
Signer: CN=QuantumNexus Code Signing, O=QuantumNexus
Issuer: CN=QuantumNexus Issuing CA
Algorithm: RSA-SHA256
Digest: SHA-256
Content: SPC_INDIRECT_DATA
$ pki-sign verify --verbose signed.exe
Verifying: signed.exe
Signature: VALID
Chain Valid: true
EKU Valid: true (codeSigning)
Timestamped: true
Timestamp: 2026-03-12T14:30:00Z
Signer: CN=QuantumNexus Code Signing, O=QuantumNexus
Issuer: CN=QuantumNexus Issuing CA
Algorithm: RSA-SHA256
Digest: SHA-256
File Hash: a1b2c3d4e5f6...
Signed Hash: a1b2c3d4e5f6...
Detached CMS Signing
Create a detached PKCS#7 signature (.p7s) for any file type — PDFs, ZIPs, tarballs, firmware images, documents. The signature is stored separately from the original file.
Detached CMS Signatures
# Sign any file
$ pki-sign sign-detached --pfx cert.pfx document.pdf -o document.p7s
Signed (detached): document.p7s
File Hash: a1b2c3d4e5f6...
P7S Hash: 789abcdef012...
Timestamped: true
# Verify detached signature
$ pki-sign verify-detached --signature document.p7s document.pdf
Verifying (detached): document.pdf
Signature: VALID
Timestamped: true
Signer: CN=QuantumNexus Code Signing, O=QuantumNexus
# Sign firmware, archives, anything
$ pki-sign sign-detached --pfx cert.pfx firmware.bin -o firmware.p7s
$ pki-sign sign-detached --pfx cert.pfx release.tar.gz -o release.p7s
PowerShell Script Signing
PowerShell Signing
$ pki-sign sign --pfx cert.pfx deploy.ps1 -o deploy-signed.ps1
Signed: deploy-signed.ps1
Format: PowerShell signature block (Base64 PKCS#7)
$ pki-sign verify deploy-signed.ps1
Verifying: deploy-signed.ps1
Signature: VALID
Timestamped: true
Web Service Mode
Run as a Code Signing REST API. Upload files, get signed files back. HTTPS with TLS, LDAP authentication, audit logging, and certificate hot-reload.
Start the Web Service
# Start with config file
$ pki-sign serve --config /etc/pki/sign.toml
INFO PKI Signing Service v0.3.0-beta.2
INFO Loaded 2 signing certificates: desktop, server
INFO Auth mode: header (LDAP)
INFO TLS enabled: /etc/pki/tls/server.pem
INFO Listening on https://0.0.0.0:6447
# Quick start (defaults, port 6447)
$ pki-sign serve
# Custom bind address
$ pki-sign serve --bind 127.0.0.1 --port 8443
Configuration
# /etc/pki/sign.toml
bind_addr = "0.0.0.0"
bind_port = 6447
tls_cert = "/etc/pki/tls/server.pem"
tls_key = "/etc/pki/tls/server-key.pem"
max_upload_size = 524288000 # 500 MB
require_timestamp = true
audit_log = "/var/log/pki-sign/audit.log"
output_dir = "/var/lib/pki-sign/signed"
# Signing certificates (multiple supported)
[[cert_configs]]
name = "desktop"
pfx_path = "/etc/pki/certs/desktop.pfx"
pfx_password_env = "PFX_PASSWORD_DESKTOP"
[[cert_configs]]
name = "server"
pfx_path = "/etc/pki/certs/server.pfx"
pfx_password_env = "PFX_PASSWORD_SERVER"
# Timestamp Authority
[tsa]
urls = ["https://timestamp.digicert.com", "https://timestamp.comodoca.com"]
timeout_secs = 30
# Authentication
auth_mode = "header" # none, header, mtls, apikey
[ldap]
enabled = true
user_header = "X-Remote-User"
groups_header = "X-Remote-Groups"
email_header = "X-Remote-Email"
admin_group = "CN=PKI Admins,OU=Groups,DC=corp,DC=quantumnexus,DC=com"
[ldap.cert_groups]
desktop = "CN=Desktop Signers,OU=Groups,DC=corp,DC=quantumnexus,DC=com"
server = "CN=Server Signers,OU=Groups,DC=corp,DC=quantumnexus,DC=com"
Production: Always set auth_mode = "header" or "mtls" in production. The default "none" mode is for development only.
API Reference
Public Endpoints
| Method | Path | Description | Auth |
POST | /api/v1/sign | Upload and sign a file (multipart) | LDAP |
POST | /api/v1/sign-detached | Create detached CMS signature | LDAP |
POST | /api/v1/verify | Verify an Authenticode signature | LDAP |
POST | /api/v1/verify-detached | Verify a detached signature | LDAP |
GET | /api/v1/status | Server status and statistics | None |
GET | /api/v1/health | Health check | None |
GET | /api/v1/certificate | Public signing certificate info | None |
POST | /api/v1/report-issue | Submit a user issue report | LDAP |
Admin Endpoints
| Method | Path | Description | Auth |
GET | /admin/stats | Detailed signing statistics | Bearer / Admin |
GET | /admin/audit | Recent audit log entries | Bearer / Admin |
POST | /admin/reload | Hot-reload PFX credentials | Bearer / Admin |
GET | /admin/certs | List all loaded certificates | Bearer / Admin |
GET | /admin/certs/:name | Detailed certificate info | Bearer / Admin |
POST | /admin/certs/:name/default | Set default signing certificate | Bearer / Admin |
API Examples
Sign a File via API
$ curl -X POST https://sign.quantumnexus.com/api/v1/sign \
-H "X-Remote-User: jdoe" \
-F "file=@myapp.exe" \
-o myapp-signed.exe
# Response headers:
# X-Request-Id: a1b2c3d4-e5f6-...
# X-PKI-Sign-Hash: abcdef123456...
# X-PKI-Sign-Algorithm: RSA-SHA256
# X-PKI-Sign-Certificate: desktop
# X-PKI-Sign-Timestamp: true
# X-PKI-Sign-Duration-Ms: 342
Detached Signature via API
# Binary response (default)
$ curl -X POST https://sign.quantumnexus.com/api/v1/sign-detached \
-H "X-Remote-User: jdoe" \
-F "file=@document.pdf" \
-o document.p7s
# JSON response
$ curl -X POST https://sign.quantumnexus.com/api/v1/sign-detached \
-H "X-Remote-User: jdoe" \
-H "Accept: application/json" \
-F "file=@document.pdf"
{
"request_id": "a1b2c3d4-...",
"p7s": "<base64-encoded-signature>",
"file_hash": "abcdef123456...",
"p7s_hash": "789abc...",
"timestamped": true,
"certificate": "desktop",
"duration_ms": 287
}
Verify & Admin API
# Verify a signed file
$ curl -X POST https://sign.quantumnexus.com/api/v1/verify \
-F "file=@signed.exe"
{
"signature_valid": true,
"chain_valid": true,
"timestamped": true,
"signer_subject": "CN=QuantumNexus Code Signing, O=QuantumNexus",
"algorithm": "RSA-SHA256"
}
# Hot-reload certificates (admin)
$ curl -X POST https://sign.quantumnexus.com/admin/reload \
-H "Authorization: Bearer <admin-token>"
{ "status": "reloaded", "certificates_loaded": 2 }
# List loaded certificates (admin)
$ curl https://sign.quantumnexus.com/admin/certs \
-H "Authorization: Bearer <admin-token>"
Authentication
Four authentication modes, configured via auth_mode in sign.toml:
| Mode | How It Works | Use Case |
none |
No authentication. All endpoints open. |
Development and testing only |
header |
Reverse proxy (nginx, Apache, HAProxy) authenticates via LDAP and forwards X-Remote-User, X-Remote-Groups, X-Remote-Email headers. |
Enterprise deployments with existing LDAP/AD infrastructure |
mtls |
Mutual TLS — clients present a certificate. Server validates against a trusted CA bundle. |
Machine-to-machine, CI/CD pipelines |
apikey |
Bearer token in Authorization header. Token hash stored in config. |
Simple API access control |
LDAP Certificate Groups
Map LDAP groups to signing certificates. Users can only sign with certificates their group allows:
[ldap.cert_groups]
desktop = "CN=Desktop Signers,OU=Groups,DC=corp,DC=quantumnexus,DC=com"
server = "CN=Server Signers,OU=Groups,DC=corp,DC=quantumnexus,DC=com"
Certificate Management
Multiple signing certificates can be loaded simultaneously. Certificates can be hot-reloaded without restarting the server.
| Operation | Endpoint | Description |
| List certificates | GET /admin/certs | Names, subjects, expiry dates |
| Certificate detail | GET /admin/certs/:name | Full certificate info, key usage, EKU |
| Set default | POST /admin/certs/:name/default | Change which cert is used when no cert is specified |
| Hot-reload | POST /admin/reload | Re-read all PFX files from disk without restart |
TSA Server (RFC 3161)
Standalone Time-Stamp Authority server. Runs on IANA-assigned port 3318. Compatible with signtool.exe, openssl ts, or this tool's own --tsa flag.
TSA Server
$ pki-sign tsa serve \
--cert /etc/pki/tsa/tsa.pem \
--key /etc/pki/tsa/tsa-key.pem \
--policy-oid 1.3.6.1.4.1.56266.1.30.1 \
--port 3318
INFO TSA server listening on http://0.0.0.0:3318
INFO Policy OID: 1.3.6.1.4.1.56266.1.30.1
INFO Certificate: CN=QuantumNexus TSA
TSA Configuration
| Flag | Description | Default |
--cert | TSA signing certificate (PEM) | Required |
--key | TSA private key (PEM) | Required |
--policy-oid | TSA policy OID | Required |
--port | Bind port | 3318 |
--bind | Bind address | 0.0.0.0 |
Client Compatibility
| Client | Command |
pki-sign | pki-sign sign --tsa http://localhost:3318 ... |
signtool.exe | signtool sign /tr http://tsa.quantumnexus.com:3318 /td sha256 ... |
openssl | openssl ts -query ... | curl -X POST -d @- http://localhost:3318 |
Architecture
pki-sign (single binary)
+--------------------------------------------+
| |
CLI users ---------->| sign | sign-detached | verify | tsa |
| |
HTTP clients -------->| /api/v1/sign REST API |
(curl, CI/CD) | /api/v1/sign-detached (axum) |
| /api/v1/verify |
| |
TSA clients --------->| :3318 RFC 3161 TSA |
(signtool, openssl) | |
| +--------------------------------------+ |
| | Signer (orchestrator) | |
| | PFX --> key + cert --> hash --> sign | |
| +------------------+-------------------+ |
| | |
| +---------------+----------------+ |
| | | | |
| PE Parser PKCS#7/CMS Timestamper |
| Authenticode SignedData RFC 3161 |
| hash+embed DigestedData TSA client |
| EnvelopedData failover |
+--------------------------------------------+
Modules
| Module | Lines | Description |
pkcs7/ | ~8,200 | CMS/PKCS#7 ASN.1 builder — SignedData, DigestedData, EnvelopedData, ECDH, KEM, ESS |
verifier | ~4,500 | Signature verification — digest comparison, chain validation, EKU, counter-signers |
pe/ | ~950 | PE/COFF parser, Authenticode hash, WIN_CERTIFICATE embedding, PE checksum |
signer | ~1,050 | Signing orchestrator — PFX loading, file type detection, pipeline coordination |
web/ | ~1,400 | axum HTTP server, LDAP middleware, audit logging, admin API, GitHub reporter |
tsa_server | ~2,100 | TSA token generation engine — nonce cache, serial tracking, policy enforcement |
timestamp | ~1,600 | RFC 3161 TSA client with failover across multiple servers |
ers | ~1,300 | Evidence Record Syntax (RFC 4998) — long-term archive timestamps |
powershell | ~310 | PowerShell script signing with Base64 PKCS#7 blocks |
crypto/ | ~340 | HKDF key derivation, RSA-OAEP encryption |
Signing Pipeline
| Step | Authenticode | Detached CMS | PowerShell |
| 1. Load | Parse PFX, validate codeSigning EKU | Parse PFX, validate digitalSignature keyUsage | Parse PFX, validate codeSigning EKU |
| 2. Hash | Authenticode hash (excludes checksum, cert table, trailing data) | SHA-256 of entire file content | SHA-256 of script text (strip BOM) |
| 3. Build | SpcIndirectData + PKCS#7 SignedData | Detached PKCS#7 SignedData (no embedded content) | PKCS#7 SignedData |
| 4. Sign | RSA-PKCS#1v1.5 over signed attributes | RSA-PKCS#1v1.5 over signed attributes | RSA-PKCS#1v1.5 over signed attributes |
| 5. Timestamp | RFC 3161 counter-signature (optional) | RFC 3161 counter-signature (optional) | RFC 3161 counter-signature (optional) |
| 6. Embed | WIN_CERTIFICATE in PE cert table, update checksum | Write .p7s file | Base64 signature block appended to script |
Cryptography
All pure Rust. No OpenSSL. No liboqs. cargo-deny explicitly blocks openssl, openssl-sys, and native-tls. TLS via rustls with aws-lc-rs backend.
Signature Algorithms
| Algorithm | Standard | Status |
| RSA-PKCS#1v1.5 (SHA-256/384/512) | RFC 8017 | Supported (default) |
| RSA-PSS (SHA-256/384/512) | RFC 8017 | Supported |
| ECDSA (P-256, P-384) | FIPS 186-5 | Supported |
| Ed25519 | RFC 8032 | Supported |
| ML-DSA-44/65/87 | FIPS 204 | Supported |
| SLH-DSA-SHA2-128s/192s/256s | FIPS 205 | Supported |
Post-Quantum Cryptography
| Algorithm | Standard | Signature Size | Use Case |
| ML-DSA-44 | FIPS 204 | 2,420 bytes | General purpose (smallest PQC) |
| ML-DSA-65 | FIPS 204 | 3,309 bytes | Recommended default PQC |
| ML-DSA-87 | FIPS 204 | 4,627 bytes | Highest security level |
| SLH-DSA-SHA2-128s | FIPS 205 | 7,856 bytes | Hash-based (conservative, stateless) |
| SLH-DSA-SHA2-192s | FIPS 205 | 16,224 bytes | Higher security, stateless |
| SLH-DSA-SHA2-256s | FIPS 205 | 29,792 bytes | Maximum security, stateless |
Digest Algorithms
| Algorithm | Output | Use |
| SHA-256 | 256-bit | Default for all signing operations |
| SHA-384 | 384-bit | Higher security, supported in Authenticode and CMS |
| SHA-512 | 512-bit | Maximum classical security |
| SHA3-256 | 256-bit | NIST post-quantum migration readiness |
| SHA3-384 | 384-bit | SHA-3 family |
| SHA3-512 | 512-bit | SHA-3 family |
Security
| Feature | Description |
| No OpenSSL | Pure Rust crypto (rsa, p256, p384, ed25519-dalek, sha2, aes-gcm). TLS via rustls. |
| OpenSSL Banned | cargo-deny blocks openssl, openssl-sys, native-tls at build time. |
| Key Zeroization | Private keys wrapped in Zeroizing<> for secure memory cleanup. |
| Audit Trail | Every sign/verify logged with request ID, file hash, signer, timestamp, duration. |
| Security Headers | Applied via middleware on all HTTP responses. |
| CI Hardening | cargo-audit + cargo-deny on every push. Pinned GitHub Action SHAs. |
| Static Binary | musl target for minimal attack surface. |
| 531 Tests | Comprehensive unit tests across all modules. |
Production Deployment
systemd Service
# /etc/systemd/system/pki-sign.service
[Unit]
Description=PKI Signing Service
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/pki-sign serve --config /etc/pki/sign.toml
Restart=on-failure
User=pki-sign
Group=pki-sign
EnvironmentFile=/etc/pki/sign.env
[Install]
WantedBy=multi-user.target
Service Management
$ sudo systemctl enable pki-sign
$ sudo systemctl start pki-sign
$ sudo systemctl status pki-sign
● pki-sign.service - PKI Signing Service
Loaded: loaded (/etc/systemd/system/pki-sign.service; enabled)
Active: active (running)
Main PID: 12345 (pki-sign)
Tasks: 8 (limit: 4915)
Memory: 24.0M
CPU: 120ms
Environment File
# /etc/pki/sign.env
PFX_PASSWORD_DESKTOP=change-me-desktop
PFX_PASSWORD_SERVER=change-me-server
PKI_SIGN_LOG_LEVEL=info
Platform Support
| Platform | Architecture | Status |
| Rocky Linux / RHEL / CentOS 8+ | x86_64 | Supported |
| Ubuntu 18.04+ | x86_64 | Supported |
| Debian 10+ | x86_64 | Supported |
| Amazon Linux 2+ | x86_64 | Supported |
| Alpine Linux 3.12+ | x86_64 | Supported |
CLI Reference
pki-sign 0.3.0-beta.2
PKI Signing Service - Pure Rust Code Signing Engine
USAGE:
pki-sign <COMMAND>
COMMANDS:
serve Start the web server for Code Signing as a Service
sign Sign a file using Authenticode
sign-detached Create a detached CMS/PKCS#7 signature (.p7s)
verify Verify an Authenticode signature
verify-detached Verify a detached CMS/PKCS#7 signature
setup Interactive setup wizard
tsa Time-Stamp Authority (RFC 3161) server commands
help Print help
| Flag | Command | Description |
--pfx | sign, sign-detached | Path to PFX/PKCS#12 certificate file |
--password-env | sign, sign-detached | Env var with PFX password (default: PKI_SIGN_PFX_PASSWORD) |
--tsa | sign, sign-detached | TSA URL for timestamping |
--no-timestamp | sign, sign-detached | Skip timestamping |
-o, --output | sign, sign-detached | Output file path |
--verbose | verify, verify-detached | Show detailed certificate info |
--signature | verify-detached | Path to .p7s signature file |
-c, --config | serve | Config file path (default: /etc/pki/sign.toml) |
-p, --port | serve, tsa serve | Bind port |
--bind | serve, tsa serve | Bind address (default: 0.0.0.0) |