package digestif

  1. Overview
  2. Docs

Source file digestif_conv.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# 1 "default/lib/digestif/digestif_conv.ml"
module Make (D : sig val digest_size : int end) = struct
  let to_hex hash =
    let res = Bytes.create (D.digest_size * 2) in

    let chr x = match x with
      | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 -> Char.chr (48 + x)
      | _ -> Char.chr (97 + (x - 10)) in

    for i = 0 to D.digest_size - 1
    do
      let v = Char.code (String.get hash i) in
      Bytes.unsafe_set res (i * 2) (chr (v lsr 4));
      Bytes.unsafe_set res (i * 2 + 1) (chr (v land 0x0F));
    done;

    Bytes.unsafe_to_string res

  let code x = match x with
    | '0' .. '9' -> Char.code x - 48
    | 'A' .. 'F' -> Char.code x - 55
    | 'a' .. 'z' -> Char.code x - 87
    | _ -> invalid_arg "of_hex"

  let decode chr1 chr2 = Char.chr ((code chr1 lsl 4) lor (code chr2))

  let of_hex hex =
    let offset = ref 0 in

    let rec go have_first idx =
      if !offset + idx >= String.length hex
      then '\x00'
      else match String.get hex (!offset + idx) with
        | ' ' | '\t' | '\r' | '\n' ->
          incr offset;
          go have_first idx
        | chr2 when have_first -> chr2
        | chr1 ->
          incr offset;
          let chr2 = go true idx in
          if chr2 <> '\x00'
          then decode chr1 chr2
          else invalid_arg "of_hex: odd number of hex characters" in
    String.init D.digest_size (go false)

  let consistent_of_hex str =
    let offset = ref 0 in
    let rec go have_first idx =
      if !offset + idx >= String.length str
      then invalid_arg "Not enough hex value"
      else match String.get str (!offset + idx) with
        | ' ' | '\t'| '\r' | '\n' ->
          incr offset;
          go have_first idx
        | chr2 when have_first -> chr2
        | chr1 ->
          incr offset;
          let chr2 = go true idx in
          decode chr1 chr2 in
    let res = String.init D.digest_size (go false) in
    let is_wsp = function ' ' | '\t'| '\r' | '\n' -> true | _ -> false in

    while (D.digest_size * 2) + !offset < String.length str
          && is_wsp (String.get str (!offset + (D.digest_size * 2)))
    do incr offset done;

    if !offset + (D.digest_size * 2) = String.length str
    then res else invalid_arg "Too much enough bytes"

  let pp ppf hash =
    for i = 0 to D.digest_size - 1
    do Format.fprintf ppf "%02x" (Char.code (String.get hash i)) done
end
OCaml

Innovation. Community. Security.