SHA-3

From CasperTech Wiki
Revision as of 00:03, 27 February 2017 by D1cd5b71-6209-4595-9bf0-771bf689ce00 (talk | contribs) (Created page with "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 sec...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
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.

<lsl> ///////////////////////////////////////////////////////////////////////////////// // // CasperTech SHA-3 implementation // // Creative Commons Attribution 4.0 International https://creativecommons.org/licenses/by/4.0/ // // Based on js-sha3 https://github.com/emn178/js-sha3 // ////////////////////////////////////////////////////////////////////////////////

list HEX_CHARS = ["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"]; list SHAKE_PADDING = [31, 7936, 2031616, 520093696]; list KECCAK_PADDING = [1, 256, 65536, 16777216]; list PADDING = [6, 1536, 393216, 100663296]; list SHIFT = [0, 8, 16, 24]; list RC = [1, 0, 32898, 0, 32906, 2147483648, 2147516416, 2147483648, 32907, 0, 2147483649,

           0, 2147516545, 2147483648, 32777, 2147483648, 138, 0, 136, 0, 2147516425, 0,
           2147483658, 0, 2147516555, 0, 139, 2147483648, 32905, 2147483648, 32771,
           2147483648, 32770, 2147483648, 128, 2147483648, 32778, 0, 2147483658, 2147483648,
           2147516545, 2147483648, 32896, 2147483648, 2147483649, 0, 2147516424, 2147483648];
           

integer ALGORITHM_SHA3 = 0; integer ALGORITHM_KECCAK = 1; integer ALGORITHM_SHAKE = 2;

integer UTF8ToUnicodeInteger(string input) //From http://wiki.secondlife.com/w/index.php?title=UTF-8 with thanks {

   integer result = llBase64ToInteger(llStringToBase64(input = llGetSubString(input,0,0)));
   if(result & 0x80000000)
   {
       integer end = (integer)("0x"+llGetSubString(input = (string)llParseString2List(llEscapeURL(input),(list)"%",[]),-8,-1));
       integer begin = (integer)("0x"+llDeleteSubString(input,-8,-1));
       return  (   (  0x0000003f &  end       ) |
                   (( 0x00003f00 &  end) >> 2 ) | 
                   (( 0x003f0000 &  end) >> 4 ) | 
                   (( 0x3f000000 &  end) >> 6 ) |
                   (( 0x0000003f &  begin) << 24) |
                   (( 0x00000100 &  begin) << 22)
               ) & (0x7FFFFFFF >> (5 * ((integer)(llLog(~result) / 0.69314718055994530941723212145818) - 25)));
   }
   return result >> 24;

} integer zeroFillRightShift(integer value, integer count) //From http://wiki.secondlife.com/wiki/Right_Shift with thanks {

   return ((value & 0x7fFFffFF) >> count) - ((value & 0x80000000) >> count);

} list f(list s) {

   integer h;
   integer l;
   integer n;
   integer c0;
   integer c1;
   integer c2;
   integer c3;
   integer c4;
   integer c5;
   integer c6;
   integer c7;
   integer c8;
   integer c9;
   integer b0;
   integer b1;
   integer b2;
   integer b3;
   integer b4;
   integer b5;
   integer b6;
   integer b7;
   integer b8;
   integer b9;
   integer b10;
   integer b11;
   integer b12;
   integer b13;
   integer b14;
   integer b15;
   integer b16;
   integer b17;
   integer b18;
   integer b19;
   integer b20;
   integer b21;
   integer b22;
   integer b23;
   integer b24;
   integer b25;
   integer b26;
   integer b27;
   integer b28;
   integer b29;
   integer b30;
   integer b31;
   integer b32;
   integer b33;
   integer b34;
   integer b35;
   integer b36;
   integer b37;
   integer b38;
   integer b39;
   integer b40;
   integer b41;
   integer b42;
   integer b43;
   integer b44;
   integer b45;
   integer b46;
   integer b47;
   integer b48;
   integer b49;
   
   integer s0 = llList2Integer(s,0);
   integer s1 = llList2Integer(s,1);
   integer s2 = llList2Integer(s,2);
   integer s3 = llList2Integer(s,3);
   integer s4 = llList2Integer(s,4);
   integer s5 = llList2Integer(s,5);
   integer s6 = llList2Integer(s,6);
   integer s7 = llList2Integer(s,7);
   integer s8 = llList2Integer(s,8);
   integer s9 = llList2Integer(s,9);
   integer s10 = llList2Integer(s,10);
   integer s11 = llList2Integer(s,11);
   integer s12 = llList2Integer(s,12);
   integer s13 = llList2Integer(s,13);
   integer s14 = llList2Integer(s,14);
   integer s15 = llList2Integer(s,15);
   integer s16 = llList2Integer(s,16);
   integer s17 = llList2Integer(s,17);
   integer s18 = llList2Integer(s,18);
   integer s19 = llList2Integer(s,19);
   integer s20 = llList2Integer(s,20);
   integer s21 = llList2Integer(s,21);
   integer s22 = llList2Integer(s,22);
   integer s23 = llList2Integer(s,23);
   integer s24 = llList2Integer(s,24);
   integer s25 = llList2Integer(s,25);
   integer s26 = llList2Integer(s,26);
   integer s27 = llList2Integer(s,27);
   integer s28 = llList2Integer(s,28);
   integer s29 = llList2Integer(s,29);
   integer s30 = llList2Integer(s,30);
   integer s31 = llList2Integer(s,31);
   integer s32 = llList2Integer(s,32);
   integer s33 = llList2Integer(s,33);
   integer s34 = llList2Integer(s,34);
   integer s35 = llList2Integer(s,35);
   integer s36 = llList2Integer(s,36);
   integer s37 = llList2Integer(s,37);
   integer s38 = llList2Integer(s,38);
   integer s39 = llList2Integer(s,39);
   integer s40 = llList2Integer(s,40);
   integer s41 = llList2Integer(s,41);
   integer s42 = llList2Integer(s,42);
   integer s43 = llList2Integer(s,43);
   integer s44 = llList2Integer(s,44);
   integer s45 = llList2Integer(s,45);
   integer s46 = llList2Integer(s,46);
   integer s47 = llList2Integer(s,47);
   integer s48 = llList2Integer(s,48);
   integer s49 = llList2Integer(s,49);
   
       
       
   for (n = 0; n < 48; n += 2) 
   {
       c0 = s0 ^ s10 ^ s20 ^ s30 ^ s40;
       c1 = s1 ^ s11 ^ s21 ^ s31 ^ s41;
       c2 = s2 ^ s12 ^ s22 ^ s32 ^ s42;
       c3 = s3 ^ s13 ^ s23 ^ s33 ^ s43;
       c4 = s4 ^ s14 ^ s24 ^ s34 ^ s44;
       c5 = s5 ^ s15 ^ s25 ^ s35 ^ s45;
       c6 = s6 ^ s16 ^ s26 ^ s36 ^ s46;
       c7 = s7 ^ s17 ^ s27 ^ s37 ^ s47;
       c8 = s8 ^ s18 ^ s28 ^ s38 ^ s48;
       c9 = s9 ^ s19 ^ s29 ^ s39 ^ s49;
       
       h = c8 ^ ((c2 << 1) | (zeroFillRightShift(c3,31)));
       l = c9 ^ ((c3 << 1) | (zeroFillRightShift(c2,31)));
       s0 = s0 ^ h;
       s1 = s1 ^ l;
       s10 = s10 ^ h;
       s11 = s11 ^ l;
       s20 = s20 ^ h;
       s21 = s21 ^ l;
       s30 = s30 ^ h;
       s31 = s31 ^ l;
       s40 = s40 ^ h;
       s41 = s41 ^ l;
       h = c0 ^ ((c4 << 1) | (zeroFillRightShift(c5,31)));
       l = c1 ^ ((c5 << 1) | (zeroFillRightShift(c4,31)));
       s2 = s2 ^ h;
       s3 = s3 ^ l;
       s12 = s12 ^ h;
       s13 = s13 ^ l;
       s22 = s22 ^ h;
       s23 = s23 ^ l;
       s32 = s32 ^ h;
       s33 = s33 ^ l;
       s42 = s42 ^ h;
       s43 = s43 ^ l;
       h = c2 ^ ((c6 << 1) | (zeroFillRightShift(c7,31)));
       l = c3 ^ ((c7 << 1) | (zeroFillRightShift(c6,31)));
       s4 = s4 ^ h;
       s5 = s5 ^ l;
       s14 = s14 ^ h;
       s15 = s15 ^ l;
       s24 = s24 ^ h;
       s25 = s25 ^ l;
       s34 = s34 ^ h;
       s35 = s35 ^ l;
       s44 = s44 ^ h;
       s45 = s45 ^ l;
       h = c4 ^ ((c8 << 1) | (zeroFillRightShift(c9,31)));
       l = c5 ^ ((c9 << 1) | (zeroFillRightShift(c8,31)));
       s6 = s6 ^ h;
       s7 = s7 ^ l;
       s16 = s16 ^ h;
       s17 = s17 ^ l;
       s26 = s26 ^ h;
       s27 = s27 ^ l;
       s36 = s36 ^ h;
       s37 = s37 ^ l;
       s46 = s46 ^ h;
       s47 = s47 ^ l;
       h = c6 ^ ((c0 << 1) | (zeroFillRightShift(c1,31)));
       l = c7 ^ ((c1 << 1) | (zeroFillRightShift(c0,31)));
       s8 = s8 ^ h;
       s9 = s9 ^ l;
       s18 = s18 ^ h;
       s19 = s19 ^ l;
       s28 = s28 ^ h;
       s29 = s29 ^ l;
       s38 = s38 ^ h;
       s39 = s39 ^ l;
       s48 = s48 ^ h;
       s49 = s49 ^ l;
       
       b0 = s0;
       b1 = s1;
       b32 = (s11 << 4) | (zeroFillRightShift(s10,28));
       b33 = (s10 << 4) | (zeroFillRightShift(s11,28));
       b14 = (s20 << 3) | (zeroFillRightShift(s21,29));
       b15 = (s21 << 3) | (zeroFillRightShift(s20,29));
       b46 = (s31 << 9) | (zeroFillRightShift(s30,23));
       b47 = (s30 << 9) | (zeroFillRightShift(s31,23));
       b28 = (s40 << 18) | (zeroFillRightShift(s41,14));
       b29 = (s41 << 18) | (zeroFillRightShift(s40,14));
       b20 = (s2 << 1) | (zeroFillRightShift(s3,31));
       b21 = (s3 << 1) | (zeroFillRightShift(s2,31));
       b2 = (s13 << 12) | (zeroFillRightShift(s12,20));
       b3 = (s12 << 12) | (zeroFillRightShift(s13,20));
       b34 = (s22 << 10) | (zeroFillRightShift(s23,22));
       b35 = (s23 << 10) | (zeroFillRightShift(s22,22));
       b16 = (s33 << 13) | (zeroFillRightShift(s32,19));
       b17 = (s32 << 13) | (zeroFillRightShift(s33,19));
       b48 = (s42 << 2) | (zeroFillRightShift(s43,30));
       b49 = (s43 << 2) | (zeroFillRightShift(s42,30));
       b40 = (s5 << 30) | (zeroFillRightShift(s4,2));
       b41 = (s4 << 30) | (zeroFillRightShift(s5,2));
       b22 = (s14 << 6) | (zeroFillRightShift(s15,26));
       b23 = (s15 << 6) | (zeroFillRightShift(s14,26));
       b4 = (s25 << 11) | (zeroFillRightShift(s24,21));
       b5 = (s24 << 11) | (zeroFillRightShift(s25,21));
       b36 = (s34 << 15) | (zeroFillRightShift(s35,17));
       b37 = (s35 << 15) | (zeroFillRightShift(s34,17));
       b18 = (s45 << 29) | (zeroFillRightShift(s44,3));
       b19 = (s44 << 29) | (zeroFillRightShift(s45,3));
       b10 = (s6 << 28) | (zeroFillRightShift(s7,4));
       b11 = (s7 << 28) | (zeroFillRightShift(s6,4));
       b42 = (s17 << 23) | (zeroFillRightShift(s16,9));
       b43 = (s16 << 23) | (zeroFillRightShift(s17,9));
       b24 = (s26 << 25) | (zeroFillRightShift(s27,7));
       b25 = (s27 << 25) | (zeroFillRightShift(s26,7));
       b6 = (s36 << 21) | (zeroFillRightShift(s37,11));
       b7 = (s37 << 21) | (zeroFillRightShift(s36,11));
       b38 = (s47 << 24) | (zeroFillRightShift(s46,8));
       b39 = (s46 << 24) | (zeroFillRightShift(s47,8));
       b30 = (s8 << 27) | (zeroFillRightShift(s9,5));
       b31 = (s9 << 27) | (zeroFillRightShift(s8,5));
       b12 = (s18 << 20) | (zeroFillRightShift(s19,12));
       b13 = (s19 << 20) | (zeroFillRightShift(s18,12));
       b44 = (s29 << 7) | (zeroFillRightShift(s28,25));
       b45 = (s28 << 7) | (zeroFillRightShift(s29,25));
       b26 = (s38 << 8) | (zeroFillRightShift(s39,24));
       b27 = (s39 << 8) | (zeroFillRightShift(s38,24));
       b8 = (s48 << 14) | (zeroFillRightShift(s49,18));
       b9 = (s49 << 14) | (zeroFillRightShift(s48,18));
       
       s0 = b0 ^ (~b2 & b4);
       s1 = b1 ^ (~b3 & b5);
       s10 = b10 ^ (~b12 & b14);
       s11 = b11 ^ (~b13 & b15);
       s20 = b20 ^ (~b22 & b24);
       s21 = b21 ^ (~b23 & b25);
       s30 = b30 ^ (~b32 & b34);
       s31 = b31 ^ (~b33 & b35);
       s40 = b40 ^ (~b42 & b44);
       s41 = b41 ^ (~b43 & b45);
       s2 = b2 ^ (~b4 & b6);
       s3 = b3 ^ (~b5 & b7);
       s12 = b12 ^ (~b14 & b16);
       s13 = b13 ^ (~b15 & b17);
       s22 = b22 ^ (~b24 & b26);
       s23 = b23 ^ (~b25 & b27);
       s32 = b32 ^ (~b34 & b36);
       s33 = b33 ^ (~b35 & b37);
       s42 = b42 ^ (~b44 & b46);
       s43 = b43 ^ (~b45 & b47);
       s4 = b4 ^ (~b6 & b8);
       s5 = b5 ^ (~b7 & b9);
       s14 = b14 ^ (~b16 & b18);
       s15 = b15 ^ (~b17 & b19);
       s24 = b24 ^ (~b26 & b28);
       s25 = b25 ^ (~b27 & b29);
       s34 = b34 ^ (~b36 & b38);
       s35 = b35 ^ (~b37 & b39);
       s44 = b44 ^ (~b46 & b48);
       s45 = b45 ^ (~b47 & b49);
       s6 = b6 ^ (~b8 & b0);
       s7 = b7 ^ (~b9 & b1);
       s16 = b16 ^ (~b18 & b10);
       s17 = b17 ^ (~b19 & b11);
       s26 = b26 ^ (~b28 & b20);
       s27 = b27 ^ (~b29 & b21);
       s36 = b36 ^ (~b38 & b30);
       s37 = b37 ^ (~b39 & b31);
       s46 = b46 ^ (~b48 & b40);
       s47 = b47 ^ (~b49 & b41);
       s8 = b8 ^ (~b0 & b2);
       s9 = b9 ^ (~b1 & b3);
       s18 = b18 ^ (~b10 & b12);
       s19 = b19 ^ (~b11 & b13);
       s28 = b28 ^ (~b20 & b22);
       s29 = b29 ^ (~b21 & b23);
       s38 = b38 ^ (~b30 & b32);
       s39 = b39 ^ (~b31 & b33);
       s48 = b48 ^ (~b40 & b42);
       s49 = b49 ^ (~b41 & b43);
       
       s0 = s0 ^ llList2Integer(RC, n);
       s1 = s1 ^ llList2Integer(RC, n + 1);
   }
   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];  

} string Keccak(integer bits, list padding, integer outputBits, string message) {

   list blocks = [];
   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];
   integer block = 0;
   integer start = 0;
   integer blockCount = (1600 - (bits << 1)) >> 5;
   
   integer byteCount = blockCount << 2;
   integer outputBlocks = outputBits >> 5;   
   integer extraBytes = (outputBits & 31) >> 3;
   integer length = llStringLength(message);
   integer index = 0;
   integer i;
   integer code;
   integer reset = FALSE;
   integer lastByteIndex = 0;
   
   blocks = [0];
   for(i = 0; i < blockCount + 1; ++i) 
   {
       blocks+=[0];
   }
   
   
   while(index < length)
   {
       if (reset == TRUE)
       {
           reset = FALSE;
           blocks = [block];
           for(i = 0; i < blockCount + 1; ++i) 
           {
               blocks+=[0];
           }
       }
       for(i = start; index < length && i < byteCount; ++index)
       {
           code = UTF8ToUnicodeInteger(llGetSubString(message, index, index));
           integer blockNumber = llList2Integer(blocks, i >> 2);            
           if (code < 0x80)
           {
               blocks = llListReplaceList(blocks, [llList2Integer(blocks, i >> 2) | code << llList2Integer(SHIFT,i & 3)], i >> 2, i >> 2);
               i = i + 1;
           } 
           else if (code < 0x800) 
           {
               blocks = llListReplaceList(blocks, [llList2Integer(blocks, i >> 2) |(0xc0 | (code >> 6)) << llList2Integer(SHIFT,i & 3)], i >> 2, i >> 2);
               i = i + 1;
               blocks = llListReplaceList(blocks, [llList2Integer(blocks, i >> 2) | (0x80 | (code & 0x3f)) << llList2Integer(SHIFT,i & 3)], i >> 2, i >> 2);
               i = i + 1;
           } 
           else if (code < 0xd800 || code >= 0xe000) 
           {
               blocks = llListReplaceList(blocks, [llList2Integer(blocks, i >> 2) | (0xe0 | (code >> 12)) << llList2Integer(SHIFT,i & 3)], i >> 2, i >> 2);
               i = i + 1;
               blocks = llListReplaceList(blocks, [llList2Integer(blocks, i >> 2) | (0x80 | ((code >> 6) & 0x3f)) << llList2Integer(SHIFT,i & 3)], i >> 2, i >> 2);
               i = i + 1;
               blocks = llListReplaceList(blocks, [llList2Integer(blocks, i >> 2) | (0x80 | (code & 0x3f)) << llList2Integer(SHIFT,i & 3)], i >> 2, i >> 2);
               i = i + 1;
           }
           else 
           {
               index = index + 1;
               code = 0x10000 + (((code & 0x3ff) << 10) | (UTF8ToUnicodeInteger(llGetSubString(message, index, index)) & 0x3ff));
               
               blocks = llListReplaceList(blocks, [llList2Integer(blocks, i >> 2) | (0xf0 | (code >> 18)) << llList2Integer(SHIFT,i & 3)], i >> 2, i >> 2);
               i = i + 1;
               blocks = llListReplaceList(blocks, [llList2Integer(blocks, i >> 2) | (0x80 | ((code >> 12) & 0x3f)) << llList2Integer(SHIFT,i & 3)], i >> 2, i >> 2);
               i = i + 1;
               blocks = llListReplaceList(blocks, [llList2Integer(blocks, i >> 2) | (0x80 | ((code >> 6) & 0x3f)) << llList2Integer(SHIFT,i & 3)], i >> 2, i >> 2);
               i = i + 1;
               blocks = llListReplaceList(blocks, [llList2Integer(blocks, i >> 2) | (0x80 | (code & 0x3f)) << llList2Integer(SHIFT,i & 3)], i >> 2, i >> 2);
               i = i + 1;
           }
       }
       lastByteIndex = i;
       if (i >= byteCount) 
       {
           start = i - byteCount;
           block = llList2Integer(blocks,blockCount);
           for(i = 0; i < blockCount; ++i)
           {
               s = llListReplaceList(s, [llList2Integer(s,i) ^ llList2Integer(blocks,i)], i, i);    
           }
           s = f(s);
           reset = TRUE;
       }
       else
       {
           start = i;    
       }
   }
   
   //Finalise
   i = lastByteIndex;
   blocks = llListReplaceList(blocks, [llList2Integer(blocks, i >> 2) | llList2Integer(padding, i & 3)],i >> 2, i >> 2);
   if (lastByteIndex == byteCount) 
   {
       blocks = llListReplaceList(blocks, [llList2Integer(blocks, blockCount)], 0, 0);
       for (i = 1; i < blockCount + 1; ++i) 
       {
           blocks = llListReplaceList(blocks, [0], i, i);
       }
   }
   blocks = llListReplaceList(blocks, [llList2Integer(blocks, blockCount - 1) | 0x80000000], blockCount - 1, blockCount - 1);
   
   for (i = 0; i < blockCount; ++i) 
   {
       s = llListReplaceList(s, [llList2Integer(s, i) ^ llList2Integer(blocks,i)], i, i);
   }    
   s = f(s);
   
   //Dump to hex
   integer j = 0;
   string hex = "";
   
   while (j < outputBlocks) 
   {
       for (i = 0; i < blockCount && j < outputBlocks; ++i, ++j) 
       {
           block = llList2Integer(s,i);        
           hex += llList2String(HEX_CHARS,(block >> 4) & 0x0F) + llList2String(HEX_CHARS, block & 0x0F);
           hex += llList2String(HEX_CHARS,(block >> 12) & 0x0F) + llList2String(HEX_CHARS,(block >> 8) & 0x0F);
           hex += llList2String(HEX_CHARS,(block >> 20) & 0x0F) + llList2String(HEX_CHARS,(block >> 16) & 0x0F);
           hex += llList2String(HEX_CHARS,(block >> 28) & 0x0F) + llList2String(HEX_CHARS,(block >> 24) & 0x0F);
       }
       if (j % blockCount == 0) 
       {
           s =f(s);
           i = 0;
       }
   }
   if (extraBytes) 
   {
       block = llList2Integer(s,i);
       if (extraBytes > 0) 
       {
           hex += llList2String(HEX_CHARS,(block >> 4) & 0x0F) + llList2String(HEX_CHARS,block & 0x0F);
       }
       if (extraBytes > 1) 
       {
           hex += llList2String(HEX_CHARS,(block >> 12) & 0x0F) + llList2String(HEX_CHARS,(block >> 8) & 0x0F);
       }
       if (extraBytes > 2) 
       {
           hex += llList2String(HEX_CHARS,(block >> 20) & 0x0F) + llList2String(HEX_CHARS,(block >> 16) & 0x0F);
       }
   }
   return hex;

}

