rbnacl 5.0.0 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
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