1 # a RFC5869 implementation:
2 # HMAC-based Extract-and-Expand Key Derivation Function (HKDF)
4 # function John Downey, downloaded from https://rubygems.org/gems/hkdf
5 # and distributed under the MIT license.
11 def initialize(source, options = {})
12 options = {:algorithm => 'SHA256', :info => '', :salt => nil}.merge(options)
14 @digest = OpenSSL::Digest.new(options[:algorithm])
15 @info = options[:info]
18 salt = 0.chr * @digest.digest_length if salt.nil? or salt.empty?
20 @prk = OpenSSL::HMAC.digest(@digest, salt, source)
31 @digest.digest_length * 255
35 raise RangeError.new("cannot seek past #{max_length}") if position > max_length
44 def next_bytes(length)
45 new_position = length + @position
46 raise RangeError.new("requested #{length} bytes, only #{max_length} available") if new_position > max_length
48 _generate_blocks(new_position)
51 @position = new_position
53 @blocks.join('').slice(start, length)
56 def next_hex_bytes(length)
57 next_bytes(length).unpack('H*').first
60 def _generate_blocks(length)
62 block_count = (length.to_f / @digest.digest_length).ceil
63 start.upto(block_count) do |n|
64 @blocks << OpenSSL::HMAC.digest(@digest, @prk, @blocks[n - 1] + @info + n.chr)
69 # puppetization by weasel
70 module Puppet::Parser::Functions
71 newfunction(:hkdf, :type => :rvalue) do |args|
72 secretfile = args.shift()
78 secret = File.new(secretfile, "r").read
80 raise Puppet::ParseError, "Error loading secret from #{seccretfile}: #{e.message}\n#{e.backtrace}"
83 hkdf = HKDF.new(secret, :info => data)
84 return hkdf.next_hex_bytes(32)
89 # vim:set shiftwidth=2: