Private key management system development

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
Private key management system development
Complex
~1-2 weeks
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1051
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    827
  • image_logo-aider_0.jpg
    AIDER company logo development
    762
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    850

Development of Private Key Management System

Private key is the only source of truth in blockchain. No password recovery, no support service, no transaction rollback. Key compromise = permanent loss of all assets under its control. Yet most organizations store keys in .env files on servers or, worse, in developers' personal wallets.

Developing corporate key management system is engineering task at intersection of cryptography, distributed systems, and operational security. Correct architecture must ensure: impossibility of compromise from single point of failure, auditability of every key use, recovery on component failure.

Threat model: what we protect against

Before choosing technologies — clearly define threats.

External attacker: server breach, credential leak, SQL injection in adjacent systems. Attacker gains access to execution environment.

Malicious insider: employee with legitimate access tries to use key without authorization or steal it.

Infrastructure failure: server with key fails at worst moment. Need replication without security reduction.

Supply chain attack: compromised dependency, modified Docker image, BGP hijack of cloud provider.

Different threats require different protective measures. No single right solution — toolkit with different security/convenience trade-offs.

Key protection levels

Hardware Security Modules (HSM)

HSM (Hardware Security Module) — physical device storing key material and performing cryptographic operations in protected environment. Key never leaves device in plain form.

Cloud variants: AWS CloudHSM, Azure Dedicated HSM, Google Cloud HSM. On-premise: Thales Luna, Entrust nShield. For blockchain often use YubiHSM 2 (accessible option, ~$600).

# HSM interaction via PKCS#11 (standard interface)
import pkcs11
from pkcs11 import Mechanism, KeyType, ObjectClass

def sign_ethereum_transaction_with_hsm(
    tx_hash: bytes,
    slot_id: int,
    pin: str,
    key_label: str
) -> tuple[int, int, int]:
    """
    Signs transaction hash with private key inside HSM
    Returns (v, r, s) signature components
    """
    lib = pkcs11.lib('/usr/lib/softhsm/libsofthsm2.so')  # or real HSM path
    token = lib.get_token(slot_id=slot_id)
    
    with token.open(user_pin=pin) as session:
        # Find key by label
        private_key = session.get_key(
            object_class=ObjectClass.PRIVATE_KEY,
            key_type=KeyType.EC,
            label=key_label
        )
        
        # Signing happens inside HSM, key not exported
        signature = private_key.sign(tx_hash, mechanism=Mechanism.ECDSA)
        
        # Convert DER signature to (r, s)
        r, s = decode_ecdsa_signature(signature)
        v = determine_recovery_id(tx_hash, r, s)
        
        return v, r, s

def generate_key_in_hsm(session, label: str) -> None:
    """Generates key pair inside HSM"""
    # Key generated inside HSM and never exits in plain form
    pub, priv = session.generate_keypair(
        KeyType.EC,
        key_length=256,
        curve='secp256k1',
        public_template={
            pkcs11.Attribute.LABEL: label,
            pkcs11.Attribute.TOKEN: True,
            pkcs11.Attribute.VERIFY: True,
        },
        private_template={
            pkcs11.Attribute.LABEL: label,
            pkcs11.Attribute.TOKEN: True,     # Save on token
            pkcs11.Attribute.PRIVATE: True,
            pkcs11.Attribute.SENSITIVE: True,  # Don't export in plain form
            pkcs11.Attribute.SIGN: True,
            pkcs11.Attribute.EXTRACTABLE: False,  # Critical: forbid export
        }
    )

Multi-Party Computation (MPC)

MPC — technology where key never exists in complete form on single device. Multiple participants hold shards (key shares), transaction signing happens via cryptographic protocol without assembling full key.

Used in Fireblocks, Zengo, Qredo, Coinbase Prime. Standard protocols: GG18/GG20 (Lindell et al.), FROST (Flexible Round-Optimized Schnorr Threshold Signatures).

MPC signing scheme (simplified):

Participant A has: key_share_A
Participant B has: key_share_B  
Participant C has: key_share_C

For signing need any 2 of 3 (2-of-3 scheme):

