cryptography-signing-verification

Digital signature creation, verification, and chain of trust for documents, code, and artifacts

Digital Signing and Verification

Scope: Digital signatures, code signing, artifact verification, chain of trust, timestamping, HSM integration Lines: ~450 Last Updated: 2025-10-27 Format Version: 1.0 (Atomic)


When to Use This Skill

Activate this skill when:

Core Concepts

What are Digital Signatures?

Digital signatures provide:

How it works:

1. Hash the data → SHA-256 hash
2. Encrypt hash with private key → Digital signature
3. Distribute data + signature + public key

Verification:
1. Hash the received data
2. Decrypt signature with public key → Original hash
3. Compare hashes → Match = authentic, Mismatch = tampered

Signature Algorithms

| Algorithm | Key Type | Security | Use Case | |-----------|----------|----------|----------| | RSA-PSS | RSA (2048-4096 bit) | High | General purpose, FIPS compliance | | ECDSA | ECC (P-256, P-384) | High | Mobile, embedded, space-constrained | | EdDSA (Ed25519) | Curve25519 | Highest | Modern applications, performance | | RSA-PKCS#1 v1.5 | RSA | Moderate | Legacy (vulnerable to attacks) | | DSA | Discrete Log | Low | Deprecated (use ECDSA instead) |

Recommendations:


Signature Formats

PKCS#7 / CMS (Cryptographic Message Syntax)

Standard: RFC 5652 Use case: Document signing, S/MIME email

# Sign file with PKCS#7
openssl smime -sign -in document.txt \
    -out document.p7s \
    -signer cert.pem \
    -inkey private.key

# Verify PKCS#7 signature
openssl smime -verify -in document.p7s \
    -CAfile ca-cert.pem \
    -out document.txt

JWS (JSON Web Signature)

Standard: RFC 7515 Use case: API tokens, JSON data signing

import jwt

# Sign JSON data
payload = {"user": "alice", "role": "admin"}
token = jwt.encode(payload, private_key, algorithm='RS256')

# Verify signature
decoded = jwt.decode(token, public_key, algorithms=['RS256'])

XML-DSig (XML Digital Signature)

Standard: W3C Recommendation Use case: SAML, SOAP, XML documents

<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
  <SignedInfo>
    <CanonicalizationMethod Algorithm="..."/>
    <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
    <Reference URI="">
      <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
      <DigestValue>...</DigestValue>
    </Reference>
  </SignedInfo>
  <SignatureValue>...</SignatureValue>
  <KeyInfo>...</KeyInfo>
</Signature>

Detached vs Embedded Signatures

Detached (separate file):

# Create detached signature
gpg --detach-sign --armor file.tar.gz
# Produces: file.tar.gz.asc

# Verify
gpg --verify file.tar.gz.asc file.tar.gz

Embedded (within file):

# Create embedded signature
gpg --sign file.tar.gz
# Produces: file.tar.gz.gpg (contains both data and signature)

# Verify and extract
gpg file.tar.gz.gpg

Code Signing

macOS / iOS (Apple Developer)

Requirements:

Sign application:

# Sign app bundle
codesign --sign "Developer ID Application: Your Name" \
    --deep \
    --force \
    --options runtime \
    --timestamp \
    YourApp.app

# Verify signature
codesign --verify --verbose=4 YourApp.app

# Display signature details
codesign --display --verbose=4 YourApp.app

# Notarize (required for macOS 10.15+)
xcrun notarytool submit YourApp.zip \
    --apple-id "your@email.com" \
    --password "app-specific-password" \
    --team-id "TEAM_ID"

Windows (Authenticode)

Requirements:

Sign executable:

# Sign with timestamp
signtool sign /f certificate.pfx /p password /fd SHA256 \
    /tr http://timestamp.digicert.com /td SHA256 \
    application.exe

# Verify signature
signtool verify /pa application.exe

# Display signature details
signtool verify /v /pa application.exe

Android (APK Signing)

