Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Rename SecretBox primitive

Now more closely mimics C API
  • Loading branch information...
commit 3d068b9f4ffef7fa450eff9578ced95a52cb8cf1 1 parent 04eb156
Jon namelessjon authored
4 lib/rbnacl/nacl.rb
View
@@ -66,8 +66,8 @@ module SecretBox
:crypto_box_curve25519xsalsa20poly1305_ref_open_afternm,
[:pointer, :pointer, :long_long, :pointer, :pointer]
- SecretBox::XSALSA20_POLY1305_KEYBYTES = 32
- SecretBox::XSALSA20_POLY1305_NONCEBYTES = 24
+ XSALSA20_POLY1305_SECRETBOX_KEYBYTES = 32
+ XSALSA20_POLY1305_SECRETBOX_NONCEBYTES = 24
wrap_nacl_function :crypto_secretbox_xsalsa20poly1305,
:crypto_secretbox_xsalsa20poly1305_ref,
[:pointer, :pointer, :long_long, :pointer, :pointer]
102 lib/rbnacl/nacl/secret_box/xsalsa20_poly1305_box.rb
View
@@ -1,102 +0,0 @@
-# encoding: binary
-module Crypto
- module NaCl
- module SecretBox
- # The XSalsa20Poly1305Box class boxes and unboxes messages
- #
- # This class uses the given secret key to encrypt and decrypt messages.
- #
- # It is VITALLY important that the nonce is a nonce, i.e. it is a number
- # used only once for any given pair of keys. If you fail to do this, you
- # compromise the privacy of the messages encrypted. Give your nonces a
- # different prefix, or have one side use an odd counter and one an even
- # counter. Just make sure they are different.
- #
- # The ciphertexts generated by this class include a 16-byte authenticator
- # which is checked as part of the decryption. An invalid authenticator
- # will cause the unbox function to raise. The authenticator is not a
- # signature. Once you've looked in the box, you've demonstrated the
- # ability to create arbitrary valid messages, so messages you send are
- # repudiatable. For non-repudiatable messages, sign them before or after
- # encryption.
- #
- # * Encryption: XSalsa20, a fast stream cipher primitive
- # * Authentication: Poly1305, a fast one time authentication primitive
- #
- # **WARNING**: This class provides direct access to a low-level
- # cryptographic method. You should not use this class without good
- # reason and instead use the Crypto::SecretBox box class which will
- # always point to the best primitive the library provides bindings for.
- # It also provides a nicer interface, with e.g. encoding of the resulting
- # messages as base64.
- class XSalsa20Poly1305Box
- # Number of bytes for a secret key
- KEYBYTES = NaCl::SecretBox::XSALSA20_POLY1305_KEYBYTES
- # Number of bytes for a nonce
- NONCEBYTES = NaCl::SecretBox::XSALSA20_POLY1305_NONCEBYTES
-
- # Create a new SecretBox
- #
- # Sets up the Box with a secret key fro encrypting and decrypting messages.
- #
- # @param key [String] The key to encrypt and decrypt with
- #
- # @raise [Crypto::LengthError] on invalid keys
- #
- # @return [Crypto::SecretBox] The new Box, ready to use
- def initialize(key)
- @key = key
- Util.check_length(@key, KEYBYTES, "Secret key")
- end
-
- # Encrypts a message
- #
- # Encrypts the message with the given nonce to the key set up when
- # initializing the class. Make sure the nonce is unique for any given
- # key, or you might as well just send plain text.
- #
- # This function takes care of the padding required by the NaCL C API.
- #
- # @param nonce [String] A 24-byte string containing the nonce.
- # @param message [String] The message to be encrypted.
- #
- # @raise [Crypto::LengthError] If the nonce is not valid
- #
- # @return [String] The ciphertext without the nonce prepended (BINARY encoded)
- def box(nonce, message)
- Util.check_length(nonce, NONCEBYTES, "Nonce")
- msg = Util.prepend_zeros(NaCl::ZEROBYTES, message)
- ct = Util.zeros(msg.bytesize)
-
- NaCl.crypto_secretbox_xsalsa20poly1305(ct, msg, msg.bytesize, nonce, @key) || raise(CryptoError, "Encryption failed")
- Util.remove_zeros(NaCl::BOXZEROBYTES, ct)
- end
- alias encrypt box
-
- # Decrypts a ciphertext
- #
- # Decrypts the ciphertext with the given nonce using the key setup when
- # initializing the class.
- #
- # This function takes care of the padding required by the NaCL C API.
- #
- # @param nonce [String] A 24-byte string containing the nonce.
- # @param ciphertext [String] The message to be decrypted.
- #
- # @raise [Crypto::LengthError] If the nonce is not valid
- # @raise [Crypto::CryptoError] If the ciphertext cannot be authenticated.
- #
- # @return [String] The decrypted message (BINARY encoded)
- def open(nonce, ciphertext)
- Util.check_length(nonce, NONCEBYTES, "Nonce")
- ct = Util.prepend_zeros(NaCl::BOXZEROBYTES, ciphertext)
- message = Util.zeros(ct.bytesize)
-
- NaCl.crypto_secretbox_xsalsa20poly1305_open(message, ct, ct.bytesize, nonce, @key) || raise(CryptoError, "Decryption failed. Ciphertext failed verification.")
- Util.remove_zeros(NaCl::ZEROBYTES, message)
- end
- alias decrypt open
- end
- end
- end
-end
7 lib/rbnacl/secret_box.rb
View
@@ -1,5 +1,5 @@
# encoding: binary
-require 'rbnacl/nacl/secret_box/xsalsa20_poly1305_box'
+require 'rbnacl/secret_box/xsalsa20_poly1305'
module Crypto
# The SecretBox class boxes and unboxes messages
#
@@ -20,6 +20,9 @@ module Crypto
class SecretBox
attr_reader :primitive
+ # The default primitive to use
+ DEFAULT_PRIMITIVE = SecretBox::XSalsa20Poly1305
+
# Create a new SecretBox
#
# Sets up the Box with a secret key fro encrypting and decrypting messages.
@@ -30,7 +33,7 @@ class SecretBox
# @raise [Crypto::LengthError] on invalid keys
#
# @return [Crypto::SecretBox] The new Box, ready to use
- def initialize(key, encoding = :raw, primitive = NaCl::SecretBox::XSalsa20Poly1305Box)
+ def initialize(key, encoding = :raw, primitive = DEFAULT_PRIMITIVE)
@key = Encoder[encoding].decode(key) if key
@primitive = primitive.new(@key)
end
102 lib/rbnacl/secret_box/xsalsa20_poly1305.rb
View
@@ -0,0 +1,102 @@
+# encoding: binary
+module Crypto
+ class SecretBox
+ # The XSalsa20Poly1305 class boxes and unboxes messages
+ #
+ # This class uses the given secret key to encrypt and decrypt messages.
+ #
+ # It is VITALLY important that the nonce is a nonce, i.e. it is a number
+ # used only once for any given pair of keys. If you fail to do this, you
+ # compromise the privacy of the messages encrypted. Give your nonces a
+ # different prefix, or have one side use an odd counter and one an even
+ # counter. Just make sure they are different.
+ #
+ # The ciphertexts generated by this class include a 16-byte authenticator
+ # which is checked as part of the decryption. An invalid authenticator
+ # will cause the unbox function to raise. The authenticator is not a
+ # signature. Once you've looked in the box, you've demonstrated the
+ # ability to create arbitrary valid messages, so messages you send are
+ # repudiatable. For non-repudiatable messages, sign them before or after
+ # encryption.
+ #
+ # * Encryption: XSalsa20, a fast stream cipher primitive
+ # * Authentication: Poly1305, a fast one time authentication primitive
+ #
+ # **WARNING**: This class provides direct access to a low-level
+ # cryptographic method. You should not use this class without good reason
+ # and instead use the Crypto::SecretBox box class which will always point
+ # to the best primitive the library provides bindings for. It also
+ # provides a nicer interface, with e.g. decoding of ascii-encoded keys.
+ class XSalsa20Poly1305
+ # Number of bytes for a secret key
+ KEYBYTES = NaCl::XSALSA20_POLY1305_SECRETBOX_KEYBYTES
+ # Number of bytes for a nonce
+ NONCEBYTES = NaCl::XSALSA20_POLY1305_SECRETBOX_NONCEBYTES
+
+ # The cryptographic primitive used
+ PRIMITIVE = :xsalsa20_poly1305
+
+ # Create a new SecretBox
+ #
+ # Sets up the Box with a secret key fro encrypting and decrypting messages.
+ #
+ # @param key [String] The key to encrypt and decrypt with
+ #
+ # @raise [Crypto::LengthError] on invalid keys
+ #
+ # @return [Crypto::SecretBox] The new Box, ready to use
+ def initialize(key)
+ @key = key
+ Util.check_length(@key, KEYBYTES, "Secret key")
+ end
+
+ # Encrypts a message
+ #
+ # Encrypts the message with the given nonce to the key set up when
+ # initializing the class. Make sure the nonce is unique for any given
+ # key, or you might as well just send plain text.
+ #
+ # This function takes care of the padding required by the NaCL C API.
+ #
+ # @param nonce [String] A 24-byte string containing the nonce.
+ # @param message [String] The message to be encrypted.
+ #
+ # @raise [Crypto::LengthError] If the nonce is not valid
+ #
+ # @return [String] The ciphertext without the nonce prepended (BINARY encoded)
+ def box(nonce, message)
+ Util.check_length(nonce, NONCEBYTES, "Nonce")
+ msg = Util.prepend_zeros(NaCl::ZEROBYTES, message)
+ ct = Util.zeros(msg.bytesize)
+
+ NaCl.crypto_secretbox_xsalsa20poly1305(ct, msg, msg.bytesize, nonce, @key) || raise(CryptoError, "Encryption failed")
+ Util.remove_zeros(NaCl::BOXZEROBYTES, ct)
+ end
+ alias encrypt box
+
+ # Decrypts a ciphertext
+ #
+ # Decrypts the ciphertext with the given nonce using the key setup when
+ # initializing the class.
+ #
+ # This function takes care of the padding required by the NaCL C API.
+ #
+ # @param nonce [String] A 24-byte string containing the nonce.
+ # @param ciphertext [String] The message to be decrypted.
+ #
+ # @raise [Crypto::LengthError] If the nonce is not valid
+ # @raise [Crypto::CryptoError] If the ciphertext cannot be authenticated.
+ #
+ # @return [String] The decrypted message (BINARY encoded)
+ def open(nonce, ciphertext)
+ Util.check_length(nonce, NONCEBYTES, "Nonce")
+ ct = Util.prepend_zeros(NaCl::BOXZEROBYTES, ciphertext)
+ message = Util.zeros(ct.bytesize)
+
+ NaCl.crypto_secretbox_xsalsa20poly1305_open(message, ct, ct.bytesize, nonce, @key) || raise(CryptoError, "Decryption failed. Ciphertext failed verification.")
+ Util.remove_zeros(NaCl::ZEROBYTES, message)
+ end
+ alias decrypt open
+ end
+ end
+end
6 ...acl/nacl/secret_box/xsalsa20_poly1305_box_spec.rb → spec/rbnacl/secret_box/xsalsa20_poly1305_spec.rb
View
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe Crypto::NaCl::SecretBox::XSalsa20Poly1305Box do
+describe Crypto::SecretBox::XSalsa20Poly1305 do
let (:key) { hex2bytes(Crypto::TestVectors[:secret_key]) }
@@ -10,11 +10,11 @@
end
it "raises on a nil key" do
- expect { described_class.new(nil) }.to raise_error(Crypto::LengthError, "Secret key was nil \(Expected #{Crypto::NaCl::SECRETKEYBYTES}\)")
+ expect { described_class.new(nil) }.to raise_error(Crypto::LengthError, "Secret key was nil \(Expected #{Crypto::NaCl::XSALSA20_POLY1305_SECRETBOX_KEYBYTES}\)")
end
it "raises on a short key" do
- expect { described_class.new("hello") }.to raise_error(Crypto::LengthError, "Secret key was 5 bytes \(Expected #{Crypto::NaCl::SECRETKEYBYTES}\)")
+ expect { described_class.new("hello") }.to raise_error(Crypto::LengthError, "Secret key was 5 bytes \(Expected #{Crypto::NaCl::XSALSA20_POLY1305_SECRETBOX_KEYBYTES}\)")
end
end
4 spec/rbnacl/secret_box_spec.rb
View
@@ -10,11 +10,11 @@
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::SecretBox::XSALSA20_POLY1305_KEYBYTES}\)")
+ expect { Crypto::SecretBox.new(nil) }.to raise_error(Crypto::LengthError, "Secret key was nil \(Expected #{Crypto::SecretBox::DEFAULT_PRIMITIVE::KEYBYTES}\)")
end
it "raises on a short key" do
- expect { Crypto::SecretBox.new("hello") }.to raise_error(Crypto::LengthError, "Secret key was 5 bytes \(Expected #{Crypto::NaCl::SecretBox::XSALSA20_POLY1305_KEYBYTES}\)")
+ expect { Crypto::SecretBox.new("hello") }.to raise_error(Crypto::LengthError, "Secret key was 5 bytes \(Expected #{Crypto::SecretBox::DEFAULT_PRIMITIVE::KEYBYTES}\)")
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.