Packages

Schnorr-based ZKP authentication via Fiat-Shamir with WebAuthn PRF passkey binding and blind-hashed identities

Current section

Files

Jump to
snarkey snarkey.livemd
Raw

snarkey.livemd

# Snarkey — Livebook Example
## Setup
```elixir
Mix.install([{:snarkey, "~> 0.1.0"}])
```
## Configure pepper
```elixir
Application.put_env(:snarkey, :pepper, "my-secret-pepper-for-blind-identities")
```
## Get default params
```elixir
params = Snarkey.default_params()
```
## Generate a keypair
```elixir
{secret_x, public_y} = Snarkey.Proof.generate_keypair(params)
```
## Registration flow (simulated)
```elixir
# Server generates a nonce
nonce = :crypto.strong_rand_bytes(32) |> Base.encode16()
# Client computes proof of ownership
proof = Snarkey.Proof.compute_proof(params, secret_x, public_y, nonce)
# Server verifies
Snarkey.register(public_y, %{r: proof.r, s: proof.s}, nonce: nonce)
```
## Authentication (non-interactive)
```elixir
# Client generates a commitment and response
{r, k} = Snarkey.Proof.generate_commitment(params.p, params.g, params.q)
user_id = "alice@example.com"
timestamp = System.system_time(:second)
data = :binary.encode_unsigned(params.g) <>
:binary.encode_unsigned(public_y) <>
:binary.encode_unsigned(r) <>
user_id <>
<<timestamp::64-unsigned-big>>
c = Snarkey.Crypto.hash_to_scalar(data, params.q)
s = Snarkey.Proof.respond(k, c, secret_x, params.q)
# Server verifies
Snarkey.authenticate(public_y, %{r: r, s: s, timestamp: timestamp},
user_id: user_id, max_drift: 5)
```
## Interactive fallback
```elixir
# Server issues challenge
challenge = Snarkey.Fallback.generate_challenge(params.q)
# Client responds
{r, k} = Snarkey.Proof.generate_commitment(params.p, params.g, params.q)
s = Snarkey.Proof.respond(k, challenge, secret_x, params.q)
# Server verifies
Snarkey.authenticate(public_y, %{r: r, c: challenge, s: s})
```
## Blind identity
```elixir
Snarkey.blind_identity("alice@example.com")
|> Base.encode16()
```