sysrandom 1.0.0-java
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.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.rspec +2 -0
- data/.rubocop.yml +34 -0
- data/.travis.yml +9 -0
- data/CHANGES.md +3 -0
- data/Gemfile +10 -0
- data/LICENSE.txt +15 -0
- data/README.md +112 -0
- data/Rakefile +21 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/ext/sysrandom/extconf.rb +4 -0
- data/ext/sysrandom/randombytes_sysrandom.c +275 -0
- data/ext/sysrandom/sysrandom_ext.c +77 -0
- data/lib/sysrandom/securerandom.rb +7 -0
- data/lib/sysrandom/version.rb +3 -0
- data/lib/sysrandom.rb +64 -0
- data/sysrandom.gemspec +26 -0
- metadata +62 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e24cd46b6417b143899bcec5491ded930fdff1b9
|
4
|
+
data.tar.gz: b4c37eded4ec30f2860538b3db047f3b12b5db78
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d91f8eb67cfa6c2a070fd06e7e15de5379e172d33d248eecce50e592fc8b1ebf1ab9d0bc22cfaef5380c34da9b8a8f979ee466406ece07270c158bead8976ee9
|
7
|
+
data.tar.gz: 708ede372c5493228dcdc63237c398a814df9b4ce47baac08dce981397346f945580cf29931c1dcd6cac2ff9afdb0c07b3d3ae208ae6e519499e3fe630ca40f6
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
AllCops:
|
2
|
+
DisplayCopNames: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# Style
|
6
|
+
#
|
7
|
+
|
8
|
+
LineLength:
|
9
|
+
Max: 128
|
10
|
+
|
11
|
+
Style/StringLiterals:
|
12
|
+
EnforcedStyle: double_quotes
|
13
|
+
|
14
|
+
Style/SpaceBeforeFirstArg:
|
15
|
+
Enabled: false
|
16
|
+
|
17
|
+
Style/ConditionalAssignment:
|
18
|
+
Enabled: false
|
19
|
+
|
20
|
+
#
|
21
|
+
# Metrics
|
22
|
+
#
|
23
|
+
|
24
|
+
Metrics/MethodLength:
|
25
|
+
Max: 22
|
26
|
+
|
27
|
+
Metrics/AbcSize:
|
28
|
+
Max: 20
|
29
|
+
|
30
|
+
AllCops:
|
31
|
+
Include:
|
32
|
+
- '**/Rakefile'
|
33
|
+
Exclude:
|
34
|
+
- 'spec/**/*'
|
data/.travis.yml
ADDED
data/CHANGES.md
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
Copyright (c) 2013-2016
|
2
|
+
Frank Denis <j at pureftpd dot org>
|
3
|
+
Tony Arcieri <bascule at gmail dot com>
|
4
|
+
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
8
|
+
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
10
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
11
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
12
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
13
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
14
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
15
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
# Sysrandom
|
2
|
+
|
3
|
+
[](https://rubygems.org/gems/sysrandom)
|
4
|
+
[](https://travis-ci.org/cryptosphere/sysrandom)
|
5
|
+
[](https://github.com/cryptosphere/sysrandom/blob/master/LICENSE.txt)
|
6
|
+
|
7
|
+
Secure random number generation for Ruby using system RNG facilities e.g. `/dev/urandom`, `getrandom(2)`
|
8
|
+
|
9
|
+
## Description
|
10
|
+
|
11
|
+
[Concerns have been raised][concerns] about the current implementation of Ruby's built-in
|
12
|
+
`SecureRandom` functionality, as it presently leverages the poorly reputed OpenSSL RNG.
|
13
|
+
|
14
|
+
In cryptography circles, [the prevailing advice is to use OS RNG functionality][/dev/urandom],
|
15
|
+
namely `/dev/urandom` or equivalent calls which use an OS-level CSPRNG to
|
16
|
+
produce random numbers.
|
17
|
+
|
18
|
+
This gem provides an easy-to-install repackaging of the `randombytes`
|
19
|
+
functionality from [libsodium] for the purpose of generating secure random
|
20
|
+
numbers trustworthy for use in cryptographic contexts, such as generating
|
21
|
+
cryptographic keys, initialization vectors, or nonces.
|
22
|
+
|
23
|
+
The following random number generators are utilized:
|
24
|
+
|
25
|
+
| OS | RNG |
|
26
|
+
|---------|-------------------------------------------------------------------|
|
27
|
+
| Linux | [getrandom(2)] if available, otherwise [/dev/urandom] |
|
28
|
+
| Windows | [RtlGenRandom] |
|
29
|
+
| OpenBSD | [arc4random(3)] with ChaCha20 CSPRNG (not RC4) |
|
30
|
+
| JRuby | [SecureRandom.getInstanceStrong] if available, otherwise SHA1PRNG |
|
31
|
+
| Others | [/dev/urandom] |
|
32
|
+
|
33
|
+
[concerns]: https://bugs.ruby-lang.org/issues/9569
|
34
|
+
[libsodium]: https://github.com/jedisct1/libsodium
|
35
|
+
[getrandom(2)]: http://man7.org/linux/man-pages/man2/getrandom.2.html
|
36
|
+
[/dev/urandom]: http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/
|
37
|
+
[RtlGenRandom]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa387694(v=vs.85).aspx
|
38
|
+
[arc4random(3)]: http://man.openbsd.org/arc4random.3
|
39
|
+
[SecureRandom.getInstanceStrong]: https://docs.oracle.com/javase/8/docs/api/java/security/SecureRandom.html#getInstanceStrong--
|
40
|
+
|
41
|
+
## Supported Platforms
|
42
|
+
|
43
|
+
Sysrandom is tested on the following Ruby implementations:
|
44
|
+
|
45
|
+
* Ruby (MRI) 2.0, 2.1, 2.2, 2.3
|
46
|
+
* JRuby 9.1.1.0
|
47
|
+
|
48
|
+
## Installation
|
49
|
+
|
50
|
+
Add this line to your application's Gemfile:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
gem 'sysrandom'
|
54
|
+
```
|
55
|
+
|
56
|
+
And then execute:
|
57
|
+
|
58
|
+
$ bundle
|
59
|
+
|
60
|
+
Or install it yourself as:
|
61
|
+
|
62
|
+
$ gem install sysrandom
|
63
|
+
|
64
|
+
## Usage
|
65
|
+
|
66
|
+
`Sysrandom` aims to be API-compatible with Ruby's built-in `SecureRandom` class,
|
67
|
+
but always prefers OS-level RNG wherever it's available:
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
>> Sysrandom.random_number(42)
|
71
|
+
=> 15
|
72
|
+
>> Sysrandom.random_bytes(32)
|
73
|
+
=> "\xD6J\xB3\xD2\x8B\x7F*9D\xB7\xF9\xEA\xE2\\\xAAH\tV#\xEC\x84\xE3E\r\x97\xB9\b\xFCH\x17\xA0\v"
|
74
|
+
>> Sysrandom.base64(32)
|
75
|
+
=> "WXPkxfAuLRpnI6Z4zFb4E+MIenx6w6vKhe01+rMPuIQ="
|
76
|
+
>> Sysrandom.urlsafe_base64(32)
|
77
|
+
=> "37rsMfR4X8g7Bb-uDJEekRHnB3r_7nO03cv52ilaWqE="
|
78
|
+
>> Sysrandom.hex(32)
|
79
|
+
=> "c950496ce200abf7d18eb1414e9206c6335f971a37d0394114f56439b59831ba"
|
80
|
+
>> Sysrandom.uuid
|
81
|
+
=> "391c6f52-8017-4838-9790-131a9b979c63"
|
82
|
+
```
|
83
|
+
|
84
|
+
* [SecureRandom API docs](http://ruby-doc.org/stdlib-2.0.0/libdoc/securerandom/rdoc/SecureRandom.html)
|
85
|
+
|
86
|
+
## Patching SecureRandom with Sysrandom
|
87
|
+
|
88
|
+
Since Sysrandom is SecureRandom-compatible, it can be patched in-place of
|
89
|
+
SecureRandom if you prefer its RNG behavior.
|
90
|
+
|
91
|
+
To do this, require `sysrandom/securerandom`:
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
>> SecureRandom
|
95
|
+
=> SecureRandom
|
96
|
+
>> require "sysrandom/securerandom"
|
97
|
+
=> true
|
98
|
+
>> SecureRandom
|
99
|
+
=> Sysrandom
|
100
|
+
>> SecureRandom.hex(32)
|
101
|
+
=> "d1bbe8c1ab78fc2fe514c5623d913a27ffd2dcdc9e002f3b358bb01a996962f1"
|
102
|
+
```
|
103
|
+
|
104
|
+
## Contributing
|
105
|
+
|
106
|
+
* Fork this repository on Github
|
107
|
+
* Make your changes and send a pull request
|
108
|
+
* If your changes look good, we'll merge them
|
109
|
+
|
110
|
+
## Copyright
|
111
|
+
|
112
|
+
Copyright (c) 2013-2016 Frank Denis, Tony Arcieri. See LICENSE.txt for further details.
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
require "rubocop/rake_task"
|
4
|
+
require "rake/clean"
|
5
|
+
|
6
|
+
unless defined? JRUBY_VERSION
|
7
|
+
require "rake/extensiontask"
|
8
|
+
Rake::ExtensionTask.new("sysrandom_ext") do |ext|
|
9
|
+
ext.ext_dir = "ext/sysrandom"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
RSpec::Core::RakeTask.new(:spec)
|
14
|
+
RuboCop::RakeTask.new
|
15
|
+
|
16
|
+
default_tasks = %w(spec rubocop)
|
17
|
+
default_tasks.unshift("compile") unless defined?(JRUBY_VERSION)
|
18
|
+
|
19
|
+
task default: default_tasks
|
20
|
+
|
21
|
+
CLEAN.include "**/*.o", "**/*.so", "**/*.bundle", "pkg", "tmp"
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "sysrandom"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
@@ -0,0 +1,275 @@
|
|
1
|
+
/*
|
2
|
+
* __randombytes_sysrandom.c: adapted from libsodium
|
3
|
+
* Copyright (c) 2013-2016 Frank Denis <j at pureftpd dot org>
|
4
|
+
* https://github.com/jedisct1/libsodium
|
5
|
+
*/
|
6
|
+
|
7
|
+
#include <stdlib.h>
|
8
|
+
#include <sys/types.h>
|
9
|
+
#ifndef _WIN32
|
10
|
+
# include <sys/stat.h>
|
11
|
+
# include <sys/time.h>
|
12
|
+
#endif
|
13
|
+
#ifdef __linux__
|
14
|
+
# include <sys/syscall.h>
|
15
|
+
#endif
|
16
|
+
|
17
|
+
#include <assert.h>
|
18
|
+
#include <errno.h>
|
19
|
+
#include <fcntl.h>
|
20
|
+
#include <limits.h>
|
21
|
+
#include <stdint.h>
|
22
|
+
#include <string.h>
|
23
|
+
#ifndef _WIN32
|
24
|
+
# include <unistd.h>
|
25
|
+
#endif
|
26
|
+
|
27
|
+
#ifdef _WIN32
|
28
|
+
# include <windows.h>
|
29
|
+
# define RtlGenRandom SystemFunction036
|
30
|
+
# if defined(__cplusplus)
|
31
|
+
extern "C"
|
32
|
+
# endif
|
33
|
+
BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength);
|
34
|
+
# pragma comment(lib, "advapi32.lib")
|
35
|
+
#endif
|
36
|
+
|
37
|
+
#if defined(__OpenBSD__) || defined(__CloudABI__)
|
38
|
+
# define HAVE_SAFE_ARC4RANDOM 1
|
39
|
+
#endif
|
40
|
+
|
41
|
+
#ifndef SSIZE_MAX
|
42
|
+
# define SSIZE_MAX (SIZE_MAX / 2 - 1)
|
43
|
+
#endif
|
44
|
+
|
45
|
+
#ifdef HAVE_SAFE_ARC4RANDOM
|
46
|
+
|
47
|
+
uint32_t
|
48
|
+
__randombytes_sysrandom(void)
|
49
|
+
{
|
50
|
+
return arc4random();
|
51
|
+
}
|
52
|
+
|
53
|
+
static void
|
54
|
+
__randombytes_sysrandom_stir(void)
|
55
|
+
{
|
56
|
+
}
|
57
|
+
|
58
|
+
void
|
59
|
+
__randombytes_sysrandom_buf(void * const buf, const size_t size)
|
60
|
+
{
|
61
|
+
return arc4random_buf(buf, size);
|
62
|
+
}
|
63
|
+
|
64
|
+
#else /* __OpenBSD__ */
|
65
|
+
|
66
|
+
typedef struct SysRandom_ {
|
67
|
+
int random_data_source_fd;
|
68
|
+
int initialized;
|
69
|
+
int getrandom_available;
|
70
|
+
} SysRandom;
|
71
|
+
|
72
|
+
static SysRandom stream = {
|
73
|
+
.random_data_source_fd = -1,
|
74
|
+
.initialized = 0,
|
75
|
+
.getrandom_available = 0
|
76
|
+
};
|
77
|
+
|
78
|
+
#ifndef _WIN32
|
79
|
+
static ssize_t
|
80
|
+
safe_read(const int fd, void * const buf_, size_t size)
|
81
|
+
{
|
82
|
+
unsigned char *buf = (unsigned char *) buf_;
|
83
|
+
ssize_t readnb;
|
84
|
+
|
85
|
+
assert(size > (size_t) 0U);
|
86
|
+
assert(size <= SSIZE_MAX);
|
87
|
+
do {
|
88
|
+
while ((readnb = read(fd, buf, size)) < (ssize_t) 0 &&
|
89
|
+
(errno == EINTR || errno == EAGAIN)); /* LCOV_EXCL_LINE */
|
90
|
+
if (readnb < (ssize_t) 0) {
|
91
|
+
return readnb; /* LCOV_EXCL_LINE */
|
92
|
+
}
|
93
|
+
if (readnb == (ssize_t) 0) {
|
94
|
+
break; /* LCOV_EXCL_LINE */
|
95
|
+
}
|
96
|
+
size -= (size_t) readnb;
|
97
|
+
buf += readnb;
|
98
|
+
} while (size > (ssize_t) 0);
|
99
|
+
|
100
|
+
return (ssize_t) (buf - (unsigned char *) buf_);
|
101
|
+
}
|
102
|
+
#endif
|
103
|
+
|
104
|
+
#ifndef _WIN32
|
105
|
+
static int
|
106
|
+
__randombytes_sysrandom_random_dev_open(void)
|
107
|
+
{
|
108
|
+
/* LCOV_EXCL_START */
|
109
|
+
struct stat st;
|
110
|
+
static const char *devices[] = {
|
111
|
+
# ifndef USE_BLOCKING_RANDOM
|
112
|
+
"/dev/urandom",
|
113
|
+
# endif
|
114
|
+
"/dev/random", NULL
|
115
|
+
};
|
116
|
+
const char ** device = devices;
|
117
|
+
int fd;
|
118
|
+
|
119
|
+
do {
|
120
|
+
fd = open(*device, O_RDONLY);
|
121
|
+
if (fd != -1) {
|
122
|
+
if (fstat(fd, &st) == 0 &&
|
123
|
+
# ifdef __COMPCERT__
|
124
|
+
1
|
125
|
+
# elif defined(S_ISNAM)
|
126
|
+
(S_ISNAM(st.st_mode) || S_ISCHR(st.st_mode))
|
127
|
+
# else
|
128
|
+
S_ISCHR(st.st_mode)
|
129
|
+
# endif
|
130
|
+
) {
|
131
|
+
# if defined(F_SETFD) && defined(FD_CLOEXEC)
|
132
|
+
(void) fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
|
133
|
+
# endif
|
134
|
+
return fd;
|
135
|
+
}
|
136
|
+
(void) close(fd);
|
137
|
+
} else if (errno == EINTR) {
|
138
|
+
continue;
|
139
|
+
}
|
140
|
+
device++;
|
141
|
+
} while (*device != NULL);
|
142
|
+
|
143
|
+
errno = EIO;
|
144
|
+
return -1;
|
145
|
+
/* LCOV_EXCL_STOP */
|
146
|
+
}
|
147
|
+
|
148
|
+
# ifdef SYS_getrandom
|
149
|
+
static int
|
150
|
+
_randombytes_linux_getrandom(void * const buf, const size_t size)
|
151
|
+
{
|
152
|
+
int readnb;
|
153
|
+
|
154
|
+
assert(size <= 256U);
|
155
|
+
do {
|
156
|
+
readnb = syscall(SYS_getrandom, buf, (int) size, 0);
|
157
|
+
} while (readnb < 0 && (errno == EINTR || errno == EAGAIN));
|
158
|
+
|
159
|
+
return (readnb == (int) size) - 1;
|
160
|
+
}
|
161
|
+
|
162
|
+
static int
|
163
|
+
randombytes_linux_getrandom(void * const buf_, size_t size)
|
164
|
+
{
|
165
|
+
unsigned char *buf = (unsigned char *) buf_;
|
166
|
+
size_t chunk_size = 256U;
|
167
|
+
|
168
|
+
do {
|
169
|
+
if (size < chunk_size) {
|
170
|
+
chunk_size = size;
|
171
|
+
assert(chunk_size > (size_t) 0U);
|
172
|
+
}
|
173
|
+
if (_randombytes_linux_getrandom(buf, chunk_size) != 0) {
|
174
|
+
return -1;
|
175
|
+
}
|
176
|
+
size -= chunk_size;
|
177
|
+
buf += chunk_size;
|
178
|
+
} while (size > (size_t) 0U);
|
179
|
+
|
180
|
+
return 0;
|
181
|
+
}
|
182
|
+
# endif
|
183
|
+
|
184
|
+
static void
|
185
|
+
__randombytes_sysrandom_init(void)
|
186
|
+
{
|
187
|
+
const int errno_save = errno;
|
188
|
+
|
189
|
+
# ifdef SYS_getrandom
|
190
|
+
{
|
191
|
+
unsigned char fodder[16];
|
192
|
+
|
193
|
+
if (randombytes_linux_getrandom(fodder, sizeof fodder) == 0) {
|
194
|
+
stream.getrandom_available = 1;
|
195
|
+
errno = errno_save;
|
196
|
+
return;
|
197
|
+
}
|
198
|
+
stream.getrandom_available = 0;
|
199
|
+
}
|
200
|
+
# endif
|
201
|
+
|
202
|
+
if ((stream.random_data_source_fd =
|
203
|
+
__randombytes_sysrandom_random_dev_open()) == -1) {
|
204
|
+
abort(); /* LCOV_EXCL_LINE */
|
205
|
+
}
|
206
|
+
errno = errno_save;
|
207
|
+
}
|
208
|
+
|
209
|
+
#else /* _WIN32 */
|
210
|
+
|
211
|
+
static void
|
212
|
+
__randombytes_sysrandom_init(void)
|
213
|
+
{
|
214
|
+
}
|
215
|
+
#endif
|
216
|
+
|
217
|
+
static void
|
218
|
+
__randombytes_sysrandom_stir(void)
|
219
|
+
{
|
220
|
+
if (stream.initialized == 0) {
|
221
|
+
__randombytes_sysrandom_init();
|
222
|
+
stream.initialized = 1;
|
223
|
+
}
|
224
|
+
}
|
225
|
+
|
226
|
+
static void
|
227
|
+
__randombytes_sysrandom_stir_if_needed(void)
|
228
|
+
{
|
229
|
+
if (stream.initialized == 0) {
|
230
|
+
__randombytes_sysrandom_stir();
|
231
|
+
}
|
232
|
+
}
|
233
|
+
|
234
|
+
void
|
235
|
+
__randombytes_sysrandom_buf(void * const buf, const size_t size)
|
236
|
+
{
|
237
|
+
__randombytes_sysrandom_stir_if_needed();
|
238
|
+
#ifdef ULONG_LONG_MAX
|
239
|
+
/* coverity[result_independent_of_operands] */
|
240
|
+
assert(size <= ULONG_LONG_MAX);
|
241
|
+
#endif
|
242
|
+
#ifndef _WIN32
|
243
|
+
# ifdef SYS_getrandom
|
244
|
+
if (stream.getrandom_available != 0) {
|
245
|
+
if (randombytes_linux_getrandom(buf, size) != 0) {
|
246
|
+
abort();
|
247
|
+
}
|
248
|
+
return;
|
249
|
+
}
|
250
|
+
# endif
|
251
|
+
if (stream.random_data_source_fd == -1 ||
|
252
|
+
safe_read(stream.random_data_source_fd, buf, size) != (ssize_t) size) {
|
253
|
+
abort(); /* LCOV_EXCL_LINE */
|
254
|
+
}
|
255
|
+
#else
|
256
|
+
if (size > (size_t) 0xffffffff) {
|
257
|
+
abort(); /* LCOV_EXCL_LINE */
|
258
|
+
}
|
259
|
+
if (! RtlGenRandom((PVOID) buf, (ULONG) size)) {
|
260
|
+
abort(); /* LCOV_EXCL_LINE */
|
261
|
+
}
|
262
|
+
#endif
|
263
|
+
}
|
264
|
+
|
265
|
+
uint32_t
|
266
|
+
__randombytes_sysrandom(void)
|
267
|
+
{
|
268
|
+
uint32_t r;
|
269
|
+
|
270
|
+
__randombytes_sysrandom_buf(&r, sizeof r);
|
271
|
+
|
272
|
+
return r;
|
273
|
+
}
|
274
|
+
|
275
|
+
#endif /* __OpenBSD__ */
|
@@ -0,0 +1,77 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
|
3
|
+
/* How many bytes to generate by default, matching SecureRandom
|
4
|
+
* Why SecureRandom has a default size argument is beyond me */
|
5
|
+
#define DEFAULT_N_BYTES 16
|
6
|
+
|
7
|
+
static VALUE mSysrandom = Qnil;
|
8
|
+
|
9
|
+
static VALUE Sysrandom_random_uint32(VALUE self);
|
10
|
+
static VALUE Sysrandom_random_bytes(int argc, VALUE *argv, VALUE self);
|
11
|
+
|
12
|
+
/* From randombytes_sysrandom.c */
|
13
|
+
uint32_t __randombytes_sysrandom(void);
|
14
|
+
void __randombytes_sysrandom_buf(void * const buf, const size_t size);
|
15
|
+
|
16
|
+
void Init_sysrandom_ext()
|
17
|
+
{
|
18
|
+
mSysrandom = rb_define_module("Sysrandom");
|
19
|
+
|
20
|
+
rb_define_singleton_method(mSysrandom, "__random_uint32", Sysrandom_random_uint32, 0);
|
21
|
+
rb_define_method(mSysrandom, "__random_uint32", Sysrandom_random_uint32, 0);
|
22
|
+
|
23
|
+
rb_define_singleton_method(mSysrandom, "random_bytes", Sysrandom_random_bytes, -1);
|
24
|
+
rb_define_method(mSysrandom, "random_bytes", Sysrandom_random_bytes, -1);
|
25
|
+
}
|
26
|
+
|
27
|
+
/**
|
28
|
+
* call-seq:
|
29
|
+
* Sysrandom#__random_uint32 -> Fixnum
|
30
|
+
*
|
31
|
+
* Generates a random unsigned 32-bit integer using the OS CSPRNG
|
32
|
+
*
|
33
|
+
*/
|
34
|
+
static VALUE
|
35
|
+
Sysrandom_random_uint32(VALUE self)
|
36
|
+
{
|
37
|
+
return UINT2NUM(__randombytes_sysrandom());
|
38
|
+
}
|
39
|
+
|
40
|
+
/**
|
41
|
+
* call-seq:
|
42
|
+
* Sysrandom#random_bytes(n=nil) -> String
|
43
|
+
*
|
44
|
+
* ::random_bytes generates a random binary string via the OS CSPRNG.
|
45
|
+
*
|
46
|
+
* The argument n specifies how long the resulting string should be.
|
47
|
+
*
|
48
|
+
* For compatibility with SecureRandom, if n is not specified, 16 is assumed.
|
49
|
+
*
|
50
|
+
* The resulting string may contain any byte (i.e. "x00" - "xff")
|
51
|
+
*
|
52
|
+
*/
|
53
|
+
static VALUE
|
54
|
+
Sysrandom_random_bytes(int argc, VALUE * argv, VALUE self)
|
55
|
+
{
|
56
|
+
VALUE n_obj, str;
|
57
|
+
int n;
|
58
|
+
|
59
|
+
if (rb_scan_args(argc, argv, "01", &n_obj) == 1) {
|
60
|
+
n = NUM2INT(n_obj);
|
61
|
+
|
62
|
+
if(n < 0) {
|
63
|
+
rb_raise(rb_eArgError, "negative string size");
|
64
|
+
}
|
65
|
+
} else {
|
66
|
+
n = DEFAULT_N_BYTES;
|
67
|
+
}
|
68
|
+
|
69
|
+
if(n > 0) {
|
70
|
+
str = rb_str_new(0, n);
|
71
|
+
__randombytes_sysrandom_buf(RSTRING_PTR(str), n);
|
72
|
+
} else {
|
73
|
+
str = rb_str_new2("");
|
74
|
+
}
|
75
|
+
|
76
|
+
return str;
|
77
|
+
}
|
data/lib/sysrandom.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require "sysrandom/version"
|
2
|
+
|
3
|
+
require "base64"
|
4
|
+
|
5
|
+
# Secure random number generation using system RNG facilities
|
6
|
+
module Sysrandom
|
7
|
+
module_function
|
8
|
+
|
9
|
+
# For some reason SecureRandom defaults to 16 bytes
|
10
|
+
DEFAULT_LENGTH = 16
|
11
|
+
|
12
|
+
if defined?(JRUBY_VERSION)
|
13
|
+
require "java"
|
14
|
+
|
15
|
+
if java.security.SecureRandom.respond_to?(:getInstanceStrong)
|
16
|
+
@_java_secure_random = java.security.SecureRandom.getInstanceStrong
|
17
|
+
else
|
18
|
+
@_java_secure_random = java.security.SecureRandom.getInstance("SHA1PRNG")
|
19
|
+
end
|
20
|
+
|
21
|
+
# Random uint32, used by random_number. The C extension provides an equivalent method
|
22
|
+
def __random_uint32
|
23
|
+
@_java_secure_random.nextLong & 0xFFFFFFFF
|
24
|
+
end
|
25
|
+
|
26
|
+
def random_bytes(n = DEFAULT_LENGTH)
|
27
|
+
raise ArgumentError, "negative string size" if n < 0
|
28
|
+
|
29
|
+
bytes = Java::byte[n].new
|
30
|
+
@_java_secure_random.nextBytes(bytes)
|
31
|
+
String.from_java_bytes(bytes)
|
32
|
+
end
|
33
|
+
else
|
34
|
+
require "sysrandom_ext"
|
35
|
+
end
|
36
|
+
|
37
|
+
def random_number(n = 0)
|
38
|
+
result = __random_uint32 / (2**32).to_f
|
39
|
+
|
40
|
+
if n <= 0
|
41
|
+
result
|
42
|
+
else
|
43
|
+
result *= n
|
44
|
+
n.is_a?(Fixnum) ? result.floor : result
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def base64(n = DEFAULT_LENGTH)
|
49
|
+
Base64.encode64(random_bytes(n)).chomp
|
50
|
+
end
|
51
|
+
|
52
|
+
def urlsafe_base64(n = DEFAULT_LENGTH)
|
53
|
+
Base64.urlsafe_encode64(random_bytes(n)).chomp
|
54
|
+
end
|
55
|
+
|
56
|
+
def hex(n = DEFAULT_LENGTH)
|
57
|
+
random_bytes(n).unpack("h*").first
|
58
|
+
end
|
59
|
+
|
60
|
+
def uuid
|
61
|
+
values = SecureRandom.hex(16).match(/\A(.{8})(.{4})(.)(.{3})(.)(.{3})(.{12})\z/)
|
62
|
+
"#{values[1]}-#{values[2]}-4#{values[4]}-#{'89ab'[values[5].ord % 4]}#{values[6]}-#{values[7]}"
|
63
|
+
end
|
64
|
+
end
|
data/sysrandom.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
lib = File.expand_path("../lib", __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "sysrandom/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "sysrandom"
|
7
|
+
spec.version = Sysrandom::VERSION
|
8
|
+
spec.authors = ["Tony Arcieri"]
|
9
|
+
spec.email = ["bascule@gmail.com"]
|
10
|
+
|
11
|
+
spec.summary = "Secure random number generation using system RNG facilities"
|
12
|
+
spec.description = "Sysrandom generates secure random numbers using /dev/urandom, getrandom(), etc"
|
13
|
+
spec.homepage = "https://github.com/cryptosphere/sysrandom"
|
14
|
+
spec.licenses = ["ISC"]
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = "exe"
|
18
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
if defined? JRUBY_VERSION
|
22
|
+
spec.platform = "java"
|
23
|
+
else
|
24
|
+
spec.extensions = ["ext/sysrandom/extconf.rb"]
|
25
|
+
end
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sysrandom
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: java
|
6
|
+
authors:
|
7
|
+
- Tony Arcieri
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-05-29 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Sysrandom generates secure random numbers using /dev/urandom, getrandom(), etc
|
14
|
+
email:
|
15
|
+
- bascule@gmail.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- ".gitignore"
|
21
|
+
- ".rspec"
|
22
|
+
- ".rubocop.yml"
|
23
|
+
- ".travis.yml"
|
24
|
+
- CHANGES.md
|
25
|
+
- Gemfile
|
26
|
+
- LICENSE.txt
|
27
|
+
- README.md
|
28
|
+
- Rakefile
|
29
|
+
- bin/console
|
30
|
+
- bin/setup
|
31
|
+
- ext/sysrandom/extconf.rb
|
32
|
+
- ext/sysrandom/randombytes_sysrandom.c
|
33
|
+
- ext/sysrandom/sysrandom_ext.c
|
34
|
+
- lib/sysrandom.rb
|
35
|
+
- lib/sysrandom/securerandom.rb
|
36
|
+
- lib/sysrandom/version.rb
|
37
|
+
- sysrandom.gemspec
|
38
|
+
homepage: https://github.com/cryptosphere/sysrandom
|
39
|
+
licenses:
|
40
|
+
- ISC
|
41
|
+
metadata: {}
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options: []
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
requirements: []
|
57
|
+
rubyforge_project:
|
58
|
+
rubygems_version: 2.4.8
|
59
|
+
signing_key:
|
60
|
+
specification_version: 4
|
61
|
+
summary: Secure random number generation using system RNG facilities
|
62
|
+
test_files: []
|