class HKDF

Provide HMAC-based Extract-and-Expand Key Derivation Function (HKDF) for Ruby.

Constants

DEFAULT_ALGOTIHM

Default hash algorithm to use for HMAC.

DEFAULT_READ_SIZE

Default buffer size for reading source IO.

Public Class Methods

new(source, options = {}) click to toggle source

Create a new HKDF instance with then provided source key material.

Options:

  • algorithm: hash function to use (defaults to SHA-256)

  • info: optional context and application specific information

  • salt: optional salt value (a non-secret random value)

  • read_size: buffer size when reading from a source IO

# File lib/hkdf.rb, line 20
def initialize(source, options = {})
  source = StringIO.new(source) if source.is_a?(String)

  algorithm = options.fetch(:algorithm, DEFAULT_ALGOTIHM)
  @digest = OpenSSL::Digest.new(algorithm)
  @info = options.fetch(:info, "")

  salt = options[:salt]
  salt = 0.chr * @digest.digest_length if salt.nil? || salt.empty?
  read_size = options.fetch(:read_size, DEFAULT_READ_SIZE)

  @prk = generate_prk(salt, source, read_size)
  @position = 0
  @blocks = [""]
end

Public Instance Methods

algorithm() click to toggle source

Returns the hash algorithm this instance was configured with.

# File lib/hkdf.rb, line 37
def algorithm
  @digest.name
end
max_length() click to toggle source

Maximum length that can be derived per the RFC.

# File lib/hkdf.rb, line 42
def max_length
  @max_length ||= @digest.digest_length * 255
end
read(length) click to toggle source

Read the next length bytes from the stream. Will raise RangeError if you attempt to read beyond #max_length.

# File lib/hkdf.rb, line 60
def read(length)
  new_position = length + @position
  raise RangeError, "requested #{length} bytes, only #{max_length} available" if new_position > max_length

  generate_blocks(new_position)

  start = @position
  @position = new_position

  @blocks.join.slice(start, length)
end
read_hex(length) click to toggle source

Read the next length bytes from the stream and return them hex encoded. Will raise RangeError if you attempt to read beyond #max_length.

# File lib/hkdf.rb, line 74
def read_hex(length)
  read(length).unpack1("H*")
end
rewind() click to toggle source

Adjust reading position back to the beginning.

# File lib/hkdf.rb, line 55
def rewind
  seek(0)
end
seek(position) click to toggle source

Adjust the reading position to an arbitrary offset. Will raise RangeError if you attempt to seek longer than #max_length.

# File lib/hkdf.rb, line 48
def seek(position)
  raise RangeError, "cannot seek past #{max_length}" if position > max_length

  @position = position
end