ruby-scrypt 1.0.0.pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []