This commit is contained in:
parent
aa2ff7b2f0
commit
2f3113f55d
11742 changed files with 1223940 additions and 0 deletions
5
unikernel/duniverse/mirage-crypto/pk/common.ml
Normal file
5
unikernel/duniverse/mirage-crypto/pk/common.ml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
let rec until p f = let r = f () in if p r then r else until p f
|
||||
|
||||
let guard p err = if p then Ok () else Error err
|
||||
|
||||
let ( let* ) = Result.bind
|
||||
695
unikernel/duniverse/mirage-crypto/pk/dh.ml
Normal file
695
unikernel/duniverse/mirage-crypto/pk/dh.ml
Normal file
|
|
@ -0,0 +1,695 @@
|
|||
open Mirage_crypto.Uncommon
|
||||
|
||||
open Common
|
||||
|
||||
exception Invalid_key
|
||||
|
||||
type group = {
|
||||
p : Z.t ; (* The prime modulus *)
|
||||
gg : Z.t ; (* Group generator *)
|
||||
q : Z.t option ; (* `gg`'s order, maybe *)
|
||||
}
|
||||
|
||||
let group ~p ~gg ?q () =
|
||||
let* () =
|
||||
guard (Z.(p > zero && is_odd p) && Z_extra.pseudoprime p)
|
||||
(`Msg "invalid prime")
|
||||
in
|
||||
let* () =
|
||||
guard Z.(one < gg && gg < p) (`Msg "invalid generator")
|
||||
in
|
||||
Ok { p ; gg ; q }
|
||||
|
||||
type secret = { group : group ; x : Z.t }
|
||||
|
||||
(*
|
||||
* Estimates of equivalent-strength exponent sizes for the moduli sizes.
|
||||
* 2048-8192 are taken from "Negotiated FF DHE Parameters for TLS."
|
||||
* Sizes above and below are further guesswork.
|
||||
*)
|
||||
let exp_equivalent = [
|
||||
(1024, 180); (2048, 225); (3072, 275); (4096, 325); (6144, 375); (8192, 400)
|
||||
]
|
||||
and exp_equivalent_max = 512
|
||||
|
||||
let exp_size bits =
|
||||
try snd @@ List.find (fun (g, _) -> g >= bits) exp_equivalent
|
||||
with Not_found -> exp_equivalent_max
|
||||
|
||||
let modulus_size { p; _ } = Z.numbits p
|
||||
|
||||
(*
|
||||
* Current thinking:
|
||||
* g^y < 0 || g^y >= p : obviously not computed mod p
|
||||
* g^y = 0 || g^y = 1 : shared secret is 0, resp. 1
|
||||
* g^y = p - 1 : order of g^y is 2
|
||||
* g^y = g : y mod (p-1) is 1
|
||||
*)
|
||||
let bad_public_key { p; gg; _ } ggx =
|
||||
ggx <= Z.one || ggx >= Z.(pred p) || ggx = gg
|
||||
|
||||
let valid_secret { p ; _ } s =
|
||||
Z.(one < s && s < p)
|
||||
|
||||
let key_of_secret_z ({ p; gg; _ } as group) x =
|
||||
if valid_secret group x then
|
||||
match Z.(powm_sec gg x p) with
|
||||
| ggx when bad_public_key group ggx -> raise_notrace Invalid_key
|
||||
| ggx -> ({ group ; x }, Z_extra.to_octets_be ggx)
|
||||
else
|
||||
raise_notrace Invalid_key
|
||||
|
||||
let key_of_secret group ~s =
|
||||
(* catches Invalid_private_key and re-raises with exception trace: *)
|
||||
try key_of_secret_z group (Z_extra.of_octets_be s)
|
||||
with Invalid_key -> raise Invalid_key
|
||||
|
||||
(* XXX
|
||||
* - slightly weird distribution when bits > |q|
|
||||
* - exponentiation time
|
||||
*)
|
||||
let rec gen_key ?g ?bits ({ p; q; _ } as group) =
|
||||
let pb = Z.numbits p in
|
||||
let s =
|
||||
imin (Option.value bits ~default:pb |> exp_size)
|
||||
(Option.fold ~none:pb ~some:Z.numbits q)
|
||||
|> Z_extra.gen_bits ?g ~msb:1
|
||||
in
|
||||
try key_of_secret_z group s with Invalid_key -> gen_key ?g ?bits group
|
||||
|
||||
let shared { group ; x } cs =
|
||||
match Z_extra.of_octets_be cs with
|
||||
| ggy when bad_public_key group ggy -> None
|
||||
| ggy -> Some (Z_extra.to_octets_be (Z.powm_sec ggy x group.p))
|
||||
|
||||
(* Finds a safe prime with [p = 2q + 1] and [2^q = 1 mod p]. *)
|
||||
let rec gen_group ?g ~bits () =
|
||||
let gg = Z.(~$2)
|
||||
and (q, p) = Z_extra.safe_prime ?g (imax bits 1) in
|
||||
if Z.(powm gg q p = one) then { p; gg; q = Some q } else gen_group ?g ~bits ()
|
||||
|
||||
module Group = struct
|
||||
|
||||
(* Safe-prime-style group: p = 2q + 1 && gg = 2 && gg^q = 1 mod p *)
|
||||
let s_group ~p =
|
||||
let p = Z_extra.of_octets_be p in
|
||||
{ p ; gg = Z.(~$2) ; q = Some Z.(pred p / ~$2) }
|
||||
|
||||
(* Any old group. *)
|
||||
let group ~p ~gg ~q =
|
||||
let f = Z_extra.of_octets_be in
|
||||
{ p = f p ; gg = f gg ; q = Some (f q) }
|
||||
|
||||
(* RFC2409 *)
|
||||
|
||||
let oakley_1 =
|
||||
(* 2^768 - 2 ^704 - 1 + 2^64 * { [2^638 pi] + 149686 } *)
|
||||
s_group ~p:
|
||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xC9\x0F\xDA\xA2\x21\x68\xC2\x34\
|
||||
\xC4\xC6\x62\x8B\x80\xDC\x1C\xD1\x29\x02\x4E\x08\x8A\x67\xCC\x74\
|
||||
\x02\x0B\xBE\xA6\x3B\x13\x9B\x22\x51\x4A\x08\x79\x8E\x34\x04\xDD\
|
||||
\xEF\x95\x19\xB3\xCD\x3A\x43\x1B\x30\x2B\x0A\x6D\xF2\x5F\x14\x37\
|
||||
\x4F\xE1\x35\x6D\x6D\x51\xC2\x45\xE4\x85\xB5\x76\x62\x5E\x7E\xC6\
|
||||
\xF4\x4C\x42\xE9\xA6\x3A\x36\x20\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
||||
|
||||
let oakley_2 =
|
||||
(* 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 }. *)
|
||||
s_group ~p:
|
||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xC9\x0F\xDA\xA2\x21\x68\xC2\x34\
|
||||
\xC4\xC6\x62\x8B\x80\xDC\x1C\xD1\x29\x02\x4E\x08\x8A\x67\xCC\x74\
|
||||
\x02\x0B\xBE\xA6\x3B\x13\x9B\x22\x51\x4A\x08\x79\x8E\x34\x04\xDD\
|
||||
\xEF\x95\x19\xB3\xCD\x3A\x43\x1B\x30\x2B\x0A\x6D\xF2\x5F\x14\x37\
|
||||
\x4F\xE1\x35\x6D\x6D\x51\xC2\x45\xE4\x85\xB5\x76\x62\x5E\x7E\xC6\
|
||||
\xF4\x4C\x42\xE9\xA6\x37\xED\x6B\x0B\xFF\x5C\xB6\xF4\x06\xB7\xED\
|
||||
\xEE\x38\x6B\xFB\x5A\x89\x9F\xA5\xAE\x9F\x24\x11\x7C\x4B\x1F\xE6\
|
||||
x49\x28\x66\x51\xEC\xE6\x53\x81\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
||||
|
||||
(* RFC3526 *)
|
||||
|
||||
let oakley_5 =
|
||||
(* 2^1536 - 2^1472 - 1 + 2^64 * { [2^1406 pi] + 741804 } *)
|
||||
s_group ~p:
|
||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xC9\x0F\xDA\xA2\x21\x68\xC2\x34\
|
||||
\xC4\xC6\x62\x8B\x80\xDC\x1C\xD1\x29\x02\x4E\x08\x8A\x67\xCC\x74\
|
||||
\x02\x0B\xBE\xA6\x3B\x13\x9B\x22\x51\x4A\x08\x79\x8E\x34\x04\xDD\
|
||||
\xEF\x95\x19\xB3\xCD\x3A\x43\x1B\x30\x2B\x0A\x6D\xF2\x5F\x14\x37\
|
||||
\x4F\xE1\x35\x6D\x6D\x51\xC2\x45\xE4\x85\xB5\x76\x62\x5E\x7E\xC6\
|
||||
\xF4\x4C\x42\xE9\xA6\x37\xED\x6B\x0B\xFF\x5C\xB6\xF4\x06\xB7\xED\
|
||||
\xEE\x38\x6B\xFB\x5A\x89\x9F\xA5\xAE\x9F\x24\x11\x7C\x4B\x1F\xE6\
|
||||
\x49\x28\x66\x51\xEC\xE4\x5B\x3D\xC2\x00\x7C\xB8\xA1\x63\xBF\x05\
|
||||
\x98\xDA\x48\x36\x1C\x55\xD3\x9A\x69\x16\x3F\xA8\xFD\x24\xCF\x5F\
|
||||
\x83\x65\x5D\x23\xDC\xA3\xAD\x96\x1C\x62\xF3\x56\x20\x85\x52\xBB\
|
||||
\x9E\xD5\x29\x07\x70\x96\x96\x6D\x67\x0C\x35\x4E\x4A\xBC\x98\x04\
|
||||
\xF1\x74\x6C\x08\xCA\x23\x73\x27\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
||||
|
||||
let oakley_14 =
|
||||
(* 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 } *)
|
||||
s_group ~p:
|
||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xC9\x0F\xDA\xA2\x21\x68\xC2\x34\
|
||||
\xC4\xC6\x62\x8B\x80\xDC\x1C\xD1\x29\x02\x4E\x08\x8A\x67\xCC\x74\
|
||||
\x02\x0B\xBE\xA6\x3B\x13\x9B\x22\x51\x4A\x08\x79\x8E\x34\x04\xDD\
|
||||
\xEF\x95\x19\xB3\xCD\x3A\x43\x1B\x30\x2B\x0A\x6D\xF2\x5F\x14\x37\
|
||||
\x4F\xE1\x35\x6D\x6D\x51\xC2\x45\xE4\x85\xB5\x76\x62\x5E\x7E\xC6\
|
||||
\xF4\x4C\x42\xE9\xA6\x37\xED\x6B\x0B\xFF\x5C\xB6\xF4\x06\xB7\xED\
|
||||
\xEE\x38\x6B\xFB\x5A\x89\x9F\xA5\xAE\x9F\x24\x11\x7C\x4B\x1F\xE6\
|
||||
\x49\x28\x66\x51\xEC\xE4\x5B\x3D\xC2\x00\x7C\xB8\xA1\x63\xBF\x05\
|
||||
\x98\xDA\x48\x36\x1C\x55\xD3\x9A\x69\x16\x3F\xA8\xFD\x24\xCF\x5F\
|
||||
\x83\x65\x5D\x23\xDC\xA3\xAD\x96\x1C\x62\xF3\x56\x20\x85\x52\xBB\
|
||||
\x9E\xD5\x29\x07\x70\x96\x96\x6D\x67\x0C\x35\x4E\x4A\xBC\x98\x04\
|
||||
\xF1\x74\x6C\x08\xCA\x18\x21\x7C\x32\x90\x5E\x46\x2E\x36\xCE\x3B\
|
||||
\xE3\x9E\x77\x2C\x18\x0E\x86\x03\x9B\x27\x83\xA2\xEC\x07\xA2\x8F\
|
||||
\xB5\xC5\x5D\xF0\x6F\x4C\x52\xC9\xDE\x2B\xCB\xF6\x95\x58\x17\x18\
|
||||
\x39\x95\x49\x7C\xEA\x95\x6A\xE5\x15\xD2\x26\x18\x98\xFA\x05\x10\
|
||||
\x15\x72\x8E\x5A\x8A\xAC\xAA\x68\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
||||
|
||||
let oakley_15 =
|
||||
(* 2^3072 - 2^3008 - 1 + 2^64 * { [2^2942 pi] + 1690314 } *)
|
||||
s_group ~p:
|
||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xC9\x0F\xDA\xA2\x21\x68\xC2\x34\
|
||||
\xC4\xC6\x62\x8B\x80\xDC\x1C\xD1\x29\x02\x4E\x08\x8A\x67\xCC\x74\
|
||||
\x02\x0B\xBE\xA6\x3B\x13\x9B\x22\x51\x4A\x08\x79\x8E\x34\x04\xDD\
|
||||
\xEF\x95\x19\xB3\xCD\x3A\x43\x1B\x30\x2B\x0A\x6D\xF2\x5F\x14\x37\
|
||||
\x4F\xE1\x35\x6D\x6D\x51\xC2\x45\xE4\x85\xB5\x76\x62\x5E\x7E\xC6\
|
||||
\xF4\x4C\x42\xE9\xA6\x37\xED\x6B\x0B\xFF\x5C\xB6\xF4\x06\xB7\xED\
|
||||
\xEE\x38\x6B\xFB\x5A\x89\x9F\xA5\xAE\x9F\x24\x11\x7C\x4B\x1F\xE6\
|
||||
\x49\x28\x66\x51\xEC\xE4\x5B\x3D\xC2\x00\x7C\xB8\xA1\x63\xBF\x05\
|
||||
\x98\xDA\x48\x36\x1C\x55\xD3\x9A\x69\x16\x3F\xA8\xFD\x24\xCF\x5F\
|
||||
\x83\x65\x5D\x23\xDC\xA3\xAD\x96\x1C\x62\xF3\x56\x20\x85\x52\xBB\
|
||||
\x9E\xD5\x29\x07\x70\x96\x96\x6D\x67\x0C\x35\x4E\x4A\xBC\x98\x04\
|
||||
\xF1\x74\x6C\x08\xCA\x18\x21\x7C\x32\x90\x5E\x46\x2E\x36\xCE\x3B\
|
||||
\xE3\x9E\x77\x2C\x18\x0E\x86\x03\x9B\x27\x83\xA2\xEC\x07\xA2\x8F\
|
||||
\xB5\xC5\x5D\xF0\x6F\x4C\x52\xC9\xDE\x2B\xCB\xF6\x95\x58\x17\x18\
|
||||
\x39\x95\x49\x7C\xEA\x95\x6A\xE5\x15\xD2\x26\x18\x98\xFA\x05\x10\
|
||||
\x15\x72\x8E\x5A\x8A\xAA\xC4\x2D\xAD\x33\x17\x0D\x04\x50\x7A\x33\
|
||||
\xA8\x55\x21\xAB\xDF\x1C\xBA\x64\xEC\xFB\x85\x04\x58\xDB\xEF\x0A\
|
||||
\x8A\xEA\x71\x57\x5D\x06\x0C\x7D\xB3\x97\x0F\x85\xA6\xE1\xE4\xC7\
|
||||
\xAB\xF5\xAE\x8C\xDB\x09\x33\xD7\x1E\x8C\x94\xE0\x4A\x25\x61\x9D\
|
||||
\xCE\xE3\xD2\x26\x1A\xD2\xEE\x6B\xF1\x2F\xFA\x06\xD9\x8A\x08\x64\
|
||||
\xD8\x76\x02\x73\x3E\xC8\x6A\x64\x52\x1F\x2B\x18\x17\x7B\x20\x0C\
|
||||
\xBB\xE1\x17\x57\x7A\x61\x5D\x6C\x77\x09\x88\xC0\xBA\xD9\x46\xE2\
|
||||
\x08\xE2\x4F\xA0\x74\xE5\xAB\x31\x43\xDB\x5B\xFC\xE0\xFD\x10\x8E\
|
||||
\x4B\x82\xD1\x20\xA9\x3A\xD2\xCA\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
||||
|
||||
let oakley_16 =
|
||||
(* 2^4096 - 2^4032 - 1 + 2^64 * { [2^3966 pi] + 240904 } *)
|
||||
s_group ~p:
|
||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xC9\x0F\xDA\xA2\x21\x68\xC2\x34\
|
||||
\xC4\xC6\x62\x8B\x80\xDC\x1C\xD1\x29\x02\x4E\x08\x8A\x67\xCC\x74\
|
||||
\x02\x0B\xBE\xA6\x3B\x13\x9B\x22\x51\x4A\x08\x79\x8E\x34\x04\xDD\
|
||||
\xEF\x95\x19\xB3\xCD\x3A\x43\x1B\x30\x2B\x0A\x6D\xF2\x5F\x14\x37\
|
||||
\x4F\xE1\x35\x6D\x6D\x51\xC2\x45\xE4\x85\xB5\x76\x62\x5E\x7E\xC6\
|
||||
\xF4\x4C\x42\xE9\xA6\x37\xED\x6B\x0B\xFF\x5C\xB6\xF4\x06\xB7\xED\
|
||||
\xEE\x38\x6B\xFB\x5A\x89\x9F\xA5\xAE\x9F\x24\x11\x7C\x4B\x1F\xE6\
|
||||
\x49\x28\x66\x51\xEC\xE4\x5B\x3D\xC2\x00\x7C\xB8\xA1\x63\xBF\x05\
|
||||
\x98\xDA\x48\x36\x1C\x55\xD3\x9A\x69\x16\x3F\xA8\xFD\x24\xCF\x5F\
|
||||
\x83\x65\x5D\x23\xDC\xA3\xAD\x96\x1C\x62\xF3\x56\x20\x85\x52\xBB\
|
||||
\x9E\xD5\x29\x07\x70\x96\x96\x6D\x67\x0C\x35\x4E\x4A\xBC\x98\x04\
|
||||
\xF1\x74\x6C\x08\xCA\x18\x21\x7C\x32\x90\x5E\x46\x2E\x36\xCE\x3B\
|
||||
\xE3\x9E\x77\x2C\x18\x0E\x86\x03\x9B\x27\x83\xA2\xEC\x07\xA2\x8F\
|
||||
\xB5\xC5\x5D\xF0\x6F\x4C\x52\xC9\xDE\x2B\xCB\xF6\x95\x58\x17\x18\
|
||||
\x39\x95\x49\x7C\xEA\x95\x6A\xE5\x15\xD2\x26\x18\x98\xFA\x05\x10\
|
||||
\x15\x72\x8E\x5A\x8A\xAA\xC4\x2D\xAD\x33\x17\x0D\x04\x50\x7A\x33\
|
||||
\xA8\x55\x21\xAB\xDF\x1C\xBA\x64\xEC\xFB\x85\x04\x58\xDB\xEF\x0A\
|
||||
\x8A\xEA\x71\x57\x5D\x06\x0C\x7D\xB3\x97\x0F\x85\xA6\xE1\xE4\xC7\
|
||||
\xAB\xF5\xAE\x8C\xDB\x09\x33\xD7\x1E\x8C\x94\xE0\x4A\x25\x61\x9D\
|
||||
\xCE\xE3\xD2\x26\x1A\xD2\xEE\x6B\xF1\x2F\xFA\x06\xD9\x8A\x08\x64\
|
||||
\xD8\x76\x02\x73\x3E\xC8\x6A\x64\x52\x1F\x2B\x18\x17\x7B\x20\x0C\
|
||||
\xBB\xE1\x17\x57\x7A\x61\x5D\x6C\x77\x09\x88\xC0\xBA\xD9\x46\xE2\
|
||||
\x08\xE2\x4F\xA0\x74\xE5\xAB\x31\x43\xDB\x5B\xFC\xE0\xFD\x10\x8E\
|
||||
\x4B\x82\xD1\x20\xA9\x21\x08\x01\x1A\x72\x3C\x12\xA7\x87\xE6\xD7\
|
||||
\x88\x71\x9A\x10\xBD\xBA\x5B\x26\x99\xC3\x27\x18\x6A\xF4\xE2\x3C\
|
||||
\x1A\x94\x68\x34\xB6\x15\x0B\xDA\x25\x83\xE9\xCA\x2A\xD4\x4C\xE8\
|
||||
\xDB\xBB\xC2\xDB\x04\xDE\x8E\xF9\x2E\x8E\xFC\x14\x1F\xBE\xCA\xA6\
|
||||
\x28\x7C\x59\x47\x4E\x6B\xC0\x5D\x99\xB2\x96\x4F\xA0\x90\xC3\xA2\
|
||||
\x23\x3B\xA1\x86\x51\x5B\xE7\xED\x1F\x61\x29\x70\xCE\xE2\xD7\xAF\
|
||||
\xB8\x1B\xDD\x76\x21\x70\x48\x1C\xD0\x06\x91\x27\xD5\xB0\x5A\xA9\
|
||||
\x93\xB4\xEA\x98\x8D\x8F\xDD\xC1\x86\xFF\xB7\xDC\x90\xA6\xC0\x8F\
|
||||
\x4D\xF4\x35\xC9\x34\x06\x31\x99\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
||||
|
||||
let oakley_17 =
|
||||
(* 2^6144 - 2^6080 - 1 + 2^64 * { [2^6014 pi] + 929484 } *)
|
||||
s_group ~p:
|
||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xC9\x0F\xDA\xA2\x21\x68\xC2\x34\
|
||||
\xC4\xC6\x62\x8B\x80\xDC\x1C\xD1\x29\x02\x4E\x08\x8A\x67\xCC\x74\
|
||||
\x02\x0B\xBE\xA6\x3B\x13\x9B\x22\x51\x4A\x08\x79\x8E\x34\x04\xDD\
|
||||
\xEF\x95\x19\xB3\xCD\x3A\x43\x1B\x30\x2B\x0A\x6D\xF2\x5F\x14\x37\
|
||||
\x4F\xE1\x35\x6D\x6D\x51\xC2\x45\xE4\x85\xB5\x76\x62\x5E\x7E\xC6\
|
||||
\xF4\x4C\x42\xE9\xA6\x37\xED\x6B\x0B\xFF\x5C\xB6\xF4\x06\xB7\xED\
|
||||
\xEE\x38\x6B\xFB\x5A\x89\x9F\xA5\xAE\x9F\x24\x11\x7C\x4B\x1F\xE6\
|
||||
\x49\x28\x66\x51\xEC\xE4\x5B\x3D\xC2\x00\x7C\xB8\xA1\x63\xBF\x05\
|
||||
\x98\xDA\x48\x36\x1C\x55\xD3\x9A\x69\x16\x3F\xA8\xFD\x24\xCF\x5F\
|
||||
\x83\x65\x5D\x23\xDC\xA3\xAD\x96\x1C\x62\xF3\x56\x20\x85\x52\xBB\
|
||||
\x9E\xD5\x29\x07\x70\x96\x96\x6D\x67\x0C\x35\x4E\x4A\xBC\x98\x04\
|
||||
\xF1\x74\x6C\x08\xCA\x18\x21\x7C\x32\x90\x5E\x46\x2E\x36\xCE\x3B\
|
||||
\xE3\x9E\x77\x2C\x18\x0E\x86\x03\x9B\x27\x83\xA2\xEC\x07\xA2\x8F\
|
||||
\xB5\xC5\x5D\xF0\x6F\x4C\x52\xC9\xDE\x2B\xCB\xF6\x95\x58\x17\x18\
|
||||
\x39\x95\x49\x7C\xEA\x95\x6A\xE5\x15\xD2\x26\x18\x98\xFA\x05\x10\
|
||||
\x15\x72\x8E\x5A\x8A\xAA\xC4\x2D\xAD\x33\x17\x0D\x04\x50\x7A\x33\
|
||||
\xA8\x55\x21\xAB\xDF\x1C\xBA\x64\xEC\xFB\x85\x04\x58\xDB\xEF\x0A\
|
||||
\x8A\xEA\x71\x57\x5D\x06\x0C\x7D\xB3\x97\x0F\x85\xA6\xE1\xE4\xC7\
|
||||
\xAB\xF5\xAE\x8C\xDB\x09\x33\xD7\x1E\x8C\x94\xE0\x4A\x25\x61\x9D\
|
||||
\xCE\xE3\xD2\x26\x1A\xD2\xEE\x6B\xF1\x2F\xFA\x06\xD9\x8A\x08\x64\
|
||||
\xD8\x76\x02\x73\x3E\xC8\x6A\x64\x52\x1F\x2B\x18\x17\x7B\x20\x0C\
|
||||
\xBB\xE1\x17\x57\x7A\x61\x5D\x6C\x77\x09\x88\xC0\xBA\xD9\x46\xE2\
|
||||
\x08\xE2\x4F\xA0\x74\xE5\xAB\x31\x43\xDB\x5B\xFC\xE0\xFD\x10\x8E\
|
||||
\x4B\x82\xD1\x20\xA9\x21\x08\x01\x1A\x72\x3C\x12\xA7\x87\xE6\xD7\
|
||||
\x88\x71\x9A\x10\xBD\xBA\x5B\x26\x99\xC3\x27\x18\x6A\xF4\xE2\x3C\
|
||||
\x1A\x94\x68\x34\xB6\x15\x0B\xDA\x25\x83\xE9\xCA\x2A\xD4\x4C\xE8\
|
||||
\xDB\xBB\xC2\xDB\x04\xDE\x8E\xF9\x2E\x8E\xFC\x14\x1F\xBE\xCA\xA6\
|
||||
\x28\x7C\x59\x47\x4E\x6B\xC0\x5D\x99\xB2\x96\x4F\xA0\x90\xC3\xA2\
|
||||
\x23\x3B\xA1\x86\x51\x5B\xE7\xED\x1F\x61\x29\x70\xCE\xE2\xD7\xAF\
|
||||
\xB8\x1B\xDD\x76\x21\x70\x48\x1C\xD0\x06\x91\x27\xD5\xB0\x5A\xA9\
|
||||
\x93\xB4\xEA\x98\x8D\x8F\xDD\xC1\x86\xFF\xB7\xDC\x90\xA6\xC0\x8F\
|
||||
\x4D\xF4\x35\xC9\x34\x02\x84\x92\x36\xC3\xFA\xB4\xD2\x7C\x70\x26\
|
||||
\xC1\xD4\xDC\xB2\x60\x26\x46\xDE\xC9\x75\x1E\x76\x3D\xBA\x37\xBD\
|
||||
\xF8\xFF\x94\x06\xAD\x9E\x53\x0E\xE5\xDB\x38\x2F\x41\x30\x01\xAE\
|
||||
\xB0\x6A\x53\xED\x90\x27\xD8\x31\x17\x97\x27\xB0\x86\x5A\x89\x18\
|
||||
\xDA\x3E\xDB\xEB\xCF\x9B\x14\xED\x44\xCE\x6C\xBA\xCE\xD4\xBB\x1B\
|
||||
\xDB\x7F\x14\x47\xE6\xCC\x25\x4B\x33\x20\x51\x51\x2B\xD7\xAF\x42\
|
||||
\x6F\xB8\xF4\x01\x37\x8C\xD2\xBF\x59\x83\xCA\x01\xC6\x4B\x92\xEC\
|
||||
\xF0\x32\xEA\x15\xD1\x72\x1D\x03\xF4\x82\xD7\xCE\x6E\x74\xFE\xF6\
|
||||
\xD5\x5E\x70\x2F\x46\x98\x0C\x82\xB5\xA8\x40\x31\x90\x0B\x1C\x9E\
|
||||
\x59\xE7\xC9\x7F\xBE\xC7\xE8\xF3\x23\xA9\x7A\x7E\x36\xCC\x88\xBE\
|
||||
\x0F\x1D\x45\xB7\xFF\x58\x5A\xC5\x4B\xD4\x07\xB2\x2B\x41\x54\xAA\
|
||||
\xCC\x8F\x6D\x7E\xBF\x48\xE1\xD8\x14\xCC\x5E\xD2\x0F\x80\x37\xE0\
|
||||
\xA7\x97\x15\xEE\xF2\x9B\xE3\x28\x06\xA1\xD5\x8B\xB7\xC5\xDA\x76\
|
||||
\xF5\x50\xAA\x3D\x8A\x1F\xBF\xF0\xEB\x19\xCC\xB1\xA3\x13\xD5\x5C\
|
||||
\xDA\x56\xC9\xEC\x2E\xF2\x96\x32\x38\x7F\xE8\xD7\x6E\x3C\x04\x68\
|
||||
\x04\x3E\x8F\x66\x3F\x48\x60\xEE\x12\xBF\x2D\x5B\x0B\x74\x74\xD6\
|
||||
\xE6\x94\xF9\x1E\x6D\xCC\x40\x24\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
||||
|
||||
let oakley_18 =
|
||||
(* 2^8192 - 2^8128 - 1 + 2^64 * { [2^8062 pi] + 4743158 } *)
|
||||
s_group ~p:
|
||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xC9\x0F\xDA\xA2\x21\x68\xC2\x34\
|
||||
\xC4\xC6\x62\x8B\x80\xDC\x1C\xD1\x29\x02\x4E\x08\x8A\x67\xCC\x74\
|
||||
\x02\x0B\xBE\xA6\x3B\x13\x9B\x22\x51\x4A\x08\x79\x8E\x34\x04\xDD\
|
||||
\xEF\x95\x19\xB3\xCD\x3A\x43\x1B\x30\x2B\x0A\x6D\xF2\x5F\x14\x37\
|
||||
\x4F\xE1\x35\x6D\x6D\x51\xC2\x45\xE4\x85\xB5\x76\x62\x5E\x7E\xC6\
|
||||
\xF4\x4C\x42\xE9\xA6\x37\xED\x6B\x0B\xFF\x5C\xB6\xF4\x06\xB7\xED\
|
||||
\xEE\x38\x6B\xFB\x5A\x89\x9F\xA5\xAE\x9F\x24\x11\x7C\x4B\x1F\xE6\
|
||||
\x49\x28\x66\x51\xEC\xE4\x5B\x3D\xC2\x00\x7C\xB8\xA1\x63\xBF\x05\
|
||||
\x98\xDA\x48\x36\x1C\x55\xD3\x9A\x69\x16\x3F\xA8\xFD\x24\xCF\x5F\
|
||||
\x83\x65\x5D\x23\xDC\xA3\xAD\x96\x1C\x62\xF3\x56\x20\x85\x52\xBB\
|
||||
\x9E\xD5\x29\x07\x70\x96\x96\x6D\x67\x0C\x35\x4E\x4A\xBC\x98\x04\
|
||||
\xF1\x74\x6C\x08\xCA\x18\x21\x7C\x32\x90\x5E\x46\x2E\x36\xCE\x3B\
|
||||
\xE3\x9E\x77\x2C\x18\x0E\x86\x03\x9B\x27\x83\xA2\xEC\x07\xA2\x8F\
|
||||
\xB5\xC5\x5D\xF0\x6F\x4C\x52\xC9\xDE\x2B\xCB\xF6\x95\x58\x17\x18\
|
||||
\x39\x95\x49\x7C\xEA\x95\x6A\xE5\x15\xD2\x26\x18\x98\xFA\x05\x10\
|
||||
\x15\x72\x8E\x5A\x8A\xAA\xC4\x2D\xAD\x33\x17\x0D\x04\x50\x7A\x33\
|
||||
\xA8\x55\x21\xAB\xDF\x1C\xBA\x64\xEC\xFB\x85\x04\x58\xDB\xEF\x0A\
|
||||
\x8A\xEA\x71\x57\x5D\x06\x0C\x7D\xB3\x97\x0F\x85\xA6\xE1\xE4\xC7\
|
||||
\xAB\xF5\xAE\x8C\xDB\x09\x33\xD7\x1E\x8C\x94\xE0\x4A\x25\x61\x9D\
|
||||
\xCE\xE3\xD2\x26\x1A\xD2\xEE\x6B\xF1\x2F\xFA\x06\xD9\x8A\x08\x64\
|
||||
\xD8\x76\x02\x73\x3E\xC8\x6A\x64\x52\x1F\x2B\x18\x17\x7B\x20\x0C\
|
||||
\xBB\xE1\x17\x57\x7A\x61\x5D\x6C\x77\x09\x88\xC0\xBA\xD9\x46\xE2\
|
||||
\x08\xE2\x4F\xA0\x74\xE5\xAB\x31\x43\xDB\x5B\xFC\xE0\xFD\x10\x8E\
|
||||
\x4B\x82\xD1\x20\xA9\x21\x08\x01\x1A\x72\x3C\x12\xA7\x87\xE6\xD7\
|
||||
\x88\x71\x9A\x10\xBD\xBA\x5B\x26\x99\xC3\x27\x18\x6A\xF4\xE2\x3C\
|
||||
\x1A\x94\x68\x34\xB6\x15\x0B\xDA\x25\x83\xE9\xCA\x2A\xD4\x4C\xE8\
|
||||
\xDB\xBB\xC2\xDB\x04\xDE\x8E\xF9\x2E\x8E\xFC\x14\x1F\xBE\xCA\xA6\
|
||||
\x28\x7C\x59\x47\x4E\x6B\xC0\x5D\x99\xB2\x96\x4F\xA0\x90\xC3\xA2\
|
||||
\x23\x3B\xA1\x86\x51\x5B\xE7\xED\x1F\x61\x29\x70\xCE\xE2\xD7\xAF\
|
||||
\xB8\x1B\xDD\x76\x21\x70\x48\x1C\xD0\x06\x91\x27\xD5\xB0\x5A\xA9\
|
||||
\x93\xB4\xEA\x98\x8D\x8F\xDD\xC1\x86\xFF\xB7\xDC\x90\xA6\xC0\x8F\
|
||||
\x4D\xF4\x35\xC9\x34\x02\x84\x92\x36\xC3\xFA\xB4\xD2\x7C\x70\x26\
|
||||
\xC1\xD4\xDC\xB2\x60\x26\x46\xDE\xC9\x75\x1E\x76\x3D\xBA\x37\xBD\
|
||||
\xF8\xFF\x94\x06\xAD\x9E\x53\x0E\xE5\xDB\x38\x2F\x41\x30\x01\xAE\
|
||||
\xB0\x6A\x53\xED\x90\x27\xD8\x31\x17\x97\x27\xB0\x86\x5A\x89\x18\
|
||||
\xDA\x3E\xDB\xEB\xCF\x9B\x14\xED\x44\xCE\x6C\xBA\xCE\xD4\xBB\x1B\
|
||||
\xDB\x7F\x14\x47\xE6\xCC\x25\x4B\x33\x20\x51\x51\x2B\xD7\xAF\x42\
|
||||
\x6F\xB8\xF4\x01\x37\x8C\xD2\xBF\x59\x83\xCA\x01\xC6\x4B\x92\xEC\
|
||||
\xF0\x32\xEA\x15\xD1\x72\x1D\x03\xF4\x82\xD7\xCE\x6E\x74\xFE\xF6\
|
||||
\xD5\x5E\x70\x2F\x46\x98\x0C\x82\xB5\xA8\x40\x31\x90\x0B\x1C\x9E\
|
||||
\x59\xE7\xC9\x7F\xBE\xC7\xE8\xF3\x23\xA9\x7A\x7E\x36\xCC\x88\xBE\
|
||||
\x0F\x1D\x45\xB7\xFF\x58\x5A\xC5\x4B\xD4\x07\xB2\x2B\x41\x54\xAA\
|
||||
\xCC\x8F\x6D\x7E\xBF\x48\xE1\xD8\x14\xCC\x5E\xD2\x0F\x80\x37\xE0\
|
||||
\xA7\x97\x15\xEE\xF2\x9B\xE3\x28\x06\xA1\xD5\x8B\xB7\xC5\xDA\x76\
|
||||
\xF5\x50\xAA\x3D\x8A\x1F\xBF\xF0\xEB\x19\xCC\xB1\xA3\x13\xD5\x5C\
|
||||
\xDA\x56\xC9\xEC\x2E\xF2\x96\x32\x38\x7F\xE8\xD7\x6E\x3C\x04\x68\
|
||||
\x04\x3E\x8F\x66\x3F\x48\x60\xEE\x12\xBF\x2D\x5B\x0B\x74\x74\xD6\
|
||||
\xE6\x94\xF9\x1E\x6D\xBE\x11\x59\x74\xA3\x92\x6F\x12\xFE\xE5\xE4\
|
||||
\x38\x77\x7C\xB6\xA9\x32\xDF\x8C\xD8\xBE\xC4\xD0\x73\xB9\x31\xBA\
|
||||
\x3B\xC8\x32\xB6\x8D\x9D\xD3\x00\x74\x1F\xA7\xBF\x8A\xFC\x47\xED\
|
||||
\x25\x76\xF6\x93\x6B\xA4\x24\x66\x3A\xAB\x63\x9C\x5A\xE4\xF5\x68\
|
||||
\x34\x23\xB4\x74\x2B\xF1\xC9\x78\x23\x8F\x16\xCB\xE3\x9D\x65\x2D\
|
||||
\xE3\xFD\xB8\xBE\xFC\x84\x8A\xD9\x22\x22\x2E\x04\xA4\x03\x7C\x07\
|
||||
\x13\xEB\x57\xA8\x1A\x23\xF0\xC7\x34\x73\xFC\x64\x6C\xEA\x30\x6B\
|
||||
\x4B\xCB\xC8\x86\x2F\x83\x85\xDD\xFA\x9D\x4B\x7F\xA2\xC0\x87\xE8\
|
||||
\x79\x68\x33\x03\xED\x5B\xDD\x3A\x06\x2B\x3C\xF5\xB3\xA2\x78\xA6\
|
||||
\x6D\x2A\x13\xF8\x3F\x44\xF8\x2D\xDF\x31\x0E\xE0\x74\xAB\x6A\x36\
|
||||
\x45\x97\xE8\x99\xA0\x25\x5D\xC1\x64\xF3\x1C\xC5\x08\x46\x85\x1D\
|
||||
\xF9\xAB\x48\x19\x5D\xED\x7E\xA1\xB1\xD5\x10\xBD\x7E\xE7\x4D\x73\
|
||||
\xFA\xF3\x6B\xC3\x1E\xCF\xA2\x68\x35\x90\x46\xF4\xEB\x87\x9F\x92\
|
||||
\x40\x09\x43\x8B\x48\x1C\x6C\xD7\x88\x9A\x00\x2E\xD5\xEE\x38\x2B\
|
||||
\xC9\x19\x0D\xA6\xFC\x02\x6E\x47\x95\x58\xE4\x47\x56\x77\xE9\xAA\
|
||||
\x9E\x30\x50\xE2\x76\x56\x94\xDF\xC8\x1F\x56\xE8\x80\xB9\x6E\x71\
|
||||
\x60\xC9\x80\xDD\x98\xED\xD3\xDF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
||||
|
||||
|
||||
(* RFC5114 *)
|
||||
|
||||
(* 1024-bit, 160-bit subgroup *)
|
||||
let rfc_5114_1 =
|
||||
let p =
|
||||
"\xB1\x0B\x8F\x96\xA0\x80\xE0\x1D\xDE\x92\xDE\x5E\xAE\x5D\x54\xEC\
|
||||
\x52\xC9\x9F\xBC\xFB\x06\xA3\xC6\x9A\x6A\x9D\xCA\x52\xD2\x3B\x61\
|
||||
\x60\x73\xE2\x86\x75\xA2\x3D\x18\x98\x38\xEF\x1E\x2E\xE6\x52\xC0\
|
||||
\x13\xEC\xB4\xAE\xA9\x06\x11\x23\x24\x97\x5C\x3C\xD4\x9B\x83\xBF\
|
||||
\xAC\xCB\xDD\x7D\x90\xC4\xBD\x70\x98\x48\x8E\x9C\x21\x9A\x73\x72\
|
||||
\x4E\xFF\xD6\xFA\xE5\x64\x47\x38\xFA\xA3\x1A\x4F\xF5\x5B\xCC\xC0\
|
||||
\xA1\x51\xAF\x5F\x0D\xC8\xB4\xBD\x45\xBF\x37\xDF\x36\x5C\x1A\x65\
|
||||
\xE6\x8C\xFD\xA7\x6D\x4D\xA7\x08\xDF\x1F\xB2\xBC\x2E\x4A\x43\x71"
|
||||
and gg =
|
||||
"\xA4\xD1\xCB\xD5\xC3\xFD\x34\x12\x67\x65\xA4\x42\xEF\xB9\x99\x05\
|
||||
\xF8\x10\x4D\xD2\x58\xAC\x50\x7F\xD6\x40\x6C\xFF\x14\x26\x6D\x31\
|
||||
\x26\x6F\xEA\x1E\x5C\x41\x56\x4B\x77\x7E\x69\x0F\x55\x04\xF2\x13\
|
||||
\x16\x02\x17\xB4\xB0\x1B\x88\x6A\x5E\x91\x54\x7F\x9E\x27\x49\xF4\
|
||||
\xD7\xFB\xD7\xD3\xB9\xA9\x2E\xE1\x90\x9D\x0D\x22\x63\xF8\x0A\x76\
|
||||
\xA6\xA2\x4C\x08\x7A\x09\x1F\x53\x1D\xBF\x0A\x01\x69\xB6\xA2\x8A\
|
||||
\xD6\x62\xA4\xD1\x8E\x73\xAF\xA3\x2D\x77\x9D\x59\x18\xD0\x8B\xC8\
|
||||
\x85\x8F\x4D\xCE\xF9\x7C\x2A\x24\\x85\x5E\x6E\xEB\x22\xB3\xB2\xE5"
|
||||
and q =
|
||||
"\xF5\x18\xAA\x87\x81\xA8\xDF\x27\x8A\xBA\x4E\x7D\x64\xB7\xCB\x9D\
|
||||
\x49\x46\x23\x53"
|
||||
in
|
||||
group ~p ~gg ~q
|
||||
|
||||
(* 2048-bit, 224-bit subgroup *)
|
||||
let rfc_5114_2 =
|
||||
let p =
|
||||
"\xAD\x10\x7E\x1E\x91\x23\xA9\xD0\xD6\x60\xFA\xA7\x95\x59\xC5\x1F\
|
||||
\xA2\x0D\x64\xE5\x68\x3B\x9F\xD1\xB5\x4B\x15\x97\xB6\x1D\x0A\x75\
|
||||
\xE6\xFA\x14\x1D\xF9\x5A\x56\xDB\xAF\x9A\x3C\x40\x7B\xA1\xDF\x15\
|
||||
\xEB\x3D\x68\x8A\x30\x9C\x18\x0E\x1D\xE6\xB8\x5A\x12\x74\xA0\xA6\
|
||||
\x6D\x3F\x81\x52\xAD\x6A\xC2\x12\x90\x37\xC9\xED\xEF\xDA\x4D\xF8\
|
||||
\xD9\x1E\x8F\xEF\x55\xB7\x39\x4B\x7A\xD5\xB7\xD0\xB6\xC1\x22\x07\
|
||||
\xC9\xF9\x8D\x11\xED\x34\xDB\xF6\xC6\xBA\x0B\x2C\x8B\xBC\x27\xBE\
|
||||
\x6A\x00\xE0\xA0\xB9\xC4\x97\x08\xB3\xBF\x8A\x31\x70\x91\x88\x36\
|
||||
\x81\x28\x61\x30\xBC\x89\x85\xDB\x16\x02\xE7\x14\x41\x5D\x93\x30\
|
||||
\x27\x82\x73\xC7\xDE\x31\xEF\xDC\x73\x10\xF7\x12\x1F\xD5\xA0\x74\
|
||||
\x15\x98\x7D\x9A\xDC\x0A\x48\x6D\xCD\xF9\x3A\xCC\x44\x32\x83\x87\
|
||||
\x31\x5D\x75\xE1\x98\xC6\x41\xA4\x80\xCD\x86\xA1\xB9\xE5\x87\xE8\
|
||||
\xBE\x60\xE6\x9C\xC9\x28\xB2\xB9\xC5\x21\x72\xE4\x13\x04\x2E\x9B\
|
||||
\x23\xF1\x0B\x0E\x16\xE7\x97\x63\xC9\xB5\x3D\xCF\x4B\xA8\x0A\x29\
|
||||
\xE3\xFB\x73\xC1\x6B\x8E\x75\xB9\x7E\xF3\x63\xE2\xFF\xA3\x1F\x71\
|
||||
\xCF\x9D\xE5\x38\x4E\x71\xB8\x1C\x0A\xC4\xDF\xFE\x0C\x10\xE6\x4F"
|
||||
and gg =
|
||||
"\xAC\x40\x32\xEF\x4F\x2D\x9A\xE3\x9D\xF3\x0B\x5C\x8F\xFD\xAC\x50\
|
||||
\x6C\xDE\xBE\x7B\x89\x99\x8C\xAF\x74\x86\x6A\x08\xCF\xE4\xFF\xE3\
|
||||
\xA6\x82\x4A\x4E\x10\xB9\xA6\xF0\xDD\x92\x1F\x01\xA7\x0C\x4A\xFA\
|
||||
\xAB\x73\x9D\x77\x00\xC2\x9F\x52\xC5\x7D\xB1\x7C\x62\x0A\x86\x52\
|
||||
\xBE\x5E\x90\x01\xA8\xD6\x6A\xD7\xC1\x76\x69\x10\x19\x99\x02\x4A\
|
||||
\xF4\xD0\x27\x27\x5A\xC1\x34\x8B\xB8\xA7\x62\xD0\x52\x1B\xC9\x8A\
|
||||
\xE2\x47\x15\x04\x22\xEA\x1E\xD4\x09\x93\x9D\x54\xDA\x74\x60\xCD\
|
||||
\xB5\xF6\xC6\xB2\x50\x71\x7C\xBE\xF1\x80\xEB\x34\x11\x8E\x98\xD1\
|
||||
\x19\x52\x9A\x45\xD6\xF8\x34\x56\x6E\x30\x25\xE3\x16\xA3\x30\xEF\
|
||||
\xBB\x77\xA8\x6F\x0C\x1A\xB1\x5B\x05\x1A\xE3\xD4\x28\xC8\xF8\xAC\
|
||||
\xB7\x0A\x81\x37\x15\x0B\x8E\xEB\x10\xE1\x83\xED\xD1\x99\x63\xDD\
|
||||
\xD9\xE2\x63\xE4\x77\x05\x89\xEF\x6A\xA2\x1E\x7F\x5F\x2F\xF3\x81\
|
||||
\xB5\x39\xCC\xE3\x40\x9D\x13\xCD\x56\x6A\xFB\xB4\x8D\x6C\x01\x91\
|
||||
\x81\xE1\xBC\xFE\x94\xB3\x02\x69\xED\xFE\x72\xFE\x9B\x6A\xA4\xBD\
|
||||
\x7B\x5A\x0F\x1C\x71\xCF\xFF\x4C\x19\xC4\x18\xE1\xF6\xEC\x01\x79\
|
||||
\x81\xBC\x08\x7F\x2A\x70\x65\xB3\x84\xB8\x90\xD3\x19\x1F\x2B\xFA"
|
||||
and q =
|
||||
"\x80\x1C\x0D\x34\xC5\x8D\x93\xFE\x99\x71\x77\x10\x1F\x80\x53\x5A\
|
||||
\x47\x38\xCE\xBC\xBF\x38\x9A\x99\xB3\x63\x71\xEB"
|
||||
in
|
||||
group ~p ~gg ~q
|
||||
|
||||
(* 2048-bit, 256-bit subgroup *)
|
||||
let rfc_5114_3 =
|
||||
let p =
|
||||
"\x87\xA8\xE6\x1D\xB4\xB6\x66\x3C\xFF\xBB\xD1\x9C\x65\x19\x59\x99\
|
||||
\x8C\xEE\xF6\x08\x66\x0D\xD0\xF2\x5D\x2C\xEE\xD4\x43\x5E\x3B\x00\
|
||||
\xE0\x0D\xF8\xF1\xD6\x19\x57\xD4\xFA\xF7\xDF\x45\x61\xB2\xAA\x30\
|
||||
\x16\xC3\xD9\x11\x34\x09\x6F\xAA\x3B\xF4\x29\x6D\x83\x0E\x9A\x7C\
|
||||
\x20\x9E\x0C\x64\x97\x51\x7A\xBD\x5A\x8A\x9D\x30\x6B\xCF\x67\xED\
|
||||
\x91\xF9\xE6\x72\x5B\x47\x58\xC0\x22\xE0\xB1\xEF\x42\x75\xBF\x7B\
|
||||
\x6C\x5B\xFC\x11\xD4\x5F\x90\x88\xB9\x41\xF5\x4E\xB1\xE5\x9B\xB8\
|
||||
\xBC\x39\xA0\xBF\x12\x30\x7F\x5C\x4F\xDB\x70\xC5\x81\xB2\x3F\x76\
|
||||
\xB6\x3A\xCA\xE1\xCA\xA6\xB7\x90\x2D\x52\x52\x67\x35\x48\x8A\x0E\
|
||||
\xF1\x3C\x6D\x9A\x51\xBF\xA4\xAB\x3A\xD8\x34\x77\x96\x52\x4D\x8E\
|
||||
\xF6\xA1\x67\xB5\xA4\x18\x25\xD9\x67\xE1\x44\xE5\x14\x05\x64\x25\
|
||||
\x1C\xCA\xCB\x83\xE6\xB4\x86\xF6\xB3\xCA\x3F\x79\x71\x50\x60\x26\
|
||||
\xC0\xB8\x57\xF6\x89\x96\x28\x56\xDE\xD4\x01\x0A\xBD\x0B\xE6\x21\
|
||||
\xC3\xA3\x96\x0A\x54\xE7\x10\xC3\x75\xF2\x63\x75\xD7\x01\x41\x03\
|
||||
\xA4\xB5\x43\x30\xC1\x98\xAF\x12\x61\x16\xD2\x27\x6E\x11\x71\x5F\
|
||||
\x69\x38\x77\xFA\xD7\xEF\x09\xCA\xDB\x09\x4A\xE9\x1E\x1A\x15\x97"
|
||||
and gg =
|
||||
"\x3F\xB3\x2C\x9B\x73\x13\x4D\x0B\x2E\x77\x50\x66\x60\xED\xBD\x48\
|
||||
\x4C\xA7\xB1\x8F\x21\xEF\x20\x54\x07\xF4\x79\x3A\x1A\x0B\xA1\x25\
|
||||
\x10\xDB\xC1\x50\x77\xBE\x46\x3F\xFF\x4F\xED\x4A\xAC\x0B\xB5\x55\
|
||||
\xBE\x3A\x6C\x1B\x0C\x6B\x47\xB1\xBC\x37\x73\xBF\x7E\x8C\x6F\x62\
|
||||
\x90\x12\x28\xF8\xC2\x8C\xBB\x18\xA5\x5A\xE3\x13\x41\x00\x0A\x65\
|
||||
\x01\x96\xF9\x31\xC7\x7A\x57\xF2\xDD\xF4\x63\xE5\xE9\xEC\x14\x4B\
|
||||
\x77\x7D\xE6\x2A\xAA\xB8\xA8\x62\x8A\xC3\x76\xD2\x82\xD6\xED\x38\
|
||||
\x64\xE6\x79\x82\x42\x8E\xBC\x83\x1D\x14\x34\x8F\x6F\x2F\x91\x93\
|
||||
\xB5\x04\x5A\xF2\x76\x71\x64\xE1\xDF\xC9\x67\xC1\xFB\x3F\x2E\x55\
|
||||
\xA4\xBD\x1B\xFF\xE8\x3B\x9C\x80\xD0\x52\xB9\x85\xD1\x82\xEA\x0A\
|
||||
\xDB\x2A\x3B\x73\x13\xD3\xFE\x14\xC8\x48\x4B\x1E\x05\x25\x88\xB9\
|
||||
\xB7\xD2\xBB\xD2\xDF\x01\x61\x99\xEC\xD0\x6E\x15\x57\xCD\x09\x15\
|
||||
\xB3\x35\x3B\xBB\x64\xE0\xEC\x37\x7F\xD0\x28\x37\x0D\xF9\x2B\x52\
|
||||
\xC7\x89\x14\x28\xCD\xC6\x7E\xB6\x18\x4B\x52\x3D\x1D\xB2\x46\xC3\
|
||||
\x2F\x63\x07\x84\x90\xF0\x0E\xF8\xD6\x47\xD1\x48\xD4\x79\x54\x51\
|
||||
\x5E\x23\x27\xCF\xEF\x98\xC5\x82\x66\x4B\x4C\x0F\x6C\xC4\x16\x59"
|
||||
and q =
|
||||
"\x8C\xF8\x36\x42\xA7\x09\xA0\x97\xB4\x47\x99\x76\x40\x12\x9D\xA2\
|
||||
\x99\xB1\xA4\x7D\x1E\xB3\x75\x0B\xA3\x08\xB0\xFE\x64\xF5\xFB\xD3"
|
||||
in
|
||||
group ~p ~gg ~q
|
||||
|
||||
|
||||
(* draft-ietf-tls-negotiated-ff-dhe-08 *)
|
||||
|
||||
let ffdhe2048 =
|
||||
(* p = 2^2048 - 2^1984 + {[2^1918 * e] + 560316 } * 2^64 - 1 *)
|
||||
(* The estimated symmetric-equivalent strength of this group is 103 bits.
|
||||
|
||||
Peers using ffdhe2048 that want to optimize their key exchange with a
|
||||
short exponent (Section 5.2) should choose a secret key of at least
|
||||
225 bits. *)
|
||||
s_group ~p:
|
||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xAD\xF8\x54\x58\xA2\xBB\x4A\x9A\
|
||||
\xAF\xDC\x56\x20\x27\x3D\x3C\xF1\xD8\xB9\xC5\x83\xCE\x2D\x36\x95\
|
||||
\xA9\xE1\x36\x41\x14\x64\x33\xFB\xCC\x93\x9D\xCE\x24\x9B\x3E\xF9\
|
||||
\x7D\x2F\xE3\x63\x63\x0C\x75\xD8\xF6\x81\xB2\x02\xAE\xC4\x61\x7A\
|
||||
\xD3\xDF\x1E\xD5\xD5\xFD\x65\x61\x24\x33\xF5\x1F\x5F\x06\x6E\xD0\
|
||||
\x85\x63\x65\x55\x3D\xED\x1A\xF3\xB5\x57\x13\x5E\x7F\x57\xC9\x35\
|
||||
\x98\x4F\x0C\x70\xE0\xE6\x8B\x77\xE2\xA6\x89\xDA\xF3\xEF\xE8\x72\
|
||||
\x1D\xF1\x58\xA1\x36\xAD\xE7\x35\x30\xAC\xCA\x4F\x48\x3A\x79\x7A\
|
||||
\xBC\x0A\xB1\x82\xB3\x24\xFB\x61\xD1\x08\xA9\x4B\xB2\xC8\xE3\xFB\
|
||||
\xB9\x6A\xDA\xB7\x60\xD7\xF4\x68\x1D\x4F\x42\xA3\xDE\x39\x4D\xF4\
|
||||
\xAE\x56\xED\xE7\x63\x72\xBB\x19\x0B\x07\xA7\xC8\xEE\x0A\x6D\x70\
|
||||
\x9E\x02\xFC\xE1\xCD\xF7\xE2\xEC\xC0\x34\x04\xCD\x28\x34\x2F\x61\
|
||||
\x91\x72\xFE\x9C\xE9\x85\x83\xFF\x8E\x4F\x12\x32\xEE\xF2\x81\x83\
|
||||
\xC3\xFE\x3B\x1B\x4C\x6F\xAD\x73\x3B\xB5\xFC\xBC\x2E\xC2\x20\x05\
|
||||
\xC5\x8E\xF1\x83\x7D\x16\x83\xB2\xC6\xF3\x4A\x26\xC1\xB2\xEF\xFA\
|
||||
\x88\x6B\x42\x38\x61\x28\x5C\x97\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
||||
|
||||
|
||||
let ffdhe3072 =
|
||||
(* p = 2^3072 - 2^3008 + {[2^2942 * e] + 2625351} * 2^64 -1 *)
|
||||
(* The estimated symmetric-equivalent strength of this group is 125 bits.
|
||||
|
||||
Peers using ffdhe3072 that want to optimize their key exchange with a
|
||||
short exponent (Section 5.2) should choose a secret key of at least
|
||||
275 bits. *)
|
||||
s_group ~p:
|
||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xAD\xF8\x54\x58\xA2\xBB\x4A\x9A\
|
||||
\xAF\xDC\x56\x20\x27\x3D\x3C\xF1\xD8\xB9\xC5\x83\xCE\x2D\x36\x95\
|
||||
\xA9\xE1\x36\x41\x14\x64\x33\xFB\xCC\x93\x9D\xCE\x24\x9B\x3E\xF9\
|
||||
\x7D\x2F\xE3\x63\x63\x0C\x75\xD8\xF6\x81\xB2\x02\xAE\xC4\x61\x7A\
|
||||
\xD3\xDF\x1E\xD5\xD5\xFD\x65\x61\x24\x33\xF5\x1F\x5F\x06\x6E\xD0\
|
||||
\x85\x63\x65\x55\x3D\xED\x1A\xF3\xB5\x57\x13\x5E\x7F\x57\xC9\x35\
|
||||
\x98\x4F\x0C\x70\xE0\xE6\x8B\x77\xE2\xA6\x89\xDA\xF3\xEF\xE8\x72\
|
||||
\x1D\xF1\x58\xA1\x36\xAD\xE7\x35\x30\xAC\xCA\x4F\x48\x3A\x79\x7A\
|
||||
\xBC\x0A\xB1\x82\xB3\x24\xFB\x61\xD1\x08\xA9\x4B\xB2\xC8\xE3\xFB\
|
||||
\xB9\x6A\xDA\xB7\x60\xD7\xF4\x68\x1D\x4F\x42\xA3\xDE\x39\x4D\xF4\
|
||||
\xAE\x56\xED\xE7\x63\x72\xBB\x19\x0B\x07\xA7\xC8\xEE\x0A\x6D\x70\
|
||||
\x9E\x02\xFC\xE1\xCD\xF7\xE2\xEC\xC0\x34\x04\xCD\x28\x34\x2F\x61\
|
||||
\x91\x72\xFE\x9C\xE9\x85\x83\xFF\x8E\x4F\x12\x32\xEE\xF2\x81\x83\
|
||||
\xC3\xFE\x3B\x1B\x4C\x6F\xAD\x73\x3B\xB5\xFC\xBC\x2E\xC2\x20\x05\
|
||||
\xC5\x8E\xF1\x83\x7D\x16\x83\xB2\xC6\xF3\x4A\x26\xC1\xB2\xEF\xFA\
|
||||
\x88\x6B\x42\x38\x61\x1F\xCF\xDC\xDE\x35\x5B\x3B\x65\x19\x03\x5B\
|
||||
\xBC\x34\xF4\xDE\xF9\x9C\x02\x38\x61\xB4\x6F\xC9\xD6\xE6\xC9\x07\
|
||||
\x7A\xD9\x1D\x26\x91\xF7\xF7\xEE\x59\x8C\xB0\xFA\xC1\x86\xD9\x1C\
|
||||
\xAE\xFE\x13\x09\x85\x13\x92\x70\xB4\x13\x0C\x93\xBC\x43\x79\x44\
|
||||
\xF4\xFD\x44\x52\xE2\xD7\x4D\xD3\x64\xF2\xE2\x1E\x71\xF5\x4B\xFF\
|
||||
\x5C\xAE\x82\xAB\x9C\x9D\xF6\x9E\xE8\x6D\x2B\xC5\x22\x36\x3A\x0D\
|
||||
\xAB\xC5\x21\x97\x9B\x0D\xEA\xDA\x1D\xBF\x9A\x42\xD5\xC4\x48\x4E\
|
||||
\x0A\xBC\xD0\x6B\xFA\x53\xDD\xEF\x3C\x1B\x20\xEE\x3F\xD5\x9D\x7C\
|
||||
\x25\xE4\x1D\x2B\x66\xC6\x2E\x37\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
||||
|
||||
let ffdhe4096 =
|
||||
(* p = 2^4096 - 2^4032 + {[2^3966 * e] + 5736041} * 2^64 - 1 *)
|
||||
(* The estimated symmetric-equivalent strength of this group is 150 bits.
|
||||
|
||||
Peers using ffdhe4096 that want to optimize their key exchange with a
|
||||
short exponent (Section 5.2) should choose a secret key of at least
|
||||
325 bits. *)
|
||||
s_group ~p:
|
||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xAD\xF8\x54\x58\xA2\xBB\x4A\x9A\
|
||||
\xAF\xDC\x56\x20\x27\x3D\x3C\xF1\xD8\xB9\xC5\x83\xCE\x2D\x36\x95\
|
||||
\xA9\xE1\x36\x41\x14\x64\x33\xFB\xCC\x93\x9D\xCE\x24\x9B\x3E\xF9\
|
||||
\x7D\x2F\xE3\x63\x63\x0C\x75\xD8\xF6\x81\xB2\x02\xAE\xC4\x61\x7A\
|
||||
\xD3\xDF\x1E\xD5\xD5\xFD\x65\x61\x24\x33\xF5\x1F\x5F\x06\x6E\xD0\
|
||||
\x85\x63\x65\x55\x3D\xED\x1A\xF3\xB5\x57\x13\x5E\x7F\x57\xC9\x35\
|
||||
\x98\x4F\x0C\x70\xE0\xE6\x8B\x77\xE2\xA6\x89\xDA\xF3\xEF\xE8\x72\
|
||||
\x1D\xF1\x58\xA1\x36\xAD\xE7\x35\x30\xAC\xCA\x4F\x48\x3A\x79\x7A\
|
||||
\xBC\x0A\xB1\x82\xB3\x24\xFB\x61\xD1\x08\xA9\x4B\xB2\xC8\xE3\xFB\
|
||||
\xB9\x6A\xDA\xB7\x60\xD7\xF4\x68\x1D\x4F\x42\xA3\xDE\x39\x4D\xF4\
|
||||
\xAE\x56\xED\xE7\x63\x72\xBB\x19\x0B\x07\xA7\xC8\xEE\x0A\x6D\x70\
|
||||
\x9E\x02\xFC\xE1\xCD\xF7\xE2\xEC\xC0\x34\x04\xCD\x28\x34\x2F\x61\
|
||||
\x91\x72\xFE\x9C\xE9\x85\x83\xFF\x8E\x4F\x12\x32\xEE\xF2\x81\x83\
|
||||
\xC3\xFE\x3B\x1B\x4C\x6F\xAD\x73\x3B\xB5\xFC\xBC\x2E\xC2\x20\x05\
|
||||
\xC5\x8E\xF1\x83\x7D\x16\x83\xB2\xC6\xF3\x4A\x26\xC1\xB2\xEF\xFA\
|
||||
\x88\x6B\x42\x38\x61\x1F\xCF\xDC\xDE\x35\x5B\x3B\x65\x19\x03\x5B\
|
||||
\xBC\x34\xF4\xDE\xF9\x9C\x02\x38\x61\xB4\x6F\xC9\xD6\xE6\xC9\x07\
|
||||
\x7A\xD9\x1D\x26\x91\xF7\xF7\xEE\x59\x8C\xB0\xFA\xC1\x86\xD9\x1C\
|
||||
\xAE\xFE\x13\x09\x85\x13\x92\x70\xB4\x13\x0C\x93\xBC\x43\x79\x44\
|
||||
\xF4\xFD\x44\x52\xE2\xD7\x4D\xD3\x64\xF2\xE2\x1E\x71\xF5\x4B\xFF\
|
||||
\x5C\xAE\x82\xAB\x9C\x9D\xF6\x9E\xE8\x6D\x2B\xC5\x22\x36\x3A\x0D\
|
||||
\xAB\xC5\x21\x97\x9B\x0D\xEA\xDA\x1D\xBF\x9A\x42\xD5\xC4\x48\x4E\
|
||||
\x0A\xBC\xD0\x6B\xFA\x53\xDD\xEF\x3C\x1B\x20\xEE\x3F\xD5\x9D\x7C\
|
||||
\x25\xE4\x1D\x2B\x66\x9E\x1E\xF1\x6E\x6F\x52\xC3\x16\x4D\xF4\xFB\
|
||||
\x79\x30\xE9\xE4\xE5\x88\x57\xB6\xAC\x7D\x5F\x42\xD6\x9F\x6D\x18\
|
||||
\x77\x63\xCF\x1D\x55\x03\x40\x04\x87\xF5\x5B\xA5\x7E\x31\xCC\x7A\
|
||||
\x71\x35\xC8\x86\xEF\xB4\x31\x8A\xED\x6A\x1E\x01\x2D\x9E\x68\x32\
|
||||
\xA9\x07\x60\x0A\x91\x81\x30\xC4\x6D\xC7\x78\xF9\x71\xAD\x00\x38\
|
||||
\x09\x29\x99\xA3\x33\xCB\x8B\x7A\x1A\x1D\xB9\x3D\x71\x40\x00\x3C\
|
||||
\x2A\x4E\xCE\xA9\xF9\x8D\x0A\xCC\x0A\x82\x91\xCD\xCE\xC9\x7D\xCF\
|
||||
\x8E\xC9\xB5\x5A\x7F\x88\xA4\x6B\x4D\xB5\xA8\x51\xF4\x41\x82\xE1\
|
||||
\xC6\x8A\x00\x7E\x5E\x65\x5F\x6A\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
||||
|
||||
let ffdhe6144 =
|
||||
(* p = 2^6144 - 2^6080 + {[2^6014 * e] + 15705020} * 2^64 - 1 *)
|
||||
(* The estimated symmetric-equivalent strength of this group is 175 bits.
|
||||
|
||||
Peers using ffdhe6144 that want to optimize their key exchange with a
|
||||
short exponent (Section 5.2) should choose a secret key of at least
|
||||
375 bits. *)
|
||||
s_group ~p:
|
||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xAD\xF8\x54\x58\xA2\xBB\x4A\x9A\
|
||||
\xAF\xDC\x56\x20\x27\x3D\x3C\xF1\xD8\xB9\xC5\x83\xCE\x2D\x36\x95\
|
||||
\xA9\xE1\x36\x41\x14\x64\x33\xFB\xCC\x93\x9D\xCE\x24\x9B\x3E\xF9\
|
||||
\x7D\x2F\xE3\x63\x63\x0C\x75\xD8\xF6\x81\xB2\x02\xAE\xC4\x61\x7A\
|
||||
\xD3\xDF\x1E\xD5\xD5\xFD\x65\x61\x24\x33\xF5\x1F\x5F\x06\x6E\xD0\
|
||||
\x85\x63\x65\x55\x3D\xED\x1A\xF3\xB5\x57\x13\x5E\x7F\x57\xC9\x35\
|
||||
\x98\x4F\x0C\x70\xE0\xE6\x8B\x77\xE2\xA6\x89\xDA\xF3\xEF\xE8\x72\
|
||||
\x1D\xF1\x58\xA1\x36\xAD\xE7\x35\x30\xAC\xCA\x4F\x48\x3A\x79\x7A\
|
||||
\xBC\x0A\xB1\x82\xB3\x24\xFB\x61\xD1\x08\xA9\x4B\xB2\xC8\xE3\xFB\
|
||||
\xB9\x6A\xDA\xB7\x60\xD7\xF4\x68\x1D\x4F\x42\xA3\xDE\x39\x4D\xF4\
|
||||
\xAE\x56\xED\xE7\x63\x72\xBB\x19\x0B\x07\xA7\xC8\xEE\x0A\x6D\x70\
|
||||
\x9E\x02\xFC\xE1\xCD\xF7\xE2\xEC\xC0\x34\x04\xCD\x28\x34\x2F\x61\
|
||||
\x91\x72\xFE\x9C\xE9\x85\x83\xFF\x8E\x4F\x12\x32\xEE\xF2\x81\x83\
|
||||
\xC3\xFE\x3B\x1B\x4C\x6F\xAD\x73\x3B\xB5\xFC\xBC\x2E\xC2\x20\x05\
|
||||
\xC5\x8E\xF1\x83\x7D\x16\x83\xB2\xC6\xF3\x4A\x26\xC1\xB2\xEF\xFA\
|
||||
\x88\x6B\x42\x38\x61\x1F\xCF\xDC\xDE\x35\x5B\x3B\x65\x19\x03\x5B\
|
||||
\xBC\x34\xF4\xDE\xF9\x9C\x02\x38\x61\xB4\x6F\xC9\xD6\xE6\xC9\x07\
|
||||
\x7A\xD9\x1D\x26\x91\xF7\xF7\xEE\x59\x8C\xB0\xFA\xC1\x86\xD9\x1C\
|
||||
\xAE\xFE\x13\x09\x85\x13\x92\x70\xB4\x13\x0C\x93\xBC\x43\x79\x44\
|
||||
\xF4\xFD\x44\x52\xE2\xD7\x4D\xD3\x64\xF2\xE2\x1E\x71\xF5\x4B\xFF\
|
||||
\x5C\xAE\x82\xAB\x9C\x9D\xF6\x9E\xE8\x6D\x2B\xC5\x22\x36\x3A\x0D\
|
||||
\xAB\xC5\x21\x97\x9B\x0D\xEA\xDA\x1D\xBF\x9A\x42\xD5\xC4\x48\x4E\
|
||||
\x0A\xBC\xD0\x6B\xFA\x53\xDD\xEF\x3C\x1B\x20\xEE\x3F\xD5\x9D\x7C\
|
||||
\x25\xE4\x1D\x2B\x66\x9E\x1E\xF1\x6E\x6F\x52\xC3\x16\x4D\xF4\xFB\
|
||||
\x79\x30\xE9\xE4\xE5\x88\x57\xB6\xAC\x7D\x5F\x42\xD6\x9F\x6D\x18\
|
||||
\x77\x63\xCF\x1D\x55\x03\x40\x04\x87\xF5\x5B\xA5\x7E\x31\xCC\x7A\
|
||||
\x71\x35\xC8\x86\xEF\xB4\x31\x8A\xED\x6A\x1E\x01\x2D\x9E\x68\x32\
|
||||
\xA9\x07\x60\x0A\x91\x81\x30\xC4\x6D\xC7\x78\xF9\x71\xAD\x00\x38\
|
||||
\x09\x29\x99\xA3\x33\xCB\x8B\x7A\x1A\x1D\xB9\x3D\x71\x40\x00\x3C\
|
||||
\x2A\x4E\xCE\xA9\xF9\x8D\x0A\xCC\x0A\x82\x91\xCD\xCE\xC9\x7D\xCF\
|
||||
\x8E\xC9\xB5\x5A\x7F\x88\xA4\x6B\x4D\xB5\xA8\x51\xF4\x41\x82\xE1\
|
||||
\xC6\x8A\x00\x7E\x5E\x0D\xD9\x02\x0B\xFD\x64\xB6\x45\x03\x6C\x7A\
|
||||
\x4E\x67\x7D\x2C\x38\x53\x2A\x3A\x23\xBA\x44\x42\xCA\xF5\x3E\xA6\
|
||||
\x3B\xB4\x54\x32\x9B\x76\x24\xC8\x91\x7B\xDD\x64\xB1\xC0\xFD\x4C\
|
||||
\xB3\x8E\x8C\x33\x4C\x70\x1C\x3A\xCD\xAD\x06\x57\xFC\xCF\xEC\x71\
|
||||
\x9B\x1F\x5C\x3E\x4E\x46\x04\x1F\x38\x81\x47\xFB\x4C\xFD\xB4\x77\
|
||||
\xA5\x24\x71\xF7\xA9\xA9\x69\x10\xB8\x55\x32\x2E\xDB\x63\x40\xD8\
|
||||
\xA0\x0E\xF0\x92\x35\x05\x11\xE3\x0A\xBE\xC1\xFF\xF9\xE3\xA2\x6E\
|
||||
\x7F\xB2\x9F\x8C\x18\x30\x23\xC3\x58\x7E\x38\xDA\x00\x77\xD9\xB4\
|
||||
\x76\x3E\x4E\x4B\x94\xB2\xBB\xC1\x94\xC6\x65\x1E\x77\xCA\xF9\x92\
|
||||
\xEE\xAA\xC0\x23\x2A\x28\x1B\xF6\xB3\xA7\x39\xC1\x22\x61\x16\x82\
|
||||
\x0A\xE8\xDB\x58\x47\xA6\x7C\xBE\xF9\xC9\x09\x1B\x46\x2D\x53\x8C\
|
||||
\xD7\x2B\x03\x74\x6A\xE7\x7F\x5E\x62\x29\x2C\x31\x15\x62\xA8\x46\
|
||||
\x50\x5D\xC8\x2D\xB8\x54\x33\x8A\xE4\x9F\x52\x35\xC9\x5B\x91\x17\
|
||||
\x8C\xCF\x2D\xD5\xCA\xCE\xF4\x03\xEC\x9D\x18\x10\xC6\x27\x2B\x04\
|
||||
\x5B\x3B\x71\xF9\xDC\x6B\x80\xD6\x3F\xDD\x4A\x8E\x9A\xDB\x1E\x69\
|
||||
\x62\xA6\x95\x26\xD4\x31\x61\xC1\xA4\x1D\x57\x0D\x79\x38\xDA\xD4\
|
||||
\xA4\x0E\x32\x9C\xD0\xE4\x0E\x65\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
||||
|
||||
let ffdhe8192 =
|
||||
(* p = 2^8192 - 2^8128 + {[2^8062 * e] + 10965728} * 2^64 - 1 *)
|
||||
(* The estimated symmetric-equivalent strength of this group is 192 bits.
|
||||
|
||||
Peers using ffdhe8192 that want to optimize their key exchange with a
|
||||
short exponent (Section 5.2) should choose a secret key of at least
|
||||
400 bits. *)
|
||||
s_group ~p:
|
||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xAD\xF8\x54\x58\xA2\xBB\x4A\x9A\
|
||||
\xAF\xDC\x56\x20\x27\x3D\x3C\xF1\xD8\xB9\xC5\x83\xCE\x2D\x36\x95\
|
||||
\xA9\xE1\x36\x41\x14\x64\x33\xFB\xCC\x93\x9D\xCE\x24\x9B\x3E\xF9\
|
||||
\x7D\x2F\xE3\x63\x63\x0C\x75\xD8\xF6\x81\xB2\x02\xAE\xC4\x61\x7A\
|
||||
\xD3\xDF\x1E\xD5\xD5\xFD\x65\x61\x24\x33\xF5\x1F\x5F\x06\x6E\xD0\
|
||||
\x85\x63\x65\x55\x3D\xED\x1A\xF3\xB5\x57\x13\x5E\x7F\x57\xC9\x35\
|
||||
\x98\x4F\x0C\x70\xE0\xE6\x8B\x77\xE2\xA6\x89\xDA\xF3\xEF\xE8\x72\
|
||||
\x1D\xF1\x58\xA1\x36\xAD\xE7\x35\x30\xAC\xCA\x4F\x48\x3A\x79\x7A\
|
||||
\xBC\x0A\xB1\x82\xB3\x24\xFB\x61\xD1\x08\xA9\x4B\xB2\xC8\xE3\xFB\
|
||||
\xB9\x6A\xDA\xB7\x60\xD7\xF4\x68\x1D\x4F\x42\xA3\xDE\x39\x4D\xF4\
|
||||
\xAE\x56\xED\xE7\x63\x72\xBB\x19\x0B\x07\xA7\xC8\xEE\x0A\x6D\x70\
|
||||
\x9E\x02\xFC\xE1\xCD\xF7\xE2\xEC\xC0\x34\x04\xCD\x28\x34\x2F\x61\
|
||||
\x91\x72\xFE\x9C\xE9\x85\x83\xFF\x8E\x4F\x12\x32\xEE\xF2\x81\x83\
|
||||
\xC3\xFE\x3B\x1B\x4C\x6F\xAD\x73\x3B\xB5\xFC\xBC\x2E\xC2\x20\x05\
|
||||
\xC5\x8E\xF1\x83\x7D\x16\x83\xB2\xC6\xF3\x4A\x26\xC1\xB2\xEF\xFA\
|
||||
\x88\x6B\x42\x38\x61\x1F\xCF\xDC\xDE\x35\x5B\x3B\x65\x19\x03\x5B\
|
||||
\xBC\x34\xF4\xDE\xF9\x9C\x02\x38\x61\xB4\x6F\xC9\xD6\xE6\xC9\x07\
|
||||
\x7A\xD9\x1D\x26\x91\xF7\xF7\xEE\x59\x8C\xB0\xFA\xC1\x86\xD9\x1C\
|
||||
\xAE\xFE\x13\x09\x85\x13\x92\x70\xB4\x13\x0C\x93\xBC\x43\x79\x44\
|
||||
\xF4\xFD\x44\x52\xE2\xD7\x4D\xD3\x64\xF2\xE2\x1E\x71\xF5\x4B\xFF\
|
||||
\x5C\xAE\x82\xAB\x9C\x9D\xF6\x9E\xE8\x6D\x2B\xC5\x22\x36\x3A\x0D\
|
||||
\xAB\xC5\x21\x97\x9B\x0D\xEA\xDA\x1D\xBF\x9A\x42\xD5\xC4\x48\x4E\
|
||||
\x0A\xBC\xD0\x6B\xFA\x53\xDD\xEF\x3C\x1B\x20\xEE\x3F\xD5\x9D\x7C\
|
||||
\x25\xE4\x1D\x2B\x66\x9E\x1E\xF1\x6E\x6F\x52\xC3\x16\x4D\xF4\xFB\
|
||||
\x79\x30\xE9\xE4\xE5\x88\x57\xB6\xAC\x7D\x5F\x42\xD6\x9F\x6D\x18\
|
||||
\x77\x63\xCF\x1D\x55\x03\x40\x04\x87\xF5\x5B\xA5\x7E\x31\xCC\x7A\
|
||||
\x71\x35\xC8\x86\xEF\xB4\x31\x8A\xED\x6A\x1E\x01\x2D\x9E\x68\x32\
|
||||
\xA9\x07\x60\x0A\x91\x81\x30\xC4\x6D\xC7\x78\xF9\x71\xAD\x00\x38\
|
||||
\x09\x29\x99\xA3\x33\xCB\x8B\x7A\x1A\x1D\xB9\x3D\x71\x40\x00\x3C\
|
||||
\x2A\x4E\xCE\xA9\xF9\x8D\x0A\xCC\x0A\x82\x91\xCD\xCE\xC9\x7D\xCF\
|
||||
\x8E\xC9\xB5\x5A\x7F\x88\xA4\x6B\x4D\xB5\xA8\x51\xF4\x41\x82\xE1\
|
||||
\xC6\x8A\x00\x7E\x5E\x0D\xD9\x02\x0B\xFD\x64\xB6\x45\x03\x6C\x7A\
|
||||
\x4E\x67\x7D\x2C\x38\x53\x2A\x3A\x23\xBA\x44\x42\xCA\xF5\x3E\xA6\
|
||||
\x3B\xB4\x54\x32\x9B\x76\x24\xC8\x91\x7B\xDD\x64\xB1\xC0\xFD\x4C\
|
||||
\xB3\x8E\x8C\x33\x4C\x70\x1C\x3A\xCD\xAD\x06\x57\xFC\xCF\xEC\x71\
|
||||
\x9B\x1F\x5C\x3E\x4E\x46\x04\x1F\x38\x81\x47\xFB\x4C\xFD\xB4\x77\
|
||||
\xA5\x24\x71\xF7\xA9\xA9\x69\x10\xB8\x55\x32\x2E\xDB\x63\x40\xD8\
|
||||
\xA0\x0E\xF0\x92\x35\x05\x11\xE3\x0A\xBE\xC1\xFF\xF9\xE3\xA2\x6E\
|
||||
\x7F\xB2\x9F\x8C\x18\x30\x23\xC3\x58\x7E\x38\xDA\x00\x77\xD9\xB4\
|
||||
\x76\x3E\x4E\x4B\x94\xB2\xBB\xC1\x94\xC6\x65\x1E\x77\xCA\xF9\x92\
|
||||
\xEE\xAA\xC0\x23\x2A\x28\x1B\xF6\xB3\xA7\x39\xC1\x22\x61\x16\x82\
|
||||
\x0A\xE8\xDB\x58\x47\xA6\x7C\xBE\xF9\xC9\x09\x1B\x46\x2D\x53\x8C\
|
||||
\xD7\x2B\x03\x74\x6A\xE7\x7F\x5E\x62\x29\x2C\x31\x15\x62\xA8\x46\
|
||||
\x50\x5D\xC8\x2D\xB8\x54\x33\x8A\xE4\x9F\x52\x35\xC9\x5B\x91\x17\
|
||||
\x8C\xCF\x2D\xD5\xCA\xCE\xF4\x03\xEC\x9D\x18\x10\xC6\x27\x2B\x04\
|
||||
\x5B\x3B\x71\xF9\xDC\x6B\x80\xD6\x3F\xDD\x4A\x8E\x9A\xDB\x1E\x69\
|
||||
\x62\xA6\x95\x26\xD4\x31\x61\xC1\xA4\x1D\x57\x0D\x79\x38\xDA\xD4\
|
||||
\xA4\x0E\x32\x9C\xCF\xF4\x6A\xAA\x36\xAD\x00\x4C\xF6\x00\xC8\x38\
|
||||
\x1E\x42\x5A\x31\xD9\x51\xAE\x64\xFD\xB2\x3F\xCE\xC9\x50\x9D\x43\
|
||||
\x68\x7F\xEB\x69\xED\xD1\xCC\x5E\x0B\x8C\xC3\xBD\xF6\x4B\x10\xEF\
|
||||
\x86\xB6\x31\x42\xA3\xAB\x88\x29\x55\x5B\x2F\x74\x7C\x93\x26\x65\
|
||||
\xCB\x2C\x0F\x1C\xC0\x1B\xD7\x02\x29\x38\x88\x39\xD2\xAF\x05\xE4\
|
||||
\x54\x50\x4A\xC7\x8B\x75\x82\x82\x28\x46\xC0\xBA\x35\xC3\x5F\x5C\
|
||||
\x59\x16\x0C\xC0\x46\xFD\x82\x51\x54\x1F\xC6\x8C\x9C\x86\xB0\x22\
|
||||
\xBB\x70\x99\x87\x6A\x46\x0E\x74\x51\xA8\xA9\x31\x09\x70\x3F\xEE\
|
||||
\x1C\x21\x7E\x6C\x38\x26\xE5\x2C\x51\xAA\x69\x1E\x0E\x42\x3C\xFC\
|
||||
\x99\xE9\xE3\x16\x50\xC1\x21\x7B\x62\x48\x16\xCD\xAD\x9A\x95\xF9\
|
||||
\xD5\xB8\x01\x94\x88\xD9\xC0\xA0\xA1\xFE\x30\x75\xA5\x77\xE2\x31\
|
||||
\x83\xF8\x1D\x4A\x3F\x2F\xA4\x57\x1E\xFC\x8C\xE0\xBA\x8A\x4F\xE8\
|
||||
\xB6\x85\x5D\xFE\x72\xB0\xA6\x6E\xDE\xD2\xFB\xAB\xFB\xE5\x8A\x30\
|
||||
\xFA\xFA\xBE\x1C\x5D\x71\xA8\x7E\x2F\x74\x1E\xF8\xC1\xFE\x86\xFE\
|
||||
\xA6\xBB\xFD\xE5\x30\x67\x7F\x0D\x97\xD1\x1D\x49\xF7\xA8\x44\x3D\
|
||||
\x08\x22\xE5\x06\xA9\xF4\x61\x4E\x01\x1E\x2A\x94\x83\x8F\xF8\x8C\
|
||||
\xD6\x8C\x8B\xB7\xC5\xC6\x42\x4C\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
||||
|
||||
end
|
||||
178
unikernel/duniverse/mirage-crypto/pk/dsa.ml
Normal file
178
unikernel/duniverse/mirage-crypto/pk/dsa.ml
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
open Mirage_crypto.Uncommon
|
||||
|
||||
open Common
|
||||
|
||||
type pub = { p : Z.t ; q : Z.t ; gg : Z.t ; y : Z.t }
|
||||
|
||||
let pub ?(fips = false) ~p ~q ~gg ~y () =
|
||||
let* () = guard Z.(one < gg && gg < p) (`Msg "bad generator") in
|
||||
let* () = guard (Z_extra.pseudoprime q) (`Msg "q is not prime") in
|
||||
let* () = guard (Z.is_odd p && Z_extra.pseudoprime p) (`Msg "p is not prime") in
|
||||
let* () = guard Z.(zero < y && y < p) (`Msg "y not in 0..p-1") in
|
||||
let* () = guard (q < p) (`Msg "q is not smaller than p") in
|
||||
let* () = guard Z.(zero = (pred p) mod q) (`Msg "p - 1 mod q <> 0") in
|
||||
let* () =
|
||||
if fips then
|
||||
match Z.numbits p, Z.numbits q with
|
||||
| 1024, 160 | 2048, 224 | 2048, 256 | 3072, 256 -> Ok ()
|
||||
| _ -> Error (`Msg "bit length of p or q not FIPS specified")
|
||||
else
|
||||
Ok ()
|
||||
in
|
||||
Ok { p ; q ; gg ; y }
|
||||
|
||||
type priv =
|
||||
{ p : Z.t ; q : Z.t ; gg : Z.t ; x : Z.t ; y : Z.t }
|
||||
|
||||
let priv ?fips ~p ~q ~gg ~x ~y () =
|
||||
let* _ = pub ?fips ~p ~q ~gg ~y () in
|
||||
let* () = guard Z.(zero < x && x < q) (`Msg "x not in 1..q-1") in
|
||||
let* () = guard Z.(y = powm gg x p) (`Msg "y <> g ^ x mod p") in
|
||||
Ok { p ; q ; gg ; x ; y }
|
||||
|
||||
let pub_of_priv { p; q; gg; y; _ } = { p; q; gg; y }
|
||||
|
||||
type keysize = [ `Fips1024 | `Fips2048 | `Fips3072 | `Exactly of int * int ]
|
||||
|
||||
let expand_size = function
|
||||
| `Fips1024 -> (1024, 160)
|
||||
| `Fips2048 -> (2048, 256)
|
||||
| `Fips3072 -> (3072, 256)
|
||||
| `Exactly (l, n) ->
|
||||
if 3 <= l && 2 <= n then (l, n) else
|
||||
invalid_arg "Dsa.generate: bits: `Exactly (%d, %d)" l n
|
||||
|
||||
type mask = [ `No | `Yes | `Yes_with of Mirage_crypto_rng.g ]
|
||||
|
||||
let expand_mask = function
|
||||
| `No -> `No
|
||||
| `Yes -> `Yes None
|
||||
| `Yes_with g -> `Yes (Some g)
|
||||
|
||||
(*
|
||||
* FIPS.186-4-style derivation:
|
||||
* - p and q are derived using a method numerically like the one described in
|
||||
* A.1.1.2, adapted to use the native rng.
|
||||
* - g is derived as per A.2.1.
|
||||
*)
|
||||
let params ?g size =
|
||||
let two = Z.(~$2) in
|
||||
let (l, n) = expand_size size in
|
||||
let q = Z_extra.prime ?g ~msb:1 n in
|
||||
let p =
|
||||
let q_q = Z.(q * two) in
|
||||
until Z_extra.pseudoprime @@ fun () ->
|
||||
let x = Z_extra.gen_bits ?g ~msb:1 l in
|
||||
Z.(x - (x mod q_q) + one)
|
||||
in
|
||||
let gg =
|
||||
let e = Z.(pred p / q) in
|
||||
until ((<>) Z.one) @@ fun () ->
|
||||
let h = Z_extra.gen_r ?g two Z.(pred p) in
|
||||
Z.(powm h e p)
|
||||
in
|
||||
(* all checks above are already satisfied *)
|
||||
(p, q, gg)
|
||||
|
||||
let generate ?g size =
|
||||
let (p, q, gg) = params ?g size in
|
||||
let x = Z_extra.gen_r ?g Z.one q in
|
||||
let y = Z.(powm gg x p) in
|
||||
(* checks are satisfied due to construction *)
|
||||
{ p; q; gg; x; y }
|
||||
|
||||
|
||||
module K_gen (H : Digestif.S) = struct
|
||||
|
||||
let drbg : 'a Mirage_crypto_rng.generator =
|
||||
let module M = Mirage_crypto_rng.Hmac_drbg (H) in (module M)
|
||||
|
||||
let z_gen ~key:{ q; x; _ } z =
|
||||
let repr = Z_extra.to_octets_be ~size:(Z.numbits q // 8) in
|
||||
let g = Mirage_crypto_rng.create ~strict:true drbg in
|
||||
Mirage_crypto_rng.reseed ~g (repr x ^ repr Z.(z mod q));
|
||||
Z_extra.gen_r ~g Z.one q
|
||||
|
||||
let generate ~key buf =
|
||||
z_gen ~key (Z_extra.of_octets_be ~bits:(Z.numbits key.q) buf)
|
||||
end
|
||||
|
||||
module K_gen_sha256 = K_gen (Digestif.SHA256)
|
||||
|
||||
let sign_z ?(mask = `Yes) ?k:k0 ~key:({ p; q; gg; x; _ } as key) z =
|
||||
let k = match k0 with Some k -> k | None -> K_gen_sha256.z_gen ~key z in
|
||||
let k' = Z.invert k q
|
||||
and b, b' = match expand_mask mask with
|
||||
| `No -> Z.one, Z.one
|
||||
| `Yes g ->
|
||||
let m = Z_extra.gen_r ?g Z.one q in
|
||||
m, Z.invert m q
|
||||
in
|
||||
let r = Z.(powm_sec gg k p mod q) in
|
||||
(* normal DSA sign is: s = k^-1 * (z + r * x) mod q *)
|
||||
(* we apply blinding where possible and compute:
|
||||
s = k^-1 * b^-1 * (b * z + b * r * x) mod q
|
||||
see https://github.com/openssl/openssl/pull/6524 for further details *)
|
||||
let s =
|
||||
let t1 =
|
||||
let t11 = Z.(b * x mod q) in
|
||||
Z.(t11 * r mod q)
|
||||
in
|
||||
let t2 = Z.(b * z mod q) in
|
||||
let t3 = Z.((t1 + t2) mod q) in
|
||||
let t4 = Z.(k' * t3 mod q) in
|
||||
Z.(b' * t4 mod q)
|
||||
in
|
||||
if r = Z.zero || s = Z.zero then invalid_arg "k unsuitable" else (r, s)
|
||||
|
||||
let verify_z ~key:({ p; q; gg; y }: pub ) (r, s) z =
|
||||
let v () =
|
||||
let w = Z.invert s q in
|
||||
let u1 = Z.(z * w mod q)
|
||||
and u2 = Z.(r * w mod q) in
|
||||
Z.((powm gg u1 p * powm y u2 p) mod p mod q) in
|
||||
Z.zero < r && r < q && Z.zero < s && s < q && v () = r
|
||||
|
||||
let sign ?mask ?k ~(key : priv) digest =
|
||||
let bits = Z.numbits key.q in
|
||||
let size = bits // 8 in
|
||||
let (r, s) = sign_z ?mask ?k ~key (Z_extra.of_octets_be ~bits digest) in
|
||||
Z_extra.(to_octets_be ~size r, to_octets_be ~size s)
|
||||
|
||||
let verify ~(key : pub) (r, s) digest =
|
||||
let z = Z_extra.of_octets_be ~bits:(Z.numbits key.q) digest
|
||||
and (r, s) = Z_extra.(of_octets_be r, of_octets_be s) in
|
||||
verify_z ~key (r, s) z
|
||||
|
||||
let rec shift_left_inplace buf = function
|
||||
| 0 -> ()
|
||||
| bits when bits mod 8 = 0 ->
|
||||
let off = bits / 8 in
|
||||
let to_blit = Bytes.length buf - off in
|
||||
Bytes.unsafe_blit buf off buf 0 to_blit ;
|
||||
Bytes.unsafe_fill buf to_blit (Bytes.length buf - to_blit) '\x00'
|
||||
| bits when bits < 8 ->
|
||||
let foo = 8 - bits in
|
||||
for i = 0 to Bytes.length buf - 2 do
|
||||
let b1 = Bytes.get_uint8 buf i
|
||||
and b2 = Bytes.get_uint8 buf (i + 1) in
|
||||
Bytes.set_uint8 buf i ((b1 lsl bits) lor (b2 lsr foo))
|
||||
done ;
|
||||
Bytes.set_uint8 buf (Bytes.length buf - 1)
|
||||
(Bytes.get_uint8 buf (Bytes.length buf - 1) lsl bits)
|
||||
| bits ->
|
||||
shift_left_inplace buf (8 * (bits / 8)) ;
|
||||
shift_left_inplace buf (bits mod 8)
|
||||
|
||||
let (lsl) buf bits =
|
||||
let buf' = Bytes.of_string buf in
|
||||
shift_left_inplace buf' bits;
|
||||
Bytes.unsafe_to_string buf'
|
||||
|
||||
let massage ~key:({ q; _ }: pub) digest =
|
||||
let bits = Z.numbits q in
|
||||
if bits >= String.length digest * 8 then
|
||||
digest
|
||||
else
|
||||
let buf = Z_extra.(to_octets_be Z.(of_octets_be digest mod q)) in
|
||||
buf lsl ((8 - bits mod 8) mod 8)
|
||||
5
unikernel/duniverse/mirage-crypto/pk/dune
Normal file
5
unikernel/duniverse/mirage-crypto/pk/dune
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
(library
|
||||
(name mirage_crypto_pk)
|
||||
(public_name mirage-crypto-pk)
|
||||
(libraries zarith mirage-crypto mirage-crypto-rng eqaf)
|
||||
(private_modules common dh dsa rsa z_extra))
|
||||
4
unikernel/duniverse/mirage-crypto/pk/mirage_crypto_pk.ml
Normal file
4
unikernel/duniverse/mirage-crypto/pk/mirage_crypto_pk.ml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
module Dh = Dh
|
||||
module Dsa = Dsa
|
||||
module Rsa = Rsa
|
||||
module Z_extra = Z_extra
|
||||
520
unikernel/duniverse/mirage-crypto/pk/mirage_crypto_pk.mli
Normal file
520
unikernel/duniverse/mirage-crypto/pk/mirage_crypto_pk.mli
Normal file
|
|
@ -0,0 +1,520 @@
|
|||
(** {1 Public-key cryptography} *)
|
||||
|
||||
(** Public and private key types are private, the constructors validate their
|
||||
well-formedness as much as possible, esp. so that [powm_sec] will not raise
|
||||
an exception (exponent > 1, or odd modulus). All modular exponentiations
|
||||
(unless otherwise noted) use the {!Z.powm_sec} function, which uses a static
|
||||
access pattern and operates in constant time (of the bit size of the input),
|
||||
independent of which bits are set and not set. The performance is up to 20%
|
||||
worse than [powm]. Additionally, blinding is applied to RSA and DSA by
|
||||
default. *)
|
||||
|
||||
(** {b RSA} public-key cryptography algorithm. *)
|
||||
module Rsa : sig
|
||||
|
||||
(** {1 Keys}
|
||||
|
||||
Messages are checked not to exceed the key size, and this is signalled via
|
||||
the {!Insufficient_key} exception.
|
||||
|
||||
Private-key operations are optionally protected through RSA blinding. *)
|
||||
|
||||
exception Insufficient_key
|
||||
(** Raised if the key is too small to transform the given message, i.e. if the
|
||||
numerical interpretation of the (potentially padded) message is not
|
||||
smaller than the modulus. *)
|
||||
|
||||
type pub = private {
|
||||
e : Z.t ; (** Public exponent *)
|
||||
n : Z.t ; (** Modulus *)
|
||||
}
|
||||
(** The public portion of the key. *)
|
||||
|
||||
val pub : e:Z.t -> n:Z.t -> (pub, [> `Msg of string ]) result
|
||||
(** [pub ~e ~n] validates the public key: [1 < e < n], [n > 0],
|
||||
[is_odd n], and [numbits n >= 89] (a requirement for PKCS1 operations). *)
|
||||
|
||||
type priv = private {
|
||||
e : Z.t ; (** Public exponent *)
|
||||
d : Z.t ; (** Private exponent *)
|
||||
n : Z.t ; (** Modulus ([p q])*)
|
||||
p : Z.t ; (** Prime factor [p] *)
|
||||
q : Z.t ; (** Prime factor [q] *)
|
||||
dp : Z.t ; (** [d mod (p-1)] *)
|
||||
dq : Z.t ; (** [d mod (q-1)] *)
|
||||
q' : Z.t ; (** [q^(-1) mod p] *)
|
||||
}
|
||||
(** Full private key (two-factor version).
|
||||
|
||||
{b Note} The key layout assumes that [p > q], which affects the quantity
|
||||
[q'] (sometimes called [u]), and the computation of the private transform.
|
||||
Some systems assume otherwise. When using keys produced by a system that
|
||||
computes [u = p^(-1) mod q], either exchange [p] with [q] and [dp] with
|
||||
[dq], or re-generate the full private key using
|
||||
{{!priv_of_primes}[priv_of_primes]}. *)
|
||||
|
||||
val priv : e:Z.t -> d:Z.t -> n:Z.t -> p:Z.t -> q:Z.t -> dp:Z.t -> dq:Z.t ->
|
||||
q':Z.t -> (priv, [> `Msg of string ]) result
|
||||
(** [priv ~e ~d ~n ~p ~q ~dp ~dq ~q'] validates the private key: [e, n] must
|
||||
be a valid {!type-pub}, [p] and [q] valid prime numbers [> 0], [odd],
|
||||
probabilistically prime, [p <> q], [n = p * q], [e] probabilistically
|
||||
prime and coprime to both [p] and [q], [q' = q ^ -1 mod p], [1 < d < n],
|
||||
[dp = d mod (p - 1)], [dq = d mod (q - 1)],
|
||||
and [d = e ^ -1 mod (p - 1) (q - 1)]. *)
|
||||
|
||||
val pub_bits : pub -> int
|
||||
(** Bit-size of a public key. *)
|
||||
|
||||
val priv_bits : priv -> int
|
||||
(** Bit-size of a private key. *)
|
||||
|
||||
val priv_of_primes : e:Z.t -> p:Z.t -> q:Z.t ->
|
||||
(priv, [> `Msg of string ]) result
|
||||
(** [priv_of_primes ~e ~p ~q] is the {{!type-priv}private key} derived from the
|
||||
minimal description [(e, p, q)]. *)
|
||||
|
||||
val priv_of_exp : ?g:Mirage_crypto_rng.g -> ?attempts:int -> e:Z.t -> d:Z.t ->
|
||||
n:Z.t -> unit -> (priv, [> `Msg of string ]) result
|
||||
(** [priv_of_exp ?g ?attempts ~e ~d n] is the unique {{!type-priv}private key}
|
||||
characterized by the public ([e]) and private ([d]) exponents, and modulus
|
||||
[n]. This operation uses a probabilistic process that can fail to recover
|
||||
the key.
|
||||
|
||||
[~attempts] is the number of trials. For triplets that form an RSA key,
|
||||
the probability of failure is at most [2^(-attempts)]. [attempts] defaults
|
||||
to an unspecified number that yields a very high probability of recovering
|
||||
valid keys.
|
||||
|
||||
Note that no time masking is done for the computations in this function. *)
|
||||
|
||||
val pub_of_priv : priv -> pub
|
||||
(** Extract the public component from a private key. *)
|
||||
|
||||
(** {1 The RSA transformation} *)
|
||||
|
||||
type 'a or_digest = [ `Message of 'a | `Digest of string ]
|
||||
(** Either an ['a] or its digest, according to some hash algorithm. *)
|
||||
|
||||
type mask = [ `No | `Yes | `Yes_with of Mirage_crypto_rng.g ]
|
||||
(** Masking (cryptographic blinding) mode for the RSA transform with the
|
||||
private key. Masking does not change the result, but it does change the
|
||||
timing profile of the operation.
|
||||
|
||||
{ul
|
||||
{- [`No] disables masking. It is slightly faster but it {b exposes the
|
||||
private key to timing-based attacks}.}
|
||||
{- [`Yes] uses random masking with the global RNG instance. This is
|
||||
the sane option.}
|
||||
{- [`Yes_with g] uses random masking with the generator [g].}} *)
|
||||
|
||||
val encrypt : key:pub -> string -> string
|
||||
(** [encrypt key message] is the encrypted [message].
|
||||
|
||||
@raise Insufficient_key (see {{!Insufficient_key}Insufficient_key})
|
||||
|
||||
@raise Invalid_argument if [message] is [0x00] or [0x01]. *)
|
||||
|
||||
val decrypt : ?crt_hardening:bool -> ?mask:mask -> key:priv ->
|
||||
string -> string
|
||||
(** [decrypt ~crt_hardening ~mask key ciphertext] is the decrypted
|
||||
[ciphertext], left-padded with [0x00] up to [key] size.
|
||||
|
||||
[~crt_hardening] defaults to [false]. If [true] verifies that the
|
||||
result is correct. This is to counter Chinese remainder theorem attacks to
|
||||
factorize primes. If the computed signature is incorrect, it is again
|
||||
computed in the classical way (c ^ d mod n) without the Chinese remainder
|
||||
theorem optimization. The deterministic {{!PKCS1.sign}PKCS1 signing},
|
||||
which is at danger, uses [true] as default.
|
||||
|
||||
[~mask] defaults to [`Yes].
|
||||
|
||||
@raise Insufficient_key (see {{!Insufficient_key}Insufficient_key}) *)
|
||||
|
||||
(** {1 Key generation} *)
|
||||
|
||||
val generate : ?g:Mirage_crypto_rng.g -> ?e:Z.t -> bits:int -> unit -> priv
|
||||
(** [generate ~g ~e ~bits ()] is a new {{!type-priv}private key}. The new key is
|
||||
guaranteed to be well formed, see {!val-priv}.
|
||||
|
||||
[e] defaults to [2^16+1].
|
||||
|
||||
{b Note} This process might diverge if there are no keys for the given
|
||||
bit size. This can happen when [bits] is extremely small.
|
||||
|
||||
@raise Invalid_argument if [e] is not a prime number (checked
|
||||
probabilistically) or not in the range [1 < e < 2^bits], or if
|
||||
[bits < 89] (as above, required for PKCS1 operations). *)
|
||||
|
||||
(** {1 PKCS#1 padded modes} *)
|
||||
|
||||
(** {b PKCS v1.5} operations, as defined by {b PKCS #1 v1.5}.
|
||||
|
||||
For the operations that only add the raw padding, the key size must be at
|
||||
least 11 bytes larger than the message. For full {{!PKCS1.sign}signing}, the
|
||||
minimal key size varies according to the hash algorithm. In this case, the
|
||||
key size is [priv_bits key / 8], rounded up. *)
|
||||
module PKCS1 : sig
|
||||
|
||||
val encrypt : ?g:Mirage_crypto_rng.g -> key:pub -> string -> string
|
||||
(** [encrypt g key message] is a PKCS1-padded (type 2) and encrypted
|
||||
[message].
|
||||
|
||||
@raise Insufficient_key (see {{!Insufficient_key}Insufficient_key}) *)
|
||||
|
||||
val decrypt : ?crt_hardening:bool -> ?mask:mask -> key:priv ->
|
||||
string -> string option
|
||||
(** [decrypt ~crt_hardening ~mask ~key ciphertext] is [Some message] if
|
||||
the [ciphertext] was produced by the corresponding {{!encrypt}encrypt}
|
||||
operation, or [None] otherwise. [crt_hardening] defaults to
|
||||
[false]. *)
|
||||
|
||||
val sig_encode : ?crt_hardening:bool -> ?mask:mask -> key:priv ->
|
||||
string -> string
|
||||
(** [sig_encode ~crt_hardening ~mask ~key message] is the PKCS1-padded
|
||||
(type 1) [message] signed by the [key]. [crt_hardening] defaults to
|
||||
[true] and verifies that the computed signature is correct.
|
||||
|
||||
{b Note} This operation performs only the padding and RSA transformation
|
||||
steps of the PKCS 1.5 signature. The full signature is implemented by
|
||||
{{!sign}[sign]}.
|
||||
|
||||
@raise Insufficient_key (see {{!Insufficient_key}Insufficient_key}) *)
|
||||
|
||||
val sig_decode : key:pub -> string -> string option
|
||||
(** [sig_decode key signature] is [Some message] when the [signature]
|
||||
was produced with the given [key] as per {{!sig_encode}sig_encode}, or
|
||||
[None] *)
|
||||
|
||||
val min_key : [< Digestif.hash' > `MD5 `SHA1 `SHA224 `SHA256 `SHA384 `SHA512 ] -> int
|
||||
(** [min_key hash] is the minimum key size required by {{!sign}[sign]}. *)
|
||||
|
||||
val sign : ?crt_hardening:bool -> ?mask:mask ->
|
||||
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
|
||||
as the payload. [crt_hardening] defaults to [true] and verifies that
|
||||
the computed signature is correct.
|
||||
|
||||
[message] is either the actual message, or its digest.
|
||||
|
||||
@raise Insufficient_key (see {{!Insufficient_key}Insufficient_key})
|
||||
|
||||
@raise Invalid_argument if message is a [`Digest] of the wrong size. *)
|
||||
|
||||
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].
|
||||
|
||||
[message] is either the actual message, or its digest.
|
||||
|
||||
[hashp] determines the allowed hash algorithms. Whenever [hashp] is
|
||||
[false], [verify] is also [false].
|
||||
|
||||
@raise Invalid_argument if message is a [`Digest] of the wrong size. *)
|
||||
end
|
||||
|
||||
(** {1 OAEP padded modes} *)
|
||||
|
||||
(** {b OAEP}-padded encryption, as defined by {b PKCS #1 v2.1}.
|
||||
|
||||
The same hash function is used for padding and MGF. MGF is {b MGF1} as
|
||||
defined in {b PKCS #1 2.1}.
|
||||
|
||||
Keys must have a minimum of [2 + 2 * hlen + len(message)] bytes, where
|
||||
[hlen] is the hash length. *)
|
||||
module OAEP (H : Digestif.S) : sig
|
||||
|
||||
val encrypt : ?g:Mirage_crypto_rng.g -> ?label:string -> key:pub ->
|
||||
string -> string
|
||||
(** [encrypt ~g ~label ~key message] is {b OAEP}-padded and encrypted
|
||||
[message], using the optional [label].
|
||||
|
||||
@raise Insufficient_key (see {{!Insufficient_key}Insufficient_key}) *)
|
||||
|
||||
val decrypt : ?crt_hardening:bool -> ?mask:mask -> ?label:string ->
|
||||
key:priv -> string -> string option
|
||||
(** [decrypt ~crt_hardening ~mask ~label ~key ciphertext] is
|
||||
[Some message] if the [ciphertext] was produced by the corresponding
|
||||
{{!encrypt}encrypt} operation, or [None] otherwise. [crt_hardening]
|
||||
defaults to [false]. *)
|
||||
end
|
||||
|
||||
(** {1 PSS signing} *)
|
||||
|
||||
(** {b PSS}-based signing, as defined by {b PKCS #1 v2.1}.
|
||||
|
||||
The same hash function is used for padding, MGF and computing message
|
||||
digest. MGF is {b MGF1} as defined in {b PKCS #1 2.1}.
|
||||
|
||||
Keys must have a minimum of [2 + hlen + slen] bytes, where [hlen] is the
|
||||
hash length and [slen] is the seed length. *)
|
||||
module PSS (H: Digestif.S) : sig
|
||||
|
||||
val sign : ?g:Mirage_crypto_rng.g -> ?crt_hardening:bool ->
|
||||
?mask:mask -> ?slen:int -> key:priv -> string or_digest -> string
|
||||
(** [sign ~g ~crt_hardening ~mask ~slen ~key message] the [PSS]-padded
|
||||
digest of [message], signed with the [key]. [crt_hardening] defaults
|
||||
to [false].
|
||||
|
||||
[slen] is the optional seed length and defaults to the size of the
|
||||
underlying hash function.
|
||||
|
||||
[message] is either the actual message, or its digest.
|
||||
|
||||
@raise Insufficient_key (see {{!Insufficient_key}Insufficient_key})
|
||||
|
||||
@raise Invalid_argument if message is a [`Digest] of the wrong size. *)
|
||||
|
||||
val verify : ?slen:int -> key:pub -> signature:string -> string or_digest -> bool
|
||||
(** [verify ~slen ~key ~signature message] checks whether [signature] is a
|
||||
valid {b PSS} signature of the [message] under the given [key].
|
||||
|
||||
[message] is either the actual message, or its digest.
|
||||
|
||||
@raise Invalid_argument if message is a [`Digest] of the wrong size. *)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
(** {b DSA} digital signature algorithm. *)
|
||||
module Dsa : sig
|
||||
|
||||
(** {1 DSA signature algorithm} *)
|
||||
|
||||
type priv = private {
|
||||
p : Z.t ; (** Modulus *)
|
||||
q : Z.t ; (** Subgroup order *)
|
||||
gg : Z.t ; (** Group Generator *)
|
||||
x : Z.t ; (** Private key proper *)
|
||||
y : Z.t ; (** Public component *)
|
||||
}
|
||||
(** Private key. [p], [q] and [gg] comprise {i domain parameters}. *)
|
||||
|
||||
val priv : ?fips:bool -> p:Z.t -> q:Z.t -> gg:Z.t -> x:Z.t -> y:Z.t -> unit ->
|
||||
(priv, [> `Msg of string ]) result
|
||||
(** [priv ~fips ~p ~q ~gg ~x ~y ()] constructs a private DSA key from the given
|
||||
numbers. Will result in an error if parameters are ill-formed: same as
|
||||
{!val-pub}, and additionally [0 < x < q] and [y = g ^ x mod p]. Note that no
|
||||
time masking is done on the modular exponentiation. *)
|
||||
|
||||
type pub = private {
|
||||
p : Z.t ;
|
||||
q : Z.t ;
|
||||
gg : Z.t ;
|
||||
y : Z.t ;
|
||||
}
|
||||
(** Public key, a subset of {{!type-priv}private key}. *)
|
||||
|
||||
val pub : ?fips:bool -> p:Z.t -> q:Z.t -> gg:Z.t -> y:Z.t -> unit ->
|
||||
(pub, [> `Msg of string ]) result
|
||||
(** [pub ~fips ~p ~q ~gg ~y ()] constructs a public DSA key from the given
|
||||
numbers. Will result in an error if the parameters are not well-formed:
|
||||
[one < gg < p], [q] probabilistically a prime, [p] probabilistically
|
||||
prime and odd, [0 < y < p], [q < p], and [p - 1 mod q = 0]. If [fips] is
|
||||
specified and [true] (defaults to [false]), only FIPS-specified bit length
|
||||
for [p] and [q] are accepted. *)
|
||||
|
||||
type keysize = [ `Fips1024 | `Fips2048 | `Fips3072 | `Exactly of int * int ]
|
||||
(** Key size request. Three {e Fips} variants refer to FIPS-standardized
|
||||
L-values ([p] size) and imply the corresponding N ([q] size); The last
|
||||
variants specifies L and N directly. *)
|
||||
|
||||
type mask = [ `No | `Yes | `Yes_with of Mirage_crypto_rng.g ]
|
||||
(** Masking (cryptographic blinding) option. *)
|
||||
|
||||
val pub_of_priv : priv -> pub
|
||||
(** Extract the public component from a private key. *)
|
||||
|
||||
val generate : ?g:Mirage_crypto_rng.g -> keysize -> priv
|
||||
(** [generate g size] is a fresh {{!type-priv}private} key. The domain parameters
|
||||
are derived using a modified FIPS.186-4 probabilistic process, but the
|
||||
derivation can not be validated. Note that no time masking is done for the
|
||||
modular exponentiations.
|
||||
|
||||
{b Note} The process might diverge if it is impossible to find parameters
|
||||
with the given bit sizes. This happens when [n] gets too big for [l], if
|
||||
the [size] was given as [`Exactly (l, n)].
|
||||
|
||||
@raise Invalid_argument if [size] is (`Exactly (l, n)), and either [l] or
|
||||
[n] is ridiculously small. *)
|
||||
|
||||
val sign : ?mask:mask -> ?k:Z.t -> key:priv -> string -> string * string
|
||||
(** [sign ~mask ~k ~key digest] is the signature, a pair of strings
|
||||
representing [r] and [s] in big-endian.
|
||||
|
||||
[digest] is the full digest of the actual message.
|
||||
|
||||
[k], the random component, can either be provided, or is deterministically
|
||||
derived as per RFC6979, using SHA256.
|
||||
|
||||
@raise Invalid_argument if [k] is unsuitable (leading to r or s being 0).
|
||||
*)
|
||||
|
||||
val verify : key:pub -> string * string -> string -> bool
|
||||
(** [verify ~key (r, s) digest] verifies that the pair [(r, s)] is the signature
|
||||
of [digest], the message digest, under the private counterpart to [key]. *)
|
||||
|
||||
val massage : key:pub -> string -> string
|
||||
(** [massage key digest] is the numeric value of [digest] taken modulo [q] and
|
||||
represented in the leftmost [bits(q)] bits of the result.
|
||||
|
||||
Both FIPS.186-4 and RFC6979 specify that only the leftmost [bits(q)] bits of
|
||||
[digest] are to be taken into account, but some implementations consider the
|
||||
entire [digest]. In cases where {{!sign}sign} and {{!verify}verify} seem
|
||||
incompatible with a given implementation (esp. if {{!sign}sign} produces
|
||||
signatures with the [s] component different from the other
|
||||
implementation's), it might help to pre-process [digest] using this
|
||||
function (e.g. [sign ~key (massage ~key:(pub_of_priv key) digest)]). *)
|
||||
|
||||
(** [K_gen] can be instantiated over a hashing module to obtain an RFC6979
|
||||
compliant [k]-generator for that hash. *)
|
||||
module K_gen (H : Digestif.S) : sig
|
||||
|
||||
val generate : key:priv -> string -> Z.t
|
||||
(** [generate key digest] deterministically takes the given private key and
|
||||
message digest to a [k] suitable for seeding the signing process. *)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
(** Diffie-Hellman, MODP version. *)
|
||||
module Dh : sig
|
||||
|
||||
(** {1 Diffie-Hellman key exchange} *)
|
||||
|
||||
exception Invalid_key
|
||||
(** Raised if the private key material is degenerate.
|
||||
The following invariants are checked:
|
||||
Secret key: [1 < secret < p]
|
||||
Public key: [1 < public < p-1] && [public <> gg]
|
||||
*)
|
||||
|
||||
type group = private {
|
||||
p : Z.t ; (** modulus *)
|
||||
gg : Z.t ; (** generator *)
|
||||
q : Z.t option ; (** subgroup order; potentially unknown *)
|
||||
}
|
||||
(** A DH group. *)
|
||||
|
||||
val group : p:Z.t -> gg:Z.t -> ?q:Z.t -> unit ->
|
||||
(group, [> `Msg of string ]) result
|
||||
(** [group ~p ~gg ~q ()] constructs a group if [p] is odd, a prime number,
|
||||
and greater than [zero]. [gg] must be in the range [1 < gg < p]. *)
|
||||
|
||||
type secret = private { group : group ; x : Z.t }
|
||||
(** A private key. *)
|
||||
|
||||
val modulus_size : group -> int
|
||||
(** Bit size of the modulus. *)
|
||||
|
||||
val key_of_secret : group -> s:string -> secret * string
|
||||
(** [key_of_secret group s] is the {!secret} and the corresponding public
|
||||
key which use [s] as the secret exponent.
|
||||
|
||||
@raise Invalid_key if [s] is degenerate. *)
|
||||
|
||||
val gen_key : ?g:Mirage_crypto_rng.g -> ?bits:int -> group -> secret * string
|
||||
(** Generate a random {!secret} and the corresponding public key.
|
||||
[bits] is the exact bit-size of {!secret} and defaults to a value
|
||||
dependent on the {!type-group}'s [p].
|
||||
|
||||
{b Note} The process might diverge when [bits] is extremely small. *)
|
||||
|
||||
val shared : secret -> string -> string option
|
||||
(** [shared secret public] is [Some shared_key] given a
|
||||
a previously generated {!secret} (which specifies the [group])
|
||||
and the other party's public key.
|
||||
[shared_key] is the unpadded big-endian representation of the shared key.
|
||||
It is [None] if these invariants do not hold for [public]:
|
||||
[1 < public < p-1] && [public <> gg]. *)
|
||||
|
||||
val gen_group : ?g:Mirage_crypto_rng.g -> bits:int -> unit -> group
|
||||
(** [gen_group ~g ~bits ()] generates a random {!type-group} with modulus size
|
||||
[bits]. Uses a safe prime [p = 2q + 1] (with [q] prime) for the modulus
|
||||
and [2] for the generator, such that [2^q = 1 mod p].
|
||||
Runtime is on the order of a minute for 1024 bits.
|
||||
Note that no time masking is done for the modular exponentiation.
|
||||
|
||||
{b Note} The process might diverge if there are no suitable groups. This
|
||||
happens with extremely small [bits] values. *)
|
||||
|
||||
(** A small catalog of standardized {!type-group}s. *)
|
||||
module Group : sig
|
||||
|
||||
(** From RFC 2409: *)
|
||||
|
||||
val oakley_1 : group
|
||||
val oakley_2 : group
|
||||
|
||||
(** From RFC 3526: *)
|
||||
|
||||
val oakley_5 : group
|
||||
val oakley_14 : group
|
||||
val oakley_15 : group
|
||||
val oakley_16 : group
|
||||
val oakley_17 : group
|
||||
val oakley_18 : group
|
||||
|
||||
(** From RFC 5114: *)
|
||||
|
||||
val rfc_5114_1 : group
|
||||
val rfc_5114_2 : group
|
||||
val rfc_5114_3 : group
|
||||
|
||||
(** From draft-ietf-tls-negotiated-ff-dhe-08 *)
|
||||
|
||||
val ffdhe2048 : group
|
||||
val ffdhe3072 : group
|
||||
val ffdhe4096 : group
|
||||
val ffdhe6144 : group
|
||||
val ffdhe8192 : group
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
(** {b Z} Convert Z to big endian string and generate random Z values. *)
|
||||
module Z_extra : sig
|
||||
(** {1 Conversion to and from string} *)
|
||||
|
||||
val of_octets_be : ?bits:int -> string -> Z.t
|
||||
(** [of_octets_be ~bits buf] interprets the bit pattern of [buf] as a
|
||||
{{!Z.t}[t]} in big-endian.
|
||||
|
||||
If [~bits] is not given, the operation considers the entire [buf],
|
||||
otherwise the initial [min ~bits (bit-length buf)] bits of [buf].
|
||||
|
||||
Assuming [n] is the number of bits to extract, the [n]-bit in [buf] is
|
||||
always the least significant bit of the result. Therefore:
|
||||
{ul
|
||||
{- if the bit size [k] of [t] is larger than [n], [k - n] most
|
||||
significant bits in the result are [0]; and}
|
||||
{- if [k] is smaller than [n], the result contains [k] last of the [n]
|
||||
first bits of [buf].}} *)
|
||||
|
||||
val to_octets_be : ?size:int -> Z.t -> string
|
||||
(** [to_octets_be ~size t] is the big-endian representation of [t].
|
||||
|
||||
If [~size] is not given, it defaults to the minimal number of bytes
|
||||
needed to represent [t], which is [bits t / 8] rounded up.
|
||||
|
||||
The least-significant bit of [t] is always the last bit in the result.
|
||||
If the size is larger than needed, the output is padded with zero bits.
|
||||
If it is smaller, the high bits in [t] are dropped. *)
|
||||
|
||||
val into_octets_be : Z.t -> bytes -> unit
|
||||
(** [into_octets_be t buf] writes the big-endian representation of [t] into
|
||||
[buf]. It behaves like {{!to_octets_be}[to_octets_be]}, with [~size]
|
||||
spanning the entire [buf]. *)
|
||||
|
||||
(** {1 Random generation} *)
|
||||
|
||||
val gen : ?g:Mirage_crypto_rng.g -> Z.t -> Z.t
|
||||
(** [gen ~g n] picks a value in the interval [\[0, n - 1\]] uniformly at random. *)
|
||||
|
||||
val gen_r : ?g:Mirage_crypto_rng.g -> Z.t -> Z.t -> Z.t
|
||||
(** [gen_r ~g low high] picks a value from the interval [\[low, high - 1\]]
|
||||
uniformly at random. *)
|
||||
end
|
||||
430
unikernel/duniverse/mirage-crypto/pk/rsa.ml
Normal file
430
unikernel/duniverse/mirage-crypto/pk/rsa.ml
Normal file
|
|
@ -0,0 +1,430 @@
|
|||
open Mirage_crypto.Uncommon
|
||||
|
||||
open Common
|
||||
|
||||
let two = Z.(~$2)
|
||||
and three = Z.(~$3)
|
||||
|
||||
(* A constant-time [find_uint8] with a default value. *)
|
||||
let ct_find_uint8 ~default ?off ~f cs =
|
||||
let res = Eqaf.find_uint8 ?off ~f cs in
|
||||
Eqaf.select_int (res + 1) default res
|
||||
|
||||
let (&.) f g = fun h -> f (g h)
|
||||
|
||||
type 'a or_digest = [ `Message of 'a | `Digest of string ]
|
||||
|
||||
module Digest_or (H : Digestif.S) = struct
|
||||
let digest_or = function
|
||||
| `Message msg -> H.(digest_string msg |> to_raw_string)
|
||||
| `Digest digest ->
|
||||
let n = String.length digest and m = H.digest_size in
|
||||
if n = m then digest else
|
||||
invalid_arg "(`Digest _): %d bytes, expecting %d" n m
|
||||
end
|
||||
|
||||
exception Insufficient_key
|
||||
|
||||
type pub = { e : Z.t ; n : Z.t }
|
||||
|
||||
(* due to PKCS1 *)
|
||||
let minimum_octets = 12
|
||||
let minimum_bits = 8 * minimum_octets - 7
|
||||
|
||||
let pub ~e ~n =
|
||||
(* We cannot verify a public key being good (this would require to verify "n"
|
||||
being the multiplication of two prime numbers - figuring out which primes
|
||||
were used is the security property of RSA).
|
||||
|
||||
but we validate to ensure our usage of powm_sec does not lead to
|
||||
exceptions, and we avoid tiny public keys where PKCS1 / PSS would lead to
|
||||
infinite loops or not work due to insufficient space for the header. *)
|
||||
let* () =
|
||||
guard Z.(n > zero && is_odd n && numbits n >= minimum_bits)
|
||||
(`Msg "invalid modulus")
|
||||
in
|
||||
let* () = guard Z.(one < e && e < n) (`Msg "invalid exponent") in
|
||||
(* NOTE that we could check for e being odd, or a prime, or 2^16+1, but
|
||||
these are not requirements, neither for RSA nor for powm_sec *)
|
||||
Ok { e ; n }
|
||||
|
||||
type priv = {
|
||||
e : Z.t ; d : Z.t ; n : Z.t ;
|
||||
p : Z.t ; q : Z.t ; dp : Z.t ; dq : Z.t ; q' : Z.t
|
||||
}
|
||||
|
||||
let valid_prime name p =
|
||||
guard Z.(p > zero && is_odd p && Z_extra.pseudoprime p)
|
||||
(`Msg ("invalid prime " ^ name))
|
||||
|
||||
let rprime a b = Z.(gcd a b = one)
|
||||
|
||||
let valid_e ~e ~p ~q =
|
||||
let* () =
|
||||
guard (rprime e (Z.pred p) && rprime e (Z.pred q))
|
||||
(`Msg "e is not coprime of p and q")
|
||||
in
|
||||
guard (Z_extra.pseudoprime e) (`Msg "exponent e is not a pseudoprime")
|
||||
|
||||
let priv ~e ~d ~n ~p ~q ~dp ~dq ~q' =
|
||||
let* _ = pub ~e ~n in
|
||||
let* () = valid_prime "p" p in
|
||||
let* () = valid_prime "q" q in
|
||||
let* () = guard (p <> q) (`Msg "p and q are the same number") in
|
||||
let* () = valid_e ~e ~p ~q in
|
||||
(* p and q are prime, and not equal -> multiplicative inverse exists *)
|
||||
let* () = guard Z.(q' = invert q p) (`Msg "q' <> q ^ -1 mod p") in
|
||||
let* () = guard Z.(n = p * q) (`Msg "modulus is not the product of p and q") in
|
||||
let* () = guard Z.(one < d && d < n) (`Msg "invalid private exponent") in
|
||||
let* () = guard Z.(dp = d mod (pred p)) (`Msg "dp <> d mod (p - 1)") in
|
||||
let* () = guard Z.(dq = d mod (pred q)) (`Msg "dq <> d mod (q - 1)") in
|
||||
(* e has been checked (valid_e) to be coprime to p-1 and q-1 ->
|
||||
muliplicative inverse exists *)
|
||||
let* () =
|
||||
guard Z.(one = d * e mod (lcm (pred p) (pred q)))
|
||||
(`Msg "1 <> d * e mod lcm (p - 1) (q - 1)")
|
||||
in
|
||||
Ok { e ; d ; n ; p ; q ; dp ; dq ; q' }
|
||||
|
||||
let priv_of_primes ~e ~p ~q =
|
||||
let* () = valid_prime "p" p in
|
||||
let* () = valid_prime "q" q in
|
||||
let* () = guard (p <> q) (`Msg "p and q are the same prime") in
|
||||
let* () = valid_e ~e ~p ~q in
|
||||
let n = Z.(p * q) in
|
||||
let* _ = pub ~e ~n in
|
||||
(* valid_e checks e coprime to p-1 and q-1, a multiplicative inverse exists *)
|
||||
let d = Z.(invert e (lcm (pred p) (pred q))) in
|
||||
let dp = Z.(d mod (pred p))
|
||||
and dq = Z.(d mod (pred q))
|
||||
in
|
||||
(* above we checked that p and q both are primes and not equal -> there
|
||||
should be a multiplicate inverse *)
|
||||
let q' = Z.invert q p in
|
||||
(* does not need to check valid_priv, since it is valid by construction *)
|
||||
Ok { e; d; n; p; q; dp; dq; q' }
|
||||
|
||||
(* Handbook of applied cryptography, 8.2.2 (i). *)
|
||||
let priv_of_exp ?g ?(attempts=100) ~e ~d ~n () =
|
||||
let* _ = pub ~e ~n in
|
||||
let* () = guard Z.(one < d && d < n) (`Msg "invalid private exponent") in
|
||||
let rec doit ~attempts =
|
||||
let factor s t =
|
||||
let rec go ax = function
|
||||
| 0 -> None
|
||||
| i' ->
|
||||
let ax2 = Z.(ax * ax mod n) in
|
||||
if Z.(ax <> one && ax <> pred n && ax2 = one) then
|
||||
Some ax
|
||||
else
|
||||
go ax2 (i' - 1)
|
||||
in
|
||||
Option.map Z.(gcd n &. pred) (go Z.(powm (Z_extra.gen ?g n) t n) s)
|
||||
in
|
||||
if attempts > 0 then
|
||||
let* s, t = Z_extra.strip_factor ~f:two Z.(e * d |> pred) in
|
||||
match s with
|
||||
| 0 -> Error (`Msg "invalid factor 0")
|
||||
| _ -> match factor s t with
|
||||
| None -> doit ~attempts:(attempts - 1)
|
||||
| Some p ->
|
||||
let q = Z.(div n p) in
|
||||
priv_of_primes ~e ~p:(max p q) ~q:(min p q)
|
||||
else Error (`Msg "attempts exceeded")
|
||||
in
|
||||
doit ~attempts
|
||||
|
||||
let rec generate ?g ?(e = Z.(~$0x10001)) ~bits () =
|
||||
if bits < minimum_bits || e < three ||
|
||||
(bits <= Z.numbits e || not (Z_extra.pseudoprime e))
|
||||
then
|
||||
invalid_arg "Rsa.generate: e: %a, bits: %d" Z.pp_print e bits;
|
||||
let (pb, qb) = (bits / 2, bits - bits / 2) in
|
||||
let (p, q) = Z_extra.(prime ?g ~msb:2 pb, prime ?g ~msb:2 qb) in
|
||||
match priv_of_primes ~e ~p:(max p q) ~q:(min p q) with
|
||||
| Error _ -> generate ?g ~e ~bits ()
|
||||
| Ok priv -> priv
|
||||
|
||||
let pub_of_priv ({ e; n; _ } : priv) = { e ; n }
|
||||
|
||||
let pub_bits ({ n; _ } : pub) = Z.numbits n
|
||||
and priv_bits ({ n; _ } : priv) = Z.numbits n
|
||||
|
||||
type mask = [ `No | `Yes | `Yes_with of Mirage_crypto_rng.g ]
|
||||
|
||||
let encrypt_unsafe ~key: ({ e; n } : pub) msg = Z.(powm msg e n)
|
||||
|
||||
let decrypt_unsafe ~crt_hardening ~key:({ e; d; n; p; q; dp; dq; q'} : priv) c =
|
||||
let m1 = Z.(powm_sec c dp p)
|
||||
and m2 = Z.(powm_sec c dq q) in
|
||||
(* NOTE: neither erem, nor the multiplications (addition, subtraction) are
|
||||
guaranteed to be constant time by gmp *)
|
||||
let h = Z.(erem (q' * (m1 - m2)) p) in
|
||||
let m = Z.(h * q + m2) in
|
||||
(* counter Arjen Lenstra's CRT attack by verifying the signature. Since the
|
||||
public exponent is small, this is not very expensive. Mentioned again
|
||||
"Factoring RSA keys with TLS Perfect Forward Secrecy" (Weimer, 2015). *)
|
||||
if not crt_hardening || Z.(powm_sec m e n) = c then
|
||||
m
|
||||
else
|
||||
Z.(powm_sec c d n)
|
||||
|
||||
let decrypt_blinded_unsafe ~crt_hardening ?g ~key:({ e; n; _} as key : priv) c =
|
||||
let r = until (rprime n) (fun _ -> Z_extra.gen_r ?g two n) in
|
||||
(* since r and n are coprime, there must be a multiplicative inverse *)
|
||||
let r' = Z.(invert r n) in
|
||||
let c' = Z.(powm_sec r e n * c mod n) in
|
||||
let x = decrypt_unsafe ~crt_hardening ~key c' in
|
||||
Z.(r' * x mod n)
|
||||
|
||||
let (encrypt_z, decrypt_z) =
|
||||
let check_params n msg =
|
||||
if msg < two then invalid_arg "Rsa: message: %a" Z.pp_print msg;
|
||||
if n <= msg then raise Insufficient_key in
|
||||
(fun ~(key : pub) msg -> check_params key.n msg ; encrypt_unsafe ~key msg),
|
||||
(fun ~crt_hardening ~mask ~(key : priv) msg ->
|
||||
check_params key.n msg ;
|
||||
match mask with
|
||||
| `No -> decrypt_unsafe ~crt_hardening ~key msg
|
||||
| `Yes -> decrypt_blinded_unsafe ~crt_hardening ~key msg
|
||||
| `Yes_with g -> decrypt_blinded_unsafe ~crt_hardening ~g ~key msg )
|
||||
|
||||
let reformat out f msg =
|
||||
Z_extra.(of_octets_be msg |> f |> to_octets_be ~size:(out // 8))
|
||||
|
||||
let encrypt ~key = reformat (pub_bits key) (encrypt_z ~key)
|
||||
|
||||
let decrypt ?(crt_hardening=false) ?(mask=`Yes) ~key =
|
||||
reformat (priv_bits key) (decrypt_z ~crt_hardening ~mask ~key)
|
||||
|
||||
let bx00, bx01 = "\x00", "\x01"
|
||||
|
||||
module PKCS1 = struct
|
||||
|
||||
let min_pad = 8
|
||||
|
||||
(* XXX Generalize this into `Rng.samplev` or something. *)
|
||||
let generate_with ?g ~f n =
|
||||
let buf = Bytes.create n
|
||||
and k = let b = Mirage_crypto_rng.block g in (n // b * b) in
|
||||
let rec go nonce i j =
|
||||
if i = n then Bytes.unsafe_to_string buf else
|
||||
if j = k then go Mirage_crypto_rng.(generate ?g k) i 0 else
|
||||
match String.get_uint8 nonce j with
|
||||
| b when f b -> Bytes.set_uint8 buf i b ; go nonce (succ i) (succ j)
|
||||
| _ -> go nonce i (succ j) in
|
||||
go Mirage_crypto_rng.(generate ?g k) 0 0
|
||||
|
||||
let pad ~mark ~padding k msg =
|
||||
let pad = padding (k - String.length msg - 3 |> imax min_pad) in
|
||||
String.concat "" [ bx00 ; mark ; pad ; bx00 ; msg ]
|
||||
|
||||
let unpad ~mark ~is_pad buf =
|
||||
let f = not &. is_pad in
|
||||
let i = ct_find_uint8 ~default:2 ~off:2 ~f buf in
|
||||
let c1 = String.get_uint8 buf 0 = 0x00
|
||||
and c2 = String.get_uint8 buf 1 = mark
|
||||
and c3 = String.get_uint8 buf i = 0x00
|
||||
and c4 = min_pad <= i - 2 in
|
||||
if c1 && c2 && c3 && c4 then
|
||||
Some (String.sub buf (i + 1) (String.length buf - i - 1))
|
||||
else None
|
||||
|
||||
let pad_01 =
|
||||
let padding size = String.make size '\xff' in
|
||||
pad ~mark:"\x01" ~padding
|
||||
let pad_02 ?g = pad ~mark:"\x02" ~padding:(generate_with ?g ~f:((<>) 0x00))
|
||||
|
||||
let unpad_01 = unpad ~mark:0x01 ~is_pad:((=) 0xff)
|
||||
let unpad_02 = unpad ~mark:0x02 ~is_pad:((<>) 0x00)
|
||||
|
||||
let padded pad transform keybits msg =
|
||||
let n = keybits // 8 in
|
||||
let p = pad n msg in
|
||||
if String.length p = n then transform p else raise Insufficient_key
|
||||
|
||||
let unpadded unpad transform keybits msg =
|
||||
if String.length msg = keybits // 8 then
|
||||
try unpad (transform msg) with Insufficient_key -> None
|
||||
else None
|
||||
|
||||
let sig_encode ?(crt_hardening = true) ?mask ~key msg =
|
||||
padded pad_01 (decrypt ~crt_hardening ?mask ~key) (priv_bits key) msg
|
||||
|
||||
let sig_decode ~key msg =
|
||||
unpadded unpad_01 (encrypt ~key) (pub_bits key) msg
|
||||
|
||||
let encrypt ?g ~key msg =
|
||||
padded (pad_02 ?g) (encrypt ~key) (pub_bits key) msg
|
||||
|
||||
let decrypt ?(crt_hardening = false) ?mask ~key msg =
|
||||
unpadded unpad_02 (decrypt ~crt_hardening ?mask ~key) (priv_bits key) msg
|
||||
|
||||
let asn_of_hash, detect =
|
||||
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
|
||||
(fun h -> List.assoc h map),
|
||||
(fun buf -> List.find_opt (fun (_, d) -> String.starts_with ~prefix:d buf) map)
|
||||
|
||||
let sign ?(crt_hardening = true) ?mask ~hash ~key msg =
|
||||
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 =
|
||||
let (>>=) = Option.bind
|
||||
and (>>|) = Fun.flip Option.map
|
||||
in
|
||||
Option.value
|
||||
(sig_decode ~key signature >>= fun buf ->
|
||||
detect buf >>| fun (hash, asn) ->
|
||||
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 =
|
||||
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
|
||||
|
||||
let repr n =
|
||||
let buf = Bytes.create 4 in
|
||||
Bytes.set_int32_be buf 0 n;
|
||||
Bytes.unsafe_to_string buf
|
||||
|
||||
(* Assumes len < 2^32 * H.digest_size. *)
|
||||
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.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 =
|
||||
let mgf_data = mgf ~seed (String.length buf) in
|
||||
unsafe_xor_into buf ~src_off:0 mgf_data ~dst_off:0 (String.length buf);
|
||||
mgf_data
|
||||
end
|
||||
|
||||
module OAEP (H : Digestif.S) = struct
|
||||
|
||||
module MGF = MGF1 (H)
|
||||
|
||||
let hlen = H.digest_size
|
||||
|
||||
let max_msg_bytes k = k - 2 * hlen - 2
|
||||
|
||||
let eme_oaep_encode ?g ?(label = "") k msg =
|
||||
let seed = Mirage_crypto_rng.generate ?g hlen
|
||||
and pad = String.make (max_msg_bytes k - String.length msg) '\x00' in
|
||||
let db = String.concat "" [ H.(digest_string label |> to_raw_string) ; pad ; bx01 ; msg ] in
|
||||
let mdb = Bytes.unsafe_to_string (MGF.mask ~seed db) in
|
||||
let mseed = Bytes.unsafe_to_string (MGF.mask ~seed:mdb seed) in
|
||||
String.concat "" [ bx00 ; mseed ; mdb ]
|
||||
|
||||
let eme_oaep_decode ?(label = "") msg =
|
||||
let b0 = String.sub msg 0 1
|
||||
and ms = String.sub msg 1 hlen
|
||||
and mdb = String.sub msg (1 + hlen) (String.length msg - 1 - hlen)
|
||||
in
|
||||
let db = Bytes.unsafe_to_string (MGF.mask ~seed:(Bytes.unsafe_to_string (MGF.mask ~seed:mdb ms)) mdb) in
|
||||
let i = ct_find_uint8 ~default:0 ~off:hlen ~f:((<>) 0x00) db in
|
||||
let c1 = Eqaf.equal (String.sub db 0 hlen) H.(digest_string label |> to_raw_string)
|
||||
and c2 = String.get_uint8 b0 0 = 0x00
|
||||
and c3 = String.get_uint8 db i = 0x01 in
|
||||
if c1 && c2 && c3 then Some (String.sub db (i + 1) (String.length db - i - 1)) else None
|
||||
|
||||
let encrypt ?g ?label ~key msg =
|
||||
let k = pub_bits key // 8 in
|
||||
if String.length msg > max_msg_bytes k then raise Insufficient_key
|
||||
else encrypt ~key @@ eme_oaep_encode ?g ?label k msg
|
||||
|
||||
let decrypt ?(crt_hardening = false) ?mask ?label ~key em =
|
||||
let k = priv_bits key // 8 in
|
||||
if String.length em <> k || max_msg_bytes k < 0 then None else
|
||||
try eme_oaep_decode ?label @@ decrypt ~crt_hardening ?mask ~key em
|
||||
with Insufficient_key -> None
|
||||
|
||||
(* XXX Review rfc3447 7.1.2 and
|
||||
* http://archiv.infsec.ethz.ch/education/fs08/secsem/Manger01.pdf
|
||||
* again for timing properties. *)
|
||||
|
||||
(* XXX expose seed for deterministic testing? *)
|
||||
end
|
||||
|
||||
module PSS (H: Digestif.S) = struct
|
||||
module MGF = MGF1 (H)
|
||||
module H1 = Digest_or (H)
|
||||
|
||||
let hlen = H.digest_size
|
||||
|
||||
let bxbc = "\xbc"
|
||||
|
||||
let b0mask embits = 0xff lsr ((8 - embits mod 8) mod 8)
|
||||
|
||||
let zero_8 = String.make 8 '\x00'
|
||||
|
||||
let digest ~salt msg =
|
||||
H.to_raw_string @@ H.digesti_string @@ iter3 zero_8 (H1.digest_or msg) salt
|
||||
|
||||
let emsa_pss_encode ?g slen emlen msg =
|
||||
let n = emlen // 8
|
||||
and salt = Mirage_crypto_rng.generate ?g slen in
|
||||
let h = digest ~salt msg in
|
||||
let db = String.concat "" [ String.make (n - slen - hlen - 2) '\x00' ; bx01 ; salt ] in
|
||||
let mdb = MGF.mask ~seed:h db in
|
||||
Bytes.set_uint8 mdb 0 @@ Bytes.get_uint8 mdb 0 land b0mask emlen ;
|
||||
String.concat "" [ Bytes.unsafe_to_string mdb ; h ; bxbc ]
|
||||
|
||||
let emsa_pss_verify slen emlen em msg =
|
||||
let mdb = String.sub em 0 (String.length em - hlen - 1)
|
||||
and h = String.sub em (String.length em - hlen - 1) hlen
|
||||
and bxx = String.get_uint8 em (String.length em - 1)
|
||||
in
|
||||
let db = MGF.mask ~seed:h mdb in
|
||||
Bytes.set_uint8 db 0 (Bytes.get_uint8 db 0 land b0mask emlen) ;
|
||||
let db = Bytes.unsafe_to_string db in
|
||||
let salt = String.sub db (String.length db - slen) slen in
|
||||
let h' = digest ~salt:salt msg
|
||||
and i = ct_find_uint8 ~default:0 ~f:((<>) 0x00) db in
|
||||
let c1 = lnot (b0mask emlen) land String.get_uint8 mdb 0 = 0x00
|
||||
and c2 = i = String.length em - hlen - slen - 2
|
||||
and c3 = String.get_uint8 db i = 0x01
|
||||
and c4 = bxx = 0xbc
|
||||
and c5 = Eqaf.equal h h' in
|
||||
c1 && c2 && c3 && c4 && c5
|
||||
|
||||
let sufficient_key ~slen kbits =
|
||||
hlen + slen + 2 <= kbits / 8 (* 8 * (hlen + slen + 1) + 2 <= kbits *)
|
||||
|
||||
let sign ?g ?(crt_hardening = false) ?mask ?(slen = hlen) ~key msg =
|
||||
let b = priv_bits key in
|
||||
if not (sufficient_key ~slen b) then raise Insufficient_key
|
||||
else
|
||||
let msg' = emsa_pss_encode ?g (imax 0 slen) (b - 1) msg in
|
||||
decrypt ~crt_hardening ?mask ~key msg'
|
||||
|
||||
let verify ?(slen = hlen) ~key ~signature msg =
|
||||
let b = pub_bits key
|
||||
and s = String.length signature in
|
||||
s = b // 8 && sufficient_key ~slen b && try
|
||||
let em = encrypt ~key signature in
|
||||
let to_see = s - (b - 1) // 8 in
|
||||
emsa_pss_verify (imax 0 slen) (b - 1) (String.sub em to_see (String.length em - to_see)) msg
|
||||
with Insufficient_key -> false
|
||||
|
||||
end
|
||||
135
unikernel/duniverse/mirage-crypto/pk/z_extra.ml
Normal file
135
unikernel/duniverse/mirage-crypto/pk/z_extra.ml
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
open Mirage_crypto.Uncommon
|
||||
|
||||
let bit_bound z = Z.size z * 64
|
||||
|
||||
let of_octets_be ?bits buf =
|
||||
let rec loop acc i = function
|
||||
| b when b >= 64 ->
|
||||
let x = String.get_int64_be buf i in
|
||||
let x = Z.of_int64_unsigned Int64.(shift_right_logical x 8) in
|
||||
loop Z.(x + acc lsl 56) (i + 7) (b - 56)
|
||||
| b when b >= 32 ->
|
||||
let x = String.get_int32_be buf i in
|
||||
let x = Z.of_int32_unsigned Int32.(shift_right_logical x 8) in
|
||||
loop Z.(x + acc lsl 24) (i + 3) (b - 24)
|
||||
| b when b >= 16 ->
|
||||
let x = Z.of_int (String.get_uint16_be buf i) in
|
||||
loop Z.(x + acc lsl 16) (i + 2) (b - 16)
|
||||
| b when b >= 8 ->
|
||||
let x = Z.of_int (String.get_uint8 buf i) in
|
||||
loop Z.(x + acc lsl 8 ) (i + 1) (b - 8 )
|
||||
| b when b > 0 ->
|
||||
let x = String.get_uint8 buf i and b' = 8 - b in
|
||||
Z.(of_int x asr b' + acc lsl b)
|
||||
| _ -> acc in
|
||||
loop Z.zero 0 @@ match bits with
|
||||
| None -> String.length buf * 8
|
||||
| Some b -> imin b (String.length buf * 8)
|
||||
|
||||
let byte1 = Z.of_int64 0xffL
|
||||
and byte2 = Z.of_int64 0xffffL
|
||||
and byte3 = Z.of_int64 0xffffffL
|
||||
and byte7 = Z.of_int64 0xffffffffffffffL
|
||||
|
||||
let into_octets_be n buf =
|
||||
let rec write n = function
|
||||
| i when i >= 7 ->
|
||||
Bytes.set_int64_be buf (i - 7) Z.(to_int64_unsigned (n land byte7)) ;
|
||||
write Z.(n asr 56) (i - 7)
|
||||
| i when i >= 3 ->
|
||||
Bytes.set_int32_be buf (i - 3) Z.(to_int32_unsigned (n land byte3)) ;
|
||||
write Z.(n asr 24) (i - 3)
|
||||
| i when i >= 1 ->
|
||||
Bytes.set_uint16_be buf (i - 1) Z.(to_int (n land byte2)) ;
|
||||
write Z.(n asr 16) (i - 2)
|
||||
| 0 -> Bytes.set_uint8 buf 0 Z.(to_int (n land byte1)) ;
|
||||
| _ -> ()
|
||||
in
|
||||
write n (Bytes.length buf - 1)
|
||||
|
||||
let to_octets_be ?size n =
|
||||
let buf = Bytes.create @@ match size with
|
||||
| Some s -> imax 0 s
|
||||
| None -> Z.numbits n // 8 in
|
||||
into_octets_be n buf;
|
||||
Bytes.unsafe_to_string buf
|
||||
|
||||
(* Handbook of Applied Cryptography, Table 4.4:
|
||||
* Miller-Rabin rounds for composite probability <= 1/2^80. *)
|
||||
let pseudoprime z =
|
||||
let i = match Z.numbits z with
|
||||
| i when i >= 1300 -> 2
|
||||
| i when i >= 850 -> 3
|
||||
| i when i >= 650 -> 4
|
||||
| i when i >= 350 -> 8
|
||||
| i when i >= 250 -> 12
|
||||
| i when i >= 150 -> 18
|
||||
| _ -> 27 in
|
||||
Z.probab_prime z i <> 0
|
||||
|
||||
(* strip_factor ~f x = (s, t), where x = f^s t *)
|
||||
let strip_factor ~f x =
|
||||
let rec go n x =
|
||||
let (x1, r) = Z.div_rem x f in
|
||||
if r = Z.zero then go (succ n) x1 else Ok (n, x)
|
||||
in
|
||||
if Z.(~$2) <= f then
|
||||
go 0 x
|
||||
else
|
||||
Error (`Msg ("factor_count: f: " ^ Z.to_string f))
|
||||
|
||||
let gen ?g n =
|
||||
if n < Z.one then invalid_arg "Rng.gen: non-positive: %a" Z.pp_print n;
|
||||
let bs = Mirage_crypto_rng.block g in
|
||||
let bits = Z.(numbits (pred n)) in
|
||||
let octets = bits // 8 in
|
||||
let batch =
|
||||
if Mirage_crypto_rng.strict g then octets else 2 * octets // bs * bs
|
||||
in
|
||||
let rec attempt buf =
|
||||
if String.length buf >= octets then
|
||||
let x = of_octets_be ~bits buf in
|
||||
if x < n then x else attempt (String.sub buf octets (String.length buf - octets))
|
||||
else attempt (Mirage_crypto_rng.generate ?g batch) in
|
||||
attempt (Mirage_crypto_rng.generate ?g batch)
|
||||
|
||||
let rec gen_r ?g a b =
|
||||
if Mirage_crypto_rng.strict g then
|
||||
let x = gen ?g b in if x < a then gen_r ?g a b else x
|
||||
else Z.(a + gen ?g (b - a))
|
||||
|
||||
|
||||
let set_msb bits buf =
|
||||
if bits > 0 then
|
||||
let n = Bytes.length buf in
|
||||
let rec go width = function
|
||||
| i when i = n -> ()
|
||||
| i when width < 8 ->
|
||||
Bytes.set_uint8 buf i (Bytes.get_uint8 buf i lor (0xff lsl (8 - width)))
|
||||
| i ->
|
||||
Bytes.set_uint8 buf i 0xff ;
|
||||
go (width - 8) (succ i)
|
||||
in
|
||||
go bits 0
|
||||
|
||||
let gen_bits ?g ?(msb = 0) bits =
|
||||
let bytelen = bits // 8 in
|
||||
let buf = Bytes.create bytelen in
|
||||
Mirage_crypto_rng.generate_into ?g buf ~off:0 bytelen;
|
||||
set_msb msb buf ;
|
||||
of_octets_be ~bits (Bytes.unsafe_to_string buf)
|
||||
|
||||
(* Invalid combinations of ~bits and ~msb will loop forever, but there is no
|
||||
* way to quickly determine upfront whether there are any primes in the
|
||||
* interval.
|
||||
* XXX Probability is distributed as inter-prime gaps. So?
|
||||
*)
|
||||
let rec prime ?g ?(msb = 1) bits =
|
||||
let p = Z.(nextprime @@ gen_bits ?g ~msb bits) in
|
||||
if p < Z.(one lsl bits) then p else prime ?g ~msb bits
|
||||
|
||||
(* XXX Add ~msb param for p? *)
|
||||
let rec safe_prime ?g bits =
|
||||
let q = prime ?g ~msb:1 (bits - 1) in
|
||||
let p = Z.(q * ~$2 + ~$1) in
|
||||
if pseudoprime p then (q, p) else safe_prime ?g bits
|
||||
Loading…
Add table
Add a link
Reference in a new issue