Skip to content

Commit

Permalink
Merge 58986db into 1e20022
Browse files Browse the repository at this point in the history
  • Loading branch information
namelessjon committed Oct 5, 2013
2 parents 1e20022 + 58986db commit 110aa3e
Show file tree
Hide file tree
Showing 25 changed files with 319 additions and 338 deletions.
6 changes: 4 additions & 2 deletions lib/rbnacl.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
# encoding: binary
require "rbnacl/version"
require "rbnacl/nacl"
require "rbnacl/sodium"
require "rbnacl/serializable"
require "rbnacl/key_comparator"
require "rbnacl/auth"
require "rbnacl/util"
require "rbnacl/random"
require "rbnacl/random_nonce_box"
require "rbnacl/test_vectors"
require "rbnacl/init"

module RbNaCl
# Oh no, something went wrong!
Expand Down Expand Up @@ -41,6 +42,7 @@ class BadSignatureError < CryptoError; end
require "rbnacl/secret_boxes/xsalsa20poly1305"

# Digital Signatures: Ed25519
require "rbnacl/signatures/ed25519"
require "rbnacl/signatures/ed25519/signing_key"
require "rbnacl/signatures/ed25519/verify_key"

Expand Down Expand Up @@ -72,7 +74,7 @@ class BadSignatureError < CryptoError; end
end

# Select platform-optimized versions of algorithms
Thread.exclusive { RbNaCl::NaCl.sodium_init }
Thread.exclusive { RbNaCl::Init.sodium_init }

# Perform self test on load
require "rbnacl/self_test"
26 changes: 14 additions & 12 deletions lib/rbnacl/authenticators/poly1305.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,28 @@ module Authenticators
#
# @see http://nacl.cr.yp.to/onetimeauth.html
class Poly1305 < Auth
# Number of bytes in a valid key
KEYBYTES = NaCl::ONETIME_KEYBYTES
extend Sodium

# Number of bytes in a valid authenticator
BYTES = NaCl::ONETIME_BYTES
sodium_type :onetimeauth
sodium_primitive :poly1305
sodium_constant :BYTES
sodium_constant :KEYBYTES

sodium_function :onetimeauth_poly1305,
:crypto_onetimeauth_poly1305,
[:pointer, :pointer, :ulong_long, :pointer]

# The crypto primitive for the Auth::OneTime class
#
# @return [Symbol] The primitive used
def self.primitive
:poly_1305
end
sodium_function :onetimeauth_poly1305_verify,
:crypto_onetimeauth_poly1305_verify,
[:pointer, :pointer, :ulong_long, :pointer]

private
def compute_authenticator(authenticator, message)
NaCl.crypto_auth_onetime(authenticator, message, message.bytesize, key)
self.class.onetimeauth_poly1305(authenticator, message, message.bytesize, key)
end

def verify_message(authenticator, message)
NaCl.crypto_auth_onetime_verify(authenticator, message, message.bytesize, key)
self.class.onetimeauth_poly1305_verify(authenticator, message, message.bytesize, key)
end

end
Expand Down
46 changes: 29 additions & 17 deletions lib/rbnacl/boxes/curve25519xsalsa20poly1305.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,28 @@ module Boxes
# arbitrary valid messages, so messages you send are repudiable. For
# non-repudiable messages, sign them before or after encryption.
class Curve25519XSalsa20Poly1305
extend Sodium

# Number of bytes in a Box nonce
NONCEBYTES = NaCl::CURVE25519_XSALSA20_POLY1305_BOX_NONCEBYTES
sodium_type :box
sodium_primitive :curve25519xsalsa20poly1305
sodium_constant :NONCEBYTES
sodium_constant :ZEROBYTES
sodium_constant :BOXZEROBYTES
sodium_constant :BEFORENMBYTES
sodium_constant :PUBLICKEYBYTES
sodium_constant :SECRETKEYBYTES, :PRIVATEKEYBYTES

sodium_function :box_curve25519xsalsa20poly1305_beforenm,
:crypto_box_curve25519xsalsa20poly1305_beforenm,
[:pointer, :pointer, :pointer]

