From 9b08bc76b1d9bd6ca68bb8addfc5ebf7301d6043 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Wed, 7 Aug 2013 23:18:23 -0700 Subject: [PATCH 1/4] Remove the encoding system After much discussion it was agreed that the encoding system was out of place in this library. This commit removes it, and hopefully improves the general quality of the codebase as well. All encoding-related thunks and glue code have been removed, the way TestVectors work have been standardized, and any stray test vectors still lingering inside of the tests have been moved to test_vectors.rb Fixes #54 --- Gemfile | 1 - Guardfile | 18 +------ lib/rbnacl.rb | 4 -- lib/rbnacl/auth.rb | 15 +++--- lib/rbnacl/box.rb | 4 +- lib/rbnacl/encoder.rb | 44 ----------------- lib/rbnacl/encoders/base32.rb | 33 ------------- lib/rbnacl/encoders/base64.rb | 30 ------------ lib/rbnacl/encoders/hex.rb | 30 ------------ lib/rbnacl/encoders/raw.rb | 12 ----- lib/rbnacl/hash.rb | 23 ++++----- lib/rbnacl/hash/blake2b.rb | 7 ++- lib/rbnacl/keys/private_key.rb | 4 +- lib/rbnacl/keys/public_key.rb | 5 +- lib/rbnacl/keys/signing_key.rb | 11 ++--- lib/rbnacl/keys/verify_key.rb | 32 ++++--------- lib/rbnacl/point.rb | 20 ++++---- lib/rbnacl/random_nonce_box.rb | 11 ++--- lib/rbnacl/secret_box.rb | 5 +- lib/rbnacl/self_test.rb | 54 ++++++++++----------- lib/rbnacl/serializable.rb | 12 +---- lib/rbnacl/test_vectors.rb | 33 +++++++++++++ spec/rbnacl/auth/one_time_spec.rb | 2 +- spec/rbnacl/box_spec.rb | 15 +++--- spec/rbnacl/encoder_spec.rb | 14 ------ spec/rbnacl/encoders/base32_spec.rb | 16 ------- spec/rbnacl/encoders/base64_spec.rb | 15 ------ spec/rbnacl/encoders/hex_spec.rb | 15 ------ spec/rbnacl/hash_spec.rb | 53 ++++++--------------- spec/rbnacl/hmac/sha256_spec.rb | 2 +- spec/rbnacl/hmac/sha512256_spec.rb | 2 +- spec/rbnacl/keys/private_key_spec.rb | 22 ++++----- spec/rbnacl/keys/public_key_spec.rb | 14 ++---- spec/rbnacl/keys/signing_key_spec.rb | 19 ++------ spec/rbnacl/keys/verify_key_spec.rb | 38 +++++---------- spec/rbnacl/point_spec.rb | 12 ++--- spec/rbnacl/random_nonce_box_spec.rb | 32 ++++++------- spec/rbnacl/secret_box_spec.rb | 5 +- spec/shared/authenticator.rb | 71 +++++++++++----------------- spec/shared/box.rb | 6 +-- spec/spec_helper.rb | 23 ++------- 41 files changed, 225 insertions(+), 559 deletions(-) delete mode 100644 lib/rbnacl/encoder.rb delete mode 100644 lib/rbnacl/encoders/base32.rb delete mode 100644 lib/rbnacl/encoders/base64.rb delete mode 100644 lib/rbnacl/encoders/hex.rb delete mode 100644 lib/rbnacl/encoders/raw.rb delete mode 100644 spec/rbnacl/encoder_spec.rb delete mode 100644 spec/rbnacl/encoders/base32_spec.rb delete mode 100644 spec/rbnacl/encoders/base64_spec.rb delete mode 100644 spec/rbnacl/encoders/hex_spec.rb diff --git a/Gemfile b/Gemfile index 54764b3..0e4e9f4 100644 --- a/Gemfile +++ b/Gemfile @@ -8,6 +8,5 @@ group :development do end group :test do - gem 'base32' gem 'coveralls', :require => false end diff --git a/Guardfile b/Guardfile index f855df0..c407c26 100644 --- a/Guardfile +++ b/Guardfile @@ -3,22 +3,6 @@ guard :rspec do watch(%r{^spec/.+_spec\.rb$}) - watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" } + watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } watch('spec/spec_helper.rb') { "spec" } - - # Rails example - watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } - watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" } - watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] } - watch(%r{^spec/support/(.+)\.rb$}) { "spec" } - watch('config/routes.rb') { "spec/routing" } - watch('app/controllers/application_controller.rb') { "spec/controllers" } - - # Capybara features specs - watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/features/#{m[1]}_spec.rb" } - - # Turnip features and steps - watch(%r{^spec/acceptance/(.+)\.feature$}) - watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' } end - diff --git a/lib/rbnacl.rb b/lib/rbnacl.rb index 26ef4ca..c09656d 100644 --- a/lib/rbnacl.rb +++ b/lib/rbnacl.rb @@ -41,10 +41,6 @@ class IncorrectPrimitiveError < ArgumentError; end require "rbnacl/hmac/sha256" require "rbnacl/auth/one_time" require "rbnacl/random" -require "rbnacl/encoder" -require "rbnacl/encoders/base64" -require "rbnacl/encoders/hex" -require "rbnacl/encoders/raw" require "rbnacl/point" require "rbnacl/random_nonce_box" require "rbnacl/test_vectors" diff --git a/lib/rbnacl/auth.rb b/lib/rbnacl/auth.rb index 9160b4c..30dd749 100644 --- a/lib/rbnacl/auth.rb +++ b/lib/rbnacl/auth.rb @@ -18,9 +18,8 @@ class Auth # A new authenticator, ready for auth and verification # # @param [#to_str] key the key used for authenticators, 32 bytes. - # @param [#to_sym] encoding decode key from this format (default raw) - def initialize(key, encoding = :raw) - @key = Encoder[encoding].decode(key) + def initialize(key) + @key = key.to_str Util.check_length(@key, key_bytes, "#{self.class} key") end @@ -48,25 +47,23 @@ def self.verify(key, message, authenticator) # Compute authenticator for message # # @param [#to_str] message the message to authenticate - # @param [#to_sym] authenticator_encoding format of the authenticator (default raw) # # @return [String] The authenticator in the requested encoding (default raw) - def auth(message, authenticator_encoding = :raw) + def auth(message) authenticator = Util.zeros(tag_bytes) message = message.to_str compute_authenticator(message, authenticator) - Encoder[authenticator_encoding].encode(authenticator) + authenticator end # Verifies the given authenticator with the message. # # @param [#to_str] authenticator to be checked # @param [#to_str] message the message to be authenticated - # @param [#to_sym] authenticator_encoding format of the authenticator (default raw) # # @return [Boolean] Was it valid? - def verify(message, authenticator, authenticator_encoding = :raw) - auth = Encoder[authenticator_encoding].decode(authenticator) + def verify(message, authenticator) + auth = authenticator.to_s return false unless auth.bytesize == tag_bytes verify_message(message, auth) end diff --git a/lib/rbnacl/box.rb b/lib/rbnacl/box.rb index d0ce225..f4199de 100644 --- a/lib/rbnacl/box.rb +++ b/lib/rbnacl/box.rb @@ -78,8 +78,8 @@ class Box # # @return [Crypto::Box] The new Box, ready to use def initialize(public_key, private_key, encoding = :raw) - @public_key = PublicKey === public_key ? public_key : PublicKey.new(public_key, encoding) - @private_key = PrivateKey === private_key ? private_key : PrivateKey.new(private_key, encoding) + @public_key = PublicKey === public_key ? public_key : PublicKey.new(public_key) + @private_key = PrivateKey === private_key ? private_key : PrivateKey.new(private_key) raise IncorrectPrimitiveError unless @public_key.primitive == primitive && @private_key.primitive == primitive end diff --git a/lib/rbnacl/encoder.rb b/lib/rbnacl/encoder.rb deleted file mode 100644 index 84fac8c..0000000 --- a/lib/rbnacl/encoder.rb +++ /dev/null @@ -1,44 +0,0 @@ -# encoding: binary -module Crypto - # Encoders can be used to serialize or deserialize keys, ciphertexts, hashes, - # and signatures. To provide an encoder, simply subclass Encoder and call the - # register class method, then define the encode and decode methods: - # - # class CrazysauceEncoder < Crypto::Encoder - # register :crazysauce - # - # def encode(string) - # ... - # end - # - # def decode(string) - # ... - # end - # end - # - # Once an encoder has been registered, an instance of it is available via - # calling Crypto::Encoder[], e.g. Crypto::Encoder[:hex].encode("foobar") - # - class Encoder - # Hash where encoder objects are stored - Registry = {} - - # Register the current class as an encoder - def self.register(name) - self[name] = self.new - end - - # Look up an encoder by the given name - def self.[](name) - Registry[name.to_sym] or raise ArgumentError, "unsupported encoder: #{name}" - end - - # Register an encoder object directly - def self.[]=(name, obj) - Registry[name.to_sym] = obj - end - - def encode(string); raise NotImplementedError, "encoding not implemented"; end - def decode(string); raise NotImplementedError, "decoding not implemented"; end - end -end diff --git a/lib/rbnacl/encoders/base32.rb b/lib/rbnacl/encoders/base32.rb deleted file mode 100644 index 370370e..0000000 --- a/lib/rbnacl/encoders/base32.rb +++ /dev/null @@ -1,33 +0,0 @@ -# encoding: binary -# Requires the base32 gem -require 'base32' - -module Crypto - module Encoders - # Base64 encoding provider - # - # Accessible as Crypto::Encoder[:base64] - # - class Base32 < Crypto::Encoder - register :base32 - - # Base32 encodes a message - # - # @param [String] bytes The bytes to encode - # - # @return [String] Lovely, elegant "Zooko-style" Base32 - def encode(bytes) - ::Base32.encode(bytes.to_s).downcase - end - - # Hex decodes a message - # - # @param [String] base32 string to decode. - # - # @return [String] crisp and clean bytes - def decode(base32) - ::Base32.decode(base32.to_s.upcase) - end - end - end -end \ No newline at end of file diff --git a/lib/rbnacl/encoders/base64.rb b/lib/rbnacl/encoders/base64.rb deleted file mode 100644 index ebe93f9..0000000 --- a/lib/rbnacl/encoders/base64.rb +++ /dev/null @@ -1,30 +0,0 @@ -# encoding: binary -module Crypto - module Encoders - # Base64 encoding provider - # - # Accessable as Crypto::Encoder[:base64] - # - class Base64 < Crypto::Encoder - register :base64 - - # Base64 encodes a message - # - # @param [String] bytes The bytes to encode - # - # @return [String] Clunky old base64 - def encode(bytes) - [bytes.to_s].pack("m").gsub("\n", '') - end - - # Hex decodes a message - # - # @param [String] base64 string to decode. - # - # @return [String] crisp and clean bytes - def decode(base64) - base64.to_s.unpack("m").first - end - end - end -end \ No newline at end of file diff --git a/lib/rbnacl/encoders/hex.rb b/lib/rbnacl/encoders/hex.rb deleted file mode 100644 index b969962..0000000 --- a/lib/rbnacl/encoders/hex.rb +++ /dev/null @@ -1,30 +0,0 @@ -# encoding: binary -module Crypto - module Encoders - # Hex encoding provider - # - # Accessible as Crypto::Encoder[:hex] - # - class Hex < Crypto::Encoder - register :hex - - # Hex encodes a message - # - # @param [String] bytes The bytes to encode - # - # @return [String] Tasty, tasty hexadecimal - def encode(bytes) - bytes.to_s.unpack("H*").first - end - - # Hex decodes a message - # - # @param [String] hex hex to decode. - # - # @return [String] crisp and clean bytes - def decode(hex) - [hex.to_s].pack("H*") - end - end - end -end \ No newline at end of file diff --git a/lib/rbnacl/encoders/raw.rb b/lib/rbnacl/encoders/raw.rb deleted file mode 100644 index a967043..0000000 --- a/lib/rbnacl/encoders/raw.rb +++ /dev/null @@ -1,12 +0,0 @@ -# encoding: binary -module Crypto - module Encoders - # Raw encoder which only does a string conversion (if necessary) - class Raw < Crypto::Encoder - register :raw - - def encode(bytes); bytes.to_s; end - def decode(bytes); bytes.to_s; end - end - end -end \ No newline at end of file diff --git a/lib/rbnacl/hash.rb b/lib/rbnacl/hash.rb index 156351b..c41fbc8 100644 --- a/lib/rbnacl/hash.rb +++ b/lib/rbnacl/hash.rb @@ -17,32 +17,31 @@ module Hash # # There's no streaming done, just pass in the data and be done with it. # - # @param [String] data The data, as a collection of bytes - # @param [#to_sym] encoding Encoding of the returned hash. + # @param [#to_str] data The data, as a collection of bytes # # @raise [CryptoError] If the hashing fails for some reason. # # @return [String] The SHA-256 hash as raw bytes (Or encoded as per the second argument) - def self.sha256(data, encoding = :raw) + def self.sha256(data) + data = data.to_str digest = Util.zeros(NaCl::SHA256BYTES) NaCl.crypto_hash_sha256(digest, data, data.bytesize) || raise(CryptoError, "Hashing failed!") - Encoder[encoding].encode(digest) + digest end # Returns the SHA-512 hash of the given data # # There's no streaming done, just pass in the data and be done with it. # - # @param [String] data The data, as a collection of bytes - # @param [#to_sym] encoding Encoding of the returned hash. + # @param [#to_str] data The data, as a collection of bytes # # @raise [CryptoError] If the hashing fails for some reason. # # @return [String] The SHA-512 hash as raw bytes (Or encoded as per the second argument) - def self.sha512(data, encoding = :raw) + def self.sha512(data) digest = Util.zeros(NaCl::SHA512BYTES) NaCl.crypto_hash_sha512(digest, data, data.bytesize) || raise(CryptoError, "Hashing failed!") - Encoder[encoding].encode(digest) + digest end if NaCl.supported_version? :libsodium, '0.4.0' @@ -54,7 +53,6 @@ def self.sha512(data, encoding = :raw) # @param [String] data The data, as a collection of bytes # @option options [Fixnum] digest_size Size in bytes (1-64, default 64) # @option options [String] key 64-byte (or less) key for keyed mode - # @option options [Symbol] encoding Output encoding format (default raw) # # @raise [CryptoError] If the hashing fails for some reason. # @@ -62,14 +60,11 @@ def self.sha512(data, encoding = :raw) def self.blake2b(data, options = {}) key = options[:key] digest_size = options[:digest_size] || NaCl::BLAKE2B_OUTBYTES - encoding = options[:encoding] || :raw - - digest = Blake2b.new(options).hash(data) - Encoder[encoding].encode(digest) + Blake2b.new(options).hash(data) end else - def self.blake2b(data, encoding = :raw) + def self.blake2b(data, options = {}) raise NotImplementedError, "not supported by this version of libsodium" end end diff --git a/lib/rbnacl/hash/blake2b.rb b/lib/rbnacl/hash/blake2b.rb index b62f079..b15f20d 100644 --- a/lib/rbnacl/hash/blake2b.rb +++ b/lib/rbnacl/hash/blake2b.rb @@ -13,7 +13,7 @@ class Blake2b # Create a new Blake2b hash object # # @param [Hash] opts Blake2b configuration - # @option opts [String] :key for Blake2b keyed mode + # @option opts [String] :key for Blake2b keyed mode # @option opts [Integer] :digest_size size of output digest in bytes # # @raise [Crypto::LengthError] Invalid length specified for one or more options @@ -31,13 +31,12 @@ def initialize(opts = {}) # Calculate a Blake2b hash # # @param [String] message Message to be hashed - # @param [#to_sym] encoding Encoding of the returned hash # # @return [String] Blake2b digest of the string as raw bytes - def hash(message, encoding = :raw) + def hash(message) digest = Util.zeros(@digest_size) NaCl.crypto_hash_blake2b(digest, @digest_size, message, message.bytesize, @key, @key_size) || raise(CryptoError, "Hashing failed!") - Encoder[encoding].encode(digest) + digest end end end diff --git a/lib/rbnacl/keys/private_key.rb b/lib/rbnacl/keys/private_key.rb index c0aa1c9..30dc44e 100644 --- a/lib/rbnacl/keys/private_key.rb +++ b/lib/rbnacl/keys/private_key.rb @@ -28,8 +28,8 @@ class PrivateKey # @raise [Crypto::LengthError] If the key is not valid after decoding. # # @return A new PrivateKey - def initialize(private_key, key_encoding = :raw) - @private_key = Crypto::Encoder[key_encoding].decode(private_key) + def initialize(private_key) + @private_key = private_key.to_str Util.check_length(@private_key, BYTES, "Private key") end diff --git a/lib/rbnacl/keys/public_key.rb b/lib/rbnacl/keys/public_key.rb index 566378e..3f54e14 100644 --- a/lib/rbnacl/keys/public_key.rb +++ b/lib/rbnacl/keys/public_key.rb @@ -18,13 +18,12 @@ class PublicKey # the exchanging of messages using a Crypto::Box # # @param public_key [String] The public key - # @param key_encoding [Symbol] The encoding of the key # # @raise [Crypto::LengthError] If the key is not valid after decoding. # # @return A new PublicKey - def initialize(public_key, key_encoding = :raw) - @public_key = Crypto::Encoder[key_encoding].decode(public_key) + def initialize(public_key) + @public_key = public_key.to_str Util.check_length(@public_key, BYTES, "Public key") end diff --git a/lib/rbnacl/keys/signing_key.rb b/lib/rbnacl/keys/signing_key.rb index 3b08ccd..37124f4 100644 --- a/lib/rbnacl/keys/signing_key.rb +++ b/lib/rbnacl/keys/signing_key.rb @@ -33,11 +33,10 @@ def self.generate # Create a SigningKey from a seed value # # @param seed [String] Random 32-byte value (i.e. private key) - # @param encoding [Symbol] Parse seed from the given encoding # # @return [Crypto::SigningKey] Key which can sign messages - def initialize(seed, encoding = :raw) - seed = Encoder[encoding].decode(seed) + def initialize(seed) + seed = seed.to_s Util.check_length(seed, NaCl::ED25519_SEED_BYTES, "seed") @@ -53,17 +52,15 @@ def initialize(seed, encoding = :raw) # Sign a message using this key # # @param message [String] Message to be signed by this key - # @param encoding [Symbol] Encode signature in the given format # # @return [String] Signature as bytes - def sign(message, encoding = :raw) + def sign(message) buffer = Util.prepend_zeros(signature_bytes, message) buffer_len = Util.zeros(FFI::Type::LONG_LONG.size) NaCl.crypto_sign_ed25519(buffer, buffer_len, message, message.bytesize, @signing_key) - signature = buffer[0, signature_bytes] - Encoder[encoding].encode(signature) + buffer[0, signature_bytes] end # Return the raw seed value of this key diff --git a/lib/rbnacl/keys/verify_key.rb b/lib/rbnacl/keys/verify_key.rb index 9ba326f..6d761f4 100644 --- a/lib/rbnacl/keys/verify_key.rb +++ b/lib/rbnacl/keys/verify_key.rb @@ -13,35 +13,24 @@ class VerifyKey include KeyComparator include Serializable - # Create a new VerifyKey object from a serialized public key. The key can - # be decoded from any serialization format supported by the - # Crypto::Encoding system. + # Create a new VerifyKey object from a serialized public key. # # @param key [String] Serialized Ed25519 public key - # @param encoding [Symbol] Parse key from the given encoding # # @return [Crypto::SigningKey] Key which can sign messages - def initialize(key, encoding = :raw) - key = Encoder[encoding].decode(key) - Util.check_length(key, NaCl::ED25519_VERIFYKEY_BYTES, "key") - - @key = key + def initialize(key) + @key = key.to_str + Util.check_length(@key, NaCl::ED25519_VERIFYKEY_BYTES, "key") end - # Create a new VerifyKey object from a serialized public key. The key can - # be decoded from any serialization format supported by the - # Crypto::Encoding system. - # - # You can remember the argument ordering by "verify message with signature" - # It's like a legal document, with the signature at the end. + # Verify a signature for a given message # # @param message [String] Message to be authenticated # @param signature [String] Alleged signature to be checked - # @param signature_encoding [Symbol] Parse signature from the given encoding # # @return [Boolean] was the signature authentic? - def verify(message, signature, signature_encoding = :raw) - signature = Encoder[signature_encoding].decode(signature) + def verify(message, signature) + signature = signature.to_str Util.check_length(signature, signature_bytes, "signature") sig_and_msg = signature + message @@ -51,7 +40,7 @@ def verify(message, signature, signature_encoding = :raw) NaCl.crypto_sign_ed25519_open(buffer, buffer_len, sig_and_msg, sig_and_msg.bytesize, @key) end - # "Dangerous" (but probably safer) verify that raises an exception if a + # "Dangerous" (but really safer) verify that raises an exception if a # signature check fails. This is probably less likely to go unnoticed than # an improperly checked verify, as you are forced to deal with the # exception explicitly (and failing signature checks are certainly an @@ -61,11 +50,10 @@ def verify(message, signature, signature_encoding = :raw) # # @param message [String] Message to be authenticated # @param signature [String] Alleged signature to be checked - # @param signature_encoding [Symbol] Parse signature from the given encoding # # @return [true] Will raise BadSignatureError if signature check fails - def verify!(message, signature, signature_encoding = :raw) - verify(message, signature, signature_encoding) or raise BadSignatureError, "signature was forged/corrupt" + def verify!(message, signature) + verify(message, signature) or raise BadSignatureError, "signature was forged/corrupt" end # Return the raw key in byte format diff --git a/lib/rbnacl/point.rb b/lib/rbnacl/point.rb index 524ddf3..32f239e 100644 --- a/lib/rbnacl/point.rb +++ b/lib/rbnacl/point.rb @@ -1,7 +1,7 @@ # encoding: binary module Crypto # NaCl's base point (a.k.a. standard group element), serialized as hex - STANDARD_GROUP_ELEMENT = "0900000000000000000000000000000000000000000000000000000000000000".freeze + STANDARD_GROUP_ELEMENT = ["0900000000000000000000000000000000000000000000000000000000000000"].pack("H*").freeze # Order of the standard group STANDARD_GROUP_ORDER = 2**252 + 27742317777372353535851937790883648493 @@ -23,12 +23,11 @@ class Point # Creates a new Point from the given serialization # - # @param value [String] 32-byte value representing a group element - # @param encoding [Symbol] The encoding format of the group element + # @param [String] point location of a group element (32-bytes) # - # @return [Crypto::Point] New Crypto::Point object - def initialize(value, encoding = :raw) - @point = Encoder[encoding].decode(value) + # @return [Crypto::Point] the Point at this location + def initialize(point) + @point = point.to_str # FIXME: really should have a separate constant here for group element size # Group elements and scalars are both 32-bits, but that's for convenience @@ -39,12 +38,11 @@ def initialize(value, encoding = :raw) # This ordering is a bit confusing because traditionally the point # would be the right-hand operand. # - # @param integer [String] 32-byte integer value - # @param encoding [Symbol] The encoding format of the integer + # @param [String] integer value to multiply with this Point (32-bytes) # - # @return [Crypto::Point] Result as a Point object + # @return [Crypto::Point] result as a Point object def mult(integer, encoding = :raw) - integer = Encoder[encoding].decode(integer) + integer = integer.to_str Util.check_length(integer, SCALARBYTES, "integer") result = Util.zeros(SCALARBYTES) @@ -58,7 +56,7 @@ def mult(integer, encoding = :raw) # @return [String] 32-byte string representing this point def to_bytes; @point; end - @base_point = Point.new(STANDARD_GROUP_ELEMENT, :hex) + @base_point = Point.new(STANDARD_GROUP_ELEMENT) # NaCl's standard base point for all Curve25519 public keys # diff --git a/lib/rbnacl/random_nonce_box.rb b/lib/rbnacl/random_nonce_box.rb index 96fa69b..dfb487d 100644 --- a/lib/rbnacl/random_nonce_box.rb +++ b/lib/rbnacl/random_nonce_box.rb @@ -75,13 +75,12 @@ def self.from_keypair(private_key, public_key) # the nonce prepended. Optionally encodes the message using an encoder. # # @param message [String] The message to encrypt - # @param encoding [Symbol] Optional encoding for the returned ciphertext # # @return [String] The enciphered message - def box(message, encoding = :raw) + def box(message) nonce = generate_nonce cipher_text = @box.box(nonce, message) - Encoder[encoding].encode(nonce + cipher_text) + nonce + cipher_text end alias encrypt box @@ -91,14 +90,12 @@ def box(message, encoding = :raw) # front and uses this to decrypt. Returns the message. # # @param enciphered_message [String] The message to decrypt. - # @param encoding [Symbol] Optional decoding for the returned ciphertext # # @raise [CryptoError] If the message has been tampered with. # # @return [String] The decoded message - def open(enciphered_message, encoding = :raw) - decoded = Encoder[encoding].decode(enciphered_message) - nonce, ciphertext = *extract_nonce(decoded) + def open(enciphered_message) + nonce, ciphertext = extract_nonce(enciphered_message.to_s) @box.open(nonce, ciphertext) end alias decrypt open diff --git a/lib/rbnacl/secret_box.rb b/lib/rbnacl/secret_box.rb index af6886b..43c43ae 100644 --- a/lib/rbnacl/secret_box.rb +++ b/lib/rbnacl/secret_box.rb @@ -28,13 +28,12 @@ class SecretBox # Sets up the Box with a secret key fro encrypting and decrypting messages. # # @param key [String] The key to encrypt and decrypt with - # @param encoding [Symbol] Parse key from the given encoding # # @raise [Crypto::LengthError] on invalid keys # # @return [Crypto::SecretBox] The new Box, ready to use - def initialize(key, encoding = :raw) - @key = Encoder[encoding].decode(key) if key + def initialize(key) + @key = key.to_str Util.check_length(@key, KEYBYTES, "Secret key") end diff --git a/lib/rbnacl/self_test.rb b/lib/rbnacl/self_test.rb index a37a530..a60d74e 100644 --- a/lib/rbnacl/self_test.rb +++ b/lib/rbnacl/self_test.rb @@ -6,23 +6,27 @@ class SelfTestFailure < Crypto::CryptoError; end module SelfTest module_function + def vector(name) + [TestVectors[name]].pack("H*") + end + def box_test - alicepk = Crypto::PublicKey.new(TestVectors[:alice_public], :hex) - bobsk = Crypto::PrivateKey.new(TestVectors[:bob_private], :hex) + alicepk = Crypto::PublicKey.new(vector(:alice_public)) + bobsk = Crypto::PrivateKey.new(vector(:bob_private)) box = Crypto::Box.new(alicepk, bobsk) box_common_test(box) end def secret_box_test - box = SecretBox.new(TestVectors[:secret_key], :hex) + box = SecretBox.new(vector(:secret_key)) box_common_test(box) end def box_common_test(box) - nonce = hexdecode_vector :box_nonce - message = hexdecode_vector :box_message - ciphertext = hexdecode_vector :box_ciphertext + nonce = vector :box_nonce + message = vector :box_message + ciphertext = vector :box_ciphertext unless box.encrypt(nonce, message) == ciphertext raise SelfTestFailure, "failed to generate correct ciphertext" @@ -45,34 +49,34 @@ def box_common_test(box) end def digital_signature_test - signing_key = SigningKey.new(TestVectors[:sign_private], :hex) + signing_key = SigningKey.new(vector(:sign_private)) verify_key = signing_key.verify_key - unless verify_key.to_s(:hex) == TestVectors[:sign_public] + unless verify_key.to_s == vector(:sign_public) raise SelfTestFailure, "failed to generate verify key correctly" end - message = hexdecode_vector :sign_message - signature = signing_key.sign(message, :hex) + message = vector :sign_message + signature = signing_key.sign(message) - unless signature == TestVectors[:sign_signature] + unless signature == vector(:sign_signature) raise SelfTestFailure, "failed to generate correct signature" end - unless verify_key.verify(message, signature, :hex) + unless verify_key.verify(message, signature) raise SelfTestFailure, "failed to verify a valid signature" end - bad_signature = signature[0,127] + '0' + bad_signature = signature[0,63] + '0' - unless verify_key.verify(message, bad_signature, :hex) == false + unless verify_key.verify(message, bad_signature) == false raise SelfTestFailure, "failed to detect an invalid signature" end end def sha256_test - message = hexdecode_vector :sha256_message - digest = hexdecode_vector :sha256_digest + message = vector :sha256_message + digest = vector :sha256_digest unless Crypto::Hash.sha256(message) == digest raise SelfTestFailure, "failed to generate a correct SHA256 digest" @@ -80,30 +84,22 @@ def sha256_test end def hmac_test(klass, tag) - authenticator = klass.new(TestVectors[:auth_key], :hex) + authenticator = klass.new(vector(:auth_key)) - message = hexdecode_vector :auth_message + message = vector :auth_message - unless authenticator.auth(message, :hex) == TestVectors[tag] + unless authenticator.auth(message) == vector(tag) raise SelfTestFailure, "#{klass} failed to generate correct authentication tag" end - unless authenticator.verify(message, TestVectors[tag], :hex) + unless authenticator.verify(message, vector(tag)) raise SelfTestFailure, "#{klass} failed to verify correct authentication tag" end - if authenticator.verify(message+' ', TestVectors[tag], :hex) + if authenticator.verify(message+' ', vector(tag)) raise SelfTestFailure, "#{klass} failed to detect invalid authentication tag" end end - - def hexdecode(string) - Encoder[:hex].decode(string) - end - - def hexdecode_vector(name) - hexdecode TestVectors[name] - end end end diff --git a/lib/rbnacl/serializable.rb b/lib/rbnacl/serializable.rb index 0684e56..8061ea2 100644 --- a/lib/rbnacl/serializable.rb +++ b/lib/rbnacl/serializable.rb @@ -2,16 +2,8 @@ module Crypto # Serialization features shared across all "key-like" classes module Serializable - # Return a string representation of this key, possibly encoded into a - # given serialization format. - # - # @param encoding [String] string encoding format in which to encode the key - # - # @return [String] key encoded in the specified format - def to_s(encoding = :raw) - Encoder[encoding].encode(to_bytes) - end - alias_method :to_str, :to_s + def to_s; to_bytes; end + def to_str; to_bytes; end # Inspect this key # diff --git a/lib/rbnacl/test_vectors.rb b/lib/rbnacl/test_vectors.rb index 7ba463f..744bf16 100644 --- a/lib/rbnacl/test_vectors.rb +++ b/lib/rbnacl/test_vectors.rb @@ -50,8 +50,41 @@ module Crypto :sha256_message => "6162636462636465636465666465666765666768666768696768696a68696a6b" + "696a6b6c6a6b6c6d6b6c6d6e6c6d6e6f6d6e6f706e6f7071", :sha256_digest => "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1", + :sha256_empty => "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", # + # SHA512 test vectors + # self-created (FIXME: find standard test vectors) + :sha512_message => "54686520717569636b2062726f776e20666f78206a756d7073206f7665722074" + + "6865206c617a7920646f672e", + :sha512_digest => "91ea1245f20d46ae9a037a989f54f1f790f0a47607eeb8a14d12890cea77a1bb" + + "c6c7ed9cf205e67b7f2b8fd4c7dfd3a7a8617e45f3c463d481c7e586c39ac1ed", + :sha512_empty => "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce" + + "47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e", + + # Blake2b test vectors + # self-created? (TODO: double check, fix) + :blake2b_message => "54686520717569636b2062726f776e20666f78206a756d7073206f7665722074" + + "6865206c617a7920646f67", + :blake2b_digest => "a8add4bdddfd93e4877d2746e62817b116364a1fa7bc148d95090bc7333b3673" + + "f82401cf7aa2e4cb1ecd90296e3f14cb5413f8ed77be73045b13914cdcd6a918", + :blake2b_empty => "786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419" + + "d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce", + + # from the Blake2 paper(?) (TODO: double check) + :blake2b_keyed_message => "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + + "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f" + + "a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + + "e0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe", + :blake2b_key => "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + :blake2b_keyed_digest => "142709d62e28fcccd0af97fad0f8465b971e82201dc51070faa0372aa43e9248" + + "4be1c1e73ba10906d5d1853db6a4106e0a7bf9800d373d6dee2d46d62ef2a461", + # Auth test vectors # Taken from NaCl distribution # diff --git a/spec/rbnacl/auth/one_time_spec.rb b/spec/rbnacl/auth/one_time_spec.rb index 1ecd3cc..6249bb1 100644 --- a/spec/rbnacl/auth/one_time_spec.rb +++ b/spec/rbnacl/auth/one_time_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe Crypto::Auth::OneTime do - let(:hex_tag) { hex_vector :auth_onetime } + let(:tag) { vector :auth_onetime } include_examples "authenticator" end diff --git a/spec/rbnacl/box_spec.rb b/spec/rbnacl/box_spec.rb index e91e691..d651bb2 100644 --- a/spec/rbnacl/box_spec.rb +++ b/spec/rbnacl/box_spec.rb @@ -2,17 +2,14 @@ require 'spec_helper' describe Crypto::Box do - let(:alicepk_hex) { hex_vector :alice_public } - let(:bobsk_hex) { hex_vector :bob_private } - - let(:alicepk) { hex2bytes(alicepk_hex) } - let(:bobsk) { hex2bytes(bobsk_hex) } + let(:alicepk) { vector :alice_public } + let(:bobsk) { vector :bob_private } let(:alice_key) { Crypto::PublicKey.new(alicepk) } let(:bob_key) { Crypto::PrivateKey.new(bobsk) } context "new" do it "accepts strings" do - expect { Crypto::Box.new(alicepk_hex, bobsk_hex, :hex) }.to_not raise_error(Exception) + expect { Crypto::Box.new(alicepk, bobsk) }.to_not raise_error(Exception) end it "accepts KeyPairs" do @@ -20,7 +17,8 @@ end it "raises on a nil public key" do - expect { Crypto::Box.new(nil, bobsk) }.to raise_error(Crypto::LengthError, /Public key was 0 bytes \(Expected 32\)/) + expect { Crypto::Box.new(nil, bobsk) }.to raise_error(NoMethodError) + pending "is a failed #to_s (NoMethodError) here sufficient?" end it "raises on an invalid public key" do @@ -28,7 +26,8 @@ end it "raises on a nil secret key" do - expect { Crypto::Box.new(alicepk, nil) }.to raise_error(Crypto::LengthError, /Private key was 0 bytes \(Expected 32\)/) + expect { Crypto::Box.new(alicepk, nil) }.to raise_error(NoMethodError) + pending "is a failed #to_s (NoMethodError) here sufficient?" end it "raises on an invalid secret key" do diff --git a/spec/rbnacl/encoder_spec.rb b/spec/rbnacl/encoder_spec.rb deleted file mode 100644 index 7b031c1..0000000 --- a/spec/rbnacl/encoder_spec.rb +++ /dev/null @@ -1,14 +0,0 @@ -# encoding: binary -require 'spec_helper' - -describe Crypto::Encoder do - it "registers encoders" do - expect { Crypto::Encoder[:foobar] }.to raise_exception(ArgumentError) - - class FoobarEncoder < described_class - register :foobar - end - - Crypto::Encoder[:foobar].should be_a FoobarEncoder - end -end \ No newline at end of file diff --git a/spec/rbnacl/encoders/base32_spec.rb b/spec/rbnacl/encoders/base32_spec.rb deleted file mode 100644 index 28f5da1..0000000 --- a/spec/rbnacl/encoders/base32_spec.rb +++ /dev/null @@ -1,16 +0,0 @@ -# encoding: binary -require 'spec_helper' -require 'rbnacl/encoders/base32' - -describe Crypto::Encoders::Base32 do - let(:source) { "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789" } - let(:base32) { "mfrggzdfmztwq2lknnwg23tpobyxe43uov3ho6dzpiydcmrtgq2tmnzyhfqwey3emvtgo2djnjvwy3lon5yhc4ttor2xm53ypf5damjsgm2dknrxha4wcytdmrswmz3infvgw3dnnzxxa4lson2hk5txpb4xumbrgiztinjwg44ds===" } - - it "encodes to base32" do - subject.encode(source).should eq base32 - end - - it "decodes from base32" do - subject.decode(base32).should eq source - end -end diff --git a/spec/rbnacl/encoders/base64_spec.rb b/spec/rbnacl/encoders/base64_spec.rb deleted file mode 100644 index c714b60..0000000 --- a/spec/rbnacl/encoders/base64_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -# encoding: binary -require 'spec_helper' - -describe Crypto::Encoders::Base64 do - let(:source) { "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789" } - let(:base64) { "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5" } - - it "encodes to base64" do - subject.encode(source).should eq base64 - end - - it "decodes from base64" do - subject.decode(base64).should eq source - end -end diff --git a/spec/rbnacl/encoders/hex_spec.rb b/spec/rbnacl/encoders/hex_spec.rb deleted file mode 100644 index c0068a7..0000000 --- a/spec/rbnacl/encoders/hex_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -# encoding: binary -require 'spec_helper' - -describe Crypto::Encoders::Hex do - let (:bytes) { [0xDE,0xAD,0xBE,0xEF].pack('c*') } - let (:hex) { "deadbeef" } - - it "encodes to hex" do - subject.encode(bytes).should eq hex - end - - it "decodes from hex" do - subject.decode(hex).should eq bytes - end -end diff --git a/spec/rbnacl/hash_spec.rb b/spec/rbnacl/hash_spec.rb index aef4046..63788bb 100644 --- a/spec/rbnacl/hash_spec.rb +++ b/spec/rbnacl/hash_spec.rb @@ -3,11 +3,9 @@ describe Crypto::Hash do context "sha256" do - let(:reference_string) { test_vector :sha256_message } - let(:reference_string_hash) { test_vector :sha256_digest } - let(:reference_string_hash_hex) { bytes2hex reference_string_hash } - let(:empty_string_hash_hex) { "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" } - let(:empty_string_hash) { hex2bytes empty_string_hash_hex } + let(:reference_string) { vector :sha256_message } + let(:reference_string_hash) { vector :sha256_digest } + let(:empty_string_hash) { vector :sha256_empty } it "calculates the correct hash for a reference string" do Crypto::Hash.sha256(reference_string).should eq reference_string_hash @@ -17,25 +15,15 @@ Crypto::Hash.sha256("").should eq empty_string_hash end - it "calculates the correct hash for a reference string and returns it in hex" do - Crypto::Hash.sha256(reference_string, :hex).should eq reference_string_hash_hex - end - - it "calculates the correct hash for an empty string and returns it in hex" do - Crypto::Hash.sha256("", :hex).should eq empty_string_hash_hex - end - it "doesn't raise on a null byte" do - expect { Crypto::Hash.sha256("\0") }.to_not raise_error(/ArgumentError: string contains null byte/) + expect { Crypto::Hash.sha256("\0") }.to_not raise_error(/ArgumentError: string contains null byte/) end end context "sha512" do - let(:reference_string) { "The quick brown fox jumps over the lazy dog." } - let(:reference_string_hash_hex) { "91ea1245f20d46ae9a037a989f54f1f790f0a47607eeb8a14d12890cea77a1bbc6c7ed9cf205e67b7f2b8fd4c7dfd3a7a8617e45f3c463d481c7e586c39ac1ed" } - let(:empty_string_hash_hex) { "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e" } - let(:reference_string_hash) { hex2bytes reference_string_hash_hex } - let(:empty_string_hash) { hex2bytes empty_string_hash_hex } + let(:reference_string) { vector :sha512_message } + let(:reference_string_hash) { vector :sha512_digest } + let(:empty_string_hash) { vector :sha512_empty } it "calculates the correct hash for a reference string" do Crypto::Hash.sha512(reference_string).should eq reference_string_hash @@ -45,26 +33,16 @@ Crypto::Hash.sha512("").should eq empty_string_hash end - it "calculates the correct hash for a reference string and returns it in hex" do - Crypto::Hash.sha512(reference_string, :hex).should eq reference_string_hash_hex - end - - it "calculates the correct hash for an empty string and returns it in hex" do - Crypto::Hash.sha512("", :hex).should eq empty_string_hash_hex - end - it "doesn't raise on a null byte" do - expect { Crypto::Hash.sha512("\0") }.to_not raise_error(/ArgumentError: string contains null byte/) + expect { Crypto::Hash.sha512("\0") }.to_not raise_error(/ArgumentError: string contains null byte/) end end if Crypto::NaCl.supported_version? :libsodium, '0.4.0' context "blake2b" do - let(:reference_string) { 'The quick brown fox jumps over the lazy dog' } - let(:reference_string_hash_hex) { 'a8add4bdddfd93e4877d2746e62817b116364a1fa7bc148d95090bc7333b3673f82401cf7aa2e4cb1ecd90296e3f14cb5413f8ed77be73045b13914cdcd6a918' } - let(:empty_string_hash_hex) { '786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce' } - let(:reference_string_hash) { hex2bytes reference_string_hash_hex } - let(:empty_string_hash) { hex2bytes empty_string_hash_hex } + let(:reference_string) { vector :blake2b_message } + let(:reference_string_hash) { vector :blake2b_digest } + let(:empty_string_hash) { vector :blake2b_empty } it "calculates the correct hash for a reference string" do Crypto::Hash.blake2b(reference_string).should eq reference_string_hash @@ -75,12 +53,9 @@ end context "keyed" do - let(:reference_string_hex) { "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe" } - let(:reference_string) { hex2bytes reference_string_hex } - let(:reference_string_hash_hex) { "142709d62e28fcccd0af97fad0f8465b971e82201dc51070faa0372aa43e92484be1c1e73ba10906d5d1853db6a4106e0a7bf9800d373d6dee2d46d62ef2a461" } - let(:reference_string_hash) { hex2bytes reference_string_hash_hex } - let(:reference_key_hex) { "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" } - let(:reference_key) { hex2bytes reference_key_hex } + let(:reference_string) { vector :blake2b_keyed_message } + let(:reference_key) { vector :blake2b_key } + let(:reference_string_hash) { vector :blake2b_keyed_digest } it "calculates keyed hashes correctly" do Crypto::Hash.blake2b(reference_string, :key => reference_key).should eq reference_string_hash diff --git a/spec/rbnacl/hmac/sha256_spec.rb b/spec/rbnacl/hmac/sha256_spec.rb index 7685eb9..3be2dd0 100644 --- a/spec/rbnacl/hmac/sha256_spec.rb +++ b/spec/rbnacl/hmac/sha256_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe Crypto::HMAC::SHA256 do - let(:hex_tag) { hex_vector :auth_hmacsha256 } + let(:tag) { vector :auth_hmacsha256 } include_examples "authenticator" end diff --git a/spec/rbnacl/hmac/sha512256_spec.rb b/spec/rbnacl/hmac/sha512256_spec.rb index f866bbe..44de171 100644 --- a/spec/rbnacl/hmac/sha512256_spec.rb +++ b/spec/rbnacl/hmac/sha512256_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe Crypto::HMAC::SHA512256 do - let(:hex_tag) { hex_vector :auth_hmacsha512256 } + let(:tag) { vector :auth_hmacsha512256 } include_examples "authenticator" end diff --git a/spec/rbnacl/keys/private_key_spec.rb b/spec/rbnacl/keys/private_key_spec.rb index 91857c7..b5f9ce0 100644 --- a/spec/rbnacl/keys/private_key_spec.rb +++ b/spec/rbnacl/keys/private_key_spec.rb @@ -2,10 +2,8 @@ require 'spec_helper' describe Crypto::PrivateKey do - let(:bobsk) { test_vector :bob_private } - let(:bobsk_hex) { bytes2hex bobsk } - let(:bobpk) { test_vector :bob_public } - let(:bobpk_hex) { bytes2hex bobpk } + let(:bobsk) { vector :bob_private } + let(:bobpk) { vector :bob_public } subject { Crypto::PrivateKey.new(bobsk) } @@ -25,12 +23,12 @@ it "accepts a valid key" do expect { Crypto::PrivateKey.new(bobsk) }.not_to raise_error end - it "accepts a hex encoded key" do - expect { Crypto::PrivateKey.new(bobsk_hex, :hex) }.not_to raise_error - end + it "rejects a nil key" do - expect { Crypto::PrivateKey.new(nil) }.to raise_error(ArgumentError) + expect { Crypto::PrivateKey.new(nil) }.to raise_error(NoMethodError) + pending "is a failed #to_s (NoMethodError) here sufficient?" end + it "rejects a short key" do expect { Crypto::PrivateKey.new("short") }.to raise_error(ArgumentError) end @@ -40,21 +38,19 @@ it "returns a public key" do subject.public_key.should be_a Crypto::PublicKey end + it "returns the correct public key" do - subject.public_key.to_s(:hex).should eql bobpk_hex + subject.public_key.to_s.should eql bobpk end end context "#to_bytes" do it "returns the bytes of the key" do - subject.to_s(:hex).should eq bobsk_hex + subject.to_s.should eq bobsk end end context "#to_s" do - it "returns the bytes of the key hex encoded" do - subject.to_s(:hex).should eq bobsk_hex - end it "returns the raw bytes of the key" do subject.to_bytes.should eq bobsk end diff --git a/spec/rbnacl/keys/public_key_spec.rb b/spec/rbnacl/keys/public_key_spec.rb index 4630f7e..5c84714 100644 --- a/spec/rbnacl/keys/public_key_spec.rb +++ b/spec/rbnacl/keys/public_key_spec.rb @@ -2,8 +2,7 @@ require 'spec_helper' describe Crypto::PublicKey do - let(:alicepk) { test_vector :alice_public } - let(:alicepk_hex) { bytes2hex alicepk } + let(:alicepk) { vector :alice_public } subject { Crypto::PublicKey.new(alicepk) } @@ -11,12 +10,12 @@ it "accepts a valid key" do expect { Crypto::PublicKey.new(alicepk) }.not_to raise_error end - it "accepts a valid key in hex" do - expect { Crypto::PublicKey.new(alicepk_hex, :hex) }.not_to raise_error - end + it "rejects a nil key" do - expect { Crypto::PublicKey.new(nil) }.to raise_error(ArgumentError) + expect { Crypto::PublicKey.new(nil) }.to raise_error(NoMethodError) + pending "is a failed #to_s (NoMethodError) here sufficient?" end + it "rejects a short key" do expect { Crypto::PublicKey.new("short") }.to raise_error(ArgumentError) end @@ -32,9 +31,6 @@ it "returns the bytes of the key" do subject.to_s.should eq alicepk end - it "returns the bytes of the key hex encoded" do - subject.to_s(:hex).should eq alicepk_hex - end end include_examples "key equality" do diff --git a/spec/rbnacl/keys/signing_key_spec.rb b/spec/rbnacl/keys/signing_key_spec.rb index 2b79772..bd7b3d9 100644 --- a/spec/rbnacl/keys/signing_key_spec.rb +++ b/spec/rbnacl/keys/signing_key_spec.rb @@ -2,14 +2,11 @@ require 'spec_helper' describe Crypto::SigningKey do - let(:signing_key_hex) { hex_vector :sign_private } - let(:signing_key) { hex2bytes signing_key_hex } + let(:signing_key) { vector :sign_private } + let(:message) { vector :sign_message } + let(:signature) { vector :sign_signature } - let(:message) { test_vector :sign_message } - let(:signature) { test_vector :sign_signature } - - # NOTE: this implicitly covers testing initialization from bytes - subject { described_class.new(signing_key_hex, :hex) } + subject { described_class.new(signing_key) } it "generates keys" do described_class.generate.should be_a described_class @@ -19,14 +16,6 @@ subject.sign(message).should eq signature end - it "signs messages as hex" do - subject.sign(message, :hex).should eq bytes2hex signature - end - - it "serializes to hex" do - subject.to_s(:hex).should eq signing_key_hex - end - it "serializes to bytes" do subject.to_bytes.should eq signing_key end diff --git a/spec/rbnacl/keys/verify_key_spec.rb b/spec/rbnacl/keys/verify_key_spec.rb index 1cc30ea..26e2c28 100644 --- a/spec/rbnacl/keys/verify_key_spec.rb +++ b/spec/rbnacl/keys/verify_key_spec.rb @@ -1,51 +1,37 @@ # encoding: binary describe Crypto::VerifyKey do - let(:signing_key) { hex_vector :sign_private } - let(:verify_key) { hex_vector :sign_public } - let(:verify_key_raw) { hex2bytes verify_key } + let(:signing_key) { vector :sign_private } + let(:verify_key) { vector :sign_public } - let(:message) { test_vector :sign_message } - let(:signature) { hex_vector :sign_signature } - let(:signature_raw) { hex2bytes signature } + let(:message) { vector :sign_message } + let(:signature) { vector :sign_signature } let(:bad_signature) { sig = signature.dup; sig[0] = (sig[0].ord + 1).chr; sig } - subject { Crypto::SigningKey.new(signing_key, :hex).verify_key } + subject { Crypto::SigningKey.new(signing_key).verify_key } it "verifies correct signatures" do - subject.verify(message, signature_raw).should be_true - end - - it "verifies correct hex signatures" do - subject.verify(message, signature, :hex).should be_true + subject.verify(message, signature).should be_true end it "detects bad signatures" do - subject.verify(message, bad_signature, :hex).should be_false + subject.verify(message, bad_signature).should be_false end it "raises when asked to verify with a bang" do - expect { subject.verify!(message, bad_signature, :hex) }.to raise_exception Crypto::BadSignatureError + expect { subject.verify!(message, bad_signature) }.to raise_exception Crypto::BadSignatureError end it "serializes to bytes" do - subject.to_bytes.should eq verify_key_raw - end - - it "serializes to hex" do - subject.to_s(:hex).should eq verify_key + subject.to_bytes.should eq verify_key end it "initializes from bytes" do - described_class.new(verify_key_raw).to_s(:hex).should eq verify_key - end - - it "initializes from hex" do - described_class.new(verify_key, :hex).to_s(:hex).should eq verify_key + described_class.new(verify_key).to_s.should eq verify_key end include_examples "key equality" do - let(:key_bytes) { verify_key_raw } - let(:key) { described_class.new(key_bytes) } + let(:key_bytes) { verify_key } + let(:key) { described_class.new(verify_key) } let(:other_key) { described_class.new("B"*32) } end end diff --git a/spec/rbnacl/point_spec.rb b/spec/rbnacl/point_spec.rb index a25a134..046e005 100644 --- a/spec/rbnacl/point_spec.rb +++ b/spec/rbnacl/point_spec.rb @@ -2,12 +2,12 @@ require 'spec_helper' describe Crypto::Point do - let(:alice_private) { test_vector :alice_private } - let(:alice_public) { test_vector :alice_public } + let(:alice_private) { vector :alice_private } + let(:alice_public) { vector :alice_public } - let(:bob_public) { test_vector :bob_public } + let(:bob_public) { vector :bob_public } - let(:alice_mult_bob) { test_vector :alice_mult_bob } + let(:alice_mult_bob) { vector :alice_mult_bob } subject { described_class.new(bob_public) } @@ -22,8 +22,4 @@ it "serializes to bytes" do subject.to_bytes.should eq bob_public end - - it "serializes to hex" do - subject.to_s(:hex).should eq bytes2hex bob_public - end end diff --git a/spec/rbnacl/random_nonce_box_spec.rb b/spec/rbnacl/random_nonce_box_spec.rb index b99268a..92b9900 100644 --- a/spec/rbnacl/random_nonce_box_spec.rb +++ b/spec/rbnacl/random_nonce_box_spec.rb @@ -2,10 +2,10 @@ require 'spec_helper' describe Crypto::RandomNonceBox do - let (:secret_key) { test_vector :secret_key } + let(:secret_key) { vector :secret_key } let(:secret_box) { Crypto::SecretBox.new(secret_key) } - let (:alicepk) { test_vector :alice_public } - let (:bobsk) { test_vector :bob_private } + let(:alicepk) { vector :alice_public } + let(:bobsk) { vector :bob_private } context "instantiation" do it "can be instantiated from an already existing box" do @@ -15,26 +15,29 @@ it "can be instantiated from a secret key" do Crypto::RandomNonceBox.from_secret_key(secret_key).should be_a Crypto::RandomNonceBox end + it "complains on an inappropriate secret key" do - expect { Crypto::RandomNonceBox.from_secret_key(nil) }.to raise_error(ArgumentError) + expect { Crypto::RandomNonceBox.from_secret_key(nil) }.to raise_error(NoMethodError) + pending "is a failed #to_s (NoMethodError) here sufficient?" end + it "can be instantiated from a key-pair" do Crypto::RandomNonceBox.from_keypair(alicepk, bobsk).should be_a Crypto::RandomNonceBox end + it "complains on an inappropriate key in the pair" do - expect { Crypto::RandomNonceBox.from_keypair(nil, bobsk) }.to raise_error(ArgumentError) + expect { Crypto::RandomNonceBox.from_keypair(nil, bobsk) }.to raise_error(NoMethodError) + pending "is a failed #to_s (NoMethodError) here sufficient?" end end - - context "cryptography" do - let(:nonce) { test_vector :box_nonce } - let(:message) { test_vector :box_message } - let(:ciphertext) { test_vector :box_ciphertext } + let(:nonce) { vector :box_nonce } + let(:message) { vector :box_message } + let(:ciphertext) { vector :box_ciphertext } let(:random_box) { Crypto::RandomNonceBox.from_keypair(alicepk, bobsk) } let(:enciphered_message) { random_box.box(message) } - let(:enciphered_message_hex) { random_box.box(message, :hex) } + let(:enciphered_message_hex) { random_box.box(message) } it "descrypts a message with a 'random' nonce" do random_box.open(nonce+ciphertext).should eql message @@ -43,12 +46,5 @@ it "can successfully round-trip a message" do random_box.open(enciphered_message).should eql message end - - it "can encode a ciphertext as hex" do - enciphered_message_hex.should match /\A[0-9a-f]+\z/ - end - it "can roundtrip a message as hex" do - random_box.open(enciphered_message_hex, :hex).should eql message - end end end diff --git a/spec/rbnacl/secret_box_spec.rb b/spec/rbnacl/secret_box_spec.rb index 34d6a95..b2357db 100644 --- a/spec/rbnacl/secret_box_spec.rb +++ b/spec/rbnacl/secret_box_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe Crypto::SecretBox do - let (:key) { test_vector :secret_key } + let (:key) { vector :secret_key } context "new" do it "accepts strings" do @@ -10,7 +10,8 @@ end it "raises on a nil key" do - expect { Crypto::SecretBox.new(nil) }.to raise_error(Crypto::LengthError, "Secret key was nil \(Expected #{Crypto::NaCl::SECRETKEYBYTES}\)") + expect { Crypto::SecretBox.new(nil) }.to raise_error(NoMethodError) + pending "is a failed #to_s (NoMethodError) here sufficient?" end it "raises on a short key" do diff --git a/spec/shared/authenticator.rb b/spec/shared/authenticator.rb index bde7694..88d8269 100644 --- a/spec/shared/authenticator.rb +++ b/spec/shared/authenticator.rb @@ -1,29 +1,28 @@ # encoding: binary shared_examples "authenticator" do - let (:hex_key) { hex_vector :auth_key } - let (:key) { test_vector :auth_key } - let (:message) { test_vector :auth_message } - let (:tag) { hex2bytes hex_tag } + let (:key) { vector :auth_key } + let (:message) { vector :auth_message } context ".new" do it "accepts a key" do - expect { described_class.new(key) }.to_not raise_error(ArgumentError) + expect { described_class.new(key) }.to_not raise_error(ArgumentError) end it "requires a key" do - expect { described_class.new }.to raise_error(ArgumentError) + expect { described_class.new }.to raise_error(ArgumentError) end it "raises on a nil key" do - expect { described_class.new(nil) }.to raise_error(ArgumentError) + expect { described_class.new(nil) }.to raise_error(NoMethodError) + pending "is a failed #to_s (NoMethodError) here sufficient?" end it "raises on a key which is too long" do - expect { described_class.new("\0"*33) }.to raise_error(ArgumentError) + expect { described_class.new("\0"*33) }.to raise_error(ArgumentError) end it "raises on a key which is too short" do - expect { described_class.new("\0"*31) }.to raise_error(ArgumentError) + expect { described_class.new("\0"*31) }.to raise_error(ArgumentError) end end @@ -33,11 +32,12 @@ end it "raises on a nil key" do - expect { described_class.auth(nil, message) }.to raise_error(ArgumentError) + expect { described_class.auth(nil, message) }.to raise_error(NoMethodError) + pending "is a failed #to_s (NoMethodError) here sufficient?" end it "raises on a key which is too long" do - expect { described_class.auth("\0"*33, message) }.to raise_error(ArgumentError) + expect { described_class.auth("\0"*33, message) }.to raise_error(ArgumentError) end end @@ -47,19 +47,22 @@ end it "raises on a nil key" do - expect { described_class.verify(nil, message, tag) }.to raise_error(ArgumentError) + expect { described_class.verify(nil, message, tag) }.to raise_error(NoMethodError) + pending "is a failed #to_s (NoMethodError) here sufficient?" end it "raises on a key which is too long" do - expect { described_class.verify("\0"*33, message, tag) }.to raise_error(ArgumentError) + expect { described_class.verify("\0"*33, message, tag) }.to raise_error(ArgumentError) end it "fails to validate an invalid authenticator" do described_class.verify(key, message+"\0", tag ).should be false end + it "fails to validate a short authenticator" do described_class.verify(key, message, tag[0,tag.bytesize - 2]).should be false end + it "fails to validate a long authenticator" do described_class.verify(key, message, tag+"\0").should be false end @@ -73,41 +76,23 @@ it "produces an authenticator" do authenticator.auth(message).should eq tag end - - it "produces a hex encoded authenticator" do - authenticator.auth(message, :hex).should eq hex_tag - end end context "#verify" do - context "raw bytes" do - it "verifies an authenticator" do - authenticator.verify(message, tag).should be true - end - it "fails to validate an invalid authenticator" do - authenticator.verify(tag, message+"\0").should be false - end - it "fails to validate a short authenticator" do - authenticator.verify(tag[0,tag.bytesize - 2], message).should be false - end - it "fails to validate a long authenticator" do - authenticator.verify(tag+"\0", message).should be false - end + it "verifies an authenticator" do + authenticator.verify(message, tag).should be true + end + + it "fails to validate an invalid authenticator" do + authenticator.verify(tag, message+"\0").should be false + end + + it "fails to validate a short authenticator" do + authenticator.verify(tag[0,tag.bytesize - 2], message).should be false end - context "hex" do - it "verifies an hexencoded authenticator" do - authenticator.verify(message, hex_tag, :hex).should be true - end - it "fails to validate an invalid authenticator" do - authenticator.verify(message+"\0", hex_tag , :hex).should be false - end - it "fails to validate a short authenticator" do - authenticator.verify( message, hex_tag[0,hex_tag.bytesize - 2], :hex).should be false - end - it "fails to validate a long authenticator" do - authenticator.verify(message, hex_tag+"00", :hex).should be false - end + it "fails to validate a long authenticator" do + authenticator.verify(tag+"\0", message).should be false end end end diff --git a/spec/shared/box.rb b/spec/shared/box.rb index 348b006..5ead9ee 100644 --- a/spec/shared/box.rb +++ b/spec/shared/box.rb @@ -3,11 +3,11 @@ require 'spec_helper' shared_examples "box" do - let(:nonce) { test_vector :box_nonce } + let(:nonce) { vector :box_nonce } let(:invalid_nonce) { nonce[0,12] } # too short! let(:invalid_nonce_long) { nonce + nonce } # too long! - let(:message) { test_vector :box_message } - let(:ciphertext) { test_vector :box_ciphertext } + let(:message) { vector :box_message } + let(:ciphertext) { vector :box_ciphertext } let (:nonce_error_regex) { /Nonce.*(Expected #{Crypto::NaCl::NONCEBYTES})/ } let(:corrupt_ciphertext) { ciphertext[80] = " " } # picked at random by fair diceroll diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 87c86af..f9f6c78 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,26 +1,13 @@ # encoding: binary -require 'rubygems' +require 'coveralls' +Coveralls.wear! + require 'bundler/setup' require 'rbnacl' require 'shared/box' require 'shared/authenticator' require 'shared/key_equality' -require 'coveralls' - -Coveralls.wear! - -def hex2bytes(hex) - Crypto::Encoder[:hex].decode(hex) -end - -def bytes2hex(bytes) - Crypto::Encoder[:hex].encode(bytes) -end - -def test_vector(name) - hex2bytes(hex_vector(name)) -end -def hex_vector(name) - Crypto::TestVectors[name] +def vector(name) + [Crypto::TestVectors[name]].pack("H*") end From 0aa5db89eb56567fed69967377f61c9700376e85 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sat, 10 Aug 2013 12:13:51 -0700 Subject: [PATCH 2/4] Raise TypeError when given nil keys This replaces previous NoMethodError #to_s exceptions with a TypeError informing users that the given class can't be coerced to a String with #to_str --- lib/rbnacl/auth.rb | 3 +-- lib/rbnacl/keys/private_key.rb | 4 ++-- lib/rbnacl/keys/public_key.rb | 3 +-- lib/rbnacl/secret_box.rb | 3 +-- lib/rbnacl/util.rb | 21 +++++++++++++++++++++ spec/rbnacl/box_spec.rb | 14 ++++++-------- spec/rbnacl/keys/private_key_spec.rb | 7 +++---- spec/rbnacl/keys/public_key_spec.rb | 3 +-- spec/rbnacl/random_nonce_box_spec.rb | 11 +++++------ spec/rbnacl/secret_box_spec.rb | 3 +-- spec/shared/authenticator.rb | 23 ++++++++++------------- 11 files changed, 52 insertions(+), 43 deletions(-) diff --git a/lib/rbnacl/auth.rb b/lib/rbnacl/auth.rb index 30dd749..8433cb5 100644 --- a/lib/rbnacl/auth.rb +++ b/lib/rbnacl/auth.rb @@ -19,8 +19,7 @@ class Auth # # @param [#to_str] key the key used for authenticators, 32 bytes. def initialize(key) - @key = key.to_str - Util.check_length(@key, key_bytes, "#{self.class} key") + @key = Util.check_string(key, key_bytes, "#{self.class} key") end # Compute authenticator for message diff --git a/lib/rbnacl/keys/private_key.rb b/lib/rbnacl/keys/private_key.rb index 30dc44e..a1a8006 100644 --- a/lib/rbnacl/keys/private_key.rb +++ b/lib/rbnacl/keys/private_key.rb @@ -25,12 +25,12 @@ class PrivateKey # @param private_key [String] The private key # @param key_encoding [Symbol] The encoding of the key # + # @raise [TypeError] If the key is nil # @raise [Crypto::LengthError] If the key is not valid after decoding. # # @return A new PrivateKey def initialize(private_key) - @private_key = private_key.to_str - Util.check_length(@private_key, BYTES, "Private key") + @private_key = Util.check_string(private_key, BYTES, "Private key") end # Generates a new keypair diff --git a/lib/rbnacl/keys/public_key.rb b/lib/rbnacl/keys/public_key.rb index 3f54e14..8c277c7 100644 --- a/lib/rbnacl/keys/public_key.rb +++ b/lib/rbnacl/keys/public_key.rb @@ -23,8 +23,7 @@ class PublicKey # # @return A new PublicKey def initialize(public_key) - @public_key = public_key.to_str - Util.check_length(@public_key, BYTES, "Public key") + @public_key = Util.check_string(public_key, BYTES, "Public key") end # The raw bytes of the key diff --git a/lib/rbnacl/secret_box.rb b/lib/rbnacl/secret_box.rb index 43c43ae..b33ee0b 100644 --- a/lib/rbnacl/secret_box.rb +++ b/lib/rbnacl/secret_box.rb @@ -33,8 +33,7 @@ class SecretBox # # @return [Crypto::SecretBox] The new Box, ready to use def initialize(key) - @key = key.to_str - Util.check_length(@key, KEYBYTES, "Secret key") + @key = Util.check_string(key, KEYBYTES, "Secret key") end # Encrypts a message diff --git a/lib/rbnacl/util.rb b/lib/rbnacl/util.rb index 82ba462..9e6b540 100644 --- a/lib/rbnacl/util.rb +++ b/lib/rbnacl/util.rb @@ -66,6 +66,27 @@ def check_length(string, length, description) true end + # Check a passed in string, converting the argument if necessary + # + # In several places through the codebase we have to be VERY strict with + # the strings we accept. This method supports that. + # + # @raise [ArgumentError] If we cannot convert to a string with #to_str + # @raise [Crypto::LengthError] If the string is not the right length + # + # @param string [#to_str] The input string + # @param length [Integer] The only acceptable length of the string + # @param description [String] Description of the string (used in the error) + def check_string(string, length, description) + unless string.respond_to? :to_str + raise TypeError, "can't convert #{string.class} into String with #to_str" + end + + string = string.to_str + check_length(string, length, description) + + string + end # Compare two 32 byte strings in constant time # diff --git a/spec/rbnacl/box_spec.rb b/spec/rbnacl/box_spec.rb index d651bb2..55c9e69 100644 --- a/spec/rbnacl/box_spec.rb +++ b/spec/rbnacl/box_spec.rb @@ -16,21 +16,19 @@ expect { Crypto::Box.new(alice_key, bob_key) }.to_not raise_error(Exception) end - it "raises on a nil public key" do - expect { Crypto::Box.new(nil, bobsk) }.to raise_error(NoMethodError) - pending "is a failed #to_s (NoMethodError) here sufficient?" + it "raises TypeError on a nil public key" do + expect { Crypto::Box.new(nil, bobsk) }.to raise_error(TypeError) end - it "raises on an invalid public key" do + it "raises Crypto::LengthError on an invalid public key" do expect { Crypto::Box.new("hello", bobsk) }.to raise_error(Crypto::LengthError, /Public key was 5 bytes \(Expected 32\)/) end - it "raises on a nil secret key" do - expect { Crypto::Box.new(alicepk, nil) }.to raise_error(NoMethodError) - pending "is a failed #to_s (NoMethodError) here sufficient?" + it "raises TypeError on a nil secret key" do + expect { Crypto::Box.new(alicepk, nil) }.to raise_error(TypeError) end - it "raises on an invalid secret key" do + it "raises Crypto::LengthError on an invalid secret key" do expect { Crypto::Box.new(alicepk, "hello") }.to raise_error(Crypto::LengthError, /Private key was 5 bytes \(Expected 32\)/) end end diff --git a/spec/rbnacl/keys/private_key_spec.rb b/spec/rbnacl/keys/private_key_spec.rb index b5f9ce0..939a28f 100644 --- a/spec/rbnacl/keys/private_key_spec.rb +++ b/spec/rbnacl/keys/private_key_spec.rb @@ -24,12 +24,11 @@ expect { Crypto::PrivateKey.new(bobsk) }.not_to raise_error end - it "rejects a nil key" do - expect { Crypto::PrivateKey.new(nil) }.to raise_error(NoMethodError) - pending "is a failed #to_s (NoMethodError) here sufficient?" + it "raises TypeError when given a nil key" do + expect { Crypto::PrivateKey.new(nil) }.to raise_error(TypeError) end - it "rejects a short key" do + it "raises ArgumentError when given a short key" do expect { Crypto::PrivateKey.new("short") }.to raise_error(ArgumentError) end end diff --git a/spec/rbnacl/keys/public_key_spec.rb b/spec/rbnacl/keys/public_key_spec.rb index 5c84714..e348dbb 100644 --- a/spec/rbnacl/keys/public_key_spec.rb +++ b/spec/rbnacl/keys/public_key_spec.rb @@ -12,8 +12,7 @@ end it "rejects a nil key" do - expect { Crypto::PublicKey.new(nil) }.to raise_error(NoMethodError) - pending "is a failed #to_s (NoMethodError) here sufficient?" + expect { Crypto::PublicKey.new(nil) }.to raise_error(TypeError) end it "rejects a short key" do diff --git a/spec/rbnacl/random_nonce_box_spec.rb b/spec/rbnacl/random_nonce_box_spec.rb index 92b9900..d4ac576 100644 --- a/spec/rbnacl/random_nonce_box_spec.rb +++ b/spec/rbnacl/random_nonce_box_spec.rb @@ -16,18 +16,17 @@ Crypto::RandomNonceBox.from_secret_key(secret_key).should be_a Crypto::RandomNonceBox end - it "complains on an inappropriate secret key" do - expect { Crypto::RandomNonceBox.from_secret_key(nil) }.to raise_error(NoMethodError) - pending "is a failed #to_s (NoMethodError) here sufficient?" + it "raises TypeError when given a nil secret key" do + expect { Crypto::RandomNonceBox.from_secret_key(nil) }.to raise_error(TypeError) end it "can be instantiated from a key-pair" do Crypto::RandomNonceBox.from_keypair(alicepk, bobsk).should be_a Crypto::RandomNonceBox end - it "complains on an inappropriate key in the pair" do - expect { Crypto::RandomNonceBox.from_keypair(nil, bobsk) }.to raise_error(NoMethodError) - pending "is a failed #to_s (NoMethodError) here sufficient?" + it "raises TypeError when given nil secret keys in the pair" do + expect { Crypto::RandomNonceBox.from_keypair(nil, bobsk) }.to raise_error(TypeError) + expect { Crypto::RandomNonceBox.from_keypair(alicepk, nil) }.to raise_error(TypeError) end end diff --git a/spec/rbnacl/secret_box_spec.rb b/spec/rbnacl/secret_box_spec.rb index b2357db..d7a2b27 100644 --- a/spec/rbnacl/secret_box_spec.rb +++ b/spec/rbnacl/secret_box_spec.rb @@ -10,8 +10,7 @@ end it "raises on a nil key" do - expect { Crypto::SecretBox.new(nil) }.to raise_error(NoMethodError) - pending "is a failed #to_s (NoMethodError) here sufficient?" + expect { Crypto::SecretBox.new(nil) }.to raise_error(TypeError) end it "raises on a short key" do diff --git a/spec/shared/authenticator.rb b/spec/shared/authenticator.rb index 88d8269..a877237 100644 --- a/spec/shared/authenticator.rb +++ b/spec/shared/authenticator.rb @@ -12,16 +12,15 @@ expect { described_class.new }.to raise_error(ArgumentError) end - it "raises on a nil key" do - expect { described_class.new(nil) }.to raise_error(NoMethodError) - pending "is a failed #to_s (NoMethodError) here sufficient?" + it "raises TypeError on a nil key" do + expect { described_class.new(nil) }.to raise_error(TypeError) end - it "raises on a key which is too long" do + it "raises ArgumentError on a key which is too long" do expect { described_class.new("\0"*33) }.to raise_error(ArgumentError) end - it "raises on a key which is too short" do + it "raises ArgumentError on a key which is too short" do expect { described_class.new("\0"*31) }.to raise_error(ArgumentError) end end @@ -31,12 +30,11 @@ described_class.auth(key, message).should eq tag end - it "raises on a nil key" do - expect { described_class.auth(nil, message) }.to raise_error(NoMethodError) - pending "is a failed #to_s (NoMethodError) here sufficient?" + it "raises TypeError on a nil key" do + expect { described_class.auth(nil, message) }.to raise_error(TypeError) end - it "raises on a key which is too long" do + it "raises ArgumentError on a key which is too long" do expect { described_class.auth("\0"*33, message) }.to raise_error(ArgumentError) end end @@ -46,12 +44,11 @@ described_class.verify(key, message, tag).should eq true end - it "raises on a nil key" do - expect { described_class.verify(nil, message, tag) }.to raise_error(NoMethodError) - pending "is a failed #to_s (NoMethodError) here sufficient?" + it "raises TypeError on a nil key" do + expect { described_class.verify(nil, message, tag) }.to raise_error(TypeError) end - it "raises on a key which is too long" do + it "raises ArgumentError on a key which is too long" do expect { described_class.verify("\0"*33, message, tag) }.to raise_error(ArgumentError) end From 44f524740b8aca29e0dba34ed35208498c33f575 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sat, 10 Aug 2013 22:25:49 -0700 Subject: [PATCH 3/4] Add back Util.hex2bin and .bin2hex --- lib/rbnacl/util.rb | 18 ++++++++++++++++++ spec/rbnacl/util_spec.rb | 14 ++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/lib/rbnacl/util.rb b/lib/rbnacl/util.rb index 9e6b540..1cf16b9 100644 --- a/lib/rbnacl/util.rb +++ b/lib/rbnacl/util.rb @@ -153,6 +153,24 @@ def verify16!(one, two) check_length(two, 16, "Second message") NaCl.crypto_verify_16(one, two) end + + # Hex encodes a message + # + # @param [String] bytes The bytes to encode + # + # @return [String] Tasty, tasty hexadecimal + def bin2hex(bytes) + bytes.to_s.unpack("H*").first + end + + # Hex decodes a message + # + # @param [String] hex hex to decode. + # + # @return [String] crisp and clean bytes + def hex2bin(hex) + [hex.to_s].pack("H*") + end end end diff --git a/spec/rbnacl/util_spec.rb b/spec/rbnacl/util_spec.rb index fb9c7bb..045b9c7 100644 --- a/spec/rbnacl/util_spec.rb +++ b/spec/rbnacl/util_spec.rb @@ -102,6 +102,7 @@ Crypto::Util.verify16(msg, long_msg).should be false end end + context "check_length" do it "accepts strings of the correct length" do expect { Crypto::Util.check_length("A"*4, 4, "Test String") }.not_to raise_error @@ -116,4 +117,17 @@ expect { Crypto::Util.check_length(nil, 4, "Test String") }.to raise_error(Crypto::LengthError, "Test String was nil (Expected 4)") end end + + context "hex encoding" do + let (:bytes) { [0xDE,0xAD,0xBE,0xEF].pack('c*') } + let (:hex) { "deadbeef" } + + it "encodes to hex with bin2hex" do + Crypto::Util.bin2hex(bytes).should eq hex + end + + it "decodes from hex with hex2bin" do + Crypto::Util.hex2bin(hex).should eq bytes + end + end end From 8f41d9408cec47d6922e610b6894422e2233a4f2 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sat, 10 Aug 2013 22:27:32 -0700 Subject: [PATCH 4/4] Fix hex conversion in Serializable --- lib/rbnacl/serializable.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rbnacl/serializable.rb b/lib/rbnacl/serializable.rb index 8061ea2..074a102 100644 --- a/lib/rbnacl/serializable.rb +++ b/lib/rbnacl/serializable.rb @@ -9,7 +9,7 @@ def to_str; to_bytes; end # # @return [String] a string representing this key def inspect - "#<#{self.class}:#{to_s(:hex)[0,8]}>" + "#<#{self.class}:#{Util.bytes2hex(to_bytes)[0,8]}>" end end end \ No newline at end of file