upstream: github.com/robur-coop/kdf
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

kdf: modernize to dune 3.21 foreign_stubs

Replace deprecated c_names/c_flags with foreign_stubs stanza
for dune 3.21 compatibility.

+345 -460
+4 -4
hkdf/dune
··· 1 1 (library 2 - (name hkdf) 3 - (public_name kdf.hkdf) 4 - (modules hkdf) 5 - (libraries digestif)) 2 + (name hkdf) 3 + (public_name kdf.hkdf) 4 + (modules hkdf) 5 + (libraries digestif))
+12 -14
hkdf/hkdf.ml
··· 1 - 2 1 module type S = sig 3 2 val extract : ?salt:string -> string -> string 4 3 val expand : prk:string -> ?info:string -> int -> string ··· 6 5 7 6 module Make (H : Digestif.S) : S = struct 8 7 let extract ?salt ikm = 9 - let key = match salt with 10 - | None -> String.make H.digest_size '\x00' 11 - | Some x -> x 8 + let key = 9 + match salt with None -> String.make H.digest_size '\x00' | Some x -> x 12 10 in 13 11 H.(to_raw_string (hmac_string ~key ikm)) 14 12 15 13 let expand ~prk ?info len = 16 - let info = match info with 17 - | None -> "" 18 - | Some x -> x 19 - in 14 + let info = match info with None -> "" | Some x -> x in 20 15 let t n last = 21 16 let nc = String.make 1 (Char.unsafe_chr n) in 22 - H.(to_raw_string (hmac_string ~key:prk (String.concat "" [last ; info ; nc]))) 17 + H.( 18 + to_raw_string 19 + (hmac_string ~key:prk (String.concat "" [ last; info; nc ]))) 23 20 in 24 21 let n = succ (len / H.digest_size) in 25 - let rec compute acc count = match count, acc with 22 + let rec compute acc count = 23 + match (count, acc) with 26 24 | c, xs when c > n -> String.concat "" (List.rev xs) 27 - | c, x::_ -> compute (t c x :: acc) (succ c) 25 + | c, x :: _ -> compute (t c x :: acc) (succ c) 28 26 | _, [] -> invalid_arg "can not happen" 29 27 in 30 - let buf = compute [""] 1 in 28 + let buf = compute [ "" ] 1 in 31 29 String.sub buf 0 len 32 30 end 33 31 34 32 let extract ~hash ?salt ikm = 35 - let module H = (val (Digestif.module_of_hash' hash)) in 33 + let module H = (val Digestif.module_of_hash' hash) in 36 34 let module HKDF = Make (H) in 37 35 HKDF.extract ?salt ikm 38 36 39 37 let expand ~hash ~prk ?info len = 40 - let module H = (val (Digestif.module_of_hash' hash)) in 38 + let module H = (val Digestif.module_of_hash' hash) in 41 39 let module HKDF = Make (H) in 42 40 HKDF.expand ~prk ?info len
+9 -9
hkdf/hkdf.mli
··· 1 - 2 1 (** {{:https://tools.ietf.org/html/rfc5869}RFC 5869} specifies a HMAC-based 3 2 Extract-and-Expand Key Derivation Function (HKDF), which is abstracted over 4 3 a specific hash function. *) 5 4 6 5 module type S = sig 7 - 6 + val extract : ?salt:string -> string -> string 8 7 (** [extract salt ikm] is [prk], the pseudorandom key of hash length octets. 9 8 The [salt] is an optional non-secret random value, [ikm] the input key 10 9 material. *) 11 - val extract : ?salt:string -> string -> string 12 10 13 - (** [expand prk info length] is [okm], the output keying material. Given the 14 - pseudorandom key of hash length (usually output of [!extract] step), and an 15 - optional context and application specific information [info], the [okm] is 16 - generated. *) 17 11 val expand : prk:string -> ?info:string -> int -> string 12 + (** [expand prk info length] is [okm], the output keying material. Given the 13 + pseudorandom key of hash length (usually output of [!extract] step), and 14 + an optional context and application specific information [info], the [okm] 15 + is generated. *) 18 16 end 19 17 20 18 (** Given a Hash function, get the HKDF *) 21 19 module Make (H : Digestif.S) : S 22 20 23 - (** convenience [extract hash salt ikm] where the [hash] has to be provided explicitly *) 24 21 val extract : hash:Digestif.hash' -> ?salt:string -> string -> string 22 + (** convenience [extract hash salt ikm] where the [hash] has to be provided 23 + explicitly *) 25 24 26 - (** convenience [expand hash prk info len] where the [hash] has to be provided explicitly *) 27 25 val expand : hash:Digestif.hash' -> prk:string -> ?info:string -> int -> string 26 + (** convenience [expand hash prk info len] where the [hash] has to be provided 27 + explicitly *)
+4 -4
hkdf/tests/dune
··· 1 1 (test 2 - (name rfctests) 3 - (modules rfctests) 4 - (modes native) 5 - (libraries alcotest kdf.hkdf ohex)) 2 + (name rfctests) 3 + (modules rfctests) 4 + (modes native) 5 + (libraries alcotest kdf.hkdf ohex))
+83 -118
hkdf/tests/rfctests.ml
··· 1 - 2 1 let test ~hash ~ikm ?salt ?info ~l ~prk ~okm () = 3 2 let ikm = Ohex.decode ikm 4 3 and salt = match salt with None -> None | Some x -> Some (Ohex.decode x) 5 4 and info = match info with None -> None | Some x -> Some (Ohex.decode x) 6 5 and prk = Ohex.decode prk 7 - and okm = Ohex.decode okm 8 - in 9 - (fun () -> 10 - let cprk = Hkdf.extract ~hash ?salt ikm in 11 - Alcotest.check Alcotest.string "PRK matches" prk cprk ; 12 - let cokm = Hkdf.expand ~hash ~prk:cprk ?info l in 13 - Alcotest.check Alcotest.string "OKM matches" okm cokm) 6 + and okm = Ohex.decode okm in 7 + fun () -> 8 + let cprk = Hkdf.extract ~hash ?salt ikm in 9 + Alcotest.check Alcotest.string "PRK matches" prk cprk; 10 + let cokm = Hkdf.expand ~hash ~prk:cprk ?info l in 11 + Alcotest.check Alcotest.string "OKM matches" okm cokm 14 12 15 13 let test1 = 16 - test 17 - ~hash:`SHA256 18 - ~ikm:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b" 19 - ~salt:"000102030405060708090a0b0c" 20 - ~info:"f0f1f2f3f4f5f6f7f8f9" 21 - ~l:42 22 - ~prk:"077709362c2e32df0ddc3f0dc47bba63 \ 23 - 90b6c73bb50f9c3122ec844ad7c2b3e5" 24 - ~okm:"3cb25f25faacd57a90434f64d0362f2a \ 25 - 2d2d0a90cf1a5a4c5db02d56ecc4c5bf \ 26 - 34007208d5b887185865" 14 + test ~hash:`SHA256 ~ikm:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b" 15 + ~salt:"000102030405060708090a0b0c" ~info:"f0f1f2f3f4f5f6f7f8f9" ~l:42 16 + ~prk:"077709362c2e32df0ddc3f0dc47bba63 90b6c73bb50f9c3122ec844ad7c2b3e5" 17 + ~okm: 18 + "3cb25f25faacd57a90434f64d0362f2a 2d2d0a90cf1a5a4c5db02d56ecc4c5bf \ 19 + 34007208d5b887185865" 27 20 () 28 21 29 22 and test2 = 30 - test 31 - ~hash:`SHA256 32 - ~ikm:"000102030405060708090a0b0c0d0e0f \ 33 - 101112131415161718191a1b1c1d1e1f \ 34 - 202122232425262728292a2b2c2d2e2f \ 35 - 303132333435363738393a3b3c3d3e3f \ 36 - 404142434445464748494a4b4c4d4e4f" 37 - ~salt:"606162636465666768696a6b6c6d6e6f \ 38 - 707172737475767778797a7b7c7d7e7f \ 39 - 808182838485868788898a8b8c8d8e8f \ 40 - 909192939495969798999a9b9c9d9e9f \ 41 - a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" 42 - ~info:"b0b1b2b3b4b5b6b7b8b9babbbcbdbebf \ 43 - c0c1c2c3c4c5c6c7c8c9cacbcccdcecf \ 44 - d0d1d2d3d4d5d6d7d8d9dadbdcdddedf \ 45 - e0e1e2e3e4e5e6e7e8e9eaebecedeeef \ 46 - f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff" 23 + test ~hash:`SHA256 24 + ~ikm: 25 + "000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f \ 26 + 202122232425262728292a2b2c2d2e2f 303132333435363738393a3b3c3d3e3f \ 27 + 404142434445464748494a4b4c4d4e4f" 28 + ~salt: 29 + "606162636465666768696a6b6c6d6e6f 707172737475767778797a7b7c7d7e7f \ 30 + 808182838485868788898a8b8c8d8e8f 909192939495969798999a9b9c9d9e9f \ 31 + a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" 32 + ~info: 33 + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf c0c1c2c3c4c5c6c7c8c9cacbcccdcecf \ 34 + d0d1d2d3d4d5d6d7d8d9dadbdcdddedf e0e1e2e3e4e5e6e7e8e9eaebecedeeef \ 35 + f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff" 47 36 ~l:82 48 - ~prk:"06a6b88c5853361a06104c9ceb35b45c \ 49 - ef760014904671014a193f40c15fc244" 50 - ~okm:"b11e398dc80327a1c8e7f78c596a4934 \ 51 - 4f012eda2d4efad8a050cc4c19afa97c \ 52 - 59045a99cac7827271cb41c65e590e09 \ 53 - da3275600c2f09b8367793a9aca3db71 \ 54 - cc30c58179ec3e87c14c01d5c1f3434f \ 55 - 1d87" 37 + ~prk:"06a6b88c5853361a06104c9ceb35b45c ef760014904671014a193f40c15fc244" 38 + ~okm: 39 + "b11e398dc80327a1c8e7f78c596a4934 4f012eda2d4efad8a050cc4c19afa97c \ 40 + 59045a99cac7827271cb41c65e590e09 da3275600c2f09b8367793a9aca3db71 \ 41 + cc30c58179ec3e87c14c01d5c1f3434f 1d87" 56 42 () 57 43 58 44 and test3 = 59 - test 60 - ~hash:`SHA256 61 - ~ikm:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b" 62 - ~salt:"" 63 - (* info = (0 octets) *) 64 - ~l:42 65 - ~prk:"19ef24a32c717b167f33a91d6f648bdf \ 66 - 96596776afdb6377ac434c1c293ccb04" 67 - ~okm:"8da4e775a563c18f715f802a063c5a31 \ 68 - b8a11f5c5ee1879ec3454e5f3c738d2d \ 69 - 9d201395faa4b61a96c8" 45 + test ~hash:`SHA256 ~ikm:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b" 46 + ~salt:"" (* info = (0 octets) *) ~l:42 47 + ~prk:"19ef24a32c717b167f33a91d6f648bdf 96596776afdb6377ac434c1c293ccb04" 48 + ~okm: 49 + "8da4e775a563c18f715f802a063c5a31 b8a11f5c5ee1879ec3454e5f3c738d2d \ 50 + 9d201395faa4b61a96c8" 70 51 () 71 52 72 53 and test4 = 73 - test 74 - ~hash:`SHA1 75 - ~ikm:"0b0b0b0b0b0b0b0b0b0b0b" 76 - ~salt:"000102030405060708090a0b0c" 77 - ~info:"f0f1f2f3f4f5f6f7f8f9" 78 - ~l:42 54 + test ~hash:`SHA1 ~ikm:"0b0b0b0b0b0b0b0b0b0b0b" 55 + ~salt:"000102030405060708090a0b0c" ~info:"f0f1f2f3f4f5f6f7f8f9" ~l:42 79 56 ~prk:"9b6c18c432a7bf8f0e71c8eb88f4b30baa2ba243" 80 - ~okm:"085a01ea1b10f36933068b56efa5ad81 \ 81 - a4f14b822f5b091568a9cdd4f155fda2 \ 82 - c22e422478d305f3f896" 57 + ~okm: 58 + "085a01ea1b10f36933068b56efa5ad81 a4f14b822f5b091568a9cdd4f155fda2 \ 59 + c22e422478d305f3f896" 83 60 () 84 61 85 62 and test5 = 86 - test 87 - ~hash:`SHA1 88 - ~ikm:"000102030405060708090a0b0c0d0e0f \ 89 - 101112131415161718191a1b1c1d1e1f \ 90 - 202122232425262728292a2b2c2d2e2f \ 91 - 303132333435363738393a3b3c3d3e3f \ 92 - 404142434445464748494a4b4c4d4e4f" 93 - ~salt:"606162636465666768696a6b6c6d6e6f \ 94 - 707172737475767778797a7b7c7d7e7f \ 95 - 808182838485868788898a8b8c8d8e8f \ 96 - 909192939495969798999a9b9c9d9e9f \ 97 - a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" 98 - ~info:"b0b1b2b3b4b5b6b7b8b9babbbcbdbebf \ 99 - c0c1c2c3c4c5c6c7c8c9cacbcccdcecf \ 100 - d0d1d2d3d4d5d6d7d8d9dadbdcdddedf \ 101 - e0e1e2e3e4e5e6e7e8e9eaebecedeeef \ 102 - f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff" 103 - ~l:82 104 - ~prk:"8adae09a2a307059478d309b26c4115a224cfaf6" 105 - ~okm:"0bd770a74d1160f7c9f12cd5912a06eb \ 106 - ff6adcae899d92191fe4305673ba2ffe \ 107 - 8fa3f1a4e5ad79f3f334b3b202b2173c \ 108 - 486ea37ce3d397ed034c7f9dfeb15c5e \ 109 - 927336d0441f4c4300e2cff0d0900b52 \ 110 - d3b4" 111 - () 63 + test ~hash:`SHA1 64 + ~ikm: 65 + "000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f \ 66 + 202122232425262728292a2b2c2d2e2f 303132333435363738393a3b3c3d3e3f \ 67 + 404142434445464748494a4b4c4d4e4f" 68 + ~salt: 69 + "606162636465666768696a6b6c6d6e6f 707172737475767778797a7b7c7d7e7f \ 70 + 808182838485868788898a8b8c8d8e8f 909192939495969798999a9b9c9d9e9f \ 71 + a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" 72 + ~info: 73 + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf c0c1c2c3c4c5c6c7c8c9cacbcccdcecf \ 74 + d0d1d2d3d4d5d6d7d8d9dadbdcdddedf e0e1e2e3e4e5e6e7e8e9eaebecedeeef \ 75 + f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff" 76 + ~l:82 ~prk:"8adae09a2a307059478d309b26c4115a224cfaf6" 77 + ~okm: 78 + "0bd770a74d1160f7c9f12cd5912a06eb ff6adcae899d92191fe4305673ba2ffe \ 79 + 8fa3f1a4e5ad79f3f334b3b202b2173c 486ea37ce3d397ed034c7f9dfeb15c5e \ 80 + 927336d0441f4c4300e2cff0d0900b52 d3b4" 81 + () 112 82 113 83 and test6 = 114 - test 115 - ~hash:`SHA1 116 - ~ikm:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b" 117 - ~salt:"" 118 - (* info = (0 octets) *) 119 - ~l:42 84 + test ~hash:`SHA1 ~ikm:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b" 85 + ~salt:"" (* info = (0 octets) *) ~l:42 120 86 ~prk:"da8c8a73c7fa77288ec6f5e7c297786aa0d32d01" 121 - ~okm:"0ac1af7002b3d761d1e55298da9d0506 \ 122 - b9ae52057220a306e07b6b87e8df21d0 \ 123 - ea00033de03984d34918" 87 + ~okm: 88 + "0ac1af7002b3d761d1e55298da9d0506 b9ae52057220a306e07b6b87e8df21d0 \ 89 + ea00033de03984d34918" 124 90 () 125 91 126 92 and test7 = 127 - test 128 - ~hash:`SHA1 93 + test ~hash:`SHA1 129 94 ~ikm:"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c" 130 - (* salt = not provided (defaults to HashLen zero octets) *) 131 - (* info = (0 octets) *) 132 - ~l:42 133 - ~prk:"2adccada18779e7c2077ad2eb19d3f3e731385dd" 134 - ~okm:"2c91117204d745f3500d636a62f64f0a \ 135 - b3bae548aa53d423b0d1f27ebba6f5e5 \ 136 - 673a081d70cce7acfc48" 95 + (* salt = not provided (defaults to HashLen zero octets) *) 96 + (* info = (0 octets) *) 97 + ~l:42 ~prk:"2adccada18779e7c2077ad2eb19d3f3e731385dd" 98 + ~okm: 99 + "2c91117204d745f3500d636a62f64f0a b3bae548aa53d423b0d1f27ebba6f5e5 \ 100 + 673a081d70cce7acfc48" 137 101 () 138 102 139 - let tests = [ 140 - "RFC 5869 Test Case 1", `Quick, test1 ; 141 - "RFC 5869 Test Case 2", `Quick, test2 ; 142 - "RFC 5869 Test Case 3", `Quick, test3 ; 143 - "RFC 5869 Test Case 4", `Quick, test4 ; 144 - "RFC 5869 Test Case 5", `Quick, test5 ; 145 - "RFC 5869 Test Case 6", `Quick, test6 ; 146 - "RFC 5869 Test Case 7", `Quick, test7 ; 147 - ] 103 + let tests = 104 + [ 105 + ("RFC 5869 Test Case 1", `Quick, test1); 106 + ("RFC 5869 Test Case 2", `Quick, test2); 107 + ("RFC 5869 Test Case 3", `Quick, test3); 108 + ("RFC 5869 Test Case 4", `Quick, test4); 109 + ("RFC 5869 Test Case 5", `Quick, test5); 110 + ("RFC 5869 Test Case 6", `Quick, test6); 111 + ("RFC 5869 Test Case 7", `Quick, test7); 112 + ] 148 113 149 - let () = Alcotest.run "HKDF Tests" [ "RFC 5869", tests ] 114 + let () = Alcotest.run "HKDF Tests" [ ("RFC 5869", tests) ]
+25 -17
pbkdf/pbkdf.ml
··· 1 1 module type S = sig 2 - val pbkdf1 : password:string -> salt:string -> count:int -> dk_len:int -> string 3 - val pbkdf2 : password:string -> salt:string -> count:int -> dk_len:int32 -> string 2 + val pbkdf1 : 3 + password:string -> salt:string -> count:int -> dk_len:int -> string 4 + 5 + val pbkdf2 : 6 + password:string -> salt:string -> count:int -> dk_len:int32 -> string 4 7 end 5 8 6 9 let cdiv x y = ··· 8 11 (formerly known as [cdiv]). It is part of the documented, publically 9 12 exposed _internal_ utility library not for public consumption, hence 10 13 the API break that prompted this copy-pasted function. *) 11 - if y < 1 then raise Division_by_zero else 12 - if x > 0 then 1 + ((x - 1) / y) else 0 [@@inline] 14 + if y < 1 then raise Division_by_zero 15 + else if x > 0 then 1 + ((x - 1) / y) 16 + else 0 17 + [@@inline] 13 18 14 - module Make (H: Digestif.S) : S = struct 19 + module Make (H : Digestif.S) : S = struct 15 20 let pbkdf1 ~password ~salt ~count ~dk_len = 16 21 if String.length salt <> 8 then invalid_arg "salt should be 8 bytes" 17 22 else if count <= 0 then invalid_arg "count must be a positive integer" 18 - else if dk_len <= 0 then invalid_arg "derived key length must be a positive integer" 23 + else if dk_len <= 0 then 24 + invalid_arg "derived key length must be a positive integer" 19 25 else if dk_len > H.digest_size then invalid_arg "derived key too long" 20 26 else 21 27 let rec loop t = function 22 - 0 -> t 28 + | 0 -> t 23 29 | i -> loop H.(to_raw_string (digest_string t)) (i - 1) 24 30 in 25 31 String.sub (loop (password ^ salt) count) 0 dk_len 26 32 27 33 let pbkdf2 ~password ~salt ~count ~dk_len = 28 34 if count <= 0 then invalid_arg "count must be a positive integer" 29 - else if dk_len <= 0l then invalid_arg "derived key length must be a positive integer" 35 + else if dk_len <= 0l then 36 + invalid_arg "derived key length must be a positive integer" 30 37 else 31 - let h_len = H.digest_size 32 - and dk_len = Int32.to_int dk_len in 38 + let h_len = H.digest_size and dk_len = Int32.to_int dk_len in 33 39 let l = cdiv dk_len h_len in 34 - let r = dk_len - (l - 1) * h_len in 40 + let r = dk_len - ((l - 1) * h_len) in 35 41 let block i = 36 42 let rec f u xor = function 37 43 | 0 -> xor 38 44 | j -> 39 - let u = H.(to_raw_string (hmac_string ~key:password u)) in 40 - f u (Crypto.Uncommon.xor xor u) (j - 1) 45 + let u = H.(to_raw_string (hmac_string ~key:password u)) in 46 + f u (Crypto.Uncommon.xor xor u) (j - 1) 41 47 in 42 48 let int_i = Bytes.create 4 in 43 49 Bytes.set_int32_be int_i 0 (Int32.of_int i); 44 - let u_1 = H.hmac_string ~key:password (salt ^ Bytes.unsafe_to_string int_i) in 50 + let u_1 = 51 + H.hmac_string ~key:password (salt ^ Bytes.unsafe_to_string int_i) 52 + in 45 53 let u_1 = H.to_raw_string u_1 in 46 54 f u_1 u_1 (count - 1) 47 55 in ··· 49 57 | 0 -> blocks 50 58 | i -> loop (block i :: blocks) (i - 1) 51 59 in 52 - String.concat "" (loop [String.sub (block l) 0 r] (l - 1)) 60 + String.concat "" (loop [ String.sub (block l) 0 r ] (l - 1)) 53 61 end 54 62 55 63 let pbkdf1 ~hash ~password ~salt ~count ~dk_len = 56 - let module H = (val (Digestif.module_of_hash' hash)) in 64 + let module H = (val Digestif.module_of_hash' hash) in 57 65 let module PBKDF = Make (H) in 58 66 PBKDF.pbkdf1 ~password ~salt ~count ~dk_len 59 67 60 68 let pbkdf2 ~prf ~password ~salt ~count ~dk_len = 61 - let module H = (val (Digestif.module_of_hash' prf)) in 69 + let module H = (val Digestif.module_of_hash' prf) in 62 70 let module PBKDF = Make (H) in 63 71 PBKDF.pbkdf2 ~password ~salt ~count ~dk_len
+33 -15
pbkdf/pbkdf.mli
··· 1 - (** {{:https://tools.ietf.org/html/rfc2898}RFC 2898} specifies two password-based 2 - key derivation functions (PBKDF1 and PBKDF2), which are abstracted over 3 - a specific hash/pseudorandom function. *) 1 + (** {{:https://tools.ietf.org/html/rfc2898}RFC 2898} specifies two 2 + password-based key derivation functions (PBKDF1 and PBKDF2), which are 3 + abstracted over a specific hash/pseudorandom function. *) 4 4 module type S = sig 5 - (** [pbkdf1 password salt count dk_len] is [dk], the derived key of [dk_len] octets. 6 - The [salt] must be eight octets, [count] the iteration count. 7 - @raise Invalid_argument when either [salt] is not eight octets long or either 8 - [count] or [dk_len] are not valid. *) 9 - val pbkdf1 : password:string -> salt:string -> count:int -> dk_len:int -> string 5 + val pbkdf1 : 6 + password:string -> salt:string -> count:int -> dk_len:int -> string 7 + (** [pbkdf1 password salt count dk_len] is [dk], the derived key of [dk_len] 8 + octets. The [salt] must be eight octets, [count] the iteration count. 9 + @raise Invalid_argument 10 + when either [salt] is not eight octets long or either [count] or 11 + [dk_len] are not valid. *) 10 12 11 - (** [pbkdf2 password salt count dk_len] is [dk], the derived key of [dk_len] octets. 13 + val pbkdf2 : 14 + password:string -> salt:string -> count:int -> dk_len:int32 -> string 15 + (** [pbkdf2 password salt count dk_len] is [dk], the derived key of [dk_len] 16 + octets. 12 17 @raise Invalid_argument when either [count] or [dk_len] are not valid *) 13 - val pbkdf2 : password:string -> salt:string -> count:int -> dk_len:int32 -> string 14 18 end 15 19 16 20 (** Given a Hash/pseudorandom function, get the PBKDF *) 17 - module Make (H: Digestif.S) : S 21 + module Make (H : Digestif.S) : S 18 22 19 - (** convenience [pbkdf1 hash password salt count dk_len] where the [hash] has to be provided explicitly *) 20 - val pbkdf1 : hash:Digestif.hash' -> password:string -> salt:string -> count:int -> dk_len:int -> string 23 + val pbkdf1 : 24 + hash:Digestif.hash' -> 25 + password:string -> 26 + salt:string -> 27 + count:int -> 28 + dk_len:int -> 29 + string 30 + (** convenience [pbkdf1 hash password salt count dk_len] where the [hash] has to 31 + be provided explicitly *) 21 32 22 - (** convenience [pbkdf2 prf password salt count dk_len] where the [prf] has to be provided explicitly *) 23 - val pbkdf2 : prf:Digestif.hash' -> password:string -> salt:string -> count:int -> dk_len:int32 -> string 33 + val pbkdf2 : 34 + prf:Digestif.hash' -> 35 + password:string -> 36 + salt:string -> 37 + count:int -> 38 + dk_len:int32 -> 39 + string 40 + (** convenience [pbkdf2 prf password salt count dk_len] where the [prf] has to 41 + be provided explicitly *)
+99 -199
pbkdf/test/pbkdf_tests.ml
··· 2 2 3 3 (* PBKDF1 *) 4 4 let test_pbkdf1 ~hash ~password ~salt ~count ~dk_len ~dk = 5 - let salt = Ohex.decode salt 6 - and dk = Ohex.decode dk in 7 - (fun () -> 8 - let edk = Pbkdf.pbkdf1 ~hash ~password ~salt ~count ~dk_len in 9 - Alcotest.check Alcotest.string "PBKDF1 test" edk dk) 5 + let salt = Ohex.decode salt and dk = Ohex.decode dk in 6 + fun () -> 7 + let edk = Pbkdf.pbkdf1 ~hash ~password ~salt ~count ~dk_len in 8 + Alcotest.check Alcotest.string "PBKDF1 test" edk dk 10 9 11 10 let test_pbkdf1_invalid_arg ~hash ~password ~salt ~count ~dk_len ~msg = 12 11 let salt = Ohex.decode salt in 13 - (fun () -> 14 - Alcotest.check_raises 15 - msg 16 - (Invalid_argument msg) 17 - (fun () -> ignore (Pbkdf.pbkdf1 ~hash ~password ~salt ~count ~dk_len))) 12 + fun () -> 13 + Alcotest.check_raises msg (Invalid_argument msg) (fun () -> 14 + ignore (Pbkdf.pbkdf1 ~hash ~password ~salt ~count ~dk_len)) 18 15 19 16 (* Taken from http://www.di-mgt.com.au/cryptoKDFs.html *) 20 17 let pbkdf1_test1 = 21 - test_pbkdf1 22 - ~hash:`SHA1 23 - ~password:"password" 24 - ~salt:"78578e5a5d63cb06" 25 - ~count:1000 26 - ~dk_len:16 27 - ~dk:"dc19847e05c64d2faf10ebfb4a3d2a20" 18 + test_pbkdf1 ~hash:`SHA1 ~password:"password" ~salt:"78578e5a5d63cb06" 19 + ~count:1000 ~dk_len:16 ~dk:"dc19847e05c64d2faf10ebfb4a3d2a20" 28 20 29 21 let pbkdf1_test2 = 30 - test_pbkdf1_invalid_arg 31 - ~hash:`SHA1 32 - ~password:"password" 33 - ~salt:"78578e5a5d63cb" 34 - ~count:1000 35 - ~dk_len:16 36 - ~msg:"salt should be 8 bytes" 22 + test_pbkdf1_invalid_arg ~hash:`SHA1 ~password:"password" 23 + ~salt:"78578e5a5d63cb" ~count:1000 ~dk_len:16 ~msg:"salt should be 8 bytes" 37 24 38 25 let pbkdf1_test3 = 39 - test_pbkdf1_invalid_arg 40 - ~hash:`SHA1 41 - ~password:"password" 42 - ~salt:"78578e5a5d63cb0600" 43 - ~count:1000 44 - ~dk_len:16 26 + test_pbkdf1_invalid_arg ~hash:`SHA1 ~password:"password" 27 + ~salt:"78578e5a5d63cb0600" ~count:1000 ~dk_len:16 45 28 ~msg:"salt should be 8 bytes" 46 29 47 30 let pbkdf1_test4 = 48 - test_pbkdf1_invalid_arg 49 - ~hash:`SHA1 50 - ~password:"password" 51 - ~salt:"78578e5a5d63cb06" 52 - ~count:(-1) 53 - ~dk_len:16 31 + test_pbkdf1_invalid_arg ~hash:`SHA1 ~password:"password" 32 + ~salt:"78578e5a5d63cb06" ~count:(-1) ~dk_len:16 54 33 ~msg:"count must be a positive integer" 55 34 56 35 let pbkdf1_test5 = 57 - test_pbkdf1_invalid_arg 58 - ~hash:`SHA1 59 - ~password:"password" 60 - ~salt:"78578e5a5d63cb06" 61 - ~count:0 62 - ~dk_len:16 36 + test_pbkdf1_invalid_arg ~hash:`SHA1 ~password:"password" 37 + ~salt:"78578e5a5d63cb06" ~count:0 ~dk_len:16 63 38 ~msg:"count must be a positive integer" 64 39 65 40 let pbkdf1_test6 = 66 - test_pbkdf1_invalid_arg 67 - ~hash:`SHA1 68 - ~password:"password" 69 - ~salt:"78578e5a5d63cb06" 70 - ~count:1000 71 - ~dk_len:24 72 - ~msg:"derived key too long" 41 + test_pbkdf1_invalid_arg ~hash:`SHA1 ~password:"password" 42 + ~salt:"78578e5a5d63cb06" ~count:1000 ~dk_len:24 ~msg:"derived key too long" 73 43 74 44 let pbkdf1_test7 = 75 - test_pbkdf1_invalid_arg 76 - ~hash:`SHA1 77 - ~password:"password" 78 - ~salt:"78578e5a5d63cb06" 79 - ~count:1000 80 - ~dk_len:0 45 + test_pbkdf1_invalid_arg ~hash:`SHA1 ~password:"password" 46 + ~salt:"78578e5a5d63cb06" ~count:1000 ~dk_len:0 81 47 ~msg:"derived key length must be a positive integer" 82 48 83 - let pbkdf1_tests = [ 84 - "Test Case 1", `Quick, pbkdf1_test1; 85 - "Test Case 2", `Quick, pbkdf1_test2; 86 - "Test Case 3", `Quick, pbkdf1_test3; 87 - "Test Case 4", `Quick, pbkdf1_test4; 88 - "Test Case 5", `Quick, pbkdf1_test5; 89 - "Test Case 6", `Quick, pbkdf1_test6; 90 - "Test Case 7", `Quick, pbkdf1_test7; 91 - ] 92 - 49 + let pbkdf1_tests = 50 + [ 51 + ("Test Case 1", `Quick, pbkdf1_test1); 52 + ("Test Case 2", `Quick, pbkdf1_test2); 53 + ("Test Case 3", `Quick, pbkdf1_test3); 54 + ("Test Case 4", `Quick, pbkdf1_test4); 55 + ("Test Case 5", `Quick, pbkdf1_test5); 56 + ("Test Case 6", `Quick, pbkdf1_test6); 57 + ("Test Case 7", `Quick, pbkdf1_test7); 58 + ] 93 59 94 60 (* PBKDF2 *) 95 61 let test_pbkdf2 ~prf ~password ~salt ~count ~dk_len ~dk = 96 - let salt = Ohex.decode salt 97 - and dk = Ohex.decode dk in 98 - (fun () -> 99 - let edk = Pbkdf.pbkdf2 ~prf ~password ~salt ~count ~dk_len in 100 - Alcotest.check Alcotest.string "PBKDF2 test" edk dk) 62 + let salt = Ohex.decode salt and dk = Ohex.decode dk in 63 + fun () -> 64 + let edk = Pbkdf.pbkdf2 ~prf ~password ~salt ~count ~dk_len in 65 + Alcotest.check Alcotest.string "PBKDF2 test" edk dk 101 66 102 67 let test_pbkdf2_invalid_arg ~prf ~password ~salt ~count ~dk_len ~msg () = 103 68 let salt = Ohex.decode salt in 104 - Alcotest.check_raises 105 - msg 106 - (Invalid_argument msg) 107 - (fun () -> ignore (Pbkdf.pbkdf2 ~prf ~password ~salt ~count ~dk_len)) 69 + Alcotest.check_raises msg (Invalid_argument msg) (fun () -> 70 + ignore (Pbkdf.pbkdf2 ~prf ~password ~salt ~count ~dk_len)) 108 71 109 72 (* Taken from https://github.com/randombit/botan/blob/master/src/tests/data/pbkdf/pbkdf2.vec *) 110 73 let pbkdf2_test1 = 111 - test_pbkdf2 112 - ~prf:`SHA1 113 - ~password:"" 114 - ~salt:"0001020304050607" 115 - ~count:10000 74 + test_pbkdf2 ~prf:`SHA1 ~password:"" ~salt:"0001020304050607" ~count:10000 116 75 ~dk_len:32l 117 76 ~dk:"59b2b1143b4cb1059ec58d9722fb1c72471e0d85c6f7543ba5228526375b0127" 118 77 119 78 let pbkdf2_test2 = 120 - test_pbkdf2 121 - ~prf:`SHA1 122 - ~password:"jyueqgxrscgglpxdykcf" 123 - ~salt:"9b56e55328a4c97a250738f8dba1b992e8a1b508" 124 - ~count:10000 125 - ~dk_len:14l 79 + test_pbkdf2 ~prf:`SHA1 ~password:"jyueqgxrscgglpxdykcf" 80 + ~salt:"9b56e55328a4c97a250738f8dba1b992e8a1b508" ~count:10000 ~dk_len:14l 126 81 ~dk:"df6d9d72872404bf73e708cf3b7d" 127 82 128 83 let pbkdf2_test3 = 129 - test_pbkdf2 130 - ~prf:`SHA1 131 - ~password:"aqrqsznzvvzgtksammgo" 132 - ~salt:"57487813cdd2220dfc485d932a2979ee8769ea8b" 133 - ~count:101 134 - ~dk_len:40l 135 - ~dk:"fa13f40af1ade2a30f2fffd66fc8a659ef95e6388c1682fc0fe4d15a70109517a32942e39c371440" 84 + test_pbkdf2 ~prf:`SHA1 ~password:"aqrqsznzvvzgtksammgo" 85 + ~salt:"57487813cdd2220dfc485d932a2979ee8769ea8b" ~count:101 ~dk_len:40l 86 + ~dk: 87 + "fa13f40af1ade2a30f2fffd66fc8a659ef95e6388c1682fc0fe4d15a70109517a32942e39c371440" 136 88 137 89 let pbkdf2_test4 = 138 - test_pbkdf2 139 - ~prf:`SHA1 140 - ~password:"ltexmfeyylmlbrsyikaw" 141 - ~salt:"ed1f39a0a7f3889aaf7e60743b3bc1cc2c738e60" 142 - ~count:1000 143 - ~dk_len:10l 90 + test_pbkdf2 ~prf:`SHA1 ~password:"ltexmfeyylmlbrsyikaw" 91 + ~salt:"ed1f39a0a7f3889aaf7e60743b3bc1cc2c738e60" ~count:1000 ~dk_len:10l 144 92 ~dk:"027afadd48f4be8dcc4f" 145 93 146 94 let pbkdf2_test5 = 147 - test_pbkdf2 148 - ~prf:`SHA1 149 - ~password:"cxgnyrcgrvllylolsjpo" 150 - ~salt:"94ac88200743fb0f6ac51be62166cbef08d94c15" 151 - ~count:1 152 - ~dk_len:32l 95 + test_pbkdf2 ~prf:`SHA1 ~password:"cxgnyrcgrvllylolsjpo" 96 + ~salt:"94ac88200743fb0f6ac51be62166cbef08d94c15" ~count:1 ~dk_len:32l 153 97 ~dk:"7c0d009fc91b48cb6d19bafbfccff3e2ccabfe725eaa234e56bde1d551c132f2" 154 98 155 99 let pbkdf2_test6 = 156 - test_pbkdf2 157 - ~prf:`SHA1 158 - ~password:"xqyfhrxehiedlhewnvbj" 159 - ~salt:"24a1a50b17d63ee8394b69fc70887f4f94883d68" 160 - ~count:5 161 - ~dk_len:32l 100 + test_pbkdf2 ~prf:`SHA1 ~password:"xqyfhrxehiedlhewnvbj" 101 + ~salt:"24a1a50b17d63ee8394b69fc70887f4f94883d68" ~count:5 ~dk_len:32l 162 102 ~dk:"4661301d3517ca4443a6a607b32b2a63f69996299df75db75f1e0b98dd0eb7d8" 163 103 164 104 let pbkdf2_test7 = 165 - test_pbkdf2 166 - ~prf:`SHA1 167 - ~password:"andaqkpjwabvcfnpnjkl" 168 - ~salt:"9316c80801623cc2734af74bec42cf4dbaa3f6d5" 169 - ~count:100 170 - ~dk_len:30l 105 + test_pbkdf2 ~prf:`SHA1 ~password:"andaqkpjwabvcfnpnjkl" 106 + ~salt:"9316c80801623cc2734af74bec42cf4dbaa3f6d5" ~count:100 ~dk_len:30l 171 107 ~dk:"82fb44a521448d5aac94b5158ead1e4dcd7363081a747b9f7626752bda2d" 172 108 173 109 let pbkdf2_test8 = 174 - test_pbkdf2 175 - ~prf:`SHA1 176 - ~password:"hsavvyvocloyuztlsniu" 177 - ~salt:"612cc61df3cf2bdb36e10c4d8c9d73192bddee05" 178 - ~count:100 179 - ~dk_len:30l 110 + test_pbkdf2 ~prf:`SHA1 ~password:"hsavvyvocloyuztlsniu" 111 + ~salt:"612cc61df3cf2bdb36e10c4d8c9d73192bddee05" ~count:100 ~dk_len:30l 180 112 ~dk:"f8ec2b0ac817896ac8189d787c6424ed24a6d881436687a4629802c0ecce" 181 113 182 114 let pbkdf2_test9 = 183 - test_pbkdf2 184 - ~prf:`SHA1 185 - ~password:"eaimrbzpcopbusaqtkmw" 186 - ~salt:"45248f9d0cebcb86a18243e76c972a1f3b36772a" 187 - ~count:100 188 - ~dk_len:34l 115 + test_pbkdf2 ~prf:`SHA1 ~password:"eaimrbzpcopbusaqtkmw" 116 + ~salt:"45248f9d0cebcb86a18243e76c972a1f3b36772a" ~count:100 ~dk_len:34l 189 117 ~dk:"c9a0b2622f13916036e29e7462e206e8ba5b50ce9212752eb8ea2a4aa7b40a4cc1bf" 190 118 191 119 let pbkdf2_test10 = 192 - test_pbkdf2 193 - ~prf:`SHA1 194 - ~password:"gwrxpqxumsdsmbmhfhmfdcvlcvngzkig" 120 + test_pbkdf2 ~prf:`SHA1 ~password:"gwrxpqxumsdsmbmhfhmfdcvlcvngzkig" 195 121 ~salt:"a39b76c6eec8374a11493ad08c246a3e40dfae5064f4ee3489c273646178" 196 - ~count:1000 197 - ~dk_len:64l 198 - ~dk:"4c9db7ba24955225d5b845f65ef24ef1b0c6e86f2e39c8ddaa4b8abd26082d1f350381fadeaeb560dc447afc68a6b47e6ea1e7412f6cf7b2d82342fccd11d3b4" 122 + ~count:1000 ~dk_len:64l 123 + ~dk: 124 + "4c9db7ba24955225d5b845f65ef24ef1b0c6e86f2e39c8ddaa4b8abd26082d1f350381fadeaeb560dc447afc68a6b47e6ea1e7412f6cf7b2d82342fccd11d3b4" 199 125 200 126 let pbkdf2_test11 = 201 - test_pbkdf2 202 - ~prf:`SHA256 203 - ~password:"xyz" 204 - ~salt:"0001020304050607" 205 - ~count: 10000 127 + test_pbkdf2 ~prf:`SHA256 ~password:"xyz" ~salt:"0001020304050607" ~count:10000 206 128 ~dk_len:48l 207 - ~dk:"defd2987fa26a4672f4d16d98398432ad95e896bf619f6a6b8d4ed1faf98e8b531b39ffb66966d0e115a6cd8e70b72d0" 129 + ~dk: 130 + "defd2987fa26a4672f4d16d98398432ad95e896bf619f6a6b8d4ed1faf98e8b531b39ffb66966d0e115a6cd8e70b72d0" 208 131 209 132 let pbkdf2_test12 = 210 - test_pbkdf2 211 - ~prf:`SHA384 212 - ~password:"xyz" 213 - ~salt:"0001020304050607" 214 - ~count:10000 133 + test_pbkdf2 ~prf:`SHA384 ~password:"xyz" ~salt:"0001020304050607" ~count:10000 215 134 ~dk_len:48l 216 - ~dk:"47a3ae920b24edaa2bb53155808554b13fab58df62b81f043d9812e9f2881164df20bbffa54e5ee2489fa183b6718a74" 135 + ~dk: 136 + "47a3ae920b24edaa2bb53155808554b13fab58df62b81f043d9812e9f2881164df20bbffa54e5ee2489fa183b6718a74" 217 137 218 138 let pbkdf2_test13 = 219 - test_pbkdf2 220 - ~prf:`SHA512 221 - ~password:"xyz" 222 - ~salt:"0001020304050607" 223 - ~count:10000 139 + test_pbkdf2 ~prf:`SHA512 ~password:"xyz" ~salt:"0001020304050607" ~count:10000 224 140 ~dk_len:48l 225 - ~dk:"daf8a734327745eb63d19054dbd4018a682cef11086a1bfb63fdbc16158c2f8b0742802f36aef1b1df92accbea5d31a5" 141 + ~dk: 142 + "daf8a734327745eb63d19054dbd4018a682cef11086a1bfb63fdbc16158c2f8b0742802f36aef1b1df92accbea5d31a5" 226 143 227 144 let pbkdf2_test14 = 228 - test_pbkdf2_invalid_arg 229 - ~prf:`SHA1 230 - ~password:"password" 231 - ~salt:"0001020304050607" 232 - ~count:(-1) 233 - ~dk_len:48l 145 + test_pbkdf2_invalid_arg ~prf:`SHA1 ~password:"password" 146 + ~salt:"0001020304050607" ~count:(-1) ~dk_len:48l 234 147 ~msg:"count must be a positive integer" 235 148 236 149 let pbkdf2_test15 = 237 - test_pbkdf2_invalid_arg 238 - ~prf:`SHA1 239 - ~password:"password" 240 - ~salt:"0001020304050607" 241 - ~count:0 242 - ~dk_len:48l 150 + test_pbkdf2_invalid_arg ~prf:`SHA1 ~password:"password" 151 + ~salt:"0001020304050607" ~count:0 ~dk_len:48l 243 152 ~msg:"count must be a positive integer" 244 153 245 154 let pbkdf2_test16 = 246 - test_pbkdf2_invalid_arg 247 - ~prf:`SHA1 248 - ~password:"password" 249 - ~salt:"0001020304050607" 250 - ~count:1000 251 - ~dk_len:(-1l) 155 + test_pbkdf2_invalid_arg ~prf:`SHA1 ~password:"password" 156 + ~salt:"0001020304050607" ~count:1000 ~dk_len:(-1l) 252 157 ~msg:"derived key length must be a positive integer" 253 158 254 159 let pbkdf2_test17 = 255 - test_pbkdf2_invalid_arg 256 - ~prf:`SHA1 257 - ~password:"password" 258 - ~salt:"0001020304050607" 259 - ~count:1000 260 - ~dk_len:0l 160 + test_pbkdf2_invalid_arg ~prf:`SHA1 ~password:"password" 161 + ~salt:"0001020304050607" ~count:1000 ~dk_len:0l 261 162 ~msg:"derived key length must be a positive integer" 262 163 263 - let pbkdf2_tests = [ 264 - "Test Case 1", `Quick, pbkdf2_test1; 265 - "Test Case 2", `Quick, pbkdf2_test2; 266 - "Test Case 3", `Quick, pbkdf2_test3; 267 - "Test Case 4", `Quick, pbkdf2_test4; 268 - "Test Case 5", `Quick, pbkdf2_test5; 269 - "Test Case 6", `Quick, pbkdf2_test6; 270 - "Test Case 7", `Quick, pbkdf2_test7; 271 - "Test Case 8", `Quick, pbkdf2_test8; 272 - "Test Case 9", `Quick, pbkdf2_test9; 273 - "Test Case 10", `Quick, pbkdf2_test10; 274 - "Test Case 11", `Quick, pbkdf2_test11; 275 - "Test Case 12", `Quick, pbkdf2_test12; 276 - "Test Case 13", `Quick, pbkdf2_test13; 277 - "Test Case 14", `Quick, pbkdf2_test14; 278 - "Test Case 15", `Quick, pbkdf2_test15; 279 - "Test Case 16", `Quick, pbkdf2_test16; 280 - "Test Case 17", `Quick, pbkdf2_test17; 281 - ] 164 + let pbkdf2_tests = 165 + [ 166 + ("Test Case 1", `Quick, pbkdf2_test1); 167 + ("Test Case 2", `Quick, pbkdf2_test2); 168 + ("Test Case 3", `Quick, pbkdf2_test3); 169 + ("Test Case 4", `Quick, pbkdf2_test4); 170 + ("Test Case 5", `Quick, pbkdf2_test5); 171 + ("Test Case 6", `Quick, pbkdf2_test6); 172 + ("Test Case 7", `Quick, pbkdf2_test7); 173 + ("Test Case 8", `Quick, pbkdf2_test8); 174 + ("Test Case 9", `Quick, pbkdf2_test9); 175 + ("Test Case 10", `Quick, pbkdf2_test10); 176 + ("Test Case 11", `Quick, pbkdf2_test11); 177 + ("Test Case 12", `Quick, pbkdf2_test12); 178 + ("Test Case 13", `Quick, pbkdf2_test13); 179 + ("Test Case 14", `Quick, pbkdf2_test14); 180 + ("Test Case 15", `Quick, pbkdf2_test15); 181 + ("Test Case 16", `Quick, pbkdf2_test16); 182 + ("Test Case 17", `Quick, pbkdf2_test17); 183 + ] 282 184 283 185 let () = 284 - Alcotest.run "PBKDF Tests" [ 285 - "PBKDF1 tests", pbkdf1_tests; 286 - "PBKDF2 tests", pbkdf2_tests; 287 - ] 186 + Alcotest.run "PBKDF Tests" 187 + [ ("PBKDF1 tests", pbkdf1_tests); ("PBKDF2 tests", pbkdf2_tests) ]
+5 -2
scrypt/dune
··· 3 3 (public_name kdf.scrypt) 4 4 (modules scrypt) 5 5 (libraries crypto kdf.pbkdf) 6 - (c_names salsa-core) 7 - (c_flags (:standard --std=c99 -Wall -Wextra -O3))) 6 + (foreign_stubs 7 + (language c) 8 + (names salsa-core) 9 + (flags 10 + (:standard --std=c99 -Wall -Wextra -O3))))
+23 -17
scrypt/scrypt.ml
··· 1 - external salsa_core : int -> string -> bytes -> unit = "caml_salsa_core" [@@noalloc] 1 + external salsa_core : int -> string -> bytes -> unit = "caml_salsa_core" 2 + [@@noalloc] 2 3 3 4 let salsa20_core count i = 4 5 let l = 64 in ··· 8 9 salsa_core count i o; 9 10 Bytes.unsafe_to_string o 10 11 11 - let salsa20_8_core i = 12 - salsa20_core 4 i 12 + let salsa20_8_core i = salsa20_core 4 i 13 13 14 14 let scrypt_block_mix b r = 15 15 let b' = Bytes.create (String.length b) in 16 16 let x = Bytes.create 64 in 17 - Bytes.unsafe_blit_string b ((2 * r - 1) * 64) x 0 64; 18 - for i = 0 to 2 * r - 1 do 17 + Bytes.unsafe_blit_string b (((2 * r) - 1) * 64) x 0 64; 18 + for i = 0 to (2 * r) - 1 do 19 19 let b_i = Bytes.unsafe_of_string (String.sub b (i * 64) 64) in 20 - Crypto.Uncommon.unsafe_xor_into (Bytes.unsafe_to_string x) ~src_off:0 b_i ~dst_off:0 64; 21 - Bytes.unsafe_blit_string (salsa20_8_core (Bytes.unsafe_to_string b_i)) 0 x 0 64; 22 - let offset = (i mod 2) lsl (max 0 (r / 2 - 1)) + i / 2 in 20 + Crypto.Uncommon.unsafe_xor_into (Bytes.unsafe_to_string x) ~src_off:0 b_i 21 + ~dst_off:0 64; 22 + Bytes.unsafe_blit_string 23 + (salsa20_8_core (Bytes.unsafe_to_string b_i)) 24 + 0 x 0 64; 25 + let offset = ((i mod 2) lsl max 0 ((r / 2) - 1)) + (i / 2) in 23 26 Bytes.blit x 0 b' (offset * 64) 64 24 27 done; 25 28 b' ··· 34 37 done; 35 38 for _ = 0 to n - 1 do 36 39 let integerify x = 37 - let k = Bytes.get_int32_le x (128 * r - 64) in 40 + let k = Bytes.get_int32_le x ((128 * r) - 64) in 38 41 let n' = n - 1 in 39 42 Int32.(to_int (logand k (of_int n'))) 40 43 in 41 44 let j = integerify !x in 42 - Crypto.Uncommon.unsafe_xor_into (Bytes.unsafe_to_string v) ~src_off:(blen * j) !x ~dst_off:0 blen; 43 - x := scrypt_block_mix (Bytes.unsafe_to_string !x) r; 45 + Crypto.Uncommon.unsafe_xor_into (Bytes.unsafe_to_string v) 46 + ~src_off:(blen * j) !x ~dst_off:0 blen; 47 + x := scrypt_block_mix (Bytes.unsafe_to_string !x) r 44 48 done; 45 49 !x 46 50 47 51 let scrypt ~password ~salt ~n ~r ~p ~dk_len = 48 - let is_power_of_2 x = (x land (x - 1)) = 0 in 52 + let is_power_of_2 x = x land (x - 1) = 0 in 49 53 if n <= 1 then invalid_arg "n must be larger than 1" 50 54 else if not (is_power_of_2 n) then invalid_arg "n must be a power of 2" 51 55 else if p <= 0 then invalid_arg "p must be a positive integer" 52 - else if p > (Int64.to_int (Int64.div 0xffffffffL 4L) / r) then invalid_arg "p too big" 53 - else if dk_len <= 0l then invalid_arg "derived key length must be a positive integer"; 56 + else if p > Int64.to_int (Int64.div 0xffffffffL 4L) / r then 57 + invalid_arg "p too big" 58 + else if dk_len <= 0l then 59 + invalid_arg "derived key length must be a positive integer"; 54 60 let rec partition b blocks = function 55 61 | 0 -> blocks 56 62 | i -> 57 - let off = (i - 1) * r * 128 in 58 - let block = Bytes.unsafe_of_string (String.sub b off (r * 128)) in 59 - partition b (block :: blocks) (i - 1) 63 + let off = (i - 1) * r * 128 in 64 + let block = Bytes.unsafe_of_string (String.sub b off (r * 128)) in 65 + partition b (block :: blocks) (i - 1) 60 66 in 61 67 let blen = Int32.of_int (128 * r * p) in 62 68 let dk = Pbkdf.pbkdf2 ~prf:`SHA256 ~password ~salt ~count:1 ~dk_len:blen in
+18 -14
scrypt/scrypt.mli
··· 1 - (** {{:https://tools.ietf.org/html/rfc7914} 2 - The scrypt Password-Based Key Derivation Function} 3 - specifies the password-based key derivation function scrypt. The 4 - function derives one or more secret keys from a secret string. 5 - It is based on memory-hard functions which offer added protection 6 - against attacks using custom hardware. *) 1 + (** {{:https://tools.ietf.org/html/rfc7914} The scrypt Password-Based Key 2 + Derivation Function} specifies the password-based key derivation function 3 + scrypt. The function derives one or more secret keys from a secret string. 4 + It is based on memory-hard functions which offer added protection against 5 + attacks using custom hardware. *) 7 6 8 - (** [scrypt_kdf password salt n r p dk_len] is [dk], the derived key 9 - of [dk_len] octets. 10 - [n], the cost parameter, must be larger than 1 and a power of 2. 11 - [p], the parallelization parameter, must be a possitive integer 12 - and less than or equal to 2^32 - 1 / (4 * r) 13 - @raise Invalid_argument when either [n], [p] or [dk_len] are not 14 - valid *) 15 - val scrypt : password:string -> salt:string -> n:int -> r:int -> p:int -> dk_len:int32 -> string 7 + val scrypt : 8 + password:string -> 9 + salt:string -> 10 + n:int -> 11 + r:int -> 12 + p:int -> 13 + dk_len:int32 -> 14 + string 15 + (** [scrypt_kdf password salt n r p dk_len] is [dk], the derived key of [dk_len] 16 + octets. [n], the cost parameter, must be larger than 1 and a power of 2. 17 + [p], the parallelization parameter, must be a possitive integer and less 18 + than or equal to 2^32 - 1 / (4 * r) 19 + @raise Invalid_argument when either [n], [p] or [dk_len] are not valid *)
+30 -47
scrypt/tests/scrypt_kdf_tests.ml
··· 1 1 let test_scrypt_kdf ~password ~salt ~n ~r ~p ~dk_len ~dk = 2 2 let dk = Ohex.decode dk in 3 - (fun () -> 4 - let edk = Scrypt.scrypt ~password ~salt ~n ~r ~p ~dk_len in 5 - Alcotest.check Alcotest.string "Scrypt test" edk dk) 3 + fun () -> 4 + let edk = Scrypt.scrypt ~password ~salt ~n ~r ~p ~dk_len in 5 + Alcotest.check Alcotest.string "Scrypt test" edk dk 6 6 7 7 let scrypt_kdf_test1 = 8 - test_scrypt_kdf 9 - ~password:"" 10 - ~salt:"" 11 - ~n:16 12 - ~r:1 13 - ~p:1 14 - ~dk_len:64l 15 - ~dk:"77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906" 8 + test_scrypt_kdf ~password:"" ~salt:"" ~n:16 ~r:1 ~p:1 ~dk_len:64l 9 + ~dk: 10 + "77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906" 16 11 17 12 let scrypt_kdf_test2 = 18 - test_scrypt_kdf 19 - ~password:"password" 20 - ~salt:"NaCl" 21 - ~n:1024 22 - ~r:8 23 - ~p:16 13 + test_scrypt_kdf ~password:"password" ~salt:"NaCl" ~n:1024 ~r:8 ~p:16 24 14 ~dk_len:64l 25 - ~dk:"fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640" 15 + ~dk: 16 + "fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640" 26 17 27 18 let scrypt_kdf_test3 = 28 - test_scrypt_kdf 29 - ~password:"pleaseletmein" 30 - ~salt:"SodiumChloride" 31 - ~n:16384 32 - ~r:8 33 - ~p:1 34 - ~dk_len:64l 35 - ~dk:"7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887" 19 + test_scrypt_kdf ~password:"pleaseletmein" ~salt:"SodiumChloride" ~n:16384 ~r:8 20 + ~p:1 ~dk_len:64l 21 + ~dk: 22 + "7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887" 36 23 37 24 let scrypt_kdf_test4 = 38 - test_scrypt_kdf 39 - ~password:"pleaseletmein" 40 - ~salt:"SodiumChloride" 41 - ~n:1048576 42 - ~r:8 43 - ~p:1 44 - ~dk_len:64l 45 - ~dk:"2101cb9b6a511aaeaddbbe09cf70f881ec568d574a2ffd4dabe5ee9820adaa478e56fd8f4ba5d09ffa1c6d927c40f4c337304049e8a952fbcbf45c6fa77a41a4" 25 + test_scrypt_kdf ~password:"pleaseletmein" ~salt:"SodiumChloride" ~n:1048576 26 + ~r:8 ~p:1 ~dk_len:64l 27 + ~dk: 28 + "2101cb9b6a511aaeaddbbe09cf70f881ec568d574a2ffd4dabe5ee9820adaa478e56fd8f4ba5d09ffa1c6d927c40f4c337304049e8a952fbcbf45c6fa77a41a4" 46 29 47 30 let scrypt_kdf_tests () = 48 - let tests = [ 49 - "Test Case 1", `Quick, scrypt_kdf_test1; 50 - "Test Case 2", `Quick, scrypt_kdf_test2; 51 - ] in 31 + let tests = 32 + [ 33 + ("Test Case 1", `Quick, scrypt_kdf_test1); 34 + ("Test Case 2", `Quick, scrypt_kdf_test2); 35 + ] 36 + in 52 37 (* Skip test case 3 and 4 for architectures with 31 bit sizes or less, as it requires a buffer larger than Int.max_size in those cases *) 53 - if Sys.int_size <= 31 then 38 + if Sys.int_size <= 31 then tests 39 + else 54 40 tests 55 - else 56 - tests @ [ 57 - "Test Case 3", `Quick, scrypt_kdf_test3; 58 - "Test Case 4", `Slow, scrypt_kdf_test4; 59 - ] 41 + @ [ 42 + ("Test Case 3", `Quick, scrypt_kdf_test3); 43 + ("Test Case 4", `Slow, scrypt_kdf_test4); 44 + ] 60 45 61 46 let () = 62 - Alcotest.run "Scrypt kdf Tests" [ 63 - "Scrypt kdf tests", scrypt_kdf_tests (); 64 - ] 47 + Alcotest.run "Scrypt kdf Tests" [ ("Scrypt kdf tests", scrypt_kdf_tests ()) ]