Skip to content

Commit

Permalink
refactor: move client_random to user model
Browse files Browse the repository at this point in the history
  • Loading branch information
purefunctor committed May 1, 2024
1 parent 710e7ac commit baedf39
Show file tree
Hide file tree
Showing 14 changed files with 105 additions and 85 deletions.
12 changes: 5 additions & 7 deletions lib/backend/Routes/Api/Login.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,18 @@ open HigherOrderHandlers
open Types_native.Definitions_j
open Vault_native

let get_secrets request username =
let get_user request username =
Dream.sql request @@ fun db ->
match%lwt Models.Secrets.get_by_username ~username db with
match%lwt Models.User.get_by_username ~username db with
| Ok user -> Lwt.return_ok user
| Error e -> Lwt.return_error e

let handler request =
let handle_salt username =
match%lwt get_secrets request username with
| Ok (Some { client_random_value; _ }) ->
match%lwt get_user request username with
| Ok (Some { client_random; _ }) ->
Dream.info (fun log -> log "User exists, serving client salt.");
let salt =
client_random_value |> Bytes.of_string |> Salt.compute_digest
in
let salt = client_random |> Bytes.of_string |> Salt.compute_digest in
Dream.json @@ string_of_login_salt_response { salt }
| Ok None ->
Dream.info (fun log -> log "User does not exist, serving server salt.");
Expand Down
4 changes: 2 additions & 2 deletions lib/backend/Routes/Api/Register.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ open HigherOrderHandlers
open Types_native.Definitions_j

