Skip to main content

Cryptography

LWD's authentication proofs rely on two well-established primitives: Ed25519 for signing and SHA-256 for the public key fingerprint stored in DNS.


Key pair​

Each registered identity has an Ed25519 key pair. The LWD Signing Provider holds and uses the key pair on the user's behalf.

  • The public key is 32 bytes (64 hex characters).
  • Only the SHA-256 hash of the public key is published in DNS — never the key itself.

Public key hash​

The device record stores:

pk = SHA-256(public_key) → 32 bytes → 64 hex characters

This hash is what gets written to the DNS TXT record:

v=lwd1; pk=3f2a1b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2

Storing the hash rather than the raw public key means:

  • DNS records are compact.
  • You can verify a presented public key without trusting any intermediary: compute the hash and compare.

Signing​

To sign a challenge, the SP computes an Ed25519 signature over the raw UTF-8 bytes of the challenge string:

signature = Ed25519.sign(UTF-8(challenge), privateKey)

The result is 64 bytes, hex-encoded (128 hex characters).


Verification​

Anyone can verify independently:

Ed25519.verify(UTF-8(challenge), signature, publicKey)
AND
SHA-256(publicKey) == pk_from_dns

Both checks must pass. The first confirms the signature is valid for the presented key. The second confirms the key is the one registered in DNS — not a key the attacker generated themselves.


Device ID​

Each identity can have one or more device IDs — one per registered device or passkey. Each device has its own key pair, its own device record in DNS, and its own 16-character hex device ID. The SP manages device IDs for each identity.

The device ID appears in:

  • The name of the DNS device record ({deviceId}._lwd.{domain})
  • The device_id parameter returned by the SP
  • The fqdn field in validation_data (after the #)

Algorithm summary​

PurposeAlgorithm
SigningEd25519
Public key fingerprintSHA-256
Device ID derivationSHA-256 (deterministic, first 16 hex chars)