string digest(integer algorithm, integer strength, integer outputBits, string message) {

   if (algorithm==ALGORITHM_SHA3)
   {
       if (strength==224 || strength == 256 || strength == 384 || strength == 512)
       {
           return Keccak(strength, PADDING, strength, message);   
       }
   }
   else if (algorithm==ALGORITHM_KECCAK)
   {
       if (strength==224 || strength==256 || strength==384 || strength==512 || strength==576)
       {
           return Keccak(strength, KECCAK_PADDING, strength, message);
       }    
   }
   else if (algorithm==ALGORITHM_SHAKE)
   {
       if (strength==128 || strength==256)
       {
           return Keccak(strength, SHAKE_PADDING, outputBits, message);
       }     
   }
   else
   {
       return "ERROR: Invalid algorithm";   
   }
   return "ERROR: Invalid parameters for algorithm";

} integer total = 0; integer passed = 0; doTest(string testName, integer algorithm, integer bits, integer outputBits, string message, string expected) {

   llResetTime();
    llSetText("Running "+testName,<1.0,1.0,1.0>,1.0);
   string result = digest(algorithm, bits, outputBits, message);
   string conclusion = "FAILED";
   total++;
   if (result == expected)
   {
       passed++;
       //Don't output passes
       conclusion = "PASSED in "+(string)llGetTime()+" seconds";
   }
   else
   {
       conclusion+=" Got: "+result+", Expected: "+expected;    
   }
   llOwnerSay(testName+": "+conclusion);        
   llSetText("",<1.0,1.0,1.0>,1.0);

}

