This commit is contained in:
swrup 2026-02-16 17:55:21 +01:00
parent 6bf2771f1c
commit 4ae149e97a
11 changed files with 40 additions and 165 deletions

View file

@ -5,7 +5,8 @@
option: correct use opt_mem or Jsont.option option: correct use opt_mem or Jsont.option
better types: better types:
- payto_uri - payto_uri
- uri *) - uri
use of monotonic time for some validity_start/_end fields *)
let protocol_version = "31:0:0" let protocol_version = "31:0:0"
@ -497,8 +498,6 @@ module AuditorSetupMessage = struct
auditor_name: string; auditor_name: string;
auditor_pub: EddsaPublicKey.t; auditor_pub: EddsaPublicKey.t;
master_sig: MasterAddAuditor.t; master_sig: MasterAddAuditor.t;
(* TODO monotonic time
something about using monotonic system time here! *)
validity_start: Timestamp.t; validity_start: Timestamp.t;
} }
@ -523,7 +522,6 @@ end
module AuditorTeardownMessage = struct module AuditorTeardownMessage = struct
type t = { type t = {
master_sig: MasterDelAuditor.t; master_sig: MasterDelAuditor.t;
(* TODO monotonic time *)
validity_end: Timestamp.t; validity_end: Timestamp.t;
} }
@ -630,7 +628,6 @@ module WireSetupMessage = struct
payto_uri: string; payto_uri: string;
master_sig_wire: MasterWireDetails.t; master_sig_wire: MasterWireDetails.t;
master_sig_add: MasterAddWire.t; master_sig_add: MasterAddWire.t;
(* TODO monotonic time *)
validity_start: Timestamp.t; validity_start: Timestamp.t;
bank_label: string option; bank_label: string option;
priority: int option; priority: int option;
@ -668,7 +665,6 @@ module WireTeardownMessage = struct
type t = { type t = {
payto_uri: string; payto_uri: string;
master_sig_del: MasterDelWire.t; master_sig_del: MasterDelWire.t;
(* TODO monotonic time *)
validity_end: Timestamp.t; validity_end: Timestamp.t;
} }

View file

@ -80,13 +80,7 @@ module Binary_format_rsa = struct
| _ -> assert false | _ -> assert false
end end
(* TODO key format
- check what is the exact format in GNUNET
- endianess issue? *)
module EddsaPublicKey = struct module EddsaPublicKey = struct
(* EdDSA and ECDHE public keys always point on Curve25519
and represented using the standard 256 bits Ed25519 compact format,
converted to Crockford Base32. *)
open Mirage_crypto_ec.Ed25519 open Mirage_crypto_ec.Ed25519
type t = pub type t = pub
@ -161,8 +155,6 @@ module EddsaSignature : sig
val bin : t Bin.t val bin : t Bin.t
val caqti : t Caqti_type.t val caqti : t Caqti_type.t
end = struct end = struct
(* TODO key format
endianess issue? *)
(* transmitted as 64-bytes base32 (* transmitted as 64-bytes base32
binary-encoded objects with just the R and S values *) binary-encoded objects with just the R and S values *)
type t = string type t = string

View file

@ -1,4 +1,3 @@
(* TODO use SHA512.of_raw_string_opt *)
open Digestif open Digestif
module type S = sig module type S = sig
@ -20,7 +19,7 @@ module H32 = struct
let of_octets s = let of_octets s =
match SHA256.of_raw_string_opt s with match SHA256.of_raw_string_opt s with
| None -> Fmt.failwith "H32.of_octets failure: data is not 32 bytes" | None -> Fmt.failwith "H32.of_octets failure"
| Some t -> t | Some t -> t
let to_octets = SHA256.to_raw_string let to_octets = SHA256.to_raw_string
@ -50,7 +49,7 @@ module H64 = struct
let of_octets s = let of_octets s =
match SHA512.of_raw_string_opt s with match SHA512.of_raw_string_opt s with
| None -> Fmt.failwith "H64.of_octets failure: data is not 64 bytes" | None -> Fmt.failwith "H64.of_octets failure"
| Some t -> t | Some t -> t
let to_octets = SHA512.to_raw_string let to_octets = SHA512.to_raw_string

View file

@ -167,25 +167,7 @@ module Keys_post = struct
let* () = list_iter (verify_signkey_signature sm) signkey_sigs in let* () = list_iter (verify_signkey_signature sm) signkey_sigs in
Ok () Ok ()
(* TODO move to test *) let do_ ~db_conn:_ (module Sm : Secmod.S)
let check_master_signatures_update ~db_conn (module Sm : Secmod.S) =
Sm.get_denoms_data ()
|> list_iter (fun denom ->
let error = Error "update_master_signatures sanity check failure" in
let* opt =
Pg.find_denom db_conn denom.Denom_data.h_pub |> unwrap_err_caqti
in
let* v = match opt with None -> error | Some v -> Ok v in
let check = function false -> error | true -> Ok () in
let* () =
check (Timestamp.compare v.stamp_start denom.stamp_start = 0)
in
let* () = check (v.value = denom.value) in
let* () = check (v.fee_refund = denom.fee_refund) in
let* () = check (v.age_mask = denom.age_mask) in
Ok ())
let do_ ~db_conn (module Sm : Secmod.S)
MasterSignatures.{ denom_sigs; signkey_sigs } = MasterSignatures.{ denom_sigs; signkey_sigs } =
let* () = let* () =
signkey_sigs signkey_sigs
@ -200,7 +182,6 @@ module Keys_post = struct
|> Sm.add_denom_master_signatures |> Sm.add_denom_master_signatures
in in
let* () = Sm.store () in let* () = Sm.store () in
let* () = check_master_signatures_update ~db_conn (module Sm) in
Ok () Ok ()
let jsont = MasterSignatures.jsont let jsont = MasterSignatures.jsont
@ -298,9 +279,7 @@ module Auditors = struct
h_auditor_url= Hash.Cstring.H64.hash auditor_url; h_auditor_url= Hash.Cstring.H64.hash auditor_url;
} }
(* TODO timestamps last_change +/- checks *) (* TODO monotonic time *)
(* todo: there is something about use of monotonic time
+ protection against replay attack that I don't understand *)
let do_ ~db_conn v = let do_ ~db_conn v =
let auditor_pub = v.AuditorSetupMessage.auditor_pub in let auditor_pub = v.AuditorSetupMessage.auditor_pub in
let validity_start = v.AuditorSetupMessage.validity_start in let validity_start = v.AuditorSetupMessage.validity_start in
@ -490,7 +469,7 @@ module Global_fees = struct
let jsont = GlobalFees.jsont let jsont = GlobalFees.jsont
(* TODO global_fees (* TODO better global_fees
ensure it is defined for the current time. ensure it is defined for the current time.
there should be only one global_fees for each moment in time there should be only one global_fees for each moment in time
and once set for a timeframe, it should not change. *) and once set for a timeframe, it should not change. *)
@ -518,7 +497,7 @@ module Wire = struct
bank_label= _; bank_label= _;
priority= _; priority= _;
} = } =
(* TODO wire *) (* TODO are those read from payto_uri? *)
let conversion_url = "" in let conversion_url = "" in
let credit_restrictions = "" in let credit_restrictions = "" in
let debit_restrictions = "" in let debit_restrictions = "" in
@ -553,9 +532,7 @@ module Wire = struct
match last_change_opt with match last_change_opt with
| Some _ -> Error "wire already setup" | Some _ -> Error "wire already setup"
| None -> | None ->
(* TODO wire *) let r =
let last_change = Timestamp.of_ptime (Ptime_clock.now ()) in
let v =
ExchangeWireAccount. ExchangeWireAccount.
{ {
payto_uri= v.payto_uri; payto_uri= v.payto_uri;
@ -567,7 +544,10 @@ module Wire = struct
priority= v.priority; priority= v.priority;
} }
in in
let+ () = Pg.insert_wire db_conn ~last_change v |> unwrap_err_caqti in let+ () =
Pg.insert_wire db_conn ~last_change:v.validity_start r
|> unwrap_err_caqti
in
() ()
let jsont = WireSetupMessage.jsont let jsont = WireSetupMessage.jsont

