Skip to content
1Claw Academy
Curriculum/Advanced Security3 minAdvanced · Lesson 3 of 11

Customer-managed keys (CMEK)

Add a client-side AES-256-GCM layer so 1Claw stores only your key's fingerprint.

CMEK double-encrypts secrets. You encrypt the value with your own AES-256-GCM key in the browser or your process, then 1Claw applies its HSM envelope encryption on top. Your key never touches the server; only its SHA-256 fingerprint is stored so the vault knows which key was used. CMEK is available on Business and Enterprise plans.

Concept

The client-side wire format is one version byte (0x01), a 12-byte IV, the ciphertext, then a 16-byte GCM auth tag. A full server compromise yields only doubly-encrypted blobs.

Watch out

Requires a Business or Enterprise plan. CMEK changes who can decrypt your data, so it is gated at the tier where that trade is usually a contractual requirement rather than a preference.

  1. 1

    Install the SDK and have an API key ready.

    bash
    npm install @1claw/sdk
  2. 2

    Export your API key and vault ID. Replace with your real values from Settings → API Keys and 1claw vault list.

    bash
    export ONECLAW_API_KEY="1ck_your_key_here"
    export ONECLAW_VAULT_ID="your-vault-uuid"
  3. 3

    Exchange your API key for a bearer token.

    bash
    export TOKEN=$(curl -s -X POST https://api.1claw.co/v1/auth/api-key-token \
      -H "Content-Type: application/json" \
      -d "{\"api_key\":\"$ONECLAW_API_KEY\"}" | jq -r .access_token)
  4. 4

    Save the code below as cmek-demo.ts. It generates a 256-bit key, encrypts a secret, stores it, reads it back, and decrypts it. Store the key safely because you need it for every read and write.

    typescript
    import {
      createClient,
      generateCmekKey,
      cmekFingerprint,
      cmekEncrypt,
      cmekDecrypt,
      toBase64,
      fromBase64,
    } from "@1claw/sdk";
    
    const client = createClient({
      baseUrl: "https://api.1claw.co",
      apiKey: process.env.ONECLAW_API_KEY!,
    });
    
    const vaultId = process.env.ONECLAW_VAULT_ID!;
    
    async function main() {
      // Every CMEK helper is async and works on bytes.
      const key = await generateCmekKey();
      console.log("fingerprint:", await cmekFingerprint(key));
    
      // cmekEncrypt takes (plaintext, key): plaintext first.
      const plaintext = new TextEncoder().encode("sk-live-secret-value");
      const blob = await cmekEncrypt(plaintext, key);
    
      // secrets.set takes the value as a positional argument.
      await client.secrets.set(vaultId, "api-keys/stripe", toBase64(blob), {
        type: "api_key",
      });
    
      const res = await client.secrets.get(vaultId, "api-keys/stripe");
      if (res.data) {
        const decrypted = await cmekDecrypt(fromBase64(res.data.value), key);
        console.log(new TextDecoder().decode(decrypted));
      }
    }
    
    main();
  5. 5

    Copy the fingerprint value printed above into the curl body below. Enable CMEK on the vault by sending only the fingerprint.

    bash
    curl -s -X POST https://api.1claw.co/v1/vaults/$ONECLAW_VAULT_ID/cmek \
      -H "Authorization: Bearer $TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"fingerprint":"<paste-fingerprint-from-above>"}'
Tip

To rotate, send the old and new keys to POST /v1/vaults/:id/cmek-rotate. The server re-encrypts in batches of 100, atomically per batch, and holds both keys in memory only for the duration of the job.

The vault now requires your key for every value, and 1Claw cannot decrypt your secrets unilaterally.

Watch out

Two easy mistakes here. generateCmekKey, cmekFingerprint, cmekEncrypt and cmekDecrypt all return promises, so every one needs await. And cmekEncrypt takes (plaintext, key) in that order, both as Uint8Array: swapping them produces a blob that will never decrypt.

Where this goes wrong in practice. CMEK moves a real risk from the provider to the customer, and the failures are consistently operational rather than cryptographic.

  • No escrow. The most common CMEK incident is not theft, it is a laptop and an unrecoverable vault. Enrolment should be paired with a customer-controlled escrow before the first secret is written.
  • Rotation is started and never finished. Server-assisted rotation runs in batches with progress tracking, and a job interrupted midway leaves secrets split across two keys. Both keys must be retained until the job reports completion.
  • The fingerprint is mistaken for a backup. It is a SHA-256 of the key, which can verify a candidate but cannot reconstruct one. Teams have discovered this at exactly the wrong moment.
  • Client-side encryption is bypassed by one integration. A single service that writes through the API without encrypting first leaves plaintext in a vault everyone believes is customer-encrypted, and nothing in the interface will point it out.
Tip

The last one is worth auditing for directly. Uniform CMEK is a property of every writer, and it fails silently the moment one of them does not participate.

Decide

A customer on CMEK reports that their finance team lost the laptop holding the only copy of their key. They have their dashboard login and their secrets are all still listed in the vault.

What can you actually do for them?

Check your understanding

3 questions
1

What does 1Claw store about your CMEK key?

2

What algorithm does the client-side CMEK layer use?

3

What protects a secret if the CMEK vault's database is stolen?