10 * Name RFC Description
11 * pass P Passphrase, an octet string.
12 * salt S Salt, an octet string.
13 * cost N CPU/Memory cost parameter
14 * bs r Block size parameter.
15 * par p Parallelization parameter
16 * len? dkLen Intended output length
22 typedef void hash_t(uint8_t *out, const uint8_t *in, int len);
26 static int mod(uint8_t out[64], uint8_t in[64])
30 static void copy(uint8_t out[64], uint8_t in[64])
34 static void xor(uint8_t out[64], uint8_t a[64], uint8_t b[64])
40 static void hmac_gen(hash_t hash,
41 uint8_t *out, int nout,
42 const uint8_t *key, int nkey,
43 const uint8_t *msg, int nmsg)
45 uint8_t *fix = alloc0(nout);
46 uint8_t *ipad = alloc0(nout+nmsg);
47 uint8_t *opad = alloc0(nout+nout);
53 memcpy(fix, key, nkey);
55 /* Create pad strings */
56 for (int i = 0; i < nout; i++) {
57 opad[i] = 0x5c ^ fix[i];
58 ipad[i] = 0x36 ^ fix[i];
61 /* Run hashes - hash(o+hash(i+msg)) */
62 memcpy(ipad+nout, msg, nmsg);
63 hash(opad+nout, ipad, nout+nmsg);
64 hash(out, opad, nout+nout);
73 static void pbkdf2_gen(uint8_t *out, int nout,
74 const uint8_t *pass, int npass,
75 const uint8_t *salt, int nsalt,
79 uint8_t *buf = alloc0(nbuf);
80 memcpy(buf, salt, nsalt);
82 const int nptr = 256/8;
84 for (int i = 0; i < nout/nptr; i++) {
85 uint8_t *ptr = &out[i*nptr];
87 buf[nsalt+0] = ((i+1) & 0xFF000000) >> 030;
88 buf[nsalt+1] = ((i+1) & 0x00FF0000) >> 020;
89 buf[nsalt+2] = ((i+1) & 0x0000FF00) >> 010;
90 buf[nsalt+3] = ((i+1) & 0x000000FF) >> 000;
92 hmac_gen(sha256_hash, ptr, nptr, pass, npass, buf, nbuf);
93 for (int j = 1; j < iter; j++)
94 hmac_gen(sha256_hash, ptr, nptr, pass, npass, ptr, nptr);
100 static void pbkdf2_gen_str(uint8_t *out, int nout,
101 const char *pass, const char *salt, int iter)
103 pbkdf2_gen(out, nout,
104 (const uint8_t *)pass, strlen(pass),
105 (const uint8_t *)salt, strlen(salt), iter);
109 static void salsa(uint8_t out[64], uint8_t in[64])
115 static void block_mix(uint8_t *out[64], uint8_t *in[64], int bs)
117 // xor each block with the last block
118 // alternat first/second half for result
121 for (int i = 0; i < 2*r; i++) {
122 int o = bs*(i%2) + (i/2);
123 xor(tmp, in[2*r - 1], in[i]);
128 static void ro_mix(uint8_t *out[128], uint8_t *in[128], int cost, int bs)
130 // generate vector of size cost
131 // randomly collapse vector as output
139 for (i = 0; i < cost; i++) {
140 copy(mixed[i], state);
141 block_mix(state, state);
144 for (i = 0; i < cost; i++) {
145 int j = mod(state, cost);
146 xor(tmp, state, mixed[j]);
147 block_mix(state, tmp);
153 static void scrypt_run(uint8_t out[64],
154 char *pass, char *salt,
155 int cost, int bs, int par, int len)
157 // hash pass/salt into large buffer
158 // mix each buffer (in parallel)
159 // combine bubers into output
161 sha256_hmac(buf, pass, salt, 1, par * 128 * bs);
163 for (i = 0; i < par; i++)
164 buf[i] = ro_mix(buf[i], cost, bs);
166 sha256_hmac(out, pass, buf, 1, len);
171 void scrypt_hash(uint8_t *in, uint8_t *sum)
178 static void test_script(void)
181 const int cost = 1024;
187 const char *pass = "hello";
188 const char *salt = "world";
191 static uint8_t out[32];
194 scrypt_hash(out, pass, salt, par, bs, len);
200 static void test_keygen(void)
202 const uint8_t truth0[] = {
203 0x55, 0xac, 0x04, 0x6e, 0x56, 0xe3, 0x08, 0x9f,
204 0xec, 0x16, 0x91, 0xc2, 0x25, 0x44, 0xb6, 0x05,
205 0xf9, 0x41, 0x85, 0x21, 0x6d, 0xde, 0x04, 0x65,
206 0xe6, 0x8b, 0x9d, 0x57, 0xc2, 0x0d, 0xac, 0xbc,
207 0x49, 0xca, 0x9c, 0xcc, 0xf1, 0x79, 0xb6, 0x45,
208 0x99, 0x16, 0x64, 0xb3, 0x9d, 0x77, 0xef, 0x31,
209 0x7c, 0x71, 0xb8, 0x45, 0xb1, 0xe3, 0x0b, 0xd5,
210 0x09, 0x11, 0x20, 0x41, 0xd3, 0xa1, 0x97, 0x83,
213 const uint8_t truth1[] = {
214 0x4d, 0xdc, 0xd8, 0xf6, 0x0b, 0x98, 0xbe, 0x21,
215 0x83, 0x0c, 0xee, 0x5e, 0xf2, 0x27, 0x01, 0xf9,
216 0x64, 0x1a, 0x44, 0x18, 0xd0, 0x4c, 0x04, 0x14,
217 0xae, 0xff, 0x08, 0x87, 0x6b, 0x34, 0xab, 0x56,
218 0xa1, 0xd4, 0x25, 0xa1, 0x22, 0x58, 0x33, 0x54,
219 0x9a, 0xdb, 0x84, 0x1b, 0x51, 0xc9, 0xb3, 0x17,
220 0x6a, 0x27, 0x2b, 0xde, 0xbb, 0xa1, 0xd0, 0x78,
221 0x47, 0x8f, 0x62, 0xb3, 0x97, 0xf3, 0x3c, 0x8d,
224 uint8_t out0[64] = {};
225 uint8_t out1[64] = {};
227 // output password salt iters
228 pbkdf2_gen_str(out0, 64, "passwd", "salt", 1);
229 //pbkdf2_gen_str(out1, 64, "Password", "NaCl", 80000);
231 hexdump("\nTest #1", NULL, truth0, 64);
232 hexdump("", NULL, out0, 64);
234 hexdump("\nTest #2", NULL, truth1, 64);
235 hexdump("", NULL, out1, 64);
242 void scrypt_test(void)