Encryption server.
This project requires libsodium
of version 1.0.18
to be installed.
Then you can build
- with stack:
stack build
.
To generate keys, run
stack exec passetto-init -- <password> <number of keys>
or
stack exec passetto-init-interactive -- addkeys <number of keys>
The -interactive
version allows the user to enter the password interactively from the keyboard.
If the storage isn't yet initialized, it becomes initialized with the password supplied (becoming storage current password) and the set of fresh <number of keys>
.
If the storage is already initialized, the password supplied is checked against storage current password and if ok, the set of fresh <number of keys>
is generated and added to the storage.
Keys are stored in acid-state database which is kept in state
folder of the working directory.
Running the server properly requires a valid TLS certificate, make sure to prepare one.
Encryption server can be run as follows:
stack exec passetto-server
Parameters are accepted via environmental variables:
MASTER_PASSWORD
- password for decrypting master key.PORT
- port to serve at. Default is 8012.USE_TLS
flag - accept HTTPS connections and only them.TLS_KEY
andTLS_CERT
- path to TLS key and certificate (viable whenUSE_TLS
is set). By default, self-signed certificate from./cert
folder is used.
Examples provided using httpie utility.
Further we assume the app running in testing enviroment at 8012 port.
> http :8012/status
HTTP/1.1 200 OK
{
"keys_number": 5
}
> http :8012/encrypt value='My text'
HTTP/1.1 200 OK
{
"value": "0.1.0|3|G8iq1rbeyA+IvM9EIe7beYEi33JEwSm+q+d+Iww8Xk8pqdbGM+4WvuGu4tKk5NCazGu3WovX1hs="
}
> echo '{ "value": "..." }' | http :8012/decrypt
HTTP/1.1 200 OK
{
"value": "My text"
}
> echo '{ "value": { "name": "User", "phone": 123 } }' \
| http :8012/encrypt/obj
HTTP/1.1 200 OK
{
"value": {
"name": "0.1.0|0|7cGcOgDAJETHmvjXEvponxger2L+QZOPRcXfToomqxZ9myXRpMU1VWUnwVNCzahV+0EH4WU=",
"phone": "0.1.0|1|pQyOJEiXPOH69UfD4QBvfWPx50z1COiQ0Djnw48yM24sYr3sP3lQFRTtxB9GYT+vEBHiLBMZ"
}
}
> echo '{ "value": { "name": "...", "phone": "..." } }' \
| http :8012/decrypt/obj
HTTP/1.1 200 OK
{
"value": {
"name": "User",
"phone": "123"
}
}
This project is mostly a port of another encryption service.
However, that service contains some security flaws as described in Passetto cryptography analysis by Serokell, which we address here via using high-level crypto library Sodium:
-
Replaced the custom symmetric encryption code with the use of the
crypto_secretbox
primitive, that provides authenticated secret-key encryption. The underlying low-level primitives are the Salsa20 stream cypher and Poly1305 MAC (see “Cryptography in NaCl” for details). -
Derived the symmetric encryption key from password using the Argon2id algorithm. It is mostly what
crypto_pwhash
key derivation function does. It is implemented in Sodium, though lacks Haskell bindings yet. -
Replaced the custom code that uses RSA with the
crypto_box
high-level primitive, which provides authenticated public-key encryption. The underlying low-level primitives are Curve25519, which is used in elliptic-curve Diffie–Helman to establish a shared symmetric session key, and the message is then encrypted and authenticated as above with Salsa20 and Poly1305 (see “Cryptography in NaCl” for details).