use correct denomination hash

This commit is contained in:
swrup 2026-02-27 23:36:05 +01:00 committed by Swrup
parent 6bba30e6be
commit 71b9d59174
14 changed files with 142 additions and 61 deletions

View file

@ -113,6 +113,6 @@ let bin =
let open Bin in
record make_exn
|+ field beint64 (fun t -> t.value)
|+ field beint32 (fun t -> t.fraction)
|+ field beint32 (fun t -> Int32.mul t.fraction 1_000_000_l)
|+ field (bytes currency_len) (fun t -> pad_currency_string t.currency)
|> sealr

View file

@ -10,7 +10,6 @@
open Time
open Crypto
open Signatures
module DenominationHash = Hash.DenominationHash
let encode jsont v = Jsont_bytesrw.encode_string jsont v
let decode jsont v = Jsont_bytesrw.decode_string jsont v
@ -296,8 +295,6 @@ end
module DenominationKey = struct
type t = Rsa of RsaDenominationKey.t
let to_octets = function Rsa denom -> RsaPublicKey.to_octets denom.rsa_pub
let of_cs _v =
Jsont.Error.msg Jsont.Meta.none "CSDenominationKey are not supported"

View file

@ -209,13 +209,12 @@ module RsaPublicKey = struct
let of_octets = Binary_format_rsa.pub_of_octets
let to_b32 t = B32.encode (to_octets t)
let jsont =
let of_b32 s =
let* s = B32.decode s in
let+ v = of_octets s in
v
in
Jsont.of_of_string ~kind:"RsaPublicKey" of_b32 ~enc:to_b32
let of_b32 s =
let* s = B32.decode s in
let+ v = of_octets s in
v
let jsont = Jsont.of_of_string ~kind:"RsaPublicKey" of_b32 ~enc:to_b32
let caqti : t Caqti_type.t =
Caqti_type.custom
@ -257,6 +256,63 @@ module RsaSignature = struct
Jsont.of_of_string ~kind:"RsaSignature" of_b32 ~enc:to_b32
end
module DenominationHash : sig
type t
val bin : t Bin.t
val caqti : t Caqti_type.t
val jsont : t Jsont.t
val hash_of_rsa : RsaPublicKey.t -> t
val of_octets : string -> t
val to_octets : t -> string
val of_b32 : B32.t -> (t, string) result
val to_b32 : t -> B32.t
end = struct
open Digestif
type t = SHA512.t
type cipher =
| RSA
| CS [@ocaml.warning "-37"]
(* = GNUNET_CRYPTO_BSA_(RSA|CS) *)
let cipher_to_int32 = function RSA -> 1_l | CS -> 2_l
let hash_of_rsa pub =
let age_mask = 0_l in
let cipher = cipher_to_int32 RSA in
let pub = RsaPublicKey.to_octets pub in
let len = String.length pub in
let buf = Bytes.create (4 + 4 + len) in
Bytes.set_int32_be buf 0 age_mask;
Bytes.set_int32_be buf 4 cipher;
Bytes.blit_string pub 0 buf 8 len;
SHA512.digest_bytes buf
let of_octets s =
match SHA512.of_raw_string_opt s with
| None -> Fmt.failwith "H64.of_octets failure"
| Some t -> t
let to_octets = SHA512.to_raw_string
let of_b32 s = Result.map of_octets (B32.decode s)
let to_b32 t = B32.encode (to_octets t)
let bin =
let open Bin in
map (bytes 64) of_octets to_octets
let caqti =
let open Caqti_type in
custom
~encode:(fun v -> Ok (to_octets v))
~decode:(fun v -> Ok (of_octets v))
octets
let jsont = Jsont.of_of_string ~kind:"DenominationHash" of_b32 ~enc:to_b32
end
(* some type aliases, just for prettier .mli *)
type eddsa_priv = EddsaPrivateKey.t
type eddsa_pub = EddsaPublicKey.t
@ -264,4 +320,4 @@ type eddsa_sig = EddsaSignature.t
type rsa_priv = RsaPrivateKey.t
type rsa_pub = RsaPublicKey.t
type rsa_sig = RsaSignature.t
type denom_hash = Hash.DenominationHash.t
type denom_hash = DenominationHash.t

View file

