hkdf 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +8 -0
- data/lib/hkdf.rb +15 -2
- data/spec/hkdf_spec.rb +25 -5
- data/spec/spec_helper.rb +5 -0
- metadata +10 -5
data/README.md
CHANGED
@@ -18,6 +18,14 @@ hkdf.next_bytes(16)
|
|
18
18
|
=> "\xC0<\x13\x85\x8C\x84z\xCE\xC7\xCE+\xFF\x1C\xEB\xE6\xBC"
|
19
19
|
```
|
20
20
|
|
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.
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
hkdf = HKDF.new(File.new('/tmp/filename'), :read_size => 512)
|
25
|
+
hkdf.next_bytes(32)
|
26
|
+
=> "\f#\xF4b\x98\x9B\x7Fw>|/|k\xF4k\xB7\xB9\x11e\xC5\x92\xD1\fH\xFDG\x94vt\xB4\x14\xCE"
|
27
|
+
```
|
28
|
+
|
21
29
|
## License
|
22
30
|
|
23
31
|
The HKDF gem is released under the [MIT license](http://www.opensource.org/licenses/MIT).
|
data/lib/hkdf.rb
CHANGED
@@ -1,16 +1,21 @@
|
|
1
1
|
require 'openssl'
|
2
|
+
require 'stringio'
|
2
3
|
|
3
4
|
class HKDF
|
5
|
+
DefaultReadSize = 512 * 1024
|
6
|
+
|
4
7
|
def initialize(source, options = {})
|
5
|
-
options = {:algorithm => 'SHA256', :info => '', :salt => nil}.merge(options)
|
8
|
+
options = {:algorithm => 'SHA256', :info => '', :salt => nil, :read_size => nil}.merge(options)
|
9
|
+
source = StringIO.new(source) if source.is_a?(String)
|
6
10
|
|
7
11
|
@digest = OpenSSL::Digest.new(options[:algorithm])
|
8
12
|
@info = options[:info]
|
9
13
|
|
10
14
|
salt = options[:salt]
|
11
15
|
salt = 0.chr * @digest.digest_length if salt.nil? or salt.empty?
|
16
|
+
read_size = options[:read_size] || DefaultReadSize
|
12
17
|
|
13
|
-
@prk =
|
18
|
+
@prk = _generate_prk(salt, source, read_size)
|
14
19
|
@position = 0
|
15
20
|
@blocks = []
|
16
21
|
@blocks << ''
|
@@ -50,6 +55,14 @@ class HKDF
|
|
50
55
|
next_bytes(length).unpack('H*').first
|
51
56
|
end
|
52
57
|
|
58
|
+
def _generate_prk(salt, source, read_size)
|
59
|
+
hmac = OpenSSL::HMAC.new(salt, @digest)
|
60
|
+
while block = source.read(read_size)
|
61
|
+
hmac.update(block)
|
62
|
+
end
|
63
|
+
hmac.digest
|
64
|
+
end
|
65
|
+
|
53
66
|
def _generate_blocks(length)
|
54
67
|
start = @blocks.size
|
55
68
|
block_count = (length.to_f / @digest.digest_length).ceil
|
data/spec/hkdf_spec.rb
CHANGED
@@ -8,6 +8,26 @@ describe HKDF do
|
|
8
8
|
end
|
9
9
|
|
10
10
|
describe 'initialize' do
|
11
|
+
it 'accepts an IO or a string as a source' do
|
12
|
+
output1 = HKDF.new(@source).next_bytes(32)
|
13
|
+
output2 = HKDF.new(StringIO.new(@source)).next_bytes(32)
|
14
|
+
output1.should == output2
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'reads in an IO at a given read size' do
|
18
|
+
io = StringIO.new(@source)
|
19
|
+
io.should_receive(:read).with(1)
|
20
|
+
|
21
|
+
HKDF.new(io, :read_size => 1)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'reads in the whole IO' do
|
25
|
+
hkdf1 = HKDF.new(@source, :read_size => 1)
|
26
|
+
hkdf2 = HKDF.new(@source)
|
27
|
+
|
28
|
+
hkdf1.next_bytes(32).should == hkdf2.next_bytes(32)
|
29
|
+
end
|
30
|
+
|
11
31
|
it 'defaults the algorithm to SHA-256' do
|
12
32
|
HKDF.new(@source).algorithm.should == 'SHA256'
|
13
33
|
end
|
@@ -46,15 +66,15 @@ describe HKDF do
|
|
46
66
|
|
47
67
|
describe 'next_bytes' do
|
48
68
|
it 'raises an error if requested size is > max_length' do
|
49
|
-
expect { @hkdf.next_bytes(@hkdf.max_length + 1) }.
|
50
|
-
expect { @hkdf.next_bytes(@hkdf.max_length) }.
|
69
|
+
expect { @hkdf.next_bytes(@hkdf.max_length + 1) }.to raise_error(RangeError, /requested \d+ bytes, only \d+ available/)
|
70
|
+
expect { @hkdf.next_bytes(@hkdf.max_length) }.to_not raise_error(RangeError)
|
51
71
|
end
|
52
72
|
|
53
73
|
it 'raises an error if requested size + current position is > max_length' do
|
54
74
|
expect do
|
55
75
|
@hkdf.next_bytes(32)
|
56
76
|
@hkdf.next_bytes(@hkdf.max_length - 31)
|
57
|
-
end.
|
77
|
+
end.to raise_error(RangeError, /requested \d+ bytes, only \d+ available/)
|
58
78
|
end
|
59
79
|
|
60
80
|
it 'advances the stream position' do
|
@@ -86,8 +106,8 @@ describe HKDF do
|
|
86
106
|
end
|
87
107
|
|
88
108
|
it 'raises an error if requested to seek past end of stream' do
|
89
|
-
expect { @hkdf.seek(@hkdf.max_length + 1) }.
|
90
|
-
expect { @hkdf.seek(@hkdf.max_length) }.
|
109
|
+
expect { @hkdf.seek(@hkdf.max_length + 1) }.to raise_error(RangeError, /cannot seek past \d+/)
|
110
|
+
expect { @hkdf.seek(@hkdf.max_length) }.to_not raise_error(RangeError)
|
91
111
|
end
|
92
112
|
end
|
93
113
|
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hkdf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-09-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,7 +21,12 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
25
30
|
description: ! 'A ruby implementation of RFC5869: HMAC-based Extract-and-Expand Key
|
26
31
|
Derivation Function (HKDF). The goal of HKDF is to take some source key material
|
27
32
|
and generate suitable cryptographic keys from it.'
|
@@ -56,7 +61,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
56
61
|
version: '0'
|
57
62
|
requirements: []
|
58
63
|
rubyforge_project:
|
59
|
-
rubygems_version: 1.8.
|
64
|
+
rubygems_version: 1.8.23
|
60
65
|
signing_key:
|
61
66
|
specification_version: 3
|
62
67
|
summary: HMAC-based Key Derivation Function
|