let handler request =
let inner ({ username; auth_token } : register_user_payload) =
let inner ({ username; auth_token; client_random } : register_user_payload) =
match ValidationUsername.validate username with
| Validated Success -> (
let auth_token = Cipher.double_hmac auth_token in
let%lwt insert_result =
Dream.sql request (fun connection ->
Models.User.insert ~username ~auth_token connection)
Models.User.insert ~username ~auth_token ~client_random connection)
in
match insert_result with
| Ok (id, public_id) ->
Expand Down
11 changes: 4 additions & 7 deletions lib/backend/Routes/Api/Secrets.ml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ let get_secrets request (user_id : int32) =
| Some
{
user_id = _;
client_random_value;
encrypted_master_key;
master_key_iv;
encrypted_protection_key;
Expand All @@ -32,7 +31,6 @@ let get_secrets request (user_id : int32) =
Lwt.return_ok
@@ Some
{
client_random_value;
encrypted_master_key;
master_key_iv;
encrypted_protection_key;
Expand All @@ -46,7 +44,6 @@ let get_secrets request (user_id : int32) =

let insert_secrets request (user_id : int32)
({
client_random_value;
encrypted_master_key;
master_key_iv;
encrypted_protection_key;
Expand All @@ -66,10 +63,10 @@ let insert_secrets request (user_id : int32)
if has_keys then Lwt.return_ok false
else
let* () =
Models.Secrets.insert ~user_id ~client_random_value ~encrypted_master_key
~master_key_iv ~encrypted_protection_key ~protection_key_iv
~exported_verification_key ~encrypted_verification_key
~verification_key_iv ~exported_protection_key connection
Models.Secrets.insert ~user_id ~encrypted_master_key ~master_key_iv
~encrypted_protection_key ~protection_key_iv ~exported_verification_key
~encrypted_verification_key ~verification_key_iv
~exported_protection_key connection
in
Lwt.return_ok true

Expand Down
1 change: 1 addition & 0 deletions lib/frontend/js/hooks/Session.re
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ let useRegister = () => {
ApiRegister.post({
username,
auth_token: Salt.toHash(freshDerivedKey.hashedAuthenticationKey),
client_random: Base64_js.Uint8Array.encode(clientRandom),
});

let* _ =
Expand Down
2 changes: 0 additions & 2 deletions lib/frontend/js/pages/GetStartedPageGenerateHooks.re
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,6 @@ let useGenerateKeys = () => {

push({kind: Loading, message: "Submitting"});
let registerKeysPayload: Types_universal.Definitions_t.register_keys_payload = {
client_random_value:
clientSecrets.clientRandom |> Base64_js.Uint8Array.encode,
encrypted_master_key: wrappedMasterKey |> Base64_js.ArrayBuffer.encode,
master_key_iv:
clientSecrets.masterKeyIv |> Base64_js.Uint8Array.encode,
Expand Down
11 changes: 0 additions & 11 deletions lib/models/Secrets.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ open Utils

type t = {
user_id : int32;
client_random_value : string;
encrypted_master_key : string;
master_key_iv : string;
encrypted_protection_key : string;
Expand All @@ -20,8 +19,6 @@ let create_table =
CREATE TABLE IF NOT EXISTS secrets (
user_id INT PRIMARY KEY REFERENCES users(id),

client_random_value BYTEA NOT NULL,

encrypted_master_key BYTEA NOT NULL,
master_key_iv BYTEA NOT NULL,

Expand All @@ -43,8 +40,6 @@ let get_by_user_id =
SELECT
@int32{user_id},

@Base64Octets{client_random_value},

@Base64Octets{encrypted_master_key},
@Base64Octets{master_key_iv},

Expand All @@ -69,8 +64,6 @@ let get_by_username =
SELECT
@int32{user_id},

@Base64Octets{client_random_value},

@Base64Octets{encrypted_master_key},
@Base64Octets{master_key_iv},

Expand Down Expand Up @@ -99,8 +92,6 @@ let insert =
INSERT INTO secrets (
user_id,

client_random_value,

encrypted_master_key,
master_key_iv,

Expand All @@ -115,8 +106,6 @@ INSERT INTO secrets (
VALUES(
%int32{user_id},

%Base64Octets{client_random_value},

%Base64Octets{encrypted_master_key},
%Base64Octets{master_key_iv},

Expand Down
6 changes: 0 additions & 6 deletions lib/models/Secrets.mli
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@

type t = {
user_id : int32; (** References a {!User.t.id}. *)
client_random_value : string;
(** A random value generated by a CSPRNG in the client.
Typically 16 string in length, this is used as part of the salt
for deriving the bits in the "[DerivedKey]". *)
encrypted_master_key : string;
(** The symmetric key used to encrypt the {!encrypted_protection_key}
and {!encrypted_verification_key}. *)
Expand Down Expand Up @@ -50,7 +45,6 @@ val get_by_username :

val insert :
user_id:int32 ->
client_random_value:string ->
encrypted_master_key:string ->
master_key_iv:string ->
encrypted_protection_key:string ->
Expand Down
18 changes: 13 additions & 5 deletions lib/models/User.ml
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
open Utils

type t = {
id : int32;
public_id : string;
username : string;
auth_token : string;
client_random : string;
}

let create_table =
Expand All @@ -13,7 +16,8 @@ CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
public_id VARCHAR(12) DEFAULT nanoid(12, '0123456789abcdefghijklmnopqrstuvwxyz'),
username VARCHAR(16) UNIQUE NOT NULL,
auth_token VARCHAR(128) NOT NULL
auth_token VARCHAR(128) NOT NULL,
client_random BYTEA NOT NULL
);
|sql}]
()
Expand All @@ -26,7 +30,8 @@ SELECT
@int32{id},
@string{public_id},
@string{username},
@string{auth_token}
@string{auth_token},
@Base64Octets{client_random}
FROM
users
WHERE
Expand All @@ -42,7 +47,8 @@ SELECT
@int32{id},
@string{public_id},
@string{username},
@string{auth_token}
@string{auth_token},
@Base64Octets{client_random}
FROM
users
WHERE
Expand All @@ -56,11 +62,13 @@ let insert =
{sql|
INSERT INTO users (
username,
auth_token
auth_token,
client_random
)
VALUES(
%string{username},
%string{auth_token}
%string{auth_token},
%Base64Octets{client_random}
)
RETURNING
@int32{id},
Expand Down
7 changes: 7 additions & 0 deletions lib/models/User.mli
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ type t = {
auth_token : string;
(** A SHA-512 hash representing the authentication
token derived from the user's password. *)
client_random : string;
(** A random value generated by a CSPRNG in the client.
Typically 16 string in length, this is used as part of the salt
for deriving the bits in the "[DerivedKey]" and consequently
the {!auth_token}. *)
}

val create_table :
Expand All @@ -32,6 +38,7 @@ val get_by_username :
val insert :
username:string ->
auth_token:string ->
client_random:string ->
(module Rapper_helper.CONNECTION) ->
(int32 * string, [> Caqti_error.call_or_retrieve ]) result Lwt.t
(** [insert ~username ~auth_token db] insert a new row in the [users] table,
Expand Down
2 changes: 1 addition & 1 deletion lib/types/definitions.atd
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ type 'json base_error_response = {
type register_user_payload = {
username: string;
auth_token: string;
client_random: string;
}

type register_keys_payload = {
client_random_value: string;
encrypted_master_key: string;
master_key_iv: string;
encrypted_protection_key: string;
Expand Down
27 changes: 22 additions & 5 deletions test/backend/Register_Api_test.ml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ let it_works =
let%lwt response, body =
let json =
string_of_register_user_payload
{ username = "purefunctor"; auth_token = double_hmac "auth_token" }
{
username = "purefunctor";
auth_token = String.make 128 'J';
client_random = String.make 16 'K';
}
in
post_json cookie_headers json "http://localhost:8080/api/register"
in
Expand Down Expand Up @@ -59,7 +63,11 @@ let already_registered =
let%lwt _, body =
let json =
string_of_register_user_payload
{ username = "purefunctor"; auth_token = double_hmac "auth_token" }
{
username = "purefunctor";
auth_token = String.make 128 'J';
client_random = String.make 16 'K';
}
in
post_json cookie_headers json "http://localhost:8080/api/register"
in
Expand All @@ -68,7 +76,11 @@ let already_registered =
let%lwt response, body =
let json =
string_of_register_user_payload
{ username = "purefunctor"; auth_token = double_hmac "auth_token" }
{
username = "purefunctor";
auth_token = String.make 128 'J';
client_random = String.make 16 'K';
}
in
post_json cookie_headers json "http://localhost:8080/api/register"
in
Expand Down Expand Up @@ -105,7 +117,11 @@ let creates_session =
let%lwt response, body =
let json =
string_of_register_user_payload
{ username = "purefunctor"; auth_token = double_hmac "auth_token" }
{
username = "purefunctor";
auth_token = String.make 128 'J';
client_random = String.make 16 'K';
}
in
post_json cookie_headers json "http://localhost:8080/api/register"
in
Expand Down Expand Up @@ -134,7 +150,8 @@ let invalid_username =
string_of_register_user_payload
{
username = "invalid&username";
auth_token = double_hmac "auth_token";
auth_token = String.make 128 'J';
client_random = String.make 16 'K';
}
in
post_json cookie_headers json "http://localhost:8080/api/register"
Expand Down
8 changes: 5 additions & 3 deletions test/backend/Secrets_Api_test.ml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ let register_fake_user () =
let%lwt response, body =
let json =
string_of_register_user_payload
{ username = "purefunctor"; auth_token = "auth_token" }
{
username = "purefunctor";
auth_token = String.make 128 'J';
client_random = String.make 16 'K';
}
in
post_json cookie_headers json "http://localhost:8080/api/register"
in
Expand All @@ -30,7 +34,6 @@ let register_fake_user () =
Lwt.return cookie_headers

let make_payload generate =
let client_random_value = generate () in
let encrypted_master_key = generate () in
let master_key_iv = generate () in
let encrypted_protection_key = generate () in
Expand All @@ -41,7 +44,6 @@ let make_payload generate =
let exported_verification_key = generate () in
string_of_register_keys_payload
{
client_random_value;
encrypted_master_key;
master_key_iv;
encrypted_protection_key;
Expand Down
Loading

0 comments on commit baedf39

Please sign in to comment.