sodium_function :box_curve25519xsalsa20poly1305_open_afternm,
:crypto_box_curve25519xsalsa20poly1305_open_afternm,
[:pointer, :pointer, :ulong_long, :pointer, :pointer]

sodium_function :box_curve25519xsalsa20poly1305_afternm,
:crypto_box_curve25519xsalsa20poly1305_afternm,
[:pointer, :pointer, :ulong_long, :pointer, :pointer]

# Create a new Box
#
Expand Down Expand Up @@ -100,11 +119,11 @@ def initialize(public_key, private_key, encoding = :raw)
# @return [String] The ciphertext without the nonce prepended (BINARY encoded)
def box(nonce, message)
Util.check_length(nonce, nonce_bytes, "Nonce")
msg = Util.prepend_zeros(NaCl::ZEROBYTES, message)
msg = Util.prepend_zeros(ZEROBYTES, message)
ct = Util.zeros(msg.bytesize)

NaCl.crypto_box_curve25519_xsalsa20_poly1305_afternm(ct, msg, msg.bytesize, nonce, beforenm) || raise(CryptoError, "Encryption failed")
Util.remove_zeros(NaCl::BOXZEROBYTES, ct)
self.class.box_curve25519xsalsa20poly1305_afternm(ct, msg, msg.bytesize, nonce, beforenm) || raise(CryptoError, "Encryption failed")
Util.remove_zeros(BOXZEROBYTES, ct)
end
alias encrypt box

Expand All @@ -124,21 +143,14 @@ def box(nonce, message)
# @return [String] The decrypted message (BINARY encoded)
def open(nonce, ciphertext)
Util.check_length(nonce, nonce_bytes, "Nonce")
ct = Util.prepend_zeros(NaCl::BOXZEROBYTES, ciphertext)
ct = Util.prepend_zeros(BOXZEROBYTES, ciphertext)
message = Util.zeros(ct.bytesize)

NaCl.crypto_box_curve25519_xsalsa20_poly1305_open_afternm(message, ct, ct.bytesize, nonce, beforenm) || raise(CryptoError, "Decryption failed. Ciphertext failed verification.")
Util.remove_zeros(NaCl::ZEROBYTES, message)
self.class.box_curve25519xsalsa20poly1305_open_afternm(message, ct, ct.bytesize, nonce, beforenm) || raise(CryptoError, "Decryption failed. Ciphertext failed verification.")
Util.remove_zeros(ZEROBYTES, message)
end
alias decrypt open

# The crypto primitive for the box class
#
# @return [Symbol] The primitive used
def self.primitive
:curve25519_xsalsa20_poly1305
end

# The crypto primitive for the box class
#
# @return [Symbol] The primitive used
Expand All @@ -163,8 +175,8 @@ def nonce_bytes
private
def beforenm
@k ||= begin
k = Util.zeros(NaCl::CURVE25519_XSALSA20_POLY1305_BOX_BEFORENMBYTES)
NaCl.crypto_box_curve25519_xsalsa20_poly1305_beforenm(k, @public_key.to_s, @private_key.to_s) || raise(CryptoError, "Failed to derive shared key")
k = Util.zeros(BEFORENMBYTES)
self.class.box_curve25519xsalsa20poly1305_beforenm(k, @public_key.to_s, @private_key.to_s) || raise(CryptoError, "Failed to derive shared key")
k
end
end
Expand Down
27 changes: 14 additions & 13 deletions lib/rbnacl/boxes/curve25519xsalsa20poly1305/private_key.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,18 @@ class Boxes::Curve25519XSalsa20Poly1305::PrivateKey

include KeyComparator
include Serializable

extend Sodium

sodium_type :box
sodium_primitive :curve25519xsalsa20poly1305

sodium_function :box_curve25519xsalsa20poly1305_keypair,
:crypto_box_curve25519xsalsa20poly1305_keypair,
[:pointer, :pointer]

# The size of the key, in bytes
BYTES = NaCl::CURVE25519_XSALSA20_POLY1305_SECRETKEY_BYTES
BYTES = Boxes::Curve25519XSalsa20Poly1305::PRIVATEKEYBYTES