string longString = "CKbfXmklN4jDlILbNgZcWeHvOupCAyrZkZW1UmXzD2QUgUhlO13L14apDFb5CecAyAQAPZAteA7V8vpMS9BiGyGjButGvy4qG01pAAQPmb1HVNOwtoLKPIWco9ZkhTCZkUzZmlgfHlfSMZLek6weUFn1h9oyaz9Ccu7ozJxLzzOlYme5ILoiYOppt1llgOcOnBu8MxoTStiKL7Gjx5H4bWtBmxtXGC1oE9nugZpgvPteogU3u5zmf3Gun3Rfh1h8PzmvFtzIaRZE0VfBONv47KZKtO0D7zMcfYJkPq7iR8lBRxmBCysObNPbGBKGrT6s5zUUjm38KHn5q8ukwZ2BZtjbmTCKNUKSgCzHuDCKXfh1yLBXDjQGooemFPNbczW1OEawY8Voi0O7nSFzfJJGoJqBcaHJzOT30FgSlzoZoamD7EgceSErjYJLYAoXJAgWOqeU22hTtl7iHfxjVrafQfOobyUTpH1Zjk9STXpGTzuR62N4HQJxFz9BfZf7S02xAJtotg6zopUTak7x1NQ0kSUFB8ZeDLzHykWxPi5C1CTQCiS4aHnDggEy455zo4ifiLzFNbBo7BW0XTqIJMp5w67kLMvScewY4KoJfvCfRfOW90ETb8kb7OBGSt4WMGvzFzfh3F8CU16oAmUESCQoYcrb7VqJfrUfKbvvPy6vRIfS70981uBI0RKZKg2jIGaCYUG30DzA662zrqfAqkg6eXqAF4JSiZfXRVImpLEfnYUZh7e573OFq8xJhq8BYAFQxPxKKts3YBTA2I42Dq0zq3SvK451CHXjwc1cpACEsLB0Cg8wx093fMi6GyFzR06aR1Cg8zQkl7mYbS2yhq1x7bMUqcklMZgui5t9LFG7RjPhetnnG4CtBzyDcJutSShAqOc3UhnM4w8cho0OshnpgwgR4ebA3fwbubkLyqsX6yFE0w7WKzMqfaSvPttoi1uVtno6KRCg7O71m4DI85uAl7VPjlsyitYNjjxFlRP6blIikaoLl8pmf3eDmFUperIQ";

