A VectorGuard Labs Product

Protect the Digital Secrets
That Keep Your Business Running.

PyHSM is a production-ready software Key Management Service (KMS) that securely stores encryption keys, signs data, manages key lifecycles, and keeps an auditable record of every operation so your applications are safer by design.

Stop embedding encryption keys in your code.

Stop building your own key management from scratch.

Give your applications a secure vault for their most valuable secrets.

Think of PyHSM as a bank vault for your software's secrets — open source, no hardware required.
pip install vectorguard-pyhsm

Every Application Has Secrets

If those secrets are compromised, attackers can impersonate users, steal money, or decrypt sensitive information.

🔑 Encryption keys
🔒 API tokens
📄 Digital certificates
✏️ Signing keys
🔔 Password reset tokens
🛡️ Session secrets

Most teams store these secrets in environment variables, config files, or worse — hardcoded in source code. One breach exposes everything.

PyHSM gives those secrets a secure home — encrypted at rest, access-controlled, audited, and lifecycle-managed.

Built for Real-World Applications

See how teams use PyHSM to protect what matters most.

Online Banking & Fintech

Protect the encryption keys securing customer accounts, transaction signatures, and payment data.

Healthcare

Safeguard patient data, digital identities, and comply with HIPAA encryption requirements.

Cryptocurrency & Web3

Sign blockchain transactions without ever exposing private keys to application code or disk.

SaaS Platforms

Securely store API credentials, webhook secrets, and per-tenant encryption keys at scale.

AI & ML Platforms

Protect model credentials, inference API secrets, and sensitive customer data used in pipelines.

IoT & Edge

Manage device certificates and signing keys across distributed deployments without cloud dependency.

Why Not Use the cryptography Library?

Python's cryptography library gives you primitives. PyHSM gives you a complete key management system.

Capability cryptography library PyHSM
Encrypt / Decrypt Yes (you manage keys yourself) Yes (keys managed for you)
Key storage & encryption at rest Not included Double-encrypted keystore (AES-GCM + AES-KWP)
Key rotation Build it yourself Built-in with version tracking
Access control & caller identity Not included Caller ACLs, rate limits, operation caps
Audit logging Not included HMAC-chained tamper-evident log
Key lifecycle policies Not included Expiration, archival, destruction
Process isolation Not included Separate OS process for key material
Memory zeroization Not included Deterministic byte-by-byte clearing
Shamir secret sharing Not included M-of-N key reconstruction

The cryptography library is a toolbox. PyHSM is the locksmith. PyHSM knows how to use the tools securely, manages the keys, tracks who accessed what, and ensures nothing is left exposed.

Why Teams Choose PyHSM

A complete key management system, not a wrapper around a single crypto library.

AES-256-GCM Encryption

Industry-standard authenticated encryption with Argon2id key derivation following OWASP recommendations.

Shamir Secret Sharing

Split master keys into shares with configurable thresholds. No single point of compromise.

HMAC-Chained Audit Logs

Tamper-evident audit trail with cryptographic chaining. Every operation is recorded and verifiable.

Dual Implementation

Full feature parity across Python and TypeScript. Use whichever fits your stack.

Key Rotation & Policies

Built-in key expiration, operation limits, caller ACLs, and automated rotation support.

Self-Test on Startup

Known-Answer Tests against RFC vectors run automatically. Crypto primitives are verified before any operation.

Support Plans

PyHSM is free and open source. Priority support gives you direct access to the creator for implementation guidance, code review, and more.

Priority Support
$1,500 /month

For teams building on PyHSM that want ongoing expert guidance and priority access to the creator.

  • Private communication channel (Slack or email)
  • Next business day response guarantee
  • Implementation guidance & architecture review
  • Code review pre-notification
  • Integration code review & config validation
  • Key rotation policy consulting
Ideal for: Startups and mid-stage teams in web3, fintech, and SaaS that need reliable access to a key management expert.
Get Started

How It Works

PyHSM is free to use. Support plans give you a direct line to the expert behind the code.

1

Install PyHSM

Clone the repo or pip install vectorguard-pyhsm. The code is MIT licensed, so use it freely in any project.

2

Build With Confidence

Full documentation, test suite, README.md, and OPERATIONS.md cover every security decision. Read the source. Audit it. It's your code now.

3

Get Expert Support

When you need implementation guidance or code review, get Priority Support or request a one-time consultation.

4

Ship Securely

Deploy with confidence knowing the creator of PyHSM is available to review, advise, and help when things get complex.

