├── .gitignore ├── .travis.yml ├── CHANGES.md ├── LICENSE.md ├── README.md ├── draft-josefsson-scrypt-kdf-04.txt ├── dune ├── dune-project ├── scrypt-kdf.opam ├── scrypt_kdf.ml ├── scrypt_kdf.mli └── scrypt_kdf_tests.ml /.gitignore: -------------------------------------------------------------------------------- 1 | *.annot 2 | *.cmo 3 | *.cma 4 | *.cmi 5 | *.a 6 | *.o 7 | *.cmx 8 | *.cmxs 9 | *.cmxa 10 | *byte 11 | *native 12 | _build 13 | _tests 14 | scrypt-kdf.install -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | install: wget https://raw.githubusercontent.com/ocaml/ocaml-ci-scripts/master/.travis-docker.sh 3 | script: bash -ex .travis-docker.sh 4 | sudo: false 5 | services: 6 | - docker 7 | env: 8 | global: 9 | - PACKAGE="scrypt-kdf" 10 | - DISTRO=alpine 11 | - TESTS=true 12 | matrix: 13 | - OCAML_VERSION=4.07 14 | - OCAML_VERSION=4.08 15 | - OCAML_VERSION=4.09 16 | - OCAML_VERSION=4.10 17 | notifications: 18 | email: false 19 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | # Unreleased 2 | 3 | * Make the licenses name SPDX compatible (thanks to @kit-ty-kate) 4 | * Change dune subst from pinned to dev (thanks to @kit-ty-kate) 5 | * Disable a failing testcase for architectures with integers no longer than 31 bits (thanks to @kit-ty-kate) 6 | 7 | # 1.2.0 (2021-08-03) 8 | 9 | * Upgrade to Cstruct 6.0.0 10 | 11 | # 1.1.0 (2020-03-31) 12 | 13 | * Port to mirage-crypto (thanks to @hannesm) 14 | 15 | # 1.0.0 (2019-04-12) 16 | 17 | * Move to dune 18 | * Upgrade to opam 2.0 19 | 20 | # 0.4.0 (2017-03-09) 21 | 22 | * Removed Makefile, unneeded with topkg 23 | * Made pkg.ml executable 24 | * Added salsa20-core as a dependency and remove related code 25 | 26 | # 0.3.0 (2017-02-21) 27 | 28 | * Replaced underscores by dashes in library names 29 | * Exported Salsa20_core module 30 | 31 | # 0.2.0 (2016-10-31) 32 | 33 | * Added topkg dependency 34 | * Optimized inner loop in salsa_core to improve performance 35 | * Replaced custom clone function by Nocrypto's implementation 36 | 37 | # 0.1.0 (2016-03-18) 38 | 39 | * Initial release 40 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Alfredo Beaumont, Sonia Meruelo 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![docs](https://img.shields.io/badge/doc-online-blue.svg)](https://abeaumont.github.io/ocaml-scrypt-kdf) 2 | [![Build Status](https://travis-ci.org/abeaumont/ocaml-scrypt-kdf.svg?branch=master)](https://travis-ci.org/abeaumont/ocaml-scrypt-kdf) 3 | 4 | # The scrypt Password-Based Key Derivation Function 5 | 6 | A pure OCaml implementation of [scrypt](https://en.wikipedia.org/wiki/Scrypt) password based key derivation function, as defined in [The scrypt Password-Based Key Derivation Function internet draft](https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-04), including test cases from the RFC. 7 | -------------------------------------------------------------------------------- /draft-josefsson-scrypt-kdf-04.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Network Working Group C. Percival 6 | Internet-Draft Tarsnap 7 | Intended status: Informational S. Josefsson 8 | Expires: May 23, 2016 SJD AB 9 | November 20, 2015 10 | 11 | 12 | The scrypt Password-Based Key Derivation Function 13 | draft-josefsson-scrypt-kdf-04 14 | 15 | Abstract 16 | 17 | This document specifies the password-based key derivation function 18 | scrypt. The function derives one or more secret keys from a secret 19 | string. It is based on memory-hard functions which offer added 20 | protection against attacks using custom hardware. The document also 21 | provides an ASN.1 schema. 22 | 23 | Status of This Memo 24 | 25 | This Internet-Draft is submitted in full conformance with the 26 | provisions of BCP 78 and BCP 79. 27 | 28 | Internet-Drafts are working documents of the Internet Engineering 29 | Task Force (IETF). Note that other groups may also distribute 30 | working documents as Internet-Drafts. The list of current Internet- 31 | Drafts is at http://datatracker.ietf.org/drafts/current/. 32 | 33 | Internet-Drafts are draft documents valid for a maximum of six months 34 | and may be updated, replaced, or obsoleted by other documents at any 35 | time. It is inappropriate to use Internet-Drafts as reference 36 | material or to cite them other than as "work in progress." 37 | 38 | This Internet-Draft will expire on May 23, 2016. 39 | 40 | Copyright Notice 41 | 42 | Copyright (c) 2015 IETF Trust and the persons identified as the 43 | document authors. All rights reserved. 44 | 45 | This document is subject to BCP 78 and the IETF Trust's Legal 46 | Provisions Relating to IETF Documents 47 | (http://trustee.ietf.org/license-info) in effect on the date of 48 | publication of this document. Please review these documents 49 | carefully, as they describe your rights and restrictions with respect 50 | to this document. Code Components extracted from this document must 51 | include Simplified BSD License text as described in Section 4.e of 52 | 53 | 54 | 55 | 56 | Percival & Josefsson Expires May 23, 2016 [Page 1] 57 | 58 | Internet-Draft scrypt November 2015 59 | 60 | 61 | the Trust Legal Provisions and are provided without warranty as 62 | described in the Simplified BSD License. 63 | 64 | Table of Contents 65 | 66 | 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 2 67 | 2. Scrypt Parameters . . . . . . . . . . . . . . . . . . . . . . 3 68 | 3. The Salsa20/8 Core Function . . . . . . . . . . . . . . . . . 4 69 | 4. The scryptBlockMix Algorithm . . . . . . . . . . . . . . . . 4 70 | 5. The scryptROMix Algorithm . . . . . . . . . . . . . . . . . . 5 71 | 6. The scrypt Algorithm . . . . . . . . . . . . . . . . . . . . 6 72 | 7. ASN.1 Syntax . . . . . . . . . . . . . . . . . . . . . . . . 7 73 | 7.1. ASN.1 Module . . . . . . . . . . . . . . . . . . . . . . 8 74 | 8. Test Vectors for Salsa20/8 Core . . . . . . . . . . . . . . . 9 75 | 9. Test Vectors for scryptBlockMix . . . . . . . . . . . . . . . 9 76 | 10. Test Vectors for scryptROMix . . . . . . . . . . . . . . . . 10 77 | 11. Test Vectors for PBKDF2 with HMAC-SHA-256 . . . . . . . . . . 11 78 | 12. Test Vectors for scrypt . . . . . . . . . . . . . . . . . . . 11 79 | 13. Test Vectors for PKCS#8 . . . . . . . . . . . . . . . . . . . 12 80 | 14. Copying Conditions . . . . . . . . . . . . . . . . . . . . . 13 81 | 15. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . 13 82 | 16. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 13 83 | 17. Security Considerations . . . . . . . . . . . . . . . . . . . 13 84 | 18. References . . . . . . . . . . . . . . . . . . . . . . . . . 14 85 | 18.1. Normative References . . . . . . . . . . . . . . . . . . 14 86 | 18.2. Informative References . . . . . . . . . . . . . . . . . 14 87 | Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 15 88 | 89 | 1. Introduction 90 | 91 | Password-based key derivation functions are used in cryptography and 92 | security protocols for deriving one or more secret keys from a secret 93 | value. Over the years, several password-based key derivation 94 | functions have been used, including the original DES-based UNIX 95 | Crypt-function, FreeBSD MD5 crypt, PKCS#5 PBKDF2 [RFC2898] (typically 96 | used with SHA-1), GNU SHA-256/512 crypt [SHA2CRYPT], Windows NT LAN 97 | Manager (NTLM) [NTLM] hash, and the Blowfish-based bcrypt [BCRYPT]. 98 | These algorithms are all based on a cryptographic primitive combined 99 | with salting and/or iteration. The iteration count is used to slow 100 | down the computation, and the salt is used to make pre-computation 101 | costlier. 102 | 103 | All password-based key derivation functions mentioned above share the 104 | same weakness against powerful attackers. Providing that the number 105 | of iterations used is increased as computer systems get faster, this 106 | allows legitimate users to spend a constant amount of time on key 107 | derivation without losing ground to an attackers' ever-increasing 108 | computing power - as long as attackers are limited to the same 109 | 110 | 111 | 112 | Percival & Josefsson Expires May 23, 2016 [Page 2] 113 | 114 | Internet-Draft scrypt November 2015 115 | 116 | 117 | software implementations as legitimate users. While parallelized 118 | hardware implementations may not change the number of operations 119 | performed compared to software implementations, this does not prevent 120 | them from dramatically changing the asymptotic cost, since in many 121 | contexts - including the embarrassingly parallel task of performing a 122 | brute-force search for a passphrase - dollar-seconds are the most 123 | appropriate units for measuring the cost of a computation. As 124 | semiconductor technology develops, circuits do not merely become 125 | faster; they also become smaller, allowing for a larger amount of 126 | parallelism at the same cost. 127 | 128 | Consequently, existing key derivation algorithms, even when the 129 | iteration count is increased so that the time taken to verify a 130 | password remains constant, the cost of finding a password by using a 131 | brute force attack implemented in hardware drops each year. 132 | 133 | The scrypt function aims to reduce the advantage which attackers can 134 | gain by using custom-designed parallel circuits for breaking 135 | password-based key derivation functions. 136 | 137 | This document do not introduce scrypt for the first time. The 138 | original scrypt paper [SCRYPT] was published as a peer-reviewed 139 | scientific paper, and contains further background and discussions. 140 | 141 | The purpose of this document is to serve as a stable reference for 142 | IETF documents making use of scrypt. The rest of this document is 143 | divided into sections that each describe parameter choices and 144 | algorithm steps needed for the final "scrypt" algorithm. 145 | 146 | 2. Scrypt Parameters 147 | 148 | The scrypt function takes several parameters. The passphrase P is 149 | typically a human-chosen password. The salt is normally uniquely and 150 | randomly generated [RFC4086]. The parameter r ("blockSize") specify 151 | the block size. The CPU/Memory cost parameter N ("costParameter") 152 | must be larger than 1, a power of 2 and less than 2^(128 * r / 8). 153 | The parallelization parameter p ("parallelizationParameter"), a 154 | positive integer less than or equal to ((2^32-1) * 32) / (128 * r). 155 | The intended output length dkLen in octets of the derived key 156 | ("keyLength"); a positive integer less than or equal to (2^32 - 1) * 157 | 32. 158 | 159 | Users of scrypt can tune the parameters N, r, and p according to the 160 | amount of memory and computing power available, the latency-bandwidth 161 | product of the memory subsystem, and the amount of parallelism 162 | desired. At the current time, taking r=8 and p=1 appears to yield 163 | good results, but as memory latency and CPU parallelism increase it 164 | is likely that the optimum values for both r and p will increase. 165 | 166 | 167 | 168 | Percival & Josefsson Expires May 23, 2016 [Page 3] 169 | 170 | Internet-Draft scrypt November 2015 171 | 172 | 173 | Note also that since the computations of SMix are independent, a 174 | large value of p can be used to increase the computational cost of 175 | scrypt without increasing the memory usage; so we can expect scrypt 176 | to remain useful even if the growth rates of CPU power and memory 177 | capacity diverge. 178 | 179 | 3. The Salsa20/8 Core Function 180 | 181 | Salsa20/8 Core is a round-reduced variant of the Salsa20 Core. It is 182 | a hash function from 64-octet strings to 64-octet strings. Note that 183 | Salsa20/8 Core is not a cryptographic hash function since it is not 184 | collision-resistant. See section 8 of [SALSA20SPEC] for its 185 | specification, and [SALSA20CORE] for more information. The algorithm 186 | description, in C language, is included below as a stable reference, 187 | without endianness conversion and alignment. 188 | 189 | #define R(a,b) (((a) << (b)) | ((a) >> (32 - (b)))) 190 | void salsa20_word_specification(uint32 out[16],uint32 in[16]) 191 | { 192 | int i; 193 | uint32 x[16]; 194 | for (i = 0;i < 16;++i) x[i] = in[i]; 195 | for (i = 8;i > 0;i -= 2) { 196 | x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9); 197 | x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18); 198 | x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9); 199 | x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18); 200 | x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9); 201 | x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18); 202 | x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9); 203 | x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18); 204 | x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9); 205 | x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18); 206 | x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9); 207 | x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18); 208 | x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9); 209 | x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18); 210 | x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9); 211 | x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18); 212 | } 213 | for (i = 0;i < 16;++i) out[i] = x[i] + in[i]; 214 | } 215 | 216 | 4. The scryptBlockMix Algorithm 217 | 218 | The scryptBlockMix algorithm is the same as the BlockMix algorithm 219 | described in [SCRYPT] but with Salsa20/8 Core used as the hash 220 | 221 | 222 | 223 | 224 | Percival & Josefsson Expires May 23, 2016 [Page 4] 225 | 226 | Internet-Draft scrypt November 2015 227 | 228 | 229 | function H. Below, Salsa(T) corresponds to the Salsa20/8 Core 230 | function applied to the octet vector T. 231 | 232 | Algorithm scryptBlockMix 233 | 234 | Parameters: 235 | r Block size parameter. 236 | 237 | Input: 238 | B[0] || B[1] || ... || B[2 * r - 1] 239 | Input octet string (of size 128 * r octets), 240 | treated as 2 * r 64-octet blocks. 241 | 242 | Output: 243 | B'[0] || B'[1] || ... || B'[2 * r - 1] 244 | Output octet string. 245 | 246 | Steps: 247 | 248 | 1. X = B[2 * r - 1] 249 | 250 | 2. for i = 0 to 2 * r - 1 do 251 | T = X xor B[i] 252 | X = Salsa (T) 253 | Y[i] = X 254 | end for 255 | 256 | 3. B' = (Y[0], Y[2], ..., Y[2 * r - 2], 257 | Y[1], Y[3], ..., Y[2 * r - 1]) 258 | 259 | 5. The scryptROMix Algorithm 260 | 261 | The scryptROMix algorithm is the same as the ROMix algorithm 262 | described in [SCRYPT] but with scryptBlockMix used as the hash 263 | function H and the Integerify function explained inline. 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | Percival & Josefsson Expires May 23, 2016 [Page 5] 281 | 282 | Internet-Draft scrypt November 2015 283 | 284 | 285 | Algorithm scryptROMix 286 | 287 | Input: 288 | r Block size parameter. 289 | B Input octet vector of length 128 * r octets. 290 | N CPU/Memory cost parameter, must be larger than 1, 291 | a power of 2 and less than 2^(128 * r / 8). 292 | 293 | Output: 294 | B' Output octet vector of length 128 * r octets. 295 | 296 | Steps: 297 | 298 | 1. X = B 299 | 300 | 2. for i = 0 to N - 1 do 301 | V[i] = X 302 | X = scryptBlockMix (X) 303 | end for 304 | 305 | 3. for i = 0 to N - 1 do 306 | j = Integerify (X) mod N 307 | where Integerify (X) is defined as the result of 308 | interpreting the last four octets of X as a little- 309 | endian integer, i.e.: 310 | littleendian(X[128*r-4], X[128*r-3], 311 | X[128*r-2], X[128*r-1]) 312 | T = X xor V[j] 313 | X = scryptBlockMix (T) 314 | end for 315 | 316 | 4. B' = X 317 | 318 | 6. The scrypt Algorithm 319 | 320 | The PBKDF2-HMAC-SHA-256 function used below denote the PBKDF2 321 | algorithm [RFC2898] used with HMAC-SHA-256 [RFC6234] as the PRF. The 322 | HMAC-SHA-256 function generates 32 octet outputs. 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | Percival & Josefsson Expires May 23, 2016 [Page 6] 337 | 338 | Internet-Draft scrypt November 2015 339 | 340 | 341 | Algorithm scrypt 342 | 343 | Input: 344 | P Passphrase, an octet string. 345 | S Salt, an octet string. 346 | N CPU/Memory cost parameter, must be larger than 1, 347 | a power of 2 and less than 2^(128 * r / 8). 348 | r Block size parameter. 349 | p Parallelization parameter, a positive integer 350 | less than or equal to ((2^32-1) * hLen) / MFLen 351 | where hLen is 32 and MFlen is 128 * r. 352 | dkLen Intended output length in octets of the derived 353 | key; a positive integer less than or equal to 354 | (2^32 - 1) * hLen where hLen is 32. 355 | 356 | Output: 357 | DK Derived key, of length dkLen octets. 358 | 359 | Steps: 360 | 361 | 1. B[0] || B[1] || ... || B[p - 1] = 362 | PBKDF2-HMAC-SHA256 (P, S, 1, p * 128 * r) 363 | 364 | 2. for i = 0 to p - 1 do 365 | B[i] = scryptROMix (r, B[i], N) 366 | end for 367 | 368 | 3. DK = PBKDF2-HMAC-SHA256 (P, B[0] || B[1] || ... || B[p - 1], 369 | 1, dkLen) 370 | 371 | 7. ASN.1 Syntax 372 | 373 | This section defines ASN.1 syntax for the scrypt key derivation 374 | function. This is intended to operate on the same abstraction level 375 | as PKCS#5's PBKDF2. The OID id-scrypt below can be used where id- 376 | PBKDF2 is used, with scrypt-params corresponding to PBKDF2-params. 377 | The intended application of these definitions includes PKCS #8 and 378 | other syntax for key management. 379 | 380 | The object identifier id-scrypt identifies the scrypt key derivation 381 | function. 382 | 383 | id-scrypt OBJECT IDENTIFIER ::= {1 3 6 1 4 1 11591 4 11} 384 | 385 | The parameters field associated with this OID in an 386 | AlgorithmIdentifier shall have type scrypt-params: 387 | 388 | 389 | 390 | 391 | 392 | Percival & Josefsson Expires May 23, 2016 [Page 7] 393 | 394 | Internet-Draft scrypt November 2015 395 | 396 | 397 | scrypt-params ::= SEQUENCE { 398 | salt OCTET STRING, 399 | costParameter INTEGER (1..MAX), 400 | blockSize INTEGER (1..MAX), 401 | parallelizationParameter INTEGER (1..MAX), 402 | keyLength INTEGER (1..MAX) OPTIONAL } 403 | 404 | The fields of type scrypt-params have the following meanings: 405 | 406 | - salt specifies the salt value. It shall be an octet string. 407 | 408 | - costParameter specifies the CPU/Memory cost parameter N. 409 | 410 | - blockSize specifies the block size parameter r. 411 | 412 | - parallelizationParameter specifies the parallelization parameter. 413 | 414 | - keyLength, an optional field, is the length in octets of the 415 | derived key. The maximum key length allowed depends on the 416 | implementation; it is expected that implementation profiles may 417 | further constrain the bounds. This field only provides convenience; 418 | the key length is not cryptographically protected. 419 | 420 | To be usable in PKCS#8 [RFC5208] and Asymmetric Key Packages 421 | [RFC5958] the following extension of the PBES2-KDFs type is needed. 422 | 423 | PBES2-KDFs ALGORITHM-IDENTIFIER ::= 424 | { {scrypt-params IDENTIFIED BY id-scrypt}, ... } 425 | 426 | 7.1. ASN.1 Module 427 | 428 | For reference purposes, the ASN.1 syntax is presented as an ASN.1 429 | module here. 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | Percival & Josefsson Expires May 23, 2016 [Page 8] 449 | 450 | Internet-Draft scrypt November 2015 451 | 452 | 453 | -- scrypt ASN.1 Module 454 | 455 | scrypt-0 {1 3 6 1 4 1 11591 4 10} 456 | 457 | DEFINITIONS ::= BEGIN 458 | 459 | id-scrypt OBJECT IDENTIFIER ::= {1 3 6 1 4 1 11591 4 11} 460 | 461 | scrypt-params ::= SEQUENCE { 462 | salt OCTET STRING, 463 | costParameter INTEGER (1..MAX), 464 | blockSize INTEGER (1..MAX), 465 | parallelizationParameter INTEGER (1..MAX), 466 | keyLength INTEGER (1..MAX) OPTIONAL 467 | } 468 | 469 | PBES2-KDFs ALGORITHM-IDENTIFIER ::= 470 | { {scrypt-params IDENTIFIED BY id-scrypt}, ... } 471 | 472 | END 473 | 474 | 8. Test Vectors for Salsa20/8 Core 475 | 476 | Below is a sequence of octets to illustrate input and output values 477 | for the Salsa20/8 Core. The octets are hex encoded and whitespace is 478 | inserted for readability. The value corresponds to the first input 479 | and output pair generated by the first scrypt test vector below. 480 | 481 | INPUT: 482 | 7e 87 9a 21 4f 3e c9 86 7c a9 40 e6 41 71 8f 26 483 | ba ee 55 5b 8c 61 c1 b5 0d f8 46 11 6d cd 3b 1d 484 | ee 24 f3 19 df 9b 3d 85 14 12 1e 4b 5a c5 aa 32 485 | 76 02 1d 29 09 c7 48 29 ed eb c6 8d b8 b8 c2 5e 486 | 487 | OUTPUT: 488 | a4 1f 85 9c 66 08 cc 99 3b 81 ca cb 02 0c ef 05 489 | 04 4b 21 81 a2 fd 33 7d fd 7b 1c 63 96 68 2f 29 490 | b4 39 31 68 e3 c9 e6 bc fe 6b c5 b7 a0 6d 96 ba 491 | e4 24 cc 10 2c 91 74 5c 24 ad 67 3d c7 61 8f 81 492 | 493 | 9. Test Vectors for scryptBlockMix 494 | 495 | Below is a sequence of octets to illustrate input and output values 496 | for scryptBlockMix. The test vector uses an r value of 1. The 497 | octets are hex encoded and whitespace is inserted for readability. 498 | The value corresponds to the first input and output pair generated by 499 | the first scrypt test vector below. 500 | 501 | 502 | 503 | 504 | Percival & Josefsson Expires May 23, 2016 [Page 9] 505 | 506 | Internet-Draft scrypt November 2015 507 | 508 | 509 | INPUT 510 | B[0] = f7 ce 0b 65 3d 2d 72 a4 10 8c f5 ab e9 12 ff dd 511 | 77 76 16 db bb 27 a7 0e 82 04 f3 ae 2d 0f 6f ad 512 | 89 f6 8f 48 11 d1 e8 7b cc 3b d7 40 0a 9f fd 29 513 | 09 4f 01 84 63 95 74 f3 9a e5 a1 31 52 17 bc d7 514 | 515 | B[1] = 89 49 91 44 72 13 bb 22 6c 25 b5 4d a8 63 70 fb 516 | cd 98 43 80 37 46 66 bb 8f fc b5 bf 40 c2 54 b0 517 | 67 d2 7c 51 ce 4a d5 fe d8 29 c9 0b 50 5a 57 1b 518 | 7f 4d 1c ad 6a 52 3c da 77 0e 67 bc ea af 7e 89 519 | 520 | OUTPUT 521 | B'[0] = a4 1f 85 9c 66 08 cc 99 3b 81 ca cb 02 0c ef 05 522 | 04 4b 21 81 a2 fd 33 7d fd 7b 1c 63 96 68 2f 29 523 | b4 39 31 68 e3 c9 e6 bc fe 6b c5 b7 a0 6d 96 ba 524 | e4 24 cc 10 2c 91 74 5c 24 ad 67 3d c7 61 8f 81 525 | 526 | B'[1] = 20 ed c9 75 32 38 81 a8 05 40 f6 4c 16 2d cd 3c 527 | 21 07 7c fe 5f 8d 5f e2 b1 a4 16 8f 95 36 78 b7 528 | 7d 3b 3d 80 3b 60 e4 ab 92 09 96 e5 9b 4d 53 b6 529 | 5d 2a 22 58 77 d5 ed f5 84 2c b9 f1 4e ef e4 25 530 | 531 | 10. Test Vectors for scryptROMix 532 | 533 | Below is a sequence of octets to illustrate input and output values 534 | for scryptROMix. The test vector uses an r value of 1 and an N value 535 | of 16. The octets are hex encoded and whitespace is inserted for 536 | readability. The value corresponds to the first input and output 537 | pair generated by the first scrypt test vector below. 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | Percival & Josefsson Expires May 23, 2016 [Page 10] 561 | 562 | Internet-Draft scrypt November 2015 563 | 564 | 565 | INPUT: 566 | B = f7 ce 0b 65 3d 2d 72 a4 10 8c f5 ab e9 12 ff dd 567 | 77 76 16 db bb 27 a7 0e 82 04 f3 ae 2d 0f 6f ad 568 | 89 f6 8f 48 11 d1 e8 7b cc 3b d7 40 0a 9f fd 29 569 | 09 4f 01 84 63 95 74 f3 9a e5 a1 31 52 17 bc d7 570 | 89 49 91 44 72 13 bb 22 6c 25 b5 4d a8 63 70 fb 571 | cd 98 43 80 37 46 66 bb 8f fc b5 bf 40 c2 54 b0 572 | 67 d2 7c 51 ce 4a d5 fe d8 29 c9 0b 50 5a 57 1b 573 | 7f 4d 1c ad 6a 52 3c da 77 0e 67 bc ea af 7e 89 574 | 575 | OUTPUT: 576 | B = 79 cc c1 93 62 9d eb ca 04 7f 0b 70 60 4b f6 b6 577 | 2c e3 dd 4a 96 26 e3 55 fa fc 61 98 e6 ea 2b 46 578 | d5 84 13 67 3b 99 b0 29 d6 65 c3 57 60 1f b4 26 579 | a0 b2 f4 bb a2 00 ee 9f 0a 43 d1 9b 57 1a 9c 71 580 | ef 11 42 e6 5d 5a 26 6f dd ca 83 2c e5 9f aa 7c 581 | ac 0b 9c f1 be 2b ff ca 30 0d 01 ee 38 76 19 c4 582 | ae 12 fd 44 38 f2 03 a0 e4 e1 c4 7e c3 14 86 1f 583 | 4e 90 87 cb 33 39 6a 68 73 e8 f9 d2 53 9a 4b 8e 584 | 585 | 11. Test Vectors for PBKDF2 with HMAC-SHA-256 586 | 587 | Below is a sequence of octets illustring input and output values for 588 | PBKDF2-HMAC-SHA-256. The octets are hex encoded and whitespace is 589 | inserted for readability. The test vectors below can be used to 590 | verify the PBKDF2-HMAC-SHA-256 [RFC2898] function. The password and 591 | salt strings are passed as sequences of ASCII [RFC0020] octets. 592 | 593 | PBKDF2-HMAC-SHA-256 (P="passwd", S="salt", 594 | c=1, dkLen=64) = 595 | 55 ac 04 6e 56 e3 08 9f ec 16 91 c2 25 44 b6 05 596 | f9 41 85 21 6d de 04 65 e6 8b 9d 57 c2 0d ac bc 597 | 49 ca 9c cc f1 79 b6 45 99 16 64 b3 9d 77 ef 31 598 | 7c 71 b8 45 b1 e3 0b d5 09 11 20 41 d3 a1 97 83 599 | 600 | PBKDF2-HMAC-SHA-256 (P="Password", S="NaCl", 601 | c=80000, dkLen=64) = 602 | 4d dc d8 f6 0b 98 be 21 83 0c ee 5e f2 27 01 f9 603 | 64 1a 44 18 d0 4c 04 14 ae ff 08 87 6b 34 ab 56 604 | a1 d4 25 a1 22 58 33 54 9a db 84 1b 51 c9 b3 17 605 | 6a 27 2b de bb a1 d0 78 47 8f 62 b3 97 f3 3c 8d 606 | 607 | 12. Test Vectors for scrypt 608 | 609 | For reference purposes, we provide the following test vectors for 610 | scrypt, where the password and salt strings are passed as sequences 611 | of ASCII [RFC0020] octets. 612 | 613 | 614 | 615 | 616 | Percival & Josefsson Expires May 23, 2016 [Page 11] 617 | 618 | Internet-Draft scrypt November 2015 619 | 620 | 621 | The parameters to the scrypt function below are, in order, the 622 | password P (octet string), the salt S (octet string), the CPU/Memory 623 | cost parameter N, the block size parameter r, and the parallelization 624 | parameter p, and the output size dkLen. The output is hex encoded 625 | and whitespace is inserted for readability. 626 | 627 | scrypt (P="", S="", 628 | N=16, r=1, p=1, dklen=64) = 629 | 77 d6 57 62 38 65 7b 20 3b 19 ca 42 c1 8a 04 97 630 | f1 6b 48 44 e3 07 4a e8 df df fa 3f ed e2 14 42 631 | fc d0 06 9d ed 09 48 f8 32 6a 75 3a 0f c8 1f 17 632 | e8 d3 e0 fb 2e 0d 36 28 cf 35 e2 0c 38 d1 89 06 633 | 634 | scrypt (P="password", S="NaCl", 635 | N=1024, r=8, p=16, dkLen=64) = 636 | fd ba be 1c 9d 34 72 00 78 56 e7 19 0d 01 e9 fe 637 | 7c 6a d7 cb c8 23 78 30 e7 73 76 63 4b 37 31 62 638 | 2e af 30 d9 2e 22 a3 88 6f f1 09 27 9d 98 30 da 639 | c7 27 af b9 4a 83 ee 6d 83 60 cb df a2 cc 06 40 640 | 641 | scrypt (P="pleaseletmein", S="SodiumChloride", 642 | N=16384, r=8, p=1, dkLen=64) = 643 | 70 23 bd cb 3a fd 73 48 46 1c 06 cd 81 fd 38 eb 644 | fd a8 fb ba 90 4f 8e 3e a9 b5 43 f6 54 5d a1 f2 645 | d5 43 29 55 61 3f 0f cf 62 d4 97 05 24 2a 9a f9 646 | e6 1e 85 dc 0d 65 1e 40 df cf 01 7b 45 57 58 87 647 | 648 | scrypt (P="pleaseletmein", S="SodiumChloride", 649 | N=1048576, r=8, p=1, dkLen=64) = 650 | 21 01 cb 9b 6a 51 1a ae ad db be 09 cf 70 f8 81 651 | ec 56 8d 57 4a 2f fd 4d ab e5 ee 98 20 ad aa 47 652 | 8e 56 fd 8f 4b a5 d0 9f fa 1c 6d 92 7c 40 f4 c3 653 | 37 30 40 49 e8 a9 52 fb cb f4 5c 6f a7 7a 41 a4 654 | 655 | 13. Test Vectors for PKCS#8 656 | 657 | PKCS#8 [RFC5208] and Asymmetric Key Packages [RFC5958] encode 658 | encrypted private-keys. Using PBES2 with scrypt as the KDF, the 659 | following illustrates an example of a PKCS#8 encoded private-key. 660 | The password is "Rabbit" (without the quotes) with N=1048576, r=8 and 661 | p=1. The salt is "Mouse" and the encryption algorithm used is 662 | aes256-CBC. The derived key is: E2 77 EA 2C AC B2 3E DA-FC 03 9D 22 663 | 9B 79 DC 13 EC ED B6 01 D9 9B 18 2A-9F ED BA 1E 2B FB 4F 58. 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | Percival & Josefsson Expires May 23, 2016 [Page 12] 673 | 674 | Internet-Draft scrypt November 2015 675 | 676 | 677 | -----BEGIN ENCRYPTED PRIVATE KEY----- 678 | MIHiME0GCSqGSIb3DQEFDTBAMB8GCSsGAQQB2kcECzASBAVNb3VzZQIDEAAAAgEI 679 | AgEBMB0GCWCGSAFlAwQBKgQQyYmguHMsOwzGMPoyObk/JgSBkJb47EWd5iAqJlyy 680 | +ni5ftd6gZgOPaLQClL7mEZc2KQay0VhjZm/7MbBUNbqOAXNM6OGebXxVp6sHUAL 681 | iBGY/Dls7B1TsWeGObE0sS1MXEpuREuloZjcsNVcNXWPlLdZtkSH6uwWzR0PyG/Z 682 | +ZXfNodZtd/voKlvLOw5B3opGIFaLkbtLZQwMiGtl42AS89lZg== 683 | -----END ENCRYPTED PRIVATE KEY----- 684 | 685 | 14. Copying Conditions 686 | 687 | The authors agree to grant third parties the irrevocable right to 688 | copy, use and distribute this entire document or any portion of it, 689 | with or without modification, in any medium, without royalty, 690 | provided that, unless separate permission is granted, redistributed 691 | modified works do not contain misleading author, version, name of 692 | work, or endorsement information. 693 | 694 | 15. Acknowledgements 695 | 696 | Text in this document was borrowed from [SCRYPT] and [RFC2898]. The 697 | PKCS#8 test vector was provided by Stephen N. Henson. 698 | 699 | Feedback on this document were received from Dmitry Chestnykh, 700 | Alexander Klink, Rob Kendrick, Royce Williams Ted Rolle, Jr., Eitan 701 | Adler, Stephen Farrel, Nikos Mavrogiannopoulos, and Paul Kyzivat. 702 | 703 | 16. IANA Considerations 704 | 705 | None. 706 | 707 | 17. Security Considerations 708 | 709 | This document specifies a cryptographic algorithm, and there is 710 | always a risk that someone will find a weakness in it. By following 711 | the cryptographic research area you may learn of publications 712 | relevant to scrypt. 713 | 714 | ROMix has been proven sequential memory-hard under the Random Oracle 715 | model for the hash function. The security of scrypt relies on the 716 | assumption that BlockMix with Salsa20/8 Core does not exhibit any 717 | "shortcuts" which would allow it to be iterated more easily than a 718 | random oracle. For other claims about the security properties see 719 | [SCRYPT]. 720 | 721 | Passwords and other sensitive data, such as intermediate values, may 722 | continue to be stored in memory, core dumps, swap areas, etc, for a 723 | long time after the implementation has processed them. This makes 724 | attacks on the implementation easier. Thus, implementation should 725 | 726 | 727 | 728 | Percival & Josefsson Expires May 23, 2016 [Page 13] 729 | 730 | Internet-Draft scrypt November 2015 731 | 732 | 733 | consider storing sensitive data in protected memory areas. How to 734 | achieve this is system dependent. 735 | 736 | By nature and depending on parameters, running the scrypt algorithm 737 | may require large amounts of memory. Systems should protect against 738 | a denial of service attack resulting from attackers presenting 739 | unreasonably large parameters. 740 | 741 | Poor parameter choices can be harmful for security; for example, if 742 | you tune the parameters so that memory use is reduced to small 743 | amounts that will affect the properties of the algorithm. 744 | 745 | 18. References 746 | 747 | 18.1. Normative References 748 | 749 | [RFC2898] Kaliski, B., "PKCS #5: Password-Based Cryptography 750 | Specification Version 2.0", RFC 2898, September 2000. 751 | 752 | [RFC6234] Eastlake, D. and T. Hansen, "US Secure Hash Algorithms 753 | (SHA and SHA-based HMAC and HKDF)", RFC 6234, May 2011. 754 | 755 | 18.2. Informative References 756 | 757 | [RFC0020] Cerf, V., "ASCII format for network interchange", RFC 20, 758 | October 1969. 759 | 760 | [RFC5208] Kaliski, B., "Public-Key Cryptography Standards (PKCS) #8: 761 | Private-Key Information Syntax Specification Version 1.2", 762 | RFC 5208, May 2008. 763 | 764 | [RFC5958] Turner, S., "Asymmetric Key Packages", RFC 5958, August 765 | 2010. 766 | 767 | [RFC4086] Eastlake, D., Schiller, J., and S. Crocker, "Randomness 768 | Requirements for Security", BCP 106, RFC 4086, June 2005. 769 | 770 | [SALSA20SPEC] 771 | Bernstein, D., "Salsa20 specification", WWW 772 | http://cr.yp.to/snuffle/spec.pdf, April 2005. 773 | 774 | [SALSA20CORE] 775 | Bernstein, D., "The Salsa20 Core", WWW 776 | http://cr.yp.to/salsa20.html, March 2005. 777 | 778 | [SCRYPT] Percival, C., "Stronger key derivation via sequential 779 | memory-hard functions", BSDCan'09 780 | http://www.tarsnap.com/scrypt/scrypt.pdf, May 2009. 781 | 782 | 783 | 784 | Percival & Josefsson Expires May 23, 2016 [Page 14] 785 | 786 | Internet-Draft scrypt November 2015 787 | 788 | 789 | [BCRYPT] Provos, N. and D. Mazieres, "A Future-Adaptable Password 790 | Scheme", USENIX 1999 791 | https://www.usenix.org/legacy/event/usenix99/provos/ 792 | provos.pdf, June 1999. 793 | 794 | [NTLM] "[MS-NLMP]: NT LAN Manager (NTLM) Authentication 795 | Protocol", Microsoft https://msdn.microsoft.com/en- 796 | us/library/cc236621.aspx, 2015. 797 | 798 | [SHA2CRYPT] 799 | Drepper, U., "Unix crypt using SHA-256 and SHA-512", URL 800 | http://www.akkadia.org/drepper/SHA-crypt.txt, April 2008. 801 | 802 | Authors' Addresses 803 | 804 | Colin Percival 805 | Tarsnap 806 | 807 | Email: cperciva@tarsnap.com 808 | 809 | 810 | Simon Josefsson 811 | SJD AB 812 | 813 | Email: simon@josefsson.org 814 | URI: http://josefsson.org/ 815 | 816 | 817 | 818 | 819 | 820 | 821 | 822 | 823 | 824 | 825 | 826 | 827 | 828 | 829 | 830 | 831 | 832 | 833 | 834 | 835 | 836 | 837 | 838 | 839 | 840 | Percival & Josefsson Expires May 23, 2016 [Page 15] 841 | -------------------------------------------------------------------------------- /dune: -------------------------------------------------------------------------------- 1 | (library 2 | (name scrypt_kdf) 3 | (public_name scrypt-kdf) 4 | (modules scrypt_kdf) 5 | (libraries cstruct mirage-crypto pbkdf salsa20-core)) 6 | 7 | (test 8 | (name scrypt_kdf_tests) 9 | (modules scrypt_kdf_tests) 10 | (libraries scrypt-kdf alcotest)) 11 | -------------------------------------------------------------------------------- /dune-project: -------------------------------------------------------------------------------- 1 | (lang dune 1.8) 2 | (name scrypt-kdf) 3 | -------------------------------------------------------------------------------- /scrypt-kdf.opam: -------------------------------------------------------------------------------- 1 | opam-version: "2.0" 2 | synopsis: "The scrypt Password-Based Key Derivation Function" 3 | description: """ 4 | A pure OCaml implementation of [scrypt](https://en.wikipedia.org/wiki/Scrypt) password based key derivation function, 5 | as defined in [The scrypt Password-Based Key Derivation Function internet draft](https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-04), 6 | including test cases from the RFC. 7 | """ 8 | maintainer: ["Alfredo Beaumont "] 9 | authors: ["Alfredo Beaumont " "Sonia Meruelo "] 10 | license: "BSD-2-Clause" 11 | homepage: "https://github.com/abeaumont/ocaml-scrypt-kdf" 12 | bug-reports: "https://github.com/abeaumont/ocaml-scrypt-kdf/issues" 13 | dev-repo: "git+https://github.com/abeaumont/ocaml-scrypt-kdf.git" 14 | doc: "https://abeaumont.github.io/ocaml-scrypt-kdf/" 15 | depends: [ 16 | "ocaml" {>= "4.07.0"} 17 | "dune" {>= "1.8.0"} 18 | "cstruct" {>= "6.0.0"} 19 | "mirage-crypto" 20 | "pbkdf" {>= "0.1.0"} 21 | "salsa20-core" {>= "0.1.0"} 22 | "alcotest" {with-test} 23 | ] 24 | build: [ 25 | [ "dune" "subst" ] {dev} 26 | [ "dune" "build" "-j" jobs "-p" name "@install" ] 27 | [ "dune" "runtest" "-j" jobs "-p" name ] {with-test} 28 | ] 29 | -------------------------------------------------------------------------------- /scrypt_kdf.ml: -------------------------------------------------------------------------------- 1 | let scrypt_block_mix b r = 2 | let b' = Cstruct.create (Cstruct.length b) 3 | and x = ref (Cstruct.sub b ((2 * r - 1) * 64) 64) in 4 | for i = 0 to 2 * r - 1 do 5 | let b_i = Cstruct.sub b (i * 64) 64 in 6 | Mirage_crypto.Uncommon.Cs.xor_into !x b_i 64; 7 | x := Salsa20_core.salsa20_8_core b_i; 8 | let offset = (i mod 2) lsl (max 0 (r / 2 - 1)) + i / 2 in 9 | Cstruct.blit !x 0 b' (offset * 64) 64 10 | done; 11 | b' 12 | 13 | let scrypt_ro_mix b ~r ~n = 14 | let blen = r * 128 in 15 | let x = ref (Mirage_crypto.Uncommon.Cs.clone b) 16 | and v = Cstruct.create (blen * n) in 17 | for i = 0 to n - 1 do 18 | Cstruct.blit !x 0 v (blen * i) blen; 19 | x := scrypt_block_mix !x r 20 | done; 21 | for _ = 0 to n - 1 do 22 | let integerify x = 23 | let k = Cstruct.LE.get_uint32 x (128 * r - 64) in 24 | let n' = n - 1 in 25 | Int32.(to_int (logand k (of_int n'))) 26 | in 27 | let j = integerify !x in 28 | let v_j = Cstruct.sub v (blen * j) blen in 29 | Mirage_crypto.Uncommon.Cs.xor_into v_j !x blen; 30 | x := scrypt_block_mix !x r; 31 | done; 32 | !x 33 | 34 | let scrypt_kdf ~password ~salt ~n ~r ~p ~dk_len = 35 | let is_power_of_2 x = (x land (x - 1)) = 0 in 36 | if n <= 1 then invalid_arg "n must be larger than 1" 37 | else if not (is_power_of_2 n) then invalid_arg "n must be a power of 2" 38 | else if p <= 0 then invalid_arg "p must be a positive integer" 39 | else if p > (Int64.to_int (Int64.div 0xffffffffL 4L) / r) then invalid_arg "p too big" 40 | else if dk_len <= 0l then invalid_arg "derived key length must be a positive integer"; 41 | let rec partition b blocks = function 42 | 0 -> blocks 43 | | i -> 44 | let off = (i - 1) * r * 128 in 45 | let block = Cstruct.sub b off (r * 128) in 46 | partition b (block :: blocks) (i - 1) in 47 | let blen = Int32.of_int (128 * r * p) in 48 | let dk = Pbkdf.pbkdf2 ~prf:`SHA256 ~password ~salt ~count:1 ~dk_len:blen in 49 | let b = partition dk [] p in 50 | let b' = List.map (scrypt_ro_mix ~r ~n) b in 51 | let salt = Cstruct.concat b' in 52 | Pbkdf.pbkdf2 ~prf:`SHA256 ~password ~salt ~count:1 ~dk_len 53 | -------------------------------------------------------------------------------- /scrypt_kdf.mli: -------------------------------------------------------------------------------- 1 | (** {{:https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-04.txt} 2 | The scrypt Password-Based Key Derivation Function Internet Draft} 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. *) 7 | 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_kdf : password:Cstruct.t -> salt:Cstruct.t -> n:int -> r:int -> p:int -> dk_len:int32 -> Cstruct.t 16 | -------------------------------------------------------------------------------- /scrypt_kdf_tests.ml: -------------------------------------------------------------------------------- 1 | let test_scrypt_kdf ~password ~salt ~n ~r ~p ~dk_len ~dk = 2 | let open Cstruct in 3 | let password = of_string password 4 | and salt = of_string salt 5 | and dk = to_string (of_hex dk) in 6 | (fun () -> 7 | let edk = Scrypt_kdf.scrypt_kdf ~password ~salt ~n ~r ~p ~dk_len in 8 | let sedk = to_string edk in 9 | Alcotest.check Alcotest.string "Scrypt test" sedk dk) 10 | 11 | let scrypt_kdf_test1 = 12 | test_scrypt_kdf 13 | ~password:"" 14 | ~salt:"" 15 | ~n:16 16 | ~r:1 17 | ~p:1 18 | ~dk_len:64l 19 | ~dk:"77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906" 20 | 21 | let scrypt_kdf_test2 = 22 | test_scrypt_kdf 23 | ~password:"password" 24 | ~salt:"NaCl" 25 | ~n:1024 26 | ~r:8 27 | ~p:16 28 | ~dk_len:64l 29 | ~dk:"fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640" 30 | 31 | let scrypt_kdf_test3 = 32 | test_scrypt_kdf 33 | ~password:"pleaseletmein" 34 | ~salt:"SodiumChloride" 35 | ~n:16384 36 | ~r:8 37 | ~p:1 38 | ~dk_len:64l 39 | ~dk:"7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887" 40 | 41 | let scrypt_kdf_test4 = 42 | test_scrypt_kdf 43 | ~password:"pleaseletmein" 44 | ~salt:"SodiumChloride" 45 | ~n:1048576 46 | ~r:8 47 | ~p:1 48 | ~dk_len:64l 49 | ~dk:"2101cb9b6a511aaeaddbbe09cf70f881ec568d574a2ffd4dabe5ee9820adaa478e56fd8f4ba5d09ffa1c6d927c40f4c337304049e8a952fbcbf45c6fa77a41a4" 50 | 51 | let scrypt_kdf_tests () = 52 | let tests = [ 53 | "Test Case 1", `Quick, scrypt_kdf_test1; 54 | "Test Case 2", `Quick, scrypt_kdf_test2; 55 | "Test Case 3", `Quick, scrypt_kdf_test3; 56 | ] in 57 | (* Skip test case 4 for architectures with 31 bit sizes or less, as it requires a buffer larger than Int.max_size in those cases *) 58 | if Sys.int_size <= 31 then 59 | tests 60 | else 61 | tests @ [ "Test Case 4", `Slow, scrypt_kdf_test4; ] 62 | 63 | let () = 64 | Alcotest.run "Scrypt kdf Tests" [ 65 | "Scrypt kdf tests", scrypt_kdf_tests (); 66 | ] 67 | --------------------------------------------------------------------------------