# Initializes a new PrivateKey for key operations.
#
Expand All @@ -41,9 +50,9 @@ def initialize(private_key)
#
# @return [RbNaCl::PrivateKey] A new private key, with the associated public key also set.
def self.generate
pk = Util.zeros(NaCl::CURVE25519_XSALSA20_POLY1305_PUBLICKEY_BYTES)
sk = Util.zeros(NaCl::CURVE25519_XSALSA20_POLY1305_SECRETKEY_BYTES)
NaCl.crypto_box_curve25519xsalsa20poly1305_keypair(pk, sk) || raise(CryptoError, "Failed to generate a key pair")
pk = Util.zeros(Boxes::Curve25519XSalsa20Poly1305::PUBLICKEYBYTES)
sk = Util.zeros(Boxes::Curve25519XSalsa20Poly1305::PRIVATEKEYBYTES)
self.box_curve25519xsalsa20poly1305_keypair(pk, sk) || raise(CryptoError, "Failed to generate a key pair")
new(sk)
end

Expand All @@ -60,20 +69,12 @@ def to_bytes
def public_key
@public_key ||= PublicKey.new GroupElements::Curve25519.base.mult(to_bytes)
end

# The crypto primitive the PrivateKey class is to be used for
#
# @return [Symbol] The primitive
def self.primitive
:curve25519_xsalsa20_poly1305
end


# The crypto primitive this PrivateKey is to be used for.
#
# @return [Symbol] The primitive
def primitive
self.class.primitive
end
end

end
4 changes: 2 additions & 2 deletions lib/rbnacl/boxes/curve25519xsalsa20poly1305/public_key.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Boxes::Curve25519XSalsa20Poly1305::PublicKey
include Serializable

# The size of the key, in bytes
BYTES = NaCl::CURVE25519_XSALSA20_POLY1305_PUBLICKEY_BYTES
BYTES = Boxes::Curve25519XSalsa20Poly1305::PUBLICKEYBYTES

# Initializes a new PublicKey for key operations.
#
Expand Down Expand Up @@ -39,7 +39,7 @@ def to_bytes
#
# @return [Symbol] The primitive
def self.primitive
:curve25519_xsalsa20_poly1305
:curve25519xsalsa20poly1305
end

# The crypto primitive this PublicKey is to be used for.
Expand Down
16 changes: 14 additions & 2 deletions lib/rbnacl/group_elements/curve25519.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,20 @@ class Curve25519
include KeyComparator
include Serializable

extend Sodium

sodium_type :scalarmult
sodium_primitive :curve25519

sodium_function :scalarmult_curve25519,
:crypto_scalarmult_curve25519,
[:pointer, :pointer, :pointer]

# Number of bytes in a scalar on this curve
SCALARBYTES = 32
BYTES = 32

# Number of bytes in a scalar on this curve
SCALARBYTES = NaCl::ED25519_SCALARBYTES

# Creates a new Point from the given serialization
#
Expand All @@ -47,7 +59,7 @@ def mult(integer, encoding = :raw)
Util.check_length(integer, SCALARBYTES, "integer")

result = Util.zeros(SCALARBYTES)
NaCl.crypto_scalarmult_curve25519(result, integer, @point)
self.class.scalarmult_curve25519(result, integer, @point)

self.class.new(result)
end
Expand Down
66 changes: 39 additions & 27 deletions lib/rbnacl/hash.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,26 @@ module RbNaCl
#
# RbNaCl provides the SHA-256 and SHA-512 hash functions.
module Hash
module SHA256
extend Sodium
sodium_type :hash
sodium_primitive :sha256
sodium_constant :BYTES
sodium_function :hash_sha256,
:crypto_hash_sha256,
[:pointer, :pointer, :ulong_long]
end

module SHA512
extend Sodium
sodium_type :hash
sodium_primitive :sha512
sodium_constant :BYTES
sodium_function :hash_sha512,
:crypto_hash_sha512,
[:pointer, :pointer, :ulong_long]
end

