digest-xxhash 0.1.0 → 0.2.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/LICENSE +1 -1
- data/README.md +44 -12
- data/Rakefile +13 -2
- data/digest-xxhash.gemspec +9 -5
- data/ext/digest/xxhash/ext.c +572 -144
- data/ext/digest/xxhash/extconf.rb +20 -0
- data/ext/digest/xxhash/utils.h +15 -4
- data/ext/digest/xxhash/xxhash.h +5607 -157
- data/lib/digest/xxhash/version.rb +1 -1
- data/test/produce-vectors-with-ruby-xxhash.rb +5 -4
- data/test/produce-vectors-with-xxhsum.rb +112 -0
- data/test/test.rb +64 -33
- data/test/test.vectors +960 -462
- data/test/xxhsum.c.c0e86bc0.diff +424 -0
- metadata +33 -12
- data/.travis.yml +0 -6
- data/appveyor.yml +0 -19
- data/ext/digest/xxhash/xxhash.c +0 -888
@@ -1,5 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
# This script does not produce test vectors for XXH3_64bits and XXH3_128bits but
|
4
|
+
# its output for XXH32 and XXH64 can be compared to xxhsum's.
|
5
|
+
|
3
6
|
require 'ruby-xxhash'
|
4
7
|
|
5
8
|
rijndael_sbox = [
|
@@ -60,14 +63,12 @@ end
|
|
60
63
|
if bit_size == 32
|
61
64
|
["00000000"].concat(_32bit_seeds_cycles.next).each do |seed|
|
62
65
|
sum = XXhash.xxh32(msg, seed.to_i(16))
|
63
|
-
|
64
|
-
$stdout.flush
|
66
|
+
puts "#{bit_size}|#{msg_method}|#{msg_length}|seed|#{seed}|#{"%08x" % sum}"
|
65
67
|
end
|
66
68
|
else
|
67
69
|
["0000000000000000"].concat(_64bit_seeds).each do |seed|
|
68
70
|
sum = XXhash.xxh64(msg, seed.to_i(16))
|
69
|
-
|
70
|
-
$stdout.flush
|
71
|
+
puts "#{bit_size}|#{msg_method}|#{msg_length}|seed|#{seed}|#{"%016x" % sum}"
|
71
72
|
end
|
72
73
|
end
|
73
74
|
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'open3'
|
4
|
+
|
5
|
+
rijndael_sbox = [
|
6
|
+
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
|
7
|
+
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
|
8
|
+
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
|
9
|
+
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
|
10
|
+
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
|
11
|
+
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
|
12
|
+
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
|
13
|
+
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
|
14
|
+
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
|
15
|
+
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
|
16
|
+
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
|
17
|
+
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
|
18
|
+
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
|
19
|
+
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
|
20
|
+
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
|
21
|
+
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
|
22
|
+
]
|
23
|
+
|
24
|
+
_32bit_seeds = rijndael_sbox.each_slice(4).map{ |e| e.map{ |f| "%02x" % f }.join }.to_a
|
25
|
+
_32bit_seeds_cycles = _32bit_seeds.cycle.each_slice(32)
|
26
|
+
_64bit_seeds = rijndael_sbox.each_slice(8).map{ |e| e.map{ |f| "%02x" % f }.join }.to_a
|
27
|
+
_secrets = rijndael_sbox.take(144).each_slice(3).map{ |e| e.permutation.to_a }
|
28
|
+
.then{ |e| e.shift.zip(*e) }.map{ |e| e.flatten.map{ |f| "%02x" %f }.join }
|
29
|
+
|
30
|
+
def get_repeated_0x00_to_0xff(length)
|
31
|
+
hex = (0..0xff).to_a.map{ |e| sprintf "%2x", e }.join
|
32
|
+
str = [hex].pack('H*')
|
33
|
+
cycles = (Float(length) / str.size).ceil
|
34
|
+
[str].cycle(cycles).to_a.join[0...length]
|
35
|
+
end
|
36
|
+
|
37
|
+
def produce_vectors(algo, algo_index, seed_type, seed_or_secret, msg, msg_method_used)
|
38
|
+
seed_opt = seed_type == :secret ? 'S' : 's'
|
39
|
+
cmd = ["./xxhsum", "-H#{algo_index}", "-#{seed_opt}#{seed_or_secret}"]
|
40
|
+
output, status = Open3.capture2(*cmd, binmode: true, stdin_data: msg)
|
41
|
+
exit 1 unless status.success?
|
42
|
+
sum = output.sub(/\s.*/, '')
|
43
|
+
puts "#{algo}|#{msg_method_used}|#{msg.length}|#{seed_type.to_s}|#{seed_or_secret}|#{sum}"
|
44
|
+
end
|
45
|
+
|
46
|
+
['32', '64', 'xxh3-64', 'xxh3-128'].map do |algo|
|
47
|
+
[
|
48
|
+
[algo, 'null', 0],
|
49
|
+
[algo, '0x00_to_0xff', 17 ** 0],
|
50
|
+
[algo, '0x00_to_0xff', 17 ** 1],
|
51
|
+
[algo, '0x00_to_0xff', 17 ** 2],
|
52
|
+
[algo, '0x00_to_0xff', 17 ** 3],
|
53
|
+
[algo, '0x00_to_0xff', 17 ** 4],
|
54
|
+
[algo, '0x00_to_0xff', 17 ** 5]
|
55
|
+
]
|
56
|
+
end.flatten(1).each do |algo, msg_method, msg_length|
|
57
|
+
case msg_method
|
58
|
+
when 'null'
|
59
|
+
msg = ''
|
60
|
+
when '0x00_to_0xff'
|
61
|
+
msg = get_repeated_0x00_to_0xff(msg_length)
|
62
|
+
else
|
63
|
+
raise "Invalid message generation method."
|
64
|
+
end
|
65
|
+
|
66
|
+
case algo
|
67
|
+
when '32'
|
68
|
+
["00000000"].concat(_32bit_seeds_cycles.next).each do |seed|
|
69
|
+
produce_vectors(algo, 0, :seed, seed, msg, msg_method)
|
70
|
+
end
|
71
|
+
when '64'
|
72
|
+
["0000000000000000"].concat(_64bit_seeds).each do |seed|
|
73
|
+
produce_vectors(algo, 1, :seed, seed, msg, msg_method)
|
74
|
+
end
|
75
|
+
when 'xxh3-64'
|
76
|
+
["0000000000000000"].concat(_64bit_seeds).each do |seed|
|
77
|
+
produce_vectors(algo, 3, :seed, seed, msg, msg_method)
|
78
|
+
end
|
79
|
+
when 'xxh3-128'
|
80
|
+
["0000000000000000"].concat(_64bit_seeds).each do |seed|
|
81
|
+
produce_vectors(algo, 2, :seed, seed, msg, msg_method)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
['xxh3-64', 'xxh3-128'].map do |algo|
|
87
|
+
[
|
88
|
+
[algo, 'null', 0],
|
89
|
+
[algo, '0x00_to_0xff', 17 ** 0],
|
90
|
+
[algo, '0x00_to_0xff', 17 ** 5]
|
91
|
+
]
|
92
|
+
end.flatten(1).each do |algo, msg_method, msg_length|
|
93
|
+
case msg_method
|
94
|
+
when 'null'
|
95
|
+
msg = ''
|
96
|
+
when '0x00_to_0xff'
|
97
|
+
msg = get_repeated_0x00_to_0xff(msg_length)
|
98
|
+
else
|
99
|
+
raise "Invalid message generation method."
|
100
|
+
end
|
101
|
+
|
102
|
+
case algo
|
103
|
+
when 'xxh3-64'
|
104
|
+
_secrets.each do |secret|
|
105
|
+
produce_vectors(algo, 3, :secret, secret, msg, msg_method)
|
106
|
+
end
|
107
|
+
when 'xxh3-128'
|
108
|
+
_secrets.each do |secret|
|
109
|
+
produce_vectors(algo, 2, :secret, secret, msg, msg_method)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
data/test/test.rb
CHANGED
@@ -17,47 +17,47 @@ def get_repeated_0x00_to_0xff(length)
|
|
17
17
|
[str].cycle(cycles).to_a.join[0...length]
|
18
18
|
end
|
19
19
|
|
20
|
-
[Digest::XXH32, Digest::XXH64].each do |klass|
|
20
|
+
[Digest::XXH32, Digest::XXH64, Digest::XXH3_64bits, Digest::XXH3_128bits].each do |klass|
|
21
21
|
describe klass do
|
22
22
|
it "produces correct types of digest outputs" do
|
23
|
-
klass.digest("").must_be_instance_of String
|
24
|
-
klass.hexdigest("").must_be_instance_of String
|
25
|
-
klass.idigest("").must_be_kind_of Integer
|
26
|
-
klass.new.digest("").must_be_instance_of String
|
27
|
-
klass.new.hexdigest("").must_be_instance_of String
|
28
|
-
klass.new.idigest("").must_be_kind_of Integer
|
23
|
+
_(klass.digest("")).must_be_instance_of String
|
24
|
+
_(klass.hexdigest("")).must_be_instance_of String
|
25
|
+
_(klass.idigest("")).must_be_kind_of Integer
|
26
|
+
_(klass.new.digest("")).must_be_instance_of String
|
27
|
+
_(klass.new.hexdigest("")).must_be_instance_of String
|
28
|
+
_(klass.new.idigest("")).must_be_kind_of Integer
|
29
29
|
end
|
30
30
|
|
31
31
|
it "produces similar output with its digest, hexdigest and idigest methods" do
|
32
32
|
digest = klass.digest("abcd")
|
33
|
-
klass.new.digest("abcd").must_equal digest
|
34
|
-
klass.new.update("ab").update("cd").digest.must_equal digest
|
35
|
-
klass.new.update("ab").update("cd").digest
|
36
|
-
klass.new.reset.update("ab").update("cd").digest
|
33
|
+
_(klass.new.digest("abcd")).must_equal digest
|
34
|
+
_(klass.new.update("ab").update("cd").digest).must_equal digest
|
35
|
+
_(klass.new.update("ab").update("cd").digest!).must_equal digest
|
36
|
+
_(klass.new.reset.update("ab").update("cd").digest!).must_equal digest
|
37
37
|
|
38
38
|
hexdigest = klass.hexdigest("abcd")
|
39
|
-
klass.new.hexdigest("abcd").must_equal hexdigest
|
40
|
-
klass.new.update("ab").update("cd").hexdigest.must_equal hexdigest
|
41
|
-
klass.new.update("ab").update("cd").hexdigest
|
42
|
-
klass.new.reset.update("ab").update("cd").hexdigest
|
39
|
+
_(klass.new.hexdigest("abcd")).must_equal hexdigest
|
40
|
+
_(klass.new.update("ab").update("cd").hexdigest).must_equal hexdigest
|
41
|
+
_(klass.new.update("ab").update("cd").hexdigest!).must_equal hexdigest
|
42
|
+
_(klass.new.reset.update("ab").update("cd").hexdigest!).must_equal hexdigest
|
43
43
|
|
44
44
|
idigest = klass.idigest("abcd")
|
45
|
-
klass.new.idigest("abcd").must_equal idigest
|
46
|
-
klass.new.update("ab").update("cd").idigest.must_equal idigest
|
47
|
-
klass.new.update("ab").update("cd").idigest
|
48
|
-
klass.new.reset.update("ab").update("cd").idigest
|
45
|
+
_(klass.new.idigest("abcd")).must_equal idigest
|
46
|
+
_(klass.new.update("ab").update("cd").idigest).must_equal idigest
|
47
|
+
_(klass.new.update("ab").update("cd").idigest!).must_equal idigest
|
48
|
+
_(klass.new.reset.update("ab").update("cd").idigest!).must_equal idigest
|
49
49
|
|
50
|
-
|
51
|
-
hexdigest.must_equal
|
50
|
+
digest_hex = digest.unpack('H*').pop
|
51
|
+
_(hexdigest).must_equal digest_hex
|
52
52
|
|
53
|
-
|
54
|
-
hexdigest.must_equal
|
53
|
+
idigest_hex = "%08x" % idigest
|
54
|
+
_(hexdigest).must_equal idigest_hex
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
59
|
CSV.foreach(File.join(TEST_DIR, 'test.vectors'), col_sep: '|').with_index(1) do |csv, line_num|
|
60
|
-
|
60
|
+
algo, msg_method, msg_length, seed_type, seed_or_secret, sum = csv
|
61
61
|
|
62
62
|
case msg_method
|
63
63
|
when 'null'
|
@@ -65,23 +65,54 @@ CSV.foreach(File.join(TEST_DIR, 'test.vectors'), col_sep: '|').with_index(1) do
|
|
65
65
|
when '0x00_to_0xff'
|
66
66
|
msg = get_repeated_0x00_to_0xff(msg_length.to_i)
|
67
67
|
else
|
68
|
-
raise "Invalid
|
68
|
+
raise "Invalid message generation method specified in test.vectors:#{line_num}: #{msg_method}"
|
69
69
|
end
|
70
70
|
|
71
|
-
case
|
72
|
-
when 32
|
71
|
+
case algo
|
72
|
+
when '32'
|
73
73
|
klass = Digest::XXH32
|
74
|
-
when 64
|
74
|
+
when '64'
|
75
75
|
klass = Digest::XXH64
|
76
|
+
when 'xxh3-64'
|
77
|
+
klass = Digest::XXH3_64bits
|
78
|
+
when 'xxh3-128'
|
79
|
+
klass = Digest::XXH3_128bits
|
76
80
|
else
|
77
|
-
raise "Invalid specified
|
81
|
+
raise "Invalid algorithm specified in test.vectors:#{line_num}: #{algo}"
|
78
82
|
end
|
79
83
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
+
case seed_type
|
85
|
+
when 'seed'
|
86
|
+
describe klass do
|
87
|
+
describe "using #{msg_method}(#{msg_length}) as message generator, and #{seed_or_secret} as seed" do
|
88
|
+
it "should produce #{sum}" do
|
89
|
+
_(klass.hexdigest(msg, seed_or_secret)).must_equal sum
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
when 'secret'
|
94
|
+
describe klass do
|
95
|
+
describe "using #{msg_method}(#{msg_length}) as message generator, and #{seed_or_secret} as secret" do
|
96
|
+
it "should produce #{sum}" do
|
97
|
+
secret_str = [seed_or_secret].pack('H*')
|
98
|
+
_(klass.new.reset_with_secret(secret_str).update(msg).hexdigest).must_equal sum
|
99
|
+
end
|
84
100
|
end
|
85
101
|
end
|
102
|
+
else
|
103
|
+
raise "Invalid seed type specified in test.vectors:#{line_num}: #{seed_type}"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe Digest::XXHash::XXH3_SECRET_SIZE_MIN do
|
108
|
+
it "should be 136" do
|
109
|
+
# Documentation should be updated to reflect the new value if this fails.
|
110
|
+
_(Digest::XXHash::XXH3_SECRET_SIZE_MIN).must_equal 136
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe Digest::XXHash do
|
115
|
+
it "must have VERSION constant" do
|
116
|
+
_(Digest::XXHash.constants).must_include :VERSION
|
86
117
|
end
|
87
118
|
end
|