oroku_saki 1.0.0 → 1.1.0
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 +4 -4
- data/.travis.yml +2 -0
- data/README.md +2 -0
- data/ext/oroku_saki/oroku_saki.c +57 -15
- data/ext/oroku_saki/oroku_saki.h +3 -0
- data/lib/oroku_saki/version.rb +1 -1
- data/lib/oroku_saki.rb +15 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1bb2e0fe1dcd41017630398ac68646eb38d5afbb
|
4
|
+
data.tar.gz: 8a95b019ba3f9514206da31bf880a1be35ea466f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 41bc12a28951a48f193ab84f348148de620629a9af0b32b483d87e1512ae1c038ddd163d57e48f71405176b1797b5a2029f175f8931829d776540c7c91985cc6
|
7
|
+
data.tar.gz: e9c21b707a38c155c962a9b43a593cbad3eef76392176403753da5b21c450303a74206a3d08b6b63efc619c30fb73a3f72f35ad869709a851b88dccc699b4dd4
|
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!
|
data/ext/oroku_saki/oroku_saki.c
CHANGED
@@ -1,31 +1,71 @@
|
|
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 the secure compare, the return type is a Fixnum
|
43
|
+
* to avoid certain optimizations that cause the branch predictor to leak timing
|
44
|
+
* information.
|
45
|
+
*/
|
46
|
+
VALUE oroku_saki_secure_compare(VALUE rb_module, VALUE rb_str_a, VALUE rb_str_b) {
|
47
|
+
raise_unless_string(rb_str_a, "OrokuSaki.secure_compare");
|
48
|
+
raise_unless_string(rb_str_b, "OrokuSaki.secure_compare");
|
49
|
+
|
50
|
+
if (RSTRING_LEN(rb_str_a) != RSTRING_LEN(rb_str_b)) {
|
51
|
+
return INT2FIX(-1);
|
52
|
+
}
|
53
|
+
|
54
|
+
return INT2FIX(secure_compare(rb_str_a, rb_str_b));
|
55
|
+
}
|
56
|
+
|
57
|
+
/* Zero out the memory housing the passed string.
|
58
|
+
*
|
59
|
+
* This method takes in a string and zeros out the memory it occupies, by design
|
60
|
+
* it does not respect frozen states of strings so make sure you're actually
|
61
|
+
* done with the String before using this method.
|
62
|
+
*
|
63
|
+
* @param [String] str The string to be zeroed out.
|
64
|
+
* @raise [TypeError] When passed something other than a String
|
65
|
+
* @return [nil]
|
66
|
+
*/
|
67
|
+
VALUE oroku_saki_shred_bang(VALUE rb_module, VALUE rb_str) {
|
68
|
+
raise_unless_string(rb_str, "OrokuSaki.shred!");
|
29
69
|
memzero(RSTRING_PTR(rb_str), RSTRING_LEN(rb_str));
|
30
70
|
return Qnil;
|
31
71
|
}
|
@@ -38,4 +78,6 @@ Init_oroku_saki(void)
|
|
38
78
|
rb_mOrokuSaki = rb_define_module("OrokuSaki");
|
39
79
|
rb_define_singleton_method(rb_mOrokuSaki, "shred!",
|
40
80
|
oroku_saki_shred_bang, 1);
|
81
|
+
rb_define_singleton_method(rb_mOrokuSaki, "secure_compare_c",
|
82
|
+
oroku_saki_secure_compare, 2);
|
41
83
|
}
|
data/ext/oroku_saki/oroku_saki.h
CHANGED
data/lib/oroku_saki/version.rb
CHANGED
data/lib/oroku_saki.rb
CHANGED
@@ -10,6 +10,10 @@ module OrokuSaki
|
|
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,7 +23,7 @@ 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,
|
@@ -28,4 +32,14 @@ module OrokuSaki
|
|
28
32
|
ObjectSpace.define_finalizer(str, STRING_FINALIZER)
|
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
|