digest-sip_hash 0.0.1 → 0.0.2

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
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