Skip to content

Commit

Permalink
Merge pull request #56 from cryptosphere/blake2b
Browse files Browse the repository at this point in the history
Blake2b support
  • Loading branch information
tarcieri committed May 27, 2013
2 parents 907bf0c + 81ab2dc commit 296f8de
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 10 deletions.
22 changes: 22 additions & 0 deletions lib/rbnacl/hash.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,27 @@ def self.sha512(data, encoding = :raw)
NaCl.crypto_hash_sha512(hash, data, data.bytesize) || raise(CryptoError, "Hashing failed!")
Encoder[encoding].encode(hash)
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.
#
# @param [String] data The data, as a collection of bytes
# @param [#to_sym] encoding Encoding of the returned hash.
#
# @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.blake2b(data, encoding = :raw)
hash = Util.zeros(NaCl::BLAKE2B_OUTBYTES)
NaCl.crypto_hash_blake2b(hash, NaCl::BLAKE2B_OUTBYTES, data, data.bytesize, nil, 0) || raise(CryptoError, "Hashing failed!")
Encoder[encoding].encode(hash)
end
else
def self.blake2b(data, encoding = :raw)
raise NotImplementedError, "not supported by this version of libsodium"
end
end
end
end
17 changes: 17 additions & 0 deletions lib/rbnacl/nacl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,18 @@ module Crypto
# @private
module NaCl
extend FFI::Library

ffi_lib 'sodium'
attach_function :sodium_version_string, [], :string

# Determine if a given feature is supported based on Sodium/NaCl version
def self.supported_version?(engine, version)
return unless engine == :libsodium

# FIXME: This sort of comparison has some edge cases we don't have to
# worry about... yet.
sodium_version_string >= version
end

# Wraps an NaCl function so it returns a sane value
#
Expand Down Expand Up @@ -45,6 +56,12 @@ def self.#{name}(*args)
:crypto_hash_sha512_ref,
[:pointer, :pointer, :long_long]

BLAKE2B_OUTBYTES = 64
BLAKE2B_KEYBYTES = 64
wrap_nacl_function :crypto_hash_blake2b,
:crypto_generichash_blake2b,
[:pointer, :size_t, :pointer, :long_long, :pointer, :size_t]

CURVE25519_XSALSA20_POLY1305_PUBLICKEY_BYTES = 32
PUBLICKEYBYTES = CURVE25519_XSALSA20_POLY1305_PUBLICKEY_BYTES
CURVE25519_XSALSA20_POLY1305_SECRETKEY_BYTES = 32
Expand Down
38 changes: 28 additions & 10 deletions spec/rbnacl/hash_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

describe Crypto::Hash do
context "sha256" do
let(:reference_string) { test_vector :sha256_message }
let(:reference_string_hash) { test_vector :sha256_digest }
let(:empty_string_hash) { "\xE3\xB0\xC4B\x98\xFC\x1C\x14\x9A\xFB\xF4\xC8\x99o\xB9$'\xAEA\xE4d\x9B\x93L\xA4\x95\x99\exR\xB8U" }
let(:reference_string_hash_hex) { reference_string_hash.unpack('H*').first }
let(:empty_string_hash_hex) { empty_string_hash.unpack('H*').first }
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 }

it "calculates the correct hash for a reference string" do
Crypto::Hash.sha256(reference_string).should eq reference_string_hash
Expand All @@ -31,11 +31,11 @@
end

context "sha512" do
let(:reference_string) { "The quick brown fox jumps over the lazy dog." }
let(:reference_string_hash) { "\x91\xEA\x12E\xF2\rF\xAE\x9A\x03z\x98\x9FT\xF1\xF7\x90\xF0\xA4v\a\xEE\xB8\xA1M\x12\x89\f\xEAw\xA1\xBB\xC6\xC7\xED\x9C\xF2\x05\xE6{\x7F+\x8F\xD4\xC7\xDF\xD3\xA7\xA8a~E\xF3\xC4c\xD4\x81\xC7\xE5\x86\xC3\x9A\xC1\xED" }
let(:empty_string_hash) { "\xCF\x83\xE15~\xEF\xB8\xBD\xF1T(P\xD6m\x80\a\xD6 \xE4\x05\vW\x15\xDC\x83\xF4\xA9!\xD3l\xE9\xCEG\xD0\xD1<]\x85\xF2\xB0\xFF\x83\x18\xD2\x87~\xEC/c\xB91\xBDGAz\x81\xA582z\xF9'\xDA>" }
let(:reference_string_hash_hex) { reference_string_hash.unpack('H*').first }
let(:empty_string_hash_hex) { empty_string_hash.unpack('H*').first }
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 }

it "calculates the correct hash for a reference string" do
Crypto::Hash.sha512(reference_string).should eq reference_string_hash
Expand All @@ -57,4 +57,22 @@
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 }

it "calculates the correct hash for a reference string" do
Crypto::Hash.blake2b(reference_string).should eq reference_string_hash
end

it "calculates the correct hash for an empty string" do
Crypto::Hash.blake2b("").should eq empty_string_hash
end
end
end
end

0 comments on commit 296f8de

Please sign in to comment.