oroku_saki 1.0.0 → 1.1.2
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 +5 -5
- data/.travis.yml +2 -0
- data/README.md +12 -2
- data/ext/oroku_saki/oroku_saki.c +63 -15
- data/ext/oroku_saki/oroku_saki.h +3 -0
- data/lib/oroku_saki/version.rb +1 -1
- data/lib/oroku_saki.rb +17 -3
- data/oroku_saki.gemspec +7 -6
- metadata +15 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 52938f10790d5d1fed271cd6ebf9f0fcf7f734745bf3b707b9594c8ffe5e5913
|
4
|
+
data.tar.gz: 33f7261880251491f3c8aa79db6d4816cdd508330b6a429043a930da41b4db74
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7ecd06e1cd35594ef8a7524d815a6779d6486d1bff8e08e2a6176e7dff07cdefcc3b6cfb9067e3b2b1c63bcc022fceba448fad90abc8dedbd0ebb0cd4ea419c0
|
7
|
+
data.tar.gz: a2f056b0f95d575bdce333fcbab22d6792c7c633ac7d4d24d8b788d6f80197ba602082ff2fb8057c31f998e26f59d5db88651344758d4b774e4be84ef00ac6a9
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
# OrokuSaki
|
2
|
+
[](https://travis-ci.org/tpickett66/oroku_saki)
|
3
|
+
[](https://badge.fury.io/rb/oroku_saki)
|
2
4
|
|
3
5
|
OrokuSaki, a.k.a. Shredder, is the destroyer of strings and attacker's worst
|
4
6
|
nightmare!
|
@@ -36,17 +38,25 @@ second_secret = 'another sekret'
|
|
36
38
|
second_secret.shred! # => "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"
|
37
39
|
```
|
38
40
|
|
39
|
-
Setting a string to be shredded before garbage collection:
|
41
|
+
Setting a string to be shredded before garbage collection via a finalizer:
|
42
|
+
|
40
43
|
```ruby
|
41
44
|
my_secret = 'super sekret value!!!'
|
42
45
|
OrokuSaki.shred_later(my_secret) # => nil
|
43
46
|
puts my_secret # => "super sekret value!!!"
|
44
|
-
# A finalizer shreds the str just before it gets collected.
|
45
47
|
|
46
48
|
second_secret = 'another sekret'
|
47
49
|
second_scret.shred_later
|
48
50
|
```
|
49
51
|
|
52
|
+
Comparing Strings in constant time (nearly as fast as `==` for small inputs):
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
hmac = '16b9b8ae8e164768d0505bcb16269efb35804643dd351084b3c6ebbc6f7db2c8'
|
56
|
+
other_hmac = '16b9b8ae8e164768d0505bcb16269efb35804643dd351084b3c6ebbc6f7db2c8'
|
57
|
+
OrokuSaki.secure_compare(hmac, other_hmac) #=> true
|
58
|
+
```
|
59
|
+
|
50
60
|
## Development
|
51
61
|
|
52
62
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/ext/oroku_saki/oroku_saki.c
CHANGED
@@ -1,31 +1,77 @@
|
|
1
|
+
#include <stdint.h>
|
1
2
|
#include "oroku_saki.h"
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
* This method takes in a string and zeros out the memory it occupies, by design
|
6
|
-
* it does not respect frozen states of strings so make sure you're actually
|
7
|
-
* done with the String before using this method.
|
8
|
-
*
|
9
|
-
* @param [String] str The string to be zeroed out.
|
10
|
-
* @raise [TypeError] When passed something other than a String
|
11
|
-
* @return [nil]
|
12
|
-
*/
|
13
|
-
VALUE oroku_saki_shred_bang(VALUE rb_module, VALUE rb_str) {
|
14
|
-
if (TYPE(rb_str) != T_STRING) {
|
4
|
+
void raise_unless_string(VALUE rb_maybe_str, char *original_function_name) {
|
5
|
+
if (TYPE(rb_maybe_str) != T_STRING) {
|
15
6
|
VALUE inspected_obj, obj_class_name;
|
16
|
-
inspected_obj = rb_funcall(
|
7
|
+
inspected_obj = rb_funcall(rb_maybe_str, rb_intern("inspect"), 0);
|
17
8
|
obj_class_name = rb_funcall(
|
18
|
-
rb_funcall(
|
9
|
+
rb_funcall(rb_maybe_str, rb_intern("class"), 0),
|
19
10
|
rb_intern("name"),
|
20
11
|
0
|
21
12
|
);
|
22
13
|
rb_raise(
|
23
14
|
rb_eTypeError,
|
24
|
-
"
|
15
|
+
"%s received %s (%s), expected String!",
|
16
|
+
original_function_name,
|
25
17
|
StringValueCStr(inspected_obj),
|
26
18
|
StringValueCStr(obj_class_name)
|
27
19
|
);
|
28
20
|
}
|
21
|
+
}
|
22
|
+
|
23
|
+
/*
|
24
|
+
* This is a modified version of NaCl's crypto_verify_N functions adatpted to
|
25
|
+
* work with Ruby's String types and with variable lengths. We're returning
|
26
|
+
* the bitmonkeyed int from this to avoid branch predication.
|
27
|
+
*/
|
28
|
+
int secure_compare(VALUE rb_str_a, VALUE rb_str_b) {
|
29
|
+
uint_fast16_t d = 0U;
|
30
|
+
int i;
|
31
|
+
int len = RSTRING_LEN(rb_str_a);
|
32
|
+
char *a = RSTRING_PTR(rb_str_a);
|
33
|
+
char *b = RSTRING_PTR(rb_str_b);
|
34
|
+
|
35
|
+
for (i = 0; i < len; i++) {
|
36
|
+
d |= a[i] ^ b[i];
|
37
|
+
}
|
38
|
+
|
39
|
+
return (1 & ((d - 1) >> 8)) - 1;
|
40
|
+
}
|
41
|
+
|
42
|
+
/* The C implementation of secure compare, don't use!
|
43
|
+
*
|
44
|
+
* The return type is a Fixnum to avoid certain optimizations that cause the
|
45
|
+
* branch predictor to potentially leak timing information.
|
46
|
+
*
|
47
|
+
* @param [String] rb_str_a
|
48
|
+
* @param [String] rb_str_b
|
49
|
+
* @return [Fixnum] Zero for success, other values for failure.
|
50
|
+
* @api private
|
51
|
+
*/
|
52
|
+
VALUE oroku_saki_secure_compare(VALUE rb_module, VALUE rb_str_a, VALUE rb_str_b) {
|
53
|
+
raise_unless_string(rb_str_a, "OrokuSaki.secure_compare");
|
54
|
+
raise_unless_string(rb_str_b, "OrokuSaki.secure_compare");
|
55
|
+
|
56
|
+
if (RSTRING_LEN(rb_str_a) != RSTRING_LEN(rb_str_b)) {
|
57
|
+
return INT2FIX(-1);
|
58
|
+
}
|
59
|
+
|
60
|
+
return INT2FIX(secure_compare(rb_str_a, rb_str_b));
|
61
|
+
}
|
62
|
+
|
63
|
+
/* Zero out the memory housing the passed string.
|
64
|
+
*
|
65
|
+
* This method takes in a string and zeros out the memory it occupies, by design
|
66
|
+
* it does not respect frozen states of strings so make sure you're actually
|
67
|
+
* done with the String before using this method.
|
68
|
+
*
|
69
|
+
* @param [String] rb_str The string to be zeroed out.
|
70
|
+
* @raise [TypeError] When passed something other than a String
|
71
|
+
* @return [nil]
|
72
|
+
*/
|
73
|
+
VALUE oroku_saki_shred_bang(VALUE rb_module, VALUE rb_str) {
|
74
|
+
raise_unless_string(rb_str, "OrokuSaki.shred!");
|
29
75
|
memzero(RSTRING_PTR(rb_str), RSTRING_LEN(rb_str));
|
30
76
|
return Qnil;
|
31
77
|
}
|
@@ -38,4 +84,6 @@ Init_oroku_saki(void)
|
|
38
84
|
rb_mOrokuSaki = rb_define_module("OrokuSaki");
|
39
85
|
rb_define_singleton_method(rb_mOrokuSaki, "shred!",
|
40
86
|
oroku_saki_shred_bang, 1);
|
87
|
+
rb_define_singleton_method(rb_mOrokuSaki, "secure_compare_c",
|
88
|
+
oroku_saki_secure_compare, 2);
|
41
89
|
}
|
data/ext/oroku_saki/oroku_saki.h
CHANGED
data/lib/oroku_saki/version.rb
CHANGED
data/lib/oroku_saki.rb
CHANGED
@@ -6,10 +6,14 @@ require 'objspace'
|
|
6
6
|
|
7
7
|
module OrokuSaki
|
8
8
|
STRING_FINALIZER = ->(id) {
|
9
|
-
OrokuSaki.shred!(ObjectSpace._id2ref(id))
|
9
|
+
OrokuSaki.shred!(ObjectSpace._id2ref(id)) rescue nil
|
10
10
|
}
|
11
11
|
private_constant :STRING_FINALIZER
|
12
12
|
|
13
|
+
class << self
|
14
|
+
private :secure_compare_c
|
15
|
+
end
|
16
|
+
|
13
17
|
# Attaches the shred method as a finalizer for the passed string
|
14
18
|
#
|
15
19
|
# Gems working with sensitive data that needs to be returned to the user need
|
@@ -19,13 +23,23 @@ module OrokuSaki
|
|
19
23
|
#
|
20
24
|
# @param [String] str The string to be shredded befor GC reaping
|
21
25
|
# @return [String] The original string
|
22
|
-
#
|
26
|
+
# @raise [TypeError] When passed something other than a String
|
23
27
|
def self.shred_later(str)
|
24
28
|
if !(String === str)
|
25
29
|
raise TypeError,
|
26
30
|
"OrokuSaki.shred_later received #{str} (#{str.class}), expected String!"
|
27
31
|
end
|
28
|
-
ObjectSpace.define_finalizer(str, STRING_FINALIZER)
|
32
|
+
ObjectSpace.define_finalizer(str, STRING_FINALIZER) unless str.frozen?
|
29
33
|
str
|
30
34
|
end
|
35
|
+
|
36
|
+
# Bitewise compare two strings in constant time
|
37
|
+
#
|
38
|
+
# @param [String] a The first string to look at
|
39
|
+
# @param [String] b The second string to look at
|
40
|
+
# @return [Boolean]
|
41
|
+
# @raise [TypeError] When passed something other than a String for either argument
|
42
|
+
def self.secure_compare(a, b)
|
43
|
+
secure_compare_c(a, b) == 0
|
44
|
+
end
|
31
45
|
end
|
data/oroku_saki.gemspec
CHANGED
@@ -10,9 +10,10 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ["t.pickett66@gmail.com"]
|
11
11
|
|
12
12
|
spec.summary = %q{OrokuSaki, a.k.a. Shredder, is the destroyer of strings and attacker's worst nightmare!}
|
13
|
-
spec.description = "OrokuSaki, a.k.a. Shredder, is a small collection
|
14
|
-
"ensuring the strings used in cryptographic operations
|
15
|
-
"
|
13
|
+
spec.description = "OrokuSaki, a.k.a. Shredder, is a small collection of " \
|
14
|
+
"utilities for ensuring the strings used in cryptographic operations " \
|
15
|
+
"remain secret. This currently includes memory zeroing and constant time " \
|
16
|
+
"String comparisons."
|
16
17
|
spec.homepage = "https://github.com/tpickett66/oroku_saki"
|
17
18
|
spec.license = "MIT"
|
18
19
|
|
@@ -22,10 +23,10 @@ Gem::Specification.new do |spec|
|
|
22
23
|
spec.require_paths = ["lib"]
|
23
24
|
spec.extensions = ["ext/oroku_saki/extconf.rb"]
|
24
25
|
|
25
|
-
spec.add_development_dependency "bundler", "~>
|
26
|
-
spec.add_development_dependency "rake", "~>
|
26
|
+
spec.add_development_dependency "bundler", "~> 2.2.33"
|
27
|
+
spec.add_development_dependency "rake", "~> 12.3.2"
|
27
28
|
spec.add_development_dependency "rake-compiler", "~> 0.9"
|
28
29
|
spec.add_development_dependency "rspec", "~> 3.0"
|
29
30
|
spec.add_development_dependency "byebug", "~> 8.2"
|
30
|
-
spec.add_development_dependency "yard", "~> 0.
|
31
|
+
spec.add_development_dependency "yard", "~> 0.9.11"
|
31
32
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oroku_saki
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tyler Pickett
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-03-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 2.2.33
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 2.2.33
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 12.3.2
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 12.3.2
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake-compiler
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -86,17 +86,17 @@ dependencies:
|
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: 0.
|
89
|
+
version: 0.9.11
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: 0.
|
97
|
-
description: OrokuSaki, a.k.a. Shredder, is a small collection for ensuring
|
98
|
-
used in cryptographic operations remain secret.
|
99
|
-
|
96
|
+
version: 0.9.11
|
97
|
+
description: OrokuSaki, a.k.a. Shredder, is a small collection of utilities for ensuring
|
98
|
+
the strings used in cryptographic operations remain secret. This currently includes
|
99
|
+
memory zeroing and constant time String comparisons.
|
100
100
|
email:
|
101
101
|
- t.pickett66@gmail.com
|
102
102
|
executables: []
|
@@ -127,7 +127,7 @@ homepage: https://github.com/tpickett66/oroku_saki
|
|
127
127
|
licenses:
|
128
128
|
- MIT
|
129
129
|
metadata: {}
|
130
|
-
post_install_message:
|
130
|
+
post_install_message:
|
131
131
|
rdoc_options: []
|
132
132
|
require_paths:
|
133
133
|
- lib
|
@@ -142,11 +142,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
142
142
|
- !ruby/object:Gem::Version
|
143
143
|
version: '0'
|
144
144
|
requirements: []
|
145
|
-
|
146
|
-
|
147
|
-
signing_key:
|
145
|
+
rubygems_version: 3.3.7
|
146
|
+
signing_key:
|
148
147
|
specification_version: 4
|
149
148
|
summary: OrokuSaki, a.k.a. Shredder, is the destroyer of strings and attacker's worst
|
150
149
|
nightmare!
|
151
150
|
test_files: []
|
152
|
-
has_rdoc:
|