View file

@ -1,21 +1,13 @@
(* TODO (* TODO
check signed/unsigned ints
check there is no issues with signed/unsigned integers check endianness
can we avoid amount tuple boilerplate?
how to fix postgres/caqti tuple type? clean up caqti error type
try something with OID?
need to add boilerplate in each query for amounts
GNU Taler db-events?
it seems caqti/pgx does not support it
transaction transaction
should check validity of signatures got from db, for /management at least GNU Taler use of db-events?
it seems caqti/pgx does not support it *)
clean up caqti error type *)
(* TODO time
fix comparison with timestamp footgun *)
module type CONN = Caqti_miou.CONNECTION module type CONN = Caqti_miou.CONNECTION
@ -330,7 +322,6 @@ let update_wire =
let disable_wire = let disable_wire =
let disable_wire = let disable_wire =
(* TODO check syntax on this *)
Caqti_type.(t2 payto_uri time ->. unit) Caqti_type.(t2 payto_uri time ->. unit)
"UPDATE wire_accounts SET conversion_url=NULL, debit_restrictions=NULL, \ "UPDATE wire_accounts SET conversion_url=NULL, debit_restrictions=NULL, \
credit_restrictions=NULL, master_sig=NULL, bank_label=NULL, \ credit_restrictions=NULL, master_sig=NULL, bank_label=NULL, \

View file

@ -3,9 +3,6 @@ open Caqti_type
open Crypto open Crypto
open Api open Api
(* TODO
check that we use Caqti_type.octets for binary data *)
let amount : Amount.t t = let amount : Amount.t t =
let open Amount in let open Amount in
custom custom

View file

@ -1,8 +1,9 @@
(* TODO debug sig (* TODO signatures
check with taler-wallet-core/src/crypto/cryptoImplementation.js check with taler-wallet-core/src/crypto/cryptoImplementation.js
unsigned-ints check signed/unsigned ints
check endianness
can we skip defining a specific record for signatures and directly use Api records? *) better handling of decoding failure *)
open Hash open Hash
module Aliases = struct module Aliases = struct
@ -185,7 +186,7 @@ end
module DenominationKeyAnnouncement = struct module DenominationKeyAnnouncement = struct
module R = struct module R = struct
(* TODO CS: use purpose TALER_SIGNATURE_SM_CS_DENOMINATION_KEY *) (* CS: use purpose TALER_SIGNATURE_SM_CS_DENOMINATION_KEY *)
(* purpose.purpose = TALER_SIGNATURE_SM_RSA_DENOMINATION_KEY *) (* purpose.purpose = TALER_SIGNATURE_SM_RSA_DENOMINATION_KEY *)
type r = { type r = {
h_denom_pub: DenominationHash.t; h_denom_pub: DenominationHash.t;
@ -252,8 +253,7 @@ module DenominationKeyValidity = struct
fee_withdraw: AmountNBO.t; fee_withdraw: AmountNBO.t;
fee_deposit: AmountNBO.t; fee_deposit: AmountNBO.t;
fee_refresh: AmountNBO.t; fee_refresh: AmountNBO.t;
(* TODO debug sig (* TODO signatures taler doc *)
missing field from taler doc *)
fee_refund: AmountNBO.t; fee_refund: AmountNBO.t;
denom_hash: DenominationHash.t; denom_hash: DenominationHash.t;
} }
@ -424,8 +424,7 @@ end
module GlobalFees = struct module GlobalFees = struct
module R = struct module R = struct
(* TODO debug sig (* TODO signatures taler doc *)
taler doc *)
(* purpose.purpose = TALER_SIGNATURE_MASTER_GLOBAL_FEES *) (* purpose.purpose = TALER_SIGNATURE_MASTER_GLOBAL_FEES *)
type r = { type r = {
start_date: TimestampNBO.t; start_date: TimestampNBO.t;

View file

@ -4,13 +4,6 @@
(libraries mte fmt)) (libraries mte fmt))
(test (test
(name crypto) (name test_crypto)
(modules crypto) (modules test_crypto)
(libraries mte fmt)) (libraries mte fmt))
; TODO
; cram test?
; gcc -o a.out ./test/signatures.c && ./a.out > a.output
; rm ./a.out
; dune exec ./test/test.exe > b.output
; cmp -l a.output b.output

