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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 92e35fcb6b712a4480ed16ad9ded3959f066b08a
4
- data.tar.gz: 87979e5935c98d372ab042a1d9aa0ddc36adb13b
3
+ metadata.gz: 1bb2e0fe1dcd41017630398ac68646eb38d5afbb
4
+ data.tar.gz: 8a95b019ba3f9514206da31bf880a1be35ea466f
5
5
  SHA512:
6
- metadata.gz: 6a755589cecf5494141b5e78d5598395fd2b022cdb6a4bdc7f94e59f9119fbb9b1218a84276c75727d32d4e7b75368e88526e8411afd631b5fdac29dbe5ad1ad
7
- data.tar.gz: f4be1b4ddbd048c686f956c6d1c884a1f3e62b70b8cbeaa6527e2743b3e28c425967044a74fcdd23eb88229cc997f580d2fdc36b74bcc93da0c49596f6a93072
6
+ metadata.gz: 41bc12a28951a48f193ab84f348148de620629a9af0b32b483d87e1512ae1c038ddd163d57e48f71405176b1797b5a2029f175f8931829d776540c7c91985cc6
7
+ data.tar.gz: e9c21b707a38c155c962a9b43a593cbad3eef76392176403753da5b21c450303a74206a3d08b6b63efc619c30fb73a3f72f35ad869709a851b88dccc699b4dd4
data/.travis.yml CHANGED
@@ -1,4 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
+ - 2.1.1
3
4
  - 2.2.2
5
+ - 2.3.0
4
6
  before_install: gem install bundler -v 1.11.2
data/README.md CHANGED
@@ -1,4 +1,6 @@
1
1
  # OrokuSaki
2
+ [![Build Status](https://travis-ci.org/tpickett66/oroku_saki.svg?branch=master)](https://travis-ci.org/tpickett66/oroku_saki)
3
+ [![Gem Version](https://badge.fury.io/rb/oroku_saki.svg)](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!
@@ -1,31 +1,71 @@
1
+ #include <stdint.h>
1
2
  #include "oroku_saki.h"
2
3
 
3
- /* Zero out the memory housing the passed string.
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(rb_str, rb_intern("inspect"), 0);
7
+ inspected_obj = rb_funcall(rb_maybe_str, rb_intern("inspect"), 0);
17
8
  obj_class_name = rb_funcall(
18
- rb_funcall(rb_str, rb_intern("class"), 0),
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
- "OrokuSaki.shred! received %s (%s), expected String!",
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
  }
@@ -4,4 +4,7 @@
4
4
  #include "ruby.h"
5
5
  #include "memzero.h"
6
6
 
7
+ VALUE oroku_saki_secure_compare(VALUE rb_module, VALUE rb_str_a, VALUE rb_str_b);
8
+ VALUE oroku_saki_shred_bang(VALUE rb_module, VALUE rb_str);
9
+
7
10
  #endif /* OROKU_SAKI_H */
@@ -1,3 +1,3 @@
1
1
  module OrokuSaki
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.0"
3
3
  end
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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oroku_saki
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tyler Pickett