-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathzkp_chor.ex
78 lines (70 loc) · 2.5 KB
/
zkp_chor.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
defmodule Zkp.ZkpChor do
import Chorex
defchor [Prover, Verifier] do
# Registration flow
def run(Prover.(username), Prover.(password), Verifier.(:register)) do
Verifier.get_params() ~> Prover.({g, p})
with Prover.(token) <- Prover.gen_verification_token(username, password, g, p) do
Prover.({username, token}) ~> Verifier.({id, token})
if Verifier.register(id, token) do
Verifier.({:ok, id})
Prover.(:ok)
else
Verifier.(:failed)
Prover.(:failed)
end
end
end
# Authentication flow
def run(Verifier.(rounds)) do
# Prover sends username to verifier
with Prover.(username) <- Prover.get_ident() do
Prover.(username) ~> Verifier.(ident)
# Prover looks up authentication parameters; y is validation key
with Verifier.(creds) <- Verifier.lookup(ident) do
if Verifier.(creds) do
with Verifier.({y, p, g}) <- Verifier.(creds) do
Verifier.({p, g}) ~> Prover.({p, g})
round_loop(Verifier.({p, g, y}), Verifier.(rounds), Prover.({p, g, get_secret(username)}))
end
else
Verifier.(:bad_username)
Prover.(:bad_username)
end
end
end
end
# y is the validation token, x is the client secret
def round_loop(Verifier.({p, g, y}), Verifier.(rounds), Prover.({p, g, x})) do
if Verifier.(rounds <= 0) do
Verifier.(:accept)
Prover.(:accept)
else
with Verifier.(good_proof?) <- do_round(Verifier.({p, g, y}), Prover.({p, g, x})) do
if Verifier.(good_proof?) do
Verifier.(rounds) ~> Prover.(remaining_rounds)
Prover.notify_progress(remaining_rounds)
round_loop(Verifier.({p, g, y}), Verifier.(rounds - 1), Prover.({p, g, x}))
else
Verifier.(:reject)
Prover.(:fail)
end
end
end
end
def do_round(Verifier.({p, g, y}), Prover.({p, g, x})) do
with Prover.(r) <- Prover.(Enum.random(2..p)) do
Prover.(:crypto.mod_pow(g, r, p)) ~> Verifier.(c)
with Verifier.(choice) <- Verifier.challenge_type() do
if Verifier.(choice == :r) do
Prover.(r) ~> Verifier.(r)
Verifier.verify_round(c, r, p, g)
else
Prover.(rem(:crypto.bytes_to_integer(x) + r, p - 1)) ~> Verifier.(xr_modp)
Verifier.verify_round(c, xr_modp, y, p, g)
end
end
end
end
end
end