View file

@ -1,55 +0,0 @@
#include <stdio.h>
#include <stdint.h>
struct H64 {
uint8_t hash[64];
};
struct Hhh {
struct H64 hash;
};
struct Purpose {
uint32_t size;
uint32_t purpose;
};
struct PS {
struct Purpose purpose;
struct Hhh h;
uint32_t noreveal_index;
};
int main(void) {
struct Purpose purpose;
struct PS ps;
purpose.size = 3 * 4 + 64;
purpose.purpose = 1050;
struct Hhh h = {
.hash = {
.hash = {
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
}
}
};
uint32_t noreveal_index = 0;
ps.purpose = purpose;
ps.h = h;
ps.noreveal_index = noreveal_index;
fwrite(&ps, sizeof(ps), 1, stdout);
// printf("\n");
return 0;
}

View file

@ -97,19 +97,14 @@ let () =
() ()
(*
let () = let () =
let open Binary_formats.WithdrawConfirmationPS in let round_trip s =
let str64 = String.init 64 (fun i -> Char.unsafe_chr (i + 1)) in let s' = s |> B32.encode |> B32.decode |> Result.get_ok in
let dummy_t = { h_planchets= { hash= str64 }; noreveal_index= 0_l } in assert (s = s')
let size = Bin.size_of_value bin dummy_t |> Option.get in in
assert (size = 76); let s = String.init 0xff Char.chr in
round_trip s;
let s_l = List.init 0x0f (fun i -> String.init i Char.chr) in
List.iter round_trip s_l;
(* for cmp test with signatures.c output *)
(*
let raw_str = Bin.to_string bin dummy_t in
Printf.printf "%s" raw_str;
*)
() ()
*)

View file

@ -1,21 +1,9 @@
(* Test vectors taken from GNUnet:
https://git.gnunet.org/gnunet/gnunet/file/src/cli/util/crypto-test-vectors.json.html *)
let encode = B32.encode let encode = B32.encode
let decode s = B32.decode s |> Result.get_ok let decode s = B32.decode s |> Result.get_ok
let round_trip s =
let s' = s |> encode |> decode in
match s' = s with
| false -> Fmt.failwith "b32 round trip failure: @\nin :`%S`@\nout:`%S`" s' s
| true -> ()
let () =
let s = String.init 0xff Char.chr in
round_trip s;
let s_l = List.init 0x0f (fun i -> String.init i Char.chr) in
List.iter round_trip s_l; ()
(* test vectors from:
https://git.gnunet.org/gnunet/gnunet/file/src/cli/util/crypto-test-vectors.json.html *)
let () = let () =
(* hash *) (* hash *)
let input = "91JPRV3F5GG4EKJNDSJQ8" in let input = "91JPRV3F5GG4EKJNDSJQ8" in
@ -96,7 +84,7 @@ let () =
() ()
let () = let () =
(* rsa blinding *) (* rsa_blind_signing *)
(* rsa_private_key data is given in gcrypt sexpr format.. *) (* rsa_private_key data is given in gcrypt sexpr format.. *)
let message_hash = let message_hash =
"XKQMJ4CNTXBFE1V2WR6JS063J7PZQE4XMB5JH3RS5X0THQ1JQSQ69Y7KDBC9TYRJEZH48MEPY2SF4QHQ4VHXC0YQX5935MQEGP0AX6R" "XKQMJ4CNTXBFE1V2WR6JS063J7PZQE4XMB5JH3RS5X0THQ1JQSQ69Y7KDBC9TYRJEZH48MEPY2SF4QHQ4VHXC0YQX5935MQEGP0AX6R"