rbnacl 5.0.0 → 6.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.
Files changed (55) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +34 -12
  4. data/.travis.yml +16 -16
  5. data/CHANGES.md +37 -10
  6. data/Gemfile +4 -3
  7. data/Guardfile +2 -0
  8. data/LICENSE.txt +1 -1
  9. data/README.md +31 -21
  10. data/Rakefile +4 -3
  11. data/lib/rbnacl.rb +8 -3
  12. data/lib/rbnacl/aead/base.rb +3 -0
  13. data/lib/rbnacl/aead/chacha20poly1305_ietf.rb +2 -2
  14. data/lib/rbnacl/aead/chacha20poly1305_legacy.rb +2 -2
  15. data/lib/rbnacl/aead/xchacha20poly1305_ietf.rb +44 -0
  16. data/lib/rbnacl/boxes/curve25519xsalsa20poly1305.rb +6 -5
  17. data/lib/rbnacl/boxes/curve25519xsalsa20poly1305/private_key.rb +1 -1
  18. data/lib/rbnacl/group_elements/curve25519.rb +2 -1
  19. data/lib/rbnacl/hash/blake2b.rb +6 -4
  20. data/lib/rbnacl/hash/sha256.rb +1 -1
  21. data/lib/rbnacl/hash/sha512.rb +1 -1
  22. data/lib/rbnacl/hmac/sha256.rb +73 -8
  23. data/lib/rbnacl/hmac/sha512.rb +73 -8
  24. data/lib/rbnacl/hmac/sha512256.rb +71 -8
  25. data/lib/rbnacl/init.rb +1 -5
  26. data/lib/rbnacl/one_time_auths/poly1305.rb +2 -2
  27. data/lib/rbnacl/password_hash.rb +33 -2
  28. data/lib/rbnacl/password_hash/argon2.rb +37 -18
  29. data/lib/rbnacl/password_hash/scrypt.rb +1 -1
  30. data/lib/rbnacl/random.rb +1 -3
  31. data/lib/rbnacl/secret_boxes/xsalsa20poly1305.rb +2 -2
  32. data/lib/rbnacl/signatures/ed25519/signing_key.rb +2 -2
  33. data/lib/rbnacl/signatures/ed25519/verify_key.rb +1 -1
  34. data/lib/rbnacl/sodium.rb +16 -12
  35. data/lib/rbnacl/sodium/version.rb +3 -1
  36. data/lib/rbnacl/test_vectors.rb +104 -44
  37. data/lib/rbnacl/util.rb +92 -8
  38. data/lib/rbnacl/version.rb +1 -1
  39. data/rbnacl.gemspec +6 -7
  40. data/spec/rbnacl/aead/xchacha20poly1305_ietf_spec.rb +14 -0
  41. data/spec/rbnacl/authenticators/poly1305_spec.rb +21 -1
  42. data/spec/rbnacl/boxes/curve25519xsalsa20poly1305_spec.rb +18 -6
  43. data/spec/rbnacl/hmac/sha256_spec.rb +6 -1
  44. data/spec/rbnacl/hmac/sha512256_spec.rb +6 -1
  45. data/spec/rbnacl/hmac/sha512_spec.rb +6 -1
  46. data/spec/rbnacl/password_hash/argon2_spec.rb +56 -14
  47. data/spec/rbnacl/signatures/ed25519/signing_key_spec.rb +5 -4
  48. data/spec/rbnacl/util_spec.rb +63 -4
  49. data/spec/shared/aead.rb +33 -13
  50. data/spec/shared/authenticator.rb +0 -19
  51. data/spec/shared/box.rb +18 -6
  52. data/spec/shared/hmac.rb +46 -0
  53. data/spec/spec_helper.rb +3 -1
  54. metadata +22 -18
  55. data/.ruby-version +0 -1
@@ -6,8 +6,9 @@ module RbNaCl
6
6
  module Util
7
7
  extend Sodium
8
8
 
