Skip to content

kryard/signer

Repository files navigation

Kryard

Open-source, Turnkey-compatible signing infrastructure — EVM and Solana.

Kryard is a remote key-signing service: create private keys and wallets, define signing policies, and request signatures — secp256k1 (EVM) and ed25519 (Solana) — over a Turnkey-wire-compatible API, without your application ever touching private key material. Private keys are generated inside an isolated signer and encrypted at rest with envelope encryption; the API tier can never decrypt them.

It's a drop-in for Turnkey's secp256k1 EVM signing: cutover is a single TURNKEY_BASE_URL swap.

Client / SDK / Dashboard
  →  api/      Turnkey-compatible API (Cloudflare Worker, Hono)  — activity + policy engine
  →  signer/   Isolated signer (Go)                              — the only component that decrypts keys
  →  KMS       AWS KMS  or  local provider                       — envelope encryption
  →  Postgres                                                    — activities, audit, policy, encrypted keys

What's in the box

Path What
api/ The Turnkey-compatible HTTP API — activities, idempotency, X-Stamp auth, a deterministic policy engine, and EVM transaction / raw-payload signing. Cloudflare Worker (Hono) over Postgres.
signer/ The isolated Go signer. Generates secp256k1 (EVM) and ed25519 (Solana) keys; signs EVM transactions (legacy / EIP-1559 / EIP-7702), raw payloads, and ed25519 messages; does KMS envelope encryption. Audited crypto only (go-ethereum; ed25519 from the Go stdlib).
dashboard/ A React console — keys, wallets, policies, activities, and a signing playground. Runs locally with no auth.
infra/aws-dev/ Terraform for a dev profile: a KMS key + the signer as an AWS Lambda behind an IAM-auth Function URL.

Why Kryard

  • The API never decrypts keys. Only the signer holds KMS decrypt permission, on a surface with no public ingress. A compromise of the application tier cannot expose a private key.
  • Every operation is an auditable activity, with SHA-256(canonical_json(body)) idempotency scoped per organization.
  • Signing is policy-bound. A deterministic, fail-closed policy engine gates every signature; the signer re-verifies the policy decision before signing.
  • No hand-rolled crypto. secp256k1, ECDSA, Keccak-256, RLP, and EVM address derivation come from go-ethereum; ed25519 is the Go standard library.
  • Runs with no cloud. The signer ships an in-process KMS provider, so the whole stack runs on your laptop — and the same code path runs against real AWS KMS in production.

Quickstart

Run the full stack locally — no AWS account required:

docker compose up -d                 # Postgres

cd signer && KMS_PROVIDER=local KMS_MASTER_KEY=$(openssl rand -hex 32) go run ./cmd/signer &

cd api && pnpm install \
  && DATABASE_URL=postgres://kryard:kryard@localhost:5432/kryard pnpm migrate \
  && SIGNER_BASE_URL=http://localhost:8081 DEV_ADMIN_ENABLED=true pnpm dev &

cd dashboard && npm install \
  && printf 'VITE_LOCAL=true\nVITE_API_BASE=http://localhost:8787\n' > .env.local \
  && npm run dev

Open http://localhost:5173. Full walkthrough: docs/local-development.md.

Use it from code — @kryard/sdk

The signer speaks the Turnkey-compatible activity API, so the published @kryard/sdk talks to your local signer the same way it talks to the hosted one — point baseUrl at your API. Every call is X-Stamp-authenticated and org-scoped (the same path runs in production), but in dev mode you don't need a managed account: bootstrapLocalClient mints a throwaway org + API key through the unauthenticated dev bootstrap and hands back a ready client.

import { bootstrapLocalClient } from "@kryard/sdk"; // >= 0.3.0

const { client } = await bootstrapLocalClient(); // http://localhost:8787

const { addresses } = await client.createPrivateKey({
  name: "local-evm",
  curve: "CURVE_SECP256K1",
});

// Signing additionally needs the API run with POLICY_BYPASS_ALLOWED=true (or a policy):
const { signedTransaction } = await client.signTransaction({
  signWith: addresses[0].address,
  unsignedTransaction: "0x02ef…",
});

Self-mint the same credentials by hand with two POSTs (/admin/dev/org/admin/dev/api-key) — see docs/local-development.md.

Documentation

Scope

This repository is the signing core. The hosted Kryard product adds capabilities on top (a managed EIP-7702 relay for gasless transactions, billing, and more) that are not part of this repository.

Related

  • @kryard/sdk — the Kryard SDK. Its signing client (KryardClient) works against this self-hosted signer (see above); its relay/sponsor helpers target the hosted managed-relay tier.

Contributing

Contributions are welcome — see CONTRIBUTING.md. We require a signed Contributor License Agreement (a one-time comment on your first PR); this lets us include your work both here and in the hosted product under an open-core model.

License

Apache-2.0. See NOTICE for third-party attributions (the signer depends on go-ethereum, LGPL-3.0, as an unmodified dependency).

About

Open-core, Turnkey-compatible private key signer (EVM + multi-curve) with AWS KMS, local-KMS dev mode, and a no-auth localhost dashboard. Apache-2.0.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors