4
4
// / Authors: $(LINK2 github.com/dd86k, dd86k)
5
5
module blake2d ;
6
6
7
- public enum BLAKE2D_VERSION_STRING = " 0.1 .0" ;
7
+ public enum BLAKE2D_VERSION_STRING = " 0.2 .0" ;
8
8
9
9
private import std.digest ;
10
10
private import core.bitop : ror, bswap;
@@ -65,10 +65,7 @@ enum BLAKE2Variant {
65
65
// key = HMAC key. This is a temporary hack to allow HMAC usage.
66
66
struct BLAKE2 (BLAKE2Variant var, uint digestSize/* , const(ubyte )[] key = null*/)
67
67
{
68
- @safe :
69
- @nogc :
70
- nothrow :
71
- pure :
68
+ @safe : @nogc : nothrow : pure :
72
69
73
70
static assert (digestSize > 0 ,
74
71
" Digest size must be non-zero." );
@@ -80,8 +77,9 @@ struct BLAKE2(BLAKE2Variant var, uint digestSize/*, const(ubyte)[] key = null*/)
80
77
static assert (digestSize >= 8 && digestSize <= 512 ,
81
78
" BLAKE2b digest size must be between 8 and 512 bits." );
82
79
80
+ private enum MAXKEYSIZE = 32 ; // In bytes
83
81
private enum MAXED = digestSize == 512 ;
84
- private enum BSIZE = 128 ; // / bb
82
+ private enum BSIZE = 128 ; // / Buffer size, "bb" variable
85
83
private enum ROUNDS = 12 ;
86
84
private enum R1 = 32 ;
87
85
private enum R2 = 24 ;
@@ -94,8 +92,9 @@ struct BLAKE2(BLAKE2Variant var, uint digestSize/*, const(ubyte)[] key = null*/)
94
92
static assert (digestSize >= 8 && digestSize <= 256 ,
95
93
" BLAKE2s digest size must be between 8 and 256 bits." );
96
94
95
+ private enum MAXKEYSIZE = 32 ; // In bytes
97
96
private enum MAXED = digestSize == 256 ;
98
- private enum BSIZE = 64 ; // / bb
97
+ private enum BSIZE = 64 ; // / Buffer size, "bb" variable
99
98
private enum ROUNDS = 10 ;
100
99
private enum R1 = 16 ;
101
100
private enum R2 = 12 ;
@@ -113,6 +112,20 @@ struct BLAKE2(BLAKE2Variant var, uint digestSize/*, const(ubyte)[] key = null*/)
113
112
this = typeof (this ).init;
114
113
}
115
114
115
+ // / Initiates a key with digest.
116
+ // / This is meant to be used after the digest initiation.
117
+ // / The key limit is 64 bytes for BLAKE2b and 32 bytes for
118
+ // / BLAKE2s. If the limit is reached, it fails silenty by truncating
119
+ // / key data.
120
+ // / Params: input = Key.
121
+ void key (scope const (ubyte )[] input)
122
+ {
123
+ enum MASK = BSIZE - 1 ;
124
+ h[0 ] ^= ((input.length & MASK ) << 8 );
125
+ put(input.length > BSIZE ? input[0 .. BSIZE ] : input);
126
+ c = BSIZE ;
127
+ }
128
+
116
129
// / Feed the algorithm with data.
117
130
// / Also implements the $(REF isOutputRange, std,range,primitives)
118
131
// / interface for `ubyte` and `const(ubyte)[]`.
@@ -167,7 +180,7 @@ struct BLAKE2(BLAKE2Variant var, uint digestSize/*, const(ubyte)[] key = null*/)
167
180
// Clear out possible sensitive data
168
181
t[0 ] = t[1 ] = c = 0 ; // clear size information
169
182
mz[] = 0 ; // clear input message buffer
170
- // Only clear remaining of state if digest not at maximum .
183
+ // Only clear remaining of state if digest isn't fulled used .
171
184
// e.g., BLAKE2b-512 has a digest size of 64 bytes
172
185
// ulong[8] (8*8) is 64 bytes of state
173
186
// So is BLAKE2x-256 is used, a digest of 32 bytes
@@ -179,22 +192,13 @@ struct BLAKE2(BLAKE2Variant var, uint digestSize/*, const(ubyte)[] key = null*/)
179
192
}
180
193
181
194
private :
182
-
183
- /* static if (key)
184
- {
185
- enum KEYLEN = key.length;
186
- }
187
- else
188
- enum KEYLEN = 0;*/
189
-
190
- // public ubyte[32] key;
191
195
192
196
enum digestSizeBytes = digestSize / 8 ;
193
197
// 3 2 1 0
194
198
// p[0] = 0x0101kknn
195
199
// kk - Key size. Set to zero since HMAC is done elsewhere.
196
200
// nn - Digest size in bytes.
197
- enum p0 = 0x0101_0000 ^ ( 0 << 8 ) ^ digestSizeBytes;
201
+ enum p0 = 0x0101_0000 ^ digestSizeBytes;
198
202
enum msz = 16 * inner_t.sizeof; // / message size in bytes
199
203
enum hsz = 8 * inner_t.sizeof; // / state size in bytes
200
204
@@ -249,7 +253,7 @@ private:
249
253
v[14 ] = last ? ~ IV [6 ] : IV [6 ];
250
254
v[15 ] = IV [7 ];
251
255
252
- // See i=0 v[16]
256
+ // Assert i=0 v[16]
253
257
254
258
for (size_t round; round < ROUNDS ; ++ round)
255
259
{
@@ -263,7 +267,7 @@ private:
263
267
G(v, 2 , 7 , 8 , 13 , m[SIGMA [round][12 ]], m[SIGMA [round][13 ]]);
264
268
G(v, 3 , 4 , 9 , 14 , m[SIGMA [round][14 ]], m[SIGMA [round][15 ]]);
265
269
266
- // See i=1..i=10/12 v[16]
270
+ // Assert i=1..i=10/12 v[16]
267
271
}
268
272
269
273
h[0 ] ^= v[0 ] ^ v[8 ];
@@ -275,7 +279,7 @@ private:
275
279
h[6 ] ^= v[6 ] ^ v[14 ];
276
280
h[7 ] ^= v[7 ] ^ v[15 ];
277
281
278
- // See h[8]
282
+ // Assert h[8]
279
283
}
280
284
281
285
static void G (ref inner_t[16 ] v, uint a, uint b, uint c, uint d, inner_t x, inner_t y)
@@ -315,16 +319,20 @@ public alias BLAKE2s256Digest = WrapperDigest!BLAKE2s256;
315
319
assert (isDigest! BLAKE2s256);
316
320
}
317
321
322
+ // / Of course they have a blockSize!
323
+ @safe unittest
324
+ {
325
+ assert (hasBlockSize! BLAKE2b512);
326
+ assert (hasBlockSize! BLAKE2s256);
327
+ }
328
+
318
329
// / Testing "Of" wrappers against digest wrappers.
319
330
@safe unittest
320
331
{
321
332
enum TEXT = " abc" ;
322
333
323
- ubyte [64 ] b2b = blake2b_Of(TEXT );
324
- assert (b2b == digest! BLAKE2b512(TEXT ));
325
-
326
- ubyte [32 ] b2s = blake2s_Of(TEXT );
327
- assert (b2s == digest! BLAKE2s256(TEXT ));
334
+ assert (blake2b_Of(TEXT ) == digest! BLAKE2b512(TEXT ));
335
+ assert (blake2s_Of(TEXT ) == digest! BLAKE2s256(TEXT ));
328
336
}
329
337
330
338
// / Testing template API
@@ -388,13 +396,13 @@ public alias BLAKE2s256Digest = WrapperDigest!BLAKE2s256;
388
396
389
397
ubyte [] s = [' a' , ' b' , ' c' ];
390
398
391
- BLAKE2b512Digest b2b = new BLAKE2b512Digest();
399
+ Digest b2b = new BLAKE2b512Digest();
392
400
b2b.put(s);
393
401
assert (b2b.finish() == cast (ubyte []) hexString! (
394
402
" ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d1" ~
395
403
" 7d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923" ));
396
404
397
- BLAKE2s256Digest b2s = new BLAKE2s256Digest();
405
+ Digest b2s = new BLAKE2s256Digest();
398
406
b2s.put(s);
399
407
assert (b2s.finish() == cast (ubyte []) hexString! (
400
408
" 508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982" ));
@@ -425,28 +433,37 @@ public alias BLAKE2s256Digest = WrapperDigest!BLAKE2s256;
425
433
" 508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982" ));
426
434
}
427
435
428
- // / Testing with HMAC
429
- /* @system unittest
436
+ // / Keying digests
437
+ @system unittest
430
438
{
439
+ // NOTE: BLAKE2 is a keyed hash and therefore not compatible with
440
+ // the hmac/HMAC templates, or OpenSSL does it differently.
441
+
431
442
import std.ascii : LetterCase;
432
- import std.digest.hmac : hmac;
433
443
import std.string : representation;
444
+ import std.conv : hexString;
434
445
435
- auto secret = "secret".representation;
446
+ auto secret2b = hexString! (
447
+ " 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" ~
448
+ " 202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" )
449
+ .representation;
450
+ auto secret2s = hexString! (
451
+ " 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" )
452
+ .representation;
453
+ auto data = hexString! (" 000102" ).representation;
436
454
437
- // Temporary hack
438
- //alias HMACBLAKE2b512 = BLAKE2!(BLAKE2Variant.b, 512, "secret".representation);
439
- //alias HMACBLAKE2s256 = BLAKE2!(BLAKE2Variant.s, 256, "secret".representation);
440
-
441
- assert("The quick brown fox jumps over the lazy dog"
442
- .representation
443
- .hmac!BLAKE2b512(secret)
444
- .toHexString!(LetterCase.lower) ==
445
- "97504d0493aaaa40b08cf700fd380f17fe32e26e008fa20f9f3f04901d9f5bf3"~
446
- "3e826ea234f93bedfe7c5c50a540ad61454eb011581194cd68bff57938760ae0");
447
- assert("The quick brown fox jumps over the lazy dog"
448
- .representation
449
- .hmac!BLAKE2s256(secret)
450
- .toHexString!(LetterCase.lower) ==
451
- "e95b806f87e9477966cd5f0ca2d496bfdfa424c69e820d33e4f1007aeb6c9de1");
452
- }*/
455
+ BLAKE2b512 b2b;
456
+ b2b.key(secret2b);
457
+ b2b.put(data);
458
+ assert (b2b.finish().toHexString! (LetterCase.lower) ==
459
+ " 33d0825dddf7ada99b0e7e307104ad07ca9cfd9692214f1561356315e784f3e5" ~
460
+ " a17e364ae9dbb14cb2036df932b77f4b292761365fb328de7afdc6d8998f5fc1"
461
+ , " BLAKE2b+secret failed" );
462
+
463
+ BLAKE2s256 b2s;
464
+ b2s.key(secret2s);
465
+ b2s.put(data);
466
+ assert (b2s.finish().toHexString! (LetterCase.lower) ==
467
+ " 1d220dbe2ee134661fdf6d9e74b41704710556f2f6e5a091b227697445dbea6b"
468
+ , " BLAKE2s+secret failed" );
469
+ }
0 commit comments