V1 (JAR signing) - Legacy:

jarsigner -keystore my-release-key.jks \
    -signedjar app-signed.apk \
    app-unsigned.apk \
    my-key-alias

V2/V3/V4 (APK Signature Scheme) - Modern:

# Sign with apksigner (recommended)
apksigner sign --ks my-release-key.jks \
    --ks-key-alias my-key-alias \
    --out app-signed.apk \
    app-unsigned.apk

# Verify
apksigner verify --verbose app-signed.apk

Container Signing (Sigstore / Cosign)

Sigstore

Sigstore provides:

Install cosign:

# macOS
brew install cosign

# Linux
wget https://github.com/sigstore/cosign/releases/download/v2.2.0/cosign-linux-amd64
chmod +x cosign-linux-amd64
sudo mv cosign-linux-amd64 /usr/local/bin/cosign

Keyless Signing (OIDC)

Sign container image:

# Sign with OIDC (Google, GitHub, Microsoft)
cosign sign ghcr.io/myorg/myapp:v1.0.0

# Interactive OIDC flow opens browser
# Ephemeral keys generated and certificate issued by Fulcio
# Signature recorded in Rekor transparency log

Verify:

# Verify with certificate identity
cosign verify ghcr.io/myorg/myapp:v1.0.0 \
    --certificate-identity=user@example.com \
    --certificate-oidc-issuer=https://accounts.google.com

Key-Based Signing

Generate signing key:

# Generate key pair
cosign generate-key-pair

# Produces:
# - cosign.key (private key, encrypted)
# - cosign.pub (public key)

Sign and verify:

# Sign with key
cosign sign --key cosign.key ghcr.io/myorg/myapp:v1.0.0

# Verify with public key
cosign verify --key cosign.pub ghcr.io/myorg/myapp:v1.0.0

Sign Artifacts (Not Containers)

Sign files:

# Sign arbitrary file
cosign sign-blob --key cosign.key file.tar.gz > file.tar.gz.sig

# Verify
cosign verify-blob --key cosign.pub \
    --signature file.tar.gz.sig \
    file.tar.gz

Timestamping

Why Timestamp Signatures?

Problem: Signatures become invalid when signing certificate expires.

Solution: Timestamp Authority (TSA) provides proof that signature existed at specific time.

Timestamping flow:

1. Sign document with private key
2. Send signature to TSA
3. TSA signs signature with timestamp
4. Signature valid even after certificate expires (as long as it was valid at signing time)

RFC 3161 Timestamp Protocol

Request timestamp:

# Sign with timestamp (OpenSSL)
openssl ts -query -data document.txt -sha256 -cert -out request.tsq

# Send to TSA
curl -H "Content-Type: application/timestamp-query" \
    --data-binary @request.tsq \
    http://timestamp.digicert.com > response.tsr

# Verify timestamp
openssl ts -verify -data document.txt -in response.tsr \
    -CAfile tsa-cert.pem

Popular TSAs:


GPG / PGP Signing

Generate Key Pair

# Generate GPG key
gpg --full-generate-key
# Choose: RSA and RSA (default), 4096 bits, expires in 1 year

# List keys
gpg --list-keys
gpg --list-secret-keys

Sign Files

# Detached ASCII signature
gpg --detach-sign --armor file.tar.gz
# Creates: file.tar.gz.asc

# Verify
gpg --verify file.tar.gz.asc file.tar.gz

# Embedded signature
gpg --sign file.tar.gz
# Creates: file.tar.gz.gpg

# Clear-sign (text with inline signature)
gpg --clearsign message.txt

Git Commit Signing

Configure Git:

# Set signing key
git config --global user.signingkey YOUR_KEY_ID

# Enable signing by default
git config --global commit.gpgsign true
git config --global tag.gpgsign true

Sign commits:

# Sign commit
git commit -S -m "Signed commit"

# Sign tag
git tag -s v1.0.0 -m "Signed release"