@ -158,9 +158,7 @@ let denoms_of_denomgroups l =
lost= _;
}
->
let h_pub =
DenominationHash.hash (Crypto.RsaPublicKey.to_octets rsa_pub)
in
let h_pub = DenominationHash.hash_of_rsa rsa_pub in
{
pub= rsa_pub;
value;

View file

@ -10,6 +10,7 @@ module type S = sig
val of_octets : string -> t
val to_octets : t -> string
val of_b32 : B32.t -> (t, string) result
val to_b32 : t -> B32.t
end
module H32 = struct
@ -24,6 +25,7 @@ module H32 = struct
let to_octets = SHA256.to_raw_string
let of_b32 s = Result.map of_octets (B32.decode s)
let to_b32 t = B32.encode (to_octets t)
let bin =
let open Bin in
@ -37,9 +39,7 @@ module H32 = struct
~decode:(fun v -> Ok (of_octets v))
octets
let jsont =
let enc v = B32.encode (to_octets v) in
Jsont.of_of_string ~kind:"Hash 32" of_b32 ~enc
let jsont = Jsont.of_of_string ~kind:"Hash 32" of_b32 ~enc:to_b32
end
module H64 = struct
@ -54,6 +54,7 @@ module H64 = struct
let to_octets = SHA512.to_raw_string
let of_b32 s = Result.map of_octets (B32.decode s)
let to_b32 t = B32.encode (to_octets t)
let bin =
let open Bin in
@ -67,9 +68,7 @@ module H64 = struct
~decode:(fun v -> Ok (of_octets v))
octets
let jsont =
let enc v = B32.encode (to_octets v) in
Jsont.of_of_string ~kind:"Hash 64" of_b32 ~enc
let jsont = Jsont.of_of_string ~kind:"Hash 64" of_b32 ~enc:to_b32
end
(* C-terminated strings
@ -92,7 +91,6 @@ end
check which hash algorithm to use for each hash type *)
module FullPaytoHash : S = H32
module NormalizedPaytoHash : S = H32
module DenominationHash : S = H64
module PrivateContractHash : S = H64
module ExtensionsPolicyHash : S = H64
module MerchantWireHash : S = H64

View file

@ -58,7 +58,7 @@ module Denom_revoke = struct
Logs.info (fun m -> m "POST /management/denominations/$H_DENOM_PUB/revoke/");
let keys = Vif.Server.device Devices.keys server in
let res =
let* h_denom_pub = DenominationHash.of_b32 h_denom_pub in
let* h_denom_pub = Crypto.DenominationHash.of_b32 h_denom_pub in
let* v = Vif.Request.of_json req |> unwrap_err_msg in
let* () = verify keys h_denom_pub v in
let* () = do_ keys h_denom_pub v in

View file

@ -119,8 +119,7 @@ module Make (Conn : Pg.CONN) : S = struct
let make_future_dn (h_pub, (section_name, pub, start)) =
Logs.debug (fun m ->
m "make_future_dn: `%s`"
(B32.encode @@ Hash.DenominationHash.to_octets h_pub));
m "make_future_dn: `%s`" (DenominationHash.to_b32 h_pub));
let open Time in
let Config.Coin.
{
@ -320,7 +319,7 @@ module Make (Conn : Pg.CONN) : S = struct
let+ () = Pg.insert_denom conn dn |> unwrap_err_caqti in
Logs.info (fun m ->
m "certified denomination `%s`"
(B32.encode @@ Hash.DenominationHash.to_octets dn.h_pub));
(DenominationHash.to_b32 dn.h_pub));
())
let revoke_signkey pub revoked_sig =
@ -342,7 +341,6 @@ module Make (Conn : Pg.CONN) : S = struct
|> unwrap_err_caqti
in
Logs.info (fun m ->
m "revoked denomination `%s`"
(B32.encode @@ Hash.DenominationHash.to_octets h_pub));
m "revoked denomination `%s`" (DenominationHash.to_b32 h_pub));
()
end

View file

@ -7,7 +7,6 @@ module Log = (val Logs.src_log src : Logs.LOG)
open Syntax
open Crypto
open Time
module DenominationHash = Hash.DenominationHash
module Cfg = struct
open Config
@ -125,7 +124,7 @@ let get_key_dir_contents dir_fpath =
let gen_key ~section_name t1 t2 =
let bits = Cfg.rsa_keysize ~section_name in
let priv, pub = RsaPrivateKey.generate ~bits () in
let h_pub = DenominationHash.hash (RsaPublicKey.to_octets pub) in
let h_pub = DenominationHash.hash_of_rsa pub in
Log.debug (fun m ->
m "generated key (%a):@,`%s`" pp_filename (t1, t2)
(DenominationHash.to_octets h_pub |> B32.encode));
@ -179,7 +178,7 @@ let load_key ~section_name fpath =
| Some (t1, t2) ->
let+ priv = read_rsa fpath in
let pub = RsaPrivateKey.pub_of_priv priv in
let h_pub = DenominationHash.hash (RsaPublicKey.to_octets pub) in
let h_pub = DenominationHash.hash_of_rsa pub in
{ section_name; priv; pub; h_pub; t1; t2 }
let load_section section_name =

