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 workingDocumentation Index
Fetch the complete documentation index at: https://docs.hyperauth.dev/llms.txt
Use this file to discover all available pages before exploring further.
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
ASigningDemo component that:
- Loads the encrypted shares from a previous
generate()call. - Signs a user-supplied message with
client.sign(). - Displays the hex-encoded signature.
- Calls
client.deriveAddress()to show the corresponding Ethereum address.
Prerequisites
- You have completed the Quickstart tutorial.
- You have a
GenerateResultfrom a call toclient.generate(). You’ll store it in React state exactly as the Quickstart does.
Steps
Understand what sign() needs
client.sign() takes two arguments:SignResult has a single field: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.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.Display the signature
Add You’ll see a long hex string like:
SignatureDisplay to the same file:src/SigningDemo.tsx
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.
Derive the Ethereum address
Now add address derivation. Add a second button to The complete updated return statement for
client.deriveAddress() takes the public key hex string and a chain name:DeriveAddressResult has two fields:SigningDemo, below the sign button:src/SigningDemo.tsx
SigningDemo:src/SigningDemo.tsx
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.