9
- sodium_function :c_verify16, :crypto_verify_16, [:pointer, :pointer]
10
- sodium_function :c_verify32, :crypto_verify_32, [:pointer, :pointer]
9
+ sodium_function :c_verify16, :crypto_verify_16, %i[pointer pointer]
10
+ sodium_function :c_verify32, :crypto_verify_32, %i[pointer pointer]
11
+ sodium_function :c_verify64, :crypto_verify_64, %i[pointer pointer]
11
12
 
12
13
  module_function
13
14
 
@@ -81,6 +82,8 @@ module RbNaCl
81
82
  # @param description [String] Description of the string (used in the error)
82
83
  def check_length(string, length, description)
83
84
  if string.nil?
85
+ # code below is runs only in test cases
86
+ # nil can't be converted to str with #to_str method
84
87
  raise LengthError,
85
88
  "#{description} was nil (Expected #{length.to_int})",
86
89
  caller
@@ -106,19 +109,98 @@ module RbNaCl
106
109
  # @param length [Integer] The only acceptable length of the string
107
110
  # @param description [String] Description of the string (used in the error)
108
111
  def check_string(string, length, description)
109
- unless string.respond_to? :to_str
110
- raise TypeError, "can't convert #{string.class} into String with #to_str"
111
- end
112
+ check_string_validation(string)
113
+ string = string.to_s
114
+ check_length(string, length, description)
115
+
116
+ string
117
+ end
118
+
119
+ # Check a passed in string, convertion if necessary
120
+ #
121
+ # This method will check the key, and raise error
122
+ # if argument is not a string, and if it's empty string.
123
+ #
124
+ # RFC 2104 HMAC
125
+ # The key for HMAC can be of any length (keys longer than B bytes are
126
+ # first hashed using H). However, less than L bytes is strongly
127
+ # discouraged as it would decrease the security strength of the
128
+ # function. Keys longer than L bytes are acceptable but the extra
129
+ # length would not significantly increase the function strength. (A
130
+ # longer key may be advisable if the randomness of the key is
131
+ # considered weak.)
132
+ #
133
+ # see https://tools.ietf.org/html/rfc2104#section-3
134
+ #
135
+ #
136
+ # @raise [ArgumentError] If we cannot convert to a string with #to_str
137
+ # @raise [RbNaCl::LengthError] If the string is empty
138
+ #
139
+ # @param string [#to_str] The input string
140
+ def check_hmac_key(string, _description)
141
+ check_string_validation(string)
112
142
 
113
143
  string = string.to_str
114
- unless string.encoding == Encoding::BINARY
115
- raise EncodingError, "strings must use BINARY encoding (got #{string.encoding})"
144
+
145
+ if string.bytesize.zero?
146
+ raise LengthError,
147
+ "#{Description} was #{string.bytesize} bytes (Expected more than 0)",
148
+ caller
116
149
  end
117
- check_length(string, length, description)
118
150
 
119
151
  string
120
152
  end
121
153
 
154
+ # Check a passed string is it valid
155
+ #
156
+ # Raise an error if passed argument is invalid
157
+ #
158
+ # @raise [TypeError] If string cannot convert to a string with #to_str
159
+ # @raise [EncodingError] If string have wrong encoding
160
+ #
161
+ # @param string [#to_str] The input string
162
+ def check_string_validation(string)
163
+ raise TypeError, "can't convert #{string.class} into String with #to_str" unless string.respond_to? :to_str
164
+
165
+ string = string.to_str
166
+
167
+ raise EncodingError, "strings must use BINARY encoding (got #{string.encoding})" if string.encoding != Encoding::BINARY
168
+ end
169
+
170
+ # Compare two 64 byte strings in constant time
171
+ #
172
+ # This should help to avoid timing attacks for string comparisons in your
173
+ # application. Note that many of the functions (such as HmacSha512#verify)
174
+ # use this method under the hood already.
175
+ #
176
+ # @param [String] one String #1
177
+ # @param [String] two String #2
178
+ #
179
+ # @return [Boolean] Well, are they equal?
180
+ def verify64(one, two)
181
+ return false unless two.bytesize == 64 && one.bytesize == 64
182
+
183
+ c_verify64(one, two)
184
+ end
185
+
186
+ # Compare two 64 byte strings in constant time
187
+ #
188
+ # This should help to avoid timing attacks for string comparisons in your
189
+ # application. Note that many of the functions (such as HmacSha512#verify)
190
+ # use this method under the hood already.
191
+ #
192
+ # @param [String] one String #1
193
+ # @param [String] two String #2
194
+ #
195
+ # @raise [ArgumentError] If the strings are not equal in length
196
+ #
197
+ # @return [Boolean] Well, are they equal?
198
+ def verify64!(one, two)
199
+ check_length(one, 64, "First message")
200
+ check_length(two, 64, "Second message")
201
+ c_verify64(one, two)
202
+ end
203
+
122
204
  # Compare two 32 byte strings in constant time
