Documentation

Encryption & Decryption

TKeeper supports threshold encryption and decryption using an integrated ECIES construction (ElGamal KEM) with a symmetric payload cipher.

Key properties:

  • Private key material remains distributed as shares; the full private key is not reconstructed.
  • Encryption/decryption are quorum-based operations executed by the keeper cluster.
  • Payload encryption uses a standard symmetric AEAD cipher.

Curve support: threshold ECIES is available only for keys on secp256k1.

Supported payload cipher

TKeeper currently supports a single payload cipher:

  • AES_GCM

The API exposes this as algorithm, but the only accepted value is AES_GCM.

Encrypt

  • POST /v1/keeper/ecies/encrypt
  • Permission: tkeeper.key.<logicalId>.encrypt

Request

{
  "keyId": "custody-key",
  "tweak": "my-user-id",
  "algorithm": "AES_GCM",
  "plaintext64": "base64(plaintext-bytes)"
}

Fields:

Field Type Required Meaning
keyId string yes Key logicalId.
tweak string no Optional tweak input used to derive a child key from the base key for this request.
algorithm enum no Payload cipher. Default: AES_GCM.
plaintext64 string yes Base64-encoded plaintext bytes.

Key Tweaking (optional)

tweak allows deterministic key derivation from one base key (keyId) for encryption/decryption flows.

This is useful when one master key should produce separate derived keys per user, account, or domain input.

Warning tweak in TKeeper is not Taproot tweaking and not BIP key derivation.
It is an application-level key derivation input for threshold operations.

Response

{
  "ciphertext64": "base64(ciphertext-bytes)",
  "generation": 3
}

Fields:

Field Meaning
ciphertext64 Base64-encoded ciphertext bytes produced by threshold ECIES.
generation Key generation used for encryption.

Warning Persist the returned generation alongside the ciphertext. If the key is rotated/refreshed later, decryption will require the original generation.

Decrypt

  • POST /v1/keeper/ecies/decrypt
  • Permission: tkeeper.key.<logicalId>.decrypt

Request

{
  "keyId": "custody-key",
  "tweak": "my-user-id",
  "algorithm": "AES_GCM",
  "ciphertext64": "base64(ciphertext-bytes)",
  "generation": 3,
  "approvals": {
    "keeperId": 1,
    "nonce": "ops-2026-02-12-020",
    "timestamp": 1764420000123,
    "proofs": [
      {
        "fingerprint": "base64(sha256(public-key-bytes))",
        "signature64": "base64(signature-over-request-hash)"
      }
    ]
  }
}

Fields:

Field Type Required Meaning
keyId string yes Key logicalId.
tweak string no Optional tweak input. Must match the value used at encryption time.
algorithm enum no Payload cipher. Default: AES_GCM.
ciphertext64 string yes Base64-encoded ciphertext bytes.
generation int no Key generation to decrypt with. If omitted, the current generation is used.
approvals object no Required when four-eye control is active for the key.

Four-eye approvals (when enabled)

If the key has policy.fourEye, /v1/keeper/ecies/decrypt requires approvals with at least m valid proofs.

For approval schema, keeperId semantics, canonical payload signing rules, and replay/availability trade-offs, see:

Response

{
  "plaintext64": "base64(plaintext-bytes)"
}

Notes

  • If encryption used tweak, decryption must use the same tweak.