1. A and B start protocol
2. Exchange commitments (don't reveal shards)
3. Compute partial signatures
4. Aggregate: signature = combine(partial_A, partial_B)
5. Result — valid ECDSA signature
6. key_share_A and key_share_B NEVER met on one device

MPC advantages over on-chain multisig: signature looks like regular single-sig transaction (less gas, doesn't reveal governance structure), off-chain policy enforcement (can add any rules without changing smart contract).

Threshold Signatures vs Multisig

Important not to confuse MPC threshold signatures with on-chain multisig (Gnosis Safe). Different approaches with different trade-offs:

Characteristic MPC (TSS) On-chain Multisig (Gnosis Safe)
Gas cost Standard signature Depends on scheme (higher)
Transparency Governance structure not visible All signers public on-chain
Off-chain policy Full flexibility No
Signing audit Off-chain log On-chain history
Shard recovery More complex Easy (add/remove owner)
Maturity Relatively new Proven for years

For most organizations: Gnosis Safe for large cold storage (transparency more important than gas), MPC for operational hot wallets (speed and policy flexibility).

Transaction authorization policies

Keys are only part of system. Equally important: define who, when, and under what conditions can sign transactions.

Policy Engine

interface TransactionPolicy {
    id: string;
    name: string;
    conditions: PolicyCondition[];
    requiredApprovals: number;
    approvers: string[];
    maxAmountUsd?: number;
    allowedContracts?: string[];
    allowedChains?: number[];
    timeRestrictions?: TimeRestriction;
}

interface PolicyCondition {
    type: 'amount' | 'contract' | 'method' | 'time' | 'chain';
    operator: 'eq' | 'lt' | 'gt' | 'in' | 'not_in';
    value: unknown;
}

class PolicyEngine {
    private policies: TransactionPolicy[];
    
    async evaluateTransaction(tx: PendingTransaction): Promise<PolicyResult> {
        const matchingPolicies = this.findMatchingPolicies(tx);
        
        if (matchingPolicies.length === 0) {
            return { 
                allowed: false, 
                reason: 'No matching policy',
                requiresManualReview: true 
            };
        }
        
        // Take most strict applicable policy
        const strictestPolicy = this.getMostRestrictivePolicy(matchingPolicies);
        
        // Check limits
        if (strictestPolicy.maxAmountUsd) {
            const txValueUsd = await this.getTransactionValueUsd(tx);
            if (txValueUsd > strictestPolicy.maxAmountUsd) {
                return {
                    allowed: false,
                    reason: `Exceeds limit: $${txValueUsd} > $${strictestPolicy.maxAmountUsd}`,
                    requiresApproval: true,
                    approvers: strictestPolicy.approvers
                };
            }
        }
        
        // Check contract whitelist
        if (strictestPolicy.allowedContracts && 
            tx.to && 
            !strictestPolicy.allowedContracts.includes(tx.to.toLowerCase())) {
            return {
                allowed: false,
                reason: 'Contract not in whitelist',
                requiresManualReview: true
            };
        }
        
        return { allowed: true, policy: strictestPolicy };
    }
}

Authorization levels

Typical corporate hierarchy:

Automatic transactions (up to $1,000 equivalent): executed without human confirmation. Suitable for gas top-ups, small operations, batch transactions.

One-person approval ($1,000–$50,000): operation requires confirmation from one authorized person via mobile app or hardware key.

Multi-person approval ($50,000–$500,000): requires M of N confirmations from different employees in different geolocations.

Board-level approval (above $500,000): committee meeting, physical meeting, possibly notarized documents.

Key Lifecycle Management

Key lifecycle: generation → registration → operational use → rotation → revocation. Each stage requires separate procedures.

Generation: must happen in trusted environment (HSM, air-gapped machine). Entropy source verified. Generation documented with witness signatures.

Backup sharding: keys backed up via Shamir's Secret Sharing. 3-of-5 scheme: five shards distributed to different physical locations, three sufficient for recovery.

from secretsharing import PlaintextToHexSecretSharer

def backup_private_key(private_key_hex: str, shares: int = 5, threshold: int = 3) -> list[str]:
    """
    Splits private key into N shards, threshold sufficient for recovery
    Shards stored separately: different people, different physical locations
    """
    shards = PlaintextToHexSecretSharer.split_secret(
        private_key_hex,
        threshold,
        shares
    )
    return shards

def recover_private_key(shards: list[str]) -> str:
    """Recovers key from any threshold shards"""
    return PlaintextToHexSecretSharer.recover_secret(shards)

# Backup procedure:
# 1. Air-gapped machine, no network
# 2. Generate 5 shards
# 3. Each shard on separate hardware drive + paper backup
# 4. Envelopes sealed, signed by witnesses
# 5. Stored in different safes (office, bank box, home safe of key employees)

Key rotation: planned (once per year) and unplanned (on compromise suspicion, employee termination). For on-chain contracts requires owner change via multisig.

Revocation: on compromise — immediate asset transfer to new key. Can't just "block" key on blockchain.

Audit and monitoring

Every key use must be logged: who requested signing, what was signed, who authorized, timestamp, IP, device fingerprint.

interface KeyUsageEvent {
    eventId: string;
    timestamp: Date;
    keyId: string;
    operation: 'sign' | 'derive' | 'export_public' | 'rotate';
    requestedBy: string;      // user ID or service account
    approvedBy: string[];     // if approval required
    transactionHash?: string; // if transaction
    transactionData?: {
        to: string;
        value: string;
        chainId: number;
        methodSignature?: string;
    };
    policyId: string;
    ipAddress: string;
    deviceId: string;
    approved: boolean;
    rejectionReason?: string;
}

// All events signed by audit HSM key — can't forge
// Stored in append-only storage (Kafka, CloudTrail, immutable S3 bucket)

Anomalies for alerting: signing at night outside work hours, atypical destination addresses, transaction volume above historical norm, attempts to sign rejected transactions.

Disaster Recovery

Recovery plan must be documented and regularly tested (tabletop exercises). Scenarios: loss of one server with key, loss of data center, shard compromise, key keeper termination.

RTO (Recovery Time Objective) for different levels: hot wallet — minutes (automatic failover to backup HSM), cold storage — hours (multi-person procedure), full key switch — 24–48 hours.

Regular tests: quarterly recovery simulation in staging. Without test, recovery plan is just document.

Stack and development timeline

Infrastructure: AWS CloudHSM or YubiHSM 2, Hashicorp Vault (secret and policy management), Kubernetes for signing services.

MPC libraries: tss-lib (Go, GG20 implementation), ZenGo-X/multi-party-ecdsa (Rust), Fireblocks SDK for enterprise.

Backend: Go or Rust for performance-critical signing service, Node.js/Python for API gateway.

Audit: security audit of key management system mandatory, preferably with penetration testing.

Development timeline for corporate KMS: 4–6 months for production-grade system with HSM, MPC, and policy engine. Integration with Gnosis Safe or Fireblocks instead of custom MPC halves timeline.