123
205
  #
124
206
  # This should help to avoid timing attacks for string comparisons in your
@@ -131,6 +213,7 @@ module RbNaCl
131
213
  # @return [Boolean] Well, are they equal?
132
214
  def verify32(one, two)
133
215
  return false unless two.bytesize == 32 && one.bytesize == 32
216
+
134
217
  c_verify32(one, two)
135
218
  end
136
219
 
@@ -164,6 +247,7 @@ module RbNaCl
164
247
  # @return [Boolean] Well, are they equal?
165
248
  def verify16(one, two)
166
249
  return false unless two.bytesize == 16 && one.bytesize == 16
250
+
167
251
  c_verify16(one, two)
168
252
  end
169
253
 
@@ -4,5 +4,5 @@
4
4
  # NaCl/libsodium for Ruby
5
5
  module RbNaCl
6
6
  # The library's version
7
- VERSION = "5.0.0"
7
+ VERSION = "6.0.0".freeze
8
8
  end
@@ -1,5 +1,6 @@
1
- # -*- encoding: utf-8 -*-
2
- lib = File.expand_path("../lib", __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path("lib", __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
  require "rbnacl/version"
5
6
 
@@ -8,21 +9,19 @@ Gem::Specification.new do |spec|
8
9
  spec.version = RbNaCl::VERSION
9
10
  spec.authors = ["Tony Arcieri", "Jonathan Stott"]
10
11
  spec.email = ["bascule@gmail.com", "jonathan.stott@gmail.com"]
11
- spec.homepage = "https://github.com/cryptosphere/rbnacl"
12
+ spec.homepage = "https://github.com/crypto-rb/rbnacl"
12
13
  spec.licenses = ["MIT"]
13
- spec.summary = "Ruby binding to the Networking and Cryptography (NaCl) library"
14
- spec.description = <<-DESCRIPTION.strip.gsub(/\s+/, " ")
14
+ spec.summary = "Ruby binding to the libsodium/NaCl cryptography library"
15
+ spec.description = <<-DESCRIPTION.strip.gsub(/\s+/, " ")
15
16
  The Networking and Cryptography (NaCl) library provides a high-level toolkit for building
16
17
  cryptographic systems and protocols
17
18
  DESCRIPTION
18
-
19
19
  spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
20
20
  spec.executables = spec.files.grep(%r{^bin/}).map { |f| File.basename(f) }
21
21
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
22
22
  spec.require_paths = ["lib"]
23
23
 
24
24
  spec.required_ruby_version = ">= 2.2.6"
25
- spec.platform = "jruby" if defined? JRUBY_VERSION
26
25
 
27
26
  spec.add_runtime_dependency "ffi"
28
27
 
@@ -0,0 +1,14 @@
1
+ # encoding: binary
2
+ # frozen_string_literal: true
3
+
4
+ RSpec.describe RbNaCl::AEAD::XChaCha20Poly1305IETF do
5
+ if RbNaCl::Sodium::Version.supported_version?("1.0.12")
6
+ include_examples "aead" do
7
+ let(:key) { vector :aead_xchacha20poly1305_ietf_key }
8
+ let(:message) { vector :aead_xchacha20poly1305_ietf_message }
9
+ let(:nonce) { vector :aead_xchacha20poly1305_ietf_nonce }
10
+ let(:ad) { vector :aead_xchacha20poly1305_ietf_ad }
11
+ let(:ciphertext) { vector :aead_xchacha20poly1305_ietf_ciphertext }
12
+ end
13
+ end
14
+ end
@@ -2,7 +2,27 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  RSpec.describe RbNaCl::OneTimeAuth do
5
- let(:tag) { vector :auth_onetime }
5
+ let(:key) { vector "auth_key_#{described_class.key_bytes}".to_sym }
6
+ let(:message) { vector :auth_message }
7
+ let(:tag) { vector :auth_onetime }
8
+
9
+ context ".new" do
10
+ it "raises ArgumentError on a key which is too long" do
11
+ expect { described_class.new("\0" * described_class.key_bytes.succ) }.to raise_error(ArgumentError)
12
+ end
13
+ end
14
+
15
+ context ".auth" do
16
+ it "raises ArgumentError on a key which is too long" do
17
+ expect { described_class.auth("\0" * described_class.key_bytes.succ, message) }.to raise_error(ArgumentError)
18
+ end
19
+ end
20
+
21
+ context ".verify" do
22
+ it "raises ArgumentError on a key which is too long" do
23
+ expect { described_class.verify("\0" * described_class.key_bytes.succ, tag, message) }.to raise_error(ArgumentError)
24
+ end
25
+ end
6
26
 
7
27
  include_examples "authenticator"
8
28
  end
@@ -9,27 +9,39 @@ RSpec.describe RbNaCl::Box do
9
9
 
10
10
  context "new" do
11
11
  it "accepts strings" do
12
- expect { RbNaCl::Box.new(alicepk, bobsk) }.to_not raise_error
12
+ expect do
13
+ RbNaCl::Box.new(alicepk, bobsk)
14
+ end.to_not raise_error
13
15
  end
14
16
 
15
17
  it "accepts KeyPairs" do
16
- expect { RbNaCl::Box.new(alice_key, bob_key) }.to_not raise_error
18
+ expect do
19
+ RbNaCl::Box.new(alice_key, bob_key)
20
+ end.to_not raise_error
17
21
  end
18
22
 
19
23
  it "raises TypeError on a nil public key" do
20
- expect { RbNaCl::Box.new(nil, bobsk) }.to raise_error(TypeError)
24
+ expect do
25
+ RbNaCl::Box.new(nil, bobsk)
26
+ end.to raise_error(TypeError)
21
27
  end
22
28
 
23
29
  it "raises RbNaCl::LengthError on an invalid public key" do
24
- expect { RbNaCl::Box.new("hello", bobsk) }.to raise_error(RbNaCl::LengthError, /Public key was 5 bytes \(Expected 32\)/)
30
+ expect do
31
+ RbNaCl::Box.new("hello", bobsk)
32
+ end.to raise_error(RbNaCl::LengthError, /Public key was 5 bytes \(Expected 32\)/)
25
33
  end
26
34
 
27
35
  it "raises TypeError on a nil secret key" do
28
- expect { RbNaCl::Box.new(alicepk, nil) }.to raise_error(TypeError)
36
+ expect do
37
+ RbNaCl::Box.new(alicepk, nil)
38
+ end.to raise_error(TypeError)
29
39
  end
30
40
 
31
41
  it "raises RbNaCl::LengthError on an invalid secret key" do
32
- expect { RbNaCl::Box.new(alicepk, "hello") }.to raise_error(RbNaCl::LengthError, /Private key was 5 bytes \(Expected 32\)/)
42
+ expect do
43
+ RbNaCl::Box.new(alicepk, "hello")
44
+ end.to raise_error(RbNaCl::LengthError, /Private key was 5 bytes \(Expected 32\)/)
33
45
  end
34
46
  end
35
47
 
@@ -2,7 +2,12 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  RSpec.describe RbNaCl::HMAC::SHA256 do
5
- let(:tag) { vector :auth_hmacsha256 }
5
+ let(:key) { vector :auth_hmac_key }
6
+ let(:message) { vector :auth_hmac_data }
7
+ let(:tag) { vector :auth_hmacsha256_tag }
8
+ let(:mult_tag) { vector :auth_hmacsha256_mult_tag }
9
+ let(:wrong_key) { "key".encode("utf-8") }
6
10
 
11
+ include_examples "HMAC"
7
12
  include_examples "authenticator"
8
13
  end
@@ -2,7 +2,12 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  RSpec.describe RbNaCl::HMAC::SHA512256 do
5
- let(:tag) { vector :auth_hmacsha512256 }
5
+ let(:key) { vector :auth_hmac_key }
6
+ let(:message) { vector :auth_message }
7
+ let(:tag) { vector :auth_hmacsha512256_tag }
8
+ let(:mult_tag) { vector :auth_hmacsha512256_mult_tag }
9
+ let(:wrong_key) { "key".encode("utf-8") }
6
10
 
11
+ include_examples "HMAC"
7
12
  include_examples "authenticator"
8
13
  end
@@ -2,7 +2,12 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  RSpec.describe RbNaCl::HMAC::SHA512 do
5
- let(:tag) { vector :auth_hmacsha512 }
5
+ let(:key) { vector :auth_hmac_key }
6
+ let(:message) { vector :auth_hmac_data }
7
+ let(:tag) { vector :auth_hmacsha512_tag }
8
+ let(:mult_tag) { vector :auth_hmacsha512_mult_tag }
9
+ let(:wrong_key) { "key".encode("utf-8") }
6
10
 
11
+ include_examples "HMAC"
7
12
  include_examples "authenticator"
8
13
  end
@@ -3,26 +3,68 @@
3
3
 
4
4
  if RbNaCl::Sodium::Version::ARGON2_SUPPORTED
5
5
  RSpec.describe RbNaCl::PasswordHash::Argon2 do
6
- let(:reference_password) { vector :argon2_password }
7
- let(:reference_salt) { vector :argon2_salt }
8
- let(:reference_opslimit) { RbNaCl::TEST_VECTORS[:argon2_opslimit] }
9
- let(:reference_memlimit) { RbNaCl::TEST_VECTORS[:argon2_memlimit] }
10
- let(:reference_digest) { vector :argon2_digest }
11
- let(:reference_outlen) { RbNaCl::TEST_VECTORS[:argon2_outlen] }
6
+ let(:argon2i_password) { vector :argon2i_password }
7
+ let(:argon2i_salt) { vector :argon2i_salt }
8
+ let(:argon2i_opslimit) { RbNaCl::TEST_VECTORS[:argon2i_opslimit] }
9
+ let(:argon2i_memlimit) { RbNaCl::TEST_VECTORS[:argon2i_memlimit] }
10
+ let(:argon2i_digest) { vector :argon2i_digest }
11
+ let(:argon2i_outlen) { RbNaCl::TEST_VECTORS[:argon2i_outlen] }
12
+
13
+ let(:argon2id_password) { vector :argon2id_password }
14
+ let(:argon2id_salt) { vector :argon2id_salt }
15
+ let(:argon2id_opslimit) { RbNaCl::TEST_VECTORS[:argon2id_opslimit] }
16
+ let(:argon2id_memlimit) { RbNaCl::TEST_VECTORS[:argon2id_memlimit] }
17
+ let(:argon2id_digest) { vector :argon2id_digest }
18
+ let(:argon2id_outlen) { RbNaCl::TEST_VECTORS[:argon2id_outlen] }
12
19
 
13
20
  let(:str_ref_password) { RbNaCl::TEST_VECTORS[:argon2_str_passwd] }
14
21
  let(:str_ref_digest) { RbNaCl::TEST_VECTORS[:argon2_str_digest] }
15
22
 
16
- it "calculates the correct digest for a reference password/salt" do
17
- digest = RbNaCl::PasswordHash.argon2(
18
- reference_password,
19
- reference_salt,
20
- reference_opslimit,
21
- reference_memlimit,
22
- reference_outlen
23
+ it "calculates the correct argon2i digest for a reference password/salt" do
24
+ digest = RbNaCl::PasswordHash.argon2i(
25
+ argon2i_password,
26
+ argon2i_salt,
27
+ argon2i_opslimit,
28
+ argon2i_memlimit,
29
+ argon2i_outlen
23
30
  )
31
+ expect(digest).to eq argon2i_digest
32
+ end
33
+
34
+ if RbNaCl::Sodium::Version::ARGON2_SUPPORTED
35
+ it "calculates the correct argon2id digest for a reference password/salt" do
36
+ digest = RbNaCl::PasswordHash.argon2id(
37
+ argon2id_password,
38
+ argon2id_salt,
39
+ argon2id_opslimit,
40
+ argon2id_memlimit,
41
+ argon2id_outlen
42
+ )
43
+ expect(digest).to eq argon2id_digest
44
+ end
45
+
46
+ it "calculates the correct argon2 default digest" do
47
+ if RbNaCl::Sodium::Version.supported_version?("1.0.15")
48
+ digest = RbNaCl::PasswordHash.argon2(
49
+ argon2id_password,
50
+ argon2id_salt,
51
+ argon2id_opslimit,
52
+ argon2id_memlimit,
53
+ argon2id_outlen
54
+ )
55
+ expect(digest).to eq argon2id_digest
56
+ else
57
+ digest = RbNaCl::PasswordHash.argon2(
58
+ argon2i_password,
59
+ argon2i_salt,
60
+ argon2i_opslimit,
61
+ argon2i_memlimit,
62
+ argon2i_outlen
63
+ )
64
+ expect(digest).to eq argon2i_digest
65
+ end
66
+ end
24
67
 
25
- expect(digest).to eq reference_digest
26
68
  end
27
69
 
28
70
  it "verifies password" do
@@ -2,9 +2,10 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  RSpec.describe RbNaCl::SigningKey do
5
- let(:signing_key) { vector :sign_private }
6
- let(:message) { vector :sign_message }
7
- let(:signature) { vector :sign_signature }
5
+ let(:signing_key) { vector :sign_private }
6
+ let(:signing_keypair) { vector :sign_keypair }
7
+ let(:message) { vector :sign_message }
8
+ let(:signature) { vector :sign_signature }
8
9
 
9
10
  subject { described_class.new(signing_key) }
10
11
 
@@ -22,7 +23,7 @@ RSpec.describe RbNaCl::SigningKey do
22
23
 
23
24
  it "serializes the internal signing key to bytes" do
24
25
  expect(subject.keypair_bytes.length).to eq 64
25
- expect(subject.keypair_bytes).to eq "\xB1\x8E\x1D\x00E\x99^\xC3\xD0\x10\xC3\x87\xCC\xFE\xB9\x84\xD7\x83\xAF\x8F\xBB\x0F@\xFA}\xB1&\xD8\x89\xF6\xDA\xDDw\xF4\x8BY\xCA\xED\xA7wQ\xED\x13\x8B\x0E\xC6g\xFFP\xF8v\x8C%\xD4\x83\t\xA8\xF3\x86\xA2\xBA\xD1\x87\xFB"
26
+ expect(subject.keypair_bytes).to eq signing_keypair
26
27
  end
27
28
 
28
29
  include_examples "key equality" do
@@ -2,6 +2,57 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  RSpec.describe RbNaCl::Util do
5
+ context ".verify64" do
6
+ let(:msg) { RbNaCl::Util.zeros(64) }
7
+ let(:identical_msg) { RbNaCl::Util.zeros(64) }
8
+ let(:other_msg) { RbNaCl::Util.zeros(63) + "\001" }
9
+ let(:short_msg) { RbNaCl::Util.zeros(63) }
10
+ let(:long_msg) { RbNaCl::Util.zeros(65) }
11
+
12
+ it "confirms identical messages are identical" do
13
+ expect(RbNaCl::Util.verify64(msg, identical_msg)).to be true
14
+ end
15
+
16
+ it "confirms non-identical messages are non-identical" do
17
+ expect(RbNaCl::Util.verify64(msg, other_msg)).to be false
18
+ expect(RbNaCl::Util.verify64(other_msg, msg)).to be false
19
+ expect(RbNaCl::Util.verify64(short_msg, msg)).to be false
20
+ expect(RbNaCl::Util.verify64(msg, short_msg)).to be false
21
+ expect(RbNaCl::Util.verify64(long_msg, msg)).to be false
22
+ expect(RbNaCl::Util.verify64(msg, long_msg)).to be false
23
+ end
24
+ end
25
+
26
+ context ".verify64!" do
27
+ let(:msg) { RbNaCl::Util.zeros(64) }
28
+ let(:identical_msg) { RbNaCl::Util.zeros(64) }
29
+ let(:other_msg) { RbNaCl::Util.zeros(63) + "\001" }
30
+ let(:short_msg) { RbNaCl::Util.zeros(63) }
31
+ let(:long_msg) { RbNaCl::Util.zeros(65) }
32
+
33
+ it "confirms identical messages are identical" do
34
+ expect(RbNaCl::Util.verify64!(msg, identical_msg)).to be true
35
+ end
36
+
37
+ it "confirms non-identical messages are non-identical" do
38
+ expect(RbNaCl::Util.verify64!(msg, other_msg)).to be false
39
+ expect(RbNaCl::Util.verify64!(other_msg, msg)).to be false
40
+ end
41
+
42
+ it "raises descriptively on a short message in position 1" do
43
+ expect { RbNaCl::Util.verify64!(short_msg, msg) }.to raise_error(RbNaCl::LengthError)
44
+ end
45
+ it "raises descriptively on a short message in position 2" do
46
+ expect { RbNaCl::Util.verify64!(msg, short_msg) }.to raise_error(RbNaCl::LengthError)
47
+ end
48
+ it "raises descriptively on a long message in position 1" do
49
+ expect { RbNaCl::Util.verify64!(long_msg, msg) }.to raise_error(RbNaCl::LengthError)
50
+ end
51
+ it "raises descriptively on a long message in position 2" do
52
+ expect { RbNaCl::Util.verify64!(msg, long_msg) }.to raise_error(RbNaCl::LengthError)
53
+ end
54
+ end
55
+
5
56
  context ".verify32!" do
6
57
  let(:msg) { RbNaCl::Util.zeros(32) }
7
58
  let(:identical_msg) { RbNaCl::Util.zeros(32) }
@@ -106,16 +157,24 @@ RSpec.describe RbNaCl::Util do
106
157
 
107
158
  context "check_length" do
108
159
  it "accepts strings of the correct length" do
109
- expect { RbNaCl::Util.check_length("A" * 4, 4, "Test String") }.not_to raise_error
160
+ expect do
161
+ RbNaCl::Util.check_length("A" * 4, 4, "Test String")
162
+ end.not_to raise_error
110
163
  end
111
164
  it "rejects strings which are too short" do
112
- expect { RbNaCl::Util.check_length("A" * 3, 4, "Test String") }.to raise_error(RbNaCl::LengthError, "Test String was 3 bytes (Expected 4)")
165
+ expect do
166
+ RbNaCl::Util.check_length("A" * 3, 4, "Test String")
167
+ end.to raise_error(RbNaCl::LengthError, "Test String was 3 bytes (Expected 4)")
113
168
  end
114
169
  it "rejects strings which are too long" do
115
- expect { RbNaCl::Util.check_length("A" * 5, 4, "Test String") }.to raise_error(RbNaCl::LengthError, "Test String was 5 bytes (Expected 4)")
170
+ expect do
171
+ RbNaCl::Util.check_length("A" * 5, 4, "Test String")
172
+ end.to raise_error(RbNaCl::LengthError, "Test String was 5 bytes (Expected 4)")
116
173
  end
117
174
  it "rejects nil strings" do
118
- expect { RbNaCl::Util.check_length(nil, 4, "Test String") }.to raise_error(RbNaCl::LengthError, "Test String was nil (Expected 4)")
175
+ expect do
176
+ RbNaCl::Util.check_length(nil, 4, "Test String")
177
+ end.to raise_error(RbNaCl::LengthError, "Test String was nil (Expected 4)")
119
178
  end
120
179
  end
121
180