digest-sip_hash 0.0.1 → 0.0.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1fb155635e2e5bd99bcff43710d42625ad2568666d0aad79ec1e37685c74aad2
4
- data.tar.gz: 68b5c8b28f2c60e7fdf8a67a3f0af9b672222c3bd42ac309a266085f4e0c595b
3
+ metadata.gz: 97550c1117af3f364f69b7cf6fe0811b98abe710c1de440d75d43e2d8da30fc9
4
+ data.tar.gz: 50f608c0b241a416890727a44be29dda80ba78e213c7b74cee9e114dfed62822
5
5
  SHA512:
6
- metadata.gz: c5bef15d6df7931d938ca1b1968d801365acc1739ea26957396e73b09ffee98bb69776ad4b08f097b4ba0cc2df890559acebf18c70c4ad9121362d79c16c1527
7
- data.tar.gz: b643ae5e6c91ead012d6c1985657421017a775680ca1b186b74fce76354192b330a13d5a25893eaa1a70ab29d351a4511d5f03eea4486e88f01b23a1a5367479
6
+ metadata.gz: 3e1ce5568375369e28fe69708ae0780d29e74c7859d3df3e8ae248e484a8f6c13d2d851c932a3084831deaf3f8ca7b05f75184bd616a2716151cd08ea9fbd30e
7
+ data.tar.gz: 47537c8a82aae0818eb6eeea9e879bc6d33e6f340e70efa11d2cb14f6a267bbe1a54bb7b8b651afacd23be918ec6d97133e422706c82dfbd9c0b519bec7e1694
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Digest::SipHash
2
2
 
3
- A pure Ruby implementation of SipHash 1-3 and 2-4.
3
+ A pure Ruby implementation of SipHash 1-3 and 2-4. Arbitrary round counts are also supported. If rounds and key are not specified, the default is SipHash 1-3 with a key of sixteen null bytes.
4
4
 
5
5
  ## Installation
6
6
 
@@ -8,7 +8,7 @@ A pure Ruby implementation of SipHash 1-3 and 2-4.
8
8
  gem install digest-sip_hash
9
9
  ```
10
10
 
11
- ## Usage Examples
11
+ ## Library Examples
12
12
 
13
13
  The default key is 16 null bytes. Use `SecureRandom.bytes 16` to generate a random key.
14
14
 
@@ -32,6 +32,36 @@ Digest::SipHash24.hexdigest ''
32
32
  #=> "1e924b9d737700d7"
33
33
  ```
34
34
 
35
+ ## Command Line Examples
36
+
37
+ ```
38
+ Usage: siphash [OPTIONS] FILE
39
+ -c=ROUNDS Number of c rounds. Default: 1
40
+ -d=ROUNDS Number of d rounds. Default: 3
41
+ -k, --key=KEY Sixteen-byte hex key. Default: "00000000000000000000000000000000"
42
+ ```
43
+
44
+ Check hashes by providing a filename to the `siphash` executable:
45
+ ```sh
46
+ touch empty_file
47
+ siphash empty_file
48
+ #>> d1fba762150c532c empty_file
49
+ ```
50
+
51
+ Or pipe input to `siphash`:
52
+ ```sh
53
+ # SipHash 1-3
54
+ echo -n "" | siphash
55
+ #>> d1fba762150c532c -
56
+
57
+ # SipHash 2-4
58
+ echo -n "" | siphash -c2 -d4
59
+ #>> 1e924b9d737700d7 -
60
+
61
+ echo -n "" | siphash --key "00010203040506070809101112131415"
62
+ #>> 067c02f6c87ccd93 -
63
+ ```
64
+
35
65
  ## C-Extension Alternative
36
66
 
