SHA-3

From CasperTech Wiki
Jump to navigation Jump to search

Here's an open source SHA-3 implementation in LSL.

It supports all three versions of the algorithm - SHA-3, Keccak, SHAKE.

Processing speed is roughly 100 characters per second.

  1 /////////////////////////////////////////////////////////////////////////////////
  2 //
  3 //      CasperTech SHA-3 implementation
  4 //
  5 //      Creative Commons Attribution 4.0 International https://creativecommons.org/licenses/by/4.0/
  6 //
  7 //      Based on js-sha3 https://github.com/emn178/js-sha3
  8 //
  9 ////////////////////////////////////////////////////////////////////////////////
 10 
 11 list HEX_CHARS = ["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"];
 12 list SHAKE_PADDING = [31, 7936, 2031616, 520093696];
 13 list KECCAK_PADDING = [1, 256, 65536, 16777216];
 14 list PADDING = [6, 1536, 393216, 100663296];
 15 list SHIFT = [0, 8, 16, 24];
 16 list RC = [1, 0, 32898, 0, 32906, 2147483648, 2147516416, 2147483648, 32907, 0, 2147483649,
 17             0, 2147516545, 2147483648, 32777, 2147483648, 138, 0, 136, 0, 2147516425, 0,
 18             2147483658, 0, 2147516555, 0, 139, 2147483648, 32905, 2147483648, 32771,
 19             2147483648, 32770, 2147483648, 128, 2147483648, 32778, 0, 2147483658, 2147483648,
 20             2147516545, 2147483648, 32896, 2147483648, 2147483649, 0, 2147516424, 2147483648];
 21             
 22 integer ALGORITHM_SHA3 = 0;
 23 integer ALGORITHM_KECCAK = 1;
 24 integer ALGORITHM_SHAKE = 2;
 25 
 26 integer UTF8ToUnicodeInteger(string input) //From http://wiki.secondlife.com/w/index.php?title=UTF-8 with thanks
 27 {
 28     integer result = llBase64ToInteger(llStringToBase64(input = llGetSubString(input,0,0)));
 29     if(result & 0x80000000)
 30     {
 31         integer end = (integer)("0x"+llGetSubString(input = (string)llParseString2List(llEscapeURL(input),(list)"%",[]),-8,-1));
 32         integer begin = (integer)("0x"+llDeleteSubString(input,-8,-1));
 33         return  (   (  0x0000003f &  end       ) |
 34                     (( 0x00003f00 &  end) >> 2 ) | 
 35                     (( 0x003f0000 &  end) >> 4 ) | 
 36                     (( 0x3f000000 &  end) >> 6 ) |
 37                     (( 0x0000003f &  begin) << 24) |
 38                     (( 0x00000100 &  begin) << 22)
 39                 ) & (0x7FFFFFFF >> (5 * ((integer)(llLog(~result) / 0.69314718055994530941723212145818) - 25)));
 40     }
 41     return result >> 24;
 42 }
 43 integer zeroFillRightShift(integer value, integer count) //From http://wiki.secondlife.com/wiki/Right_Shift with thanks
 44 {
 45     return ((value & 0x7fFFffFF) >> count) - ((value & 0x80000000) >> count);
 46 }
 47 list f(list s) 
 48 {
 49     integer h;
 50     integer l;
 51     integer n;
 52     integer c0;
 53     integer c1;
 54     integer c2;
 55     integer c3;
 56     integer c4;
 57     integer c5;
 58     integer c6;
 59     integer c7;
 60     integer c8;
 61     integer c9;
 62     integer b0;
 63     integer b1;
 64     integer b2;
 65     integer b3;
 66     integer b4;
 67     integer b5;
 68     integer b6;
 69     integer b7;
 70     integer b8;
 71     integer b9;
 72     integer b10;
 73     integer b11;
 74     integer b12;
 75     integer b13;
 76     integer b14;
 77     integer b15;
 78     integer b16;
 79     integer b17;
 80     integer b18;
 81     integer b19;
 82     integer b20;
 83     integer b21;
 84     integer b22;
 85     integer b23;
 86     integer b24;
 87     integer b25;
 88     integer b26;
 89     integer b27;
 90     integer b28;
 91     integer b29;
 92     integer b30;
 93     integer b31;
 94     integer b32;
 95     integer b33;
 96     integer b34;
 97     integer b35;
 98     integer b36;
 99     integer b37;
100     integer b38;
101     integer b39;
102     integer b40;
103     integer b41;
104     integer b42;
105     integer b43;
106     integer b44;
107     integer b45;
108     integer b46;
109     integer b47;
110     integer b48;
111     integer b49;
112     
113     integer s0 = llList2Integer(s,0);
114     integer s1 = llList2Integer(s,1);
115     integer s2 = llList2Integer(s,2);
116     integer s3 = llList2Integer(s,3);
117     integer s4 = llList2Integer(s,4);
118     integer s5 = llList2Integer(s,5);
119     integer s6 = llList2Integer(s,6);
120     integer s7 = llList2Integer(s,7);
121     integer s8 = llList2Integer(s,8);
122     integer s9 = llList2Integer(s,9);
123     integer s10 = llList2Integer(s,10);
124     integer s11 = llList2Integer(s,11);
125     integer s12 = llList2Integer(s,12);
126     integer s13 = llList2Integer(s,13);
127     integer s14 = llList2Integer(s,14);
128     integer s15 = llList2Integer(s,15);
129     integer s16 = llList2Integer(s,16);
130     integer s17 = llList2Integer(s,17);
131     integer s18 = llList2Integer(s,18);
132     integer s19 = llList2Integer(s,19);
133     integer s20 = llList2Integer(s,20);
134     integer s21 = llList2Integer(s,21);
135     integer s22 = llList2Integer(s,22);
136     integer s23 = llList2Integer(s,23);
137     integer s24 = llList2Integer(s,24);
138     integer s25 = llList2Integer(s,25);
139     integer s26 = llList2Integer(s,26);
140     integer s27 = llList2Integer(s,27);
141     integer s28 = llList2Integer(s,28);
142     integer s29 = llList2Integer(s,29);
143     integer s30 = llList2Integer(s,30);
144     integer s31 = llList2Integer(s,31);
145     integer s32 = llList2Integer(s,32);
146     integer s33 = llList2Integer(s,33);
147     integer s34 = llList2Integer(s,34);
148     integer s35 = llList2Integer(s,35);
149     integer s36 = llList2Integer(s,36);
150     integer s37 = llList2Integer(s,37);
151     integer s38 = llList2Integer(s,38);
152     integer s39 = llList2Integer(s,39);
153     integer s40 = llList2Integer(s,40);
154     integer s41 = llList2Integer(s,41);
155     integer s42 = llList2Integer(s,42);
156     integer s43 = llList2Integer(s,43);
157     integer s44 = llList2Integer(s,44);
158     integer s45 = llList2Integer(s,45);
159     integer s46 = llList2Integer(s,46);
160     integer s47 = llList2Integer(s,47);
161     integer s48 = llList2Integer(s,48);
162     integer s49 = llList2Integer(s,49);
163     
164         
165         
166     for (n = 0; n < 48; n += 2) 
167     {
168         c0 = s0 ^ s10 ^ s20 ^ s30 ^ s40;
169         c1 = s1 ^ s11 ^ s21 ^ s31 ^ s41;
170         c2 = s2 ^ s12 ^ s22 ^ s32 ^ s42;
171         c3 = s3 ^ s13 ^ s23 ^ s33 ^ s43;
172         c4 = s4 ^ s14 ^ s24 ^ s34 ^ s44;
173         c5 = s5 ^ s15 ^ s25 ^ s35 ^ s45;
174         c6 = s6 ^ s16 ^ s26 ^ s36 ^ s46;
175         c7 = s7 ^ s17 ^ s27 ^ s37 ^ s47;
176         c8 = s8 ^ s18 ^ s28 ^ s38 ^ s48;
177         c9 = s9 ^ s19 ^ s29 ^ s39 ^ s49;
178         
179         h = c8 ^ ((c2 << 1) | (zeroFillRightShift(c3,31)));
180         l = c9 ^ ((c3 << 1) | (zeroFillRightShift(c2,31)));
181         s0 = s0 ^ h;
182         s1 = s1 ^ l;
183         s10 = s10 ^ h;
184         s11 = s11 ^ l;
185         s20 = s20 ^ h;
186         s21 = s21 ^ l;
187         s30 = s30 ^ h;
188         s31 = s31 ^ l;
189         s40 = s40 ^ h;
190         s41 = s41 ^ l;
191         h = c0 ^ ((c4 << 1) | (zeroFillRightShift(c5,31)));
192         l = c1 ^ ((c5 << 1) | (zeroFillRightShift(c4,31)));
193         s2 = s2 ^ h;
194         s3 = s3 ^ l;
195         s12 = s12 ^ h;
196         s13 = s13 ^ l;
197         s22 = s22 ^ h;
198         s23 = s23 ^ l;
199         s32 = s32 ^ h;
200         s33 = s33 ^ l;
201         s42 = s42 ^ h;
202         s43 = s43 ^ l;
203         h = c2 ^ ((c6 << 1) | (zeroFillRightShift(c7,31)));
204         l = c3 ^ ((c7 << 1) | (zeroFillRightShift(c6,31)));
205         s4 = s4 ^ h;
206         s5 = s5 ^ l;
207         s14 = s14 ^ h;
208         s15 = s15 ^ l;
209         s24 = s24 ^ h;
210         s25 = s25 ^ l;
211         s34 = s34 ^ h;
212         s35 = s35 ^ l;
213         s44 = s44 ^ h;
214         s45 = s45 ^ l;
215         h = c4 ^ ((c8 << 1) | (zeroFillRightShift(c9,31)));
216         l = c5 ^ ((c9 << 1) | (zeroFillRightShift(c8,31)));
217         s6 = s6 ^ h;
218         s7 = s7 ^ l;
219         s16 = s16 ^ h;
220         s17 = s17 ^ l;
221         s26 = s26 ^ h;
222         s27 = s27 ^ l;
223         s36 = s36 ^ h;
224         s37 = s37 ^ l;
225         s46 = s46 ^ h;
226         s47 = s47 ^ l;
227         h = c6 ^ ((c0 << 1) | (zeroFillRightShift(c1,31)));
228         l = c7 ^ ((c1 << 1) | (zeroFillRightShift(c0,31)));
229         s8 = s8 ^ h;
230         s9 = s9 ^ l;
231         s18 = s18 ^ h;
232         s19 = s19 ^ l;
233         s28 = s28 ^ h;
234         s29 = s29 ^ l;
235         s38 = s38 ^ h;
236         s39 = s39 ^ l;
237         s48 = s48 ^ h;
238         s49 = s49 ^ l;
239         
240         b0 = s0;
241         b1 = s1;
242         b32 = (s11 << 4) | (zeroFillRightShift(s10,28));
243         b33 = (s10 << 4) | (zeroFillRightShift(s11,28));
244         b14 = (s20 << 3) | (zeroFillRightShift(s21,29));
245         b15 = (s21 << 3) | (zeroFillRightShift(s20,29));
246         b46 = (s31 << 9) | (zeroFillRightShift(s30,23));
247         b47 = (s30 << 9) | (zeroFillRightShift(s31,23));
248         b28 = (s40 << 18) | (zeroFillRightShift(s41,14));
249         b29 = (s41 << 18) | (zeroFillRightShift(s40,14));
250         b20 = (s2 << 1) | (zeroFillRightShift(s3,31));
251         b21 = (s3 << 1) | (zeroFillRightShift(s2,31));
252         b2 = (s13 << 12) | (zeroFillRightShift(s12,20));
253         b3 = (s12 << 12) | (zeroFillRightShift(s13,20));
254         b34 = (s22 << 10) | (zeroFillRightShift(s23,22));
255         b35 = (s23 << 10) | (zeroFillRightShift(s22,22));
256         b16 = (s33 << 13) | (zeroFillRightShift(s32,19));
257         b17 = (s32 << 13) | (zeroFillRightShift(s33,19));
258         b48 = (s42 << 2) | (zeroFillRightShift(s43,30));
259         b49 = (s43 << 2) | (zeroFillRightShift(s42,30));
260         b40 = (s5 << 30) | (zeroFillRightShift(s4,2));
261         b41 = (s4 << 30) | (zeroFillRightShift(s5,2));
262         b22 = (s14 << 6) | (zeroFillRightShift(s15,26));
263         b23 = (s15 << 6) | (zeroFillRightShift(s14,26));
264         b4 = (s25 << 11) | (zeroFillRightShift(s24,21));
265         b5 = (s24 << 11) | (zeroFillRightShift(s25,21));
266         b36 = (s34 << 15) | (zeroFillRightShift(s35,17));
267         b37 = (s35 << 15) | (zeroFillRightShift(s34,17));
268         b18 = (s45 << 29) | (zeroFillRightShift(s44,3));
269         b19 = (s44 << 29) | (zeroFillRightShift(s45,3));
270         b10 = (s6 << 28) | (zeroFillRightShift(s7,4));
271         b11 = (s7 << 28) | (zeroFillRightShift(s6,4));
272         b42 = (s17 << 23) | (zeroFillRightShift(s16,9));
273         b43 = (s16 << 23) | (zeroFillRightShift(s17,9));
274         b24 = (s26 << 25) | (zeroFillRightShift(s27,7));
275         b25 = (s27 << 25) | (zeroFillRightShift(s26,7));
276         b6 = (s36 << 21) | (zeroFillRightShift(s37,11));
277         b7 = (s37 << 21) | (zeroFillRightShift(s36,11));
278         b38 = (s47 << 24) | (zeroFillRightShift(s46,8));
279         b39 = (s46 << 24) | (zeroFillRightShift(s47,8));
280         b30 = (s8 << 27) | (zeroFillRightShift(s9,5));
281         b31 = (s9 << 27) | (zeroFillRightShift(s8,5));
282         b12 = (s18 << 20) | (zeroFillRightShift(s19,12));
283         b13 = (s19 << 20) | (zeroFillRightShift(s18,12));
284         b44 = (s29 << 7) | (zeroFillRightShift(s28,25));
285         b45 = (s28 << 7) | (zeroFillRightShift(s29,25));
286         b26 = (s38 << 8) | (zeroFillRightShift(s39,24));
287         b27 = (s39 << 8) | (zeroFillRightShift(s38,24));
288         b8 = (s48 << 14) | (zeroFillRightShift(s49,18));
289         b9 = (s49 << 14) | (zeroFillRightShift(s48,18));
290         
291         s0 = b0 ^ (~b2 & b4);
292         s1 = b1 ^ (~b3 & b5);
293         s10 = b10 ^ (~b12 & b14);
294         s11 = b11 ^ (~b13 & b15);
295         s20 = b20 ^ (~b22 & b24);
296         s21 = b21 ^ (~b23 & b25);
297         s30 = b30 ^ (~b32 & b34);
298         s31 = b31 ^ (~b33 & b35);
299         s40 = b40 ^ (~b42 & b44);
300         s41 = b41 ^ (~b43 & b45);
301         s2 = b2 ^ (~b4 & b6);
302         s3 = b3 ^ (~b5 & b7);
303         s12 = b12 ^ (~b14 & b16);
304         s13 = b13 ^ (~b15 & b17);
305         s22 = b22 ^ (~b24 & b26);
306         s23 = b23 ^ (~b25 & b27);
307         s32 = b32 ^ (~b34 & b36);
308         s33 = b33 ^ (~b35 & b37);
309         s42 = b42 ^ (~b44 & b46);
310         s43 = b43 ^ (~b45 & b47);
311         s4 = b4 ^ (~b6 & b8);
312         s5 = b5 ^ (~b7 & b9);
313         s14 = b14 ^ (~b16 & b18);
314         s15 = b15 ^ (~b17 & b19);
315         s24 = b24 ^ (~b26 & b28);
316         s25 = b25 ^ (~b27 & b29);
317         s34 = b34 ^ (~b36 & b38);
318         s35 = b35 ^ (~b37 & b39);
319         s44 = b44 ^ (~b46 & b48);
320         s45 = b45 ^ (~b47 & b49);
321         s6 = b6 ^ (~b8 & b0);
322         s7 = b7 ^ (~b9 & b1);
323         s16 = b16 ^ (~b18 & b10);
324         s17 = b17 ^ (~b19 & b11);
325         s26 = b26 ^ (~b28 & b20);
326         s27 = b27 ^ (~b29 & b21);
327         s36 = b36 ^ (~b38 & b30);
328         s37 = b37 ^ (~b39 & b31);
329         s46 = b46 ^ (~b48 & b40);
330         s47 = b47 ^ (~b49 & b41);
331         s8 = b8 ^ (~b0 & b2);
332         s9 = b9 ^ (~b1 & b3);
333         s18 = b18 ^ (~b10 & b12);
334         s19 = b19 ^ (~b11 & b13);
335         s28 = b28 ^ (~b20 & b22);
336         s29 = b29 ^ (~b21 & b23);
337         s38 = b38 ^ (~b30 & b32);
338         s39 = b39 ^ (~b31 & b33);
339         s48 = b48 ^ (~b40 & b42);
340         s49 = b49 ^ (~b41 & b43);
341         
342         s0 = s0 ^ llList2Integer(RC, n);
343         s1 = s1 ^ llList2Integer(RC, n + 1);
344     }
345     return [s0,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11,s12,s13,s14,s15,s16,s17,s18,s19,s20,s21,s22,s23,s24,s25,s26,s27,s28,s29,s30,s31,s32,s33,s34,s35,s36,s37,s38,s39,s40,s41,s42,s43,s44,s45,s46,s47,s48,s49];  
346 }
347 string Keccak(integer bits, list padding, integer outputBits, string message)
348 {
349     list blocks = [];
350     list s = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
351     integer block = 0;
352     integer start = 0;
353     integer blockCount = (1600 - (bits << 1)) >> 5;
354     
355     integer byteCount = blockCount << 2;
356     integer outputBlocks = outputBits >> 5;   
357     integer extraBytes = (outputBits & 31) >> 3;
358     integer length = llStringLength(message);
359     integer index = 0;
360     integer i;
361     integer code;
362     integer reset = FALSE;
363     integer lastByteIndex = 0;
364     
365     blocks = [0];
366     for(i = 0; i < blockCount + 1; ++i) 
367     {
368         blocks+=[0];
369     }
370     
371     
372     while(index < length)
373     {
374         if (reset == TRUE)
375         {
376             reset = FALSE;
377             blocks = [block];
378             for(i = 0; i < blockCount + 1; ++i) 
379             {
380                 blocks+=[0];
381             }
382         }
383         for(i = start; index < length && i < byteCount; ++index)
384         {
385             code = UTF8ToUnicodeInteger(llGetSubString(message, index, index));
386             integer blockNumber = llList2Integer(blocks, i >> 2);            
387             if (code < 0x80)
388             {
389                 blocks = llListReplaceList(blocks, [llList2Integer(blocks, i >> 2) | code << llList2Integer(SHIFT,i & 3)], i >> 2, i >> 2);
390                 i = i + 1;
391             } 
392             else if (code < 0x800) 
393             {
394                 blocks = llListReplaceList(blocks, [llList2Integer(blocks, i >> 2) |(0xc0 | (code >> 6)) << llList2Integer(SHIFT,i & 3)], i >> 2, i >> 2);
395                 i = i + 1;
396                 blocks = llListReplaceList(blocks, [llList2Integer(blocks, i >> 2) | (0x80 | (code & 0x3f)) << llList2Integer(SHIFT,i & 3)], i >> 2, i >> 2);
397                 i = i + 1;
398             } 
399             else if (code < 0xd800 || code >= 0xe000) 
400             {
401                 blocks = llListReplaceList(blocks, [llList2Integer(blocks, i >> 2) | (0xe0 | (code >> 12)) << llList2Integer(SHIFT,i & 3)], i >> 2, i >> 2);
402                 i = i + 1;
403                 blocks = llListReplaceList(blocks, [llList2Integer(blocks, i >> 2) | (0x80 | ((code >> 6) & 0x3f)) << llList2Integer(SHIFT,i & 3)], i >> 2, i >> 2);
404                 i = i + 1;
405                 blocks = llListReplaceList(blocks, [llList2Integer(blocks, i >> 2) | (0x80 | (code & 0x3f)) << llList2Integer(SHIFT,i & 3)], i >> 2, i >> 2);
406                 i = i + 1;
407             }
408             else 
409             {
410                 index = index + 1;
411                 code = 0x10000 + (((code & 0x3ff) << 10) | (UTF8ToUnicodeInteger(llGetSubString(message, index, index)) & 0x3ff));
412                 
413                 blocks = llListReplaceList(blocks, [llList2Integer(blocks, i >> 2) | (0xf0 | (code >> 18)) << llList2Integer(SHIFT,i & 3)], i >> 2, i >> 2);
414                 i = i + 1;
415                 blocks = llListReplaceList(blocks, [llList2Integer(blocks, i >> 2) | (0x80 | ((code >> 12) & 0x3f)) << llList2Integer(SHIFT,i & 3)], i >> 2, i >> 2);
416                 i = i + 1;
417                 blocks = llListReplaceList(blocks, [llList2Integer(blocks, i >> 2) | (0x80 | ((code >> 6) & 0x3f)) << llList2Integer(SHIFT,i & 3)], i >> 2, i >> 2);
418                 i = i + 1;
419                 blocks = llListReplaceList(blocks, [llList2Integer(blocks, i >> 2) | (0x80 | (code & 0x3f)) << llList2Integer(SHIFT,i & 3)], i >> 2, i >> 2);
420                 i = i + 1;
421             }
422         }
423         lastByteIndex = i;
424         if (i >= byteCount) 
425         {
426             start = i - byteCount;
427             block = llList2Integer(blocks,blockCount);
428             for(i = 0; i < blockCount; ++i)
429             {
430                 s = llListReplaceList(s, [llList2Integer(s,i) ^ llList2Integer(blocks,i)], i, i);    
431             }
432             s = f(s);
433             reset = TRUE;
434         }
435         else
436         {
437             start = i;    
438         }
439     }
440     
441     //Finalise
442     i = lastByteIndex;
443     blocks = llListReplaceList(blocks, [llList2Integer(blocks, i >> 2) | llList2Integer(padding, i & 3)],i >> 2, i >> 2);
444     if (lastByteIndex == byteCount) 
445     {
446         blocks = llListReplaceList(blocks, [llList2Integer(blocks, blockCount)], 0, 0);
447         for (i = 1; i < blockCount + 1; ++i) 
448         {
449             blocks = llListReplaceList(blocks, [0], i, i);
450         }
451     }
452     blocks = llListReplaceList(blocks, [llList2Integer(blocks, blockCount - 1) | 0x80000000], blockCount - 1, blockCount - 1);
453     
454     for (i = 0; i < blockCount; ++i) 
455     {
456         s = llListReplaceList(s, [llList2Integer(s, i) ^ llList2Integer(blocks,i)], i, i);
457     }    
458 
459     s = f(s);
460     
461     //Dump to hex
462     integer j = 0;
463     string hex = "";
464     
465     while (j < outputBlocks) 
466     {
467         for (i = 0; i < blockCount && j < outputBlocks; ++i, ++j) 
468         {
469             block = llList2Integer(s,i);        
470             hex += llList2String(HEX_CHARS,(block >> 4) & 0x0F) + llList2String(HEX_CHARS, block & 0x0F);
471             hex += llList2String(HEX_CHARS,(block >> 12) & 0x0F) + llList2String(HEX_CHARS,(block >> 8) & 0x0F);
472             hex += llList2String(HEX_CHARS,(block >> 20) & 0x0F) + llList2String(HEX_CHARS,(block >> 16) & 0x0F);
473             hex += llList2String(HEX_CHARS,(block >> 28) & 0x0F) + llList2String(HEX_CHARS,(block >> 24) & 0x0F);
474         }
475         if (j % blockCount == 0) 
476         {
477             s =f(s);
478             i = 0;
479         }
480     }
481     if (extraBytes) 
482     {
483         block = llList2Integer(s,i);
484         if (extraBytes > 0) 
485         {
486             hex += llList2String(HEX_CHARS,(block >> 4) & 0x0F) + llList2String(HEX_CHARS,block & 0x0F);
487         }
488         if (extraBytes > 1) 
489         {
490             hex += llList2String(HEX_CHARS,(block >> 12) & 0x0F) + llList2String(HEX_CHARS,(block >> 8) & 0x0F);
491         }
492         if (extraBytes > 2) 
493         {
494             hex += llList2String(HEX_CHARS,(block >> 20) & 0x0F) + llList2String(HEX_CHARS,(block >> 16) & 0x0F);
495         }
496     }
497     return hex;
498 }
499 
500 string digest(integer algorithm, integer strength, integer outputBits, string message)
501 {
502     if (algorithm==ALGORITHM_SHA3)
503     {
504         if (strength==224 || strength == 256 || strength == 384 || strength == 512)
505         {
506             return Keccak(strength, PADDING, strength, message);   
507         }
508     }
509     else if (algorithm==ALGORITHM_KECCAK)
510     {
511         if (strength==224 || strength==256 || strength==384 || strength==512 || strength==576)
512         {
513             return Keccak(strength, KECCAK_PADDING, strength, message);
514         }    
515     }
516     else if (algorithm==ALGORITHM_SHAKE)
517     {
518         if (strength==128 || strength==256)
519         {
520             return Keccak(strength, SHAKE_PADDING, outputBits, message);
521         }     
522     }
523     else
524     {
525         return "ERROR: Invalid algorithm";   
526     }
527     return "ERROR: Invalid parameters for algorithm";
528 }
529 integer total = 0;
530 integer passed = 0;
531 doTest(string testName, integer algorithm, integer bits, integer outputBits, string message, string expected)
532 {
533     llResetTime();
534      llSetText("Running "+testName,<1.0,1.0,1.0>,1.0);
535     string result = digest(algorithm, bits, outputBits, message);
536     string conclusion = "FAILED";
537     total++;
538     if (result == expected)
539     {
540         passed++;
541         //Don't output passes
542         conclusion = "PASSED in "+(string)llGetTime()+" seconds";
543     }
544     else
545     {
546         conclusion+=" Got: "+result+", Expected: "+expected;    
547     }
548 
549     llOwnerSay(testName+": "+conclusion);        
550     llSetText("",<1.0,1.0,1.0>,1.0);
551 }
552 
553 string longString = "CKbfXmklN4jDlILbNgZcWeHvOupCAyrZkZW1UmXzD2QUgUhlO13L14apDFb5CecAyAQAPZAteA7V8vpMS9BiGyGjButGvy4qG01pAAQPmb1HVNOwtoLKPIWco9ZkhTCZkUzZmlgfHlfSMZLek6weUFn1h9oyaz9Ccu7ozJxLzzOlYme5ILoiYOppt1llgOcOnBu8MxoTStiKL7Gjx5H4bWtBmxtXGC1oE9nugZpgvPteogU3u5zmf3Gun3Rfh1h8PzmvFtzIaRZE0VfBONv47KZKtO0D7zMcfYJkPq7iR8lBRxmBCysObNPbGBKGrT6s5zUUjm38KHn5q8ukwZ2BZtjbmTCKNUKSgCzHuDCKXfh1yLBXDjQGooemFPNbczW1OEawY8Voi0O7nSFzfJJGoJqBcaHJzOT30FgSlzoZoamD7EgceSErjYJLYAoXJAgWOqeU22hTtl7iHfxjVrafQfOobyUTpH1Zjk9STXpGTzuR62N4HQJxFz9BfZf7S02xAJtotg6zopUTak7x1NQ0kSUFB8ZeDLzHykWxPi5C1CTQCiS4aHnDggEy455zo4ifiLzFNbBo7BW0XTqIJMp5w67kLMvScewY4KoJfvCfRfOW90ETb8kb7OBGSt4WMGvzFzfh3F8CU16oAmUESCQoYcrb7VqJfrUfKbvvPy6vRIfS70981uBI0RKZKg2jIGaCYUG30DzA662zrqfAqkg6eXqAF4JSiZfXRVImpLEfnYUZh7e573OFq8xJhq8BYAFQxPxKKts3YBTA2I42Dq0zq3SvK451CHXjwc1cpACEsLB0Cg8wx093fMi6GyFzR06aR1Cg8zQkl7mYbS2yhq1x7bMUqcklMZgui5t9LFG7RjPhetnnG4CtBzyDcJutSShAqOc3UhnM4w8cho0OshnpgwgR4ebA3fwbubkLyqsX6yFE0w7WKzMqfaSvPttoi1uVtno6KRCg7O71m4DI85uAl7VPjlsyitYNjjxFlRP6blIikaoLl8pmf3eDmFUperIQ";
554 
555 default
556 {
557     state_entry()
558     {
559         llOwnerSay("Touch to run test suite");
560     }
561 
562     touch_start(integer total_number)
563     {
564         doTest("SHA-3 224 Empty",ALGORITHM_SHA3, 224, 0, "", "6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7");
565         doTest("SHA-3 512", ALGORITHM_SHA3, 512, 0, "The quick brown fox jumps over the lazy dog", "01dedd5de4ef14642445ba5f5b97c15e47b9ad931326e4b0727cd94cefc44fff23f07bf543139939b49128caf436dc1bdee54fcb24023a08d9403f9b4bf0d450");
566         doTest("SHA-3 512 Cascade", ALGORITHM_SHA3, 512, 0, "The quick brown fox jumps over the lazy dog.", "18f4f4bd419603f95538837003d9d254c26c23765565162247483f65c50303597bc9ce4d289f21d1c2f1f458828e33dc442100331b35e7eb031b5d38ba6460f8");
567         doTest("SHA-3 512 Empty", ALGORITHM_SHA3, 512, 0, "", "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26");
568         doTest("SHA-3 512 Unicode",ALGORITHM_SHA3, 512, 0, "中文", "059bbe2efc50cc30e4d8ec5a96be697e2108fcbf9193e1296192eddabc13b143c0120d059399a13d0d42651efe23a6c1ce2d1efb576c5b207fa2516050505af7");
569         doTest("SHA-3 512 Long",ALGORITHM_SHA3, 512, 0, longString, "7e8452e1a742af7170b1b85ef1743e0cac3e8f1dd11ffb6a0657641b813289b1a3efcc76a9d781e5c55400d8c337d437aa43d43ee6694d18814c76f8504a70cd");     
570 
571 
572         doTest("SHA-3 384", ALGORITHM_SHA3, 384, 0, "The quick brown fox jumps over the lazy dog", "7063465e08a93bce31cd89d2e3ca8f602498696e253592ed26f07bf7e703cf328581e1471a7ba7ab119b1a9ebdf8be41");
573         doTest("SHA-3 384 Cascade",ALGORITHM_SHA3, 384, 0, "The quick brown fox jumps over the lazy dog.", "1a34d81695b622df178bc74df7124fe12fac0f64ba5250b78b99c1273d4b080168e10652894ecad5f1f4d5b965437fb9");
574         doTest("SHA-3 384 Empty", ALGORITHM_SHA3, 384, 0, "", "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004");
575         doTest("SHA-3 384 Unicode",ALGORITHM_SHA3, 384, 0, "中文", "9fb5b99e3c546f2738dcd50a14e9aef9c313800c1bf8cf76bc9b2c3a23307841364c5a2d0794702662c5796fb72f5432");
576         doTest("SHA-3 384 Long", ALGORITHM_SHA3, 384, 0, longString, "683009d6ebe8596b77142ace13ac0dfc3b640bdbc437f848a41dc11e7b36db49bc4c648f2fff887e49b1ec48e47bd457");
577 
578         doTest("SHA-3 256",ALGORITHM_SHA3, 256, 0, "The quick brown fox jumps over the lazy dog", "69070dda01975c8c120c3aada1b282394e7f032fa9cf32f4cb2259a0897dfc04");
579         doTest("SHA-3 256 Cascade",ALGORITHM_SHA3, 256, 0, "The quick brown fox jumps over the lazy dog.", "a80f839cd4f83f6c3dafc87feae470045e4eb0d366397d5c6ce34ba1739f734d");
580         doTest("SHA-3 256 Empty",ALGORITHM_SHA3, 256, 0, "", "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a");        ;
581         doTest("SHA-3 256 Unicode",ALGORITHM_SHA3, 256, 0, "中文", "ac5305da3d18be1aed44aa7c70ea548da243a59a5fd546f489348fd5718fb1a0");
582         doTest("SHA-3 256 Long",ALGORITHM_SHA3, 256, 0, longString, "070ca9c7ea03e907ace05f976db311c85e26f2ccf1f00c8db8e222d1ae336ca9");
583 
584         doTest("SHA-3 224",ALGORITHM_SHA3, 224, 0, "The quick brown fox jumps over the lazy dog", "d15dadceaa4d5d7bb3b48f446421d542e08ad8887305e28d58335795");
585         doTest("SHA-3 224 Cascade",ALGORITHM_SHA3, 224, 0, "The quick brown fox jumps over the lazy dog.", "2d0708903833afabdd232a20201176e8b58c5be8a6fe74265ac54db0");
586         doTest("SHA-3 224 Empty",ALGORITHM_SHA3, 224, 0, "", "6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7");
587         doTest("SHA-3 224 Unicode",ALGORITHM_SHA3, 224, 0, "中文", "106d169e10b61c2a2a05554d3e631ec94467f8316640f29545d163ee");
588         doTest("SHA-3 224 Long",ALGORITHM_SHA3, 224, 0, longString, "1ea077c39a1e88ae715458f29fc580ca3e94a7d47dcdd829ac5e68af");
589         
590         doTest("Keccak 512",ALGORITHM_KECCAK, 512, 0, "The quick brown fox jumps over the lazy dog", "d135bb84d0439dbac432247ee573a23ea7d3c9deb2a968eb31d47c4fb45f1ef4422d6c531b5b9bd6f449ebcc449ea94d0a8f05f62130fda612da53c79659f609");
591         doTest("Keccak 512 Cascade",ALGORITHM_KECCAK, 512, 0, "The quick brown fox jumps over the lazy dog.", "ab7192d2b11f51c7dd744e7b3441febf397ca07bf812cceae122ca4ded6387889064f8db9230f173f6d1ab6e24b6e50f065b039f799f5592360a6558eb52d760");
592         doTest("Keccak 512 Empty",ALGORITHM_KECCAK, 512, 0, "", "0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e");
593         doTest("Keccak 512 Unicode",ALGORITHM_KECCAK, 512, 0, "中文", "2f6a1bd50562230229af34b0ccf46b8754b89d23ae2c5bf7840b4acfcef86f87395edc0a00b2bfef53bafebe3b79de2e3e01cbd8169ddbb08bde888dcc893524");
594         
595         doTest("Keccak 384",ALGORITHM_KECCAK, 384, 0, "The quick brown fox jumps over the lazy dog", "283990fa9d5fb731d786c5bbee94ea4db4910f18c62c03d173fc0a5e494422e8a0b3da7574dae7fa0baf005e504063b3");
596         doTest("Keccak 384 Cascade",ALGORITHM_KECCAK, 384, 0, "The quick brown fox jumps over the lazy dog.", "9ad8e17325408eddb6edee6147f13856ad819bb7532668b605a24a2d958f88bd5c169e56dc4b2f89ffd325f6006d820b");
597         doTest("Keccak 384 Empty",ALGORITHM_KECCAK, 384, 0, "", "2c23146a63a29acf99e73b88f8c24eaa7dc60aa771780ccc006afbfa8fe2479b2dd2b21362337441ac12b515911957ff");
598         doTest("Keccak 384 Unicode",ALGORITHM_KECCAK, 384, 0, "中文", "743f64bb7544c6ed923be4741b738dde18b7cee384a3a09c4e01acaaac9f19222cdee137702bd3aa05dc198373d87d6c");
599 
600         doTest("Keccak 256",ALGORITHM_KECCAK, 256, 0, "The quick brown fox jumps over the lazy dog", "4d741b6f1eb29cb2a9b9911c82f56fa8d73b04959d3d9d222895df6c0b28aa15");
601         doTest("Keccak 256 Cascade",ALGORITHM_KECCAK, 256, 0, "The quick brown fox jumps over the lazy dog.", "578951e24efd62a3d63a86f7cd19aaa53c898fe287d2552133220370240b572d");
602         doTest("Keccak 256 Empty",ALGORITHM_KECCAK, 256, 0, "", "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470");
603         doTest("Keccak 256 Unicode",ALGORITHM_KECCAK, 256, 0, "中文", "70a2b6579047f0a977fcb5e9120a4e07067bea9abb6916fbc2d13ffb9a4e4eee");
604 
605         doTest("Keccak 224",ALGORITHM_KECCAK, 224, 0, "The quick brown fox jumps over the lazy dog", "310aee6b30c47350576ac2873fa89fd190cdc488442f3ef654cf23fe");
606         doTest("Keccak 224 Cascade",ALGORITHM_KECCAK, 224, 0, "The quick brown fox jumps over the lazy dog.", "c59d4eaeac728671c635ff645014e2afa935bebffdb5fbd207ffdeab");
607         doTest("Keccak 224 Empty",ALGORITHM_KECCAK, 224, 0, "", "f71837502ba8e10837bdd8d365adb85591895602fc552b48b7390abd");
608         doTest("Keccak 224 Unicode",ALGORITHM_KECCAK, 224, 0, "中文", "7bc2a0b6e7e0a055a61e4f731e2944b560f41ff98967dcbf4bbf77a5");
609         
610         doTest("Shake 256 (512)",ALGORITHM_SHAKE, 256, 512, "The quick brown fox jumps over the lazy dog", "2f671343d9b2e1604dc9dcf0753e5fe15c7c64a0d283cbbf722d411a0e36f6ca1d01d1369a23539cd80f7c054b6e5daf9c962cad5b8ed5bd11998b40d5734442");
611         doTest("Shake 256 (512) Cascade",ALGORITHM_SHAKE, 256, 512, "The quick brown fox jumps over the lazy dog.", "bd225bfc8b255f3036f0c8866010ed0053b5163a3cae111e723c0c8e704eca4e5d0f1e2a2fa18c8a219de6b88d5917ff5dd75b5fb345e7409a3b333b508a65fb");
612         doTest("Shake 256 (512) Empty",ALGORITHM_SHAKE, 256, 512, "", "46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762fd75dc4ddd8c0f200cb05019d67b592f6fc821c49479ab48640292eacb3b7c4be");
613         doTest("Shake 256 (512) Unicode",ALGORITHM_SHAKE, 256, 512, "中文", "23c0e9f7f5e9863798dcc6de066ba3bc858fcf1652fbb19aeb0d45b049aae5b3cff3f2ee0f33ec00b4527c25e13c8fdf6abf56a4e4c18821fa9afa7d5cb5609d");
614         
615         doTest("Shake 128 (256)",ALGORITHM_SHAKE, 128, 256, "The quick brown fox jumps over the lazy dog", "f4202e3c5852f9182a0430fd8144f0a74b95e7417ecae17db0f8cfeed0e3e66e");
616         doTest("Shake 128 (256) Cascade",ALGORITHM_SHAKE, 128, 256, "The quick brown fox jumps over the lazy dog.", "634069e6b13c3af64c57f05babf5911b6acf1d309b9624fc92b0c0bd9f27f538");
617         doTest("Shake 128 (256) Empty",ALGORITHM_SHAKE, 128, 256, "", "7f9c2ba4e88f827d616045507605853ed73b8093f6efbc88eb1a6eacfa66ef26");
618         doTest("Shake 128 (256) Unicode",ALGORITHM_SHAKE, 128, 256, "中文", "d001a1cbe144d95604a9483407bdfbe078421a5f5a91a3de3465182cd11df868");
619         
620         llOwnerSay("("+(string)passed+"/"+(string)total+") tests passed");
621         
622     }
623 }