This commit is contained in:
parent
09d0539537
commit
730a704154
10 changed files with 115 additions and 131 deletions
BIN
secrets.old/dn_kudo_1
Normal file
BIN
secrets.old/dn_kudo_1
Normal file
Binary file not shown.
BIN
secrets.old/dn_kudo_2
Normal file
BIN
secrets.old/dn_kudo_2
Normal file
Binary file not shown.
1
secrets.old/sk_0
Normal file
1
secrets.old/sk_0
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
ÙÊÙK^¿®Ê£ÕSaÊ<61>;ߟԴcîªpð%¢¶D
|
||||||
1
secrets.old/sm_key
Normal file
1
secrets.old/sm_key
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
ðŒ½vö5&øê4r¹}µµA !È6ošCRGt¦s
|
||||||
|
|
@ -2,6 +2,7 @@ open Parse_config
|
||||||
|
|
||||||
let config_filename = "mte.conf"
|
let config_filename = "mte.conf"
|
||||||
let secrets_dir = Fpath.v "secrets"
|
let secrets_dir = Fpath.v "secrets"
|
||||||
|
let secmod_dir = Fpath.(secrets_dir / "secmod")
|
||||||
|
|
||||||
let config_data =
|
let config_data =
|
||||||
match Assets_crunch.read config_filename with
|
match Assets_crunch.read config_filename with
|
||||||
|
|
|
||||||
|
|
@ -2,34 +2,20 @@ open Bos.OS
|
||||||
open Syntax
|
open Syntax
|
||||||
open Crypto
|
open Crypto
|
||||||
|
|
||||||
let read fname =
|
let read fname = File.read fname |> unwrap_err_msg
|
||||||
let* b = File.exists fname |> Syntax.unwrap_err_msg in
|
|
||||||
match b with
|
|
||||||
| false -> Ok None
|
|
||||||
| true ->
|
|
||||||
let+ content = File.read fname |> Syntax.unwrap_err_msg in
|
|
||||||
Some content
|
|
||||||
|
|
||||||
let write_eddsa fname priv =
|
let write_eddsa fname priv =
|
||||||
EddsaPrivateKey.to_octets priv |> File.write fname |> Syntax.unwrap_err_msg
|
EddsaPrivateKey.to_octets priv |> File.write fname |> unwrap_err_msg
|
||||||
|
|
||||||
let write_rsa fname priv =
|
let write_rsa fname priv =
|
||||||
RsaPrivateKey.to_octets priv |> File.write fname |> Syntax.unwrap_err_msg
|
RsaPrivateKey.to_octets priv |> File.write fname |> unwrap_err_msg
|
||||||
|
|
||||||
let read_eddsa fname =
|
let read_eddsa fname =
|
||||||
let* opt = read fname in
|
let* data = read fname in
|
||||||
match opt with
|
let+ v = EddsaPrivateKey.of_octets data in
|
||||||
| None -> Ok None
|
v
|
||||||
| Some data -> (
|
|
||||||
EddsaPrivateKey.of_octets data |> function
|
|
||||||
| Error e -> Error e
|
|
||||||
| Ok v -> Ok (Some v))
|
|
||||||
|
|
||||||
let read_rsa fname =
|
let read_rsa fname =
|
||||||
let* opt = read fname in
|
let* data = read fname in
|
||||||
match opt with
|
let+ v = RsaPrivateKey.of_octets data in
|
||||||
| None -> Ok None
|
v
|
||||||
| Some data -> (
|
|
||||||
RsaPrivateKey.of_octets data |> function
|
|
||||||
| Error e -> Error e
|
|
||||||
| Ok v -> Ok (Some v))
|
|
||||||
|
|
|
||||||
|
|
@ -32,15 +32,15 @@ module Keys_get = struct
|
||||||
end
|
end
|
||||||
|
|
||||||
module Keys_post = struct
|
module Keys_post = struct
|
||||||
|
let error_key_unknown =
|
||||||
|
"404 not found, One of the keys for which a signature was provided is \
|
||||||
|
unknown to the exchange."
|
||||||
|
|
||||||
let verify_denom_signature (module Sm : Secmod.S)
|
let verify_denom_signature (module Sm : Secmod.S)
|
||||||
DenomSignature.{ h_denom_pub; master_sig } =
|
DenomSignature.{ h_denom_pub; master_sig } =
|
||||||
let* denom =
|
let* denom =
|
||||||
match Sm.find_denomination h_denom_pub with
|
Sm.find_future_denomination h_denom_pub
|
||||||
| None ->
|
|> Option.to_result ~none:error_key_unknown
|
||||||
Fmt.error
|
|
||||||
"404 not found, One of the keys for which a signature was provided \
|
|
||||||
is unknown to the exchange."
|
|
||||||
| Some denom -> Ok denom
|
|
||||||
in
|
in
|
||||||
let open Signatures.DenominationKeyValidity in
|
let open Signatures.DenominationKeyValidity in
|
||||||
let r : r =
|
let r : r =
|
||||||
|
|
@ -63,12 +63,7 @@ module Keys_post = struct
|
||||||
let verify_signkey_signature (module Sm : Secmod.S)
|
let verify_signkey_signature (module Sm : Secmod.S)
|
||||||
SignKeySignature.{ key; master_sig } =
|
SignKeySignature.{ key; master_sig } =
|
||||||
let* signkey =
|
let* signkey =
|
||||||
match Sm.find_signkey key with
|
Sm.find_future_signkey key |> Option.to_result ~none:error_key_unknown
|
||||||
| None ->
|
|
||||||
Fmt.error
|
|
||||||
"404 not found, One of the keys for which a signature was provided \
|
|
||||||
is unknown to the exchange."
|
|
||||||
| Some signkey -> Ok signkey
|
|
||||||
in
|
in
|
||||||
let open Signatures.ExchangeSigningKeyValidity in
|
let open Signatures.ExchangeSigningKeyValidity in
|
||||||
let r : r =
|
let r : r =
|
||||||
|
|
@ -76,7 +71,7 @@ module Keys_post = struct
|
||||||
start= signkey.stamp_start;
|
start= signkey.stamp_start;
|
||||||
expire= signkey.stamp_expire;
|
expire= signkey.stamp_expire;
|
||||||
end_= signkey.stamp_end;
|
end_= signkey.stamp_end;
|
||||||
signkey_pub= signkey.pub;
|
signkey_pub= signkey.key;
|
||||||
}
|
}
|
||||||
in
|
in
|
||||||
verify_f ~f:Sm.verify_with_master_key master_sig r
|
verify_f ~f:Sm.verify_with_master_key master_sig r
|
||||||
|
|
|
||||||
106
src/secmod.ml
106
src/secmod.ml
|
|
@ -16,6 +16,8 @@ module type S = sig
|
||||||
val get_future_denominations : unit -> Api.FutureDenom.t list
|
val get_future_denominations : unit -> Api.FutureDenom.t list
|
||||||
val find_signkey : eddsa_pub -> Signkey.t option
|
val find_signkey : eddsa_pub -> Signkey.t option
|
||||||
val find_denomination : denom_hash -> Denomination.t option
|
val find_denomination : denom_hash -> Denomination.t option
|
||||||
|
val find_future_signkey : eddsa_pub -> Api.FutureSignKey.t option
|
||||||
|
val find_future_denomination : denom_hash -> Api.FutureDenom.t option
|
||||||
|
|
||||||
val certify_future_signkey :
|
val certify_future_signkey :
|
||||||
eddsa_pub ->
|
eddsa_pub ->
|
||||||
|
|
@ -64,11 +66,12 @@ module Make (Conn : Pg.CONN) = struct
|
||||||
dn_section_name_ht: (denom_hash, string) Hashtbl.t;
|
dn_section_name_ht: (denom_hash, string) Hashtbl.t;
|
||||||
}
|
}
|
||||||
|
|
||||||
let sm_key_fname = Fpath.(Config.secrets_dir / "sm_key")
|
let conn = (module Conn : Pg.CONN)
|
||||||
let sk_key_fname i = Fpath.(Config.secrets_dir / Fmt.str "sk_%d" i)
|
let sm_key_fname = Fpath.(Config.secmod_dir / "sm_key")
|
||||||
|
let sk_fname i = Fpath.(Config.secmod_dir / Fmt.str "sk_%d" i)
|
||||||
|
|
||||||
let dn_key_fname section_name =
|
let dn_fname section_name =
|
||||||
Fpath.(Config.secrets_dir / Fmt.str "dn_%s" section_name)
|
Fpath.(Config.secmod_dir / Fmt.str "dn_%s" section_name)
|
||||||
|
|
||||||
let database_find_sk conn pub =
|
let database_find_sk conn pub =
|
||||||
let* opt = Pg.find_signkey conn pub |> unwrap_err_caqti in
|
let* opt = Pg.find_signkey conn pub |> unwrap_err_caqti in
|
||||||
|
|
@ -85,38 +88,14 @@ module Make (Conn : Pg.CONN) = struct
|
||||||
"secmod failure: a denomination could not be found in database"
|
"secmod failure: a denomination could not be found in database"
|
||||||
| Some dn_data -> Ok dn_data
|
| Some dn_data -> Ok dn_data
|
||||||
|
|
||||||
(* TODO clean up *)
|
let list_to_ht l = Hashtbl.of_seq (List.to_seq l)
|
||||||
let load conn =
|
|
||||||
let error_invalid_state =
|
let load () =
|
||||||
Fmt.error "secmod load error: invalid store state."
|
|
||||||
in
|
|
||||||
let* sm_key = Data_file.read_eddsa sm_key_fname in
|
let* sm_key = Data_file.read_eddsa sm_key_fname in
|
||||||
let* sk_keys =
|
|
||||||
let l = List.init 1 sk_key_fname in
|
|
||||||
let* l = list_map (fun fname -> Data_file.read_eddsa fname) l in
|
|
||||||
match opt_list l with Error () -> error_invalid_state | Ok opt -> Ok opt
|
|
||||||
in
|
|
||||||
let* dn_keys =
|
|
||||||
let* l =
|
|
||||||
let open Config.Coin in
|
|
||||||
list_map
|
|
||||||
(fun coin ->
|
|
||||||
let section_name = coin.section_name in
|
|
||||||
let+ opt = Data_file.read_rsa (dn_key_fname section_name) in
|
|
||||||
Option.map (fun priv -> (section_name, priv)) opt)
|
|
||||||
all_coins
|
|
||||||
in
|
|
||||||
match Syntax.opt_list l with
|
|
||||||
| Error () -> error_invalid_state
|
|
||||||
| Ok opt -> Ok opt
|
|
||||||
in
|
|
||||||
match (sm_key, sk_keys, dn_keys) with
|
|
||||||
| None, None, None -> Ok None
|
|
||||||
| Some sm_key, Some sk_keys, Some dn_keys ->
|
|
||||||
let list_to_ht l = Hashtbl.of_seq (List.to_seq l) in
|
|
||||||
let sm_pubkey = EddsaPrivateKey.pub_of_priv sm_key in
|
let sm_pubkey = EddsaPrivateKey.pub_of_priv sm_key in
|
||||||
(* sk *)
|
|
||||||
let* l =
|
let* sk_keys = list_map Data_file.read_eddsa (List.init 1 sk_fname) in
|
||||||
|
let* sk_l =
|
||||||
list_map
|
list_map
|
||||||
(fun priv ->
|
(fun priv ->
|
||||||
let pub = EddsaPrivateKey.pub_of_priv priv in
|
let pub = EddsaPrivateKey.pub_of_priv priv in
|
||||||
|
|
@ -125,12 +104,19 @@ module Make (Conn : Pg.CONN) = struct
|
||||||
sk_keys
|
sk_keys
|
||||||
in
|
in
|
||||||
let sk_ht, sk_key_ht =
|
let sk_ht, sk_key_ht =
|
||||||
let sk_l, priv_l = List.split l in
|
match List.split sk_l with l1, l2 -> (list_to_ht l1, list_to_ht l2)
|
||||||
(list_to_ht sk_l, list_to_ht priv_l)
|
|
||||||
in
|
in
|
||||||
(* dn *)
|
|
||||||
let dn_section_name_ht = Hashtbl.create 0xff in
|
let dn_section_name_ht = Hashtbl.create 0xff in
|
||||||
let* l =
|
let* dn_keys =
|
||||||
|
list_map
|
||||||
|
(fun coin ->
|
||||||
|
let section_name = coin.Config.Coin.section_name in
|
||||||
|
let+ priv = Data_file.read_rsa (dn_fname section_name) in
|
||||||
|
(section_name, priv))
|
||||||
|
Config.Coin.all_coins
|
||||||
|
in
|
||||||
|
let* dn_l =
|
||||||
list_map
|
list_map
|
||||||
(fun (section_name, priv) ->
|
(fun (section_name, priv) ->
|
||||||
let h_pub =
|
let h_pub =
|
||||||
|
|
@ -139,16 +125,14 @@ module Make (Conn : Pg.CONN) = struct
|
||||||
|> RsaPublicKey.to_octets
|
|> RsaPublicKey.to_octets
|
||||||
|> DenominationHash.hash
|
|> DenominationHash.hash
|
||||||
in
|
in
|
||||||
|
|
||||||
(* fill dn_section_name_ht *)
|
(* fill dn_section_name_ht *)
|
||||||
Hashtbl.replace dn_section_name_ht h_pub section_name;
|
Hashtbl.replace dn_section_name_ht h_pub section_name;
|
||||||
|
|
||||||
let+ dn = database_find_dn conn h_pub in
|
let+ dn = database_find_dn conn h_pub in
|
||||||
((h_pub, dn), (h_pub, priv)))
|
((h_pub, dn), (h_pub, priv)))
|
||||||
dn_keys
|
dn_keys
|
||||||
in
|
in
|
||||||
let dn_ht, dn_key_ht =
|
let dn_ht, dn_key_ht =
|
||||||
match List.split l with l1, l2 -> (list_to_ht l1, list_to_ht l2)
|
match List.split dn_l with l1, l2 -> (list_to_ht l1, list_to_ht l2)
|
||||||
in
|
in
|
||||||
(* future keys are not stored anywhere until they are certified with a master_sig
|
(* future keys are not stored anywhere until they are certified with a master_sig
|
||||||
so we don't have any future key to load *)
|
so we don't have any future key to load *)
|
||||||
|
|
@ -167,8 +151,7 @@ module Make (Conn : Pg.CONN) = struct
|
||||||
dn_section_name_ht;
|
dn_section_name_ht;
|
||||||
}
|
}
|
||||||
in
|
in
|
||||||
Ok (Some t)
|
Ok t
|
||||||
| _, _, _ -> error_invalid_state
|
|
||||||
|
|
||||||
let sign_with_sm_key t s = EddsaSignature.sign ~key:t.sm_key s
|
let sign_with_sm_key t s = EddsaSignature.sign ~key:t.sm_key s
|
||||||
|
|
||||||
|
|
@ -284,16 +267,29 @@ module Make (Conn : Pg.CONN) = struct
|
||||||
List.iter (make_future_dn t) Config.Coin.all_coins;
|
List.iter (make_future_dn t) Config.Coin.all_coins;
|
||||||
t
|
t
|
||||||
|
|
||||||
let t =
|
let init () =
|
||||||
match load (module Conn) with
|
let dir = Config.secmod_dir in
|
||||||
| Ok None ->
|
let* b = Bos.OS.Dir.create ~mode:0o700 dir |> unwrap_err_msg in
|
||||||
|
if b then
|
||||||
|
Logs.info (fun m -> m "secmod: created directory `%a`" Fpath.pp dir);
|
||||||
|
let* l =
|
||||||
|
Bos.OS.Dir.contents ~dotfiles:false ~rel:false dir |> unwrap_err_msg
|
||||||
|
in
|
||||||
|
match List.is_empty l with
|
||||||
|
| true ->
|
||||||
|
Logs.info (fun m -> m "secmod: empty storage, generating fresh keys");
|
||||||
let t = make_new () in
|
let t = make_new () in
|
||||||
Logs.info (fun m -> m "secmod initialized with fresh keys");
|
Ok t
|
||||||
|
| false ->
|
||||||
|
Logs.info (fun m -> m "secmod: loading keys from storage");
|
||||||
|
load ()
|
||||||
|
|
||||||
|
let t =
|
||||||
|
match init () with
|
||||||
|
| Error e -> Fmt.failwith "secmod initialization failure: `%s`." e
|
||||||
|
| Ok t ->
|
||||||
|
Logs.info (fun m -> m "secmod initialized");
|
||||||
t
|
t
|
||||||
| Ok (Some t) ->
|
|
||||||
Logs.info (fun m -> m "secmod initialized from storage");
|
|
||||||
t
|
|
||||||
| Error e -> Fmt.failwith "secmod init failure: %s." e
|
|
||||||
|
|
||||||
let sm_pubkey = t.sm_pubkey
|
let sm_pubkey = t.sm_pubkey
|
||||||
let sign_with_sm_key s = sign_with_sm_key t s
|
let sign_with_sm_key s = sign_with_sm_key t s
|
||||||
|
|
@ -324,7 +320,9 @@ module Make (Conn : Pg.CONN) = struct
|
||||||
t.future_dn_ht |> Hashtbl.to_seq_values |> List.of_seq
|
t.future_dn_ht |> Hashtbl.to_seq_values |> List.of_seq
|
||||||
|
|
||||||
let find_signkey pub = Hashtbl.find_opt t.sk_ht pub
|
let find_signkey pub = Hashtbl.find_opt t.sk_ht pub
|
||||||
let find_denomination pub = Hashtbl.find_opt t.dn_ht pub
|
let find_denomination h_pub = Hashtbl.find_opt t.dn_ht h_pub
|
||||||
|
let find_future_signkey pub = Hashtbl.find_opt t.future_sk_ht pub
|
||||||
|
let find_future_denomination h_pub = Hashtbl.find_opt t.future_dn_ht h_pub
|
||||||
|
|
||||||
let certify_future_signkey pub master_sig =
|
let certify_future_signkey pub master_sig =
|
||||||
match
|
match
|
||||||
|
|
@ -453,7 +451,7 @@ module Make (Conn : Pg.CONN) = struct
|
||||||
let* () =
|
let* () =
|
||||||
Hashtbl.to_seq_values t.sk_key_ht
|
Hashtbl.to_seq_values t.sk_key_ht
|
||||||
|> List.of_seq
|
|> List.of_seq
|
||||||
|> List.mapi (fun i priv -> Data_file.write_eddsa (sk_key_fname i) priv)
|
|> List.mapi (fun i priv -> Data_file.write_eddsa (sk_fname i) priv)
|
||||||
|> list_iter Fun.id
|
|> list_iter Fun.id
|
||||||
in
|
in
|
||||||
let* () =
|
let* () =
|
||||||
|
|
@ -465,7 +463,7 @@ module Make (Conn : Pg.CONN) = struct
|
||||||
| None -> Error "invalid state, section_name not found"
|
| None -> Error "invalid state, section_name not found"
|
||||||
| Some s -> Ok s
|
| Some s -> Ok s
|
||||||
in
|
in
|
||||||
Data_file.write_rsa (dn_key_fname section_name) priv)
|
Data_file.write_rsa (dn_fname section_name) priv)
|
||||||
in
|
in
|
||||||
Logs.info (fun m -> m "saved secmod private keys data");
|
Logs.info (fun m -> m "saved secmod private keys data");
|
||||||
Ok ()
|
Ok ()
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ module type S = sig
|
||||||
val get_future_denominations : unit -> Api.FutureDenom.t list
|
val get_future_denominations : unit -> Api.FutureDenom.t list
|
||||||
val find_signkey : eddsa_pub -> Signkey.t option
|
val find_signkey : eddsa_pub -> Signkey.t option
|
||||||
val find_denomination : denom_hash -> Denomination.t option
|
val find_denomination : denom_hash -> Denomination.t option
|
||||||
|
val find_future_signkey : eddsa_pub -> Api.FutureSignKey.t option
|
||||||
|
val find_future_denomination : denom_hash -> Api.FutureDenom.t option
|
||||||
|
|
||||||
val certify_future_signkey :
|
val certify_future_signkey :
|
||||||
eddsa_pub ->
|
eddsa_pub ->
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue