Permalink
Browse files

Merge pull request #2 from stouset/sodium-hash

Implement Sodium::Hash
  • Loading branch information...
2 parents cb49f6e + 1a90302 commit 3063daa64281a7cb3d66891c00e90173fcf23190 @stouset committed Mar 20, 2013
Showing with 144 additions and 2 deletions.
  1. +23 −2 config/nacl_ffi.yml
  2. +1 −0 lib/sodium.rb
  3. +21 −0 lib/sodium/hash.rb
  4. +32 −0 test/sodium/hash/sha256_test.rb
  5. +35 −0 test/sodium/hash/sha512_test.rb
  6. +32 −0 test/sodium/hash_test.rb
View
@@ -3,7 +3,7 @@
:constants: [ VERSION, BYTES, KEYBYTES ]
:functions:
- ! '' : [ pointer, pointer, ulong_long, pointer, int ]
+ ~ : [ pointer, pointer, ulong_long, pointer, int ]
:verify: [ pointer, pointer, ulong_long, pointer, int ]
:implementations:
@@ -33,7 +33,7 @@
- MACBYTES
:functions:
- ! '' : [ pointer, pointer, ulong_long, pointer, pointer, pointer, int ]
+ ~ : [ pointer, pointer, ulong_long, pointer, pointer, pointer, int ]
:open : [ pointer, pointer, ulong_long, pointer, pointer, pointer, int ]
:keypair : [ pointer, pointer, int ]
:beforenm : [ pointer, pointer, pointer, int ]
@@ -48,3 +48,24 @@
:constants : [ -, 32, 32, 32, 24, 32, 16, 16 ]
:default: *default_box
+
+- :class : Sodium::Hash
+ :family : crypto_hash
+ :constants: [ VERSION, BYTES ]
+
+ :functions:
+ ~: [ pointer, pointer, ulong_long, int ]
+
+ :implementations:
+ - &default_hash
+ :name : :SHA512
+ :primitive : :sha512
+ :implementation: ref
+ :constants : [ -, 64 ]
+
+ - :name : :SHA256
+ :primitive : :sha256
+ :implementation: ref
+ :constants : [ -, 32 ]
+
+ :default: *default_hash
View
@@ -9,5 +9,6 @@ class CryptoError < Error; end
require 'sodium/auth'
require 'sodium/box'
+require 'sodium/hash'
require 'sodium/na_cl'
View
@@ -0,0 +1,21 @@
+require 'sodium'
+
+class Sodium::Hash
+ include Sodium::Delegate
+
+ def self.hash(message)
+ message = _message(message)
+ digest = Sodium::Util.buffer self.implementation[:BYTES]
+
+ self.implementation.nacl(digest, message, message.length) or
+ raise Sodium::CryptoError, 'failed to generate a hash for the message'
+
+ digest
+ end
+
+ private
+
+ def self._message(m)
+ m.to_str
+ end
+end
@@ -0,0 +1,32 @@
+require 'test_helper'
+
+describe Sodium::Hash::SHA256 do
+ let (:klass) { Sodium::Hash::SHA256 }
+ let (:primitive) { :sha256 }
+
+ let :constants do
+ { :BYTES => 32 }
+ end
+
+ let :hash do
+ Base64.decode64 'q1MKE+RZFJgrefm34/uplM/R8/si9xzqGvvwK0YMbR0='
+ end
+
+ let(:plaintext) { 'message' }
+
+ it '::primitive must be correct' do
+ self.klass.primitive.must_equal self.primitive
+ end
+
+ it 'must have correct values for its constants' do
+ self.constants.each_pair do |name, value|
+ self.klass[name].must_equal value
+ end
+ end
+
+ it 'must generate hashes' do
+ self.klass.hash(
+ self.plaintext
+ ).must_equal self.hash
+ end
+end
@@ -0,0 +1,35 @@
+require 'test_helper'
+
+describe Sodium::Hash::SHA512 do
+ let (:klass) { Sodium::Hash::SHA512 }
+ let (:primitive) { :sha512 }
+
+ let :constants do
+ { :BYTES => 64 }
+ end
+
+ let :hash do
+ Base64.decode64 %{
+ +Nr1ejNHzE1rnVdbMf5gd+LLSH9gqWIzwIy0edvzFTjMkV7G1IvbqpbdwaFt
+ tPT5bzcnbPyzUQuCRiQXcNWVLA==
+ }
+ end
+
+ let(:plaintext) { 'message' }
+
+ it '::primitive must be correct' do
+ self.klass.primitive.must_equal self.primitive
+ end
+
+ it 'must have correct values for its constants' do
+ self.constants.each_pair do |name, value|
+ self.klass[name].must_equal value
+ end
+ end
+
+ it 'must generate hashes' do
+ self.klass.hash(
+ self.plaintext
+ ).must_equal self.hash
+ end
+end
View
@@ -0,0 +1,32 @@
+require 'test_helper'
+
+describe Sodium::Hash do
+ let(:klass) { Sodium::Hash }
+ let(:plaintext) { 'message' }
+
+ it 'must default to the SHA512 implementation' do
+ self.klass.implementation.
+ must_equal Sodium::Hash::SHA512
+ end
+
+ it 'must allow access to alternate implementations' do
+ self.klass.implementation(:sha256).
+ must_equal Sodium::Hash::SHA256
+ end
+
+ it 'must hash from the default implementation' do
+ sodium_mock_default(self.klass) do |klass, mock|
+ mock.expect :[], 0, [ :BYTES ]
+ mock.expect :nacl, '', [ String, self.plaintext, self.plaintext.length ]
+
+ klass.hash(self.plaintext).length.must_equal 0
+ end
+ end
+
+ it 'must raise when failing to generate a hash' do
+ sodium_stub_failure(self.klass, :nacl) do
+ lambda { self.klass.hash(self.plaintext) }.
+ must_raise Sodium::CryptoError
+ end
+ end
+end

0 comments on commit 3063daa

Please sign in to comment.