<commit_before>open Common

type group = {
  p  : Z.t        ;  (* The prime modulus *)
  gg : Z.t        ;  (* Group generator *)
  q  : Z.t option ;  (* `gg`'s order, maybe *)
}

type secret = { x : Z.t }

let to_cstruct_sized { p; _ } z =
  Numeric.Z.(to_cstruct_be ~size:(cdiv (bits p) 8) z)

let group ~p ~gg ?q () =
  let (p, gg, q) =
    Numeric.Z.
      (of_cstruct_be p, of_cstruct_be gg, map_opt of_cstruct_be q)
  in
  (* This is more of a sanity theck, as order can actually be a divisor of q. *)
  ( match q with
    | Some q ->
        if Z.(powm gg q p <> one) then
          invalid_arg "DH.group: bogus order"
    | None -> () ) ;
  { p; gg; q }

let to_cstruct { p ; gg ; _ } =
  Numeric.Z.(to_cstruct_be p, to_cstruct_be gg)

let compute_public ({ p; gg; q } as group) x =
  let x   = opt x ~f:(Z.(mod) x) q in
  let ggx = Z.(powm gg x p) in
  ({ x }, to_cstruct_sized group ggx)

let of_secret group ~s =
  compute_public group (Numeric.Z.of_cstruct_be s)

let shared ({ p; _ } as group) { x } cs =
  let ggy    = Numeric.Z.of_cstruct_be cs in
  let secret = Z.(powm ggy x p) in
  to_cstruct_sized group secret

let gen_secret ?g ({ p; q; _ } as group) =
  compute_public group @@ Rng.Z.gen ?g (opt p ~f:id q)

(* Find a "safe prime." Slow, but the group has good order. *)
let gen_group ?g bits =
  (* XXX Compute the order? *)
  let (gg, p) = Rng.safe_prime ?g ~bits in
  { p; gg; q = None }<commit_msg>DH: x <- [2..p-2], not [0..p-1]<commit_after>open Common

type group = {
  p  : Z.t        ;  (* The prime modulus *)
  gg : Z.t        ;  (* Group generator *)
  q  : Z.t option ;  (* `gg`'s order, maybe *)
}

type secret = { x : Z.t }

let to_cstruct_sized { p; _ } z =
  Numeric.Z.(to_cstruct_be ~size:(cdiv (bits p) 8) z)

let group ~p ~gg ?q () =
  let (p, gg, q) =
    Numeric.Z.
      (of_cstruct_be p, of_cstruct_be gg, map_opt of_cstruct_be q)
  in
  (* This is more of a sanity theck, as order can actually be a divisor of q. *)
  ( match q with
    | Some q ->
        if Z.(powm gg q p <> one) then
          invalid_arg "DH.group: bogus order"
    | None -> () ) ;
  { p; gg; q }

let to_cstruct { p ; gg ; _ } =
  Numeric.Z.(to_cstruct_be p, to_cstruct_be gg)

let compute_public ({ p; gg; q } as group) x =
  let x =
    match q with
    | None   -> x
    | Some q -> Z.(x mod q) in
  let ggx = Z.(powm gg x p) in
  ({ x }, to_cstruct_sized group ggx)

let of_secret group ~s =
  compute_public group (Numeric.Z.of_cstruct_be s)

let gen_secret ?g ({ p; q; _ } as group) =
  let limit =
    match q with
    | None   -> Z.pred p
    | Some q -> q in
  compute_public group @@ Rng.Z.gen_r ?g z_two limit

let shared ({ p; _ } as group) { x } cs =
  let ggy    = Numeric.Z.of_cstruct_be cs in
  let secret = Z.(powm ggy x p) in
  to_cstruct_sized group secret


(* Find a "safe prime." Slow, but the group has good order. *)
let gen_group ?g bits =
  (* XXX Compute the order? *)
  let (gg, p) = Rng.safe_prime ?g ~bits in
  { p; gg; q = None }
{'fraction_non_alphanumeric': 0.13883299798792756, 'fraction_numerical': 0.002012072434607646, 'mean_word_length': 2.3479236812570146, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1289085', 'n_tokens_mistral': 1248, 'n_tokens_neox': 1223, 'n_words': 413}