class RbNaCl::Hash::Blake2b
The Blake2b
hash function
Blake2b
is based on Blake, a SHA3 finalist which was snubbed in favor of Keccak, a much slower hash function but one sufficiently different from SHA2 to let the SHA3 judges panel sleep easy. Back in the real world, it'd be great if we can calculate hashes quickly if possible.
Blake2b
provides for up to 64-bit digests and also supports a keyed mode similar to HMAC
Constants
- EMPTY_PERSONAL
- EMPTY_SALT
Public Class Methods
Calculate a Blake2b
digest
@param [String] message Message to be hashed @param [Hash] options Blake2b
configuration @option opts [String] :key for Blake2b
keyed mode @option opts [Integer] :digest_size size of output digest in bytes @option opts [String] :salt Provide a salt to support randomised hashing.
This is mixed into the parameters block to start the hashing.
@option opts [Personal] :personal Provide personalisation string to allow pinning a hash for a particular purpose.
This is mixed into the parameters block to start the hashing
@raise [RbNaCl::LengthError] Invalid length specified for one or more options
@return [String] Blake2b
digest of the string as raw bytes
# File lib/rbnacl/hash/blake2b.rb, line 60 def self.digest(message, options) opts = validate_opts(options) digest = Util.zeros(opts[:digest_size]) generichash_blake2b(digest, opts[:digest_size], message, message.bytesize, opts[:key], opts[:key_size], opts[:salt], opts[:personal]) || raise(CryptoError, "Hashing failed!") digest end
# File lib/rbnacl/hash/blake2b.rb, line 109 def self.new(opts = {}) opts = validate_opts(opts) super end
Create a new Blake2b
hash object
@param [Hash] opts Blake2b
configuration @option opts [String] :key for Blake2b
keyed mode @option opts [Integer] :digest_size size of output digest in bytes @option opts [String] :salt Provide a salt to support randomised hashing.
This is mixed into the parameters block to start the hashing.
@option opts [Personal] :personal Provide personalisation string to allow pinning a hash for a particular purpose.
This is mixed into the parameters block to start the hashing
@raise [RbNaCl::LengthError] Invalid length specified for one or more options
@return [RbNaCl::Hash::Blake2b] A Blake2b
hasher object
# File lib/rbnacl/hash/blake2b.rb, line 127 def initialize(opts = {}) @key = opts[:key] @key_size = opts[:key_size] @digest_size = opts[:digest_size] @personal = opts[:personal] @salt = opts[:salt] @incycle = false @instate = nil end
Private Class Methods
Validate and sanitize values for Blake2b
configuration
@param [Hash] options Blake2b
configuration @option opts [String] :key for Blake2b
keyed mode @option opts [Integer] :digest_size size of output digest in bytes @option opts [String] :salt Provide a salt to support randomised hashing.
This is mixed into the parameters block to start the hashing.
@option opts [Personal] :personal Provide personalisation string to allow pinning a hash for a particular purpose.
This is mixed into the parameters block to start the hashing
@raise [RbNaCl::LengthError] Invalid length specified for one or more options
@return [Hash] opts Configuration hash with sanitized values
# File lib/rbnacl/hash/blake2b.rb, line 82 def self.validate_opts(opts) key = opts.fetch(:key, nil) if key key_size = key.bytesize raise LengthError, "key too short" if key_size < KEYBYTES_MIN raise LengthError, "key too long" if key_size > KEYBYTES_MAX else key_size = 0 end opts[:key_size] = key_size digest_size = opts.fetch(:digest_size, BYTES_MAX) raise LengthError, "digest size too short" if digest_size < BYTES_MIN raise LengthError, "digest size too long" if digest_size > BYTES_MAX opts[:digest_size] = digest_size personal = opts.fetch(:personal, EMPTY_PERSONAL) opts[:personal] = Util.zero_pad(PERSONALBYTES, personal) salt = opts.fetch(:salt, EMPTY_SALT) opts[:salt] = Util.zero_pad(SALTBYTES, salt) opts end
Public Instance Methods
Finalize digest calculation, return cached digest if any
@return [String] Blake2b
digest of the string as raw bytes
# File lib/rbnacl/hash/blake2b.rb, line 162 def digest raise(CryptoError, "No message to hash yet!") unless @incycle return @digest if @digest @digest = Util.zeros(@digest_size) self.class.generichash_blake2b_final(@instate.pointer, @digest, @digest_size) || raise(CryptoError, "Hash finalization failed!") @digest end
Initialize state for Blake2b
hash calculation, this will be called automatically from update
if needed
# File lib/rbnacl/hash/blake2b.rb, line 140 def reset @instate.release if @instate @instate = State.new self.class.generichash_blake2b_init(@instate.pointer, @key, @key_size, @digest_size, @salt, @personal) || raise(CryptoError, "Hash init failed!") @incycle = true @digest = nil end
Reentrant version of Blake2b
digest calculation method
@param [String] message Message to be hashed
# File lib/rbnacl/hash/blake2b.rb, line 152 def update(message) reset unless @incycle self.class.generichash_blake2b_update(@instate.pointer, message, message.bytesize) || raise(CryptoError, "Hashing failed!") end