37
67
  [digest-siphash](https://github.com/ksss/digest-siphash)
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # frozen_string_literal: true
4
+
5
+ require 'digest/sip_hash'
6
+ require 'optionparser'
7
+
8
+ hex_key = Digest::SipHash::DEFAULT_KEY.unpack1 'H*'
9
+ Settings = Struct.new :c, :d, :key, keyword_init: true
10
+ settings = Settings.new c: 1, d: 3, key: hex_key
11
+ options = ARGV.options do |x|
12
+ x.banner = "Usage: #{x.program_name} [OPTIONS] FILE"
13
+ x.version = Digest::SipHash::VERSION
14
+
15
+ UnsignedInteger = /\A\d+\z/
16
+ x.accept UnsignedInteger, UnsignedInteger, &:to_i
17
+
18
+ x.on '-c=ROUNDS', UnsignedInteger, "Number of c rounds. Default: #{settings.c}"
19
+ x.on '-d=ROUNDS', UnsignedInteger, "Number of d rounds. Default: #{settings.d}"
20
+ x.on '-k', '--key=KEY', String, "Sixteen-byte hex key. Default: \"#{hex_key}\""
21
+ end.freeze
22
+ options.permute! into: settings
23
+
24
+ path = ARGV.fetch 0, '-'
25
+ hash = Digest::SipHash.new(settings.c, settings.d, key: [settings.key].pack('H*')).hexdigest ARGF.read
26
+
27
+ puts "#{hash} #{path}"
@@ -5,7 +5,7 @@ require 'digest/sip_hash/version'
5
5
 
6
6
  module Digest
7
7
  class SipHash < Digest::Class
8
- DEFAULT_KEY = (0.chr * 16).freeze
8
+ DEFAULT_KEY = 0.chr * 16
9
9
 
10
10
  attr_accessor :key
11
11
 
@@ -29,7 +29,7 @@ module Digest
29
29
 
30
30
  def finish
31
31
  sip = Sip.new @buffer, @key, @c_rounds, @d_rounds
32
- sip.append
32
+ sip.transform
33
33
  sip.finalize
34
34
  end
35
35
 
@@ -55,9 +55,10 @@ module Digest
55
55
  @v3 = V3 ^ k1
56
56
  end
57
57
 
58
- def append
59
- (@size / 8).times { |n| compress_word @buffer.slice(n * 8, 8).unpack1 'Q<' }
60
- compress_word complete_pending
58
+ def transform
59
+ return compress_word 0 if @size.zero?
60
+ (@size / 8).times { |n| compress_word word n }
61
+ compress_word last_word
61
62
  end
62
63
 
63
64
  def finalize
@@ -68,45 +69,53 @@ module Digest
68
69
 
69
70
  private
70
71
 
72
+ def compress_word m
73
+ @v3 ^= m
74
+ @c_rounds.times { compress }
75
+ @v0 ^= m
76
+ end
77
+
78
+ def word n
79
+ @buffer.slice(n * 8, 8).unpack1 'Q<'
80
+ end
81
+
82
+ def last_word
83
+ remainder = @size % 8
84
+ offset = @size - remainder
85
+
86
+ last = @size << 56 & MASK
87
+
88
+ 7.downto 0 do |n|
89
+ next if n >= remainder
90
+ last |= @buffer[n + offset].ord << 8 * n
91
+ end
92
+
93
+ last
94
+ end
95
+
71
96
  def compress
72
- @v0 = (@v0 + @v1) & MASK
97
+ @v0 += @v1
98
+ @v0 &= MASK
73
99
  @v1 = rotate @v1, by: 13
74
100
  @v1 ^= @v0
75
101
  @v0 = rotate @v0, by: 32
76
- @v2 = (@v2 + @v3) & MASK
102
+ @v2 += @v3
103
+ @v2 &= MASK
77
104
  @v3 = rotate @v3, by: 16
78
105
  @v3 ^= @v2
79
- @v0 = (@v0 + @v3) & MASK
106
+ @v0 += @v3
107
+ @v0 &= MASK
80
108
  @v3 = rotate @v3, by: 21
81
109
  @v3 ^= @v0
82
- @v2 = (@v2 + @v1) & MASK
110
+ @v2 += @v1
111
+ @v2 &= MASK
83
112
  @v1 = rotate @v1, by: 17
84
113
  @v1 ^= @v2
85
114
  @v2 = rotate @v2, by: 32
86
115
  end
87
116
 
88
117
  def rotate n, by:
89
- n << by & MASK | (n >> (64 - by))
90
- end
91
-
92
- def compress_word m
93
- @v3 ^= m
94
- @c_rounds.times { compress }
95
- @v0 ^= m
96
- end
97
-
98
- def complete_pending
99
- last = (@size << 56) & MASK
100
- return last if @size.zero?
101
-
102
- r = @size % 8
103
- offset = @size / 8 * 8
104
-
105
- [0, 8, 16, 24, 32, 40, 48].each_with_index.reverse_each do |n, i|
106
- last |= @buffer[offset + i].ord << n if r > i
107
- end
108
-
109
- last
118
+ n << by & MASK | n >> 64 - by
110
119
  end
111
120
  end
112
121
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Digest
4
4
  class SipHash < Digest::Class
5
- VERSION = '0.0.1'
5
+ VERSION = '0.0.2'
6
6
  end
7
7
  end
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../lib/digest/sip_hash'
3
+ lib = File.expand_path '../../lib', __FILE__
4
+ $LOAD_PATH.prepend lib unless $LOAD_PATH.include? lib
5
+
6
+ require 'digest/sip_hash'
4
7
  require 'minitest/autorun'
5
8
  require 'minitest/pride'
@@ -8,25 +8,51 @@ describe Digest::SipHash do
8
8
  assert_equal Digest::SipHash.hexdigest(''), Digest::SipHash13.hexdigest('')
9
9
  end
10
10
 
11
- it 'produces the correct hash' do
11
+ it 'is the correct hexdigest' do
12
12
  assert_equal 'd1fba762150c532c', Digest::SipHash13.hexdigest('')
13
- assert_equal 'abac0158050fc4dc', Digest::SipHash13.hexdigest('', key: 16.times.map(&:chr).join)
13
+ assert_equal '8264ceeccb16bcbe', Digest::SipHash13.hexdigest('siphash')
14
14
  assert_equal 'ce31007e34130c0a', Digest::SipHash13.hexdigest('digest-sip_hash')
15
15
  assert_equal '1b47c0cc4dd21f05', Digest::SipHash13.hexdigest('x' * 1_000)
16
16
  end
17
+
18
+ describe 'with a key' do
19
+ let :key do
20
+ 16.times.map(&:chr).join
21
+ end
22
+
23
+ it 'is the correct hexdigest' do
24
+ assert_equal 'abac0158050fc4dc', Digest::SipHash13.hexdigest('', key: key)
25
+ assert_equal 'd5518fe19f28c745', Digest::SipHash13.hexdigest('siphash', key: key)
26
+ assert_equal '71783f159400d4b5', Digest::SipHash13.hexdigest('digest-sip_hash', key: key)
27
+ assert_equal '2a82bb3e74675b16', Digest::SipHash13.hexdigest('x' * 1_000, key: key)
28
+ end
29
+ end
17
30
  end
18
31
 
19
32
  describe Digest::SipHash24 do
20
- it 'produces the correct hash' do
33
+ it 'is the correct hexdigest' do
21
34
  assert_equal '1e924b9d737700d7', Digest::SipHash24.hexdigest('')
22
- assert_equal '726fdb47dd0e0e31', Digest::SipHash24.hexdigest('', key: 16.times.map(&:chr).join)
35
+ assert_equal '59caaeb90d542464', Digest::SipHash24.hexdigest('siphash')
23
36
  assert_equal '4b5cd6bb2500bc8f', Digest::SipHash24.hexdigest('digest-sip_hash')
24
37
  assert_equal 'a07a230346e2656b', Digest::SipHash24.hexdigest('x' * 1_000)
25
38
  end
39
+
40
+ describe 'with a key' do
41
+ let :key do
42
+ 16.times.map(&:chr).join
43
+ end
44
+
45
+ it 'is the correct hexdigest' do
46
+ assert_equal '726fdb47dd0e0e31', Digest::SipHash24.hexdigest('', key: key)
47
+ assert_equal '882768570dc71c92', Digest::SipHash24.hexdigest('siphash', key: key)
48
+ assert_equal '882768570dc71c92', Digest::SipHash24.hexdigest('siphash', key: key)
49
+ assert_equal '882768570dc71c92', Digest::SipHash24.hexdigest('siphash', key: key)
50
+ end
51
+ end
26
52
  end
27
53
 
28
54
  describe 'arbitrary rounds other than 1-3 and 2-4' do
29
- it 'produces the correct hash' do
55
+ it 'is the correct hexdigest' do
30
56
  assert_equal '3204eeb59b3cccdd', Digest::SipHash.new(1, 2).hexdigest('')
31
57
  assert_equal 'cea28b51565c12e2', Digest::SipHash.new(1, 2, key: 16.times.map(&:chr).join).hexdigest('')
32
58
  assert_equal '95772adebda3f3f0', Digest::SipHash.new(3, 5).hexdigest('')
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: digest-sip_hash
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shannon Skipper
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-31 00:00:00.000000000 Z
11
+ date: 2018-06-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -41,7 +41,8 @@ dependencies:
41
41
  description: An implementation of SipHash 1-3 and 2-4 in pure Ruby.
42
42
  email:
43
43
  - shannonskipper@gmail.com
44
- executables: []
44
+ executables:
45
+ - siphash
45
46
  extensions: []
46
47
  extra_rdoc_files: []
47
48
  files:
@@ -49,6 +50,7 @@ files:
49
50
  - LICENSE
50
51
  - README.md
51
52
  - Rakefile
53
+ - bin/siphash
52
54
  - lib/digest/sip_hash.rb
53
55
  - lib/digest/sip_hash/version.rb
54
56
  - spec/helper.rb