Meathill HSM

Meathill HSM

CI

English | 中文

A software-defined Hardware Security Module (HSM) built on Cloudflare Worker + KV.

One-Click Deploy to Cloudflare Workers

Deploy to Cloudflare

Clicking this button walks users through forking the repo, provisioning required resources, and deploying.

Maintainer note: this repo now uses a dual-track setup. pnpm deploy always deploys to the fixed production environment (bound to existing production KV), not the template environment.

Required Configuration After Deploy

Generate strong random values (recommended 32+ bytes):

openssl rand -hex 32

If you need to update secrets manually later:

wrangler secret put CF_SECRET_PART
wrangler secret put INDEX_SECRET

Should I Create a Separate Environment?

Example (configure and deploy staging separately):

wrangler secret put CF_SECRET_PART --env staging
wrangler secret put INDEX_SECRET --env staging
wrangler deploy --env staging

AI Integration Entry Points

To make this project easier for AI agents (Codex, Claude, Cursor, Copilot) to understand and use, the repository includes:

After static-site deployment, these files are also published at site root, plus /.well-known/mcp.json for discovery.

MCP Quick Start (Cursor)

If you do not want to build your own HSM and only need secure encrypted storage quickly, use this config and point it to your deployed service:

  1. Copy the content of mcp.json into your Cursor project config .cursor/mcp.json.
  2. Replace HSM_BASE_URL with your Worker URL (for example https://your-hsm-worker.workers.dev).
  3. Replace HSM_SECRET with the same secret you send as X-HSM-Secret.
  4. Restart Cursor MCP and call hsm_put_key / hsm_get_key / hsm_delete_key.

Features

Why Is Your Data Absolutely Safe Here?

Traditional storage solutions require you to trust the service provider not to peek at your data. Meathill HSM adopts a Zero-Trust cryptographic design that mathematically guarantees your data cannot be decrypted or tampered with, even if the server is compromised or the provider acts maliciously:

  1. No one holds the complete key: Your data is encrypted by a KEK, which is derived from both the server's CF_SECRET_PART (Part A) and your client-side X-HSM-Secret (Part B). The server never stores Part B, so it can never assemble the full decryption key.
  2. Stolen data is useless: Even if someone hacks into the Cloudflare KV database and dumps everything, it's just random encrypted noise. Without your X-HSM-Secret, brute-forcing the encryption is practically impossible.
  3. Tampering, overwriting, or deleting your data? No way: The system uses AES-GCM-256 AEAD for encryption, which ensures both confidentiality and data integrity. Any attempt to overwrite or delete your data triggers a background decryption check. If it fails (wrong identity/key), the request is rejected with a 403 error.
  4. Even your key paths are hidden: The paths you store are obfuscated with HMAC-SHA256 in the database. Even browsing the database only reveals hash values — the original path names cannot be reversed.

How to Use Directly from the Frontend (Web)?

For maximum security transparency, the HSM service natively enables full CORS cross-origin access and supports OPTIONS preflight requests. This means you can send requests directly from your browser-side code (React, Vue, Vanilla JS) to store and retrieve data, without going through your own backend server, eliminating the risk of X-HSM-Secret leakage through intermediaries.

Frontend Direct Access Examples (Fetch API)

Store Data

async function saveMySecret() {
  const response = await fetch('https://hsm.meathill.com/keys/my-app/user-1/token', {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json',
      'X-HSM-Secret': 'my-super-secret-client-key' // Only you know this secret
    },
    body: JSON.stringify({ value: 'the-data-i-want-to-protect' })
  });

  if (response.ok) {
    console.log('Data stored securely!');
  }
}

Retrieve Data

async function getMySecret() {
  const response = await fetch('https://hsm.meathill.com/keys/my-app/user-1/token', {
    method: 'GET',
    headers: {
      'X-HSM-Secret': 'my-super-secret-client-key' // Use the same key to decrypt
    }
  });

  const result = await response.json();
  if (result.success) {
    console.log('Decrypted data:', result.data.value);
  }
}

Update/Overwrite Data Updating data uses the same PUT endpoint as storing, but the security mechanism requires you to provide the same X-HSM-Secret used during initial storage. Otherwise, the overwrite is rejected (403 Forbidden).

async function updateMySecret() {
  const response = await fetch('https://hsm.meathill.com/keys/my-app/user-1/token', {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json',
      'X-HSM-Secret': 'my-super-secret-client-key' // Must match the original key
    },
    body: JSON.stringify({ value: 'my-new-updated-data' })
  });

  if (response.ok) {
    console.log('Data updated successfully!');
  } else {
    console.error('Update failed — possibly wrong key (unauthorized)');
  }
}

Delete Data Similarly, deleting requires the correct X-HSM-Secret.

async function deleteMySecret() {
  const response = await fetch('https://hsm.meathill.com/keys/my-app/user-1/token', {
    method: 'DELETE',
    headers: {
      'X-HSM-Secret': 'my-super-secret-client-key' // Must match the original key
    }
  });

  if (response.ok) {
    console.log('Data securely destroyed!');
  }
}

The maximum value length per storage is 8192 characters. You can safely store various tokens, private configurations, or small encryption keys.

Runtime Environment

API Endpoints

Store Secret

PUT /keys/:path
Content-Type: application/json
X-HSM-Secret: <client-secret>

{
  "value": "my-secret-key-value"
}

Retrieve Secret

GET /keys/:path
X-HSM-Secret: <client-secret>

Delete Secret

DELETE /keys/:path
X-HSM-Secret: <client-secret>

Security Design

Key Splitting

KEK (Key Encryption Key) is derived via HKDF from:

Security Guarantees:

Envelope Encryption

  1. Generate a random DEK (Data Encryption Key)
  2. Encrypt data with DEK + AES-GCM-256
  3. Encrypt DEK with KEK + AES-GCM-256
  4. Store the encrypted DEK and data

AAD (Additional Authenticated Data)

The key path is used as AAD to prevent key-swap attacks.

Environment Variables

Variable Description
INDEX_SECRET HMAC index obfuscation key
CF_SECRET_PART HSM service secret (Part A)

Request Headers

Header Description
X-HSM-Secret Client secret (Part B)

Development

# Install dependencies
pnpm install

# Run tests
pnpm test

# Local development
pnpm dev

# Deploy
pnpm deploy

Test Coverage

Current test coverage includes:

Comments

Loading comments...