Skip to main content
In this tutorial you’ll sign a message using the encrypted key shares produced during registration, examine the raw signature bytes, and derive a blockchain address from the same public key. By the end you’ll have a working SigningDemo component that lets a user sign any text they type and shows them the hex-encoded signature and their Ethereum address — all without the private key ever leaving the vault worker.

What you’ll build

A SigningDemo component that:
  1. Loads the encrypted shares from a previous generate() call.
  2. Signs a user-supplied message with client.sign().
  3. Displays the hex-encoded signature.
  4. Calls client.deriveAddress() to show the corresponding Ethereum address.

Prerequisites

  • You have completed the Quickstart tutorial.
  • You have a GenerateResult from a call to client.generate(). You’ll store it in React state exactly as the Quickstart does.

Steps

1

Understand what sign() needs

client.sign() takes two arguments:
SignResult has a single field:
The encryptedShares value is opaque — you do not need to inspect it. You receive it from generate() and hand it back to sign(). The vault worker handles all key material internally; your application code never touches a private key.The data argument is a plain array of bytes. You’ll convert a UTF-8 string into number[] using TextEncoder.
2

Store the generate result in state

Extend the App component from the Quickstart to keep the GenerateResult in state after passkey creation, then pass it down to SigningDemo.Replace the contents of src/App.tsx:
src/App.tsx
identity.shares is the value you’ll carry through to signing. It is typed as EncryptedShares & { enclave_id: string }, and you pass the entire identity object to SigningDemo so it can reach both shares and shares.public_key_hex.
3

Create the SigningDemo component

Create src/SigningDemo.tsx:
src/SigningDemo.tsx
4

Display the signature

Add SignatureDisplay to the same file:
src/SigningDemo.tsx
You’ll see a long hex string like:
That is the DER-encoded ECDSA signature. The bytes are produced by the enclave WASM and returned to your component — the signing key itself never crosses the worker boundary.
5

Derive the Ethereum address

Now add address derivation. client.deriveAddress() takes the public key hex string and a chain name:
DeriveAddressResult has two fields:
Add a second button to SigningDemo, below the sign button:
src/SigningDemo.tsx
The complete updated return statement for SigningDemo:
src/SigningDemo.tsx
6

Run the demo

Start the dev server:
Open the app, click Create identity with passkey, and complete the WebAuthn prompt. You’ll see:
Type a message in the input field and click Sign message. Within a second the hex signature appears below. Then click Derive Ethereum address to see the address that corresponds to your passkey’s public key.
Both operations are instant after the first one — the enclave is already loaded and the shares are already in memory. Neither button triggers a network request; all cryptographic work happens inside the vault worker.

What you have built

You can now sign and verify data with your HyperAuth identity. client.sign() takes your encrypted shares and any byte array and returns a raw ECDSA signature. client.deriveAddress() turns the same public key into a chain-specific address. Neither operation requires a server, a seed phrase, or any key material in your application code. From here you can explore more advanced capabilities: the UCAN Delegation guide shows how to mint capability tokens using client.mintUcan(), and the Smart Accounts guide shows how the address you derived becomes the owner of an ERC-4337 account.