From 7d7dd2400c2a7c83273e14efe3c8d3bb61ac4d91 Mon Sep 17 00:00:00 2001 From: swrup Date: Tue, 10 Feb 2026 16:47:08 +0100 Subject: [PATCH] hash: use of_raw_string_opt --- src/b32.ml | 4 ++++ src/hash.ml | 20 ++++++++------------ test/b32.ml | 15 --------------- test/crypto.ml | 28 ++++++++++++++++++++++++++++ test/dune | 6 +++--- 5 files changed, 43 insertions(+), 30 deletions(-) delete mode 100644 test/b32.ml create mode 100644 test/crypto.ml diff --git a/src/b32.ml b/src/b32.ml index 12ef4294..6bd06400 100644 --- a/src/b32.ml +++ b/src/b32.ml @@ -29,6 +29,10 @@ let decode s = | c -> c) s in + (* restore padding for base32 lib *) + let n = 8 - (String.length s mod 8) in + let pad = String.make n '=' in + let s = s ^ pad in match Base32.decode ~alphabet ~off:0 ~len:(String.length s) s with | Error (`Msg e) -> Error e | Ok v -> Ok v diff --git a/src/hash.ml b/src/hash.ml index ca32519f..0da809df 100644 --- a/src/hash.ml +++ b/src/hash.ml @@ -1,3 +1,4 @@ +(* TODO use SHA512.of_raw_string_opt *) open Digestif module type S = sig @@ -18,9 +19,9 @@ module H32 = struct let hash s = SHA256.(digest_string s) let of_octets s = - match String.length s = 32 with - | false -> Fmt.failwith "Hash.of_octets failure: data is not 32 bytes" - | true -> SHA256.of_raw_string s + match SHA256.of_raw_string_opt s with + | None -> Fmt.failwith "H32.of_octets failure: data is not 32 bytes" + | Some t -> t let to_octets = SHA256.to_raw_string let of_b32 s = Result.map of_octets (B32.decode s) @@ -48,16 +49,11 @@ module H64 = struct let hash s = SHA512.(digest_string s) let of_octets s = - match String.length s = 64 with - | false -> Fmt.failwith "Hash.of_octets failure: data is not 64 bytes" - | true -> SHA512.of_raw_string s - - let to_octets v = - let s = SHA512.to_raw_string v in - match String.length s = 64 with - | false -> Fmt.failwith "Hash.to_octets failure: data is not 64 bytes" - | true -> s + match SHA512.of_raw_string_opt s with + | None -> Fmt.failwith "H64.of_octets failure: data is not 64 bytes" + | Some t -> t + let to_octets = SHA512.to_raw_string let of_b32 s = Result.map of_octets (B32.decode s) let bin = diff --git a/test/b32.ml b/test/b32.ml deleted file mode 100644 index c6986084..00000000 --- a/test/b32.ml +++ /dev/null @@ -1,15 +0,0 @@ -let () = - let id s = s |> B32.encode |> B32.decode |> Result.get_ok in - let f s = - let s' = id s in - match s' = s with - | false -> - Fmt.failwith "b32 round trip failure: @\nin :`%S`@\nout:`%S`" s' s - | true -> () - in - let s = String.init 0xff Char.chr in - let s_l = List.init 0x0f (fun i -> String.init i Char.chr) in - f s; - List.iter f s_l; - - () diff --git a/test/crypto.ml b/test/crypto.ml new file mode 100644 index 00000000..e2d007c9 --- /dev/null +++ b/test/crypto.ml @@ -0,0 +1,28 @@ +let round_trip s = + let s' = s |> B32.encode |> B32.decode |> Result.get_ok 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; () + +let () = + let input = "91JPRV3F5GG4EKJNDSJQ8" in + let expected = + "D0R24RZ1TPASVQ2NY56CT8AJDYZE9ZGDB0GVZ05E9D4YGZQW2RC5YFPQ0Q86EPW836DY7VYQTNFFJT3ZR2K508F4JVS5JNJKYN2MMFR" + in + let output = + input + |> B32.decode + |> Result.get_ok + |> Hash.H64.hash + |> Hash.H64.to_octets + |> B32.encode + in + assert (output = expected); + + () diff --git a/test/dune b/test/dune index bec41ef4..1aa7506a 100644 --- a/test/dune +++ b/test/dune @@ -4,9 +4,9 @@ (libraries mte fmt)) (test - (name b32) - (modules b32) - (libraries b32 fmt)) + (name crypto) + (modules crypto) + (libraries mte fmt)) ; TODO ; cram test?