Full Demo

A complete walkthrough showing how PyHSM encrypts a private key, splits the master password with Shamir secret sharing, and recovers it using the default Anvil private key.

Note: The private key used in this demo is 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80. This is the default Anvil (Foundry) test private key. Never use test keys in production.
1

Encrypt the Private Key

First, we create a keystore and generate an AES-256 encryption key inside it. Then we encrypt the Anvil private key using that key. The master password protects the entire keystore. Without it, the encrypted data is useless.

Create keystore and generate an AES-256 encryption key
vectorguard-pyhsm --store demo-keystore.enc generate vault-key --type aes-256 -p "demo-master-password"
# → Generated aes-256 key: vault-key
Encrypt the private key
vectorguard-pyhsm --store demo-keystore.enc encrypt vault-key \
  -d "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" \
  -p "demo-master-password"
# → 0200000001f383ad67000000009a3d48dfa78fe787...(ciphertext)

The private key is now encrypted inside the keystore. The ciphertext output is the AES-256-GCM encrypted form of the key; it's completely useless without the master password. Even if an attacker steals the keystore file, they cannot recover the private key.

2

Shard with Shamir 3-of-5

Now we eliminate the single point of failure. Instead of one person holding the master password, we split it into 5 shares using Shamir's Secret Sharing. Any 3 shares can reconstruct the password, but 2 or fewer reveal zero information. This is mathematically proven, not just computationally hard.

First, convert the master password to its hex representation
# Each ASCII character becomes its 2-digit hex code:
# 'd' = 64, 'e' = 65, 'm' = 6d, 'o' = 6f, '-' = 2d, 'm' = 6d, 'a' = 61, ...
#
# Full breakdown of "demo-master-password":
#   d=64  e=65  m=6d  o=6f  -=2d  m=6d  a=61  s=73
#   t=74  e=65  r=72  -=2d  p=70  a=61  s=73  s=73
#   w=77  o=6f  r=72  d=64
#
# You can verify this with Python:
python3 -c "print('demo-master-password'.encode().hex())"
# → 64656d6f2d6d61737465722d70617373776f7264

The split command operates on hex-encoded byte strings. The hex value 64656d6f2d6d61737465722d70617373776f7264 is simply the ASCII encoding of "demo-master-password" represented in hexadecimal. Each character maps to its hex byte value (e.g., 'd' → 64, 'e' → 65, 'm' → 6d). This is not encryption or hashing; it's a direct, reversible encoding that the Shamir split algorithm requires as input.

Now split the hex-encoded password into 5 shares (3 required to reconstruct)
vectorguard-pyhsm split -k 3 -n 5 -s "64656d6f2d6d61737465722d70617373776f7264"

# → Share 1: {"index": 1, "data": "d18a992fabfb5eb8e53689284a0f69f734d3312b"}
# → Share 2: {"index": 2, "data": "0985e4adb3d6b7e7c3e9a8fba6d4a5958b7628ae"}
# → Share 3: {"index": 3, "data": "bc6a10ed3540882c52ba53fe9cbabf11c8ca6be1"}
# → Share 4: {"index": 4, "data": "ce2a97e3180640240fce01c779af615d67ae9ba0"}
# → Share 5: {"index": 5, "data": "7bc563a39e907fef9e9dfac243c17bd92412d8ef"}

Distribute one share to each of 5 custodians. No single custodian (or even any 2) can reconstruct the password. Each share should be stored in a separate location — different password managers, different physical safes, or different geographic regions depending on your threat model.

3

What Happens Next — Recovery

When you need to decrypt (sign a transaction, recover the key, rotate credentials, etc.), you gather any 3 of the 5 custodians. Each provides their share, and the master password is reconstructed.

1 Gather any 3 of the 5 custodians
2 Each provides their share
3 Reconstruct the master password:
Reconstruct the master password from any 3 shares
vectorguard-pyhsm reconstruct \
  --share '{"index": 1, "data": "d18a992fabfb5eb8e53689284a0f69f734d3312b"}' \
  --share '{"index": 3, "data": "bc6a10ed3540882c52ba53fe9cbabf11c8ca6be1"}' \
  --share '{"index": 5, "data": "7bc563a39e907fef9e9dfac243c17bd92412d8ef"}'
# → 64656d6f2d6d61737465722d70617373776f7264 (hex of "demo-master-password")

Notice we used shares 1, 3, and 5 (any combination of 3 works). The reconstruction outputs the hex-encoded master password which is then used to unlock the keystore.

