All posts

How We Sign Your Transactions Without Holding Your Keys

Turnkey signer integration for KeeperHub workflows

It is 3 a.m. A KeeperHub workflow fires. Somewhere on-chain, a transfer goes out on behalf of an organization. No one is watching. No one is clicking approve. The signature lands, the transaction gets mined, and the workflow moves on.

Nothing about that should be possible if we are doing custody the way most platforms do it.

What follows is a walk through the wallet infrastructure behind every on-chain action KeeperHub takes, and the decisions that shaped it.

An automated wallet is a target by design

A wallet that signs automatically is different from a wallet you use yourself. You can sit in front of a normal wallet and refuse to sign something suspicious. A workflow wallet cannot. If the conditions match, it signs. That is the whole point.

That changes the threat model. Anywhere the private key lives becomes a place an attacker can go looking. Anywhere it is copied becomes another one. If the key exists in process memory, on disk, in a config file, or in any secret store we can read, that is already too much surface area.

So the starting constraint was blunt: KeeperHub should not be able to read your private key. Not with a database dump, not with a misconfigured backup, not under any circumstance. There should be nothing to steal because there should be nothing to read.

The decisions behind the design

Three principles drove the architecture.

Hardware-backed key custody

The private key has to live in dedicated hardware, inside a boundary we cannot reach through our own systems. Software isolation on its own is not enough. A determined attacker sharing the same machine can usually find a seam. Dedicated hardware with an attested boundary is a different class of guarantee.

Users always own their keys

Every KeeperHub wallet has to be exportable. Directly, from the product, whenever the user decides. No support ticket, no agreement to sign, no conditions. A wallet you cannot take somewhere else is not really your wallet, and the flow that delivers it has to be secure end-to-end so that exportability does not become a new attack surface.

A signer that plugs into each chain's native tooling

Our workflow engine already talks to chains through their native signer interfaces: ethers.js for EVM, Solana's signer for Solana, and so on. The wallet layer plugs in behind those interfaces, not alongside them. Workflow code stays chain-idiomatic, swapping or extending the provider is a localized change, and our business logic does not need to know what is holding the key.

Keys live in hardware, not in our database

We run on Turnkey, which stores private keys inside Trusted Execution Environments (TEEs). A TEE is dedicated hardware that runs code in isolation from the rest of the machine it sits on, including the operators of that machine. Keys are generated inside the enclave, used inside the enclave, and never leave the enclave during normal operation.

When a KeeperHub organization creates a wallet, we call Turnkey to spin up a new sub-organization scoped to that org. The sub-org is the customer's own perimeter inside Turnkey: its own admin user, its own API credentials, its own wallets. The wallet itself is generated on the standard derivation path for its chain family, so the same key works across every network in that family.

What comes back to us, and what we store, is the wallet address, the sub-organization ID, and the wallet ID. That is all. The private key stays behind the enclave boundary. It never lands in our database, it never appears in a log, and it never sits in memory on our servers.

Signing that fits the chain's native tooling

From the workflow engine's perspective, none of the above matters. A step asks for a signer and gets back whatever signer its chain expects: an ethers.js Signer for EVM chains, a Solana-native signer for Solana, and so on. Each one is called the same way you would call any other signer on that chain. Code that already knows how to send an EVM transfer or a Solana transaction does not change.

Under the hood, every one of those signers is bound to the organization's sub-org and backed by the Turnkey enclave. When a step submits a transaction, the signer serializes the payload, hands it to the enclave over an authenticated channel, and waits for a signature. The signing itself happens inside the hardware. We never see the key, not even for the microsecond it would take to produce a signature ourselves.

Once we have the signed transaction, we broadcast it to the chain like any other.

How a Workflow Signs a Transaction

The same path is used for every on-chain action KeeperHub runs: transfers, approvals, contract writes, protocol-specific steps. They all route through the same abstraction.

Exportable means exportable

The "your keys are yours" part of the design had to actually work in the browser, not just read well in a blog post.

An admin can export a wallet's private key directly from the settings page. The flow is designed so that a compromised session cannot trigger an export on its own, and so that the key never lands anywhere persistent on our side.

It runs in two halves.

First is identity. The admin requests an export, and we email a six-digit code that expires in five minutes and allows five attempts. The admin types it back in the browser. This proves they control the email on file, not just the session.

Second is the cryptography. Once the code checks out, our server generates a fresh ephemeral P256 key pair. We hand the public half to the Turnkey enclave with the export request, and the enclave encrypts the wallet's private key using that public key. What comes back is an encrypted bundle that only the matching ephemeral private key can decrypt, and only our server holds that private key, for the duration of a single request.

We decrypt locally, render the plaintext key once to the admin's browser, and immediately discard the ephemeral key pair. Nothing about the plaintext key is logged, cached, or persisted. The next export request gets a brand new ephemeral key pair.

How You Export Your Private Key

What this looks like from your side

Three things fall out of this design.

You can sign on-chain actions without custody risk. Workflows fire on their own schedules and the signatures are produced in hardware KeeperHub cannot reach. Not through our database, not through an admin panel, not through a support ticket.

Your funds are always yours. The private key can be exported from the settings page at any time, with no forms, no escalation, and no conditions. Custody stays on your side.

Built on the standards you already know. Workflows talk to each chain through its native signer: ethers.js for EVM, Solana's signer for Solana. No custom SDK, no proprietary wrapper, nothing about your integration tied to a specific wallet provider.

What comes next

The architecture is built to keep growing. New chains, new wallet capabilities like account abstraction or multi-sig, and eventually new providers all plug into the same signer interface we use today. That means support ships without rewiring anything on top.

You bring the workflow. We keep the signing layer under it quiet and correct.

Start building with KeeperHub

Stay in the loop

Get the latest on Web3 automation, product updates, and technical deep dives delivered to your inbox.