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 +4 -4
- data/README.md +32 -2
- data/bin/siphash +27 -0
- data/lib/digest/sip_hash.rb +39 -30
- data/lib/digest/sip_hash/version.rb +1 -1
- data/spec/helper.rb +4 -1
- data/spec/runner.rb +31 -5
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 97550c1117af3f364f69b7cf6fe0811b98abe710c1de440d75d43e2d8da30fc9
|
4
|
+
data.tar.gz: 50f608c0b241a416890727a44be29dda80ba78e213c7b74cee9e114dfed62822
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
##
|
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)
|
data/bin/siphash
ADDED
@@ -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}"
|
data/lib/digest/sip_hash.rb
CHANGED
@@ -5,7 +5,7 @@ require 'digest/sip_hash/version'
|
|
5
5
|
|
6
6
|
module Digest
|
7
7
|
class SipHash < Digest::Class
|
8
|
-
DEFAULT_KEY =
|
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.
|
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
|
59
|
-
|
60
|
-
compress_word
|
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
|
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
|
102
|
+
@v2 += @v3
|
103
|
+
@v2 &= MASK
|
77
104
|
@v3 = rotate @v3, by: 16
|
78
105
|
@v3 ^= @v2
|
79
|
-
@v0
|
106
|
+
@v0 += @v3
|
107
|
+
@v0 &= MASK
|
80
108
|
@v3 = rotate @v3, by: 21
|
81
109
|
@v3 ^= @v0
|
82
|
-
@v2
|
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 |
|
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
|
data/spec/helper.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
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'
|
data/spec/runner.rb
CHANGED
@@ -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 '
|
11
|
+
it 'is the correct hexdigest' do
|
12
12
|
assert_equal 'd1fba762150c532c', Digest::SipHash13.hexdigest('')
|
13
|
-
assert_equal '
|
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 '
|
33
|
+
it 'is the correct hexdigest' do
|
21
34
|
assert_equal '1e924b9d737700d7', Digest::SipHash24.hexdigest('')
|
22
|
-
assert_equal '
|
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 '
|
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.
|
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-
|
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
|