digest-sip_hash 0.0.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1fb155635e2e5bd99bcff43710d42625ad2568666d0aad79ec1e37685c74aad2
4
+ data.tar.gz: 68b5c8b28f2c60e7fdf8a67a3f0af9b672222c3bd42ac309a266085f4e0c595b
5
+ SHA512:
6
+ metadata.gz: c5bef15d6df7931d938ca1b1968d801365acc1739ea26957396e73b09ffee98bb69776ad4b08f097b4ba0cc2df890559acebf18c70c4ad9121362d79c16c1527
7
+ data.tar.gz: b643ae5e6c91ead012d6c1985657421017a775680ca1b186b74fce76354192b330a13d5a25893eaa1a70ab29d351a4511d5f03eea4486e88f01b23a1a5367479
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2018 Shannon Skipper
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,45 @@
1
+ # Digest::SipHash
2
+
3
+ A pure Ruby implementation of SipHash 1-3 and 2-4.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ gem install digest-sip_hash
9
+ ```
10
+
11
+ ## Usage Examples
12
+
13
+ The default key is 16 null bytes. Use `SecureRandom.bytes 16` to generate a random key.
14
+
15
+ ```ruby
16
+ Digest::SipHash.new.hexdigest ''
17
+ #=> "d1fba762150c532c"
18
+
19
+ Digest::SipHash.new(key: 16.times.map(&:chr).join).hexdigest ''
20
+ #=> "abac0158050fc4dc"
21
+
22
+ Digest::SipHash.new(1, 3).hexdigest ''
23
+ #=> "d1fba762150c532c"
24
+
25
+ Digest::SipHash13.hexdigest ''
26
+ #=> "d1fba762150c532c"
27
+
28
+ Digest::SipHash.new(2, 4).hexdigest ''
29
+ #=> "1e924b9d737700d7"
30
+
31
+ Digest::SipHash24.hexdigest ''
32
+ #=> "1e924b9d737700d7"
33
+ ```
34
+
35
+ ## C-Extension Alternative
36
+
37
+ [digest-siphash](https://github.com/ksss/digest-siphash)
38
+
39
+ ## Requirements
40
+
41
+ Ruby 2.5+
42
+
43
+ ## License
44
+
45
+ MIT
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ task default: %w[test]
4
+
5
+ task :test do
6
+ ruby 'spec/runner.rb'
7
+ end
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'digest'
4
+ require 'digest/sip_hash/version'
5
+
6
+ module Digest
7
+ class SipHash < Digest::Class
8
+ DEFAULT_KEY = (0.chr * 16).freeze
9
+
10
+ attr_accessor :key
11
+
12
+ def initialize c_rounds = 1, d_rounds = 3, key: DEFAULT_KEY
13
+ @c_rounds = c_rounds
14
+ @d_rounds = d_rounds
15
+ @key = key
16
+ @buffer = +''
17
+ end
18
+
19
+ def << s
20
+ @buffer << s
21
+ self
22
+ end
23
+ alias update <<
24
+
25
+ def reset
26
+ @buffer.clear
27
+ self
28
+ end
29
+
30
+ def finish
31
+ sip = Sip.new @buffer, @key, @c_rounds, @d_rounds
32
+ sip.append
33
+ sip.finalize
34
+ end
35
+
36
+ class Sip
37
+ MASK = 2 ** 64 - 1
38
+ V0 = 'somepseu'.unpack1 'Q>'
39
+ V1 = 'dorandom'.unpack1 'Q>'
40
+ V2 = 'lygenera'.unpack1 'Q>'
41
+ V3 = 'tedbytes'.unpack1 'Q>'
42
+
43
+ def initialize buffer, key, c_rounds, d_rounds
44
+ @buffer = buffer
45
+ @size = @buffer.size
46
+ @c_rounds = c_rounds
47
+ @d_rounds = d_rounds
48
+
49
+ k0 = key[0..7].unpack1 'Q<'
50
+ k1 = key[8..15].unpack1 'Q<'
51
+
52
+ @v0 = V0 ^ k0
53
+ @v1 = V1 ^ k1
54
+ @v2 = V2 ^ k0
55
+ @v3 = V3 ^ k1
56
+ end
57
+
58
+ def append
59
+ (@size / 8).times { |n| compress_word @buffer.slice(n * 8, 8).unpack1 'Q<' }
60
+ compress_word complete_pending
61
+ end
62
+
63
+ def finalize
64
+ @v2 ^= 2 ** 8 - 1
65
+ @d_rounds.times { compress }
66
+ [@v0 ^ @v1 ^ @v2 ^ @v3].pack 'Q>'
67
+ end
68
+
69
+ private
70
+
71
+ def compress
72
+ @v0 = (@v0 + @v1) & MASK
73
+ @v1 = rotate @v1, by: 13
74
+ @v1 ^= @v0
75
+ @v0 = rotate @v0, by: 32
76
+ @v2 = (@v2 + @v3) & MASK
77
+ @v3 = rotate @v3, by: 16
78
+ @v3 ^= @v2
79
+ @v0 = (@v0 + @v3) & MASK
80
+ @v3 = rotate @v3, by: 21
81
+ @v3 ^= @v0
82
+ @v2 = (@v2 + @v1) & MASK
83
+ @v1 = rotate @v1, by: 17
84
+ @v1 ^= @v2
85
+ @v2 = rotate @v2, by: 32
86
+ end
87
+
88
+ 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
110
+ end
111
+ end
112
+ end
113
+
114
+ class SipHash13 < SipHash
115
+ def initialize key: DEFAULT_KEY
116
+ super 1, 3, key: key
117
+ end
118
+ end
119
+
120
+ class SipHash24 < SipHash
121
+ def initialize key: DEFAULT_KEY
122
+ super 2, 4, key: key
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Digest
4
+ class SipHash < Digest::Class
5
+ VERSION = '0.0.1'
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../lib/digest/sip_hash'
4
+ require 'minitest/autorun'
5
+ require 'minitest/pride'
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+
5
+ describe Digest::SipHash do
6
+ describe Digest::SipHash13 do
7
+ it 'is the default' do
8
+ assert_equal Digest::SipHash.hexdigest(''), Digest::SipHash13.hexdigest('')
9
+ end
10
+
11
+ it 'produces the correct hash' do
12
+ assert_equal 'd1fba762150c532c', Digest::SipHash13.hexdigest('')
13
+ assert_equal 'abac0158050fc4dc', Digest::SipHash13.hexdigest('', key: 16.times.map(&:chr).join)
14
+ assert_equal 'ce31007e34130c0a', Digest::SipHash13.hexdigest('digest-sip_hash')
15
+ assert_equal '1b47c0cc4dd21f05', Digest::SipHash13.hexdigest('x' * 1_000)
16
+ end
17
+ end
18
+
19
+ describe Digest::SipHash24 do
20
+ it 'produces the correct hash' do
21
+ assert_equal '1e924b9d737700d7', Digest::SipHash24.hexdigest('')
22
+ assert_equal '726fdb47dd0e0e31', Digest::SipHash24.hexdigest('', key: 16.times.map(&:chr).join)
23
+ assert_equal '4b5cd6bb2500bc8f', Digest::SipHash24.hexdigest('digest-sip_hash')
24
+ assert_equal 'a07a230346e2656b', Digest::SipHash24.hexdigest('x' * 1_000)
25
+ end
26
+ end
27
+
28
+ describe 'arbitrary rounds other than 1-3 and 2-4' do
29
+ it 'produces the correct hash' do
30
+ assert_equal '3204eeb59b3cccdd', Digest::SipHash.new(1, 2).hexdigest('')
31
+ assert_equal 'cea28b51565c12e2', Digest::SipHash.new(1, 2, key: 16.times.map(&:chr).join).hexdigest('')
32
+ assert_equal '95772adebda3f3f0', Digest::SipHash.new(3, 5).hexdigest('')
33
+ assert_equal 'f344baf915afc13a', Digest::SipHash.new(3, 5).hexdigest('x' * 1_000)
34
+ end
35
+ end
36
+ end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: digest-sip_hash
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Shannon Skipper
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-05-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '12'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '12'
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '5'
41
+ description: An implementation of SipHash 1-3 and 2-4 in pure Ruby.
42
+ email:
43
+ - shannonskipper@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - Gemfile
49
+ - LICENSE
50
+ - README.md
51
+ - Rakefile
52
+ - lib/digest/sip_hash.rb
53
+ - lib/digest/sip_hash/version.rb
54
+ - spec/helper.rb
55
+ - spec/runner.rb
56
+ homepage: https://github.com/havenwood/digest-sip_hash
57
+ licenses:
58
+ - MIT
59
+ metadata: {}
60
+ post_install_message:
61
+ rdoc_options: []
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ requirements: []
75
+ rubyforge_project:
76
+ rubygems_version: 2.7.7
77
+ signing_key:
78
+ specification_version: 4
79
+ summary: Pure Ruby SipHash 1-3 and 2-4.
80
+ test_files: []