default {

   state_entry()
   {
       llOwnerSay("Touch to run test suite");
   }
   touch_start(integer total_number)
   {
       doTest("SHA-3 224 Empty",ALGORITHM_SHA3, 224, 0, "", "6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7");
       doTest("SHA-3 512", ALGORITHM_SHA3, 512, 0, "The quick brown fox jumps over the lazy dog", "01dedd5de4ef14642445ba5f5b97c15e47b9ad931326e4b0727cd94cefc44fff23f07bf543139939b49128caf436dc1bdee54fcb24023a08d9403f9b4bf0d450");
       doTest("SHA-3 512 Cascade", ALGORITHM_SHA3, 512, 0, "The quick brown fox jumps over the lazy dog.", "18f4f4bd419603f95538837003d9d254c26c23765565162247483f65c50303597bc9ce4d289f21d1c2f1f458828e33dc442100331b35e7eb031b5d38ba6460f8");
       doTest("SHA-3 512 Empty", ALGORITHM_SHA3, 512, 0, "", "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26");
       doTest("SHA-3 512 Unicode",ALGORITHM_SHA3, 512, 0, "中文", "059bbe2efc50cc30e4d8ec5a96be697e2108fcbf9193e1296192eddabc13b143c0120d059399a13d0d42651efe23a6c1ce2d1efb576c5b207fa2516050505af7");
       doTest("SHA-3 512 Long",ALGORITHM_SHA3, 512, 0, longString, "7e8452e1a742af7170b1b85ef1743e0cac3e8f1dd11ffb6a0657641b813289b1a3efcc76a9d781e5c55400d8c337d437aa43d43ee6694d18814c76f8504a70cd");     


       doTest("SHA-3 384", ALGORITHM_SHA3, 384, 0, "The quick brown fox jumps over the lazy dog", "7063465e08a93bce31cd89d2e3ca8f602498696e253592ed26f07bf7e703cf328581e1471a7ba7ab119b1a9ebdf8be41");
       doTest("SHA-3 384 Cascade",ALGORITHM_SHA3, 384, 0, "The quick brown fox jumps over the lazy dog.", "1a34d81695b622df178bc74df7124fe12fac0f64ba5250b78b99c1273d4b080168e10652894ecad5f1f4d5b965437fb9");
       doTest("SHA-3 384 Empty", ALGORITHM_SHA3, 384, 0, "", "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004");
       doTest("SHA-3 384 Unicode",ALGORITHM_SHA3, 384, 0, "中文", "9fb5b99e3c546f2738dcd50a14e9aef9c313800c1bf8cf76bc9b2c3a23307841364c5a2d0794702662c5796fb72f5432");
       doTest("SHA-3 384 Long", ALGORITHM_SHA3, 384, 0, longString, "683009d6ebe8596b77142ace13ac0dfc3b640bdbc437f848a41dc11e7b36db49bc4c648f2fff887e49b1ec48e47bd457");
       doTest("SHA-3 256",ALGORITHM_SHA3, 256, 0, "The quick brown fox jumps over the lazy dog", "69070dda01975c8c120c3aada1b282394e7f032fa9cf32f4cb2259a0897dfc04");
       doTest("SHA-3 256 Cascade",ALGORITHM_SHA3, 256, 0, "The quick brown fox jumps over the lazy dog.", "a80f839cd4f83f6c3dafc87feae470045e4eb0d366397d5c6ce34ba1739f734d");
       doTest("SHA-3 256 Empty",ALGORITHM_SHA3, 256, 0, "", "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a");        ;
       doTest("SHA-3 256 Unicode",ALGORITHM_SHA3, 256, 0, "中文", "ac5305da3d18be1aed44aa7c70ea548da243a59a5fd546f489348fd5718fb1a0");
       doTest("SHA-3 256 Long",ALGORITHM_SHA3, 256, 0, longString, "070ca9c7ea03e907ace05f976db311c85e26f2ccf1f00c8db8e222d1ae336ca9");
       doTest("SHA-3 224",ALGORITHM_SHA3, 224, 0, "The quick brown fox jumps over the lazy dog", "d15dadceaa4d5d7bb3b48f446421d542e08ad8887305e28d58335795");
       doTest("SHA-3 224 Cascade",ALGORITHM_SHA3, 224, 0, "The quick brown fox jumps over the lazy dog.", "2d0708903833afabdd232a20201176e8b58c5be8a6fe74265ac54db0");
       doTest("SHA-3 224 Empty",ALGORITHM_SHA3, 224, 0, "", "6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7");
       doTest("SHA-3 224 Unicode",ALGORITHM_SHA3, 224, 0, "中文", "106d169e10b61c2a2a05554d3e631ec94467f8316640f29545d163ee");
       doTest("SHA-3 224 Long",ALGORITHM_SHA3, 224, 0, longString, "1ea077c39a1e88ae715458f29fc580ca3e94a7d47dcdd829ac5e68af");
       
       doTest("Keccak 512",ALGORITHM_KECCAK, 512, 0, "The quick brown fox jumps over the lazy dog", "d135bb84d0439dbac432247ee573a23ea7d3c9deb2a968eb31d47c4fb45f1ef4422d6c531b5b9bd6f449ebcc449ea94d0a8f05f62130fda612da53c79659f609");
       doTest("Keccak 512 Cascade",ALGORITHM_KECCAK, 512, 0, "The quick brown fox jumps over the lazy dog.", "ab7192d2b11f51c7dd744e7b3441febf397ca07bf812cceae122ca4ded6387889064f8db9230f173f6d1ab6e24b6e50f065b039f799f5592360a6558eb52d760");
       doTest("Keccak 512 Empty",ALGORITHM_KECCAK, 512, 0, "", "0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e");
       doTest("Keccak 512 Unicode",ALGORITHM_KECCAK, 512, 0, "中文", "2f6a1bd50562230229af34b0ccf46b8754b89d23ae2c5bf7840b4acfcef86f87395edc0a00b2bfef53bafebe3b79de2e3e01cbd8169ddbb08bde888dcc893524");
       
       doTest("Keccak 384",ALGORITHM_KECCAK, 384, 0, "The quick brown fox jumps over the lazy dog", "283990fa9d5fb731d786c5bbee94ea4db4910f18c62c03d173fc0a5e494422e8a0b3da7574dae7fa0baf005e504063b3");
       doTest("Keccak 384 Cascade",ALGORITHM_KECCAK, 384, 0, "The quick brown fox jumps over the lazy dog.", "9ad8e17325408eddb6edee6147f13856ad819bb7532668b605a24a2d958f88bd5c169e56dc4b2f89ffd325f6006d820b");
       doTest("Keccak 384 Empty",ALGORITHM_KECCAK, 384, 0, "", "2c23146a63a29acf99e73b88f8c24eaa7dc60aa771780ccc006afbfa8fe2479b2dd2b21362337441ac12b515911957ff");
       doTest("Keccak 384 Unicode",ALGORITHM_KECCAK, 384, 0, "中文", "743f64bb7544c6ed923be4741b738dde18b7cee384a3a09c4e01acaaac9f19222cdee137702bd3aa05dc198373d87d6c");
       doTest("Keccak 256",ALGORITHM_KECCAK, 256, 0, "The quick brown fox jumps over the lazy dog", "4d741b6f1eb29cb2a9b9911c82f56fa8d73b04959d3d9d222895df6c0b28aa15");
       doTest("Keccak 256 Cascade",ALGORITHM_KECCAK, 256, 0, "The quick brown fox jumps over the lazy dog.", "578951e24efd62a3d63a86f7cd19aaa53c898fe287d2552133220370240b572d");
       doTest("Keccak 256 Empty",ALGORITHM_KECCAK, 256, 0, "", "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470");
       doTest("Keccak 256 Unicode",ALGORITHM_KECCAK, 256, 0, "中文", "70a2b6579047f0a977fcb5e9120a4e07067bea9abb6916fbc2d13ffb9a4e4eee");
       doTest("Keccak 224",ALGORITHM_KECCAK, 224, 0, "The quick brown fox jumps over the lazy dog", "310aee6b30c47350576ac2873fa89fd190cdc488442f3ef654cf23fe");
       doTest("Keccak 224 Cascade",ALGORITHM_KECCAK, 224, 0, "The quick brown fox jumps over the lazy dog.", "c59d4eaeac728671c635ff645014e2afa935bebffdb5fbd207ffdeab");
       doTest("Keccak 224 Empty",ALGORITHM_KECCAK, 224, 0, "", "f71837502ba8e10837bdd8d365adb85591895602fc552b48b7390abd");
       doTest("Keccak 224 Unicode",ALGORITHM_KECCAK, 224, 0, "中文", "7bc2a0b6e7e0a055a61e4f731e2944b560f41ff98967dcbf4bbf77a5");
       
       doTest("Shake 256 (512)",ALGORITHM_SHAKE, 256, 512, "The quick brown fox jumps over the lazy dog", "2f671343d9b2e1604dc9dcf0753e5fe15c7c64a0d283cbbf722d411a0e36f6ca1d01d1369a23539cd80f7c054b6e5daf9c962cad5b8ed5bd11998b40d5734442");
       doTest("Shake 256 (512) Cascade",ALGORITHM_SHAKE, 256, 512, "The quick brown fox jumps over the lazy dog.", "bd225bfc8b255f3036f0c8866010ed0053b5163a3cae111e723c0c8e704eca4e5d0f1e2a2fa18c8a219de6b88d5917ff5dd75b5fb345e7409a3b333b508a65fb");
       doTest("Shake 256 (512) Empty",ALGORITHM_SHAKE, 256, 512, "", "46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762fd75dc4ddd8c0f200cb05019d67b592f6fc821c49479ab48640292eacb3b7c4be");
       doTest("Shake 256 (512) Unicode",ALGORITHM_SHAKE, 256, 512, "中文", "23c0e9f7f5e9863798dcc6de066ba3bc858fcf1652fbb19aeb0d45b049aae5b3cff3f2ee0f33ec00b4527c25e13c8fdf6abf56a4e4c18821fa9afa7d5cb5609d");
       
       doTest("Shake 128 (256)",ALGORITHM_SHAKE, 128, 256, "The quick brown fox jumps over the lazy dog", "f4202e3c5852f9182a0430fd8144f0a74b95e7417ecae17db0f8cfeed0e3e66e");
       doTest("Shake 128 (256) Cascade",ALGORITHM_SHAKE, 128, 256, "The quick brown fox jumps over the lazy dog.", "634069e6b13c3af64c57f05babf5911b6acf1d309b9624fc92b0c0bd9f27f538");
       doTest("Shake 128 (256) Empty",ALGORITHM_SHAKE, 128, 256, "", "7f9c2ba4e88f827d616045507605853ed73b8093f6efbc88eb1a6eacfa66ef26");
       doTest("Shake 128 (256) Unicode",ALGORITHM_SHAKE, 128, 256, "中文", "d001a1cbe144d95604a9483407bdfbe078421a5f5a91a3de3465182cd11df868");
       
       llOwnerSay("("+(string)passed+"/"+(string)total+") tests passed");
       
   }

}

</lsl>