Skip to main content
This guide covers using a CoinCover backup key — secp256k1 or ed25519, depending on your chain — as the backup key in your own multi-sig wallet. CoinCover generates and holds the private key inside its enclave and signs only at recovery — so a lost or compromised key on your side never means lost assets. If instead you want to encrypt recovery material and store the ciphertext with us, see Back up key material.
The worked example below is the secp256k1 / BIP32 case. ed25519 keys (used by chains such as Solana) are also supported as backup keys, but they follow their chain’s own hierarchical derivation scheme rather than BIP32 — the chain-code and xpub assembly steps don’t apply. The assign, store, verify, and recovery shape is otherwise the same; talk to your account manager for the ed25519 derivation specifics.

The xpub challenge (secp256k1)

Most multi-sig platforms expect a BIP32 extended public key (xpub) for each key in the wallet. An xpub is (compressed public key + 32-byte chain code) plus BIP32 metadata. CoinCover’s enclave returns the compressed public key but not a chain code, so there’s no native xpub — you supply the chain code, assemble the xpub yourself, and store the chain code back with CoinCover so it’s available at recovery.

Step 1 — Authenticate

Authenticate with a Bearer token in the Authorization header — a JWT or a long-lived API key.
export COINCOVER_API_KEY="<your-jwt-or-api-key>"
export COINCOVER_BASE_URL="https://service.uat-keys.coincover.com"

Step 2 — Assign the signer key

Call POST /v1/keys with key_type: "secp256k1" (or "ed25519" for chains that use it). CoinCover generates the key pair in the enclave and returns the compressed public key (hex) plus a signature. The private key never leaves the enclave.
curl -X POST "$COINCOVER_BASE_URL/v1/keys" \
  -H "Authorization: Bearer $COINCOVER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "user_identifier": "treasury-wallet-01",
    "key_type": "secp256k1",
    "key_environment": "COLD"
  }'
Verify the returned signature against your CoinCover verification key before continuing. If it fails, treat the response as untrusted and escalate before building the wallet.

Step 3 — Generate a chain code

Generate a random 32-byte chain code with a CSPRNG.
Node
import crypto from "node:crypto";
const chainCode = crypto.randomBytes(32); // 32 bytes from a CSPRNG

Step 4 — Assemble the xpub

Build a BIP32 xpub from the enclave’s compressed public key plus your chain code. This is the backup key xpub you’ll register with your wallet platform.

Step 5 — Store the chain code with CoinCover

The chain code is recovery-critical: without it, the private key alone can’t derive child keys. Store it with CoinCover so it’s available at recovery.
1

Assign an encryption key

POST /v1/keys with key_type: "rsa4096" to get an encryption public key.
2

Encrypt the chain code

RSA-OAEP encrypt a small payload such as { chainCode, publicKey, coin, label } with that public key (SHA-256, as in Back up key material).
3

Store the ciphertext

POST /v1/secure/data with the ciphertext and plaintext checksum. Keep the returned backup_id.

Step 6 — Register the backup key with your wallet platform

Register the assembled xpub as the backup key in your wallet, following your platform’s own key-ceremony process. The exact API calls vary by platform, but the shape is consistent:
1

Generate your own keys

Create the keys you control locally (e.g. your primary signing key), following your platform’s guidance.
2

Register all keys for the wallet

Register your own public key(s), the CoinCover backup xpub from step 4, and any platform-held key, per your wallet’s multi-sig scheme.
3

Complete the key ceremony

Run your platform’s key ceremony to bind the keys into the wallet.
You only ever persist the key material you control, in your own secrets store. The backup private key lives solely in CoinCover’s enclave — never store it, and don’t create empty placeholders for it.

Step 7 — Record references

In your own database, store the references you’ll need at recovery time:
  • coincoverBackup.keyId — the signer key ID from step 2
  • coincoverBackup.backupId — the chain-code backup ID from step 5

Step 8 — Round-trip verify before production

Also confirm the key and chain-code backup with the self-service verify endpoints:
curl "$COINCOVER_BASE_URL/v1/keys/$KEY_ID/verify" \
  -H "Authorization: Bearer $COINCOVER_API_KEY"
curl "$COINCOVER_BASE_URL/v1/backups/$BACKUP_ID/verify" \
  -H "Authorization: Bearer $COINCOVER_API_KEY"

Step 9 — Test before you ship

Walk the backup-key scenarios in the testing page, including a sandbox recovery that reconstructs the backup key from the enclave key plus the stored chain code and signs at your wallet’s derivation path.

What’s next

Back up key material

Encrypt recovery material client-side and store it with CoinCover.

API reference

Every endpoint, request, and response.