From 4b757b1a34556046e2ff9ef0ea691850a2100c2a Mon Sep 17 00:00:00 2001 From: Hannes Mehnert Date: Tue, 19 Mar 2024 11:36:28 +0100 Subject: [PATCH] use digestif 1.2.0 API (#215) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * use digestif 1.2.0 API Co-authored-by: Reynir Björnsson --- ec/mirage_crypto_ec.ml | 24 ++++++----- mirage-crypto-ec.opam | 2 +- mirage-crypto-pk.opam | 2 +- pk/mirage_crypto_pk.mli | 13 +++--- pk/rsa.ml | 91 +++++++++++------------------------------ 5 files changed, 43 insertions(+), 89 deletions(-) diff --git a/ec/mirage_crypto_ec.ml b/ec/mirage_crypto_ec.ml index 51e03ecd..25772ddc 100644 --- a/ec/mirage_crypto_ec.ml +++ b/ec/mirage_crypto_ec.ml @@ -967,15 +967,22 @@ module Ed25519 = struct type priv = string + let sha512 datas = + let open Digestif.SHA512 in + let buf = Bytes.create digest_size in + let ctx = List.fold_left (feed_string ?off:None ?len:None) empty datas in + get_into_bytes ctx buf; + buf + (* RFC 8032 *) let public secret = (* section 5.1.5 *) (* step 1 *) - let h = Digestif.SHA512.(digest_string secret |> to_raw_string) in + let h = sha512 [ secret ] in (* step 2 *) let s, rest = - Bytes.unsafe_of_string (String.sub h 0 key_len), - String.sub h key_len (String.length h - key_len) + Bytes.sub h 0 key_len, + Bytes.unsafe_to_string (Bytes.sub h key_len (Bytes.length h - key_len)) in Bytes.set_uint8 s 0 ((Bytes.get_uint8 s 0) land 248); Bytes.set_uint8 s 31 (((Bytes.get_uint8 s 31) land 127) lor 64); @@ -1009,13 +1016,11 @@ module Ed25519 = struct let sign ~key msg = (* section 5.1.6 *) let pub, (s, prefix) = public key in - let r = Digestif.SHA512.(digest_string (String.concat "" [ prefix; msg ]) |> to_raw_string) in - let r = Bytes.unsafe_of_string r in + let r = sha512 [ prefix; msg ] in reduce_l r; let r = Bytes.unsafe_to_string r in let r_big = scalar_mult_base_to_bytes r in - let k = Digestif.SHA512.(digest_string (String.concat "" [ r_big; pub; msg]) |> to_raw_string) in - let k = Bytes.unsafe_of_string k in + let k = sha512 [ r_big; pub; msg] in reduce_l k; let k = Bytes.unsafe_to_string k in let s_out = muladd k s r in @@ -1041,10 +1046,7 @@ module Ed25519 = struct String.equal s'' s' in if s_smaller_l then begin - let k = - Digestif.SHA512.(digest_string (String.concat "" [ r ; key ; msg ]) |> to_raw_string) - in - let k = Bytes.unsafe_of_string k in + let k = sha512 [ r ; key ; msg ] in reduce_l k; let k = Bytes.unsafe_to_string k in let success, r' = double_scalar_mult k key s in diff --git a/mirage-crypto-ec.opam b/mirage-crypto-ec.opam index 0a8551de..a248dafe 100644 --- a/mirage-crypto-ec.opam +++ b/mirage-crypto-ec.opam @@ -30,7 +30,7 @@ depends: [ "dune-configurator" "eqaf" {>= "0.7"} "mirage-crypto-rng" {=version} - "digestif" {>= "1.1.4"} + "digestif" {>= "1.2.0"} "hex" {with-test} "alcotest" {with-test & >= "0.8.1"} "ppx_deriving_yojson" {with-test} diff --git a/mirage-crypto-pk.opam b/mirage-crypto-pk.opam index 2edce658..e3a3b538 100644 --- a/mirage-crypto-pk.opam +++ b/mirage-crypto-pk.opam @@ -20,7 +20,7 @@ depends: [ "randomconv" {with-test & >= "0.2.0"} "mirage-crypto" {=version} "mirage-crypto-rng" {=version} - "digestif" {>= "1.1.4"} + "digestif" {>= "1.2.0"} "zarith" {>= "1.13"} "eqaf" {>= "0.8"} ] diff --git a/pk/mirage_crypto_pk.mli b/pk/mirage_crypto_pk.mli index 9457b955..5980b9a5 100644 --- a/pk/mirage_crypto_pk.mli +++ b/pk/mirage_crypto_pk.mli @@ -187,15 +187,12 @@ module Rsa : sig was produced with the given [key] as per {{!sig_encode}sig_encode}, or [None] *) - type hash = [ `MD5 | `SHA1 | `SHA224 | `SHA256 | `SHA384 | `SHA512 ] - (** The type of supported hash algorithms. *) - - val min_key : hash -> bits + val min_key : [< Digestif.hash' > `MD5 `SHA1 `SHA224 `SHA256 `SHA384 `SHA512 ] -> bits (** [min_key hash] is the minimum key size required by {{!sign}[sign]}. *) val sign : ?crt_hardening:bool -> ?mask:mask -> - hash:hash -> key:priv -> string or_digest -> - string + hash:[< Digestif.hash' > `MD5 `SHA1 `SHA224 `SHA256 `SHA384 `SHA512 ] -> + key:priv -> string or_digest -> string (** [sign ~crt_hardening ~mask ~hash ~key message] is the PKCS 1.5 signature of [message], signed by the [key], using the hash function [hash]. This is the full signature, with the ASN-encoded message digest @@ -208,8 +205,8 @@ module Rsa : sig @raise Invalid_argument if message is a [`Digest] of the wrong size. *) - val verify : hashp:(hash -> bool) -> key:pub -> - signature:string -> string or_digest -> bool + val verify : hashp:([< Digestif.hash' > `MD5 `SHA1 `SHA224 `SHA256 `SHA384 `SHA512 ] -> bool) -> + key:pub -> signature:string -> string or_digest -> bool (** [verify ~hashp ~key ~signature message] checks that [signature] is the PKCS 1.5 signature of the [message] under the given [key]. diff --git a/pk/rsa.ml b/pk/rsa.ml index cd268e5f..cc0d7d35 100644 --- a/pk/rsa.ml +++ b/pk/rsa.ml @@ -23,11 +23,6 @@ module Digest_or (H : Digestif.S) = struct invalid_arg "(`Digest _): %d bytes, expecting %d" n m end -let digest_or (type a) ~(hash : a Digestif.hash) = - let module H = (val Digestif.module_of hash) in - let module D = Digest_or (H) in - D.digest_or - exception Insufficient_key type pub = { e : Z.t ; n : Z.t } @@ -274,69 +269,23 @@ module PKCS1 = struct String.length msg >= String.length asn && String.equal asn (String.sub msg 0 (String.length asn)) - type hash = [ `MD5 | `SHA1 | `SHA224 | `SHA256 | `SHA384 | `SHA512 ] - - let digestif_or = function - | `MD5 -> digest_or ~hash:Digestif.md5 - | `SHA1 -> digest_or ~hash:Digestif.sha1 - | `SHA224 -> digest_or ~hash:Digestif.sha224 - | `SHA256 -> digest_or ~hash:Digestif.sha256 - | `SHA384 -> digest_or ~hash:Digestif.sha384 - | `SHA512 -> digest_or ~hash:Digestif.sha512 - - let digestif_size = function - | `MD5 -> - let module H = (val Digestif.module_of Digestif.md5) in - H.digest_size - | `SHA1 -> - let module H = (val Digestif.module_of Digestif.sha1) in - H.digest_size - | `SHA224 -> - let module H = (val Digestif.module_of Digestif.sha224) in - H.digest_size - | `SHA256 -> - let module H = (val Digestif.module_of Digestif.sha256) in - H.digest_size - | `SHA384 -> - let module H = (val Digestif.module_of Digestif.sha384) in - H.digest_size - | `SHA512 -> - let module H = (val Digestif.module_of Digestif.sha512) in - H.digest_size - let asn_of_hash, detect = - let md5 = "\x30\x20\x30\x0c\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05\x05\x00\x04\x10" - and sha1 = "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14" - and sha224 = "\x30\x2d\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04\x05\x00\x04\x1c" - and sha256 = "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20" - and sha384 = "\x30\x41\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02\x05\x00\x04\x30" - and sha512 = "\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03\x05\x00\x04\x40" + let map = [ + `MD5, "\x30\x20\x30\x0c\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05\x05\x00\x04\x10" ; + `SHA1, "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14" ; + `SHA224, "\x30\x2d\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04\x05\x00\x04\x1c" ; + `SHA256, "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20" ; + `SHA384, "\x30\x41\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02\x05\x00\x04\x30" ; + `SHA512, "\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03\x05\x00\x04\x40" + ] in - (function - | `MD5 -> md5 - | `SHA1 -> sha1 - | `SHA224 -> sha224 - | `SHA256 -> sha256 - | `SHA384 -> sha384 - | `SHA512 -> sha512), - (fun buf -> - if is_prefix md5 buf then - Some (`MD5, md5) - else if is_prefix sha1 buf then - Some (`SHA1, sha1) - else if is_prefix sha224 buf then - Some (`SHA224, sha224) - else if is_prefix sha256 buf then - Some (`SHA256, sha256) - else if is_prefix sha384 buf then - Some (`SHA384, sha384) - else if is_prefix sha512 buf then - Some (`SHA512, sha512) - else - None) + (fun h -> List.assoc h map), + (fun buf -> List.find_opt (fun (_, d) -> is_prefix d buf) map) let sign ?(crt_hardening = true) ?mask ~hash ~key msg = - let msg' = asn_of_hash hash ^ digestif_or hash msg in + let module H = (val Digestif.module_of_hash' (hash :> Digestif.hash')) in + let module D = Digest_or(H) in + let msg' = asn_of_hash hash ^ D.digest_or msg in sig_encode ~crt_hardening ?mask ~key msg' let verify ~hashp ~key ~signature msg = @@ -346,11 +295,14 @@ module PKCS1 = struct Option.value (sig_decode ~key signature >>= fun buf -> detect buf >>| fun (hash, asn) -> - hashp hash && Eqaf.equal (asn ^ digestif_or hash msg) buf) + let module H = (val Digestif.module_of_hash' (hash :> Digestif.hash')) in + let module D = Digest_or(H) in + hashp hash && Eqaf.equal (asn ^ D.digest_or msg) buf) ~default:false let min_key hash = - (String.length (asn_of_hash hash) + digestif_size hash + min_pad + 2) * 8 + 1 + let module H = (val Digestif.module_of_hash' (hash :> Digestif.hash')) in + (String.length (asn_of_hash hash) + H.digest_size + min_pad + 2) * 8 + 1 end module MGF1 (H : Digestif.S) = struct @@ -364,8 +316,11 @@ module MGF1 (H : Digestif.S) = struct let mgf ~seed len = let rec go acc c = function | 0 -> Bytes.sub (Bytes.concat Bytes.empty (List.rev acc)) 0 len - | n -> let h = Bytes.unsafe_of_string H.(digesti_string (iter2 seed (repr c)) |> to_raw_string) in - go (h :: acc) Int32.(succ c) (pred n) in + | n -> + let h = Bytes.create H.digest_size in + H.get_into_bytes (H.feedi_string H.empty (iter2 seed (repr c))) h; + go (h :: acc) Int32.(succ c) (pred n) + in go [] 0l (len // H.digest_size) let mask ~seed buf =