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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 92e35fcb6b712a4480ed16ad9ded3959f066b08a
4
- data.tar.gz: 87979e5935c98d372ab042a1d9aa0ddc36adb13b
2
+ SHA256:
3
+ metadata.gz: 52938f10790d5d1fed271cd6ebf9f0fcf7f734745bf3b707b9594c8ffe5e5913
4
+ data.tar.gz: 33f7261880251491f3c8aa79db6d4816cdd508330b6a429043a930da41b4db74
5
5
  SHA512:
6
- metadata.gz: 6a755589cecf5494141b5e78d5598395fd2b022cdb6a4bdc7f94e59f9119fbb9b1218a84276c75727d32d4e7b75368e88526e8411afd631b5fdac29dbe5ad1ad
7
- data.tar.gz: f4be1b4ddbd048c686f956c6d1c884a1f3e62b70b8cbeaa6527e2743b3e28c425967044a74fcdd23eb88229cc997f580d2fdc36b74bcc93da0c49596f6a93072
6
+ metadata.gz: 7ecd06e1cd35594ef8a7524d815a6779d6486d1bff8e08e2a6176e7dff07cdefcc3b6cfb9067e3b2b1c63bcc022fceba448fad90abc8dedbd0ebb0cd4ea419c0
7
+ data.tar.gz: a2f056b0f95d575bdce333fcbab22d6792c7c633ac7d4d24d8b788d6f80197ba602082ff2fb8057c31f998e26f59d5db88651344758d4b774e4be84ef00ac6a9
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!
@@ -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.
@@ -1,31 +1,77 @@
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 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
  }
@@ -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.2"
3
3
  end
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 for " \
14
- "ensuring the strings used in cryptographic operations remain secret. It is " \
15
- "based around a simple memzero C function."
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", "~> 1.11"
26
- spec.add_development_dependency "rake", "~> 10.0"
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.8.7"
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.0.0
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: 2016-04-13 00:00:00.000000000 Z
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: '1.11'
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: '1.11'
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: '10.0'
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: '10.0'
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.8.7
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.8.7
97
- description: OrokuSaki, a.k.a. Shredder, is a small collection for ensuring the strings
98
- used in cryptographic operations remain secret. It is based around a simple memzero
99
- C function.
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
- rubyforge_project:
146
- rubygems_version: 2.4.5
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: