ruby-scrypt 1.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Timmy72
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,4 @@
1
+ ruby-scrypt
2
+ ===========
3
+
4
+ Litecoin Scrypt hashing function for Ruby
@@ -0,0 +1,5 @@
1
+ require "mkmf"
2
+
3
+ abort "missing stdint.h header" unless have_header("stdint.h")
4
+
5
+ create_makefile "scrypt/scrypt"
@@ -0,0 +1,686 @@
1
+ /*-
2
+ * Copyright 2009 Colin Percival, 2011 ArtForz
3
+ * All rights reserved.
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions
7
+ * are met:
8
+ * 1. Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * 2. Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ *
14
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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
20
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
+ * SUCH DAMAGE.
25
+ *
26
+ * This file was originally written by Colin Percival as part of the Tarsnap
27
+ * online backup system.
28
+ */
29
+
30
+ #include "percival_scrypt.h"
31
+ #include <stdlib.h>
32
+
33
+ #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
34
+ #include "stdint.h"
35
+ #else
36
+ #include <stdint.h>
37
+ #endif
38
+
39
+ #include <string.h>
40
+
41
+ static __inline uint32_t
42
+ be32dec(const void *pp)
43
+ {
44
+ const uint8_t *p = (uint8_t const *)pp;
45
+
46
+ return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) +
47
+ ((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24));
48
+ }
49
+
50
+ static __inline void
51
+ be32enc(void *pp, uint32_t x)
52
+ {
53
+ uint8_t * p = (uint8_t *)pp;
54
+
55
+ p[3] = x & 0xff;
56
+ p[2] = (x >> 8) & 0xff;
57
+ p[1] = (x >> 16) & 0xff;
58
+ p[0] = (x >> 24) & 0xff;
59
+ }
60
+
61
+ static __inline uint32_t
62
+ le32dec(const void *pp)
63
+ {
64
+ const uint8_t *p = (uint8_t const *)pp;
65
+
66
+ return ((uint32_t)(p[0]) + ((uint32_t)(p[1]) << 8) +
67
+ ((uint32_t)(p[2]) << 16) + ((uint32_t)(p[3]) << 24));
68
+ }
69
+
70
+ static __inline void
71
+ le32enc(void *pp, uint32_t x)
72
+ {
73
+ uint8_t * p = (uint8_t *)pp;
74
+
75
+ p[0] = x & 0xff;
76
+ p[1] = (x >> 8) & 0xff;
77
+ p[2] = (x >> 16) & 0xff;
78
+ p[3] = (x >> 24) & 0xff;
79
+ }
80
+
81
+
82
+ typedef struct SHA256Context {
83
+ uint32_t state[8];
84
+ uint32_t count[2];
85
+ unsigned char buf[64];
86
+ } SHA256_CTX;
87
+
88
+ typedef struct HMAC_SHA256Context {
89
+ SHA256_CTX ictx;
90
+ SHA256_CTX octx;
91
+ } HMAC_SHA256_CTX;
92
+
93
+ /*
94
+ * Encode a length len/4 vector of (uint32_t) into a length len vector of
95
+ * (unsigned char) in big-endian form. Assumes len is a multiple of 4.
96
+ */
97
+ static void
98
+ be32enc_vect(unsigned char *dst, const uint32_t *src, size_t len)
99
+ {
100
+ size_t i;
101
+
102
+ for (i = 0; i < len / 4; i++)
103
+ be32enc(dst + i * 4, src[i]);
104
+ }
105
+
106
+ /*
107
+ * Decode a big-endian length len vector of (unsigned char) into a length
108
+ * len/4 vector of (uint32_t). Assumes len is a multiple of 4.
109
+ */
110
+ static void
111
+ be32dec_vect(uint32_t *dst, const unsigned char *src, size_t len)
112
+ {
113
+ size_t i;
114
+
115
+ for (i = 0; i < len / 4; i++)
116
+ dst[i] = be32dec(src + i * 4);
117
+ }
118
+
119
+ /* Elementary functions used by SHA256 */
120
+ #define Ch(x, y, z) ((x & (y ^ z)) ^ z)
121
+ #define Maj(x, y, z) ((x & (y | z)) | (y & z))
122
+ #define SHR(x, n) (x >> n)
123
+ #define ROTR(x, n) ((x >> n) | (x << (32 - n)))
124
+ #define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
125
+ #define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
126
+ #define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3))
127
+ #define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10))
128
+
129
+ /* SHA256 round function */
130
+ #define RND(a, b, c, d, e, f, g, h, k) \
131
+ t0 = h + S1(e) + Ch(e, f, g) + k; \
132
+ t1 = S0(a) + Maj(a, b, c); \
133
+ d += t0; \
134
+ h = t0 + t1;
135
+
136
+ /* Adjusted round function for rotating state */
137
+ #define RNDr(S, W, i, k) \
138
+ RND(S[(64 - i) % 8], S[(65 - i) % 8], \
139
+ S[(66 - i) % 8], S[(67 - i) % 8], \
140
+ S[(68 - i) % 8], S[(69 - i) % 8], \
141
+ S[(70 - i) % 8], S[(71 - i) % 8], \
142
+ W[i] + k)
143
+
144
+ /*
145
+ * SHA256 block compression function. The 256-bit state is transformed via
146
+ * the 512-bit input block to produce a new state.
147
+ */
148
+ static void
149
+ SHA256_Transform(uint32_t * state, const unsigned char block[64])
150
+ {
151
+ uint32_t W[64];
152
+ uint32_t S[8];
153
+ uint32_t t0, t1;
154
+ int i;
155
+
156
+ /* 1. Prepare message schedule W. */
157
+ be32dec_vect(W, block, 64);
158
+ for (i = 16; i < 64; i++)
159
+ W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16];
160
+
161
+ /* 2. Initialize working variables. */
162
+ memcpy(S, state, 32);
163
+
164
+ /* 3. Mix. */
165
+ RNDr(S, W, 0, 0x428a2f98);
166
+ RNDr(S, W, 1, 0x71374491);
167
+ RNDr(S, W, 2, 0xb5c0fbcf);
168
+ RNDr(S, W, 3, 0xe9b5dba5);
169
+ RNDr(S, W, 4, 0x3956c25b);
170
+ RNDr(S, W, 5, 0x59f111f1);
171
+ RNDr(S, W, 6, 0x923f82a4);
172
+ RNDr(S, W, 7, 0xab1c5ed5);
173
+ RNDr(S, W, 8, 0xd807aa98);
174
+ RNDr(S, W, 9, 0x12835b01);
175
+ RNDr(S, W, 10, 0x243185be);
176
+ RNDr(S, W, 11, 0x550c7dc3);
177
+ RNDr(S, W, 12, 0x72be5d74);
178
+ RNDr(S, W, 13, 0x80deb1fe);
179
+ RNDr(S, W, 14, 0x9bdc06a7);
180
+ RNDr(S, W, 15, 0xc19bf174);
181
+ RNDr(S, W, 16, 0xe49b69c1);
182
+ RNDr(S, W, 17, 0xefbe4786);
183
+ RNDr(S, W, 18, 0x0fc19dc6);
184
+ RNDr(S, W, 19, 0x240ca1cc);
185
+ RNDr(S, W, 20, 0x2de92c6f);
186
+ RNDr(S, W, 21, 0x4a7484aa);
187
+ RNDr(S, W, 22, 0x5cb0a9dc);
188
+ RNDr(S, W, 23, 0x76f988da);
189
+ RNDr(S, W, 24, 0x983e5152);
190
+ RNDr(S, W, 25, 0xa831c66d);
191
+ RNDr(S, W, 26, 0xb00327c8);
192
+ RNDr(S, W, 27, 0xbf597fc7);
193
+ RNDr(S, W, 28, 0xc6e00bf3);
194
+ RNDr(S, W, 29, 0xd5a79147);
195
+ RNDr(S, W, 30, 0x06ca6351);
196
+ RNDr(S, W, 31, 0x14292967);
197
+ RNDr(S, W, 32, 0x27b70a85);
198
+ RNDr(S, W, 33, 0x2e1b2138);
199
+ RNDr(S, W, 34, 0x4d2c6dfc);
200
+ RNDr(S, W, 35, 0x53380d13);
201
+ RNDr(S, W, 36, 0x650a7354);
202
+ RNDr(S, W, 37, 0x766a0abb);
203
+ RNDr(S, W, 38, 0x81c2c92e);
204
+ RNDr(S, W, 39, 0x92722c85);
205
+ RNDr(S, W, 40, 0xa2bfe8a1);
206
+ RNDr(S, W, 41, 0xa81a664b);
207
+ RNDr(S, W, 42, 0xc24b8b70);
208
+ RNDr(S, W, 43, 0xc76c51a3);
209
+ RNDr(S, W, 44, 0xd192e819);
210
+ RNDr(S, W, 45, 0xd6990624);
211
+ RNDr(S, W, 46, 0xf40e3585);
212
+ RNDr(S, W, 47, 0x106aa070);
213
+ RNDr(S, W, 48, 0x19a4c116);
214
+ RNDr(S, W, 49, 0x1e376c08);
215
+ RNDr(S, W, 50, 0x2748774c);
216
+ RNDr(S, W, 51, 0x34b0bcb5);
217
+ RNDr(S, W, 52, 0x391c0cb3);
218
+ RNDr(S, W, 53, 0x4ed8aa4a);
219
+ RNDr(S, W, 54, 0x5b9cca4f);
220
+ RNDr(S, W, 55, 0x682e6ff3);
221
+ RNDr(S, W, 56, 0x748f82ee);
222
+ RNDr(S, W, 57, 0x78a5636f);
223
+ RNDr(S, W, 58, 0x84c87814);
224
+ RNDr(S, W, 59, 0x8cc70208);
225
+ RNDr(S, W, 60, 0x90befffa);
226
+ RNDr(S, W, 61, 0xa4506ceb);
227
+ RNDr(S, W, 62, 0xbef9a3f7);
228
+ RNDr(S, W, 63, 0xc67178f2);
229
+
230
+ /* 4. Mix local working variables into global state */
231
+ for (i = 0; i < 8; i++)
232
+ state[i] += S[i];
233
+
234
+ /* Clean the stack. */
235
+ memset(W, 0, 256);
236
+ memset(S, 0, 32);
237
+ t0 = t1 = 0;
238
+ }
239
+
240
+ static unsigned char PAD[64] = {
241
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
242
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
243
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
244
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
245
+ };
246
+
247
+ /* SHA-256 initialization. Begins a SHA-256 operation. */
248
+ static void
249
+ SHA256_Init(SHA256_CTX * ctx)
250
+ {
251
+
252
+ /* Zero bits processed so far */
253
+ ctx->count[0] = ctx->count[1] = 0;
254
+
255
+ /* Magic initialization constants */
256
+ ctx->state[0] = 0x6A09E667;
257
+ ctx->state[1] = 0xBB67AE85;
258
+ ctx->state[2] = 0x3C6EF372;
259
+ ctx->state[3] = 0xA54FF53A;
260
+ ctx->state[4] = 0x510E527F;
261
+ ctx->state[5] = 0x9B05688C;
262
+ ctx->state[6] = 0x1F83D9AB;
263
+ ctx->state[7] = 0x5BE0CD19;
264
+ }
265
+
266
+ /* Add bytes into the hash */
267
+ static void
268
+ SHA256_Update(SHA256_CTX * ctx, const void *in, size_t len)
269
+ {
270
+ uint32_t bitlen[2];
271
+ uint32_t r;
272
+ const unsigned char *src = in;
273
+
274
+ /* Number of bytes left in the buffer from previous updates */
275
+ r = (ctx->count[1] >> 3) & 0x3f;
276
+
277
+ /* Convert the length into a number of bits */
278
+ bitlen[1] = ((uint32_t)len) << 3;
279
+ bitlen[0] = (uint32_t)(len >> 29);
280
+
281
+ /* Update number of bits */
282
+ if ((ctx->count[1] += bitlen[1]) < bitlen[1])
283
+ ctx->count[0]++;
284
+ ctx->count[0] += bitlen[0];
285
+
286
+ /* Handle the case where we don't need to perform any transforms */
287
+ if (len < 64 - r) {
288
+ memcpy(&ctx->buf[r], src, len);
289
+ return;
290
+ }
291
+
292
+ /* Finish the current block */
293
+ memcpy(&ctx->buf[r], src, 64 - r);
294
+ SHA256_Transform(ctx->state, ctx->buf);
295
+ src += 64 - r;
296
+ len -= 64 - r;
297
+
298
+ /* Perform complete blocks */
299
+ while (len >= 64) {
300
+ SHA256_Transform(ctx->state, src);
301
+ src += 64;
302
+ len -= 64;
303
+ }
304
+
305
+ /* Copy left over data into buffer */
306
+ memcpy(ctx->buf, src, len);
307
+ }
308
+
309
+ /* Add padding and terminating bit-count. */
310
+ static void
311
+ SHA256_Pad(SHA256_CTX * ctx)
312
+ {
313
+ unsigned char len[8];
314
+ uint32_t r, plen;
315
+
316
+ /*
317
+ * Convert length to a vector of bytes -- we do this now rather
318
+ * than later because the length will change after we pad.
319
+ */
320
+ be32enc_vect(len, ctx->count, 8);
321
+
322
+ /* Add 1--64 bytes so that the resulting length is 56 mod 64 */
323
+ r = (ctx->count[1] >> 3) & 0x3f;
324
+ plen = (r < 56) ? (56 - r) : (120 - r);
325
+ SHA256_Update(ctx, PAD, (size_t)plen);
326
+
327
+ /* Add the terminating bit-count */
328
+ SHA256_Update(ctx, len, 8);
329
+ }
330
+
331
+ /*
332
+ * SHA-256 finalization. Pads the input data, exports the hash value,
333
+ * and clears the context state.
334
+ */
335
+ static void
336
+ SHA256_Final(unsigned char digest[32], SHA256_CTX * ctx)
337
+ {
338
+
339
+ /* Add padding */
340
+ SHA256_Pad(ctx);
341
+
342
+ /* Write the hash */
343
+ be32enc_vect(digest, ctx->state, 32);
344
+
345
+ /* Clear the context state */
346
+ memset((void *)ctx, 0, sizeof(*ctx));
347
+ }
348
+
349
+ /* Initialize an HMAC-SHA256 operation with the given key. */
350
+ static void
351
+ HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen)
352
+ {
353
+ unsigned char pad[64];
354
+ unsigned char khash[32];
355
+ const unsigned char * K = _K;
356
+ size_t i;
357
+
358
+ /* If Klen > 64, the key is really SHA256(K). */
359
+ if (Klen > 64) {
360
+ SHA256_Init(&ctx->ictx);
361
+ SHA256_Update(&ctx->ictx, K, Klen);
362
+ SHA256_Final(khash, &ctx->ictx);
363
+ K = khash;
364
+ Klen = 32;
365
+ }
366
+
367
+ /* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */
368
+ SHA256_Init(&ctx->ictx);
369
+ memset(pad, 0x36, 64);
370
+ for (i = 0; i < Klen; i++)
371
+ pad[i] ^= K[i];
372
+ SHA256_Update(&ctx->ictx, pad, 64);
373
+
374
+ /* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */
375
+ SHA256_Init(&ctx->octx);
376
+ memset(pad, 0x5c, 64);
377
+ for (i = 0; i < Klen; i++)
378
+ pad[i] ^= K[i];
379
+ SHA256_Update(&ctx->octx, pad, 64);
380
+
381
+ /* Clean the stack. */
382
+ memset(khash, 0, 32);
383
+ }
384
+
385
+ /* Add bytes to the HMAC-SHA256 operation. */
386
+ static void
387
+ HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void *in, size_t len)
388
+ {
389
+
390
+ /* Feed data to the inner SHA256 operation. */
391
+ SHA256_Update(&ctx->ictx, in, len);
392
+ }
393
+
394
+ /* Finish an HMAC-SHA256 operation. */
395
+ static void
396
+ HMAC_SHA256_Final(unsigned char digest[32], HMAC_SHA256_CTX * ctx)
397
+ {
398
+ unsigned char ihash[32];
399
+
400
+ /* Finish the inner SHA256 operation. */
401
+ SHA256_Final(ihash, &ctx->ictx);
402
+
403
+ /* Feed the inner hash to the outer SHA256 operation. */
404
+ SHA256_Update(&ctx->octx, ihash, 32);
405
+
406
+ /* Finish the outer SHA256 operation. */
407
+ SHA256_Final(digest, &ctx->octx);
408
+
409
+ /* Clean the stack. */
410
+ memset(ihash, 0, 32);
411
+ }
412
+
413
+ /**
414
+ * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
415
+ * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
416
+ * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
417
+ */
418
+ static void
419
+ PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt,
420
+ size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen)
421
+ {
422
+ HMAC_SHA256_CTX PShctx, hctx;
423
+ size_t i;
424
+ uint8_t ivec[4];
425
+ uint8_t U[32];
426
+ uint8_t T[32];
427
+ uint64_t j;
428
+ int k;
429
+ size_t clen;
430
+
431
+ /* Compute HMAC state after processing P and S. */
432
+ HMAC_SHA256_Init(&PShctx, passwd, passwdlen);
433
+ HMAC_SHA256_Update(&PShctx, salt, saltlen);
434
+
435
+ /* Iterate through the blocks. */
436
+ for (i = 0; i * 32 < dkLen; i++) {
437
+ /* Generate INT(i + 1). */
438
+ be32enc(ivec, (uint32_t)(i + 1));
439
+
440
+ /* Compute U_1 = PRF(P, S || INT(i)). */
441
+ memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX));
442
+ HMAC_SHA256_Update(&hctx, ivec, 4);
443
+ HMAC_SHA256_Final(U, &hctx);
444
+
445
+ /* T_i = U_1 ... */
446
+ memcpy(T, U, 32);
447
+
448
+ for (j = 2; j <= c; j++) {
449
+ /* Compute U_j. */
450
+ HMAC_SHA256_Init(&hctx, passwd, passwdlen);
451
+ HMAC_SHA256_Update(&hctx, U, 32);
452
+ HMAC_SHA256_Final(U, &hctx);
453
+
454
+ /* ... xor U_j ... */
455
+ for (k = 0; k < 32; k++)
456
+ T[k] ^= U[k];
457
+ }
458
+
459
+ /* Copy as many bytes as necessary into buf. */
460
+ clen = dkLen - i * 32;
461
+ if (clen > 32)
462
+ clen = 32;
463
+ memcpy(&buf[i * 32], T, clen);
464
+ }
465
+
466
+ /* Clean PShctx, since we never called _Final on it. */
467
+ memset(&PShctx, 0, sizeof(HMAC_SHA256_CTX));
468
+ }
469
+
470
+
471
+ static void blkcpy(void *, void *, size_t);
472
+ static void blkxor(void *, void *, size_t);
473
+ static void salsa20_8(uint32_t[16]);
474
+ static void blockmix_salsa8(uint32_t *, uint32_t *, uint32_t *, size_t);
475
+ static uint64_t integerify(void *, size_t);
476
+ static void smix(uint8_t *, size_t, uint64_t, uint32_t *, uint32_t *);
477
+
478
+ static void
479
+ blkcpy(void * dest, void * src, size_t len)
480
+ {
481
+ size_t * D = dest;
482
+ size_t * S = src;
483
+ size_t L = len / sizeof(size_t);
484
+ size_t i;
485
+
486
+ for (i = 0; i < L; i++)
487
+ D[i] = S[i];
488
+ }
489
+
490
+ static void
491
+ blkxor(void * dest, void * src, size_t len)
492
+ {
493
+ size_t * D = dest;
494
+ size_t * S = src;
495
+ size_t L = len / sizeof(size_t);
496
+ size_t i;
497
+
498
+ for (i = 0; i < L; i++)
499
+ D[i] ^= S[i];
500
+ }
501
+
502
+ /**
503
+ * salsa20_8(B):
504
+ * Apply the salsa20/8 core to the provided block.
505
+ */
506
+ static void
507
+ salsa20_8(uint32_t B[16])
508
+ {
509
+ uint32_t x[16];
510
+ size_t i;
511
+
512
+ blkcpy(x, B, 64);
513
+ for (i = 0; i < 8; i += 2) {
514
+ #define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
515
+ /* Operate on columns. */
516
+ x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9);
517
+ x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18);
518
+
519
+ x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9);
520
+ x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18);
521
+
522
+ x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9);
523
+ x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18);
524
+
525
+ x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9);
526
+ x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18);
527
+
528
+ /* Operate on rows. */
529
+ x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9);
530
+ x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18);
531
+
532
+ x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9);
533
+ x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18);
534
+
535
+ x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9);
536
+ x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18);
537
+
538
+ x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9);
539
+ x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18);
540
+ #undef R
541
+ }
542
+ for (i = 0; i < 16; i++)
543
+ B[i] += x[i];
544
+ }
545
+
546
+ /**
547
+ * blockmix_salsa8(Bin, Bout, X, r):
548
+ * Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r
549
+ * bytes in length; the output Bout must also be the same size. The
550
+ * temporary space X must be 64 bytes.
551
+ */
552
+ static void
553
+ blockmix_salsa8(uint32_t * Bin, uint32_t * Bout, uint32_t * X, size_t r)
554
+ {
555
+ size_t i;
556
+
557
+ /* 1: X <-- B_{2r - 1} */
558
+ blkcpy(X, &Bin[(2 * r - 1) * 16], 64);
559
+
560
+ /* 2: for i = 0 to 2r - 1 do */
561
+ for (i = 0; i < 2 * r; i += 2) {
562
+ /* 3: X <-- H(X \xor B_i) */
563
+ blkxor(X, &Bin[i * 16], 64);
564
+ salsa20_8(X);
565
+
566
+ /* 4: Y_i <-- X */
567
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
568
+ blkcpy(&Bout[i * 8], X, 64);
569
+
570
+ /* 3: X <-- H(X \xor B_i) */
571
+ blkxor(X, &Bin[i * 16 + 16], 64);
572
+ salsa20_8(X);
573
+
574
+ /* 4: Y_i <-- X */
575
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
576
+ blkcpy(&Bout[i * 8 + r * 16], X, 64);
577
+ }
578
+ }
579
+
580
+ /**
581
+ * integerify(B, r):
582
+ * Return the result of parsing B_{2r-1} as a little-endian integer.
583
+ */
584
+ static uint64_t
585
+ integerify(void * B, size_t r)
586
+ {
587
+ uint32_t * X = (void *)((uintptr_t)(B) + (2 * r - 1) * 64);
588
+
589
+ return (((uint64_t)(X[1]) << 32) + X[0]);
590
+ }
591
+
592
+ /**
593
+ * smix(B, r, N, V, XY):
594
+ * Compute B = SMix_r(B, N). The input B must be 128r bytes in length;
595
+ * the temporary storage V must be 128rN bytes in length; the temporary
596
+ * storage XY must be 256r + 64 bytes in length. The value N must be a
597
+ * power of 2 greater than 1. The arrays B, V, and XY must be aligned to a
598
+ * multiple of 64 bytes.
599
+ */
600
+ static void
601
+ smix(uint8_t * B, size_t r, uint64_t N, uint32_t * V, uint32_t * XY)
602
+ {
603
+ uint32_t * X = XY;
604
+ uint32_t * Y = &XY[32 * r];
605
+ uint32_t * Z = &XY[64 * r];
606
+ uint64_t i;
607
+ uint64_t j;
608
+ size_t k;
609
+
610
+ /* 1: X <-- B */
611
+ for (k = 0; k < 32 * r; k++)
612
+ X[k] = le32dec(&B[4 * k]);
613
+
614
+ /* 2: for i = 0 to N - 1 do */
615
+ for (i = 0; i < N; i += 2) {
616
+ /* 3: V_i <-- X */
617
+ blkcpy(&V[i * (32 * r)], X, 128 * r);
618
+
619
+ /* 4: X <-- H(X) */
620
+ blockmix_salsa8(X, Y, Z, r);
621
+
622
+ /* 3: V_i <-- X */
623
+ blkcpy(&V[(i + 1) * (32 * r)], Y, 128 * r);
624
+
625
+ /* 4: X <-- H(X) */
626
+ blockmix_salsa8(Y, X, Z, r);
627
+ }
628
+
629
+ /* 6: for i = 0 to N - 1 do */
630
+ for (i = 0; i < N; i += 2) {
631
+ /* 7: j <-- Integerify(X) mod N */
632
+ j = integerify(X, r) & (N - 1);
633
+
634
+ /* 8: X <-- H(X \xor V_j) */
635
+ blkxor(X, &V[j * (32 * r)], 128 * r);
636
+ blockmix_salsa8(X, Y, Z, r);
637
+
638
+ /* 7: j <-- Integerify(X) mod N */
639
+ j = integerify(Y, r) & (N - 1);
640
+
641
+ /* 8: X <-- H(X \xor V_j) */
642
+ blkxor(Y, &V[j * (32 * r)], 128 * r);
643
+ blockmix_salsa8(Y, X, Z, r);
644
+ }
645
+
646
+ /* 10: B' <-- X */
647
+ for (k = 0; k < 32 * r; k++)
648
+ le32enc(&B[4 * k], X[k]);
649
+ }
650
+
651
+ /* cpu and memory intensive function to transform a 80 byte buffer into a 32 byte output
652
+ scratchpad size needs to be at least 63 + (128 * r * p) + (256 * r + 64) + (128 * r * N) bytes
653
+ */
654
+ void scrypt_1024_1_1_256_sp(const char* input, char* output, char* scratchpad)
655
+ {
656
+ uint8_t * B;
657
+ uint32_t * V;
658
+ uint32_t * XY;
659
+ uint32_t i;
660
+
661
+ const uint32_t N = 1024;
662
+ const uint32_t r = 1;
663
+ const uint32_t p = 1;
664
+
665
+ B = (uint8_t *)(((uintptr_t)(scratchpad) + 63) & ~ (uintptr_t)(63));
666
+ XY = (uint32_t *)(B + (128 * r * p));
667
+ V = (uint32_t *)(B + (128 * r * p) + (256 * r + 64));
668
+
669
+ /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
670
+ PBKDF2_SHA256((const uint8_t*)input, 80, (const uint8_t*)input, 80, 1, B, p * 128 * r);
671
+
672
+ /* 2: for i = 0 to p - 1 do */
673
+ for (i = 0; i < p; i++) {
674
+ /* 3: B_i <-- MF(B_i, N) */
675
+ smix(&B[i * 128 * r], r, N, V, XY);
676
+ }
677
+
678
+ /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
679
+ PBKDF2_SHA256((const uint8_t*)input, 80, B, p * 128 * r, 1, (uint8_t*)output, 32);
680
+ }
681
+
682
+ void scrypt_1024_1_1_256(const char* input, char* output)
683
+ {
684
+ char scratchpad[131583];
685
+ scrypt_1024_1_1_256_sp(input, output, scratchpad);
686
+ }
@@ -0,0 +1,8 @@
1
+ #ifndef SCRYPT_H
2
+ #define SCRYPT_H
3
+
4
+ void scrypt_1024_1_1_256(const char* input, char* output);
5
+ void scrypt_1024_1_1_256_sp(const char* input, char* output, char* scratchpad);
6
+ #define scrypt_scratchpad_size 131583;
7
+
8
+ #endif
@@ -0,0 +1,50 @@
1
+ // The MIT License (MIT)
2
+ //
3
+ // Copyright (c) 2014 Timmy72
4
+ //
5
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ // of this software and associated documentation files (the "Software"), to deal
7
+ // in the Software without restriction, including without limitation the rights
8
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ // copies of the Software, and to permit persons to whom the Software is
10
+ // furnished to do so, subject to the following conditions:
11
+ //
12
+ // The above copyright notice and this permission notice shall be included in all
13
+ // copies or substantial portions of the Software.
14
+ //
15
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ // SOFTWARE.
22
+
23
+ #include <ruby.h>
24
+ #include "percival_scrypt.h"
25
+
26
+ // The business logic -- this is the function we're exposing to Ruby. It returns
27
+ // a Ruby VALUE, and takes two VALUE arguments: the receiver object, and the
28
+ // method parameter. Notes on APIs used here:
29
+ // * rb_str_new(char * str, int len) creates a new Ruby string with the given length
30
+ // * StringValuePtr converts a Ruby String object to a C char *
31
+ static VALUE method_scrypt_hash_bin(VALUE mod, VALUE payload) {
32
+ char output[32];
33
+ Check_Type(payload, T_STRING);
34
+ if (RSTRING_LEN(payload) != 80)
35
+ rb_raise(rb_eArgError, "Invalid argument : wait a 80 length binary string. %ld", RSTRING_LEN(payload));
36
+
37
+ scrypt_1024_1_1_256(StringValuePtr(payload), output);
38
+ return rb_str_new(output, 32);
39
+ }
40
+
41
+ // Initial setup function, takes no arguments and returns nothing. Some API
42
+ // notes:
43
+ // * rb_define_module() creates and returns a top-level module by name
44
+ // * rb_define_singleton_method() take a module, the method name, a reference to
45
+ // a C function, and the method's arity, and exposes the C function as a
46
+ // single method on the given module
47
+ void Init_scrypt() {
48
+ VALUE Scrypt = rb_define_module("Scrypt");
49
+ rb_define_singleton_method(Scrypt, "hash_bin", method_scrypt_hash_bin, 1);
50
+ }
data/lib/scrypt.rb ADDED
@@ -0,0 +1,8 @@
1
+ require "scrypt/scrypt"
2
+
3
+ module Scrypt
4
+ def self.hash_hex( input )
5
+ raise ArgumentError, 'input must be a 160 byte hexa string.' if input.size != 160
6
+ hash_bin( [input].pack("H*") ).reverse.unpack("H*")[0]
7
+ end
8
+ end
@@ -0,0 +1,23 @@
1
+
2
+ require 'minitest/autorun'
3
+
4
+ require 'scrypt'
5
+
6
+ class ScryptTest < MiniTest::Unit::TestCase
7
+ def test_1
8
+ input_hex = "02000000b73417169f9055d2a9e143faa078e0cf97a13c40a5fc117a6b85a2240e5a7d1adc39618a259aa142f2c01e3640f19a68848a7494e75f22a4f068e24ae5a4d8b1b1e518530eb6101b003a269b"
9
+ input_bin = [input_hex].pack("H*")
10
+ output_hex = "000000000003f406a8163444623935c2c4320a7d5508773b3c2de8fee4b14068"
11
+ output_bin = [output_hex].pack("H*").reverse
12
+
13
+ assert_equal output_hex, Scrypt.hash_hex(input_hex)
14
+ assert_equal output_bin, Scrypt.hash_bin(input_bin)
15
+
16
+ assert_raises ArgumentError do
17
+ Scrypt.hash_bin("toto")
18
+ end
19
+ assert_raises ArgumentError do
20
+ Scrypt.hash_hex("toto")
21
+ end
22
+ end
23
+ end
metadata ADDED
@@ -0,0 +1,55 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-scrypt
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0.pre
5
+ prerelease: 6
6
+ platform: ruby
7
+ authors:
8
+ - Vincent Renaudineau
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-03-08 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Litecoin Scrypt hashing function for Ruby. Only allow 80 bytes payload.
15
+ email:
16
+ - vincent.renaudineau@wanadoo.fr
17
+ executables: []
18
+ extensions:
19
+ - ext/scrypt/extconf.rb
20
+ extra_rdoc_files: []
21
+ files:
22
+ - LICENSE
23
+ - README.md
24
+ - ext/scrypt/extconf.rb
25
+ - ext/scrypt/percival_scrypt.c
26
+ - ext/scrypt/percival_scrypt.h
27
+ - ext/scrypt/scrypt.c
28
+ - lib/scrypt.rb
29
+ - test/scrypt_test.rb
30
+ homepage: https://github.com/Timmy72/ruby-scrypt
31
+ licenses:
32
+ - MIT
33
+ post_install_message:
34
+ rdoc_options: []
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ! '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ! '>'
47
+ - !ruby/object:Gem::Version
48
+ version: 1.3.1
49
+ requirements: []
50
+ rubyforge_project:
51
+ rubygems_version: 1.8.25
52
+ signing_key:
53
+ specification_version: 3
54
+ summary: Litecoin Scrypt hashing function for Ruby.
55
+ test_files: []