├── .gitignore ├── .travis.yml ├── README.md ├── include └── scrypt.h ├── package.json ├── scrypt.gyp ├── src ├── common.h ├── hmac.c ├── hmac.h ├── pbkdf2.c ├── pbkdf2.h ├── salsa20.c ├── salsa20.h ├── scrypt.c ├── scrypt.h ├── sha256.c └── sha256.h └── test ├── hmac.c ├── pbkdf2.c ├── salsa20.c ├── scrypt.c ├── sha256.c ├── test.c └── test.h /.gitignore: -------------------------------------------------------------------------------- 1 | out/ 2 | build/ 3 | tools/gyp 4 | *.xcodeproj 5 | node_modules/ 6 | npm-debug.log 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | sudo: false 3 | node_js: 4 | - "7.0" 5 | branches: 6 | only: 7 | - master 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dumb scrypt 2 | 3 | [![Build Status](https://secure.travis-ci.org/indutny/scrypt.svg)](http://travis-ci.org/indutny/scrypt) 4 | 5 | Dumb and simple verifiable implementation of [scrypt][0] 6 | 7 | ## Usage 8 | 9 | ```C 10 | #include 11 | #include 12 | 13 | #include "scrypt.h" 14 | 15 | int main() { 16 | int err; 17 | scrypt_state_t state; 18 | const char* passphrase; 19 | const char* salt; 20 | uint8_t out[32]; 21 | 22 | state.n = 1024; 23 | state.r = 8; 24 | state.p = 16; 25 | err = scrypt_state_init(&state); 26 | assert(err == 0); 27 | 28 | scrypt(&state, 29 | (const uint8_t*) passphrase, 30 | strlen(passphrase), 31 | (const uint8_t*) salt, 32 | strlen(salt), 33 | out, 34 | sizeof(out)); 35 | scrypt_state_free(&state); 36 | 37 | /* Use `out` */ 38 | 39 | return 0; 40 | } 41 | ``` 42 | 43 | ## Building 44 | 45 | ```bash 46 | npm install && npm test 47 | ls -la ./out/Release/libscrypt.a 48 | ``` 49 | 50 | ## Using as dependency 51 | 52 | This project uses [gypkg][1] as a build tool. Please refer to its readme to 53 | use this project as dependency. 54 | 55 | #### LICENSE 56 | 57 | This software is licensed under the MIT License. 58 | 59 | Copyright Fedor Indutny, 2017. 60 | 61 | Permission is hereby granted, free of charge, to any person obtaining a 62 | copy of this software and associated documentation files (the 63 | "Software"), to deal in the Software without restriction, including 64 | without limitation the rights to use, copy, modify, merge, publish, 65 | distribute, sublicense, and/or sell copies of the Software, and to permit 66 | persons to whom the Software is furnished to do so, subject to the 67 | following conditions: 68 | 69 | The above copyright notice and this permission notice shall be included 70 | in all copies or substantial portions of the Software. 71 | 72 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 73 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 74 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 75 | NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 76 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 77 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 78 | USE OR OTHER DEALINGS IN THE SOFTWARE. 79 | 80 | [0]: https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-03 81 | [1]: http://gypkg.io/ 82 | -------------------------------------------------------------------------------- /include/scrypt.h: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDE_SCRYPT_H_ 2 | #define INCLUDE_SCRYPT_H_ 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #include /* uint8_t */ 8 | #include /* size_t */ 9 | 10 | typedef struct scrypt_state_s scrypt_state_t; 11 | 12 | struct scrypt_state_s { 13 | unsigned int r; 14 | unsigned int n; 15 | unsigned int p; 16 | 17 | size_t block_size; 18 | 19 | /* scrypt params */ 20 | uint8_t* b; 21 | 22 | /* ro_mix params */ 23 | uint8_t* x; 24 | uint8_t* v; 25 | uint8_t* t; 26 | }; 27 | 28 | int scrypt_state_init(scrypt_state_t* state); 29 | void scrypt_state_destroy(scrypt_state_t* state); 30 | 31 | void scrypt(scrypt_state_t* state, 32 | const uint8_t* passphrase, 33 | size_t passphase_len, 34 | const uint8_t* salt, 35 | size_t salt_len, 36 | uint8_t* out, 37 | size_t out_len); 38 | 39 | #ifdef __cplusplus 40 | } 41 | #endif 42 | #endif /* INCLUDE_SCRYPT_H_ */ 43 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "scrypt", 3 | "version": "1.0.1", 4 | "private": true, 5 | "description": "Dumb and simple verifiable implementation of scrypt", 6 | "scripts": { 7 | "test": "npm run install && ./out/Release/test", 8 | "install": "gypkg build" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git@github.com:indutny/scrypt" 13 | }, 14 | "keywords": [ 15 | "scrypt" 16 | ], 17 | "author": "Fedor Indutny ", 18 | "license": "MIT", 19 | "gypfile": true, 20 | "dependencies": { 21 | "gypkg": "^2.7.7" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /scrypt.gyp: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [{ 3 | "target_name": "scrypt", 4 | "type": " 5 | #include 6 | 7 | #ifndef MIN 8 | # define MIN(a, b) ((a) > (b) ? (b) : (a)) 9 | #endif /* MIN */ 10 | 11 | #ifndef ARRAY_SIZE 12 | # define ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0])) 13 | #endif 14 | 15 | #define ASSERT__COMMON(expr, desc, ...) \ 16 | do { \ 17 | if (!(expr)) { \ 18 | fprintf(stderr, desc "\n", __VA_ARGS__); \ 19 | abort(); \ 20 | } \ 21 | } while (0) 22 | 23 | #define ASSERT_VA(expr, desc, ...) \ 24 | ASSERT__COMMON(expr, \ 25 | "Assertion failed %s:%d\n" desc, \ 26 | __FILE__, \ 27 | __LINE__, \ 28 | __VA_ARGS__) 29 | 30 | #define ASSERT(expr, desc) \ 31 | ASSERT__COMMON(expr, \ 32 | "Assertion failed %s:%d\n" desc, \ 33 | __FILE__, \ 34 | __LINE__) 35 | 36 | #define UNEXPECTED ASSERT(0, "Unexpected") 37 | 38 | #endif /* SRC_COMMON_H_ */ 39 | -------------------------------------------------------------------------------- /src/hmac.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "src/hmac.h" 6 | #include "src/common.h" 7 | #include "src/sha256.h" 8 | 9 | 10 | /* See https://tools.ietf.org/html/rfc2104#section-2 */ 11 | 12 | void scrypt_hmac_init(scrypt_hmac_t* hmac, const uint8_t* key, size_t key_len) { 13 | /* 14 | * ipad = the byte 0x36 repeated B times 15 | * opad = the byte 0x5C repeated B times. 16 | * 17 | * To compute HMAC over the data `text' we perform 18 | * 19 | * H(K XOR opad, H(K XOR ipad, text)) 20 | * 21 | * Namely, 22 | * 23 | * (1) append zeros to the end of K to create a B byte string 24 | * (e.g., if K is of length 20 bytes and B=64, then K will be 25 | * appended with 44 zero bytes 0x00) 26 | * (2) XOR (bitwise exclusive-OR) the B byte string computed in step 27 | * (1) with ipad 28 | * (3) append the stream of data 'text' to the B byte string resulting 29 | * from step (2) 30 | * (4) apply H to the stream generated in step (3) 31 | * (5) XOR (bitwise exclusive-OR) the B byte string computed in 32 | * step (1) with opad 33 | * (6) append the H result from step (4) to the B byte string 34 | * resulting from step (5) 35 | * (7) apply H to the stream generated in step (6) and output 36 | * the result 37 | */ 38 | 39 | uint8_t block[kSha256BlockSize]; 40 | size_t to_copy; 41 | int i; 42 | 43 | 44 | /* Hash the key to fit it into the block */ 45 | if (key_len > kSha256BlockSize) { 46 | scrypt_sha256_t tmp; 47 | scrypt_sha256_init(&tmp); 48 | scrypt_sha256_update(&tmp, key, key_len); 49 | scrypt_sha256_digest(&tmp, block); 50 | 51 | return scrypt_hmac_init(hmac, block, kSha256DigestSize); 52 | } 53 | 54 | scrypt_sha256_init(&hmac->outer); 55 | scrypt_sha256_init(&hmac->inner); 56 | 57 | /* Pad the key */ 58 | to_copy = MIN(key_len, ARRAY_SIZE(block)); 59 | memcpy(block, key, to_copy); 60 | memset(block + to_copy, 0, ARRAY_SIZE(block) - to_copy); 61 | 62 | for (i = 0; i < kSha256BlockSize; i++) 63 | block[i] ^= 0x36; 64 | scrypt_sha256_update(&hmac->inner, block, kSha256BlockSize); 65 | 66 | /* NOTE: a ^ b ^ b ^ c = a ^ c */ 67 | for (i = 0; i < kSha256BlockSize; i++) 68 | block[i] ^= 0x36 ^ 0x5c; 69 | scrypt_sha256_update(&hmac->outer, block, kSha256BlockSize); 70 | } 71 | 72 | 73 | void scrypt_hmac_update(scrypt_hmac_t* hmac, const uint8_t* data, size_t size) { 74 | scrypt_sha256_update(&hmac->inner, data, size); 75 | } 76 | 77 | 78 | void scrypt_hmac_digest(scrypt_hmac_t* hmac, uint8_t* out) { 79 | uint8_t digest[kSha256DigestSize]; 80 | 81 | scrypt_sha256_digest(&hmac->inner, digest); 82 | scrypt_sha256_update(&hmac->outer, digest, sizeof(digest)); 83 | scrypt_sha256_digest(&hmac->outer, out); 84 | } 85 | -------------------------------------------------------------------------------- /src/hmac.h: -------------------------------------------------------------------------------- 1 | #ifndef SRC_HMAC_H_ 2 | #define SRC_HMAC_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include "src/sha256.h" 8 | 9 | typedef struct scrypt_hmac_s scrypt_hmac_t; 10 | 11 | struct scrypt_hmac_s { 12 | scrypt_sha256_t outer; 13 | scrypt_sha256_t inner; 14 | }; 15 | 16 | void scrypt_hmac_init(scrypt_hmac_t* hmac, const uint8_t* key, size_t key_len); 17 | void scrypt_hmac_update(scrypt_hmac_t* hmac, const uint8_t* data, size_t size); 18 | void scrypt_hmac_digest(scrypt_hmac_t* hmac, uint8_t* out); 19 | 20 | #endif /* SRC_HMAC_H_ */ 21 | -------------------------------------------------------------------------------- /src/pbkdf2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "scrypt.h" 4 | #include "src/pbkdf2.h" 5 | #include "src/hmac.h" 6 | #include "src/common.h" 7 | 8 | /* See: https://tools.ietf.org/html/rfc2898#section-5.2 */ 9 | 10 | void scrypt_pbkdf2_sha256(const uint8_t* password, 11 | size_t password_len, 12 | const uint8_t* salt, 13 | size_t salt_len, 14 | unsigned int c, 15 | uint8_t* out, 16 | size_t out_len) { 17 | /* 18 | * Terminology: 19 | * P = password 20 | * S = salt 21 | * DK = out 22 | * dkLen = out_len 23 | */ 24 | 25 | /* 1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and stop. */ 26 | /* (skip) */ 27 | 28 | /* 2. Let l be the number of hLen-octet blocks in the derived key, 29 | * rounding up, and let r be the number of octets in the last 30 | * block: 31 | * 32 | * l = CEIL (dkLen / hLen) , 33 | * r = dkLen - (l - 1) * hLen . 34 | * 35 | * Here, CEIL (x) is the "ceiling" function, i.e. the smallest 36 | * integer greater than, or equal to, x. 37 | */ 38 | size_t i; 39 | size_t l; 40 | size_t r; 41 | 42 | l = (out_len + kSha256DigestSize - 1) / kSha256DigestSize; 43 | r = out_len - (l - 1) * kSha256DigestSize; 44 | 45 | /* 3. For each block of the derived key apply the function F defined 46 | * below to the password P, the salt S, the iteration count c, and 47 | * the block index to compute the block: 48 | * 49 | * T_1 = F (P, S, c, 1) , 50 | * T_2 = F (P, S, c, 2) , 51 | * ... 52 | * T_l = F (P, S, c, l) , 53 | * 54 | * where the function F is defined as the exclusive-or sum of the 55 | * first c iterates of the underlying pseudorandom function PRF 56 | * applied to the password P and the concatenation of the salt S 57 | * and the block index i: 58 | * 59 | * F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c 60 | * 61 | * where 62 | * 63 | * U_1 = PRF (P, S || INT (i)) , 64 | * U_2 = PRF (P, U_1) , 65 | * ... 66 | * U_c = PRF (P, U_{c-1}) . 67 | * 68 | * Here, INT (i) is a four-octet encoding of the integer i, most 69 | * significant octet first. 70 | */ 71 | for (i = 1; i <= l; i++) { 72 | unsigned int j; 73 | uint8_t t[kSha256DigestSize]; 74 | uint8_t u[kSha256DigestSize]; 75 | uint8_t ctr[4]; 76 | scrypt_hmac_t hmac; 77 | 78 | ctr[0] = i >> 24; 79 | ctr[1] = i >> 16; 80 | ctr[2] = i >> 8; 81 | ctr[3] = i; 82 | 83 | /* U_1 = PRF (P, S || INT (i)) */ 84 | scrypt_hmac_init(&hmac, password, password_len); 85 | scrypt_hmac_update(&hmac, salt, salt_len); 86 | scrypt_hmac_update(&hmac, ctr, sizeof(ctr)); 87 | scrypt_hmac_digest(&hmac, u); 88 | memcpy(t, u, sizeof(u)); 89 | 90 | for (j = 2; j <= c; j++) { 91 | size_t u_len; 92 | size_t k; 93 | 94 | u_len = sizeof(u); 95 | 96 | /* U_c = PRF (P, U_{c-1}) */ 97 | scrypt_hmac_init(&hmac, password, password_len); 98 | scrypt_hmac_update(&hmac, u, u_len); 99 | scrypt_hmac_digest(&hmac, u); 100 | 101 | /* Xor Us */ 102 | for (k = 0; k < kSha256DigestSize; k++) 103 | t[k] ^= u[k]; 104 | } 105 | 106 | /* Copy out the results */ 107 | memcpy(&out[(i - 1) * kSha256DigestSize], 108 | t, 109 | MIN(out_len - (i - 1) * kSha256DigestSize, kSha256DigestSize)); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/pbkdf2.h: -------------------------------------------------------------------------------- 1 | #ifndef SRC_PBKDF2_H_ 2 | #define SRC_PBKDF2_H_ 3 | 4 | #include 5 | #include 6 | 7 | void scrypt_pbkdf2_sha256(const uint8_t* password, 8 | size_t password_len, 9 | const uint8_t* salt, 10 | size_t salt_len, 11 | unsigned int c, 12 | uint8_t* out, 13 | size_t out_len); 14 | 15 | #endif /* SRC_PBKDF2_H_ */ 16 | -------------------------------------------------------------------------------- /src/salsa20.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "src/salsa20.h" 5 | 6 | /* http://cr.yp.to/snuffle/spec.pdf */ 7 | static uint32_t scrypt_salsa20_rotl(uint32_t n, int s) { 8 | return (n << s) | (n >> (32 - s)); 9 | } 10 | 11 | 12 | void scrypt_salsa20_quarterround(const uint32_t* y, uint32_t* z) { 13 | /* 14 | * If y = (y0, y1, y2, y3) then quarterround(y) = (z0, z1, z2, z3) where 15 | * 16 | * z1 = y1 ⊕ ((y0 + y3) <<< 7), 17 | * z2 = y2 ⊕ ((z1 + y0) <<< 9), 18 | * z3 = y3 ⊕ ((z2 + z1) <<< 13), 19 | * z0 = y0 ⊕ ((z3 + z2) <<< 18). 20 | */ 21 | z[1] = y[1] ^ scrypt_salsa20_rotl(y[0] + y[3], 7); 22 | z[2] = y[2] ^ scrypt_salsa20_rotl(z[1] + y[0], 9); 23 | z[3] = y[3] ^ scrypt_salsa20_rotl(z[2] + z[1], 13); 24 | z[0] = y[0] ^ scrypt_salsa20_rotl(z[3] + z[2], 18); 25 | } 26 | 27 | 28 | void scrypt_salsa20_rowround(const uint32_t* y, uint32_t* z) { 29 | /* 30 | * If y = (y0, y1, y2, y3, . . . , y15) then 31 | * rowround(y) = (z0, z1, z2, z3, . . . , z15) where 32 | * 33 | * (z0, z1, z2, z3) = quarterround(y0, y1, y2, y3), 34 | * (z5, z6, z7, z4) = quarterround(y5, y6, y7, y4), 35 | * (z10, z11, z8, z9) = quarterround(y10, y11, y8, y9), 36 | * (z15, z12, z13, z14) = quarterround(y15, y12, y13, y14). 37 | */ 38 | 39 | uint32_t s0[4] = { y[0], y[1], y[2], y[3] }; 40 | uint32_t s1[4] = { y[5], y[6], y[7], y[4] }; 41 | uint32_t s2[4] = { y[10], y[11], y[8], y[9] }; 42 | uint32_t s3[4] = { y[15], y[12], y[13], y[14] }; 43 | uint32_t t[4]; 44 | 45 | scrypt_salsa20_quarterround(s0, t); 46 | z[0] = t[0]; 47 | z[1] = t[1]; 48 | z[2] = t[2]; 49 | z[3] = t[3]; 50 | 51 | scrypt_salsa20_quarterround(s1, t); 52 | z[5] = t[0]; 53 | z[6] = t[1]; 54 | z[7] = t[2]; 55 | z[4] = t[3]; 56 | 57 | scrypt_salsa20_quarterround(s2, t); 58 | z[10] = t[0]; 59 | z[11] = t[1]; 60 | z[8] = t[2]; 61 | z[9] = t[3]; 62 | 63 | scrypt_salsa20_quarterround(s3, t); 64 | z[15] = t[0]; 65 | z[12] = t[1]; 66 | z[13] = t[2]; 67 | z[14] = t[3]; 68 | } 69 | 70 | 71 | void scrypt_salsa20_columnround(const uint32_t* x, uint32_t* y) { 72 | /* 73 | * If x = (x0, x1, x2, x3, . . . , x15) then 74 | * columnround(x) = (y0, y1, y2, y3, . . . , y15) where 75 | * 76 | * (y0, y4, y8, y12) = quarterround(x0, x4, x8, x12), 77 | * (y5, y9, y13, y1) = quarterround(x5, x9, x13, x1), 78 | * (y10, y14, y2, y6) = quarterround(x10, x14, x2, x6), 79 | * (y15, y3, y7, y11) = quarterround(x15, x3, x7, x11). 80 | */ 81 | 82 | uint32_t s0[4] = { x[0], x[4], x[8], x[12] }; 83 | uint32_t s1[4] = { x[5], x[9], x[13], x[1] }; 84 | uint32_t s2[4] = { x[10], x[14], x[2], x[6] }; 85 | uint32_t s3[4] = { x[15], x[3], x[7], x[11] }; 86 | uint32_t t[4]; 87 | 88 | scrypt_salsa20_quarterround(s0, t); 89 | y[0] = t[0]; 90 | y[4] = t[1]; 91 | y[8] = t[2]; 92 | y[12] = t[3]; 93 | 94 | scrypt_salsa20_quarterround(s1, t); 95 | y[5] = t[0]; 96 | y[9] = t[1]; 97 | y[13] = t[2]; 98 | y[1] = t[3]; 99 | 100 | scrypt_salsa20_quarterround(s2, t); 101 | y[10] = t[0]; 102 | y[14] = t[1]; 103 | y[2] = t[2]; 104 | y[6] = t[3]; 105 | 106 | scrypt_salsa20_quarterround(s3, t); 107 | y[15] = t[0]; 108 | y[3] = t[1]; 109 | y[7] = t[2]; 110 | y[11] = t[3]; 111 | } 112 | 113 | 114 | void scrypt_salsa20_doubleround(const uint32_t* x, uint32_t* y) { 115 | /* 116 | * A double round is a column round followed by a row round: 117 | * doubleround(x) = rowround(columnround(x)). 118 | */ 119 | scrypt_salsa20_columnround(x, y); 120 | scrypt_salsa20_rowround(y, y); 121 | } 122 | 123 | 124 | static uint32_t scrypt_salsa20_littleendian(const uint8_t* b) { 125 | /* 126 | * If b = (b0, b1, b2, b3) then littleendian(b) = 127 | * b0 + 2^8 * b1 + 2^16 * b2 + 2^24 * b3. 128 | */ 129 | return (uint32_t) b[0] | 130 | ((uint32_t) b[1] << 8) | 131 | ((uint32_t) b[2] << 16) | 132 | ((uint32_t) b[3] << 24); 133 | } 134 | 135 | 136 | static void scrypt_salsa20_littleendian_inv(uint32_t x, uint8_t* y) { 137 | y[0] = x; 138 | y[1] = x >> 8; 139 | y[2] = x >> 16; 140 | y[3] = x >> 24; 141 | } 142 | 143 | 144 | void scrypt_salsa20(const uint8_t* input, int rounds, uint8_t* output) { 145 | /* 146 | * In short: Salsa20(x) = x + doubleround^10(x), where each 4-byte sequence is 147 | * viewed as a word in little-endian form. 148 | * 149 | * In detail: Starting from x = (x[0], x[1], . . . , x[63]), define 150 | * x0 = littleendian(x[0], x[1], x[2], x[3]), 151 | * x1 = littleendian(x[4], x[5], x[6], x[7]), 152 | * x2 = littleendian(x[8], x[9], x[10], x[11]), 153 | * ... 154 | * x15 = littleendian(x[60], x[61], x[62], x[63]). 155 | * 156 | * Define (z0, z1, . . . , z15) = doubleround10(x0, x1, . . . , x15). 157 | * 158 | * Then Salsa20(x) is the concatenation of 159 | * littleendian^−1(z0 + x0), 160 | * littleendian^−1(z1 + x1), 161 | * littleendian^−1(z2 + x2), 162 | * ... 163 | * littleendian^−1(z15 + x15). 164 | */ 165 | 166 | int i; 167 | int j; 168 | 169 | uint32_t x[16]; 170 | uint32_t z[16]; 171 | 172 | for (i = 0; i < (int) (kSalsa20BlockSize / sizeof(*x)); i++) 173 | x[i] = scrypt_salsa20_littleendian(&input[i * sizeof(*x)]); 174 | 175 | memcpy(z, x, sizeof(x)); 176 | 177 | for (j = 0; j < rounds; j++) 178 | scrypt_salsa20_doubleround(z, z); 179 | 180 | for (i = 0; i < (int) (kSalsa20BlockSize / sizeof(*x)); i++) 181 | scrypt_salsa20_littleendian_inv(x[i] + z[i], &output[i * sizeof(*x)]); 182 | } 183 | -------------------------------------------------------------------------------- /src/salsa20.h: -------------------------------------------------------------------------------- 1 | #ifndef SRC_SALSA20_H_ 2 | #define SRC_SALSA20_H_ 3 | 4 | #include 5 | 6 | static const int kSalsa20BlockSize = 64; 7 | 8 | void scrypt_salsa20(const uint8_t* input, int rounds, uint8_t* output); 9 | 10 | /* Just for testing */ 11 | void scrypt_salsa20_quarterround(const uint32_t* y, uint32_t* z); 12 | void scrypt_salsa20_rowround(const uint32_t* y, uint32_t* z); 13 | void scrypt_salsa20_columnround(const uint32_t* x, uint32_t* y); 14 | void scrypt_salsa20_doubleround(const uint32_t* x, uint32_t* y); 15 | 16 | #endif /* SRC_SALSA20_H_ */ 17 | -------------------------------------------------------------------------------- /src/scrypt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "src/scrypt.h" 5 | #include "include/scrypt.h" 6 | #include "src/pbkdf2.h" 7 | #include "src/salsa20.h" 8 | 9 | 10 | static int kScryptSalsaRounds = 4; 11 | static int kScryptPBKDF2Rounds = 1; 12 | static int kScryptBlockMultiplier = 128; 13 | 14 | static void scrypt_xor(const uint8_t* a, 15 | const uint8_t* b, 16 | size_t size, 17 | uint8_t* out) { 18 | size_t i; 19 | 20 | for (i = 0; i < size; i++) 21 | out[i] = a[i] ^ b[i]; 22 | } 23 | 24 | void scrypt_block_mix(const uint8_t* b, unsigned int r, uint8_t* output) { 25 | /* 26 | * Algorithm scryptBlockMix 27 | * 28 | * Parameters: 29 | * r Block size parameter. 30 | * 31 | * Input: 32 | * B[0], ..., B[2 * r - 1] 33 | * Input vector of 2 * r 64-octet blocks. 34 | * 35 | * Output: 36 | * B'[0], ..., B'[2 * r - 1] 37 | * Output vector of 2 * r 64-octet blocks. 38 | * 39 | * Steps: 40 | * 41 | * 1. X = B[2 * r - 1] 42 | * 43 | * 2. for i = 0 to 2 * r - 1 do 44 | * T = X xor B[i] 45 | * X = Salsa (T) 46 | * Y[i] = X 47 | * end for 48 | * 49 | * 3. B' = (Y[0], Y[2], ..., Y[2 * r - 2], 50 | * Y[1], Y[3], ..., Y[2 * r - 1]) 51 | */ 52 | 53 | uint8_t x[kSalsa20BlockSize]; 54 | unsigned int i; 55 | 56 | /* Step 1 */ 57 | memcpy(x, &b[(2 * r - 1) * kSalsa20BlockSize], sizeof(x)); 58 | 59 | /* Step 2 */ 60 | for (i = 0; i < 2 * r; i++) { 61 | uint8_t t[sizeof(x)]; 62 | 63 | scrypt_xor(x, &b[i * kSalsa20BlockSize], kSalsa20BlockSize, t); 64 | scrypt_salsa20(t, kScryptSalsaRounds, x); 65 | 66 | /* Step 3 */ 67 | if (i % 2 == 0) 68 | memcpy(&output[(i / 2) * kSalsa20BlockSize], x, sizeof(x)); 69 | else 70 | memcpy(&output[(r + (i / 2)) * kSalsa20BlockSize], x, sizeof(x)); 71 | } 72 | } 73 | 74 | 75 | static uint64_t scrypt_integerify(scrypt_state_t* state, const uint8_t* x) { 76 | const uint8_t* p; 77 | uint64_t res; 78 | 79 | p = &x[state->block_size - kSalsa20BlockSize]; 80 | res = (uint64_t) p[0] + ((uint64_t) p[1] << 8) + 81 | ((uint64_t) p[2] << 16) + ((uint64_t) p[3] << 24) + 82 | ((uint64_t) p[4] << 32) + ((uint64_t) p[5] << 40) + 83 | ((uint64_t) p[6] << 48) + ((uint64_t) p[7] << 56); 84 | 85 | return res; 86 | } 87 | 88 | 89 | void scrypt_ro_mix(scrypt_state_t* state, const uint8_t* b, uint8_t* output) { 90 | /* 91 | * Algorithm scryptROMix 92 | * 93 | * Input: 94 | * r Block size parameter. 95 | * B Input octet vector of length 128 * r octets. 96 | * N CPU/Memory cost parameter, must be larger than 1, 97 | * a power of 2 and less than 2^(128 * r / 8). 98 | * 99 | * Output: 100 | * B' Output octet vector of length 128 * r octets. 101 | * 102 | * Steps: 103 | * 104 | * 1. X = B 105 | * 106 | * 2. for i = 0 to N - 1 do 107 | * V[i] = X 108 | * X = scryptBlockMix (X) 109 | * end for 110 | * 111 | * 3. for i = 0 to N - 1 do 112 | * j = Integerify (X) mod N 113 | * where Integerify (B[0] ... B[2 * r - 1]) is defined 114 | * as the result of interpreting B[2 * r - 1] as a 115 | * little-endian integer. 116 | * T = X xor V[j] 117 | * X = scryptBlockMix (T) 118 | * end for 119 | * 120 | * 4. B' = X 121 | */ 122 | 123 | uint8_t* x; 124 | uint8_t* v; 125 | uint8_t* t; 126 | unsigned int i; 127 | 128 | x = state->x; 129 | v = state->v; 130 | t = state->t; 131 | 132 | /* Step 1 */ 133 | memcpy(x, b, state->block_size); 134 | 135 | /* Step 2 */ 136 | for (i = 0; i < state->n; i++) { 137 | uint8_t* s; 138 | 139 | memcpy(&v[state->block_size * i], x, state->block_size); 140 | scrypt_block_mix(x, state->r, t); 141 | 142 | s = t; 143 | t = x; 144 | x = s; 145 | } 146 | 147 | /* Step 3 */ 148 | for (i = 0; i < state->n; i++) { 149 | int j; 150 | 151 | j = scrypt_integerify(state, x) % state->n; 152 | scrypt_xor(x, &v[j * state->block_size], state->block_size, t); 153 | scrypt_block_mix(t, state->r, x); 154 | } 155 | 156 | /* Step 4 */ 157 | memcpy(output, x, state->block_size); 158 | } 159 | 160 | 161 | void scrypt(scrypt_state_t* state, 162 | const uint8_t* passphrase, 163 | size_t passphase_len, 164 | const uint8_t* salt, 165 | size_t salt_len, 166 | uint8_t* out, 167 | size_t out_len) { 168 | /* 169 | * Algorithm scrypt 170 | * 171 | * Input: 172 | * P Passphrase, an octet string. 173 | * S Salt, an octet string. 174 | * N CPU/Memory cost parameter, must be larger than 1, 175 | * a power of 2 and less than 2^(128 * r / 8). 176 | * r Block size parameter. 177 | * p Parallelization parameter, a positive integer 178 | * less than or equal to ((2^32-1) * hLen) / MFLen 179 | * where hLen is 32 and MFlen is 128 * r. 180 | * dkLen Intended output length in octets of the derived 181 | * key; a positive integer less than or equal to 182 | * (2^32 - 1) * hLen where hLen is 32. 183 | * 184 | * Output: 185 | * DK Derived key, of length dkLen octets. 186 | * 187 | * Steps: 188 | * 189 | * 1. B[0] || B[1] || ... || B[p - 1] = 190 | * PBKDF2-HMAC-SHA256 (P, S, 1, p * 128 * r) 191 | * 192 | * 2. for i = 0 to p - 1 do 193 | * B[i] = scryptROMix (r, B[i], N) 194 | * end for 195 | * 196 | * 3. DK = PBKDF2-HMAC-SHA256 (P, B[0] || B[1] || ... || B[p - 1], 197 | * 1, dkLen) 198 | */ 199 | 200 | unsigned int i; 201 | 202 | /* Step 1 */ 203 | scrypt_pbkdf2_sha256(passphrase, 204 | passphase_len, 205 | salt, 206 | salt_len, 207 | kScryptPBKDF2Rounds, 208 | state->b, 209 | state->p * state->block_size); 210 | 211 | /* Step 2 */ 212 | for (i = 0; i < state->p; i++) { 213 | uint8_t* b; 214 | 215 | b = &state->b[state->block_size * i]; 216 | scrypt_ro_mix(state, b, b); 217 | } 218 | 219 | /* Step 3 */ 220 | scrypt_pbkdf2_sha256(passphrase, 221 | passphase_len, 222 | state->b, 223 | state->p * state->block_size, 224 | kScryptPBKDF2Rounds, 225 | out, 226 | out_len); 227 | } 228 | 229 | 230 | int scrypt_state_init(scrypt_state_t* state) { 231 | state->block_size = kScryptBlockMultiplier * state->r; 232 | 233 | state->b = malloc(state->p * state->block_size); 234 | if (state->b == NULL) 235 | goto failed_alloc_b; 236 | 237 | state->x = malloc(state->block_size); 238 | if (state->x == NULL) 239 | goto failed_alloc_x; 240 | 241 | state->v = malloc(state->block_size * state->n); 242 | if (state->v == NULL) 243 | goto failed_alloc_v; 244 | 245 | state->t = malloc(state->block_size); 246 | if (state->t == NULL) 247 | goto failed_alloc_t; 248 | 249 | return 0; 250 | 251 | failed_alloc_t: 252 | free(state->v); 253 | state->v = NULL; 254 | 255 | failed_alloc_v: 256 | free(state->x); 257 | state->x = NULL; 258 | 259 | failed_alloc_x: 260 | free(state->b); 261 | state->b = NULL; 262 | 263 | failed_alloc_b: 264 | return -1; 265 | } 266 | 267 | 268 | void scrypt_state_destroy(scrypt_state_t* state) { 269 | free(state->v); 270 | free(state->x); 271 | free(state->t); 272 | memset(state, 0, sizeof(*state)); 273 | } 274 | -------------------------------------------------------------------------------- /src/scrypt.h: -------------------------------------------------------------------------------- 1 | #ifndef SRC_SCRYPT_H_ 2 | #define SRC_SCRYPT_H_ 3 | 4 | #include 5 | 6 | #include "include/scrypt.h" 7 | 8 | /* Just for testing */ 9 | void scrypt_block_mix(const uint8_t* b, unsigned int r, uint8_t* output); 10 | void scrypt_ro_mix(scrypt_state_t* state, const uint8_t* b, uint8_t* output); 11 | 12 | #endif /* SRC_SCRYPT_H_ */ 13 | -------------------------------------------------------------------------------- /src/sha256.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "src/sha256.h" 6 | #include "src/common.h" 7 | 8 | 9 | /* See: https://tools.ietf.org/html/rfc6234#section-5.1 */ 10 | static uint32_t scrypt_sha256_k[] = { 11 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 12 | 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 13 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 14 | 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 15 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 16 | 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 17 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 18 | 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 19 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 20 | 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 21 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 22 | 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 23 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 24 | 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 25 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 26 | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 27 | }; 28 | 29 | 30 | static uint32_t scrypt_sha256_h[] = { 31 | 0x6a09e667, 32 | 0xbb67ae85, 33 | 0x3c6ef372, 34 | 0xa54ff53a, 35 | 0x510e527f, 36 | 0x9b05688c, 37 | 0x1f83d9ab, 38 | 0x5be0cd19 39 | }; 40 | 41 | 42 | /* CH( x, y, z) = (x AND y) XOR ( (NOT x) AND z) */ 43 | static uint32_t scrypt_sha256_ch(uint32_t x, uint32_t y, uint32_t z) { 44 | return (x & y) ^ ((~x) & z); 45 | } 46 | 47 | 48 | /* MAJ( x, y, z) = (x AND y) XOR (x AND z) XOR (y AND z) */ 49 | static uint32_t scrypt_sha256_maj(uint32_t x, uint32_t y, uint32_t z) { 50 | return (x & y) ^ (x & z) ^ (y & z); 51 | } 52 | 53 | 54 | static uint32_t scrypt_sha256_rotr(uint32_t n, int s) { 55 | return (n << (32 - s)) | (n >> s); 56 | } 57 | 58 | 59 | /* BSIG0(x) = ROTR^2(x) XOR ROTR^13(x) XOR ROTR^22(x) */ 60 | static uint32_t scrypt_sha256_bsig0(uint32_t x) { 61 | return scrypt_sha256_rotr(x, 2) ^ 62 | scrypt_sha256_rotr(x, 13) ^ 63 | scrypt_sha256_rotr(x, 22); 64 | } 65 | 66 | 67 | /* BSIG1(x) = ROTR^6(x) XOR ROTR^11(x) XOR ROTR^25(x) */ 68 | static uint32_t scrypt_sha256_bsig1(uint32_t x) { 69 | return scrypt_sha256_rotr(x, 6) ^ 70 | scrypt_sha256_rotr(x, 11) ^ 71 | scrypt_sha256_rotr(x, 25); 72 | } 73 | 74 | 75 | /* SSIG0(x) = ROTR^7(x) XOR ROTR^18(x) XOR SHR^3(x) */ 76 | static uint32_t scrypt_sha256_ssig0(uint32_t x) { 77 | return scrypt_sha256_rotr(x, 7) ^ 78 | scrypt_sha256_rotr(x, 18) ^ 79 | (x >> 3); 80 | } 81 | 82 | 83 | /* SSIG1(x) = ROTR^17(x) XOR ROTR^19(x) XOR SHR^10(x) */ 84 | static uint32_t scrypt_sha256_ssig1(uint32_t x) { 85 | return scrypt_sha256_rotr(x, 17) ^ 86 | scrypt_sha256_rotr(x, 19) ^ 87 | (x >> 10); 88 | } 89 | 90 | 91 | void scrypt_sha256_init(scrypt_sha256_t* sha256) { 92 | memcpy(sha256->h, scrypt_sha256_h, sizeof(scrypt_sha256_h)); 93 | sha256->length = 0; 94 | } 95 | 96 | 97 | static void scrypt_sha256_fill_block(const uint8_t* input, 98 | uint32_t* output, 99 | size_t n) { 100 | size_t i; 101 | 102 | for (i = 0; i < n; i++) { 103 | output[i] = ((uint32_t) input[i * 4] << 24) | 104 | ((uint32_t) input[i * 4 + 1] << 16) | 105 | ((uint32_t) input[i * 4 + 2] << 8) | 106 | (uint32_t) input[i * 4 + 3]; 107 | } 108 | } 109 | 110 | 111 | static void scrypt_sha256_process_block(scrypt_sha256_t* sha256, 112 | const uint32_t* block) { 113 | /* 114 | * 1. Prepare the message schedule W: 115 | * For t = 0 to 15 116 | * Wt = M(i)t 117 | * For t = 16 to 63 118 | * Wt = SSIG1(W(t-2)) + W(t-7) + SSIG0(w(t-15)) + W(t-16) 119 | * 120 | */ 121 | uint32_t w[64]; 122 | size_t t; 123 | uint32_t a; 124 | uint32_t b; 125 | uint32_t c; 126 | uint32_t d; 127 | uint32_t e; 128 | uint32_t f; 129 | uint32_t g; 130 | uint32_t h; 131 | 132 | memcpy(w, block, sizeof(*w) * 16); 133 | for (t = 16; t < 64; t++) { 134 | w[t] = scrypt_sha256_ssig1(w[t - 2]) + 135 | w[t - 7] + 136 | scrypt_sha256_ssig0(w[t - 15]) + 137 | w[t - 16]; 138 | } 139 | 140 | /* 141 | * 2. Initialize the working variables: 142 | * a = H(i-1)0 143 | * b = H(i-1)1 144 | * c = H(i-1)2 145 | * d = H(i-1)3 146 | * e = H(i-1)4 147 | * f = H(i-1)5 148 | * g = H(i-1)6 149 | * h = H(i-1)7 150 | */ 151 | a = sha256->h[0]; 152 | b = sha256->h[1]; 153 | c = sha256->h[2]; 154 | d = sha256->h[3]; 155 | e = sha256->h[4]; 156 | f = sha256->h[5]; 157 | g = sha256->h[6]; 158 | h = sha256->h[7]; 159 | 160 | /* 161 | * 3. Perform the main hash computation: 162 | * For t = 0 to 63 163 | * T1 = h + BSIG1(e) + CH(e,f,g) + Kt + Wt 164 | * T2 = BSIG0(a) + MAJ(a,b,c) 165 | * h = g 166 | * g = f 167 | * f = e 168 | * e = d + T1 169 | * d = c 170 | * c = b 171 | * b = a 172 | * a = T1 + T2 173 | */ 174 | for (t = 0; t < 64; t++) { 175 | uint32_t t1; 176 | uint32_t t2; 177 | 178 | t1 = h + 179 | scrypt_sha256_bsig1(e) + 180 | scrypt_sha256_ch(e, f, g) + 181 | scrypt_sha256_k[t] + 182 | w[t]; 183 | t2 = scrypt_sha256_bsig0(a) + scrypt_sha256_maj(a, b, c); 184 | h = g; 185 | g = f; 186 | f = e; 187 | e = d + t1; 188 | d = c; 189 | c = b; 190 | b = a; 191 | a = t1 + t2; 192 | } 193 | 194 | /* 195 | * 4. Compute the intermediate hash value H(i) 196 | * H(i)0 = a + H(i-1)0 197 | * H(i)1 = b + H(i-1)1 198 | * H(i)2 = c + H(i-1)2 199 | * H(i)3 = d + H(i-1)3 200 | * H(i)4 = e + H(i-1)4 201 | * H(i)5 = f + H(i-1)5 202 | * H(i)6 = g + H(i-1)6 203 | * H(i)7 = h + H(i-1)7 204 | */ 205 | sha256->h[0] += a; 206 | sha256->h[1] += b; 207 | sha256->h[2] += c; 208 | sha256->h[3] += d; 209 | sha256->h[4] += e; 210 | sha256->h[5] += f; 211 | sha256->h[6] += g; 212 | sha256->h[7] += h; 213 | } 214 | 215 | 216 | void scrypt_sha256_update(scrypt_sha256_t* sha256, 217 | const uint8_t* data, 218 | size_t size) { 219 | const uint8_t* p; 220 | size_t left; 221 | 222 | p = data; 223 | left = size; 224 | 225 | while (left != 0) { 226 | size_t off; 227 | size_t to_copy; 228 | uint32_t block[16]; 229 | 230 | off = sha256->length % kSha256BlockSize; 231 | to_copy = MIN(left, kSha256BlockSize - off); 232 | 233 | /* Just bufferize to fill the block */ 234 | memcpy(sha256->buffer + off, p, to_copy); 235 | sha256->length += to_copy; 236 | 237 | p += to_copy; 238 | left -= to_copy; 239 | 240 | /* Incomplete block - wait for more data */ 241 | if (off + to_copy != kSha256BlockSize) 242 | break; 243 | 244 | scrypt_sha256_fill_block(sha256->buffer, block, ARRAY_SIZE(block)); 245 | scrypt_sha256_process_block(sha256, block); 246 | } 247 | } 248 | 249 | 250 | static void scrypt_sha256_write_uint64_be(uint8_t* data, 251 | uint64_t value, 252 | size_t off) { 253 | data[off] = value >> 56; 254 | data[off + 1] = value >> 48; 255 | data[off + 2] = value >> 40; 256 | data[off + 3] = value >> 32; 257 | data[off + 4] = value >> 24; 258 | data[off + 5] = value >> 16; 259 | data[off + 6] = value >> 8; 260 | data[off + 7] = value; 261 | } 262 | 263 | 264 | void scrypt_sha256_digest(scrypt_sha256_t* sha256, uint8_t* out) { 265 | /* https://tools.ietf.org/html/rfc6234#section-4.1 */ 266 | 267 | /* 268 | * Suppose a message has length L < 2^64. Before it is input to the 269 | * hash function, the message is padded on the right as follows: 270 | * 271 | * a. "1" is appended. Example: if the original message is "01010000", 272 | * this is padded to "010100001". 273 | * 274 | * b. K "0"s are appended where K is the smallest, non-negative solution 275 | * to the equation 276 | * 277 | * ( L + 1 + K ) mod 512 = 448 278 | * 279 | * c. Then append the 64-bit block that is L in binary representation. 280 | * After appending this block, the length of the message will be a 281 | * multiple of 512 bits. 282 | */ 283 | 284 | size_t off; 285 | uint32_t block[16]; 286 | size_t i; 287 | int has_overflow; 288 | 289 | /* NOTE: It is simple to calculate `k`, but having it is a bit useless, since 290 | * we know that this algorithm just wants to zero the rest of the block and to 291 | * put the 64bit length to the end */ 292 | off = (sha256->length % kSha256BlockSize); 293 | 294 | /* (b) */ 295 | memset(sha256->buffer + off, 0, kSha256BlockSize - off); 296 | 297 | /* If padding does not fit in a single block - append 0x80 and zeroes to the 298 | * current block and flush it. 299 | * Then fill the block with zeroes and append size to it, and flush it again 300 | */ 301 | has_overflow = off + 9 > kSha256BlockSize; 302 | if (has_overflow) { 303 | /* (a) */ 304 | sha256->buffer[off] |= 0x80; 305 | 306 | scrypt_sha256_fill_block(sha256->buffer, block, ARRAY_SIZE(block)); 307 | scrypt_sha256_process_block(sha256, block); 308 | 309 | off = 0; 310 | memset(sha256->buffer, 0, kSha256BlockSize); 311 | } 312 | 313 | /* (c) */ 314 | scrypt_sha256_write_uint64_be(sha256->buffer, 315 | sha256->length * 8, 316 | kSha256BlockSize - 8); 317 | 318 | /* (a) */ 319 | if (!has_overflow) 320 | sha256->buffer[off] |= 0x80; 321 | 322 | scrypt_sha256_fill_block(sha256->buffer, block, ARRAY_SIZE(block)); 323 | scrypt_sha256_process_block(sha256, block); 324 | 325 | for (i = 0; i < ARRAY_SIZE(sha256->h); i++) { 326 | out[i * 4] = sha256->h[i] >> 24; 327 | out[i * 4 + 1] = sha256->h[i] >> 16; 328 | out[i * 4 + 2] = sha256->h[i] >> 8; 329 | out[i * 4 + 3] = sha256->h[i]; 330 | } 331 | } 332 | -------------------------------------------------------------------------------- /src/sha256.h: -------------------------------------------------------------------------------- 1 | #ifndef SRC_SHA256_H_ 2 | #define SRC_SHA256_H_ 3 | 4 | #include 5 | #include 6 | 7 | typedef struct scrypt_sha256_s scrypt_sha256_t; 8 | 9 | static const int kSha256DigestSize = 32; 10 | static const int kSha256BlockSize = 64; 11 | 12 | struct scrypt_sha256_s { 13 | /* kSha256DigestSize / 4 */ 14 | uint32_t h[8]; 15 | 16 | /* kSha256BlockSize */ 17 | uint8_t buffer[64]; 18 | uint64_t length; 19 | }; 20 | 21 | void scrypt_sha256_init(scrypt_sha256_t* sha256); 22 | void scrypt_sha256_update(scrypt_sha256_t* sha256, 23 | const uint8_t* data, 24 | size_t size); 25 | void scrypt_sha256_digest(scrypt_sha256_t* sha256, uint8_t* out); 26 | 27 | #endif /* SRC_SHA256_H_ */ 28 | -------------------------------------------------------------------------------- /test/hmac.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "test/test.h" 5 | #include "src/common.h" 6 | #include "src/hmac.h" 7 | 8 | typedef struct scrypt_hmac_test_s scrypt_hmac_test_t; 9 | 10 | struct scrypt_hmac_test_s { 11 | const char* key; 12 | const char* inputs[16]; 13 | uint8_t expected[32]; 14 | }; 15 | 16 | SCRYPT_TEST(hmac) { 17 | size_t i; 18 | 19 | /* See https://tools.ietf.org/html/rfc4231 */ 20 | scrypt_hmac_test_t tests[] = { 21 | { 22 | .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" 23 | "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 24 | .inputs = { "Hi There", NULL }, 25 | .expected = { 26 | 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 27 | 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b, 28 | 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, 29 | 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7 30 | } 31 | }, 32 | { 33 | .key = "Jefe", 34 | .inputs = { "what do ya want ", "for nothing?", NULL }, 35 | .expected = { 36 | 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, 37 | 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7, 38 | 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, 39 | 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43 40 | } 41 | }, 42 | { 43 | .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" 44 | "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 45 | .inputs = { 46 | "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", 47 | "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", 48 | "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", 49 | "\xdd\xdd", 50 | NULL 51 | }, 52 | .expected = { 53 | 0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, 54 | 0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7, 55 | 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22, 56 | 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe 57 | } 58 | }, 59 | { 60 | .key = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" 61 | "\x11\x12\x13\x14\x15\x16\x17\x18\x19", 62 | .inputs = { 63 | "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", 64 | "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", 65 | "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", 66 | "\xcd\xcd", 67 | NULL 68 | }, 69 | .expected = { 70 | 0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e, 71 | 0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a, 72 | 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07, 73 | 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b 74 | } 75 | }, 76 | { 77 | .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" 78 | "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" 79 | "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" 80 | "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" 81 | "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" 82 | "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" 83 | "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" 84 | "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" 85 | "\xaa\xaa\xaa", 86 | .inputs = { 87 | "Test Using Large", 88 | "r Than Block-Siz", 89 | "e Key - Hash Key", 90 | " First", 91 | NULL 92 | }, 93 | .expected = { 94 | 0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 95 | 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f, 96 | 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, 97 | 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54 98 | } 99 | }, 100 | { 101 | .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" 102 | "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" 103 | "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" 104 | "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" 105 | "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" 106 | "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" 107 | "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" 108 | "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" 109 | "\xaa\xaa\xaa", 110 | .inputs = { 111 | "This is a test u", 112 | "sing a larger th", 113 | "an block-size ke", 114 | "y and a larger t", 115 | "han block-size d", 116 | "ata. The key nee", 117 | "ds to be hashed ", 118 | "before being use", 119 | "d by the HMAC al", 120 | "gorithm.", 121 | NULL 122 | }, 123 | .expected = { 124 | 0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, 125 | 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44, 126 | 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, 127 | 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2 128 | } 129 | } 130 | }; 131 | 132 | for (i = 0; i < ARRAY_SIZE(tests); i++) { 133 | scrypt_hmac_test_t* v; 134 | uint8_t out[sizeof(v->expected)]; 135 | size_t j; 136 | scrypt_hmac_t hmac; 137 | const char** chunk; 138 | 139 | v = &tests[i]; 140 | 141 | scrypt_hmac_init(&hmac, (uint8_t*) v->key, strlen(v->key)); 142 | for (chunk = v->inputs; *chunk != NULL; chunk++) 143 | scrypt_hmac_update(&hmac, (uint8_t*) *chunk, strlen(*chunk)); 144 | scrypt_hmac_digest(&hmac, out); 145 | 146 | for (j = 0; j < ARRAY_SIZE(out); j++) { 147 | if (out[j] == v->expected[j]) 148 | continue; 149 | 150 | fprintf(stderr, 151 | "0x%02x != 0x%02x at %d (test vector: %d)\n", 152 | out[j], 153 | v->expected[j], 154 | (int) j, 155 | (int) i); 156 | ASSERT(0, "sha256 hmac failure"); 157 | } 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /test/pbkdf2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "test/test.h" 5 | #include "src/common.h" 6 | #include "src/pbkdf2.h" 7 | 8 | typedef struct pbkdf2_test_vector_s pbkdf2_test_vector_t; 9 | 10 | struct pbkdf2_test_vector_s { 11 | const char* password; 12 | const char* salt; 13 | unsigned int c; 14 | size_t dkLen; 15 | const char* expected; 16 | }; 17 | 18 | SCRYPT_TEST(pbkdf2_test_vectors) { 19 | size_t i; 20 | 21 | /* See: https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-03#page-10 */ 22 | pbkdf2_test_vector_t tests[] = { 23 | { 24 | .password = "passwd", 25 | .salt = "salt", 26 | .c = 1, 27 | .dkLen = 64, 28 | .expected = "55ac046e56e3089fec1691c22544b605" 29 | "f94185216dde0465e68b9d57c20dacbc" 30 | "49ca9cccf179b645991664b39d77ef31" 31 | "7c71b845b1e30bd509112041d3a19783" 32 | }, 33 | { 34 | .password = "Password", 35 | .salt = "NaCl", 36 | .c = 80000, 37 | .dkLen = 64, 38 | .expected = "4ddcd8f60b98be21830cee5ef22701f9" 39 | "641a4418d04c0414aeff08876b34ab56" 40 | "a1d425a1225833549adb841b51c9b317" 41 | "6a272bdebba1d078478f62b397f33c8d" 42 | } 43 | }; 44 | 45 | for (i = 0; i < ARRAY_SIZE(tests); i++) { 46 | pbkdf2_test_vector_t* v; 47 | uint8_t out[1024]; 48 | 49 | v = &tests[i]; 50 | ASSERT(v->dkLen <= sizeof(out), "Not enough space for dkLen"); 51 | 52 | scrypt_pbkdf2_sha256((const uint8_t*) v->password, 53 | strlen(v->password), 54 | (const uint8_t*) v->salt, 55 | strlen(v->salt), 56 | v->c, 57 | out, 58 | v->dkLen); 59 | 60 | ASSERT(scrypt_compare_hex(out, v->expected) == 0, "DK mismatch"); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /test/salsa20.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "test/test.h" 5 | #include "src/common.h" 6 | #include "src/salsa20.h" 7 | 8 | typedef struct salsa20_quarter_test_vector_s salsa20_quarter_test_vector_t; 9 | typedef struct salsa20_row_test_vector_s salsa20_row_test_vector_t; 10 | typedef struct salsa20_test_vector_s salsa20_test_vector_t; 11 | 12 | struct salsa20_quarter_test_vector_s { 13 | uint32_t input[4]; 14 | uint32_t expected[4]; 15 | }; 16 | 17 | struct salsa20_row_test_vector_s { 18 | uint32_t input[16]; 19 | uint32_t expected[16]; 20 | }; 21 | 22 | struct salsa20_test_vector_s { 23 | int rounds; 24 | uint8_t input[64]; 25 | uint8_t expected[64]; 26 | }; 27 | 28 | SCRYPT_TEST(salsa20_quarterround) { 29 | size_t i; 30 | 31 | /* http://cr.yp.to/snuffle/spec.pdf */ 32 | salsa20_quarter_test_vector_t tests[] = { 33 | { 34 | .input = { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 35 | .expected = { 0x00000000, 0x00000000, 0x00000000, 0x00000000 } 36 | }, 37 | { 38 | .input = { 0x00000001, 0x00000000, 0x00000000, 0x00000000 }, 39 | .expected = { 0x08008145, 0x00000080, 0x00010200, 0x20500000 } 40 | }, 41 | { 42 | .input = { 0x00000000, 0x00000001, 0x00000000, 0x00000000 }, 43 | .expected = { 0x88000100, 0x00000001, 0x00000200, 0x00402000 } 44 | }, 45 | { 46 | .input = { 0x00000000, 0x00000000, 0x00000001, 0x00000000 }, 47 | .expected = { 0x80040000, 0x00000000, 0x00000001, 0x00002000 } 48 | }, 49 | { 50 | .input = { 0x00000000, 0x00000000, 0x00000000, 0x00000001 }, 51 | .expected = { 0x00048044, 0x00000080, 0x00010000, 0x20100001 } 52 | }, 53 | { 54 | .input = { 0xe7e8c006, 0xc4f9417d, 0x6479b4b2, 0x68c67137 }, 55 | .expected = { 0xe876d72b, 0x9361dfd5, 0xf1460244, 0x948541a3 } 56 | }, 57 | { 58 | .input = { 0xd3917c5b, 0x55f1c407, 0x52a58a7a, 0x8f887a3b }, 59 | .expected = { 0x3e2f308c, 0xd90a8f36, 0x6ab2a923, 0x2883524c } 60 | } 61 | }; 62 | 63 | for (i = 0; i < ARRAY_SIZE(tests); i++) { 64 | salsa20_quarter_test_vector_t* v; 65 | uint32_t out[ARRAY_SIZE(v->input)]; 66 | size_t j; 67 | 68 | v = &tests[i]; 69 | 70 | scrypt_salsa20_quarterround(v->input, out); 71 | for (j = 0; j < ARRAY_SIZE(out); j++) { 72 | if (out[j] == v->expected[j]) 73 | continue; 74 | 75 | fprintf(stderr, 76 | "0x%08x != 0x%08x at %d\n", 77 | out[j], 78 | v->expected[j], 79 | (int) j); 80 | ASSERT(0, "Quarterround failure"); 81 | } 82 | } 83 | } 84 | 85 | 86 | SCRYPT_TEST(salsa20_columnround) { 87 | size_t i; 88 | 89 | /* http://cr.yp.to/snuffle/spec.pdf */ 90 | salsa20_row_test_vector_t tests[] = { 91 | { 92 | .input = { 93 | 0x00000001, 0x00000000, 0x00000000, 0x00000000, 94 | 0x00000001, 0x00000000, 0x00000000, 0x00000000, 95 | 0x00000001, 0x00000000, 0x00000000, 0x00000000, 96 | 0x00000001, 0x00000000, 0x00000000, 0x00000000 97 | }, 98 | .expected = { 99 | 0x10090288, 0x00000000, 0x00000000, 0x00000000, 100 | 0x00000101, 0x00000000, 0x00000000, 0x00000000, 101 | 0x00020401, 0x00000000, 0x00000000, 0x00000000, 102 | 0x40a04001, 0x00000000, 0x00000000, 0x00000000 103 | } 104 | }, 105 | { 106 | .input = { 107 | 0x08521bd6, 0x1fe88837, 0xbb2aa576, 0x3aa26365, 108 | 0xc54c6a5b, 0x2fc74c2f, 0x6dd39cc3, 0xda0a64f6, 109 | 0x90a2f23d, 0x067f95a6, 0x06b35f61, 0x41e4732e, 110 | 0xe859c100, 0xea4d84b7, 0x0f619bff, 0xbc6e965a 111 | }, 112 | .expected = { 113 | 0x8c9d190a, 0xce8e4c90, 0x1ef8e9d3, 0x1326a71a, 114 | 0x90a20123, 0xead3c4f3, 0x63a091a0, 0xf0708d69, 115 | 0x789b010c, 0xd195a681, 0xeb7d5504, 0xa774135c, 116 | 0x481c2027, 0x53a8e4b5, 0x4c1f89c5, 0x3f78c9c8 117 | } 118 | } 119 | }; 120 | 121 | for (i = 0; i < ARRAY_SIZE(tests); i++) { 122 | salsa20_row_test_vector_t* v; 123 | uint32_t out[ARRAY_SIZE(v->input)]; 124 | size_t j; 125 | 126 | v = &tests[i]; 127 | 128 | scrypt_salsa20_columnround(v->input, out); 129 | for (j = 0; j < ARRAY_SIZE(out); j++) { 130 | if (out[j] == v->expected[j]) 131 | continue; 132 | 133 | fprintf(stderr, 134 | "0x%08x != 0x%08x at %d\n", 135 | out[j], 136 | v->expected[j], 137 | (int) j); 138 | ASSERT(0, "Columnround failure"); 139 | } 140 | } 141 | } 142 | 143 | 144 | SCRYPT_TEST(salsa20_doubleround) { 145 | size_t i; 146 | 147 | /* http://cr.yp.to/snuffle/spec.pdf */ 148 | salsa20_row_test_vector_t tests[] = { 149 | { 150 | .input = { 151 | 0x00000001, 0x00000000, 0x00000000, 0x00000000, 152 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 153 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 154 | 0x00000000, 0x00000000, 0x00000000, 0x00000000 155 | }, 156 | .expected = { 157 | 0x8186a22d, 0x0040a284, 0x82479210, 0x06929051, 158 | 0x08000090, 0x02402200, 0x00004000, 0x00800000, 159 | 0x00010200, 0x20400000, 0x08008104, 0x00000000, 160 | 0x20500000, 0xa0000040, 0x0008180a, 0x612a8020 161 | } 162 | }, 163 | { 164 | .input = { 165 | 0xde501066, 0x6f9eb8f7, 0xe4fbbd9b, 0x454e3f57, 166 | 0xb75540d3, 0x43e93a4c, 0x3a6f2aa0, 0x726d6b36, 167 | 0x9243f484, 0x9145d1e8, 0x4fa9d247, 0xdc8dee11, 168 | 0x054bf545, 0x254dd653, 0xd9421b6d, 0x67b276c1 169 | }, 170 | .expected = { 171 | 0xccaaf672, 0x23d960f7, 0x9153e63a, 0xcd9a60d0, 172 | 0x50440492, 0xf07cad19, 0xae344aa0, 0xdf4cfdfc, 173 | 0xca531c29, 0x8e7943db, 0xac1680cd, 0xd503ca00, 174 | 0xa74b2ad6, 0xbc331c5c, 0x1dda24c7, 0xee928277 175 | } 176 | } 177 | }; 178 | 179 | for (i = 0; i < ARRAY_SIZE(tests); i++) { 180 | salsa20_row_test_vector_t* v; 181 | uint32_t out[ARRAY_SIZE(v->input)]; 182 | size_t j; 183 | 184 | v = &tests[i]; 185 | 186 | scrypt_salsa20_doubleround(v->input, out); 187 | for (j = 0; j < ARRAY_SIZE(out); j++) { 188 | if (out[j] == v->expected[j]) 189 | continue; 190 | 191 | fprintf(stderr, 192 | "0x%08x != 0x%08x at %d\n", 193 | out[j], 194 | v->expected[j], 195 | (int) j); 196 | ASSERT(0, "Doubleround failure"); 197 | } 198 | } 199 | } 200 | 201 | 202 | SCRYPT_TEST(salsa20_rowround) { 203 | size_t i; 204 | 205 | /* http://cr.yp.to/snuffle/spec.pdf */ 206 | salsa20_row_test_vector_t tests[] = { 207 | { 208 | .input = { 209 | 0x00000001, 0x00000000, 0x00000000, 0x00000000, 210 | 0x00000001, 0x00000000, 0x00000000, 0x00000000, 211 | 0x00000001, 0x00000000, 0x00000000, 0x00000000, 212 | 0x00000001, 0x00000000, 0x00000000, 0x00000000 213 | }, 214 | .expected = { 215 | 0x08008145, 0x00000080, 0x00010200, 0x20500000, 216 | 0x20100001, 0x00048044, 0x00000080, 0x00010000, 217 | 0x00000001, 0x00002000, 0x80040000, 0x00000000, 218 | 0x00000001, 0x00000200, 0x00402000, 0x88000100 219 | } 220 | }, 221 | { 222 | .input = { 223 | 0x08521bd6, 0x1fe88837, 0xbb2aa576, 0x3aa26365, 224 | 0xc54c6a5b, 0x2fc74c2f, 0x6dd39cc3, 0xda0a64f6, 225 | 0x90a2f23d, 0x067f95a6, 0x06b35f61, 0x41e4732e, 226 | 0xe859c100, 0xea4d84b7, 0x0f619bff, 0xbc6e965a 227 | }, 228 | .expected = { 229 | 0xa890d39d, 0x65d71596, 0xe9487daa, 0xc8ca6a86, 230 | 0x949d2192, 0x764b7754, 0xe408d9b9, 0x7a41b4d1, 231 | 0x3402e183, 0x3c3af432, 0x50669f96, 0xd89ef0a8, 232 | 0x0040ede5, 0xb545fbce, 0xd257ed4f, 0x1818882d 233 | } 234 | } 235 | }; 236 | 237 | for (i = 0; i < ARRAY_SIZE(tests); i++) { 238 | salsa20_row_test_vector_t* v; 239 | uint32_t out[ARRAY_SIZE(v->input)]; 240 | size_t j; 241 | 242 | v = &tests[i]; 243 | 244 | scrypt_salsa20_rowround(v->input, out); 245 | for (j = 0; j < ARRAY_SIZE(out); j++) { 246 | if (out[j] == v->expected[j]) 247 | continue; 248 | 249 | fprintf(stderr, 250 | "0x%08x != 0x%08x at %d\n", 251 | out[j], 252 | v->expected[j], 253 | (int) j); 254 | ASSERT(0, "Rowround failure"); 255 | } 256 | } 257 | } 258 | 259 | SCRYPT_TEST(salsa20_test_vectors) { 260 | size_t i; 261 | 262 | salsa20_test_vector_t tests[] = { 263 | { 264 | .rounds = 10, 265 | .input = { 266 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 267 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 268 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 269 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 270 | }, 271 | .expected = { 272 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 273 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 274 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 275 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 276 | } 277 | }, 278 | { 279 | .rounds = 10, 280 | .input = { 281 | 211,159, 13,115, 76, 55, 82,183, 3,117,222, 37,191,187,234,136, 282 | 49,237,179, 48, 1,106,178,219,175,199,166, 48, 86, 16,179,207, 283 | 31,240, 32, 63, 15, 83, 93,161,116,147, 48,113,238, 55,204, 36, 284 | 79,201,235, 79, 3, 81,156, 47,203, 26,244,243, 88,118,104, 54 285 | }, 286 | .expected = { 287 | 109, 42,178,168,156,240,248,238,168,196,190,203, 26,110,170,154, 288 | 29, 29,150, 26,150, 30,235,249,190,163,251, 48, 69,144, 51, 57, 289 | 118, 40,152,157,180, 57, 27, 94,107, 42,236, 35, 27,111,114,114, 290 | 219,236,232,135,111,155,110, 18, 24,232, 95,158,179, 19, 48,202 291 | } 292 | }, 293 | { 294 | .rounds = 10, 295 | .input = { 296 | 88,118,104, 54, 79,201,235, 79, 3, 81,156, 47,203, 26,244,243, 297 | 191,187,234,136,211,159, 13,115, 76, 55, 82,183, 3,117,222, 37, 298 | 86, 16,179,207, 49,237,179, 48, 1,106,178,219,175,199,166, 48, 299 | 238, 55,204, 36, 31,240, 32, 63, 15, 83, 93,161,116,147, 48,113 300 | }, 301 | .expected = { 302 | 179, 19, 48,202,219,236,232,135,111,155,110, 18, 24,232, 95,158, 303 | 26,110,170,154,109, 42,178,168,156,240,248,238,168,196,190,203, 304 | 69,144, 51, 57, 29, 29,150, 26,150, 30,235,249,190,163,251, 48, 305 | 27,111,114,114,118, 40,152,157,180, 57, 27, 94,107, 42,236, 35 306 | } 307 | }, 308 | 309 | /* https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-03#page-8 */ 310 | { 311 | .rounds = 4, 312 | .input = { 313 | 0x7e, 0x87, 0x9a, 0x21, 0x4f, 0x3e, 0xc9, 0x86, 314 | 0x7c, 0xa9, 0x40, 0xe6, 0x41, 0x71, 0x8f, 0x26, 315 | 0xba, 0xee, 0x55, 0x5b, 0x8c, 0x61, 0xc1, 0xb5, 316 | 0x0d, 0xf8, 0x46, 0x11, 0x6d, 0xcd, 0x3b, 0x1d, 317 | 0xee, 0x24, 0xf3, 0x19, 0xdf, 0x9b, 0x3d, 0x85, 318 | 0x14, 0x12, 0x1e, 0x4b, 0x5a, 0xc5, 0xaa, 0x32, 319 | 0x76, 0x02, 0x1d, 0x29, 0x09, 0xc7, 0x48, 0x29, 320 | 0xed, 0xeb, 0xc6, 0x8d, 0xb8, 0xb8, 0xc2, 0x5e 321 | }, 322 | .expected = { 323 | 0xa4, 0x1f, 0x85, 0x9c, 0x66, 0x08, 0xcc, 0x99, 324 | 0x3b, 0x81, 0xca, 0xcb, 0x02, 0x0c, 0xef, 0x05, 325 | 0x04, 0x4b, 0x21, 0x81, 0xa2, 0xfd, 0x33, 0x7d, 326 | 0xfd, 0x7b, 0x1c, 0x63, 0x96, 0x68, 0x2f, 0x29, 327 | 0xb4, 0x39, 0x31, 0x68, 0xe3, 0xc9, 0xe6, 0xbc, 328 | 0xfe, 0x6b, 0xc5, 0xb7, 0xa0, 0x6d, 0x96, 0xba, 329 | 0xe4, 0x24, 0xcc, 0x10, 0x2c, 0x91, 0x74, 0x5c, 330 | 0x24, 0xad, 0x67, 0x3d, 0xc7, 0x61, 0x8f, 0x81, 331 | } 332 | }, 333 | }; 334 | 335 | for (i = 0; i < ARRAY_SIZE(tests); i++) { 336 | salsa20_test_vector_t* v; 337 | uint8_t out[kSalsa20BlockSize]; 338 | size_t j; 339 | 340 | v = &tests[i]; 341 | 342 | scrypt_salsa20(v->input, v->rounds, out); 343 | for (j = 0; j < ARRAY_SIZE(out); j++) { 344 | if (out[j] == v->expected[j]) 345 | continue; 346 | 347 | fprintf(stderr, 348 | "0x%02x != 0x%02x at %d (test vector: %d)\n", 349 | out[j], 350 | v->expected[j], 351 | (int) j, 352 | (int) i); 353 | ASSERT(0, "salsa20 failure"); 354 | } 355 | } 356 | } 357 | -------------------------------------------------------------------------------- /test/scrypt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "test/test.h" 5 | #include "src/common.h" 6 | #include "src/scrypt.h" 7 | 8 | typedef struct scrypt_block_mix_test_s scrypt_block_mix_test_t; 9 | typedef struct scrypt_ro_mix_test_s scrypt_ro_mix_test_t; 10 | typedef struct scrypt_scrypt_test_s scrypt_scrypt_test_t; 11 | 12 | struct scrypt_block_mix_test_s { 13 | unsigned int r; 14 | uint8_t input[128]; 15 | uint8_t expected[128]; 16 | }; 17 | 18 | struct scrypt_ro_mix_test_s { 19 | unsigned int r; 20 | unsigned int n; 21 | uint8_t input[128]; 22 | uint8_t expected[128]; 23 | }; 24 | 25 | struct scrypt_scrypt_test_s { 26 | const char* passphrase; 27 | const char* salt; 28 | 29 | unsigned int r; 30 | unsigned int n; 31 | unsigned int p; 32 | 33 | uint8_t expected[64]; 34 | }; 35 | 36 | SCRYPT_TEST(scrypt_block_mix) { 37 | size_t i; 38 | 39 | scrypt_block_mix_test_t tests[] = { 40 | /* https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-03#page-8 */ 41 | { 42 | .r = 1, 43 | .input = { 44 | 0xf7, 0xce, 0x0b, 0x65, 0x3d, 0x2d, 0x72, 0xa4, 45 | 0x10, 0x8c, 0xf5, 0xab, 0xe9, 0x12, 0xff, 0xdd, 46 | 0x77, 0x76, 0x16, 0xdb, 0xbb, 0x27, 0xa7, 0x0e, 47 | 0x82, 0x04, 0xf3, 0xae, 0x2d, 0x0f, 0x6f, 0xad, 48 | 0x89, 0xf6, 0x8f, 0x48, 0x11, 0xd1, 0xe8, 0x7b, 49 | 0xcc, 0x3b, 0xd7, 0x40, 0x0a, 0x9f, 0xfd, 0x29, 50 | 0x09, 0x4f, 0x01, 0x84, 0x63, 0x95, 0x74, 0xf3, 51 | 0x9a, 0xe5, 0xa1, 0x31, 0x52, 0x17, 0xbc, 0xd7, 52 | 53 | 0x89, 0x49, 0x91, 0x44, 0x72, 0x13, 0xbb, 0x22, 54 | 0x6c, 0x25, 0xb5, 0x4d, 0xa8, 0x63, 0x70, 0xfb, 55 | 0xcd, 0x98, 0x43, 0x80, 0x37, 0x46, 0x66, 0xbb, 56 | 0x8f, 0xfc, 0xb5, 0xbf, 0x40, 0xc2, 0x54, 0xb0, 57 | 0x67, 0xd2, 0x7c, 0x51, 0xce, 0x4a, 0xd5, 0xfe, 58 | 0xd8, 0x29, 0xc9, 0x0b, 0x50, 0x5a, 0x57, 0x1b, 59 | 0x7f, 0x4d, 0x1c, 0xad, 0x6a, 0x52, 0x3c, 0xda, 60 | 0x77, 0x0e, 0x67, 0xbc, 0xea, 0xaf, 0x7e, 0x89 61 | }, 62 | .expected = { 63 | 0xa4, 0x1f, 0x85, 0x9c, 0x66, 0x08, 0xcc, 0x99, 64 | 0x3b, 0x81, 0xca, 0xcb, 0x02, 0x0c, 0xef, 0x05, 65 | 0x04, 0x4b, 0x21, 0x81, 0xa2, 0xfd, 0x33, 0x7d, 66 | 0xfd, 0x7b, 0x1c, 0x63, 0x96, 0x68, 0x2f, 0x29, 67 | 0xb4, 0x39, 0x31, 0x68, 0xe3, 0xc9, 0xe6, 0xbc, 68 | 0xfe, 0x6b, 0xc5, 0xb7, 0xa0, 0x6d, 0x96, 0xba, 69 | 0xe4, 0x24, 0xcc, 0x10, 0x2c, 0x91, 0x74, 0x5c, 70 | 0x24, 0xad, 0x67, 0x3d, 0xc7, 0x61, 0x8f, 0x81, 71 | 72 | 0x20, 0xed, 0xc9, 0x75, 0x32, 0x38, 0x81, 0xa8, 73 | 0x05, 0x40, 0xf6, 0x4c, 0x16, 0x2d, 0xcd, 0x3c, 74 | 0x21, 0x07, 0x7c, 0xfe, 0x5f, 0x8d, 0x5f, 0xe2, 75 | 0xb1, 0xa4, 0x16, 0x8f, 0x95, 0x36, 0x78, 0xb7, 76 | 0x7d, 0x3b, 0x3d, 0x80, 0x3b, 0x60, 0xe4, 0xab, 77 | 0x92, 0x09, 0x96, 0xe5, 0x9b, 0x4d, 0x53, 0xb6, 78 | 0x5d, 0x2a, 0x22, 0x58, 0x77, 0xd5, 0xed, 0xf5, 79 | 0x84, 0x2c, 0xb9, 0xf1, 0x4e, 0xef, 0xe4, 0x25 80 | } 81 | } 82 | }; 83 | 84 | for (i = 0; i < ARRAY_SIZE(tests); i++) { 85 | scrypt_block_mix_test_t* v; 86 | uint8_t out[sizeof(v->expected)]; 87 | size_t j; 88 | 89 | v = &tests[i]; 90 | 91 | scrypt_block_mix(v->input, v->r, out); 92 | for (j = 0; j < ARRAY_SIZE(out); j++) { 93 | if (out[j] == v->expected[j]) 94 | continue; 95 | 96 | fprintf(stderr, 97 | "0x%02x != 0x%02x at %d (test vector: %d)\n", 98 | out[j], 99 | v->expected[j], 100 | (int) j, 101 | (int) i); 102 | ASSERT(0, "scrypt_block_mix failure"); 103 | } 104 | } 105 | } 106 | 107 | 108 | SCRYPT_TEST(scrypt_ro_mix) { 109 | size_t i; 110 | 111 | scrypt_ro_mix_test_t tests[] = { 112 | /* https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-03#page-8 */ 113 | { 114 | .r = 1, 115 | .n = 16, 116 | .input = { 117 | 0xf7, 0xce, 0x0b, 0x65, 0x3d, 0x2d, 0x72, 0xa4, 118 | 0x10, 0x8c, 0xf5, 0xab, 0xe9, 0x12, 0xff, 0xdd, 119 | 0x77, 0x76, 0x16, 0xdb, 0xbb, 0x27, 0xa7, 0x0e, 120 | 0x82, 0x04, 0xf3, 0xae, 0x2d, 0x0f, 0x6f, 0xad, 121 | 0x89, 0xf6, 0x8f, 0x48, 0x11, 0xd1, 0xe8, 0x7b, 122 | 0xcc, 0x3b, 0xd7, 0x40, 0x0a, 0x9f, 0xfd, 0x29, 123 | 0x09, 0x4f, 0x01, 0x84, 0x63, 0x95, 0x74, 0xf3, 124 | 0x9a, 0xe5, 0xa1, 0x31, 0x52, 0x17, 0xbc, 0xd7, 125 | 0x89, 0x49, 0x91, 0x44, 0x72, 0x13, 0xbb, 0x22, 126 | 0x6c, 0x25, 0xb5, 0x4d, 0xa8, 0x63, 0x70, 0xfb, 127 | 0xcd, 0x98, 0x43, 0x80, 0x37, 0x46, 0x66, 0xbb, 128 | 0x8f, 0xfc, 0xb5, 0xbf, 0x40, 0xc2, 0x54, 0xb0, 129 | 0x67, 0xd2, 0x7c, 0x51, 0xce, 0x4a, 0xd5, 0xfe, 130 | 0xd8, 0x29, 0xc9, 0x0b, 0x50, 0x5a, 0x57, 0x1b, 131 | 0x7f, 0x4d, 0x1c, 0xad, 0x6a, 0x52, 0x3c, 0xda, 132 | 0x77, 0x0e, 0x67, 0xbc, 0xea, 0xaf, 0x7e, 0x89 133 | }, 134 | .expected = { 135 | 0x79, 0xcc, 0xc1, 0x93, 0x62, 0x9d, 0xeb, 0xca, 136 | 0x04, 0x7f, 0x0b, 0x70, 0x60, 0x4b, 0xf6, 0xb6, 137 | 0x2c, 0xe3, 0xdd, 0x4a, 0x96, 0x26, 0xe3, 0x55, 138 | 0xfa, 0xfc, 0x61, 0x98, 0xe6, 0xea, 0x2b, 0x46, 139 | 0xd5, 0x84, 0x13, 0x67, 0x3b, 0x99, 0xb0, 0x29, 140 | 0xd6, 0x65, 0xc3, 0x57, 0x60, 0x1f, 0xb4, 0x26, 141 | 0xa0, 0xb2, 0xf4, 0xbb, 0xa2, 0x00, 0xee, 0x9f, 142 | 0x0a, 0x43, 0xd1, 0x9b, 0x57, 0x1a, 0x9c, 0x71, 143 | 0xef, 0x11, 0x42, 0xe6, 0x5d, 0x5a, 0x26, 0x6f, 144 | 0xdd, 0xca, 0x83, 0x2c, 0xe5, 0x9f, 0xaa, 0x7c, 145 | 0xac, 0x0b, 0x9c, 0xf1, 0xbe, 0x2b, 0xff, 0xca, 146 | 0x30, 0x0d, 0x01, 0xee, 0x38, 0x76, 0x19, 0xc4, 147 | 0xae, 0x12, 0xfd, 0x44, 0x38, 0xf2, 0x03, 0xa0, 148 | 0xe4, 0xe1, 0xc4, 0x7e, 0xc3, 0x14, 0x86, 0x1f, 149 | 0x4e, 0x90, 0x87, 0xcb, 0x33, 0x39, 0x6a, 0x68, 150 | 0x73, 0xe8, 0xf9, 0xd2, 0x53, 0x9a, 0x4b, 0x8e 151 | } 152 | } 153 | }; 154 | 155 | for (i = 0; i < ARRAY_SIZE(tests); i++) { 156 | scrypt_ro_mix_test_t* v; 157 | scrypt_state_t state; 158 | uint8_t out[sizeof(v->expected)]; 159 | size_t j; 160 | 161 | v = &tests[i]; 162 | 163 | state.r = v->r; 164 | state.n = v->n; 165 | state.p = 1; 166 | ASSERT(0 == scrypt_state_init(&state), "Failed to alloc state"); 167 | 168 | scrypt_ro_mix(&state, v->input, out); 169 | scrypt_state_destroy(&state); 170 | 171 | for (j = 0; j < ARRAY_SIZE(out); j++) { 172 | if (out[j] == v->expected[j]) 173 | continue; 174 | 175 | fprintf(stderr, 176 | "0x%02x != 0x%02x at %d (test vector: %d)\n", 177 | out[j], 178 | v->expected[j], 179 | (int) j, 180 | (int) i); 181 | ASSERT(0, "scrypt failure"); 182 | } 183 | } 184 | } 185 | 186 | 187 | SCRYPT_TEST(scrypt) { 188 | size_t i; 189 | 190 | scrypt_scrypt_test_t tests[] = { 191 | /* https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-03#page-10 */ 192 | { 193 | .n = 16, 194 | .r = 1, 195 | .p = 1, 196 | .passphrase = "", 197 | .salt = "", 198 | .expected = { 199 | 0x77, 0xd6, 0x57, 0x62, 0x38, 0x65, 0x7b, 0x20, 200 | 0x3b, 0x19, 0xca, 0x42, 0xc1, 0x8a, 0x04, 0x97, 201 | 0xf1, 0x6b, 0x48, 0x44, 0xe3, 0x07, 0x4a, 0xe8, 202 | 0xdf, 0xdf, 0xfa, 0x3f, 0xed, 0xe2, 0x14, 0x42, 203 | 0xfc, 0xd0, 0x06, 0x9d, 0xed, 0x09, 0x48, 0xf8, 204 | 0x32, 0x6a, 0x75, 0x3a, 0x0f, 0xc8, 0x1f, 0x17, 205 | 0xe8, 0xd3, 0xe0, 0xfb, 0x2e, 0x0d, 0x36, 0x28, 206 | 0xcf, 0x35, 0xe2, 0x0c, 0x38, 0xd1, 0x89, 0x06 207 | } 208 | }, 209 | { 210 | .n = 1024, 211 | .r = 8, 212 | .p = 16, 213 | .passphrase = "password", 214 | .salt = "NaCl", 215 | .expected = { 216 | 0xfd, 0xba, 0xbe, 0x1c, 0x9d, 0x34, 0x72, 0x00, 217 | 0x78, 0x56, 0xe7, 0x19, 0x0d, 0x01, 0xe9, 0xfe, 218 | 0x7c, 0x6a, 0xd7, 0xcb, 0xc8, 0x23, 0x78, 0x30, 219 | 0xe7, 0x73, 0x76, 0x63, 0x4b, 0x37, 0x31, 0x62, 220 | 0x2e, 0xaf, 0x30, 0xd9, 0x2e, 0x22, 0xa3, 0x88, 221 | 0x6f, 0xf1, 0x09, 0x27, 0x9d, 0x98, 0x30, 0xda, 222 | 0xc7, 0x27, 0xaf, 0xb9, 0x4a, 0x83, 0xee, 0x6d, 223 | 0x83, 0x60, 0xcb, 0xdf, 0xa2, 0xcc, 0x06, 0x40 224 | } 225 | }, 226 | { 227 | .n = 16384, 228 | .r = 8, 229 | .p = 1, 230 | .passphrase = "pleaseletmein", 231 | .salt = "SodiumChloride", 232 | .expected = { 233 | 0x70, 0x23, 0xbd, 0xcb, 0x3a, 0xfd, 0x73, 0x48, 234 | 0x46, 0x1c, 0x06, 0xcd, 0x81, 0xfd, 0x38, 0xeb, 235 | 0xfd, 0xa8, 0xfb, 0xba, 0x90, 0x4f, 0x8e, 0x3e, 236 | 0xa9, 0xb5, 0x43, 0xf6, 0x54, 0x5d, 0xa1, 0xf2, 237 | 0xd5, 0x43, 0x29, 0x55, 0x61, 0x3f, 0x0f, 0xcf, 238 | 0x62, 0xd4, 0x97, 0x05, 0x24, 0x2a, 0x9a, 0xf9, 239 | 0xe6, 0x1e, 0x85, 0xdc, 0x0d, 0x65, 0x1e, 0x40, 240 | 0xdf, 0xcf, 0x01, 0x7b, 0x45, 0x57, 0x58, 0x87 241 | } 242 | }, 243 | { 244 | .n = 1048576, 245 | .r = 8, 246 | .p = 1, 247 | .passphrase = "pleaseletmein", 248 | .salt = "SodiumChloride", 249 | .expected = { 250 | 0x21, 0x01, 0xcb, 0x9b, 0x6a, 0x51, 0x1a, 0xae, 251 | 0xad, 0xdb, 0xbe, 0x09, 0xcf, 0x70, 0xf8, 0x81, 252 | 0xec, 0x56, 0x8d, 0x57, 0x4a, 0x2f, 0xfd, 0x4d, 253 | 0xab, 0xe5, 0xee, 0x98, 0x20, 0xad, 0xaa, 0x47, 254 | 0x8e, 0x56, 0xfd, 0x8f, 0x4b, 0xa5, 0xd0, 0x9f, 255 | 0xfa, 0x1c, 0x6d, 0x92, 0x7c, 0x40, 0xf4, 0xc3, 256 | 0x37, 0x30, 0x40, 0x49, 0xe8, 0xa9, 0x52, 0xfb, 257 | 0xcb, 0xf4, 0x5c, 0x6f, 0xa7, 0x7a, 0x41, 0xa4 258 | } 259 | } 260 | }; 261 | 262 | for (i = 0; i < ARRAY_SIZE(tests); i++) { 263 | scrypt_scrypt_test_t* v; 264 | scrypt_state_t state; 265 | uint8_t out[sizeof(v->expected)]; 266 | size_t j; 267 | 268 | v = &tests[i]; 269 | 270 | state.n = v->n; 271 | state.r = v->r; 272 | state.p = v->p; 273 | ASSERT(0 == scrypt_state_init(&state), "Failed to alloc state"); 274 | 275 | scrypt(&state, 276 | (const uint8_t*) v->passphrase, 277 | strlen(v->passphrase), 278 | (const uint8_t*) v->salt, 279 | strlen(v->salt), 280 | out, 281 | sizeof(out)); 282 | scrypt_state_destroy(&state); 283 | 284 | for (j = 0; j < ARRAY_SIZE(out); j++) { 285 | if (out[j] == v->expected[j]) 286 | continue; 287 | 288 | fprintf(stderr, 289 | "0x%02x != 0x%02x at %d (test vector: %d)\n", 290 | out[j], 291 | v->expected[j], 292 | (int) j, 293 | (int) i); 294 | ASSERT(0, "scrypt_ro_mix failure"); 295 | } 296 | } 297 | } 298 | -------------------------------------------------------------------------------- /test/sha256.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "test/test.h" 5 | #include "src/common.h" 6 | #include "src/sha256.h" 7 | 8 | typedef struct scrypt_sha256_test_s scrypt_sha256_test_t; 9 | 10 | struct scrypt_sha256_test_s { 11 | const char* inputs[16]; 12 | uint8_t expected[32]; 13 | }; 14 | 15 | SCRYPT_TEST(sha256) { 16 | size_t i; 17 | 18 | scrypt_sha256_test_t tests[] = { 19 | { 20 | .inputs = { "abc", NULL }, 21 | .expected = { 22 | 0xBA, 0x78, 0x16, 0xBF, 23 | 0x8F, 0x01, 0xCF, 0xEA, 24 | 0x41, 0x41, 0x40, 0xDE, 25 | 0x5D, 0xAE, 0x22, 0x23, 26 | 0xB0, 0x03, 0x61, 0xA3, 27 | 0x96, 0x17, 0x7A, 0x9C, 28 | 0xB4, 0x10, 0xFF, 0x61, 29 | 0xF2, 0x00, 0x15, 0xAD 30 | } 31 | }, 32 | { 33 | .inputs = { "a", "b", "c", NULL }, 34 | .expected = { 35 | 0xBA, 0x78, 0x16, 0xBF, 36 | 0x8F, 0x01, 0xCF, 0xEA, 37 | 0x41, 0x41, 0x40, 0xDE, 38 | 0x5D, 0xAE, 0x22, 0x23, 39 | 0xB0, 0x03, 0x61, 0xA3, 40 | 0x96, 0x17, 0x7A, 0x9C, 41 | 0xB4, 0x10, 0xFF, 0x61, 42 | 0xF2, 0x00, 0x15, 0xAD 43 | } 44 | }, 45 | { 46 | .inputs = { 47 | "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 48 | NULL 49 | }, 50 | .expected = { 51 | 0x24, 0x8D, 0x6A, 0x61, 52 | 0xD2, 0x06, 0x38, 0xB8, 53 | 0xE5, 0xC0, 0x26, 0x93, 54 | 0x0C, 0x3E, 0x60, 0x39, 55 | 0xA3, 0x3C, 0xE4, 0x59, 56 | 0x64, 0xFF, 0x21, 0x67, 57 | 0xF6, 0xEC, 0xED, 0xD4, 58 | 0x19, 0xDB, 0x06, 0xC1 59 | } 60 | }, 61 | { 62 | .inputs = { 63 | "abcdbcdec", 64 | "defdefgefg", 65 | "hfghighijhi", 66 | "jkijkljklmkl", 67 | "mnlmnomnopnopq", 68 | NULL 69 | }, 70 | .expected = { 71 | 0x24, 0x8D, 0x6A, 0x61, 72 | 0xD2, 0x06, 0x38, 0xB8, 73 | 0xE5, 0xC0, 0x26, 0x93, 74 | 0x0C, 0x3E, 0x60, 0x39, 75 | 0xA3, 0x3C, 0xE4, 0x59, 76 | 0x64, 0xFF, 0x21, 0x67, 77 | 0xF6, 0xEC, 0xED, 0xD4, 78 | 0x19, 0xDB, 0x06, 0xC1 79 | } 80 | }, 81 | { 82 | .inputs = { 83 | "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 84 | "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 85 | NULL 86 | }, 87 | .expected = { 88 | 0x59, 0xf1, 0x09, 0xd9, 89 | 0x53, 0x3b, 0x2b, 0x70, 90 | 0xe7, 0xc3, 0xb8, 0x14, 91 | 0xa2, 0xbd, 0x21, 0x8f, 92 | 0x78, 0xea, 0x5d, 0x37, 93 | 0x14, 0x45, 0x5b, 0xc6, 94 | 0x79, 0x87, 0xcf, 0x0d, 95 | 0x66, 0x43, 0x99, 0xcf 96 | } 97 | }, 98 | { 99 | .inputs = { 100 | "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" 101 | "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 102 | NULL 103 | }, 104 | .expected = { 105 | 0x59, 0xf1, 0x09, 0xd9, 106 | 0x53, 0x3b, 0x2b, 0x70, 107 | 0xe7, 0xc3, 0xb8, 0x14, 108 | 0xa2, 0xbd, 0x21, 0x8f, 109 | 0x78, 0xea, 0x5d, 0x37, 110 | 0x14, 0x45, 0x5b, 0xc6, 111 | 0x79, 0x87, 0xcf, 0x0d, 112 | 0x66, 0x43, 0x99, 0xcf 113 | } 114 | }, 115 | { 116 | .inputs = { 117 | "abcdbcdec", 118 | "defdefgefghfghi", 119 | "ghijhijkijkljklmklmnl", 120 | "mnomnopnopq", 121 | "abcdbcdecdefd", 122 | "efgefghfghighijhijkijkljklmklmnlmnomnopnopq", 123 | NULL 124 | }, 125 | .expected = { 126 | 0x59, 0xf1, 0x09, 0xd9, 127 | 0x53, 0x3b, 0x2b, 0x70, 128 | 0xe7, 0xc3, 0xb8, 0x14, 129 | 0xa2, 0xbd, 0x21, 0x8f, 130 | 0x78, 0xea, 0x5d, 0x37, 131 | 0x14, 0x45, 0x5b, 0xc6, 132 | 0x79, 0x87, 0xcf, 0x0d, 133 | 0x66, 0x43, 0x99, 0xcf 134 | } 135 | } 136 | }; 137 | 138 | for (i = 0; i < ARRAY_SIZE(tests); i++) { 139 | scrypt_sha256_test_t* v; 140 | uint8_t out[sizeof(v->expected)]; 141 | size_t j; 142 | scrypt_sha256_t sha256; 143 | const char** chunk; 144 | 145 | v = &tests[i]; 146 | 147 | scrypt_sha256_init(&sha256); 148 | for (chunk = v->inputs; *chunk != NULL; chunk++) 149 | scrypt_sha256_update(&sha256, (uint8_t*) *chunk, strlen(*chunk)); 150 | scrypt_sha256_digest(&sha256, out); 151 | 152 | for (j = 0; j < ARRAY_SIZE(out); j++) { 153 | if (out[j] == v->expected[j]) 154 | continue; 155 | 156 | fprintf(stderr, 157 | "0x%02x != 0x%02x at %d (test vector: %d)\n", 158 | out[j], 159 | v->expected[j], 160 | (int) j, 161 | (int) i); 162 | ASSERT(0, "sha256 failure"); 163 | } 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /test/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "test/test.h" 6 | 7 | static scrypt_test_t* tests; 8 | 9 | 10 | void scrypt_add_test(scrypt_test_t* test) { 11 | test->next = tests; 12 | tests = test; 13 | } 14 | 15 | 16 | int scrypt_compare_hex(const uint8_t* actual, const char* expected) { 17 | int i; 18 | for (i = 0; expected[i] != '\0'; i += 2) { 19 | char hi; 20 | char lo; 21 | uint8_t ch; 22 | 23 | hi = expected[i]; 24 | lo = expected[i + 1]; 25 | if ('0' <= hi && hi <= '9') 26 | ch = hi - '0'; 27 | else 28 | ch = (hi - 'a') + 0xa; 29 | ch <<= 4; 30 | if ('0' <= lo && lo <= '9') 31 | ch |= lo - '0'; 32 | else 33 | ch |= (lo - 'a') + 0xa; 34 | 35 | if (actual[i / 2] != ch) { 36 | fprintf(stderr, 37 | "HEX mismatch: 0x%02x instead of 0x%02x at %d\n", 38 | actual[i / 2], 39 | ch, 40 | i); 41 | return -1; 42 | } 43 | } 44 | 45 | return 0; 46 | } 47 | 48 | 49 | int main(int argc, char** argv) { 50 | scrypt_test_t* cur; 51 | 52 | for (cur = tests; cur != NULL; cur = cur->next) { 53 | if (argc == 2 && strcmp(cur->name, argv[1]) != 0) 54 | continue; 55 | 56 | fprintf(stderr, "===== [%s] =====\n", cur->name); 57 | cur->fn(cur); 58 | } 59 | 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /test/test.h: -------------------------------------------------------------------------------- 1 | #ifndef TEST_TEST_H_ 2 | #define TEST_TEST_H_ 3 | 4 | #include /* NULL */ 5 | #include /* uint8_t */ 6 | 7 | typedef struct scrypt_test_s scrypt_test_t; 8 | typedef void (*scrypt_test_fn)(scrypt_test_t* test); 9 | 10 | struct scrypt_test_s { 11 | const char* name; 12 | scrypt_test_fn fn; 13 | 14 | scrypt_test_t* next; 15 | }; 16 | 17 | void scrypt_add_test(scrypt_test_t* test); 18 | 19 | int scrypt_compare_hex(const uint8_t* actual, const char* expected); 20 | 21 | #if defined(_MSC_VER) 22 | # pragma section(".CRT$XCU", read) 23 | # define SCRYPT_C_CTOR(fn) \ 24 | static void __cdecl fn(void); \ 25 | __declspec(dllexport, allocate(".CRT$XCU")) \ 26 | void (__cdecl*fn ## _)(void) = fn; \ 27 | static void __cdecl fn(void) 28 | #else 29 | # define SCRYPT_C_CTOR(fn) \ 30 | static void fn(void) __attribute__((constructor)); \ 31 | static void fn(void) 32 | #endif 33 | 34 | #define SCRYPT_TEST(NAME) \ 35 | static void scrypt_test_impl_##NAME(scrypt_test_t* test); \ 36 | SCRYPT_C_CTOR(scrypt_test_decl_##NAME) { \ 37 | static scrypt_test_t test = { \ 38 | .name = #NAME, \ 39 | .fn = scrypt_test_impl_##NAME, \ 40 | .next = NULL \ 41 | }; \ 42 | scrypt_add_test(&test); \ 43 | } \ 44 | void scrypt_test_impl_##NAME(scrypt_test_t* test) 45 | 46 | #endif /* TEST_TEST_H_ */ 47 | --------------------------------------------------------------------------------