Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions tips/tip-1011.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
---
id: TIP-1011
title: P256 and WebAuthn Address Derivation
description: Documents how P256 and WebAuthn signatures derive account addresses from public keys, and clarifies that both signature types share the same address space.
authors: Tempo Team
status: Draft
related: Transactions, Account Keychain
protocolVersion: T1
---

# TIP-1011: P256 and WebAuthn Address Derivation

## Abstract

TIP-1011 documents the address derivation scheme for P256 (secp256r1) and WebAuthn signatures on Tempo. Both signature types derive addresses using `keccak256(pub_key_x || pub_key_y)`, taking the last 20 bytes as the address. This means a single P256 key pair produces the same address regardless of whether it is used with raw P256 signatures or WebAuthn signatures.

## Motivation

Tempo supports three signature types for transaction authorization:

1. **secp256k1**: Standard Ethereum-compatible ECDSA signatures
2. **P256**: Raw secp256r1 (NIST P-256) signatures
3. **WebAuthn**: WebAuthn-wrapped P256 signatures (passkeys, hardware keys)

Users should understand that P256 and WebAuthn signatures share the same address derivation mechanism. A private key used for P256 signatures can also be used for WebAuthn signatures over the same account address, and vice versa. This is intentional and expected behavior.

---

# Specification

## Address Derivation

### secp256k1

For secp256k1 signatures, address derivation follows the standard Ethereum approach:

```
address = keccak256(uncompressed_public_key)[12:32]
```

Where `uncompressed_public_key` is the 64-byte concatenation of the x and y coordinates (excluding the 0x04 prefix).

### P256 and WebAuthn

For both P256 and WebAuthn signatures, address derivation uses:

```
address = keccak256(pub_key_x || pub_key_y)[12:32]
```

Where:
- `pub_key_x`: 32-byte x-coordinate of the P256 public key
- `pub_key_y`: 32-byte y-coordinate of the P256 public key
- `||`: byte concatenation

This is implemented as:

```rust
pub fn derive_p256_address(pub_key_x: &B256, pub_key_y: &B256) -> Address {
let hash = keccak256([pub_key_x.as_slice(), pub_key_y.as_slice()].concat());
Address::from_slice(&hash[12..])
}
```

## Shared Address Space

Because P256 and WebAuthn signatures use the same address derivation, a single P256 key pair maps to exactly one address. This has the following implications:

1. **Key reuse across signature types**: A user can sign transactions for the same address using either raw P256 signatures or WebAuthn signatures, provided they use the same underlying key pair.

2. **Passkey portability**: A passkey (WebAuthn) used to create an account can also authorize transactions via raw P256 signatures if the private key is exported or available through another interface.

3. **No signature type binding**: The protocol does not restrict which signature type can be used for a given address. Any valid signature (P256 or WebAuthn) from the corresponding private key will be accepted.

## Security Considerations

This shared address space is acceptable because:

1. **Same key material**: Both signature types require possession of the same private key. There is no privilege escalation—if an attacker has the private key, they can sign with either method.

2. **No replay across types**: Transaction signatures include the signature type in the encoding, preventing a P256 signature from being replayed as WebAuthn or vice versa.

3. **User flexibility**: Users benefit from being able to use whichever signing method is most convenient for their current context (e.g., passkey on mobile, raw P256 from a hardware security module).

---

# Invariants

- Given the same `(pub_key_x, pub_key_y)` pair, the derived address MUST always be identical regardless of signature type
- A transaction signed with P256 MUST recover to the same address as the same transaction signed with WebAuthn using the same key pair
- P256/WebAuthn addresses occupy a different address space than secp256k1 addresses (different curves, different key pairs)

## Test Cases

The test suite must cover:

1. **P256 address derivation**: Verify `derive_p256_address(x, y)` produces the expected address
2. **WebAuthn same address**: Verify WebAuthn signature recovery produces the same address as P256 for identical keys
3. **Cross-signature authorization**: Verify an account created via P256 can authorize transactions via WebAuthn (and vice versa)
4. **Determinism**: Verify repeated derivations with the same key produce identical addresses
Loading