1 /* Invisible Vector Library
2 * coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
3 * Understanding is not required. Only obedience.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3 of the License ONLY.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 module iv
.hash
.rg32
/*is aliced*/;
18 // RadioGatun[32] hash function, based on the code by Sam Trenholme
21 /// RadioGatun[32] hash function
22 public struct RG32Hash
{
24 enum ByteSize
= 32; // 32 bytes (aka 256 bits, if you cannot do the math)
34 nothrow @trusted @nogc:
36 void reset () pure { buf
[] = 0; a
[] = 0; b
[] = 0; bufused
= 0; o
= 0; hasdata
= 0; }
38 /// process data block
39 void put(T
) (scope const(T
)[] data
...) if (T
.sizeof
== 1) {
40 if (data
.length
== 0) return; // nothing to do
42 auto bytes
= cast(const(ubyte)*)data
.ptr
;
43 auto len
= data
.length
;
45 while (bufused
< 12 && len
> 0) {
46 buf
.ptr
[bufused
++] = *bytes
++;
49 if (bufused
== 12) { processBuf(); bufused
= 0; }
53 /// finalize a hash (i.e. return current result).
54 /// note that you can continue putting data, as this is not destructive
55 ubyte[ByteSize
] finish () {
56 if (!hasdata || bufused
) processBuf();
58 foreach (immutable uint c
; 0..16) {
59 rground(a
.ptr
, b
.ptr
, o
);
63 ubyte[ByteSize
] res
= void;
66 foreach (immutable uint c
; 0..4) {
67 rground(a
.ptr
, b
.ptr
, o
);
70 assert(respos
< ByteSize
&& ByteSize
-respos
>= 8);
71 res
.ptr
[respos
++] = a
.ptr
[1]&0xff;
72 res
.ptr
[respos
++] = (a
.ptr
[1]>>8)&0xff;
73 res
.ptr
[respos
++] = (a
.ptr
[1]>>16)&0xff;
74 res
.ptr
[respos
++] = (a
.ptr
[1]>>24)&0xff;
75 res
.ptr
[respos
++] = a
.ptr
[2]&0xff;
76 res
.ptr
[respos
++] = (a
.ptr
[2]>>8)&0xff;
77 res
.ptr
[respos
++] = (a
.ptr
[2]>>16)&0xff;
78 res
.ptr
[respos
++] = (a
.ptr
[2]>>24)&0xff;
86 if (bufused
== 0) return;
90 foreach (immutable uint r
; 0..3) {
91 foreach (immutable uint q
; 0..4) {
92 uint x
= buf
.ptr
[offset
];
93 if (offset
>= bufused
) {
95 /* Spec says this should have a value
96 * of 0x80; reference code gives this
97 * a value of 1. This is IMHO a bug
98 * in the reference code. */
102 p
.ptr
[r
] |
= x
<<(q
*8);
104 foreach (immutable uint c
; 0..3) {
107 b
.ptr
[w
+c
*13] ^
= p
.ptr
[c
];
108 a
.ptr
[16+c
] ^
= p
.ptr
[c
];
110 rground(a
.ptr
, b
.ptr
, o
);
117 foreach (immutable uint c
; 0..3) {
120 b
.ptr
[w
+c
*13] ^
= p
.ptr
[c
];
121 a
.ptr
[16+c
] ^
= p
.ptr
[c
];
123 rground(a
.ptr
, b
.ptr
, o
);
129 void mill (uint* a
) {
132 // the following is the output of the awk script "make.mill.core"
133 x
= a
[0]^
(a
[1]|
(~a
[2]));
135 x
= a
[7]^
(a
[8]|
(~a
[9]));
136 A
.ptr
[1] = (x
>>1)|
(x
<<31);
137 x
= a
[14]^
(a
[15]|
(~a
[16]));
138 A
.ptr
[2] = (x
>>3)|
(x
<<29);
139 x
= a
[2]^
(a
[3]|
(~a
[4]));
140 A
.ptr
[3] = (x
>>6)|
(x
<<26);
141 x
= a
[9]^
(a
[10]|
(~a
[11]));
142 A
.ptr
[4] = (x
>>10)|
(x
<<22);
143 x
= a
[16]^
(a
[17]|
(~a
[18]));
144 A
.ptr
[5] = (x
>>15)|
(x
<<17);
145 x
= a
[4]^
(a
[5]|
(~a
[6]));
146 A
.ptr
[6] = (x
>>21)|
(x
<<11);
147 x
= a
[11]^
(a
[12]|
(~a
[13]));
148 A
.ptr
[7] = (x
>>28)|
(x
<<4);
149 x
= a
[18]^
(a
[0]|
(~a
[1]));
150 A
.ptr
[8] = (x
>>4)|
(x
<<28);
151 x
= a
[6]^
(a
[7]|
(~a
[8]));
152 A
.ptr
[9] = (x
>>13)|
(x
<<19);
153 x
= a
[13]^
(a
[14]|
(~a
[15]));
154 A
.ptr
[10] = (x
>>23)|
(x
<<9);
155 x
= a
[1]^
(a
[2]|
(~a
[3]));
156 A
.ptr
[11] = (x
>>2)|
(x
<<30);
157 x
= a
[8]^
(a
[9]|
(~a
[10]));
158 A
.ptr
[12] = (x
>>14)|
(x
<<18);
159 x
= a
[15]^
(a
[16]|
(~a
[17]));
160 A
.ptr
[13] = (x
>>27)|
(x
<<5);
161 x
= a
[3]^
(a
[4]|
(~a
[5]));
162 A
.ptr
[14] = (x
>>9)|
(x
<<23);
163 x
= a
[10]^
(a
[11]|
(~a
[12]));
164 A
.ptr
[15] = (x
>>24)|
(x
<<8);
165 x
= a
[17]^
(a
[18]|
(~a
[0]));
166 A
.ptr
[16] = (x
>>8)|
(x
<<24);
167 x
= a
[5]^
(a
[6]|
(~a
[7]));
168 A
.ptr
[17] = (x
>>25)|
(x
<<7);
169 x
= a
[12]^
(a
[13]|
(~a
[14]));
170 A
.ptr
[18] = (x
>>11)|
(x
<<21);
171 a
[0] = A
.ptr
[0]^A
.ptr
[1]^A
.ptr
[4];
172 a
[1] = A
.ptr
[1]^A
.ptr
[2]^A
.ptr
[5];
173 a
[2] = A
.ptr
[2]^A
.ptr
[3]^A
.ptr
[6];
174 a
[3] = A
.ptr
[3]^A
.ptr
[4]^A
.ptr
[7];
175 a
[4] = A
.ptr
[4]^A
.ptr
[5]^A
.ptr
[8];
176 a
[5] = A
.ptr
[5]^A
.ptr
[6]^A
.ptr
[9];
177 a
[6] = A
.ptr
[6]^A
.ptr
[7]^A
.ptr
[10];
178 a
[7] = A
.ptr
[7]^A
.ptr
[8]^A
.ptr
[11];
179 a
[8] = A
.ptr
[8]^A
.ptr
[9]^A
.ptr
[12];
180 a
[9] = A
.ptr
[9]^A
.ptr
[10]^A
.ptr
[13];
181 a
[10] = A
.ptr
[10]^A
.ptr
[11]^A
.ptr
[14];
182 a
[11] = A
.ptr
[11]^A
.ptr
[12]^A
.ptr
[15];
183 a
[12] = A
.ptr
[12]^A
.ptr
[13]^A
.ptr
[16];
184 a
[13] = A
.ptr
[13]^A
.ptr
[14]^A
.ptr
[17];
185 a
[14] = A
.ptr
[14]^A
.ptr
[15]^A
.ptr
[18];
186 a
[15] = A
.ptr
[15]^A
.ptr
[16]^A
.ptr
[0];
187 a
[16] = A
.ptr
[16]^A
.ptr
[17]^A
.ptr
[1];
188 a
[17] = A
.ptr
[17]^A
.ptr
[18]^A
.ptr
[2];
189 a
[18] = A
.ptr
[18]^A
.ptr
[0]^A
.ptr
[3];
193 // the following is the output of "make.belt.core"
194 void belt_00 (uint* a
, uint *b
) {
216 void belt_01 (uint* a
, uint* b
) {
238 void belt_02 (uint* a
, uint* b
) {
260 void belt_03 (uint* a
, uint* b
) {
282 void belt_04 (uint* a
, uint* b
) {
304 void belt_05 (uint* a
, uint* b
) {
326 void belt_06 (uint* a
, uint* b
) {
348 void belt_07 (uint* a
, uint* b
) {
370 void belt_08 (uint* a
, uint* b
) {
392 void belt_09 (uint* a
, uint* b
) {
414 void belt_10 (uint* a
, uint* b
) {
436 void belt_11 (uint* a
, uint* b
) {
458 void belt_12 (uint* a
, uint* b
) {
480 void rground (uint* a
, uint* b
, int offset
) {
481 final switch (offset
) {
482 case 0: belt_00(a
, b
); return;
483 case 1: belt_01(a
, b
); return;
484 case 2: belt_02(a
, b
); return;
485 case 3: belt_03(a
, b
); return;
486 case 4: belt_04(a
, b
); return;
487 case 5: belt_05(a
, b
); return;
488 case 6: belt_06(a
, b
); return;
489 case 7: belt_07(a
, b
); return;
490 case 8: belt_08(a
, b
); return;
491 case 9: belt_09(a
, b
); return;
492 case 10: belt_10(a
, b
); return;
493 case 11: belt_11(a
, b
); return;
494 case 12: belt_12(a
, b
); return;
500 ubyte[RG32Hash
.ByteSize
] RG32HashOf(T
) (const(T
)[] data
) nothrow @trusted @nogc if (T
.sizeof
== 1) {
507 ubyte[RG32Hash
.ByteSize
] RG32HashOf(T
) (const(T
)[] data
) nothrow @trusted @nogc if (T
.sizeof
> 1) {
509 h
.put((cast(const(ubyte)*)data
.ptr
)[0..data
.length
*T
.sizeof
]);
515 enum xhash
= RG32HashOf("Alice & Miriel");
516 static assert(cast(string
)xhash
== x
"ebcd82ad5b21cc5ac6ca1f707faad10fe047963aa9e5cb35150a8bf2120bee4a");
520 version(rg32_test
) void main () {
521 static immutable string xres
= x
"ebcd82ad5b21cc5ac6ca1f707faad10fe047963aa9e5cb35150a8bf2120bee4a";
522 auto hash
= RG32HashOf("Alice & Miriel");
523 { import core
.stdc
.stdio
; foreach (ubyte b
; hash
[]) printf("%02x", b
); printf("\n"); }
524 assert(hash
[] == cast(const(ubyte)[])xres
);