hkdf 0.3.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 32e2c102c323f4510551f669261ce3fe39c11dc3
4
- data.tar.gz: f2585bdce88e509b0d7acf699b0313029fb767ab
2
+ SHA256:
3
+ metadata.gz: b3981a10daf0d498be5d757d585f60d5b7ed39510da169fd57caaf05cfd19b55
4
+ data.tar.gz: 639210e0fa56a62d07483f2e67e8df7b20d35fb55f0ca55296509f1a029c906c
5
5
  SHA512:
6
- metadata.gz: 303d49a8b562e90325cc90fe5bb1ce6294de07973d6f974f136c50bc9ae23e02cb09f36c725be7394e610bd4526beea9f61b9b5aee67fa7f370a0e553a4b1713
7
- data.tar.gz: 1037d09b22dac87dea10a86a8ec1dea9f84390d43d5a9d5ace084e1d6c02a0e50ce57015a916dad6fe75f58683487cee911043168f63119c15da12ea17347685
6
+ metadata.gz: 62d0e251f2ecc9f713571a38388851a3781667c3de53f339061a7663fdb09f9a78705df12828151b5d252a59754cd401ab80dd95e36f96a255018f1721b4203d
7
+ data.tar.gz: 8be1132f9dc82666401d1034e509c3ce02aff76f63c0c033b716d50836d805747e90cc1358105176e0df9c9cbc2658aa6a23e1140d0c4c52ff11d9cc02f3a4d0
data/README.md CHANGED
@@ -1,4 +1,6 @@
1
- # HKDF [![Build Status](https://secure.travis-ci.org/jtdowney/hkdf.png?branch=master)](http://travis-ci.org/jtdowney/hkdf)
1
+ # HKDF
2
+
3
+ [![CI](https://github.com/jtdowney/hkdf/actions/workflows/ci.yml/badge.svg)](https://github.com/jtdowney/hkdf/actions/workflows/ci.yml)
2
4
 
3
5
  This is a ruby implementation of [RFC 5869](http://tools.ietf.org/html/rfc5869): HMAC-based Extract-and-Expand Key Derivation Function. The goal of HKDF is to take some source key material and generate suitable cryptographic keys from it.
4
6
 
@@ -6,7 +8,7 @@ This is a ruby implementation of [RFC 5869](http://tools.ietf.org/html/rfc5869):
6
8
 
7
9
  ```ruby
8
10
  hkdf = HKDF.new('source key material')
9
- hkdf.next_bytes(32)
11
+ hkdf.read(32)
10
12
  => "\f#\xF4b\x98\x9B\x7Fw>|/|k\xF4k\xB7\xB9\x11e\xC5\x92\xD1\fH\xFDG\x94vt\xB4\x14\xCE"
11
13
  ```
12
14
 
@@ -14,14 +16,18 @@ The default algorithm is HMAC-SHA256, you can override this and other defaults b
14
16
 
15
17
  ```ruby
16
18
  hkdf = HKDF.new('source key material', :salt => 'NaCl', :algorithm => 'SHA1', :info => 'the 411')
17
- hkdf.next_bytes(16)
19
+ hkdf.read(16)
18
20
  => "\xC0<\x13\x85\x8C\x84z\xCE\xC7\xCE+\xFF\x1C\xEB\xE6\xBC"
19
21
  ```
20
22
 
21
- You can also give an IO object as the source. It will be read in as a stream to generate the key. The optional argument ```:read_size``` can be used to control how many bytes are read from the IO at a time.
23
+ You can also give an IO object as the source. It will be read in as a stream to generate the key. The optional argument `:read_size` can be used to control how many bytes are read from the IO at a time.
22
24
 
23
25
  ```ruby
24
26
  hkdf = HKDF.new(File.new('/tmp/filename'), :read_size => 512)
25
- hkdf.next_bytes(32)
27
+ hkdf.read(32)
26
28
  => "\f#\xF4b\x98\x9B\x7Fw>|/|k\xF4k\xB7\xB9\x11e\xC5\x92\xD1\fH\xFDG\x94vt\xB4\x14\xCE"
27
29
  ```
30
+
31
+ ## Requirements
32
+
33
+ - Ruby >= 2.4
data/lib/hkdf.rb CHANGED
@@ -1,74 +1,96 @@
1
- require 'openssl'
2
- require 'stringio'
1
+ # frozen_string_literal: true
3
2
 
4
- class HKDF
5
- DefaultAlgorithm = 'SHA256'
6
- DefaultReadSize = 512 * 1024
3
+ require "openssl"
4
+ require "stringio"
7
5
 
6
+ # Provide HMAC-based Extract-and-Expand Key Derivation Function (HKDF) for Ruby.
7
+ class HKDF
8
+ # Default hash algorithm to use for HMAC.
9
+ DEFAULT_ALGOTIHM = "SHA256"
10
+ # Default buffer size for reading source IO.
11
+ DEFAULT_READ_SIZE = 512 * 1024
12
+
13
+ # Create a new HKDF instance with then provided +source+ key material.
14
+ #
15
+ # Options:
16
+ # - +algorithm:+ hash function to use (defaults to SHA-256)
17
+ # - +info:+ optional context and application specific information
18
+ # - +salt:+ optional salt value (a non-secret random value)
19
+ # - +read_size:+ buffer size when reading from a source IO
8
20
  def initialize(source, options = {})
9
21
  source = StringIO.new(source) if source.is_a?(String)
10
22
 
11
- algorithm = options.fetch(:algorithm, DefaultAlgorithm)
23
+ algorithm = options.fetch(:algorithm, DEFAULT_ALGOTIHM)
12
24
  @digest = OpenSSL::Digest.new(algorithm)
13
- @info = options.fetch(:info, '')
25
+ @info = options.fetch(:info, "")
14
26
 
15
27
  salt = options[:salt]
16
- salt = 0.chr * @digest.digest_length if salt.nil? or salt.empty?
17
- read_size = options.fetch(:read_size, DefaultReadSize)
28
+ salt = 0.chr * @digest.digest_length if salt.nil? || salt.empty?
29
+ read_size = options.fetch(:read_size, DEFAULT_READ_SIZE)
18
30
 
19
- @prk = _generate_prk(salt, source, read_size)
31
+ @prk = generate_prk(salt, source, read_size)
20
32
  @position = 0
21
- @blocks = []
22
- @blocks << ''
33
+ @blocks = [""]
23
34
  end
24
35
 
36
+ # Returns the hash algorithm this instance was configured with.
25
37
  def algorithm
26
38
  @digest.name
27
39
  end
28
40
 
41
+ # Maximum length that can be derived per the RFC.
29
42
  def max_length
30
43
  @max_length ||= @digest.digest_length * 255
31
44
  end
32
45
 
46
+ # Adjust the reading position to an arbitrary offset. Will raise +RangeError+ if you attempt to seek longer than
47
+ # +#max_length+.
33
48
  def seek(position)
34
- raise RangeError.new("cannot seek past #{max_length}") if position > max_length
49
+ raise RangeError, "cannot seek past #{max_length}" if position > max_length
35
50
 
36
51
  @position = position
37
52
  end
38
53
 
54
+ # Adjust reading position back to the beginning.
39
55
  def rewind
40
56
  seek(0)
41
57
  end
42
58
 
43
- def next_bytes(length)
59
+ # Read the next +length+ bytes from the stream. Will raise +RangeError+ if you attempt to read beyond +#max_length+.
60
+ def read(length)
44
61
  new_position = length + @position
45
- raise RangeError.new("requested #{length} bytes, only #{max_length} available") if new_position > max_length
62
+ raise RangeError, "requested #{length} bytes, only #{max_length} available" if new_position > max_length
46
63
 
47
- _generate_blocks(new_position)
64
+ generate_blocks(new_position)
48
65
 
49
66
  start = @position
50
67
  @position = new_position
51
68
 
52
- @blocks.join('').slice(start, length)
69
+ @blocks.join.slice(start, length)
53
70
  end
54
71
 
55
- def next_hex_bytes(length)
56
- next_bytes(length).unpack('H*').first
72
+ # Read the next +length+ bytes from the stream and return them hex encoded. Will raise +RangeError+ if you attempt to
73
+ # read beyond +#max_length+.
74
+ def read_hex(length)
75
+ read(length).unpack1("H*")
57
76
  end
58
77
 
78
+ # :nodoc:
59
79
  def inspect
60
80
  "#{to_s[0..-2]} algorithm=#{@digest.name.inspect} info=#{@info.inspect}>"
61
81
  end
62
82
 
63
- def _generate_prk(salt, source, read_size)
83
+ private
84
+
85
+ def generate_prk(salt, source, read_size)
64
86
  hmac = OpenSSL::HMAC.new(salt, @digest)
65
- while block = source.read(read_size)
87
+ while (block = source.read(read_size))
66
88
  hmac.update(block)
67
89
  end
68
90
  hmac.digest
69
91
  end
70
92
 
71
- def _generate_blocks(length)
93
+ def generate_blocks(length)
72
94
  start = @blocks.size
73
95
  block_count = (length.to_f / @digest.digest_length).ceil
74
96
  start.upto(block_count) do |n|
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ class HKDF
4
+ # :nodoc:
5
+ VERSION = "1.0.0"
6
+ end
data/spec/hkdf_spec.rb CHANGED
@@ -1,132 +1,139 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
2
4
 
3
5
  describe HKDF do
4
- let(:source) { 'source' }
5
6
  subject(:hkdf) do
6
- HKDF.new(source)
7
+ described_class.new(source)
7
8
  end
8
9
 
9
- describe 'initialize' do
10
- it 'accepts an IO or a string as a source' do
11
- output1 = HKDF.new(source).next_bytes(32)
12
- output2 = HKDF.new(StringIO.new(source)).next_bytes(32)
10
+ let(:source) { "source" }
11
+
12
+ describe "initialize" do
13
+ it "accepts an IO or a string as a source" do
14
+ output1 = described_class.new(source).read(32)
15
+ output2 = described_class.new(StringIO.new(source)).read(32)
13
16
  expect(output1).to eq(output2)
14
17
  end
15
18
 
16
- it 'reads in an IO at a given read size' do
17
- io = StringIO.new(source)
18
- expect(io).to receive(:read).with(1)
19
-
20
- HKDF.new(io, :read_size => 1)
19
+ it "reads in an IO at a given read size" do
20
+ io = instance_spy(StringIO, :io, read: nil)
21
+ described_class.new(io, read_size: 1)
22
+ expect(io).to have_received(:read).with(1)
21
23
  end
22
24
 
23
- it 'reads in the whole IO' do
24
- hkdf1 = HKDF.new(source, :read_size => 1)
25
- hkdf2 = HKDF.new(source)
25
+ it "reads in the whole IO" do
26
+ hkdf1 = described_class.new(source, read_size: 1)
27
+ hkdf2 = described_class.new(source)
26
28
 
27
- expect(hkdf1.next_bytes(32)).to eq(hkdf2.next_bytes(32))
29
+ expect(hkdf1.read(32)).to eq(hkdf2.read(32))
28
30
  end
29
31
 
30
- it 'defaults the algorithm to SHA-256' do
31
- expect(HKDF.new(source).algorithm).to eq('SHA256')
32
+ it "defaults the algorithm to SHA-256" do
33
+ expect(described_class.new(source).algorithm).to eq("SHA256")
32
34
  end
33
35
 
34
- it 'takes an optional digest algorithm' do
35
- hkdf = HKDF.new('source', :algorithm => 'SHA1')
36
- expect(hkdf.algorithm).to eq('SHA1')
36
+ it "takes an optional digest algorithm" do
37
+ hkdf = described_class.new("source", algorithm: "SHA1")
38
+ expect(hkdf.algorithm).to eq("SHA1")
37
39
  end
38
40
 
39
- it 'defaults salt to all zeros of digest length' do
41
+ it "defaults salt to all zeros of digest length" do
40
42
  salt = 0.chr * 32
41
43
 
42
- hkdf_salt = HKDF.new(source, :salt => salt)
43
- hkdf_nosalt = HKDF.new(source)
44
- expect(hkdf_salt.next_bytes(32)).to eq(hkdf_nosalt.next_bytes(32))
44
+ hkdf_salt = described_class.new(source, salt: salt)
45
+ hkdf_nosalt = described_class.new(source)
46
+ expect(hkdf_salt.read(32)).to eq(hkdf_nosalt.read(32))
45
47
  end
46
48
 
47
- it 'sets salt to all zeros if empty' do
48
- hkdf_blanksalt = HKDF.new(source, :salt => '')
49
- hkdf_nosalt = HKDF.new(source)
50
- expect(hkdf_blanksalt.next_bytes(32)).to eq(hkdf_nosalt.next_bytes(32))
49
+ it "sets salt to all zeros if empty" do
50
+ hkdf_blanksalt = described_class.new(source, salt: "")
51
+ hkdf_nosalt = described_class.new(source)
52
+ expect(hkdf_blanksalt.read(32)).to eq(hkdf_nosalt.read(32))
51
53
  end
52
54
 
53
- it 'defaults info to an empty string' do
54
- hkdf_info = HKDF.new(source, :info => '')
55
- hkdf_noinfo = HKDF.new(source)
56
- expect(hkdf_info.next_bytes(32)).to eq(hkdf_noinfo.next_bytes(32))
55
+ it "defaults info to an empty string" do
56
+ hkdf_info = described_class.new(source, info: "")
57
+ hkdf_noinfo = described_class.new(source)
58
+ expect(hkdf_info.read(32)).to eq(hkdf_noinfo.read(32))
57
59
  end
58
60
  end
59
61
 
60
- describe 'max_length' do
61
- it 'is 255 times the digest length' do
62
+ describe "max_length" do
63
+ it "is 255 times the digest length" do
62
64
  expect(hkdf.max_length).to eq(255 * 32)
63
65
  end
64
66
  end
65
67
 
66
- describe 'next_bytes' do
67
- it 'raises an error if requested size is > max_length' do
68
+ describe "read" do
69
+ it "does not raise if reading <= max_length" do
68
70
  expect do
69
- hkdf.next_bytes(hkdf.max_length + 1)
70
- end.to raise_error(RangeError, /requested \d+ bytes, only \d+ available/)
71
+ hkdf.read(hkdf.max_length)
72
+ end.not_to raise_error
73
+ end
71
74
 
75
+ it "raises an error if requested size is > max_length" do
72
76
  expect do
73
- hkdf.next_bytes(hkdf.max_length)
74
- end.to_not raise_error
77
+ hkdf.read(hkdf.max_length + 1)
78
+ end.to raise_error(RangeError, /requested \d+ bytes, only \d+ available/)
75
79
  end
76
80
 
77
- it 'raises an error if requested size + current position is > max_length' do
81
+ it "raises an error if requested size + current position is > max_length" do
78
82
  expect do
79
- hkdf.next_bytes(32)
80
- hkdf.next_bytes(hkdf.max_length - 31)
83
+ hkdf.read(32)
84
+ hkdf.read(hkdf.max_length - 31)
81
85
  end.to raise_error(RangeError, /requested \d+ bytes, only \d+ available/)
82
86
  end
83
87
 
84
- it 'advances the stream position' do
85
- expect(hkdf.next_bytes(32)).not_to eq(hkdf.next_bytes(32))
88
+ it "advances the stream position" do
89
+ expect(hkdf.read(32)).not_to eq(hkdf.read(32))
86
90
  end
87
91
 
88
- test_vectors.each do |name, options|
92
+ TestVectors.vectors.each do |name, options|
89
93
  it "matches output from the '#{name}' test vector" do
90
94
  options[:algorithm] = options[:Hash]
91
95
 
92
- hkdf = HKDF.new(options[:IKM], options)
93
- expect(hkdf.next_bytes(options[:L].to_i)).to eq(options[:OKM])
96
+ hkdf = described_class.new(options[:IKM], options)
97
+ expect(hkdf.read(options[:L].to_i)).to eq(options[:OKM])
94
98
  end
95
99
  end
96
100
  end
97
101
 
98
- describe 'next_hex_bytes' do
99
- it 'returns the next bytes as hex' do
100
- expect(hkdf.next_hex_bytes(20)).to eq('fb496612b8cb82cd2297770f83c72b377af16d7b')
102
+ describe "read_hex" do
103
+ it "returns the next bytes as hex" do
104
+ expect(hkdf.read_hex(20)).to eq("fb496612b8cb82cd2297770f83c72b377af16d7b")
101
105
  end
102
106
  end
103
107
 
104
- describe 'seek' do
105
- it 'sets the position anywhere in the stream' do
106
- hkdf.next_bytes(10)
107
- output = hkdf.next_bytes(32)
108
+ describe "seek" do
109
+ it "sets the position anywhere in the stream" do
110
+ hkdf.read(10)
111
+ output = hkdf.read(32)
108
112
  hkdf.seek(10)
109
- expect(hkdf.next_bytes(32)).to eq(output)
113
+ expect(hkdf.read(32)).to eq(output)
114
+ end
115
+
116
+ it "does not raise if <= max_length" do
117
+ expect { hkdf.seek(hkdf.max_length) }.not_to raise_error
110
118
  end
111
119
 
112
- it 'raises an error if requested to seek past end of stream' do
120
+ it "raises an error if requested to seek past end of stream" do
113
121
  expect { hkdf.seek(hkdf.max_length + 1) }.to raise_error(RangeError, /cannot seek past \d+/)
114
- expect { hkdf.seek(hkdf.max_length) }.to_not raise_error
115
122
  end
116
123
  end
117
124
 
118
- describe 'rewind' do
119
- it 'resets the stream position to the beginning' do
120
- output = hkdf.next_bytes(32)
125
+ describe "rewind" do
126
+ it "resets the stream position to the beginning" do
127
+ output = hkdf.read(32)
121
128
  hkdf.rewind
122
- expect(hkdf.next_bytes(32)).to eq(output)
129
+ expect(hkdf.read(32)).to eq(output)
123
130
  end
124
131
  end
125
132
 
126
- describe 'inspect' do
127
- it 'returns minimal information' do
128
- hkdf = HKDF.new('secret', info: 'public')
129
- expect(hkdf.inspect).to match(/^#<HKDF:0x[\h]+ algorithm="SHA256" info="public">$/)
133
+ describe "inspect" do
134
+ it "returns minimal information" do
135
+ hkdf = described_class.new("secret", info: "public")
136
+ expect(hkdf.inspect).to match(/^#<HKDF:0x[0-9a-f]+ algorithm="SHA256" info="public">$/)
130
137
  end
131
138
  end
132
139
  end
data/spec/spec_helper.rb CHANGED
@@ -1,23 +1,8 @@
1
- require 'hkdf'
1
+ # frozen_string_literal: true
2
2
 
3
- RSpec.configure do |config|
4
- config.order = 'random'
5
- end
3
+ require "hkdf"
4
+ require_relative "support/test_vectors"
6
5
 
7
- def test_vectors
8
- test_parts = File.readlines('spec/fixtures/test_vectors.txt').
9
- map(&:strip).
10
- reject(&:empty?).
11
- each_slice(8)
12
-
13
- test_parts.reduce({}) do |vectors, lines|
14
- name = lines.shift
15
- values = lines.reduce({}) do |hash, line|
16
- key, value = line.split('=').map(&:strip)
17
- value = '' unless value
18
- value = [value.slice(2..-1)].pack('H*') if value.start_with?('0x')
19
- hash.merge(key.to_sym => value)
20
- end
21
- vectors.merge(name => values)
22
- end
6
+ RSpec.configure do |config|
7
+ config.order = "random"
23
8
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :nodoc:
4
+ module TestVectors
5
+ module_function
6
+
7
+ # :nodoc:
8
+ def vectors
9
+ test_parts = File.readlines("spec/fixtures/test_vectors.txt")
10
+ .map(&:strip)
11
+ .reject(&:empty?)
12
+ .each_slice(8)
13
+
14
+ test_parts.reduce({}) do |vectors, lines|
15
+ name = lines.shift
16
+ values = split_test_vector(lines)
17
+ vectors.merge(name => values)
18
+ end
19
+ end
20
+
21
+ # :nodoc:
22
+ def split_test_vector(lines)
23
+ lines.reduce({}) do |hash, line|
24
+ key, value = line.split("=").map(&:strip)
25
+ value ||= ""
26
+ value = [value.slice(2..-1)].pack("H*") if value.start_with?("0x")
27
+ hash.merge(key.to_sym => value)
28
+ end
29
+ end
30
+ end
metadata CHANGED
@@ -1,60 +1,88 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hkdf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Downey
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-09 00:00:00.000000000 Z
11
+ date: 2021-04-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bundler
14
+ name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.0'
19
+ version: '12.0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.0'
26
+ version: '12.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rake
28
+ name: rspec
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '='
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 10.5.0
33
+ version: '3.9'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '='
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 10.5.0
40
+ version: '3.9'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rspec
42
+ name: rubocop
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '='
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 3.4.0
47
+ version: '1.12'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '='
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.12'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop-rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
53
60
  - !ruby/object:Gem::Version
54
- version: 3.4.0
55
- description: 'A ruby implementation of RFC5869: HMAC-based Extract-and-Expand Key
56
- Derivation Function (HKDF). The goal of HKDF is to take some source key material
57
- and generate suitable cryptographic keys from it.'
61
+ version: 0.5.1
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.5.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop-rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '2.2'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '2.2'
83
+ description: |
84
+ A ruby implementation of RFC5869: HMAC-based Extract-and-Expand Key Derivation Function (HKDF). The goal of HKDF is
85
+ to take some source key material and generate suitable cryptographic keys from it.
58
86
  email:
59
87
  - jdowney@gmail.com
60
88
  executables: []
@@ -64,14 +92,16 @@ files:
64
92
  - LICENSE
65
93
  - README.md
66
94
  - lib/hkdf.rb
95
+ - lib/hkdf/version.rb
67
96
  - spec/fixtures/test_vectors.txt
68
97
  - spec/hkdf_spec.rb
69
98
  - spec/spec_helper.rb
99
+ - spec/support/test_vectors.rb
70
100
  homepage: http://github.com/jtdowney/hkdf
71
101
  licenses:
72
102
  - MIT
73
103
  metadata: {}
74
- post_install_message:
104
+ post_install_message:
75
105
  rdoc_options: []
76
106
  require_paths:
77
107
  - lib
@@ -79,19 +109,19 @@ required_ruby_version: !ruby/object:Gem::Requirement
79
109
  requirements:
80
110
  - - ">="
81
111
  - !ruby/object:Gem::Version
82
- version: '0'
112
+ version: 2.4.0
83
113
  required_rubygems_version: !ruby/object:Gem::Requirement
84
114
  requirements:
85
115
  - - ">="
86
116
  - !ruby/object:Gem::Version
87
117
  version: '0'
88
118
  requirements: []
89
- rubyforge_project:
90
- rubygems_version: 2.5.1
91
- signing_key:
119
+ rubygems_version: 3.2.15
120
+ signing_key:
92
121
  specification_version: 4
93
122
  summary: HMAC-based Key Derivation Function
94
123
  test_files:
95
124
  - spec/fixtures/test_vectors.txt
96
125
  - spec/hkdf_spec.rb
97
126
  - spec/spec_helper.rb
127
+ - spec/support/test_vectors.rb