rbnacl 4.0.2 → 5.0.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: 06b62936ca905b101e22418710c37dfc78cd5d11
4
- data.tar.gz: 0b8b8ba5efb7e6673bb8811e19695a7fbb714fbd
3
+ metadata.gz: 0ff080260ca84ccc368c7c8414627267dffa9348
4
+ data.tar.gz: 2a3275a27b2ca89e36223529316076b67f895cac
5
5
  SHA512:
6
- metadata.gz: 69a6b4e5aaeee71020409df122943399ba64c1b46a76c4a75b4abaf113fb6d3d93c553f128f8b42e2a52d57a7e8081e45749b6c585b6aca434cbda1eea972fb7
7
- data.tar.gz: 20d228a8f6a56e5c710288fb6e73b16ad39d0185f369bd29b519f8742c1da1b5523388ea6bdfea8e1d21df892019761cc99e6e920f44bfdae8e671fa2cb00fe3
6
+ metadata.gz: 32bd4e83ea75ce57d93dcc7c1b2f3249d7e0010694c03d7d9a73a20e1a310ec6b9b6f40e0f190fb454f64eda528ea4e7eb35367d49d04f5ea7aafad270d26ff2
7
+ data.tar.gz: 9408f5ae9713e018e29a943bb9ddbb64010e9ace49d4cff37b2769e886f09025edba7776dcfbe81372363051b8d7b68cd7e04a583b8eeda87b3d48a17f39607b
@@ -35,3 +35,6 @@ Style/SpaceBeforeFirstArg:
35
35
 
36
36
  Style/GlobalVars:
37
37
  Enabled: false
38
+
39
+ Style/SafeNavigation:
40
+ Enabled: false
data/CHANGES.md CHANGED
@@ -1,4 +1,10 @@
1
- ## 4.0.2 (2016-03-12)
1
+ ## 5.0.0 (2017-06-13)
2
+
3
+ * [#159](https://github.com/cryptosphere/rbnacl/pull/159)
4
+ Support the BLAKE2b Initialize-Update-Finalize API.
5
+ ([@fudanchii])
6
+
7
+ ## 4.0.2 (2017-03-12)
2
8
 
3
9
  * [#157](https://github.com/cryptosphere/rbnacl/pull/157)
4
10
  Raise error on degenerate keys (fixes #152).
@@ -112,3 +118,4 @@
112
118
  [@mwpastore]: https://github.com/mwpastore
113
119
  [@elijh]: https://github.com/elijh
114
120
  [@paragonie-scott]: https://github.com/paragonie-scott
121
+ [@fudanchii]: https://github.com/fudanchii
data/README.md CHANGED
@@ -6,10 +6,10 @@
6
6
  [![Coverage Status](https://coveralls.io/repos/cryptosphere/rbnacl/badge.svg?branch=master)](https://coveralls.io/r/cryptosphere/rbnacl)
7
7
  [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/cryptosphere/rbnacl/blob/master/LICENSE.txt)
8
8
 
9
- _NOTE: This is the 4.x **stable** branch of RbNaCl. For the 3.x **legacy**
9
+ _NOTE: This is the 5.x **stable** branch of RbNaCl. For the 4.x **legacy**
10
10
  branch, please see:_
11
11
 
12
- https://github.com/cryptosphere/rbnacl/tree/3-x-stable
12
+ https://github.com/cryptosphere/rbnacl/tree/4-x-stable
13
13
 
14
14
  A Ruby binding to the state-of-the-art [Networking and Cryptography][nacl]
15
15
  library by [Daniel J. Bernstein][djb]. This is **NOT** Google Native Client.
@@ -63,7 +63,7 @@ module RbNaCl
63
63
  #
64
64
  # @return [String] The Blake2b hash digest as raw bytes
65
65
  def self.blake2b(data, options = {})
66
- Blake2b.new(options).digest(data)
66
+ Blake2b.digest(data, options)
67
67
  end
68
68
  end
69
69
  end
@@ -28,12 +28,25 @@ module RbNaCl
28
28
  :crypto_generichash_blake2b_salt_personal,
29
29
  [:pointer, :size_t, :pointer, :ulong_long, :pointer, :size_t, :pointer, :pointer]
30
30
 
31
+ sodium_function :generichash_blake2b_init,
32
+ :crypto_generichash_blake2b_init_salt_personal,
33
+ [:pointer, :pointer, :size_t, :size_t, :pointer, :pointer]
34
+
35
+ sodium_function :generichash_blake2b_update,
36
+ :crypto_generichash_blake2b_update,
37
+ [:pointer, :pointer, :ulong_long]
38
+
39
+ sodium_function :generichash_blake2b_final,
40
+ :crypto_generichash_blake2b_final,
41
+ [:pointer, :pointer, :size_t]
42
+
31
43
  EMPTY_PERSONAL = ("\0" * PERSONALBYTES).freeze
32
44
  EMPTY_SALT = ("\0" * SALTBYTES).freeze
33
45
 
34
- # Create a new Blake2b hash object
46
+ # Calculate a Blake2b digest
35
47
  #
36
- # @param [Hash] opts Blake2b configuration
48
+ # @param [String] message Message to be hashed
49
+ # @param [Hash] options Blake2b configuration
37
50
  # @option opts [String] :key for Blake2b keyed mode
38
51
  # @option opts [Integer] :digest_size size of output digest in bytes
39
52
  # @option opts [String] :salt Provide a salt to support randomised hashing.
@@ -43,39 +56,126 @@ module RbNaCl
43
56
  #
44
57
  # @raise [RbNaCl::LengthError] Invalid length specified for one or more options
45
58
  #
46
- # @return [RbNaCl::Hash::Blake2b] A Blake2b hasher object
47
- def initialize(opts = {})
48
- @key = opts.fetch(:key, nil)
59
+ # @return [String] Blake2b digest of the string as raw bytes
60
+ def self.digest(message, options)
61
+ opts = validate_opts(options)
62
+ digest = Util.zeros(opts[:digest_size])
63
+ generichash_blake2b(digest, opts[:digest_size], message, message.bytesize,
64
+ opts[:key], opts[:key_size], opts[:salt], opts[:personal]) ||
65
+ raise(CryptoError, "Hashing failed!")
66
+ digest
67
+ end
49
68
 
50
- if @key
51
- @key_size = @key.bytesize
52
- raise LengthError, "key too short" if @key_size < KEYBYTES_MIN
53
- raise LengthError, "key too long" if @key_size > KEYBYTES_MAX
69
+ # Validate and sanitize values for Blake2b configuration
70
+ #
71
+ # @param [Hash] options Blake2b configuration
72
+ # @option opts [String] :key for Blake2b keyed mode
73
+ # @option opts [Integer] :digest_size size of output digest in bytes
74
+ # @option opts [String] :salt Provide a salt to support randomised hashing.
75
+ # This is mixed into the parameters block to start the hashing.
76
+ # @option opts [Personal] :personal Provide personalisation string to allow pinning a hash for a particular purpose.
77
+ # This is mixed into the parameters block to start the hashing
78
+ #
79
+ # @raise [RbNaCl::LengthError] Invalid length specified for one or more options
80
+ #
81
+ # @return [Hash] opts Configuration hash with sanitized values
82
+ def self.validate_opts(opts)
83
+ key = opts.fetch(:key, nil)
84
+ if key
85
+ key_size = key.bytesize
86
+ raise LengthError, "key too short" if key_size < KEYBYTES_MIN
87
+ raise LengthError, "key too long" if key_size > KEYBYTES_MAX
54
88
  else
55
- @key_size = 0
89
+ key_size = 0
56
90
  end
91
+ opts[:key_size] = key_size
57
92
 
58
- @digest_size = opts.fetch(:digest_size, BYTES_MAX)
59
- raise LengthError, "digest size too short" if @digest_size < BYTES_MIN
60
- raise LengthError, "digest size too long" if @digest_size > BYTES_MAX
93
+ digest_size = opts.fetch(:digest_size, BYTES_MAX)
94
+ raise LengthError, "digest size too short" if digest_size < BYTES_MIN
95
+ raise LengthError, "digest size too long" if digest_size > BYTES_MAX
96
+ opts[:digest_size] = digest_size
61
97
 
62
- @personal = opts.fetch(:personal, EMPTY_PERSONAL)
63
- @personal = Util.zero_pad(PERSONALBYTES, @personal)
98
+ personal = opts.fetch(:personal, EMPTY_PERSONAL)
99
+ opts[:personal] = Util.zero_pad(PERSONALBYTES, personal)
64
100
 
65
- @salt = opts.fetch(:salt, EMPTY_SALT)
66
- @salt = Util.zero_pad(SALTBYTES, @salt)
101
+ salt = opts.fetch(:salt, EMPTY_SALT)
102
+ opts[:salt] = Util.zero_pad(SALTBYTES, salt)
103
+ opts
67
104
  end
68
105
 
69
- # Calculate a Blake2b digest
106
+ private_class_method :validate_opts
107
+
108
+ def self.new(opts = {})
109
+ opts = validate_opts(opts)
110
+ super
111
+ end
112
+
113
+ # Create a new Blake2b hash object
114
+ #
115
+ # @param [Hash] opts Blake2b configuration
116
+ # @option opts [String] :key for Blake2b keyed mode
117
+ # @option opts [Integer] :digest_size size of output digest in bytes
118
+ # @option opts [String] :salt Provide a salt to support randomised hashing.
119
+ # This is mixed into the parameters block to start the hashing.
120
+ # @option opts [Personal] :personal Provide personalisation string to allow pinning a hash for a particular purpose.
121
+ # This is mixed into the parameters block to start the hashing
122
+ #
123
+ # @raise [RbNaCl::LengthError] Invalid length specified for one or more options
124
+ #
125
+ # @return [RbNaCl::Hash::Blake2b] A Blake2b hasher object
126
+ def initialize(opts = {})
127
+ @key = opts[:key]
128
+ @key_size = opts[:key_size]
129
+ @digest_size = opts[:digest_size]
130
+ @personal = opts[:personal]
131
+ @salt = opts[:salt]
132
+
133
+ @incycle = false
134
+ @instate = nil
135
+ end
136
+
137
+ # Initialize state for Blake2b hash calculation,
138
+ # this will be called automatically from #update if needed
139
+ def reset
140
+ @instate.release if @instate
141
+ @instate = State.new
142
+ self.class.generichash_blake2b_init(@instate.pointer, @key, @key_size, @digest_size, @salt, @personal) ||
143
+ raise(CryptoError, "Hash init failed!")
144
+ @incycle = true
145
+ @digest = nil
146
+ end
147
+
148
+ # Reentrant version of Blake2b digest calculation method
70
149
  #
71
150
  # @param [String] message Message to be hashed
151
+ def update(message)
152
+ reset unless @incycle
153
+ self.class.generichash_blake2b_update(@instate.pointer, message, message.bytesize) ||
154
+ raise(CryptoError, "Hashing failed!")
155
+ end
156
+ alias << update
157
+
158
+ # Finalize digest calculation, return cached digest if any
72
159
  #
73
160
  # @return [String] Blake2b digest of the string as raw bytes
74
- def digest(message)
75
- digest = Util.zeros(@digest_size)
76
- self.class.generichash_blake2b(digest, @digest_size, message, message.bytesize, @key, @key_size, @salt, @personal) ||
77
- raise(CryptoError, "Hashing failed!")
78
- digest
161
+ def digest
162
+ raise(CryptoError, "No message to hash yet!") unless @incycle
163
+ return @digest if @digest
164
+ @digest = Util.zeros(@digest_size)
165
+ self.class.generichash_blake2b_final(@instate.pointer, @digest, @digest_size) ||
166
+ raise(CryptoError, "Hash finalization failed!")
167
+ @digest
168
+ end
169
+
170
+ # The crypto_generichash_blake2b_state struct representation
171
+ # ref: jedisct1/libsodium/src/libsodium/include/sodium/crypto_generichash_blake2b.h#L23
172
+ class State < FFI::Struct
173
+ layout :h, [:uint64, 8],
174
+ :t, [:uint64, 2],
175
+ :f, [:uint64, 2],
176
+ :buf, [:uint8, 2 * 128],
177
+ :buflen, :size_t,
178
+ :last_node, :uint8
79
179
  end
80
180
  end
81
181
  end
@@ -4,5 +4,5 @@
4
4
  # NaCl/libsodium for Ruby
5
5
  module RbNaCl
6
6
  # The library's version
7
- VERSION = "4.0.2"
7
+ VERSION = "5.0.0"
8
8
  end
@@ -14,6 +14,29 @@ RSpec.describe RbNaCl::Hash::Blake2b do
14
14
  expect(RbNaCl::Hash.blake2b("")).to eq empty_string_hash
15
15
  end
16
16
 
17
+ context "arbitrary length message API" do
18
+ let(:blake2b) { RbNaCl::Hash::Blake2b.new }
19
+
20
+ it "calculates the correct hash for a reference string" do
21
+ blake2b << reference_string
22
+ expect(blake2b.digest).to eq reference_string_hash
23
+ end
24
+
25
+ it "calculates the correct hash for an empty string" do
26
+ blake2b << ""
27
+ expect(blake2b.digest).to eq empty_string_hash
28
+ end
29
+
30
+ it "raise CryptoError when digest called without reset / message" do
31
+ expect { blake2b.digest }.to raise_error(RbNaCl::CryptoError)
32
+ end
33
+
34
+ it "calculates hash for empty string when digest called directly after reset" do
35
+ blake2b.reset
36
+ expect(blake2b.digest).to eq empty_string_hash
37
+ end
38
+ end
39
+
17
40
  context "keyed" do
18
41
  let(:reference_string) { vector :blake2b_keyed_message }
19
42
  let(:reference_key) { vector :blake2b_key }
@@ -26,6 +49,23 @@ RSpec.describe RbNaCl::Hash::Blake2b do
26
49
  it "doesn't accept empty strings as a key" do
27
50
  expect { RbNaCl::Hash.blake2b(reference_string, key: "") }.to raise_error(RbNaCl::LengthError)
28
51
  end
52
+
53
+ context "arbitrary length message API" do
54
+ let(:blake2b) { RbNaCl::Hash::Blake2b.new(key: "") }
55
+ let(:blake2b_wk) { RbNaCl::Hash::Blake2b.new(key: reference_key) }
56
+
57
+ it "calculates keyed hashes correctly" do
58
+ blake2b_wk << reference_string
59
+ expect(blake2b_wk.digest).to eq reference_string_hash
60
+ end
61
+
62
+ it "doesn't accept empty strings as a key" do
63
+ expect do
64
+ blake2b << reference_string
65
+ blake2b.digest
66
+ end.to raise_error(RbNaCl::LengthError)
67
+ end
68
+ end
29
69
  end
30
70
 
31
71
  context "personalized" do
@@ -42,6 +82,21 @@ RSpec.describe RbNaCl::Hash::Blake2b do
42
82
  it "calculates personalised hashes correctly with a short personal" do
43
83
  expect(RbNaCl::Hash.blake2b(reference_string, personal: reference_personal_short)).to eq reference_personal_short_hash
44
84
  end
85
+
86
+ context "arbitrary length message API" do
87
+ let(:blake2b) { RbNaCl::Hash::Blake2b.new(personal: reference_personal) }
88
+ let(:blake2b_sh) { RbNaCl::Hash::Blake2b.new(personal: reference_personal_short) }
89
+
90
+ it "calculates personalised hashes correctly" do
91
+ blake2b << reference_string
92
+ expect(blake2b.digest).to eq reference_personal_hash
93
+ end
94
+
95
+ it "calculates personalised hashes correctly with a short personal" do
96
+ blake2b_sh << reference_string
97
+ expect(blake2b_sh.digest).to eq reference_personal_short_hash
98
+ end
99
+ end
45
100
  end
46
101
 
47
102
  context "salted" do
@@ -58,5 +113,20 @@ RSpec.describe RbNaCl::Hash::Blake2b do
58
113
  it "calculates saltised hashes correctly with a short salt" do
59
114
  expect(RbNaCl::Hash.blake2b(reference_string, salt: reference_salt_short)).to eq reference_salt_short_hash
60
115
  end
116
+
117
+ context "arbitrary length message API" do
118
+ let(:blake2b) { RbNaCl::Hash::Blake2b.new(salt: reference_salt) }
119
+ let(:blake2b_sh) { RbNaCl::Hash::Blake2b.new(salt: reference_salt_short) }
120
+
121
+ it "calculates saltised hashes correctly" do
122
+ blake2b << reference_string
123
+ expect(blake2b.digest).to eq reference_salt_hash
124
+ end
125
+
126
+ it "calculates saltised hashes correctly with a short salt" do
127
+ blake2b_sh << reference_string
128
+ expect(blake2b_sh.digest).to eq reference_salt_short_hash
129
+ end
130
+ end
61
131
  end
62
132
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rbnacl
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.2
4
+ version: 5.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tony Arcieri
@@ -9,34 +9,34 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-03-13 00:00:00.000000000 Z
12
+ date: 2017-06-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ffi
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - ">="
18
+ - - '>='
19
19
  - !ruby/object:Gem::Version
20
20
  version: '0'
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - ">="
25
+ - - '>='
26
26
  - !ruby/object:Gem::Version
27
27
  version: '0'
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: bundler
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
- - - ">="
32
+ - - '>='
33
33
  - !ruby/object:Gem::Version
34
34
  version: '0'
35
35
  type: :development
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - ">="
39
+ - - '>='
40
40
  - !ruby/object:Gem::Version
41
41
  version: '0'
42
42
  description: The Networking and Cryptography (NaCl) library provides a high-level
@@ -48,13 +48,13 @@ executables: []
48
48
  extensions: []
49
49
  extra_rdoc_files: []
50
50
  files:
51
- - ".coveralls.yml"
52
- - ".gitignore"
53
- - ".rspec"
54
- - ".rubocop.yml"
55
- - ".ruby-version"
56
- - ".travis.yml"
57
- - ".yardopts"
51
+ - .coveralls.yml
52
+ - .gitignore
53
+ - .rspec
54
+ - .rubocop.yml
55
+ - .ruby-version
56
+ - .travis.yml
57
+ - .yardopts
58
58
  - CHANGES.md
59
59
  - Gemfile
60
60
  - Guardfile
@@ -139,17 +139,17 @@ require_paths:
139
139
  - lib
140
140
  required_ruby_version: !ruby/object:Gem::Requirement
141
141
  requirements:
142
- - - ">="
142
+ - - '>='
143
143
  - !ruby/object:Gem::Version
144
144
  version: 2.2.6
145
145
  required_rubygems_version: !ruby/object:Gem::Requirement
146
146
  requirements:
147
- - - ">="
147
+ - - '>='
148
148
  - !ruby/object:Gem::Version
149
149
  version: '0'
150
150
  requirements: []
151
151
  rubyforge_project:
152
- rubygems_version: 2.6.10
152
+ rubygems_version: 2.0.14.1
153
153
  signing_key:
154
154
  specification_version: 4
155
155
  summary: Ruby binding to the Networking and Cryptography (NaCl) library