4

Decrypt and Recover the Private Key

With the reconstructed master password, unlock the keystore and decrypt the original private key.

Use the reconstructed password to decrypt
vectorguard-pyhsm --store demo-keystore.enc decrypt vault-key \
  -d "0200000001f383ad67...(ciphertext)" \
  -p "demo-master-password"
# → 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80

The original private key is recovered exactly as it was. The audit log records every operation with HMAC-chained tamper detection; so you have a permanent, verifiable record of who decrypted what and when.

Security Properties

The private key is never stored in plaintext anywhere

The master password doesn't exist as a single secret (it's split across 5 people)

Any 2 or fewer shares reveal zero information (information-theoretic, not computational)

Every encrypt/decrypt operation is permanently recorded in the audit log

If someone tampers with the keystore file, PyHSM detects it and refuses to open

Built for Security Teams

Open Source

MIT licensed. Read every line. Security-conscious developers trust what they can verify.

No Vendor Lock-In

You own the code, the keys, and the deployment. No cloud dependency, no per-operation fees.

Battle-Tested Primitives

AES-256-GCM, Argon2id, HKDF, HMAC-SHA256. No custom cryptography — only proven standards.

Compliance-Ready

HMAC-chained audit logs, caller ID tracking, and architecture review sessions provide evidence for auditors.

Frequently Asked Questions

Architecture, security, and design questions about PyHSM.

Vault solves a different problem at a different scale. It's a secrets management platform — it manages database credentials, API tokens, PKI certificates, and dynamic secrets across an organization. It requires Consul for HA, needs dedicated operators, and the Enterprise license for features like HSM auto-unseal costs six figures.

PyHSM is a focused key management library. You pip install it, import it in your code, and you have key generation, signing, encryption, and audit logging in five lines. There's no cluster to manage, no Consul dependency, no operator UI to secure, no HCL policy language to learn.

Use Vault if: You need org-wide secrets management with 50 services and dynamic credential rotation.

Use PyHSM if: You need to encrypt data or sign transactions from your application with proper key lifecycle management — without the operational overhead.

Additional distinction: Vault's Transit engine doesn't support secp256k1. If you're signing Ethereum or Bitcoin transactions, Vault can't do it natively. PyHSM can.

Short answer: PyHSM doesn't claim the key is impossible to extract. It makes extraction as difficult as possible within software constraints, and makes all access auditable.

The layers of defense:

  1. Double-encrypted at rest. The keystore file is AES-256-GCM encrypted (master password → Argon2id → HKDF → encryption key). Each individual key inside is additionally wrapped with AES-KWP (RFC 5649).
  2. Never in memory as immutable objects. Key material is stored as mutable bytearray (Python) or Buffer (Node.js) and deterministically zeroized byte-by-byte after each operation.
  3. The API never returns raw key bytes. You call hsm.sign() and get a signature back. The private key is unwrapped internally, used, and zeroized.
  4. Process isolation mode puts the keys in a separate OS process. Even a full RCE in your application can't read the HSM process's address space without a kernel exploit.
  5. Export is explicit and audited. export_jwk() exists for interoperability, but it's a deliberate call that gets logged in the audit trail.

What PyHSM cannot prevent: A root-level attacker with memory debugging tools attached to the running HSM process during the microseconds of signing. That's what hardware HSMs solve with a physical trust boundary.

Key rotation generates a new key version and archives the old one. Old ciphertexts remain decryptable because the version number is embedded in the ciphertext format.

Mechanically:

  1. New random key material is generated (os.urandom(32))
  2. It's wrapped with AES-KWP before storage
  3. The previous version is marked archived: true
  4. New encrypt() calls use the new version
  5. decrypt() reads the version prefix from the ciphertext header and selects the matching key version automatically

This means you can rotate keys without re-encrypting your entire database. Old data decrypts with the old version, new data uses the new version.

Rotation is currently supported for AES keys. Asymmetric keys (EC, RSA, Ed25519) don't rotate in-place — you generate a new key ID and transition callers.

Each audit entry contains an HMAC that chains to the previous entry — similar to a blockchain of log records.

To tamper with entry N, an attacker would need to recompute the HMAC for entries N, N+1, N+2, ... all the way to the end. And to compute any HMAC, they need the audit HMAC key — which is derived from the master password via HKDF.

Verification walks the chain and checks every HMAC against its predecessor. If any entry was modified, inserted, or deleted, the chain breaks and verification reports the exact sequence number where corruption occurred.

The log is append-only — entries are never modified or deleted during normal operation. Every operation (including denied ones) is recorded with timestamp, operation type, key ID, caller ID, and success/failure status.

PyHSM provides the following guarantees:

  • Confidentiality at rest: AES-256-GCM / AES-256-GCM-SIV (NIST SP 800-38D / RFC 8452)
  • Key wrapping: AES-KWP (RFC 5649)
  • Key derivation: Argon2id (64MB/3 passes) → HKDF-Expand (RFC 9106 / RFC 5869)
  • Authentication: Encrypt-then-MAC (HMAC-SHA256) — proven-secure composition
  • Nonce safety: Hybrid nonce (random+counter+random) / GCM-SIV — birthday bound eliminated
  • Signing (ECDSA): SHA-256 (P-256, secp256k1), SHA-384 (P-384), SHA-512 (P-521) — FIPS 186-5
  • Signing (EdDSA): Ed25519 (RFC 8032)
  • Constant-time comparison: Timing side-channel resistant
  • Audit integrity: HMAC-chained append-only log — tamper-evident

What is explicitly NOT guaranteed: Protection against kernel-level access, CPU side-channel attacks, physical access to hardware, or compromised underlying crypto libraries.

PyHSM defends against five classes of threat actors:

  • T1: Network attacker — Process isolation; app never holds keys
  • T2: App-level code execution — Rate limiting, ACLs, operation caps, process isolation
  • T3: Filesystem read access — Double-encryption (AES-GCM + AES-KWP), Argon2id
  • T4: Malicious insider — Shamir M-of-N, tamper detection, audit log
  • T5: Root/kernel accessLIMITED — deterministic zeroization reduces window only

In-scope: Filesystem theft, application compromise, unauthorized key usage, silent key abuse, insider threats with partial access, keystore tampering, audit log manipulation.

Out-of-scope (acknowledged): Root attacker with debugger during signing, CPU side-channels, physical hardware access, compromised OS kernel.

It depends on your constraints. Neither is universally better.

Use AWS KMS if: You're in a regulated environment requiring FIPS certification, you're already all-in on AWS, you don't need secp256k1/Ed25519, and you're fine with per-operation costs and network latency.

Use PyHSM if: You need secp256k1/Ed25519 signing (blockchain), you want to avoid per-operation costs at scale, you require data sovereignty, you want zero vendor lock-in, or your latency budget can't tolerate network round-trips for every operation.

