Skip to content

Commit

Permalink
use digestif 1.2.0 API (#215)
Browse files Browse the repository at this point in the history
* use digestif 1.2.0 API

Co-authored-by: Reynir Björnsson <reynir@reynir.dk>
  • Loading branch information
hannesm and reynir authored Mar 19, 2024
1 parent fff44e5 commit 4b757b1
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 89 deletions.
24 changes: 13 additions & 11 deletions ec/mirage_crypto_ec.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion mirage-crypto-ec.opam
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
2 changes: 1 addition & 1 deletion mirage-crypto-pk.opam
Original file line number Diff line number Diff line change
Expand Up @@ -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"}
]
Expand Down
13 changes: 5 additions & 8 deletions pk/mirage_crypto_pk.mli
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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].
Expand Down
91 changes: 23 additions & 68 deletions pk/rsa.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down Expand Up @@ -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 =
Expand All @@ -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
Expand All @@ -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 =
Expand Down

0 comments on commit 4b757b1

Please sign in to comment.