# Returns the SHA-256 hash of the given data
#
# There's no streaming done, just pass in the data and be done with it.
Expand All @@ -24,8 +44,8 @@ module Hash
# @return [String] The SHA-256 hash as raw bytes (Or encoded as per the second argument)
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!")
digest = Util.zeros(SHA256::BYTES)
SHA256.hash_sha256(digest, data, data.bytesize) || raise(CryptoError, "Hashing failed!")
digest
end

Expand All @@ -39,34 +59,26 @@ def self.sha256(data)
#
# @return [String] The SHA-512 hash as raw bytes (Or encoded as per the second argument)
def self.sha512(data)
digest = Util.zeros(NaCl::SHA512BYTES)
NaCl.crypto_hash_sha512(digest, data, data.bytesize) || raise(CryptoError, "Hashing failed!")
digest = Util.zeros(SHA512::BYTES)
SHA512.hash_sha512(digest, data, data.bytesize) || raise(CryptoError, "Hashing failed!")
digest
end

if NaCl.supported_version? :libsodium, '0.4.0'
# Returns the Blake2b hash of the given data
#
# There's no streaming done, just pass in the data and be done with it.
# This method returns a 64-byte hash by default.
#
# @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
#
# @raise [CryptoError] If the hashing fails for some reason.
#
# @return [String] The blake2b hash as raw bytes (Or encoded as per the second argument)
def self.blake2b(data, options = {})
key = options[:key]
digest_size = options[:digest_size] || NaCl::BLAKE2B_OUTBYTES
Blake2b.new(options).digest(data)
end

else
def self.blake2b(data, options = {})
raise NotImplementedError, "not supported by this version of libsodium"
end
# Returns the Blake2b hash of the given data
#
# There's no streaming done, just pass in the data and be done with it.
# This method returns a 64-byte hash by default.
#
# @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
#
# @raise [CryptoError] If the hashing fails for some reason.
#
# @return [String] The blake2b hash as raw bytes (Or encoded as per the second argument)
def self.blake2b(data, options = {})
key = options[:key]
Blake2b.new(options).digest(data)
end
end
end
21 changes: 17 additions & 4 deletions lib/rbnacl/hash/blake2b.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@ module Hash
# Blake2b provides for up to 64-bit digests and also supports a keyed mode
# similar to HMAC
class Blake2b
extend Sodium

sodium_type :generichash
sodium_primitive :blake2b
sodium_constant :BYTES_MIN
sodium_constant :BYTES_MAX
sodium_constant :KEYBYTES_MIN
sodium_constant :KEYBYTES_MAX

sodium_function :generichash_blake2b,
:crypto_generichash_blake2b,
[:pointer, :ulong_long, :pointer, :ulong_long, :pointer, :ulong_long]

# Create a new Blake2b hash object
#
# @param [Hash] opts Blake2b configuration
Expand All @@ -22,10 +35,10 @@ class Blake2b
def initialize(opts = {})
@key = opts.fetch(:key, nil)
@key_size = @key ? @key.bytesize : 0
raise LengthError, "key too long" if @key_size > NaCl::BLAKE2B_KEYBYTES
raise LengthError, "Invalid key size" if (@key_size != 0) && (@key_size < KEYBYTES_MIN || @key_size > KEYBYTES_MAX)

@digest_size = opts.fetch(:digest_size, NaCl::BLAKE2B_OUTBYTES)
raise LengthError, "invalid digest size" if @digest_size < 1 || @digest_size > NaCl::BLAKE2B_OUTBYTES
@digest_size = opts.fetch(:digest_size, BYTES_MAX)
raise LengthError, "Invalid digest size" if @digest_size < BYTES_MIN || @digest_size > BYTES_MAX
end

# Calculate a Blake2b digest
Expand All @@ -35,7 +48,7 @@ def initialize(opts = {})
# @return [String] Blake2b digest of the string as raw bytes
def digest(message)
digest = Util.zeros(@digest_size)
NaCl.crypto_hash_blake2b(digest, @digest_size, message, message.bytesize, @key, @key_size) || raise(CryptoError, "Hashing failed!")
self.class.generichash_blake2b(digest, @digest_size, message, message.bytesize, @key, @key_size) || raise(CryptoError, "Hashing failed!")
digest
end
end
Expand Down
Loading

0 comments on commit 110aa3e

Please sign in to comment.