digest-kangarootwelve 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d71e89ddf0629c43ac51a05492c19ae291007522
4
+ data.tar.gz: 605df33fb6c7b786262604f294aaae5269bc5ec9
5
+ SHA512:
6
+ metadata.gz: 1b7fc73a0210dbcc229a767daf6f90c4fefc269a608cc87001af9c59017732abac18c03d43c2e6588076aef3bac5f92d60ebb4e559ba3055c687269cf335803b
7
+ data.tar.gz: 4b488488ea6306425388fd69f6f9a56444feb584c86df1cea3d412746569f443cd88f32a37b02f43c23efccd7d71688a074575c4f7a56299a947e239bb72519e
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2017 konsolebox
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.
data/README.md ADDED
@@ -0,0 +1,84 @@
1
+ # digest-kangarootwelve-ruby
2
+
3
+ An implementation of KangarooTwelve for Ruby that works on top of Digest::Base.
4
+
5
+ It allows hashing with different digest lengths and different customization
6
+ strings.
7
+
8
+ See http://kangarootwelve.org/ to know more about the hashing algorithm.
9
+
10
+ The core implementation was extracted/generated from the KCP
11
+ (https://github.com/gvanas/KeccakCodePackage). The extension currently utilizes
12
+ the compact version, but I'll try to use a more optimized version in the future,
13
+ and also consider adding a capability to use an external library that can be
14
+ natively optimized (e.g. libkeccak.a), without compromisations.
15
+
16
+ ## Installation
17
+
18
+ Add this line to your application's Gemfile:
19
+
20
+ gem 'digest-kangarootwelve'
21
+
22
+ And then execute:
23
+
24
+ $ bundle
25
+
26
+ Or install it yourself as:
27
+
28
+ $ gem install digest-kangarootwelve
29
+
30
+ ## Example Usage
31
+
32
+ require 'digest/kangarootwelve'
33
+
34
+ klass = Digest::KangarooTwelve[32]
35
+ => Digest::KangarooTwelve_32
36
+
37
+ hash = klass.new
38
+ => #<Digest::KangarooTwelve_32|32|65536||1ac2d450fc3b4205d19da7bfca1b37513c0803577ac7167f06fe2ce1f0ef39e5>
39
+
40
+ hash.hexdigest("abc")
41
+ => "ab174f328c55a5510b0b209791bf8b60e801a7cfc2aa42042dcb8f547fbe3a7d"
42
+
43
+ Digest::KangarooTwelve[32].new.hexdigest("abc")
44
+ => "ab174f328c55a5510b0b209791bf8b60e801a7cfc2aa42042dcb8f547fbe3a7d"
45
+
46
+ Digest::KangarooTwelve.default
47
+ => Digest::KangarooTwelve_64
48
+
49
+ Digest::KangarooTwelve.implement(digest_length: 32, customization: "secret")
50
+ => Digest::KangarooTwelve_32_65536_736563726574
51
+
52
+ Digest::KangarooTwelve.implement(name: "SecretHash", digest_length: 32, customization: "secret")
53
+ => Digest::SecretHash
54
+
55
+ Digest::KangarooTwelve.implement(n: "SecretHash", d: 32, c: "secret")
56
+ => Digest::SecretHash
57
+
58
+ Digest::SecretHash.new.hexdigest("abc")
59
+ => "dc1fd53f85402e2b34fa92bd87593dd9c3fe6cc49d9db6c05dc0cf26c6a7e03f"
60
+
61
+ Digest::KangarooTwelve.implement(name: nil, digest_length: 48)
62
+ => #<Class:0x000000015fe8e8>
63
+
64
+ ## Details
65
+
66
+ For details on how to use the methods, please examine the comments in
67
+ `ext/digest/kangarootwelve/ext.c`, or try to run
68
+ `ri 'Digest::KangarooTwelve'` or
69
+ `ri 'Digest::KangarooTwelve::<method_name>'`. I'll try to provide a more
70
+ readable format of the documentation for the API soon.
71
+
72
+ You can use the implementation classes produced by `[]`, `default` or
73
+ `implement`, just like any other implementation class in `Digest`
74
+ (e.g. `Digest::SHA1`, `Digest::SHA512`), since they are also derived from
75
+ `Digest::Base`, and are programmed to work the way an implementation class
76
+ that's based on the `Digest` framework should.
77
+
78
+ ## Contributing
79
+
80
+ 1. Fork it ( https://github.com/konsolebox/digest-kangarootwelve-ruby/fork ).
81
+ 2. Create your feature branch (`git checkout -b my-new-feature`).
82
+ 3. Commit your changes (`git commit -am 'Add some feature'`).
83
+ 4. Push to the branch (`git push origin my-new-feature`).
84
+ 5. Create a new Pull Request.
data/Rakefile ADDED
@@ -0,0 +1,20 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ # clean, clobber, compile, and compile:digest/kangarootwelve
5
+ require 'rake/extensiontask'
6
+ Rake::ExtensionTask.new('digest/kangarootwelve', Bundler::GemHelper.gemspec)
7
+
8
+ # test
9
+ Rake::TestTask.new(:test => :compile) do |t|
10
+ t.test_files = FileList['test/test.rb']
11
+ t.verbose = true
12
+ end
13
+
14
+ # clean
15
+ task :clean do
16
+ list = FileList.new('test/*.tmp', 'test/*.temp')
17
+ rm_f list unless list.empty?
18
+ end
19
+
20
+ # Run `rake --tasks` for a list of tasks.
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'digest/kangarootwelve/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "digest-kangarootwelve"
9
+ spec.version = Digest::KangarooTwelve::VERSION
10
+ spec.authors = ["konsolebox"]
11
+ spec.email = ["konsolebox@gmail.com"]
12
+ spec.summary = "KangarooTwelve for Ruby"
13
+ spec.description = "An implementation of KangarooTwelve for Ruby that works on top of Digest::Base."
14
+ spec.homepage = "https://github.com/konsolebox/digest-kangaootwelve-ruby"
15
+ spec.license = "MIT"
16
+
17
+ spec.required_ruby_version = '>= 2.2'
18
+
19
+ spec.files = `git ls-files -z`.split("\x0")
20
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
21
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "rake-compiler", "~> 1.0"
26
+ spec.add_development_dependency "minitest", "~> 5.8"
27
+
28
+ spec.extensions = %w[ext/digest/kangarootwelve/extconf.rb]
29
+ end
@@ -0,0 +1,275 @@
1
+ /*
2
+ Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
3
+ Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
4
+ denoted as "the implementer".
5
+
6
+ For more information, feedback or questions, please refer to our websites:
7
+ http://keccak.noekeon.org/
8
+ http://keyak.noekeon.org/
9
+ http://ketje.noekeon.org/
10
+
11
+ To the extent possible under law, the implementer has waived all copyright
12
+ and related or neighboring rights to the source code in this file.
13
+ http://creativecommons.org/publicdomain/zero/1.0/
14
+ */
15
+
16
+ #include <string.h>
17
+ #include "KangarooTwelve.h"
18
+ #ifndef KeccakP1600timesN_excluded
19
+ #include "KeccakP-1600-times2-SnP.h"
20
+ #include "KeccakP-1600-times4-SnP.h"
21
+ #include "KeccakP-1600-times8-SnP.h"
22
+ #endif
23
+
24
+ #define chunkSize 8192
25
+ #define laneSize 8
26
+ #define suffixLeaf 0x0B /* '110': message hop, simple padding, inner node */
27
+
28
+ #define security 128
29
+ #define capacity (2*security)
30
+ #define capacityInBytes (capacity/8)
31
+ #define capacityInLanes (capacityInBytes/laneSize)
32
+ #define rate (1600-capacity)
33
+ #define rateInBytes (rate/8)
34
+ #define rateInLanes (rateInBytes/laneSize)
35
+
36
+ #define ParallelSpongeFastLoop( Parallellism ) \
37
+ while ( inLen >= Parallellism * chunkSize ) { \
38
+ ALIGN(KeccakP1600times##Parallellism##_statesAlignment) unsigned char states[KeccakP1600times##Parallellism##_statesSizeInBytes]; \
39
+ unsigned char intermediate[Parallellism*capacityInBytes]; \
40
+ unsigned int localBlockLen = chunkSize; \
41
+ const unsigned char * localInput = input; \
42
+ unsigned int i; \
43
+ unsigned int fastLoopOffset; \
44
+ \
45
+ KeccakP1600times##Parallellism##_StaticInitialize(); \
46
+ KeccakP1600times##Parallellism##_InitializeAll(states); \
47
+ fastLoopOffset = KeccakP1600times##Parallellism##_12rounds_FastLoop_Absorb(states, rateInLanes, chunkSize / laneSize, rateInLanes, localInput, Parallellism * chunkSize); \
48
+ localBlockLen -= fastLoopOffset; \
49
+ localInput += fastLoopOffset; \
50
+ for ( i = 0; i < Parallellism; ++i, localInput += chunkSize ) { \
51
+ KeccakP1600times##Parallellism##_AddBytes(states, i, localInput, 0, localBlockLen); \
52
+ KeccakP1600times##Parallellism##_AddByte(states, i, suffixLeaf, localBlockLen); \
53
+ KeccakP1600times##Parallellism##_AddByte(states, i, 0x80, rateInBytes-1); \
54
+ } \
55
+ KeccakP1600times##Parallellism##_PermuteAll_12rounds(states); \
56
+ input += Parallellism * chunkSize; \
57
+ inLen -= Parallellism * chunkSize; \
58
+ ktInstance->blockNumber += Parallellism; \
59
+ KeccakP1600times##Parallellism##_ExtractLanesAll(states, intermediate, capacityInLanes, capacityInLanes ); \
60
+ if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->finalNode, intermediate, Parallellism * capacityInBytes) != 0) return 1; \
61
+ }
62
+
63
+ #define ParallelSpongeLoop( Parallellism ) \
64
+ while ( inLen >= Parallellism * chunkSize ) { \
65
+ ALIGN(KeccakP1600times##Parallellism##_statesAlignment) unsigned char states[KeccakP1600times##Parallellism##_statesSizeInBytes]; \
66
+ unsigned char intermediate[Parallellism*capacityInBytes]; \
67
+ unsigned int localBlockLen = chunkSize; \
68
+ const unsigned char * localInput = input; \
69
+ unsigned int i; \
70
+ \
71
+ KeccakP1600times##Parallellism##_StaticInitialize(); \
72
+ KeccakP1600times##Parallellism##_InitializeAll(states); \
73
+ while(localBlockLen >= rateInBytes) { \
74
+ KeccakP1600times##Parallellism##_AddLanesAll(states, localInput, rateInLanes, chunkSize / laneSize); \
75
+ KeccakP1600times##Parallellism##_PermuteAll_12rounds(states); \
76
+ localBlockLen -= rateInBytes; \
77
+ localInput += rateInBytes; \
78
+ } \
79
+ for ( i = 0; i < Parallellism; ++i, localInput += chunkSize ) { \
80
+ KeccakP1600times##Parallellism##_AddBytes(states, i, localInput, 0, localBlockLen); \
81
+ KeccakP1600times##Parallellism##_AddByte(states, i, suffixLeaf, localBlockLen); \
82
+ KeccakP1600times##Parallellism##_AddByte(states, i, 0x80, rateInBytes-1); \
83
+ } \
84
+ KeccakP1600times##Parallellism##_PermuteAll_12rounds(states); \
85
+ input += Parallellism * chunkSize; \
86
+ inLen -= Parallellism * chunkSize; \
87
+ ktInstance->blockNumber += Parallellism; \
88
+ KeccakP1600times##Parallellism##_ExtractLanesAll(states, intermediate, capacityInLanes, capacityInLanes ); \
89
+ if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->finalNode, intermediate, Parallellism * capacityInBytes) != 0) return 1; \
90
+ }
91
+
92
+ static unsigned int right_encode( unsigned char * encbuf, size_t value )
93
+ {
94
+ unsigned int n, i;
95
+ size_t v;
96
+
97
+ for ( v = value, n = 0; v && (n < sizeof(size_t)); ++n, v >>= 8 )
98
+ ; /* empty */
99
+ for ( i = 1; i <= n; ++i )
100
+ encbuf[i-1] = (unsigned char)(value >> (8 * (n-i)));
101
+ encbuf[n] = (unsigned char)n;
102
+ return n + 1;
103
+ }
104
+
105
+ int KangarooTwelve_Initialize(KangarooTwelve_Instance *ktInstance, size_t outputLen)
106
+ {
107
+ ktInstance->fixedOutputLength = outputLen;
108
+ ktInstance->queueAbsorbedLen = 0;
109
+ ktInstance->blockNumber = 0;
110
+ ktInstance->phase = ABSORBING;
111
+ return KeccakWidth1600_12rounds_SpongeInitialize(&ktInstance->finalNode, rate, capacity);
112
+ }
113
+
114
+ int KangarooTwelve_Update(KangarooTwelve_Instance *ktInstance, const unsigned char *input, size_t inLen)
115
+ {
116
+ if (ktInstance->phase != ABSORBING)
117
+ return 1;
118
+
119
+ if ( ktInstance->blockNumber == 0 ) {
120
+ /* First block, absorb in final node */
121
+ unsigned int len = (inLen < (chunkSize - ktInstance->queueAbsorbedLen)) ? inLen : (chunkSize - ktInstance->queueAbsorbedLen);
122
+ if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->finalNode, input, len) != 0)
123
+ return 1;
124
+ input += len;
125
+ inLen -= len;
126
+ ktInstance->queueAbsorbedLen += len;
127
+ if ( (ktInstance->queueAbsorbedLen == chunkSize) && (inLen != 0) ) {
128
+ /* First block complete and more input data available, finalize it */
129
+ const unsigned char padding = 0x03; /* '110^6': message hop, simple padding */
130
+ ktInstance->queueAbsorbedLen = 0;
131
+ ktInstance->blockNumber = 1;
132
+ if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->finalNode, &padding, 1) != 0)
133
+ return 1;
134
+ ktInstance->finalNode.byteIOIndex = (ktInstance->finalNode.byteIOIndex + 7) & ~7; /* Zero padding up to 64 bits */
135
+ }
136
+ }
137
+ else if ( ktInstance->queueAbsorbedLen != 0 ) {
138
+ /* There is data in the queue, absorb further in queue until block complete */
139
+ unsigned int len = (inLen < (chunkSize - ktInstance->queueAbsorbedLen)) ? inLen : (chunkSize - ktInstance->queueAbsorbedLen);
140
+ if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->queueNode, input, len) != 0)
141
+ return 1;
142
+ input += len;
143
+ inLen -= len;
144
+ ktInstance->queueAbsorbedLen += len;
145
+ if ( ktInstance->queueAbsorbedLen == chunkSize ) {
146
+ unsigned char intermediate[capacityInBytes];
147
+ ktInstance->queueAbsorbedLen = 0;
148
+ ++ktInstance->blockNumber;
149
+ if (KeccakWidth1600_12rounds_SpongeAbsorbLastFewBits(&ktInstance->queueNode, suffixLeaf) != 0)
150
+ return 1;
151
+ if (KeccakWidth1600_12rounds_SpongeSqueeze(&ktInstance->queueNode, intermediate, capacityInBytes) != 0)
152
+ return 1;
153
+ if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->finalNode, intermediate, capacityInBytes) != 0)
154
+ return 1;
155
+ }
156
+ }
157
+
158
+ #if defined(KeccakP1600times8_implementation)
159
+ #if defined(KeccakP1600times8_12rounds_FastLoop_supported)
160
+ ParallelSpongeFastLoop( 8 )
161
+ #else
162
+ ParallelSpongeLoop( 8 )
163
+ #endif
164
+ #endif
165
+
166
+ #if defined(KeccakP1600times4_implementation)
167
+ #if defined(KeccakP1600times4_12rounds_FastLoop_supported)
168
+ ParallelSpongeFastLoop( 4 )
169
+ #else
170
+ ParallelSpongeLoop( 4 )
171
+ #endif
172
+ #endif
173
+
174
+ #if defined(KeccakP1600times2_implementation)
175
+ #if defined(KeccakP1600times2_12rounds_FastLoop_supported)
176
+ ParallelSpongeFastLoop( 2 )
177
+ #else
178
+ ParallelSpongeLoop( 2 )
179
+ #endif
180
+ #endif
181
+
182
+ while ( inLen > 0 ) {
183
+ unsigned int len = (inLen < chunkSize) ? inLen : chunkSize;
184
+ if (KeccakWidth1600_12rounds_SpongeInitialize(&ktInstance->queueNode, rate, capacity) != 0)
185
+ return 1;
186
+ if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->queueNode, input, len) != 0)
187
+ return 1;
188
+ input += len;
189
+ inLen -= len;
190
+ if ( len == chunkSize ) {
191
+ unsigned char intermediate[capacityInBytes];
192
+ ++ktInstance->blockNumber;
193
+ if (KeccakWidth1600_12rounds_SpongeAbsorbLastFewBits(&ktInstance->queueNode, suffixLeaf) != 0)
194
+ return 1;
195
+ if (KeccakWidth1600_12rounds_SpongeSqueeze(&ktInstance->queueNode, intermediate, capacityInBytes) != 0)
196
+ return 1;
197
+ if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->finalNode, intermediate, capacityInBytes) != 0)
198
+ return 1;
199
+ }
200
+ else
201
+ ktInstance->queueAbsorbedLen = len;
202
+ }
203
+
204
+ return 0;
205
+ }
206
+
207
+ int KangarooTwelve_Final(KangarooTwelve_Instance *ktInstance, unsigned char * output, const unsigned char * customization, size_t customLen)
208
+ {
209
+ unsigned char encbuf[sizeof(size_t)+1+2];
210
+ unsigned char padding;
211
+
212
+ if (ktInstance->phase != ABSORBING)
213
+ return 1;
214
+
215
+ /* Absorb customization | right_encode(customLen) */
216
+ if ((customLen != 0) && (KangarooTwelve_Update(ktInstance, customization, customLen) != 0))
217
+ return 1;
218
+ if (KangarooTwelve_Update(ktInstance, encbuf, right_encode(encbuf, customLen)) != 0)
219
+ return 1;
220
+
221
+ if ( ktInstance->blockNumber == 0 ) {
222
+ /* Non complete first block in final node, pad it */
223
+ padding = 0x07; /* '11': message hop, final node */
224
+ }
225
+ else {
226
+ unsigned int n;
227
+
228
+ if ( ktInstance->queueAbsorbedLen != 0 ) {
229
+ /* There is data in the queue node */
230
+ unsigned char intermediate[capacityInBytes];
231
+ ++ktInstance->blockNumber;
232
+ if (KeccakWidth1600_12rounds_SpongeAbsorbLastFewBits(&ktInstance->queueNode, suffixLeaf) != 0)
233
+ return 1;
234
+ if (KeccakWidth1600_12rounds_SpongeSqueeze(&ktInstance->queueNode, intermediate, capacityInBytes) != 0)
235
+ return 1;
236
+ if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->finalNode, intermediate, capacityInBytes) != 0)
237
+ return 1;
238
+ }
239
+ --ktInstance->blockNumber; /* Absorb right_encode(number of Chaining Values) || 0xFF || 0xFF */
240
+ n = right_encode(encbuf, ktInstance->blockNumber);
241
+ encbuf[n++] = 0xFF;
242
+ encbuf[n++] = 0xFF;
243
+ if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->finalNode, encbuf, n) != 0)
244
+ return 1;
245
+ padding = 0x06; /* '01': chaining hop, final node */
246
+ }
247
+ if (KeccakWidth1600_12rounds_SpongeAbsorbLastFewBits(&ktInstance->finalNode, padding) != 0)
248
+ return 1;
249
+ if ( ktInstance->fixedOutputLength != 0 ) {
250
+ ktInstance->phase = FINAL;
251
+ return KeccakWidth1600_12rounds_SpongeSqueeze(&ktInstance->finalNode, output, ktInstance->fixedOutputLength);
252
+ }
253
+ ktInstance->phase = SQUEEZING;
254
+ return 0;
255
+ }
256
+
257
+ int KangarooTwelve_Squeeze(KangarooTwelve_Instance *ktInstance, unsigned char * output, size_t outputLen)
258
+ {
259
+ if (ktInstance->phase != SQUEEZING)
260
+ return 1;
261
+ return KeccakWidth1600_12rounds_SpongeSqueeze(&ktInstance->finalNode, output, outputLen);
262
+ }
263
+
264
+ int KangarooTwelve( const unsigned char * input, size_t inLen, unsigned char * output, size_t outLen, const unsigned char * customization, size_t customLen )
265
+ {
266
+ KangarooTwelve_Instance ktInstance;
267
+
268
+ if (outLen == 0)
269
+ return 1;
270
+ if (KangarooTwelve_Initialize(&ktInstance, outLen) != 0)
271
+ return 1;
272
+ if (KangarooTwelve_Update(&ktInstance, input, inLen) != 0)
273
+ return 1;
274
+ return KangarooTwelve_Final(&ktInstance, output, customization, customLen);
275
+ }