Examples for the Chorex project
This repository showcases some example programs built using the Chorex package, which enables choreographic programming in Elixir. Please see the Chorex library for more details on what this is.
Examples:
This is not a library—this is a demo project. (Well, more like lots of little demo projects smooshed together.)
This example runs a TCP handler: one connection listens on the port, and as soon as a connection comes in it gets handed off to another process, which spins up a dedicated handler (right now just a simple echo-like server) to manage the individual connection.
This setup is derived from the organization of the Thousand Island socket server.
There are actually two choreographies at play here:
The listener choreography describes how the port listener hands off connections to an accepter. The acceptor then instantiates a handler choreography for each individual connection.
Ensure that the TcpServer
is configured to run in your application
setup:
def application do
[
mod: {TcpServer, []},
extra_applications: [:logger]
]
end
Now fire up the project with a running iex
shell:
iex -S mix
The server by default listens on port 4242
. You can connect to it with an application like nc
:
nc localhost 4242
You should see the connection acknowledgement in the iex
shell. You can make as many connections as you want; each one gets its own dedicated handler process.
This example demonstrates a zero-knowledge proof using discrete logarithms. See this blog post for an explanation of how the mathematics work.
The choreography lives at lib/zkp/zkp_chor.ex.
Set up the application in mix.exs
to run the ZkpLogin
app:
def application do
[
mod: {ZkpLogin, []},
extra_applications: [:logger]
]
end
All this does is ensure that there’s an ETS table running to hold the login credentials.
Now you can run a login session after running iex -S mix
like so:
iex> ZkpLogin.register_log()
[New User] username: alice
[New User] password: foobar
User alice
registered.
Prover finished.
:ok
iex> ZkpLogin.login_log()
Username: alice
Password: foobar
[Prover] notified that 20 rounds of verification remain
[Prover] notified that 19 rounds of verification remain
[Prover] notified that 18 rounds of verification remain
[Prover] notified that 17 rounds of verification remain
[Prover] notified that 16 rounds of verification remain
[Prover] notified that 15 rounds of verification remain
[Prover] notified that 14 rounds of verification remain
[Prover] notified that 13 rounds of verification remain
[Prover] notified that 12 rounds of verification remain
[Prover] notified that 11 rounds of verification remain
[Prover] notified that 10 rounds of verification remain
[Prover] notified that 9 rounds of verification remain
[Prover] notified that 8 rounds of verification remain
[Prover] notified that 7 rounds of verification remain
[Prover] notified that 6 rounds of verification remain
[Prover] notified that 5 rounds of verification remain
[Prover] notified that 4 rounds of verification remain
[Prover] notified that 3 rounds of verification remain
[Prover] notified that 2 rounds of verification remain
[Prover] notified that 1 rounds of verification remain
Verifier responds :accept
Prover responds :accept
:ok
iex> ZkpLogin.login_log()
Username: alice
Password: zzzz
Verifier responds :reject
Prover responds :fail
:ok
iex>
(Output might change slightly.)
This example is a working implementation of the SRP protocol or password-based login. It uses a zero-knowledge proof to verify a user’s identity and creates a secure session key as a byproduct.
The choreography lives at lib/zkp/srp_chor.ex.
This example needs the same application setup as the Discrete-logarithm zero-knowledge proof:
def application do
[
mod: {ZkpLogin, []},
extra_applications: [:logger]
]
end
Now you can call the ZkpLogin.register_srp()
function to create a new user, and ZkpLogin.login_srp()
to attempt to log in:
iex(1)> ZkpLogin.register_srp()
[New User SRP] username: alice
[New User SRP] password: foobar
Server responds {:registered, "alice"}
Client responds :registered
:ok
iex(2)> ZkpLogin.login_srp()
[Login] username: alice
[Login] password: foobar
Server responds {:ok, <<109, 118, 74, 148, 188, 77, 157, 221, 90, 9, 126, 195, 53, 81, 105, 252, 54, 157, 31, 149, 249, 127, 142, 190, 177, 220, 25, 42, 142, 192, 160, 125, 110, 238, 153, 12, 16, 42>>}
Client responds {:ok, <<109, 118, 74, 148, 188, 77, 157, 221, 90, 9, 126, 195, 53, 81, 105, 252, 54, 157, 31, 149, 249, 127, 142, 190, 177, 220, 25, 42, 142, 192, 160, 125, 110, 238, 153, 12, 16, 42>>}
:ok
iex(3)> ZkpLogin.login_srp()
[Login] username: alice
[Login] password: zzzzzz
Server responds {:fail, :reject_client_digest}
Client responds {:fail, :server_rejected_digest}
:ok
Chorex is a rapidly-evolving library. (I found several bugs while building these examples!) If you find a bug or would like to contribute an example or to Chorex itself, please feel free to open an issue or a pull-request on GitHub.
If you have any comments or feedback, you can contact me directly.
MIT License