View file

@ -2,7 +2,7 @@ open Time
open Hash
module Aliases = struct
(* - Keys - *)
module DenominationHash = Crypto.DenominationHash
(* some of those are actuall ecdhe, or union of eddsa|ecdhe *)
open Crypto

View file

@ -29,7 +29,7 @@ offline_tool revoke-denom \
--output $b \
--rsa \
$rsa_pub
h_denom=$(dune exec offline -- hash64 $rsa_pub)
h_denom=$(dune exec offline -- denomination-hash $rsa_pub)
offline_tool upload --input $b --url $url"/management/denominations/"$h_denom"/revoke"
echo "[OK] /management/denominations/\$H_DENOM/revoke"

View file

@ -99,9 +99,8 @@ let () =
"3KHKZJZ30ABB4E56MA2V0EQWGCWH0QQG9P2ZHYHR186C5HZXJMM4N9WXAQTKS94QSV9Y17GGNXN5MB1PZZFG7Q0FY88QPKKRG4MYCPSMTZK5W59R0MJVNJ4P4AQM96TDG5W7RV8GSNR1QQZ1GNHW3CX6D6ZRTMXB2NKB5SSYTDJS79F5ZFBRZ4HVED9JBBPWSR79KVV5QQ4APBGHBCKGMF9NJJS53A1BVYHDEVYAGFYF2SNEP827ZP50FKJ5GKGV8NQ15ESEZ69AT7GJG0T3TZVENY2YN9CVR98W3BKEZ53J7VTANARG8SJS8AMJQ7S23P5HRJ7XE9KTNRNXKH49MXV9JHHYE5535N7AGWEKR47SBCGNF44Z7XJ9RV5BQV12ZRJKN4HBZQHDNCMH3QKX9Z6G64"
in
let open Crypto in
let pub =
rsa_public_key |> decode |> RsaPublicKey.of_octets |> Result.get_ok
in
let pub = rsa_public_key |> RsaPublicKey.of_b32 |> Result.get_ok in
assert (RsaPublicKey.to_b32 pub = rsa_public_key);
let bks = blinding_key_secret |> decode in
let msg = decode message_hash in
let bmsg = Fdh_rsa.blind_msg pub ~bks msg in
@ -123,3 +122,24 @@ let () =
assert (Result.is_ok res);
()
let () =
(* denomination-hash *)
(* test value generated by using taler-typescript-core (taler-util/src/taler-crypto.ts)
at SUPPORTED_EXCHANGE_PROTOCOL_VERSION = "31:0:6" *)
let rsa_pub =
"040000Y0EAK8KAVYJ3GBT5EJHEE6PQ843PDRPRNBFTPEPQEYCXZ30M0S7B80303C75D1CMK74ZJT7WA7DGWTEK7C26J6GVPR93FX99BWX48HGSN8R9C2V104X6WECY6TYPDCAM3FXEVFVVE610P1C8DPV2GKGWYJ5K91A470CBZ00EASZ6A013B7CZ6SAF7MJS20TBYTVWHN7CPJFV5Q7Q0AXGED999E1G3JC3PY5W4MVC16J5SG2SPRJMW5YGM0N1C64NCZBDBTA9HW009TEV5NBCNRQ9GK54AEDY84SVEF4V43ZCPMQ6M3ZWZGQNBX8EF19NCKVQN7MMRCDCY7A9MVJSDEBRZDQ4ZKRVT2C35225KM660ZQ731B9ZYH9JQ35WQ93MKH4PH4AWCJ8EH38JJA93R73M704002"
in
let h_pub =
"X1WDZ01CAP3V8ZRQMXX1CCWNKYDMYYKA6RG3X61N7RBARX85QCDJCDEAEDZNFYC2J22P2C930A13BAGQNVZMFG4M1YM28TCS2WK0T6R"
in
let open Crypto in
let h_pub' =
RsaPublicKey.of_b32 rsa_pub
|> Result.get_ok
|> DenominationHash.hash_of_rsa
|> DenominationHash.to_b32
in
assert (h_pub' = h_pub);
()

View file

@ -74,8 +74,18 @@ let keys content =
let denom_l = v.denominations |> Denomination.denoms_of_denomgroups in
let* () =
denom_l
|> list_iter
(Denomination.verify_denomination_key_validity ~key:v.master_public_key)
|> list_iter (fun dn ->
let open Denomination in
(*let to_int64 ts = ts |> Timestamp.to_s |> Option.get in*)
Fmt.pr "rsa_pub: %s@." (Crypto.RsaPublicKey.to_b32 dn.pub);
Fmt.pr "master_sig: %s@." (B32.encode @@ Obj.magic dn.master_sig);
(* amount bin fraction bad? *)
let* () =
Denomination.verify_denomination_key_validity ~key:v.master_public_key
dn
in
Fmt.pr "validated a denom@.";
Ok ())
in
let* () =
let last_issue_date =

View file

@ -59,6 +59,14 @@ module Arg = struct
Fmt.pf fmt "%s" s
in
Arg.Conv.make ~docv:"eddsa public key argument" ~parser ~pp ()
let rsa_pub =
let parser s = Crypto.RsaPublicKey.of_b32 s in
let pp fmt key =
let s = Crypto.RsaPublicKey.to_b32 key in
Fmt.pf fmt "%s" s
in
Arg.Conv.make ~docv:"rsa public key argument" ~parser ~pp ()
end
let master_key =
@ -147,11 +155,11 @@ let revoke_denom_cmd =
match is_rsa_pub with
| false -> Ok v
| true -> (
match B32.decode v with
match Crypto.RsaPublicKey.of_b32 v with
| Error e -> Error e
| Ok s ->
let h = Hash.DenominationHash.hash s in
let s = B32.encode (Hash.DenominationHash.to_octets h) in
| Ok rsa_pub ->
let h = Crypto.DenominationHash.hash_of_rsa rsa_pub in
let s = Crypto.DenominationHash.to_b32 h in
Ok s)
in
match res with
@ -159,21 +167,15 @@ let revoke_denom_cmd =
| Ok h_denom -> revoke_denom ~output ~master_key ~h_denom
(* just for tests... *)
let test_hash64_cmd =
let doc =
"Compute SHA-512, print output to stdout, input and output are \
Crockford-base32 encoded"
in
let s = Arg.(required & pos 0 (some string) None & info []) in
Cmd.make (Cmd.info "hash64" ~doc)
let test_denomination_hash_cmd =
let doc = "compute denomination hash (of rsa)" in
let rsa_pub = Arg.(required & pos 0 (some rsa_pub) None & info []) in
Cmd.make (Cmd.info "denomination-hash" ~doc)
@@
let+ s = s in
match B32.decode s with
| Error e -> Error e
| Ok s ->
let h = Hash.DenominationHash.hash s in
let s = B32.encode (Hash.DenominationHash.to_octets h) in
Fmt.pr "%s@." s; Ok ()
let+ rsa_pub = rsa_pub in
let h = Crypto.DenominationHash.hash_of_rsa rsa_pub in
let s = Crypto.DenominationHash.to_b32 h in
Fmt.pr "%s@." s; Ok ()
let revoke_signkey_cmd =
let doc = "Revoke signkey." in
@ -367,7 +369,7 @@ let cli =
disable_wire_cmd;
drain_cmd;
(* - *)
test_hash64_cmd;
test_denomination_hash_cmd;
]
let main () = Cmd.eval_result cli

View file

@ -30,9 +30,10 @@ module Future_keys = struct
fee_refund= _;
denom_secmod_sig;
} =
let h_denom_pub =
DenominationHash.hash (DenominationKey.to_octets denom_pub)
let rsa_pub =
match denom_pub with DenominationKey.Rsa denom -> denom.rsa_pub
in
let h_denom_pub = DenominationHash.hash_of_rsa rsa_pub in
let h_section_name = Hash.Cstring.H64.hash section_name in
let anchor_time = stamp_start in
let duration_withdraw =
@ -96,8 +97,10 @@ module Future_keys = struct
fee_refund;
denom_secmod_sig= _;
} =
let octets = DenominationKey.to_octets denom_pub in
let h_denom_pub = DenominationHash.hash octets in
let rsa_pub =
match denom_pub with DenominationKey.Rsa denom -> denom.rsa_pub
in
let h_denom_pub = DenominationHash.hash_of_rsa rsa_pub in
let master_sig =
let open Signatures.DenominationKeyValidity in
let master = EddsaPrivateKey.(pub_of_priv master_key) in