Key differences: AWS KMS costs $1/key/month + $0.03/10K API calls and adds 5–50ms latency per operation. PyHSM is free (MIT), runs locally with sub-millisecond crypto latency, supports secp256k1 and Ed25519 (which KMS doesn't), and has no vendor lock-in — you can export keys in standard JWK format.

They're not mutually exclusive: Some teams use AWS KMS for general infrastructure encryption and PyHSM specifically for blockchain transaction signing where AWS has no native support.

Process isolation is the highest security configuration PyHSM offers within software constraints. It separates key material into a dedicated OS process that communicates with your application over a Unix domain socket (IPC).

Why it matters: Without isolation, an attacker who achieves Remote Code Execution (RCE) in your application can read anything in that process's memory — including any key material that happens to be unwrapped at that moment. With process isolation, the keys live in a separate address space. The attacker would need a kernel exploit to cross that boundary.

How it works:

  1. The HSM process starts independently, loads the encrypted keystore, and listens on a Unix socket (e.g., /run/pyhsm/pyhsm.sock).
  2. Your application connects as a client and sends operation requests (encrypt, sign, rotate, etc.) over the socket.
  3. The HSM process unwraps the key, performs the cryptographic operation, zeroizes the key from memory, and returns only the result (ciphertext, signature, etc.).
  4. Your application never sees raw key bytes — it only receives operation outputs.

Authentication: The client authenticates each request using an HMAC over the message payload with a shared caller secret (PYHSM_CALLER_SECRET). This prevents other processes on the same host from issuing unauthorized commands to the socket.

Trade-offs: Process isolation adds IPC latency (typically <1ms on localhost) and operational complexity (two processes to manage instead of one). For most deployments, this is negligible compared to the security gain.

In production, you don't want a single person (or a single .env file) holding the master password that unlocks all keys. PyHSM implements Shamir's Secret Sharing over GF(256) to split the master password into N shares where any K shares can reconstruct it — but K-1 or fewer reveal zero information about the secret.

Typical setup (3-of-5):

  1. During initial deployment, the security team generates 5 shares from the master password.
  2. Each share is distributed to a different key custodian (stored offline, in separate locations, or in separate password managers).
  3. At startup, 3 custodians provide their shares to unlock the HSM. No single custodian can unlock it alone.

Security properties:

  • K-1 shares reveal nothing. Even if an attacker steals 2 of 5 shares (in a 3-of-5 scheme), they gain zero knowledge about the master password. This is mathematically proven, not just computationally hard.
  • Intermediate buffers are zeroized. After reconstruction, the share data and intermediate polynomial evaluation buffers are deterministically cleared from memory.
  • Works with environment variables. In containerized deployments, shares can be injected via PYHSM_SHARES as a comma-separated list of JSON objects — each provided by a different secrets manager or operator.

When to use Shamir: Any deployment where the master password represents a single point of failure — production systems, multi-team environments, regulatory contexts requiring separation of duties, or anywhere you need to survive the "hit by a bus" scenario.

This is by design — it's a security property of Shamir Secret Sharing, not a bug.

Why the shares differ each time: Shamir Secret Sharing works by generating a random polynomial of degree K-1 (where K is your threshold). The secret is the constant term (the y-intercept), but the other coefficients are randomly chosen each time you run split.

For a 3-of-5 split, PyHSM generates a random degree-2 polynomial:

f(x) = secret + a1*x + a2*x² (over GF(256))

  • secret is fixed (your master password bytes)
  • a1 and a2 are randomly generated each time

The shares are points on this polynomial: Share 1 = f(1), Share 2 = f(2), etc. Different random coefficients produce a different polynomial, which produces different shares — but the same y-intercept (your secret).

Why reconstruction still works: Any 3 points on a degree-2 polynomial uniquely determine that polynomial, and therefore uniquely determine f(0) — the secret. Your shares and someone else's shares are from different polynomials that pass through the same point at x=0.

Visual intuition:

  • Run 1: f(x) = secret + 7x + 3x² → shares A, B, C, D, E
  • Run 2: g(x) = secret + 2x + 9x² → shares V, W, X, Y, Z

Both f(0) = g(0) = secret. But f(1) ≠ g(1), f(2) ≠ g(2), etc.

Why this matters for security: This randomness is critical. If the same secret always produced the same shares, an attacker who saw shares from two different split ceremonies could cross-reference them. The random coefficients ensure that every split is independent — even if you split the same secret 1,000 times, the shares are completely different each time and reveal nothing about each other.

Yes — blockchain signing is one of PyHSM's primary use cases and a key differentiator from cloud KMS solutions like AWS KMS or Google Cloud KMS, which don't support secp256k1 or Ed25519.

Supported blockchain ecosystems:

  • Ethereum / EVM chains (secp256k1 + ECDSA): Sign raw transaction hashes for Ethereum, Polygon, Arbitrum, Optimism, BSC, and any EVM-compatible network.
  • Bitcoin (secp256k1 + ECDSA): Sign Bitcoin transactions with the same curve and algorithm Bitcoin uses natively.
  • Solana / Cosmos (Ed25519 + EdDSA): High-performance 64-byte signatures for Solana transactions, Cosmos SDK messages, and any Ed25519-based protocol.

How it works in practice:

  1. Import your existing private key (e.g., from MetaMask export) via JWK, or generate a fresh wallet key directly in PyHSM.
  2. The private key is AES-KWP double-encrypted at rest — it never sits in plaintext on disk.
  3. Your application builds and hashes the transaction, then calls hsm.sign("eth-wallet", tx_hash).
  4. PyHSM unwraps the key, signs, zeroizes the key from memory, and returns only the signature.
  5. Your application parses the DER-encoded signature into (r, s, v) and broadcasts.

Security advantages over raw key files:

  • The key is never in a .env file — it's double-encrypted and requires the master password (or M-of-N Shamir shares) to unlock.
  • Every signing operation is recorded in the HMAC-chained audit log with caller ID, timestamp, and key version.
  • Rate limiting and max_operations policies prevent unlimited signing even if the application is compromised.
  • Process isolation mode ensures key material lives in a separate address space from your application.

Production considerations: Latency is ~103ms per sign operation (dominated by keystore persistence). For high-frequency use cases, consider the TypeScript layer's deferred persistence mode. For cold wallets or treasury keys, combine with Shamir 3-of-5 so no single operator can unlock the signing key.

Get in Touch

Ready to secure your key management? Let's talk about which plan fits your team.

Response Time

We respond to all inquiries within 1 business day.