# Verify
git verify-commit HEAD
git verify-tag v1.0.0

Certificate Chains and Trust

Chain of Trust

┌─────────────────────┐
│ Root CA             │ ← Self-signed, offline, highly trusted
└──────────┬──────────┘
           │ signs
┌──────────▼──────────┐
│ Intermediate CA     │ ← Operational CA
└──────────┬──────────┘
           │ signs
┌──────────▼──────────┐
│ Code Signing Cert   │ ← End-entity certificate
└─────────────────────┘
           │
           ▼
      Signed Code

Verify Certificate Chain

OpenSSL:

# Verify certificate chain
openssl verify -CAfile root.pem -untrusted intermediate.pem cert.pem

# Extract certificate from signed binary
openssl pkcs7 -inform DER -in signature.p7s -print_certs -out cert.pem

# Check certificate validity
openssl x509 -in cert.pem -noout -dates
openssl x509 -in cert.pem -noout -subject -issuer

Certificate Revocation

Check revocation status:

CRL (Certificate Revocation List):

# Download CRL
wget http://crl.example.com/revoked.crl

# Check if certificate is revoked
openssl crl -inform DER -in revoked.crl -noout -text | grep -A1 "Serial Number"

OCSP (Online Certificate Status Protocol):

# Query OCSP responder
openssl ocsp -issuer intermediate.pem \
    -cert cert.pem \
    -url http://ocsp.example.com \
    -CAfile root.pem

HSM Integration

Why Use HSM for Signing?

Benefits:

PKCS#11 Interface

