scrypty 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +22 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +51 -0
- data/Rakefile +1 -0
- data/ext/crypto_aesctr.c +124 -0
- data/ext/crypto_aesctr.h +59 -0
- data/ext/crypto_scrypt-nosse.c.orig +338 -0
- data/ext/crypto_scrypt-ref.c +284 -0
- data/ext/crypto_scrypt-sse.c.orig +366 -0
- data/ext/crypto_scrypt.h +46 -0
- data/ext/extconf.rb +32 -0
- data/ext/memlimit.c +302 -0
- data/ext/memlimit.h +42 -0
- data/ext/ruby_ext.c +239 -0
- data/ext/scrypt_platform.h +6 -0
- data/ext/scryptenc.c +606 -0
- data/ext/scryptenc.h +112 -0
- data/ext/scryptenc_cpuperf.c +185 -0
- data/ext/scryptenc_cpuperf.h +39 -0
- data/ext/sha256.c +412 -0
- data/ext/sha256.h +62 -0
- data/ext/sysendian.h +140 -0
- data/lib/scrypty/version.rb +3 -0
- data/lib/scrypty.rb +2 -0
- data/scrypty.gemspec +20 -0
- metadata +73 -0
data/ext/extconf.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
have_library('rt', 'clock_gettime')
|
4
|
+
have_library('crypto', 'AES_set_encrypt_key')
|
5
|
+
%w{err.h fcntl.h inttypes.h memory.h stddef.h stdint.h stdlib.h string.h strings.h sys/endian.h sys/param.h sys/stat.h sys/time.h sys/types.h termios.h unistd.h}.each do |header|
|
6
|
+
have_header(header)
|
7
|
+
end
|
8
|
+
have_type('size_t')
|
9
|
+
have_type('ssize_t')
|
10
|
+
have_type('uint32_t')
|
11
|
+
have_type('uint64_t')
|
12
|
+
have_type('uint8_t')
|
13
|
+
if have_header('sys/sysinfo.h')
|
14
|
+
if have_type('struct sysinfo', 'sys/sysinfo.h')
|
15
|
+
have_struct_member('struct sysinfo', 'mem_unit', 'sys/sysinfo.h')
|
16
|
+
have_struct_member('struct sysinfo', 'totalram', 'sys/sysinfo.h')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
have_func('malloc')
|
20
|
+
have_func('mmap')
|
21
|
+
have_func('strtod')
|
22
|
+
%w{clock_gettime gettimeofday memmove memset munmap posix_memalign strcspn strdup strerror strtoumax sysinfo}.each do |func|
|
23
|
+
have_func(func)
|
24
|
+
end
|
25
|
+
have_const('be64enc')
|
26
|
+
|
27
|
+
system("sysctl hw.usermem >/dev/null 2>/dev/null")
|
28
|
+
if $?.exitstatus == 0
|
29
|
+
$defs.push("-DHAVE_SYSCTL_HW_USERMEM=1")
|
30
|
+
end
|
31
|
+
create_header
|
32
|
+
create_makefile('scrypty_ext')
|
data/ext/memlimit.c
ADDED
@@ -0,0 +1,302 @@
|
|
1
|
+
/*-
|
2
|
+
* Copyright 2009 Colin Percival
|
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
|
+
#include "scrypt_platform.h"
|
30
|
+
|
31
|
+
#include <sys/types.h>
|
32
|
+
#include <sys/resource.h>
|
33
|
+
|
34
|
+
#ifdef HAVE_SYS_PARAM_H
|
35
|
+
#include <sys/param.h>
|
36
|
+
#endif
|
37
|
+
#ifdef HAVE_SYSCTL_HW_USERMEM
|
38
|
+
#include <sys/sysctl.h>
|
39
|
+
#endif
|
40
|
+
#ifdef HAVE_SYS_SYSINFO_H
|
41
|
+
#include <sys/sysinfo.h>
|
42
|
+
#endif
|
43
|
+
|
44
|
+
#include <errno.h>
|
45
|
+
#include <stddef.h>
|
46
|
+
#include <stdint.h>
|
47
|
+
#include <unistd.h>
|
48
|
+
|
49
|
+
#ifdef DEBUG
|
50
|
+
#include <stdio.h>
|
51
|
+
#endif
|
52
|
+
|
53
|
+
#include "memlimit.h"
|
54
|
+
|
55
|
+
#ifdef HAVE_SYSCTL_HW_USERMEM
|
56
|
+
static int
|
57
|
+
memlimit_sysctl_hw_usermem(size_t * memlimit)
|
58
|
+
{
|
59
|
+
int mib[2];
|
60
|
+
uint8_t usermembuf[8];
|
61
|
+
size_t usermemlen = 8;
|
62
|
+
uint64_t usermem;
|
63
|
+
|
64
|
+
/* Ask the kernel how much RAM we have. */
|
65
|
+
mib[0] = CTL_HW;
|
66
|
+
mib[1] = HW_USERMEM;
|
67
|
+
if (sysctl(mib, 2, usermembuf, &usermemlen, NULL, 0))
|
68
|
+
return (1);
|
69
|
+
|
70
|
+
/*
|
71
|
+
* Parse as either a uint64_t or a uint32_t based on the length of
|
72
|
+
* output the kernel reports having copied out. It appears that all
|
73
|
+
* systems providing a sysctl interface for reading integers copy
|
74
|
+
* them out as system-endian values, so we don't need to worry about
|
75
|
+
* parsing them.
|
76
|
+
*/
|
77
|
+
if (usermemlen == sizeof(uint64_t))
|
78
|
+
usermem = *(uint64_t *)usermembuf;
|
79
|
+
else if (usermemlen == sizeof(uint32_t))
|
80
|
+
usermem = *(uint32_t *)usermembuf;
|
81
|
+
else
|
82
|
+
return (1);
|
83
|
+
|
84
|
+
/* Return the sysctl value, but clamp to SIZE_MAX if necessary. */
|
85
|
+
#if UINT64_MAX > SIZE_MAX
|
86
|
+
if (usermem > SIZE_MAX)
|
87
|
+
*memlimit = SIZE_MAX;
|
88
|
+
else
|
89
|
+
*memlimit = usermem;
|
90
|
+
#else
|
91
|
+
*memlimit = usermem;
|
92
|
+
#endif
|
93
|
+
|
94
|
+
/* Success! */
|
95
|
+
return (0);
|
96
|
+
}
|
97
|
+
#endif
|
98
|
+
|
99
|
+
/* If we don't HAVE_STRUCT_SYSINFO, we can't use sysinfo. */
|
100
|
+
#ifndef HAVE_STRUCT_SYSINFO
|
101
|
+
#undef HAVE_SYSINFO
|
102
|
+
#endif
|
103
|
+
|
104
|
+
/* If we don't HAVE_STRUCT_SYSINFO_TOTALRAM, we can't use sysinfo. */
|
105
|
+
#ifndef HAVE_STRUCT_SYSINFO_TOTALRAM
|
106
|
+
#undef HAVE_SYSINFO
|
107
|
+
#endif
|
108
|
+
|
109
|
+
#ifdef HAVE_SYSINFO
|
110
|
+
static int
|
111
|
+
memlimit_sysinfo(size_t * memlimit)
|
112
|
+
{
|
113
|
+
struct sysinfo info;
|
114
|
+
uint64_t totalmem;
|
115
|
+
|
116
|
+
/* Get information from the kernel. */
|
117
|
+
if (sysinfo(&info))
|
118
|
+
return (1);
|
119
|
+
totalmem = info.totalram;
|
120
|
+
|
121
|
+
/* If we're on a modern kernel, adjust based on mem_unit. */
|
122
|
+
#ifdef HAVE_STRUCT_SYSINFO_MEM_UNIT
|
123
|
+
totalmem = totalmem * info.mem_unit;
|
124
|
+
#endif
|
125
|
+
|
126
|
+
/* Return the value, but clamp to SIZE_MAX if necessary. */
|
127
|
+
#if UINT64_MAX > SIZE_MAX
|
128
|
+
if (totalmem > SIZE_MAX)
|
129
|
+
*memlimit = SIZE_MAX;
|
130
|
+
else
|
131
|
+
*memlimit = totalmem;
|
132
|
+
#else
|
133
|
+
*memlimit = totalmem;
|
134
|
+
#endif
|
135
|
+
|
136
|
+
/* Success! */
|
137
|
+
return (0);
|
138
|
+
}
|
139
|
+
#endif /* HAVE_SYSINFO */
|
140
|
+
|
141
|
+
static int
|
142
|
+
memlimit_rlimit(size_t * memlimit)
|
143
|
+
{
|
144
|
+
struct rlimit rl;
|
145
|
+
uint64_t memrlimit;
|
146
|
+
|
147
|
+
/* Find the least of... */
|
148
|
+
memrlimit = (uint64_t)(-1);
|
149
|
+
|
150
|
+
/* ... RLIMIT_AS... */
|
151
|
+
#ifdef RLIMIT_AS
|
152
|
+
if (getrlimit(RLIMIT_AS, &rl))
|
153
|
+
return (1);
|
154
|
+
if ((rl.rlim_cur != RLIM_INFINITY) &&
|
155
|
+
((uint64_t)rl.rlim_cur < memrlimit))
|
156
|
+
memrlimit = rl.rlim_cur;
|
157
|
+
#endif
|
158
|
+
|
159
|
+
/* ... RLIMIT_DATA... */
|
160
|
+
if (getrlimit(RLIMIT_DATA, &rl))
|
161
|
+
return (1);
|
162
|
+
if ((rl.rlim_cur != RLIM_INFINITY) &&
|
163
|
+
((uint64_t)rl.rlim_cur < memrlimit))
|
164
|
+
memrlimit = rl.rlim_cur;
|
165
|
+
|
166
|
+
/* ... and RLIMIT_RSS. */
|
167
|
+
#ifdef RLIMIT_RSS
|
168
|
+
if (getrlimit(RLIMIT_RSS, &rl))
|
169
|
+
return (1);
|
170
|
+
if ((rl.rlim_cur != RLIM_INFINITY) &&
|
171
|
+
((uint64_t)rl.rlim_cur < memrlimit))
|
172
|
+
memrlimit = rl.rlim_cur;
|
173
|
+
#endif
|
174
|
+
|
175
|
+
/* Return the value, but clamp to SIZE_MAX if necessary. */
|
176
|
+
#if UINT64_MAX > SIZE_MAX
|
177
|
+
if (memrlimit > SIZE_MAX)
|
178
|
+
*memlimit = SIZE_MAX;
|
179
|
+
else
|
180
|
+
*memlimit = memrlimit;
|
181
|
+
#else
|
182
|
+
*memlimit = memrlimit;
|
183
|
+
#endif
|
184
|
+
|
185
|
+
/* Success! */
|
186
|
+
return (0);
|
187
|
+
}
|
188
|
+
|
189
|
+
#ifdef _SC_PHYS_PAGES
|
190
|
+
|
191
|
+
/* Some systems define _SC_PAGESIZE instead of _SC_PAGE_SIZE. */
|
192
|
+
#ifndef _SC_PAGE_SIZE
|
193
|
+
#define _SC_PAGE_SIZE _SC_PAGESIZE
|
194
|
+
#endif
|
195
|
+
|
196
|
+
static int
|
197
|
+
memlimit_sysconf(size_t * memlimit)
|
198
|
+
{
|
199
|
+
long pagesize;
|
200
|
+
long physpages;
|
201
|
+
uint64_t totalmem;
|
202
|
+
|
203
|
+
/* Set errno to 0 in order to distinguish "no limit" from "error". */
|
204
|
+
errno = 0;
|
205
|
+
|
206
|
+
/* Read the two limits. */
|
207
|
+
if (((pagesize = sysconf(_SC_PAGE_SIZE)) == -1) ||
|
208
|
+
((physpages = sysconf(_SC_PHYS_PAGES)) == -1)) {
|
209
|
+
/* Did an error occur? */
|
210
|
+
if (errno != 0)
|
211
|
+
return (1);
|
212
|
+
|
213
|
+
/* If not, there is no limit. */
|
214
|
+
totalmem = (uint64_t)(-1);
|
215
|
+
} else {
|
216
|
+
/* Compute the limit. */
|
217
|
+
totalmem = (uint64_t)(pagesize) * (uint64_t)(physpages);
|
218
|
+
}
|
219
|
+
|
220
|
+
/* Return the value, but clamp to SIZE_MAX if necessary. */
|
221
|
+
#if UINT64_MAX > SIZE_MAX
|
222
|
+
if (totalmem > SIZE_MAX)
|
223
|
+
*memlimit = SIZE_MAX;
|
224
|
+
else
|
225
|
+
*memlimit = totalmem;
|
226
|
+
#else
|
227
|
+
*memlimit = totalmem;
|
228
|
+
#endif
|
229
|
+
|
230
|
+
/* Success! */
|
231
|
+
return (0);
|
232
|
+
}
|
233
|
+
#endif
|
234
|
+
|
235
|
+
int
|
236
|
+
memtouse(size_t maxmem, double maxmemfrac, size_t * memlimit)
|
237
|
+
{
|
238
|
+
size_t sysctl_memlimit, sysinfo_memlimit, rlimit_memlimit;
|
239
|
+
size_t sysconf_memlimit;
|
240
|
+
size_t memlimit_min;
|
241
|
+
size_t memavail;
|
242
|
+
|
243
|
+
/* Get memory limits. */
|
244
|
+
#ifdef HAVE_SYSCTL_HW_USERMEM
|
245
|
+
if (memlimit_sysctl_hw_usermem(&sysctl_memlimit))
|
246
|
+
return (1);
|
247
|
+
#else
|
248
|
+
sysctl_memlimit = (size_t)(-1);
|
249
|
+
#endif
|
250
|
+
#ifdef HAVE_SYSINFO
|
251
|
+
if (memlimit_sysinfo(&sysinfo_memlimit))
|
252
|
+
return (1);
|
253
|
+
#else
|
254
|
+
sysinfo_memlimit = (size_t)(-1);
|
255
|
+
#endif
|
256
|
+
if (memlimit_rlimit(&rlimit_memlimit))
|
257
|
+
return (1);
|
258
|
+
#ifdef _SC_PHYS_PAGES
|
259
|
+
if (memlimit_sysconf(&sysconf_memlimit))
|
260
|
+
return (1);
|
261
|
+
#else
|
262
|
+
sysconf_memlimit = (size_t)(-1);
|
263
|
+
#endif
|
264
|
+
|
265
|
+
#ifdef DEBUG
|
266
|
+
fprintf(stderr, "Memory limits are %zu %zu %zu %zu\n",
|
267
|
+
sysctl_memlimit, sysinfo_memlimit, rlimit_memlimit,
|
268
|
+
sysconf_memlimit);
|
269
|
+
#endif
|
270
|
+
|
271
|
+
/* Find the smallest of them. */
|
272
|
+
memlimit_min = (size_t)(-1);
|
273
|
+
if (memlimit_min > sysctl_memlimit)
|
274
|
+
memlimit_min = sysctl_memlimit;
|
275
|
+
if (memlimit_min > sysinfo_memlimit)
|
276
|
+
memlimit_min = sysinfo_memlimit;
|
277
|
+
if (memlimit_min > rlimit_memlimit)
|
278
|
+
memlimit_min = rlimit_memlimit;
|
279
|
+
if (memlimit_min > sysconf_memlimit)
|
280
|
+
memlimit_min = sysconf_memlimit;
|
281
|
+
|
282
|
+
/* Only use the specified fraction of the available memory. */
|
283
|
+
if ((maxmemfrac > 0.5) || (maxmemfrac == 0.0))
|
284
|
+
maxmemfrac = 0.5;
|
285
|
+
memavail = maxmemfrac * memlimit_min;
|
286
|
+
|
287
|
+
/* Don't use more than the specified maximum. */
|
288
|
+
if ((maxmem > 0) && (memavail > maxmem))
|
289
|
+
memavail = maxmem;
|
290
|
+
|
291
|
+
/* But always allow at least 1 MiB. */
|
292
|
+
if (memavail < 1048576)
|
293
|
+
memavail = 1048576;
|
294
|
+
|
295
|
+
#ifdef DEBUG
|
296
|
+
fprintf(stderr, "Allowing up to %zu memory to be used\n", memavail);
|
297
|
+
#endif
|
298
|
+
|
299
|
+
/* Return limit via the provided pointer. */
|
300
|
+
*memlimit = memavail;
|
301
|
+
return (0);
|
302
|
+
}
|
data/ext/memlimit.h
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
/*-
|
2
|
+
* Copyright 2009 Colin Percival
|
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
|
+
#ifndef _MEMLIMIT_H_
|
30
|
+
#define _MEMLIMIT_H_
|
31
|
+
|
32
|
+
#include <stddef.h>
|
33
|
+
|
34
|
+
/**
|
35
|
+
* memtouse(maxmem, maxmemfrac, memlimit):
|
36
|
+
* Examine the system and return via memlimit the amount of RAM which should
|
37
|
+
* be used -- the specified fraction of the available RAM, but no more than
|
38
|
+
* maxmem, and no less than 1MiB.
|
39
|
+
*/
|
40
|
+
int memtouse(size_t, double, size_t *);
|
41
|
+
|
42
|
+
#endif /* !_MEMLIMIT_H_ */
|
data/ext/ruby_ext.c
ADDED
@@ -0,0 +1,239 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <stdio.h>
|
3
|
+
#include "scryptenc.h"
|
4
|
+
|
5
|
+
VALUE mScrypty;
|
6
|
+
|
7
|
+
VALUE eScryptyError;
|
8
|
+
VALUE eMemoryLimitError;
|
9
|
+
VALUE eClockTimeError;
|
10
|
+
VALUE eDerivedKeyError;
|
11
|
+
VALUE eSaltError;
|
12
|
+
VALUE eOpenSSLError;
|
13
|
+
/* Use NoMemoryError */
|
14
|
+
VALUE eInvalidBlockError;
|
15
|
+
VALUE eUnrecognizedFormatError;
|
16
|
+
VALUE eNotEnoughMemoryError;
|
17
|
+
VALUE eTooMuchTimeError;
|
18
|
+
VALUE eIncorrectPasswordError;
|
19
|
+
VALUE eWriteError;
|
20
|
+
VALUE eReadError;
|
21
|
+
|
22
|
+
/**
|
23
|
+
* Return codes from scrypt(enc|dec)_(buf|file):
|
24
|
+
* 0 success
|
25
|
+
* 1 getrlimit or sysctl(hw.usermem) failed
|
26
|
+
* 2 clock_getres or clock_gettime failed
|
27
|
+
* 3 error computing derived key
|
28
|
+
* 4 could not read salt from /dev/urandom
|
29
|
+
* 5 error in OpenSSL
|
30
|
+
* 6 malloc failed
|
31
|
+
* 7 data is not a valid scrypt-encrypted block
|
32
|
+
* 8 unrecognized scrypt format
|
33
|
+
* 9 decrypting file would take too much memory
|
34
|
+
* 10 decrypting file would take too long
|
35
|
+
* 11 password is incorrect
|
36
|
+
* 12 error writing output file
|
37
|
+
* 13 error reading input file
|
38
|
+
*/
|
39
|
+
static void
|
40
|
+
raise_scrypty_error(errorcode)
|
41
|
+
int errorcode;
|
42
|
+
{
|
43
|
+
switch (errorcode) {
|
44
|
+
case 1:
|
45
|
+
rb_raise(eMemoryLimitError, "couldn't get memory limit");
|
46
|
+
break;
|
47
|
+
case 2:
|
48
|
+
rb_raise(eClockTimeError, "couldn't determine CPU speed");
|
49
|
+
break;
|
50
|
+
case 3:
|
51
|
+
rb_raise(eDerivedKeyError, "couldn't compute derived key");
|
52
|
+
break;
|
53
|
+
case 4:
|
54
|
+
rb_raise(eSaltError, "couldn't read salt from /dev/urandom");
|
55
|
+
break;
|
56
|
+
case 5:
|
57
|
+
rb_raise(eOpenSSLError, "OpenSSL error");
|
58
|
+
break;
|
59
|
+
case 6:
|
60
|
+
rb_raise(rb_eNoMemError, "couldn't allocate memory");
|
61
|
+
break;
|
62
|
+
case 7:
|
63
|
+
rb_raise(eInvalidBlockError, "data is not a valid scrypt-encrypted block");
|
64
|
+
break;
|
65
|
+
case 8:
|
66
|
+
rb_raise(eUnrecognizedFormatError, "unrecognized scrypt format");
|
67
|
+
break;
|
68
|
+
case 9:
|
69
|
+
rb_raise(eNotEnoughMemoryError, "decrypting would take too much memory");
|
70
|
+
break;
|
71
|
+
case 10:
|
72
|
+
rb_raise(eTooMuchTimeError, "decrypting would take too long");
|
73
|
+
break;
|
74
|
+
case 11:
|
75
|
+
rb_raise(eIncorrectPasswordError, "password is incorrect");
|
76
|
+
break;
|
77
|
+
case 12:
|
78
|
+
rb_raise(eWriteError, "error writing output file");
|
79
|
+
break;
|
80
|
+
case 13:
|
81
|
+
rb_raise(eReadError, "error reading input file");
|
82
|
+
break;
|
83
|
+
}
|
84
|
+
}
|
85
|
+
|
86
|
+
VALUE
|
87
|
+
scrypty_encrypt(rb_obj, rb_data, rb_password, rb_maxmem, rb_maxmemfrac, rb_maxtime)
|
88
|
+
VALUE rb_obj;
|
89
|
+
VALUE rb_data;
|
90
|
+
VALUE rb_password;
|
91
|
+
VALUE rb_maxmem;
|
92
|
+
VALUE rb_maxmemfrac;
|
93
|
+
VALUE rb_maxtime;
|
94
|
+
{
|
95
|
+
VALUE rb_out;
|
96
|
+
char *data, *password, *out;
|
97
|
+
size_t data_len, password_len, out_len, maxmem;
|
98
|
+
double maxmemfrac, maxtime;
|
99
|
+
int errorcode;
|
100
|
+
|
101
|
+
if (TYPE(rb_data) == T_STRING) {
|
102
|
+
data = RSTRING_PTR(rb_data);
|
103
|
+
data_len = (size_t) RSTRING_LEN(rb_data);
|
104
|
+
}
|
105
|
+
else {
|
106
|
+
rb_raise(rb_eTypeError, "first argument (data) must be a String");
|
107
|
+
}
|
108
|
+
|
109
|
+
if (TYPE(rb_password) == T_STRING) {
|
110
|
+
password = RSTRING_PTR(rb_password);
|
111
|
+
password_len = (size_t) RSTRING_LEN(rb_password);
|
112
|
+
}
|
113
|
+
else {
|
114
|
+
rb_raise(rb_eTypeError, "second argument (password) must be a String");
|
115
|
+
}
|
116
|
+
|
117
|
+
if (TYPE(rb_maxmem) == T_FIXNUM) {
|
118
|
+
maxmem = FIX2INT(rb_maxmem);
|
119
|
+
}
|
120
|
+
else {
|
121
|
+
rb_raise(rb_eTypeError, "third argument (maxmem) must be a Fixnum");
|
122
|
+
}
|
123
|
+
|
124
|
+
if (FIXNUM_P(rb_maxmemfrac) || TYPE(rb_maxmemfrac) == T_FLOAT) {
|
125
|
+
maxmemfrac = NUM2DBL(rb_maxmemfrac);
|
126
|
+
}
|
127
|
+
else {
|
128
|
+
rb_raise(rb_eTypeError, "fourth argument (maxmemfrac) must be a Fixnum or Float");
|
129
|
+
}
|
130
|
+
|
131
|
+
if (FIXNUM_P(rb_maxtime) || TYPE(rb_maxtime) == T_FLOAT) {
|
132
|
+
maxtime = NUM2DBL(rb_maxtime);
|
133
|
+
}
|
134
|
+
else {
|
135
|
+
rb_raise(rb_eTypeError, "fifth argument (maxtime) must be a Fixnum or Float");
|
136
|
+
}
|
137
|
+
|
138
|
+
out_len = data_len + 128;
|
139
|
+
rb_out = rb_str_new(NULL, out_len);
|
140
|
+
out = RSTRING_PTR(rb_out);
|
141
|
+
|
142
|
+
errorcode = scryptenc_buf((const uint8_t *) data, data_len,
|
143
|
+
(uint8_t *) out, (const uint8_t *) password, password_len,
|
144
|
+
maxmem, maxmemfrac, maxtime);
|
145
|
+
if (errorcode) {
|
146
|
+
raise_scrypt_error(errorcode);
|
147
|
+
}
|
148
|
+
rb_str_set_len(rb_out, out_len);
|
149
|
+
|
150
|
+
return rb_out;
|
151
|
+
}
|
152
|
+
|
153
|
+
VALUE
|
154
|
+
scrypty_decrypt(rb_obj, rb_data, rb_password, rb_maxmem, rb_maxmemfrac, rb_maxtime)
|
155
|
+
VALUE rb_obj;
|
156
|
+
VALUE rb_data;
|
157
|
+
VALUE rb_password;
|
158
|
+
VALUE rb_maxmem;
|
159
|
+
VALUE rb_maxmemfrac;
|
160
|
+
VALUE rb_maxtime;
|
161
|
+
{
|
162
|
+
VALUE rb_out;
|
163
|
+
char *data, *password, *out;
|
164
|
+
size_t data_len, password_len, out_len, maxmem;
|
165
|
+
double maxmemfrac, maxtime;
|
166
|
+
int errorcode;
|
167
|
+
|
168
|
+
if (TYPE(rb_data) == T_STRING) {
|
169
|
+
data = RSTRING_PTR(rb_data);
|
170
|
+
data_len = (size_t) RSTRING_LEN(rb_data);
|
171
|
+
}
|
172
|
+
else {
|
173
|
+
rb_raise(rb_eTypeError, "first argument (data) must be a String");
|
174
|
+
}
|
175
|
+
|
176
|
+
if (TYPE(rb_password) == T_STRING) {
|
177
|
+
password = RSTRING_PTR(rb_password);
|
178
|
+
password_len = (size_t) RSTRING_LEN(rb_password);
|
179
|
+
}
|
180
|
+
else {
|
181
|
+
rb_raise(rb_eTypeError, "second argument (password) must be a String");
|
182
|
+
}
|
183
|
+
|
184
|
+
if (TYPE(rb_maxmem) == T_FIXNUM) {
|
185
|
+
maxmem = FIX2INT(rb_maxmem);
|
186
|
+
}
|
187
|
+
else {
|
188
|
+
rb_raise(rb_eTypeError, "third argument (maxmem) must be a Fixnum");
|
189
|
+
}
|
190
|
+
|
191
|
+
if (FIXNUM_P(rb_maxmemfrac) || TYPE(rb_maxmemfrac) == T_FLOAT) {
|
192
|
+
maxmemfrac = NUM2DBL(rb_maxmemfrac);
|
193
|
+
}
|
194
|
+
else {
|
195
|
+
rb_raise(rb_eTypeError, "fourth argument (maxmemfrac) must be a Fixnum or Float");
|
196
|
+
}
|
197
|
+
|
198
|
+
if (FIXNUM_P(rb_maxtime) || TYPE(rb_maxtime) == T_FLOAT) {
|
199
|
+
maxtime = NUM2DBL(rb_maxtime);
|
200
|
+
}
|
201
|
+
else {
|
202
|
+
rb_raise(rb_eTypeError, "fifth argument (maxtime) must be a Fixnum or Float");
|
203
|
+
}
|
204
|
+
|
205
|
+
rb_out = rb_str_new(NULL, data_len);
|
206
|
+
out = RSTRING_PTR(rb_out);
|
207
|
+
|
208
|
+
errorcode = scryptdec_buf((const uint8_t *) data, data_len,
|
209
|
+
(uint8_t *) out, &out_len, (const uint8_t *) password, password_len,
|
210
|
+
maxmem, maxmemfrac, maxtime);
|
211
|
+
if (errorcode) {
|
212
|
+
raise_scrypty_error(errorcode);
|
213
|
+
}
|
214
|
+
rb_str_set_len(rb_out, out_len);
|
215
|
+
|
216
|
+
return rb_out;
|
217
|
+
}
|
218
|
+
|
219
|
+
void
|
220
|
+
Init_scrypty_ext(void)
|
221
|
+
{
|
222
|
+
mScrypty = rb_define_module("Scrypty");
|
223
|
+
rb_define_singleton_method(mScrypty, "encrypt", scrypty_encrypt, 5);
|
224
|
+
rb_define_singleton_method(mScrypty, "decrypt", scrypty_decrypt, 5);
|
225
|
+
|
226
|
+
eScryptyError = rb_define_class_under(mScrypty, "Exception", rb_eException);
|
227
|
+
eMemoryLimitError = rb_define_class_under(mScrypty, "MemoryLimitError", eScryptyError);
|
228
|
+
eClockTimeError = rb_define_class_under(mScrypty, "ClockTimeError", eScryptyError);
|
229
|
+
eDerivedKeyError = rb_define_class_under(mScrypty, "DerivedKeyError", eScryptyError);
|
230
|
+
eSaltError = rb_define_class_under(mScrypty, "SaltError", eScryptyError);
|
231
|
+
eOpenSSLError = rb_define_class_under(mScrypty, "OpenSSLError", eScryptyError);
|
232
|
+
eInvalidBlockError = rb_define_class_under(mScrypty, "InvalidBlockError", eScryptyError);
|
233
|
+
eUnrecognizedFormatError = rb_define_class_under(mScrypty, "UnrecognizedFormatError", eScryptyError);
|
234
|
+
eNotEnoughMemoryError = rb_define_class_under(mScrypty, "NotEnoughMemoryError", eScryptyError);
|
235
|
+
eTooMuchTimeError = rb_define_class_under(mScrypty, "TooMuchTimeError", eScryptyError);
|
236
|
+
eIncorrectPasswordError = rb_define_class_under(mScrypty, "IncorrectPasswordError", eScryptyError);
|
237
|
+
eWriteError = rb_define_class_under(mScrypty, "WriteError", eScryptyError);
|
238
|
+
eReadError = rb_define_class_under(mScrypty, "ReadError", eScryptyError);
|
239
|
+
}
|