Skip to content
Tenzro
Documentation menu
Keys and identity

Sign-In With Tenzro

Authenticate a Tenzro identity to any website or API with an EIP-4361-shaped message signed by a hardware-rooted key.

Sign-In With Tenzro (SIWT) lets a website, API or agent authenticate a Tenzro identity. The user signs a short, human-readable message scoped to the requesting domain, and the relying party checks the signature against the identity's registered keys. The message format follows EIP-4361 (Sign-In with Ethereum) byte for byte, so existing SIWE parsers can read it.

The signature comes from a hardware-rooted key: a passkey with user verification for a person, a TPM 2.0 or Secure Enclave key for a machine. Like every Tenzro signature it is hybrid (classical plus ML-DSA-65). See Hardware-rooted keys.

The message

example.com wants you to sign in with your Tenzro account:
0x1234567890abcdef1234567890abcdef12345678

Sign in to Example

URI: https://example.com/login
Version: 1
Chain ID: <Tenzro Network chain id>
Nonce: abc123XYZ
Issued At: 2026-10-01T12:00:00Z
Expiration Time: 2026-10-01T12:05:00Z
Request ID: req-001
Resources:
- https://example.com/r1
FieldNotes
DomainThe host asking for the sign-in. Wallets should show it to the user and refuse one that does not match the page's origin.
AddressThe Tenzro account. The EVM-shaped 20-byte form is accepted, as EIP-4361 requires.
StatementOptional text shown to the user.
URIThe resource being signed in to. A tenzro:// URI is allowed.
Version1.
Chain IDThe value eth_chainId returns on Tenzro Network.
NonceAt least eight random alphanumeric characters, issued by the relying party.
Issued At, Expiration Time, Not BeforeRFC 3339 timestamps.
Request ID, ResourcesOptional.

Always read the chain id from the network (eth_chainId) rather than hard-coding it.

Flow

  1. Issue a nonce. The relying party generates a random nonce and stores it against the pending sign-in.
  2. Build the message. Fill in the fields and render the canonical text locally.
  3. Sign. The user's wallet shows the domain and statement and signs the exact canonical bytes with their hardware-rooted key.
  4. Verify. The relying party parses the message, checks the domain, nonce and time window, resolves the DID document for the address (tenzro_resolveDidDocument), and verifies the hybrid signature against the verification methods it lists.
  5. Consume the nonce. Mark it used so the same signed message cannot be replayed.

Verification is stateless on the network side: replay protection comes from the relying party's nonce store.

Build the message

The message is plain text in a fixed layout, built and parsed on the client; no call to a node is needed. Read the chain id first:

bash
CHAIN_ID=$(printf '%d' "$(curl -s https://rpc.tenzro.com \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_chainId","params":[]}' | jq -r .result)")

Then render the fields in order, one per line, exactly as the table above names them, and have the wallet sign those exact bytes. A parser must refuse a message that is missing a required field such as URI.

Checking the time window

A verifier rejects a message whose Expiration Time has passed or whose Not Before is still in the future. Keep expiry short, a few minutes, and issue a fresh nonce for every attempt.