Sign with HSM (PKCS#11):

from PyKCS11 import *

pkcs11 = PyKCS11Lib()
pkcs11.load('/usr/lib/softhsm/libsofthsm2.so')  # HSM library

# Open session
session = pkcs11.openSession(slot)
session.login('user_pin')

# Find signing key
key = session.findObjects([(CKA_CLASS, CKO_PRIVATE_KEY)])[0]

# Sign data
mechanism = Mechanism(CKM_RSA_PKCS, None)
signature = session.sign(key, data, mechanism)

session.logout()

AWS CloudHSM:

# Configure CloudHSM
/opt/cloudhsm/bin/configure -a <cluster-ip>

# Sign with pkcs11-tool
pkcs11-tool --module /opt/cloudhsm/lib/libcloudhsm_pkcs11.so \
    --login --pin <user-pin> \
    --sign --mechanism RSA-PKCS \
    --input-file data.bin \
    --output-file signature.bin

Compliance

FIPS 186-4 (Digital Signature Standard)

Approved algorithms:

Requirements:

eIDAS (EU Electronic Identification and Trust Services)

Signature levels:

Requirements:

Common Criteria

Evaluation Assurance Levels (EAL):


Best Practices

1. Signature Algorithm Selection

# ✅ Good: Modern, secure algorithms
EdDSA (Ed25519)
ECDSA P-256
RSA-PSS 3072+

# ❌ Bad: Deprecated or weak
RSA-PKCS#1 v1.5
DSA
MD5 hashing

2. Always Timestamp Signatures

# ✅ Good: Include timestamp
codesign --timestamp --sign "Developer ID" app.app
signtool sign /tr http://timestamp.digicert.com /td SHA256 app.exe

# ❌ Bad: No timestamp (signature expires with certificate)
codesign --sign "Developer ID" app.app

3. Verify Signatures Before Use

# ✅ Good: Always verify before execution
cosign verify --key cosign.pub image:tag
gpg --verify file.tar.gz.asc file.tar.gz

# ❌ Bad: Trust without verification
docker run unverified-image
tar -xzf unsigned-archive.tar.gz

4. Protect Private Keys

# ✅ Good: Use HSM, encrypted keys, access control
- Store signing keys in HSM
- Encrypt private keys (gpg, openssl)
- Require authentication for signing
- Audit all signing operations

# ❌ Bad: Unprotected keys
- Private key in Git repository
- Unencrypted key on disk
- Shared signing credentials

Troubleshooting

Issue 1: Signature Verification Fails

Check:

# Certificate expired?
openssl x509 -in cert.pem -noout -dates

# Wrong public key?
openssl x509 -in cert.pem -pubkey -noout > pubkey.pem

# Certificate revoked?
openssl ocsp -issuer ca.pem -cert cert.pem -url http://ocsp.example.com

# Data modified after signing?
sha256sum file.tar.gz  # Compare with original hash

Issue 2: Code Signing Rejected by OS

macOS Gatekeeper:

# Check notarization status
spctl --assess --verbose=4 YourApp.app

# Check signature
codesign --verify --deep --strict --verbose=2 YourApp.app

Windows SmartScreen:

# Verify certificate chain
signtool verify /pa /v application.exe

# Check timestamp
signtool verify /pa /tw application.exe

Related Skills


Level 3: Resources

Location: ~/.hanzo/skills/cryptography/signing-verification/resources/

This skill includes comprehensive Level 3 resources for production signing and verification implementations.

REFERENCE.md (~3,500 lines)

Comprehensive technical reference covering:

Scripts (3 production-ready tools)

validate_signatures.py (650+ lines) - Multi-format signature validator

sign_artifacts.py (750+ lines) - Universal artifact signing tool

audit_signing_keys.py (600+ lines) - Signing key lifecycle auditor

Examples (8 production-ready implementations)

python/rsa_pss_signing.py - RSA-PSS document signing

python/ecdsa_signing.py - ECDSA code signing with verification

go/ed25519_artifacts.go - EdDSA artifact signing

python/sigstore_cosign.py - Sigstore cosign integration

python/hsm_signing.py - HSM-backed signing (PKCS#11)

python/timestamp_authority.py - Timestamp authority integration

docker-compose/signing-infrastructure.yml - Container signing infrastructure

config/compliance-validation.yaml - Compliance policy configuration

Quick Start

# Validate signature
cd ~/.hanzo/skills/cryptography/signing-verification/resources/scripts
./validate_signatures.py --file document.p7s --check-chain --check-revocation

# Sign artifact with timestamp
./sign_artifacts.py --file release.tar.gz --key signing.key --timestamp --format pkcs7

# Audit signing keys
./audit_signing_keys.py --keystore /etc/pki/signing --compliance FIPS --json

# Run Python examples
cd ../examples/python
pip install cryptography PyKCS11 jwt sigstore
python rsa_pss_signing.py sign document.txt
python ecdsa_signing.py verify signature.bin
python sigstore_cosign.py keyless-sign myimage:v1.0.0

# View comprehensive reference
cd ../
less REFERENCE.md

Integration Notes

CI/CD Integration:

# .github/workflows/sign-release.yml
- name: Sign Release Artifacts
  run: |
    ./scripts/sign_artifacts.py \
      --batch-file artifacts.txt \
      --key ${{ secrets.SIGNING_KEY }} \
      --timestamp \
      --json

Verification in Deployment:

# Verify signatures before deployment
./scripts/validate_signatures.py \
  --batch-file production-artifacts.txt \
  --check-revocation \
  --compliance FIPS \
  --fail-on-error

Quick Reference

# OpenSSL signing
openssl dgst -sha256 -sign private.key -out signature.bin file.txt
openssl dgst -sha256 -verify public.key -signature signature.bin file.txt

# GPG signing
gpg --detach-sign --armor file.tar.gz
gpg --verify file.tar.gz.asc file.tar.gz

# Cosign (container)
cosign sign --key cosign.key image:tag
cosign verify --key cosign.pub image:tag

# Code signing (macOS)
codesign --sign "Developer ID" --timestamp app.app
codesign --verify --verbose=4 app.app

# Code signing (Windows)
signtool sign /f cert.pfx /p password /tr http://timestamp.digicert.com /td SHA256 app.exe
signtool verify /pa app.exe

Last Updated: 2025-10-27