Line   1:/* C# SHA3 Implementation                                                                                                                          
Line   2: * Chris Lomont, Oct 2012                                                                                                                          
Line   3: * Version 1.0                                                                                                                                     
Line   4: *                                                                                                                                                 
Line   5:The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,                                                                                
Line   6:Michaël Peeters and Gilles Van Assche. For more information, feedback or                                                                           
Line   7:questions, please refer to our website: http://keccak.noekeon.org/                                                                                 
Line   8:                                                                                                                                                   
Line   9:Implementation by the designers, hereby denoted as "the implementer".                                                                              
Line  10:                                                                                                                                                   
Line  11:To the extent possible under law, the implementer has waived all copyright                                                                         
Line  12:and related or neighboring rights to the source code in this file.                                                                                 
Line  13:http://creativecommons.org/publicdomain/zero/1.0/                                                                                                  
Line  14:                                                                                                                                                   
Line  15:C# translation and improvement by Chris Lomont, 2012, http://www.lomont.org                                                                        
Line  16:                                                                                                                                                   
Line  17:To the extent possible under law, the Chris Lomont has waived all copyright                                                                        
Line  18:and related or neighboring rights to the source code in this file.                                                                                 
Line  19:http://creativecommons.org/publicdomain/zero/1.0/                                                                                                  
Line  20:                                                                                                                                                   
Line  21:*/                                                                                                                                                 
Line  22:                                                                                                                                                   
Line  23:/* TODO                                                                                                                                            
Line  24: * - update comments                                                                                                                               
Line  25: * - usage example in code                                                                                                                         
Line  26: *                                                                                                                                                 
Line  27: * Improvements                                                                                                                                    
Line  28: * - types made restrictive, bool, etc                                                                                                             
Line  29: * - sizes and signed/unsigned cleaned and made consistent                                                                                         
Line  30:  */                                                                                                                                               
Line  31:using System;                                                                                                                                      
Line  32:using System.Diagnostics;                                                                                                                          
Line  33:using System.Security.Cryptography;                                                                                                                
Line  34:                                                                                                                                                   
Line  35:namespace Lomont.Security.Cryptography                                                                                                             
Line  36:{                                                                                                                                                  
Line  37:    /// <summary>                                                                                                                                  
Line  38:    /// Class to perform SHA-3 hashing                                                                                                             
Line  39:    /// </summary>                                                                                                                                 
Line  40:    public sealed class SHA3 : HashAlgorithm                                                                                                       
Line  41:    {                                                                                                                                              
Line  42:                                                                                                                                                   
Line  43:        #region Public Interface                                                                                                                   
Line  44:                                                                                                                                                   
Line  45:        /// <summary>                                                                                                                              
Line  46:        /// Return values from some hash functions                                                                                                 
Line  47:        /// </summary>                                                                                                                             
Line  48:        public enum HashReturn                                                                                                                     
Line  49:        {                                                                                                                                          
Line  50:            Success = 0,                                                                                                                           
Line  51:            Fail = 1,                                                                                                                              
Line  52:            BadHashLength = 2                                                                                                                      
Line  53:        }                                                                                                                                          
Line  54:                                                                                                                                                   
Line  55:        /// <summary>                                                                                                                              
Line  56:        /// This calue controls the amount of loop unrolling used                                                                                  
Line  57:        /// It must be a positive integer dividing 24                                                                                              
Line  58:        /// </summary>                                                                                                                             
Line  59:        public int Unrolling                                                                                                                       
Line  60:        {                                                                                                                                          
Line  61:            get { return unrolling; }                                                                                                              
Line  62:            set                                                                                                                                    
Line  63:            {                                                                                                                                      
Line  64:                if ((value <= 0) || ((24%value) != 0))                                                                                             
Line  65:                    throw new ArgumentException("Unrolling is not correctly specified!");                                                          
Line  66:                unrolling = value;                                                                                                                 
Line  67:            }                                                                                                                                      
Line  68:        }                                                                                                                                          
Line  69:                                                                                                                                                   
Line  70:        private int unrolling = 24;                                                                                                                
Line  71:                                                                                                                                                   
Line  72:        /// <summary>                                                                                                                              
Line  73:        /// initialize the SHA3 object by setting the Keccak[r, c] sponge function.                                                                
Line  74:        /// </summary>                                                                                                                             
Line  75:        /// <param name="rate">The value of the rate r.</param>                                                                                    
Line  76:        /// <param name="capacity">The value of the capacity c.</param>                                                                            
Line  77:        /// <remarks>                                                                                                                              
Line  78:        /// One must have r+c=1600 and the rate a multiple of 64 bits in this implementation.                                                      
Line  79:        /// Throws an ArgumentException on invalid parameters.                                                                                     
Line  80:        /// </remarks>                                                                                                                             
Line  81:        public SHA3(int rate, int capacity)                                                                                                        
Line  82:        {                                                                                                                                          
Line  83:            Unrolling = 24;                                                                                                                        
Line  84:            if (!InitSponge(rate, capacity))                                                                                                       
Line  85:                throw new ArgumentException("SHA3 constructor failed");                                                                            
Line  86:        }                                                                                                                                          
Line  87:                                                                                                                                                   
Line  88:        /// <summary>                                                                                                                              
Line  89:        /// initialize the SHA3 object by setting the Keccak[r, c] sponge function.                                                                
Line  90:        /// </summary>                                                                                                                             
Line  91:        /// <param name="hashBitLength">The desired number of output bits,                                                                         
Line  92:        /// or 0 for Keccak[] with default parameters and arbitrarily-long output                                                                  
Line  93:        /// </param>                                                                                                                               
Line  94:        /// <remarks>                                                                                                                              
Line  95:        /// The value of hashbitlen must 1 one of 0, 224, 256, 384 and 512.                                                                        
Line  96:        /// Throws on invalid parameters                                                                                                           
Line  97:        /// </remarks>                                                                                                                             
Line  98:        public SHA3(int hashBitLength = 0)                                                                                                         
Line  99:        {                                                                                                                                          
Line 100:            Unrolling = 24;                                                                                                                        
Line 101:            var result = Init(hashBitLength);                                                                                                      
Line 102:            if (result == HashReturn.BadHashLength)                                                                                                
Line 103:                throw new Exception("Invalid hash length in SHA3 constructor");                                                                    
Line 104:            if (result == HashReturn.Fail)                                                                                                         
Line 105:                throw new Exception("SHA3 constructor failed");                                                                                    
Line 106:        }                                                                                                                                          
Line 107:                                                                                                                                                   
Line 108:        /// <summary>                                                                                                                              
Line 109:        /// Add some data to the internal hash instate                                                                                             
Line 110:        /// </summary>                                                                                                                             
Line 111:        /// <param name="data">The data bits to add</param>                                                                                        
Line 112:        /// <param name="dataBitLength">The number of input bits provided in the input data.</param>                                               
Line 113:        /// <returns></returns>                                                                                                                    
Line 114:        /// <remarks>                                                                                                                              
Line 115:        /// When databitlen is not a multiple of 8, the last bits                                                                                  
Line 116:        /// of data must 1 in the most significant bits of the last byte.                                                                          
Line 117:        /// All calls must have databitlen a multiple of 8 except at most the last one.                                                            
Line 118:        /// Leaving dataBitLength = Int64.MaxValue uses the length of the data array                                                               
Line 119:        /// </remarks>                                                                                                                             
Line 120:        public HashReturn Update(byte[] data, long dataBitLength = Int64.MaxValue)                                                                 
Line 121:        {                                                                                                                                          
Line 122:            if (dataBitLength == Int64.MaxValue)                                                                                                   
Line 123:                dataBitLength = data.Length*8;                                                                                                     
Line 124:            if ((dataBitLength%8) == 0)                                                                                                            
Line 125:                return Absorb(data, dataBitLength) ? HashReturn.Success : HashReturn.Fail;                                                         
Line 126:            if (Absorb(data, dataBitLength - (dataBitLength%8)))                                                                                   
Line 127:            {                                                                                                                                      
Line 128:                // Align the last partial byte to the least significant bits                                                                       
Line 129:                var lastByte = (byte) (data[dataBitLength/8] >> (8 - (int) (dataBitLength%8)));                                                    
Line 130:                return Absorb(new[] {lastByte}, dataBitLength%8) ? HashReturn.Success : HashReturn.Fail;                                           
Line 131:            }                                                                                                                                      
Line 132:            return HashReturn.Fail;                                                                                                                
Line 133:        }                                                                                                                                          
Line 134:                                                                                                                                                   
Line 135:                                                                                                                                                   
Line 136:        /// <summary>                                                                                                                              
Line 137:        /// Call this to obtain the final hash value.                                                                                              
Line 138:        /// If this object was created with a hash size, then hashval must 1 large enough to hold that many bits.                                  
Line 139:        /// If this object was created with a rate and capacity, then hashval must hold capacity bits.                                             
Line 140:        /// If this object was created with a 0 hashsize, then hashval will 1 filled with hashed bytes.                                            
Line 141:        /// </summary>                                                                                                                             
Line 142:        /// <param name="hashval"></param>                                                                                                         
Line 143:        /// <returns></returns>                                                                                                                    
Line 144:        public HashReturn Final(byte[] hashval)                                                                                                    
Line 145:        {                                                                                                                                          
Line 146:            if (sponge.FixedOutputLength != 0)                                                                                                     
Line 147:                return Squeeze(hashval, sponge.FixedOutputLength) ? HashReturn.Success : HashReturn.Fail;                                          
Line 148:            return Squeeze(hashval, hashval.Length*8) ? HashReturn.Success : HashReturn.Fail;                                                      
Line 149:        }                                                                                                                                          
Line 150:                                                                                                                                                   
Line 151:        /// <summary>                                                                                                                              
Line 152:        /// Function to compute a hash all in one pass.                                                                                            
Line 153:        /// The value of hashbitlen must 1 one of 0, 224, 256, 384 and 512.                                                                        
Line 154:        /// </summary>                                                                                                                             
Line 155:        /// <param name="hashbitlen">The hash length in bits</param>                                                                               
Line 156:        /// <param name="data">The data to hash.</param>                                                                                           
Line 157:        /// <param name="databitlen">The number of bits to hash from data</param>                                                                  
Line 158:        /// <param name="hashval">the output hash value</param>                                                                                    
Line 159:        /// <returns></returns>                                                                                                                    
Line 160:        public HashReturn HashData(int hashbitlen, byte[] data, long databitlen, byte[] hashval)                                                   
Line 161:        {                                                                                                                                          
Line 162:            if ((hashbitlen != 224) && (hashbitlen != 256) && (hashbitlen != 384) && (hashbitlen != 512))                                          
Line 163:                return HashReturn.BadHashLength; // Only the four fixed output lengths available through this API                                  
Line 164:            var result = Init(hashbitlen);                                                                                                         
Line 165:            if (result != HashReturn.Success)                                                                                                      
Line 166:                return result;                                                                                                                     
Line 167:            result = Update(data, databitlen);                                                                                                     
Line 168:            if (result != HashReturn.Success)                                                                                                      
Line 169:                return result;                                                                                                                     
Line 170:            result = Final(hashval);                                                                                                               
Line 171:            return result;                                                                                                                         
Line 172:        }                                                                                                                                          
Line 173:                                                                                                                                                   
Line 174:        #endregion                                                                                                                                 
Line 175:                                                                                                                                                   
Line 176:        #region Implementation                                                                                                                     
Line 177:                                                                                                                                                   
Line 178:        private const int PermutationSizeInBytes = (1600/8);                                                                                       
Line 179:        private const int MaximumRateInBytes = (1536/8);                                                                                           
Line 180:                                                                                                                                                   
Line 181:        /// <summary>                                                                                                                              
Line 182:        /// Function to initialize the instate of the Keccak[r, c] sponge function.                                                                
Line 183:        /// The sponge function is set to the absorbing phase.                                                                                     
Line 184:        /// </summary>                                                                                                                             
Line 185:        /// <param name="rate"></param>                                                                                                            
Line 186:        /// <param name="capacity"></param>                                                                                                        
Line 187:        /// <returns>true on success, else false</returns>                                                                                         
Line 188:        /// One must have r+c=1600 and the rate a multiple of 64 bits in this implementation.                                                      
Line 189:        private bool InitSponge(int rate, int capacity)                                                                                            
Line 190:        {                                                                                                                                          
Line 191:            sponge = new SpongeState();                                                                                                            
Line 192:            if (rate + capacity != 1600)                                                                                                           
Line 193:                return false;                                                                                                                      
Line 194:            if ((rate <= 0) || (rate >= 1600) || ((rate%64) != 0))                                                                                 
Line 195:                return false;                                                                                                                      
Line 196:            sponge.Rate = rate;                                                                                                                    
Line 197:            sponge.FixedOutputLength = 0;                                                                                                          
Line 198:            InitializeState(sponge.State);                                                                                                         
Line 199:            for (var i = 0; i < sponge.DataQueue.Length; ++i)                                                                                      
Line 200:                sponge.DataQueue[i] = 0;                                                                                                           
Line 201:            sponge.BitsInQueue = 0;                                                                                                                
Line 202:            sponge.Squeezing = false;                                                                                                              
Line 203:            sponge.BitsAvailableForSqueezing = 0;                                                                                                  
Line 204:                                                                                                                                                   
Line 205:            return true;                                                                                                                           
Line 206:        }                                                                                                                                          
Line 207:                                                                                                                                                   
Line 208:        /// <summary>                                                                                                                              
Line 209:        /// Function to initialize the instate of the Keccak[r, c] sponge function.                                                                
Line 210:        /// The value of hashbitlen must 1 one of 0, 224, 256, 384 and 512.                                                                        
Line 211:        /// </summary>                                                                                                                             
Line 212:        /// <param name="hashbitlen"></param>                                                                                                      
Line 213:        /// <returns> Success if successful, BadHashLength if the value of hashbitlen is incorrect</returns>                                       
Line 214:        private HashReturn Init(int hashbitlen)                                                                                                    
Line 215:        {                                                                                                                                          
Line 216:            switch (hashbitlen)                                                                                                                    
Line 217:            {                                                                                                                                      
Line 218:                case 0: // Default parameters, arbitrary length output                                                                             
Line 219:                    if (!InitSponge(1024, 576))                                                                                                    
Line 220:                        return HashReturn.Fail;                                                                                                    
Line 221:                    break;                                                                                                                         
Line 222:                case 224:                                                                                                                          
Line 223:                    if (!InitSponge(1152, 448))                                                                                                    
Line 224:                        return HashReturn.Fail;                                                                                                    
Line 225:                    break;                                                                                                                         
Line 226:                case 256:                                                                                                                          
Line 227:                    if (!InitSponge(1088, 512))                                                                                                    
Line 228:                        return HashReturn.Fail;                                                                                                    
Line 229:                    break;                                                                                                                         
Line 230:                case 384:                                                                                                                          
Line 231:                    if (!InitSponge(832, 768))                                                                                                     
Line 232:                        return HashReturn.Fail;                                                                                                    
Line 233:                    break;                                                                                                                         
Line 234:                case 512:                                                                                                                          
Line 235:                    if (!InitSponge(576, 1024))                                                                                                    
Line 236:                        return HashReturn.Fail;                                                                                                    
Line 237:                    break;                                                                                                                         
Line 238:                default:                                                                                                                           
Line 239:                    return HashReturn.BadHashLength;                                                                                               
Line 240:            }                                                                                                                                      
Line 241:            sponge.FixedOutputLength = hashbitlen;                                                                                                 
Line 242:            return HashReturn.Success;                                                                                                             
Line 243:        }                                                                                                                                          
Line 244:                                                                                                                                                   
Line 245:        /// <summary>                                                                                                                              
Line 246:        /// Store the sponge state                                                                                                                 
Line 247:        /// </summary>                                                                                                                             
Line 248:        private class SpongeState                                                                                                                  
Line 249:        {                                                                                                                                          
Line 250:            internal readonly byte[] State = new byte[PermutationSizeInBytes];                                                                     
Line 251:            internal readonly byte[] DataQueue = new byte[MaximumRateInBytes];                                                                     
Line 252:            internal int Rate;                                                                                                                     
Line 253:            internal int BitsInQueue;                                                                                                              
Line 254:            internal int FixedOutputLength;                                                                                                        
Line 255:            internal bool Squeezing;                                                                                                               
Line 256:            internal long BitsAvailableForSqueezing;                                                                                               
Line 257:        }                                                                                                                                          
Line 258:                                                                                                                                                   
Line 259:                                                                                                                                                   
Line 260:        private static ulong Rol64(ulong a, int offset)                                                                                            
Line 261:        {                                                                                                                                          
Line 262:            return (a << offset) ^ (a >> (64 - offset));                                                                                           
Line 263:        }                                                                                                                                          
Line 264:                                                                                                                                                   
Line 265:        // some global storage used in the permutation                                                                                             
Line 266:        private ulong bba, bbe, bbi, bbo, bbu;                                                                                                     
Line 267:        private ulong bga, bge, bgi, bgo, bgu;                                                                                                     
Line 268:        private ulong bka, bke, bki, bko, bku;                                                                                                     
Line 269:        private ulong bma, bme, bmi, bmo, bmu;                                                                                                     
Line 270:        private ulong bsa, bse, bsi, bso, bsu;                                                                                                     
Line 271:        private ulong ca, ce, ci, co, cu;                                                                                                          
Line 272:        private ulong da, de, di, Do, du;                                                                                                          
Line 273:        private ulong[] temp1 = new ulong[25];                                                                                                     
Line 274:        private ulong[] temp2 = new ulong[25];                                                                                                     
Line 275:                                                                                                                                                   
Line 276:        private void PrepareTheta()                                                                                                                
Line 277:        {                                                                                                                                          
Line 278:            ca = temp1[0] ^ temp1[5] ^ temp1[10] ^ temp1[15] ^ temp1[20];                                                                          
Line 279:            ce = temp1[1] ^ temp1[6] ^ temp1[11] ^ temp1[16] ^ temp1[21];                                                                          
Line 280:            ci = temp1[2] ^ temp1[7] ^ temp1[12] ^ temp1[17] ^ temp1[22];                                                                          
Line 281:            co = temp1[3] ^ temp1[8] ^ temp1[13] ^ temp1[18] ^ temp1[23];                                                                          
Line 282:            cu = temp1[4] ^ temp1[9] ^ temp1[14] ^ temp1[19] ^ temp1[24];                                                                          
Line 283:        }                                                                                                                                          
Line 284:                                                                                                                                                   
Line 285:        // --- Code for round, with prepare-theta (lane complementing pattern 'bebigokimisa')                                                      
Line 286:        // --- 64-bit lanes mapped to 64-bit words                                                                                                 
Line 287:        private void ThetaRhoPiChiIotaPrepareTheta(int i, ulong[] a, ulong[] e)                                                                    
Line 288:        {                                                                                                                                          
Line 289:            da = cu ^ Rol64(ce, 1);                                                                                                                
Line 290:            de = ca ^ Rol64(ci, 1);                                                                                                                
Line 291:            di = ce ^ Rol64(co, 1);                                                                                                                
Line 292:            Do = ci ^ Rol64(cu, 1);                                                                                                                
Line 293:            du = co ^ Rol64(ca, 1);                                                                                                                
Line 294:                                                                                                                                                   
Line 295:            a[0] ^= da;                                                                                                                            
Line 296:            bba = a[0];                                                                                                                            
Line 297:            a[6] ^= de;                                                                                                                            
Line 298:            bbe = Rol64(a[6], 44);                                                                                                                 
Line 299:            a[12] ^= di;                                                                                                                           
Line 300:            bbi = Rol64(a[12], 43);                                                                                                                
Line 301:            a[18] ^= Do;                                                                                                                           
Line 302:            bbo = Rol64(a[18], 21);                                                                                                                
Line 303:            a[24] ^= du;                                                                                                                           
Line 304:            bbu = Rol64(a[24], 14);                                                                                                                
Line 305:            e[0] = bba ^ (bbe | bbi);                                                                                                              
Line 306:            e[0] ^= roundConstants[i];                                                                                                             
Line 307:            ca = e[0];                                                                                                                             
Line 308:            e[1] = bbe ^ ((~bbi) | bbo);                                                                                                           
Line 309:            ce = e[1];                                                                                                                             
Line 310:            e[2] = bbi ^ (bbo & bbu);                                                                                                              
Line 311:            ci = e[2];                                                                                                                             
Line 312:            e[3] = bbo ^ (bbu | bba);                                                                                                              
Line 313:            co = e[3];                                                                                                                             
Line 314:            e[4] = bbu ^ (bba & bbe);                                                                                                              
Line 315:            cu = e[4];                                                                                                                             
Line 316:                                                                                                                                                   
Line 317:            a[3] ^= Do;                                                                                                                            
Line 318:            bga = Rol64(a[3], 28);                                                                                                                 
Line 319:            a[9] ^= du;                                                                                                                            
Line 320:            bge = Rol64(a[9], 20);                                                                                                                 
Line 321:            a[10] ^= da;                                                                                                                           
Line 322:            bgi = Rol64(a[10], 3);                                                                                                                 
Line 323:            a[16] ^= de;                                                                                                                           
Line 324:            bgo = Rol64(a[16], 45);                                                                                                                
Line 325:            a[22] ^= di;                                                                                                                           
Line 326:            bgu = Rol64(a[22], 61);                                                                                                                
Line 327:            e[5] = bga ^ (bge | bgi);                                                                                                              
Line 328:            ca ^= e[5];                                                                                                                            
Line 329:            e[6] = bge ^ (bgi & bgo);                                                                                                              
Line 330:            ce ^= e[6];                                                                                                                            
Line 331:            e[7] = bgi ^ (bgo | (~bgu));                                                                                                           
Line 332:            ci ^= e[7];                                                                                                                            
Line 333:            e[8] = bgo ^ (bgu | bga);                                                                                                              
Line 334:            co ^= e[8];                                                                                                                            
Line 335:            e[9] = bgu ^ (bga & bge);                                                                                                              
Line 336:            cu ^= e[9];                                                                                                                            
Line 337:                                                                                                                                                   
Line 338:            a[1] ^= de;                                                                                                                            
Line 339:            bka = Rol64(a[1], 1);                                                                                                                  
Line 340:            a[7] ^= di;                                                                                                                            
Line 341:            bke = Rol64(a[7], 6);                                                                                                                  
Line 342:            a[13] ^= Do;                                                                                                                           
Line 343:            bki = Rol64(a[13], 25);                                                                                                                
Line 344:            a[19] ^= du;                                                                                                                           
Line 345:            bko = Rol64(a[19], 8);                                                                                                                 
Line 346:            a[20] ^= da;                                                                                                                           
Line 347:            bku = Rol64(a[20], 18);                                                                                                                
Line 348:            e[10] = bka ^ (bke | bki);                                                                                                             
Line 349:            ca ^= e[10];                                                                                                                           
Line 350:            e[11] = bke ^ (bki & bko);                                                                                                             
Line 351:            ce ^= e[11];                                                                                                                           
Line 352:            e[12] = bki ^ ((~bko) & bku);                                                                                                          
Line 353:            ci ^= e[12];                                                                                                                           
Line 354:            e[13] = (~bko) ^ (bku | bka);                                                                                                          
Line 355:            co ^= e[13];                                                                                                                           
Line 356:            e[14] = bku ^ (bka & bke);                                                                                                             
Line 357:            cu ^= e[14];                                                                                                                           
Line 358:                                                                                                                                                   
Line 359:            a[4] ^= du;                                                                                                                            
Line 360:            bma = Rol64(a[4], 27);                                                                                                                 
Line 361:            a[5] ^= da;                                                                                                                            
Line 362:            bme = Rol64(a[5], 36);                                                                                                                 
Line 363:            a[11] ^= de;                                                                                                                           
Line 364:            bmi = Rol64(a[11], 10);                                                                                                                
Line 365:            a[17] ^= di;                                                                                                                           
Line 366:            bmo = Rol64(a[17], 15);                                                                                                                
Line 367:            a[23] ^= Do;                                                                                                                           
Line 368:            bmu = Rol64(a[23], 56);                                                                                                                
Line 369:            e[15] = bma ^ (bme & bmi);                                                                                                             
Line 370:            ca ^= e[15];                                                                                                                           
Line 371:            e[16] = bme ^ (bmi | bmo);                                                                                                             
Line 372:            ce ^= e[16];                                                                                                                           
Line 373:            e[17] = bmi ^ ((~bmo) | bmu);                                                                                                          
Line 374:            ci ^= e[17];                                                                                                                           
Line 375:            e[18] = (~bmo) ^ (bmu & bma);                                                                                                          
Line 376:            co ^= e[18];                                                                                                                           
Line 377:            e[19] = bmu ^ (bma | bme);                                                                                                             
Line 378:            cu ^= e[19];                                                                                                                           
Line 379:                                                                                                                                                   
Line 380:            a[2] ^= di;                                                                                                                            
Line 381:            bsa = Rol64(a[2], 62);                                                                                                                 
Line 382:            a[8] ^= Do;                                                                                                                            
Line 383:            bse = Rol64(a[8], 55);                                                                                                                 
Line 384:            a[14] ^= du;                                                                                                                           
Line 385:            bsi = Rol64(a[14], 39);                                                                                                                
Line 386:            a[15] ^= da;                                                                                                                           
Line 387:            bso = Rol64(a[15], 41);                                                                                                                
Line 388:            a[21] ^= de;                                                                                                                           
Line 389:            bsu = Rol64(a[21], 2);                                                                                                                 
Line 390:            e[20] = bsa ^ ((~bse) & bsi);                                                                                                          
Line 391:            ca ^= e[20];                                                                                                                           
Line 392:            e[21] = (~bse) ^ (bsi | bso);                                                                                                          
Line 393:            ce ^= e[21];                                                                                                                           
Line 394:            e[22] = bsi ^ (bso & bsu);                                                                                                             
Line 395:            ci ^= e[22];                                                                                                                           
Line 396:            e[23] = bso ^ (bsu | bsa);                                                                                                             
Line 397:            co ^= e[23];                                                                                                                           
Line 398:            e[24] = bsu ^ (bsa & bse);                                                                                                             
Line 399:            cu ^= e[24];                                                                                                                           
Line 400:        }                                                                                                                                          
Line 401:                                                                                                                                                   
Line 402:        // --- Code for round (lane complementing pattern 'bebigokimisa')                                                                          
Line 403:        // --- 64-bit lanes mapped to 64-bit words                                                                                                 
Line 404:        private void ThetaRhoPiChiIota(int i, ulong[] a, ulong[] e)                                                                                
Line 405:        {                                                                                                                                          
Line 406:            da = cu ^ Rol64(ce, 1);                                                                                                                
Line 407:            de = ca ^ Rol64(ci, 1);                                                                                                                
Line 408:            di = ce ^ Rol64(co, 1);                                                                                                                
Line 409:            Do = ci ^ Rol64(cu, 1);                                                                                                                
Line 410:            du = co ^ Rol64(ca, 1);                                                                                                                
Line 411:                                                                                                                                                   
Line 412:            a[0] ^= da;                                                                                                                            
Line 413:            bba = a[0];                                                                                                                            
Line 414:            a[6] ^= de;                                                                                                                            
Line 415:            bbe = Rol64(a[6], 44);                                                                                                                 
Line 416:            a[12] ^= di;                                                                                                                           
Line 417:            bbi = Rol64(a[12], 43);                                                                                                                
Line 418:            a[18] ^= Do;                                                                                                                           
Line 419:            bbo = Rol64(a[18], 21);                                                                                                                
Line 420:            a[24] ^= du;                                                                                                                           
Line 421:            bbu = Rol64(a[24], 14);                                                                                                                
Line 422:            e[0] = bba ^ (bbe | bbi);                                                                                                              
Line 423:            e[0] ^= roundConstants[i];                                                                                                             
Line 424:            e[1] = bbe ^ ((~bbi) | bbo);                                                                                                           
Line 425:            e[2] = bbi ^ (bbo & bbu);                                                                                                              
Line 426:            e[3] = bbo ^ (bbu | bba);                                                                                                              
Line 427:            e[4] = bbu ^ (bba & bbe);                                                                                                              
Line 428:                                                                                                                                                   
Line 429:            a[3] ^= Do;                                                                                                                            
Line 430:            bga = Rol64(a[3], 28);                                                                                                                 
Line 431:            a[9] ^= du;                                                                                                                            
Line 432:            bge = Rol64(a[9], 20);                                                                                                                 
Line 433:            a[10] ^= da;                                                                                                                           
Line 434:            bgi = Rol64(a[10], 3);                                                                                                                 
Line 435:            a[16] ^= de;                                                                                                                           
Line 436:            bgo = Rol64(a[16], 45);                                                                                                                
Line 437:            a[22] ^= di;                                                                                                                           
Line 438:            bgu = Rol64(a[22], 61);                                                                                                                
Line 439:            e[5] = bga ^ (bge | bgi);                                                                                                              
Line 440:            e[6] = bge ^ (bgi & bgo);                                                                                                              
Line 441:            e[7] = bgi ^ (bgo | (~bgu));                                                                                                           
Line 442:            e[8] = bgo ^ (bgu | bga);                                                                                                              
Line 443:            e[9] = bgu ^ (bga & bge);                                                                                                              
Line 444:                                                                                                                                                   
Line 445:            a[1] ^= de;                                                                                                                            
Line 446:            bka = Rol64(a[1], 1);                                                                                                                  
Line 447:            a[7] ^= di;                                                                                                                            
Line 448:            bke = Rol64(a[7], 6);                                                                                                                  
Line 449:            a[13] ^= Do;                                                                                                                           
Line 450:            bki = Rol64(a[13], 25);                                                                                                                
Line 451:            a[19] ^= du;                                                                                                                           
Line 452:            bko = Rol64(a[19], 8);                                                                                                                 
Line 453:            a[20] ^= da;                                                                                                                           
Line 454:            bku = Rol64(a[20], 18);                                                                                                                
Line 455:            e[10] = bka ^ (bke | bki);                                                                                                             
Line 456:            e[11] = bke ^ (bki & bko);                                                                                                             
Line 457:            e[12] = bki ^ ((~bko) & bku);                                                                                                          
Line 458:            e[13] = (~bko) ^ (bku | bka);                                                                                                          
Line 459:            e[14] = bku ^ (bka & bke);                                                                                                             
Line 460:                                                                                                                                                   
Line 461:            a[4] ^= du;                                                                                                                            
Line 462:            bma = Rol64(a[4], 27);                                                                                                                 
Line 463:            a[5] ^= da;                                                                                                                            
Line 464:            bme = Rol64(a[5], 36);                                                                                                                 
Line 465:            a[11] ^= de;                                                                                                                           
Line 466:            bmi = Rol64(a[11], 10);                                                                                                                
Line 467:            a[17] ^= di;                                                                                                                           
Line 468:            bmo = Rol64(a[17], 15);                                                                                                                
Line 469:            a[23] ^= Do;                                                                                                                           
Line 470:            bmu = Rol64(a[23], 56);                                                                                                                
Line 471:            e[15] = bma ^ (bme & bmi);                                                                                                             
Line 472:            e[16] = bme ^ (bmi | bmo);                                                                                                             
Line 473:            e[17] = bmi ^ ((~bmo) | bmu);                                                                                                          
Line 474:            e[18] = (~bmo) ^ (bmu & bma);                                                                                                          
Line 475:            e[19] = bmu ^ (bma | bme);                                                                                                             
Line 476:                                                                                                                                                   
Line 477:            a[2] ^= di;                                                                                                                            
Line 478:            bsa = Rol64(a[2], 62);                                                                                                                 
Line 479:            a[8] ^= Do;                                                                                                                            
Line 480:            bse = Rol64(a[8], 55);                                                                                                                 
Line 481:            a[14] ^= du;                                                                                                                           
Line 482:            bsi = Rol64(a[14], 39);                                                                                                                
Line 483:            a[15] ^= da;                                                                                                                           
Line 484:            bso = Rol64(a[15], 41);                                                                                                                
Line 485:            a[21] ^= de;                                                                                                                           
Line 486:            bsu = Rol64(a[21], 2);                                                                                                                 
Line 487:            e[20] = bsa ^ ((~bse) & bsi);                                                                                                          
Line 488:            e[21] = (~bse) ^ (bsi | bso);                                                                                                          
Line 489:            e[22] = bsi ^ (bso & bsu);                                                                                                             
Line 490:            e[23] = bso ^ (bsu | bsa);                                                                                                             
Line 491:            e[24] = bsu ^ (bsa & bse);                                                                                                             
Line 492:        }                                                                                                                                          
Line 493:                                                                                                                                                   
Line 494:        private static readonly ulong[] roundConstants =                                                                                           
Line 495:            {                                                                                                                                      
Line 496:                0x0000000000000001UL,                                                                                                              
Line 497:                0x0000000000008082UL,                                                                                                              
Line 498:                0x800000000000808aUL,                                                                                                              
Line 499:                0x8000000080008000UL,                                                                                                              
Line 500:                0x000000000000808bUL,                                                                                                              
Line 501:                0x0000000080000001UL,                                                                                                              
Line 502:                0x8000000080008081UL,                                                                                                              
Line 503:                0x8000000000008009UL,                                                                                                              
Line 504:                0x000000000000008aUL,                                                                                                              
Line 505:                0x0000000000000088UL,                                                                                                              
Line 506:                0x0000000080008009UL,                                                                                                              
Line 507:                0x000000008000000aUL,                                                                                                              
Line 508:                0x000000008000808bUL,                                                                                                              
Line 509:                0x800000000000008bUL,                                                                                                              
Line 510:                0x8000000000008089UL,                                                                                                              
Line 511:                0x8000000000008003UL,                                                                                                              
Line 512:                0x8000000000008002UL,                                                                                                              
Line 513:                0x8000000000000080UL,                                                                                                              
Line 514:                0x000000000000800aUL,                                                                                                              
Line 515:                0x800000008000000aUL,                                                                                                              
Line 516:                0x8000000080008081UL,                                                                                                              
Line 517:                0x8000000000008080UL,                                                                                                              
Line 518:                0x0000000080000001UL,                                                                                                              
Line 519:                0x8000000080008008UL                                                                                                               
Line 520:            };                                                                                                                                     
Line 521:                                                                                                                                                   
Line 522:        private void SwapTempVariables()                                                                                                           
Line 523:        {                                                                                                                                          
Line 524:            var t = temp1;                                                                                                                         
Line 525:            temp1 = temp2;                                                                                                                         
Line 526:            temp2 = t;                                                                                                                             
Line 527:        }                                                                                                                                          
Line 528:                                                                                                                                                   
Line 529:        /// <summary>                                                                                                                              
Line 530:        /// Perform 24 rounds of the permutation on the temp1                                                                                      
Line 531:        /// </summary>                                                                                                                             
Line 532:        private void Rounds()                                                                                                                      
Line 533:        {                                                                                                                                          
Line 534:            PrepareTheta();                                                                                                                        
Line 535:            switch (Unrolling)                                                                                                                     
Line 536:            {                                                                                                                                      
Line 537:                case 24:                                                                                                                           
Line 538:                    ThetaRhoPiChiIotaPrepareTheta(0, temp1, temp2);                                                                                
Line 539:                    ThetaRhoPiChiIotaPrepareTheta(1, temp2, temp1);                                                                                
Line 540:                    ThetaRhoPiChiIotaPrepareTheta(2, temp1, temp2);                                                                                
Line 541:                    ThetaRhoPiChiIotaPrepareTheta(3, temp2, temp1);                                                                                
Line 542:                    ThetaRhoPiChiIotaPrepareTheta(4, temp1, temp2);                                                                                
Line 543:                    ThetaRhoPiChiIotaPrepareTheta(5, temp2, temp1);                                                                                
Line 544:                    ThetaRhoPiChiIotaPrepareTheta(6, temp1, temp2);                                                                                
Line 545:                    ThetaRhoPiChiIotaPrepareTheta(7, temp2, temp1);                                                                                
Line 546:                    ThetaRhoPiChiIotaPrepareTheta(8, temp1, temp2);                                                                                
Line 547:                    ThetaRhoPiChiIotaPrepareTheta(9, temp2, temp1);                                                                                
Line 548:                    ThetaRhoPiChiIotaPrepareTheta(10, temp1, temp2);                                                                               
Line 549:                    ThetaRhoPiChiIotaPrepareTheta(11, temp2, temp1);                                                                               
Line 550:                    ThetaRhoPiChiIotaPrepareTheta(12, temp1, temp2);                                                                               
Line 551:                    ThetaRhoPiChiIotaPrepareTheta(13, temp2, temp1);                                                                               
Line 552:                    ThetaRhoPiChiIotaPrepareTheta(14, temp1, temp2);                                                                               
Line 553:                    ThetaRhoPiChiIotaPrepareTheta(15, temp2, temp1);                                                                               
Line 554:                    ThetaRhoPiChiIotaPrepareTheta(16, temp1, temp2);                                                                               
Line 555:                    ThetaRhoPiChiIotaPrepareTheta(17, temp2, temp1);                                                                               
Line 556:                    ThetaRhoPiChiIotaPrepareTheta(18, temp1, temp2);                                                                               
Line 557:                    ThetaRhoPiChiIotaPrepareTheta(19, temp2, temp1);                                                                               
Line 558:                    ThetaRhoPiChiIotaPrepareTheta(20, temp1, temp2);                                                                               
Line 559:                    ThetaRhoPiChiIotaPrepareTheta(21, temp2, temp1);                                                                               
Line 560:                    ThetaRhoPiChiIotaPrepareTheta(22, temp1, temp2);                                                                               
Line 561:                    ThetaRhoPiChiIota(23, temp2, temp1);                                                                                           
Line 562:                    break;                                                                                                                         
Line 563:                case 12:                                                                                                                           
Line 564:                    for (var i = 0; i < 24; i += 12)                                                                                               
Line 565:                    {                                                                                                                              
Line 566:                        ThetaRhoPiChiIotaPrepareTheta(i, temp1, temp2);                                                                            
Line 567:                        ThetaRhoPiChiIotaPrepareTheta(i + 1, temp2, temp1);                                                                        
Line 568:                        ThetaRhoPiChiIotaPrepareTheta(i + 2, temp1, temp2);                                                                        
Line 569:                        ThetaRhoPiChiIotaPrepareTheta(i + 3, temp2, temp1);                                                                        
Line 570:                        ThetaRhoPiChiIotaPrepareTheta(i + 4, temp1, temp2);                                                                        
Line 571:                        ThetaRhoPiChiIotaPrepareTheta(i + 5, temp2, temp1);                                                                        
Line 572:                        ThetaRhoPiChiIotaPrepareTheta(i + 6, temp1, temp2);                                                                        
Line 573:                        ThetaRhoPiChiIotaPrepareTheta(i + 7, temp2, temp1);                                                                        
Line 574:                        ThetaRhoPiChiIotaPrepareTheta(i + 8, temp1, temp2);                                                                        
Line 575:                        ThetaRhoPiChiIotaPrepareTheta(i + 9, temp2, temp1);                                                                        
Line 576:                        ThetaRhoPiChiIotaPrepareTheta(i + 10, temp1, temp2);                                                                       
Line 577:                        ThetaRhoPiChiIotaPrepareTheta(i + 11, temp2, temp1);                                                                       
Line 578:                    }                                                                                                                              
Line 579:                    break;                                                                                                                         
Line 580:                case 8:                                                                                                                            
Line 581:                    for (var i = 0; i < 24; i += 8)                                                                                                
Line 582:                    {                                                                                                                              
Line 583:                        ThetaRhoPiChiIotaPrepareTheta(i, temp1, temp2);                                                                            
Line 584:                        ThetaRhoPiChiIotaPrepareTheta(i + 1, temp2, temp1);                                                                        
Line 585:                        ThetaRhoPiChiIotaPrepareTheta(i + 2, temp1, temp2);                                                                        
Line 586:                        ThetaRhoPiChiIotaPrepareTheta(i + 3, temp2, temp1);                                                                        
Line 587:                        ThetaRhoPiChiIotaPrepareTheta(i + 4, temp1, temp2);                                                                        
Line 588:                        ThetaRhoPiChiIotaPrepareTheta(i + 5, temp2, temp1);                                                                        
Line 589:                        ThetaRhoPiChiIotaPrepareTheta(i + 6, temp1, temp2);                                                                        
Line 590:                        ThetaRhoPiChiIotaPrepareTheta(i + 7, temp2, temp1);                                                                        
Line 591:                    }                                                                                                                              
Line 592:                    break;                                                                                                                         
Line 593:                case 6:                                                                                                                            
Line 594:                    for (var i = 0; i < 24; i += 6)                                                                                                
Line 595:                    {                                                                                                                              
Line 596:                        ThetaRhoPiChiIotaPrepareTheta(i, temp1, temp2);                                                                            
Line 597:                        ThetaRhoPiChiIotaPrepareTheta(i + 1, temp2, temp1);                                                                        
Line 598:                        ThetaRhoPiChiIotaPrepareTheta(i + 2, temp1, temp2);                                                                        
Line 599:                        ThetaRhoPiChiIotaPrepareTheta(i + 3, temp2, temp1);                                                                        
Line 600:                        ThetaRhoPiChiIotaPrepareTheta(i + 4, temp1, temp2);                                                                        
Line 601:                        ThetaRhoPiChiIotaPrepareTheta(i + 5, temp2, temp1);                                                                        
Line 602:                    }                                                                                                                              
Line 603:                    break;                                                                                                                         
Line 604:                case 4:                                                                                                                            
Line 605:                    for (var i = 0; i < 24; i += 4)                                                                                                
Line 606:                    {                                                                                                                              
Line 607:                        ThetaRhoPiChiIotaPrepareTheta(i, temp1, temp2);                                                                            
Line 608:                        ThetaRhoPiChiIotaPrepareTheta(i + 1, temp2, temp1);                                                                        
Line 609:                        ThetaRhoPiChiIotaPrepareTheta(i + 2, temp1, temp2);                                                                        
Line 610:                        ThetaRhoPiChiIotaPrepareTheta(i + 3, temp2, temp1);                                                                        
Line 611:                    }                                                                                                                              
Line 612:                    break;                                                                                                                         
Line 613:                case 3:                                                                                                                            
Line 614:                    for (var i = 0; i < 24; i += 3)                                                                                                
Line 615:                    {                                                                                                                              
Line 616:                        ThetaRhoPiChiIotaPrepareTheta(i, temp1, temp2);                                                                            
Line 617:                        ThetaRhoPiChiIotaPrepareTheta(i + 1, temp2, temp1);                                                                        
Line 618:                        ThetaRhoPiChiIotaPrepareTheta(i + 2, temp1, temp2);                                                                        
Line 619:                        SwapTempVariables();                                                                                                       
Line 620:                    }                                                                                                                              
Line 621:                    break;                                                                                                                         
Line 622:                case 2:                                                                                                                            
Line 623:                    for (var i = 0; i < 24; i += 2)                                                                                                
Line 624:                    {                                                                                                                              
Line 625:                        ThetaRhoPiChiIotaPrepareTheta(i, temp1, temp2);                                                                            
Line 626:                        ThetaRhoPiChiIotaPrepareTheta(i + 1, temp2, temp1);                                                                        
Line 627:                    }                                                                                                                              
Line 628:                    break;                                                                                                                         
Line 629:                case 1:                                                                                                                            
Line 630:                    for (var i = 0; i < 24; i++)                                                                                                   
Line 631:                    {                                                                                                                              
Line 632:                        ThetaRhoPiChiIotaPrepareTheta(i, temp1, temp2);                                                                            
Line 633:                        SwapTempVariables();                                                                                                       
Line 634:                    }                                                                                                                              
Line 635:                    break;                                                                                                                         
Line 636:            }                                                                                                                                      
Line 637:        }                                                                                                                                          
Line 638:                                                                                                                                                   
Line 639:        private void PermutationOnWords(ulong[] instate)                                                                                           
Line 640:        {                                                                                                                                          
Line 641:            temp1 = instate;                                                                                                                       
Line 642:            Rounds();                                                                                                                              
Line 643:        }                                                                                                                                          
Line 644:                                                                                                                                                   
Line 645:        private void PermutationOnWordsAfterXoring(ulong[] instate, ulong[] input, int laneCount)                                                  
Line 646:        {                                                                                                                                          
Line 647:            for (var j = 0; j < laneCount; j++)                                                                                                    
Line 648:                instate[j] ^= input[j];                                                                                                            
Line 649:            temp1 = instate;                                                                                                                       
Line 650:            Rounds();                                                                                                                              
Line 651:        }                                                                                                                                          
Line 652:                                                                                                                                                   
Line 653:        private void InitializeState(byte[] instate)                                                                                               
Line 654:        {                                                                                                                                          
Line 655:            Debug.Assert(instate.Length != 0);                                                                                                     
Line 656:            for (var i = 0; i < instate.Length; ++i)                                                                                               
Line 657:                instate[i] = 0;                                                                                                                    
Line 658:            const ulong complement = ~(ulong) 0;                                                                                                   
Line 659:            WriteLong(instate, 1, complement);                                                                                                     
Line 660:            WriteLong(instate, 2, complement);                                                                                                     
Line 661:            WriteLong(instate, 8, complement);                                                                                                     
Line 662:            WriteLong(instate, 12, complement);                                                                                                    
Line 663:            WriteLong(instate, 17, complement);                                                                                                    
Line 664:            WriteLong(instate, 20, complement);                                                                                                    
Line 665:        }                                                                                                                                          
Line 666:                                                                                                                                                   
Line 667:        private static void WriteLong(byte[] instate, int index, ulong value)                                                                      
Line 668:        {                                                                                                                                          
Line 669:            index *= 8;                                                                                                                            
Line 670:            for (var i = 0; i < 7; ++i)                                                                                                            
Line 671:            {                                                                                                                                      
Line 672:                instate[index++] = (byte) (value & 255);                                                                                           
Line 673:                value >>= 8;                                                                                                                       
Line 674:            }                                                                                                                                      
Line 675:            instate[index] = (byte) (value & 255);                                                                                                 
Line 676:        }                                                                                                                                          
Line 677:                                                                                                                                                   
Line 678:        private static void WordsToBytes(ulong[] words, byte[] bytes)                                                                              
Line 679:        {                                                                                                                                          
Line 680:            // todo - remove all these if possible                                                                                                 
Line 681:            for (var j = 0; j < words.Length; ++j)                                                                                                 
Line 682:            {                                                                                                                                      
Line 683:                var word = words[j];                                                                                                               
Line 684:                for (var i = 0; i < (64/8); i++)                                                                                                   
Line 685:                {                                                                                                                                  
Line 686:                    // todo - remove &255 - needed for checked build - check all code                                                              
Line 687:                    bytes[i + j*8] = (byte) ((word >> (8*i)) & 255);                                                                               
Line 688:                }                                                                                                                                  
Line 689:            }                                                                                                                                      
Line 690:        }                                                                                                                                          
Line 691:                                                                                                                                                   
Line 692:        private static void BytesToWords(byte[] bytes, ulong[] words)                                                                              
Line 693:        {                                                                                                                                          
Line 694:            // todo - remove all these if possible                                                                                                 
Line 695:            for (var j = 0; j < words.Length; ++j)                                                                                                 
Line 696:            {                                                                                                                                      
Line 697:                ulong word = 0;                                                                                                                    
Line 698:                for (var i = 0; i < (64/8); i++)                                                                                                   
Line 699:                    word |= (ulong) (bytes[i + j*8]) << (8*i);                                                                                     
Line 700:                words[j] = word;                                                                                                                   
Line 701:            }                                                                                                                                      
Line 702:        }                                                                                                                                          
Line 703:                                                                                                                                                   
Line 704:        private void Absorb(byte[] instate, byte[] data, int laneCount)                                                                            
Line 705:        {                                                                                                                                          
Line 706:            var wstate = new ulong[instate.Length/8];                                                                                              
Line 707:            var wdata = new ulong[data.Length/8];                                                                                                  
Line 708:            BytesToWords(instate, wstate);                                                                                                         
Line 709:            BytesToWords(data, wdata);                                                                                                             
Line 710:            PermutationOnWordsAfterXoring(wstate, wdata, laneCount);                                                                               
Line 711:            WordsToBytes(wstate, instate);                                                                                                         
Line 712:        }                                                                                                                                          
Line 713:                                                                                                                                                   
Line 714:        private static void NotLong(byte[] data, int longIndex)                                                                                    
Line 715:        {                                                                                                                                          
Line 716:            longIndex *= 8;                                                                                                                        
Line 717:            for (var i = 0; i < 7; ++i)                                                                                                            
Line 718:            {                                                                                                                                      
Line 719:                data[longIndex] = (byte) (~data[longIndex] & 255);                                                                                 
Line 720:                longIndex++;                                                                                                                       
Line 721:            }                                                                                                                                      
Line 722:            data[longIndex] = (byte) (~data[longIndex] & 255);                                                                                     
Line 723:        }                                                                                                                                          
Line 724:                                                                                                                                                   
Line 725:        private void Extract(byte[] instate, byte[] data, int laneCount)                                                                           
Line 726:        {                                                                                                                                          
Line 727:            for (var j = 0; j < laneCount*8; ++j)                                                                                                  
Line 728:                data[j] = instate[j];                                                                                                              
Line 729:            if (laneCount > 1)                                                                                                                     
Line 730:            {                                                                                                                                      
Line 731:                NotLong(data, 1);                                                                                                                  
Line 732:                                                                                                                                                   
Line 733:                if (laneCount > 2)                                                                                                                 
Line 734:                {                                                                                                                                  
Line 735:                    NotLong(data, 2);                                                                                                              
Line 736:                                                                                                                                                   
Line 737:                    if (laneCount > 8)                                                                                                             
Line 738:                    {                                                                                                                              
Line 739:                        NotLong(data, 8);                                                                                                          
Line 740:                                                                                                                                                   
Line 741:                        if (laneCount > 12)                                                                                                        
Line 742:                        {                                                                                                                          
Line 743:                            NotLong(data, 12);                                                                                                     
Line 744:                            if (laneCount > 17)                                                                                                    
Line 745:                            {                                                                                                                      
Line 746:                                NotLong(data, 17);                                                                                                 
Line 747:                                if (laneCount > 20)                                                                                                
Line 748:                                {                                                                                                                  
Line 749:                                    NotLong(data, 17);                                                                                             
Line 750:                                }                                                                                                                  
Line 751:                            }                                                                                                                      
Line 752:                        }                                                                                                                          
Line 753:                    }                                                                                                                              
Line 754:                }                                                                                                                                  
Line 755:            }                                                                                                                                      
Line 756:        }                                                                                                                                          
Line 757:                                                                                                                                                   
Line 758:        // remove instate parameter to function calls                                                                                              
Line 759:        private SpongeState sponge;                                                                                                                
Line 760:                                                                                                                                                   
Line 761:                                                                                                                                                   
Line 762:        private void AbsorbQueue()                                                                                                                 
Line 763:        {                                                                                                                                          
Line 764:            // instate.bitsInQueue is assumed to 1 equal to instate.rate                                                                           
Line 765:            Absorb(sponge.State, sponge.DataQueue, sponge.Rate/64);                                                                                
Line 766:            sponge.BitsInQueue = 0;                                                                                                                
Line 767:        }                                                                                                                                          
Line 768:                                                                                                                                                   
Line 769:                                                                                                                                                   
Line 770:        /// <summary>                                                                                                                              
Line 771:        /// Function to squeeze output data from the sponge function.                                                                              
Line 772:        /// If the sponge function was in the absorbing phase, this function                                                                       
Line 773:        /// switches it to the squeezing phase.                                                                                                    
Line 774:        /// </summary>                                                                                                                             
Line 775:        /// <param name="output">Pointer to the buffer where to store the output data.</param>                                                     
Line 776:        /// <param name="outputLength">The number of output bits desired. It must be a multiple of 8.</param>                                      
Line 777:        /// <returns>true if successful, false otherwise.</returns>                                                                                
Line 778:        private bool Squeeze(byte[] output, long outputLength)                                                                                     
Line 779:        {                                                                                                                                          
Line 780:            if (!sponge.Squeezing)                                                                                                                 
Line 781:                PadAndSwitchToSqueezingPhase();                                                                                                    
Line 782:            if ((outputLength%8) != 0)                                                                                                             
Line 783:                return false// Only multiple of 8 bits are allowed, truncation can 1 done at user level                                          
Line 784:                                                                                                                                                   
Line 785:            long i = 0;                                                                                                                            
Line 786:            while (i < outputLength)                                                                                                               
Line 787:            {                                                                                                                                      
Line 788:                if (sponge.BitsAvailableForSqueezing == 0)                                                                                         
Line 789:                {                                                                                                                                  
Line 790:                    var wstate = new ulong[sponge.State.Length/8];                                                                                 
Line 791:                    BytesToWords(sponge.State, wstate);                                                                                            
Line 792:                                                                                                                                                   
Line 793:                    PermutationOnWords(wstate);                                                                                                    
Line 794:                                                                                                                                                   
Line 795:                    WordsToBytes(wstate, sponge.State);                                                                                            
Line 796:                                                                                                                                                   
Line 797:                    Extract(sponge.State, sponge.DataQueue, sponge.Rate/64);                                                                       
Line 798:                    sponge.BitsAvailableForSqueezing = sponge.Rate;                                                                                
Line 799:                                                                                                                                                   
Line 800:                                                                                                                                                   
Line 801:                }                                                                                                                                  
Line 802:                var partialBlock = sponge.BitsAvailableForSqueezing;                                                                               
Line 803:                if (partialBlock > outputLength - i)                                                                                               
Line 804:                    partialBlock = outputLength - i;                                                                                               
Line 805:                                                                                                                                                   
Line 806:                for (var j = 0; j < partialBlock/8; ++j)                                                                                           
Line 807:                {                                                                                                                                  
Line 808:                    var index = (sponge.Rate - sponge.BitsAvailableForSqueezing)/8;                                                                
Line 809:                    output[i/8 + j] = sponge.DataQueue[index + j];                                                                                 
Line 810:                }                                                                                                                                  
Line 811:                                                                                                                                                   
Line 812:                sponge.BitsAvailableForSqueezing -= partialBlock;                                                                                  
Line 813:                i += partialBlock;                                                                                                                 
Line 814:            }                                                                                                                                      
Line 815:            return true;                                                                                                                           
Line 816:        }                                                                                                                                          
Line 817:                                                                                                                                                   
Line 818:        /// <summary>                                                                                                                              
Line 819:        /// Function to give input data for the sponge function to absorb.                                                                         
Line 820:        /// </summary>                                                                                                                             
Line 821:        /// <param name="data">                                                                                                                    
Line 822:        /// Pointer to the input data. When databitLen is not                                                                                      
Line 823:        /// a multiple of 8, the last bits of data must be in the                                                                                  
Line 824:        /// least significant bits of the last byte.</param>                                                                                       
Line 825:        /// <param name="databitlen">The number of input bits provided in the input data.</param>                                                  
Line 826:        /// <returns>true on success, else false</returns>                                                                                         
Line 827:        private bool Absorb(byte[] data, long databitlen)                                                                                          
Line 828:        {                                                                                                                                          
Line 829:            if ((sponge.BitsInQueue%8) != 0)                                                                                                       
Line 830:                return false// Only the last call may contain a partial byte                                                                     
Line 831:            if (sponge.Squeezing)                                                                                                                  
Line 832:                return false// Too late for additional input                                                                                     
Line 833:                                                                                                                                                   
Line 834:            long i = 0;                                                                                                                            
Line 835:            Func<longintbyte[]> makeData = (index, length) =>                                                                                  
Line 836:                                                   {                                                                                               
Line 837:                                                       // todo - this data movement needs changed - too many copies                                
Line 838:                                                       var dat2 = new byte[length];                                                                
Line 839:                                                       Array.Copy(data, (int) index, dat2, 0, length);                                             
Line 840:                                                       return dat2;                                                                                
Line 841:                                                   };                                                                                              
Line 842:            while (i < databitlen)                                                                                                                 
Line 843:            {                                                                                                                                      
Line 844:                if ((sponge.BitsInQueue == 0) && (databitlen >= sponge.Rate) && (i <= (databitlen - sponge.Rate)))                                 
Line 845:                {                                                                                                                                  
Line 846:                    var wholeBlocks = (databitlen - i)/sponge.Rate;                                                                                
Line 847:                    var curData = i/8;                                                                                                             
Line 848:                                                                                                                                                   
Line 849:                                                                                                                                                   
Line 850:                    for (var j = 0; j < wholeBlocks; j++, curData += sponge.Rate/8)                                                                
Line 851:                    {                                                                                                                              
Line 852:                        Absorb(sponge.State, makeData(curData, sponge.Rate/8), sponge.Rate/64);                                                    
Line 853:                    }                                                                                                                              
Line 854:                    i += wholeBlocks*sponge.Rate;                                                                                                  
Line 855:                }                                                                                                                                  
Line 856:                else                                                                                                                               
Line 857:                {                                                                                                                                  
Line 858:                    var partialBlock = (int) (databitlen - i);                                                                                     
Line 859:                    if (partialBlock + sponge.BitsInQueue > sponge.Rate)                                                                           
Line 860:                        partialBlock = sponge.Rate - sponge.BitsInQueue;                                                                           
Line 861:                    var partialByte = partialBlock%8;                                                                                              
Line 862:                    partialBlock -= partialByte;                                                                                                   
Line 863:                    for (long k = 0; k < partialBlock/8; ++k)                                                                                      
Line 864:                    {                                                                                                                              
Line 865:                        sponge.DataQueue[sponge.BitsAvailableForSqueezing/8 + k] = data[i/8 + k];                                                  
Line 866:                    }                                                                                                                              
Line 867:                    sponge.BitsInQueue += partialBlock;                                                                                            
Line 868:                    i += partialBlock;                                                                                                             
Line 869:                    if (sponge.BitsInQueue == sponge.Rate)                                                                                         
Line 870:                        AbsorbQueue();                                                                                                             
Line 871:                    if (partialByte > 0)                                                                                                           
Line 872:                    {                                                                                                                              
Line 873:                        var mask = (byte) ((1 << partialByte) - 1);                                                                                
Line 874:                        sponge.DataQueue[sponge.BitsInQueue/8] = (byte) (data[i/8] & mask);                                                        
Line 875:                        sponge.BitsInQueue += partialByte;                                                                                         
Line 876:                        i += partialByte;                                                                                                          
Line 877:                    }                                                                                                                              
Line 878:                }                                                                                                                                  
Line 879:            }                                                                                                                                      
Line 880:            return true;                                                                                                                           
Line 881:        }                                                                                                                                          
Line 882:                                                                                                                                                   
Line 883:        private void PadAndSwitchToSqueezingPhase()                                                                                                
Line 884:        {                                                                                                                                          
Line 885:            // Note: the bits are numbered from 0=LSB to 7=MSB                                                                                     
Line 886:            if (sponge.BitsInQueue + 1 == sponge.Rate)                                                                                             
Line 887:            {                                                                                                                                      
Line 888:                sponge.DataQueue[sponge.BitsInQueue/8] |= (byte) (1 << (sponge.BitsInQueue%8));                                                    
Line 889:                AbsorbQueue();                                                                                                                     
Line 890:                for (var j = 0; j < sponge.Rate/8; ++j)                                                                                            
Line 891:                    sponge.DataQueue[j] = 0;                                                                                                       
Line 892:                                                                                                                                                   
Line 893:            }                                                                                                                                      
Line 894:            else                                                                                                                                   
Line 895:            {                                                                                                                                      
Line 896:                for (var j = 0; j < sponge.Rate/8 - (sponge.BitsInQueue + 7)/8; ++j)                                                               
Line 897:                    sponge.DataQueue[(sponge.BitsInQueue + 7)/8 + j] = 0;                                                                          
Line 898:                sponge.DataQueue[sponge.BitsInQueue/8] |= (byte) (1 << (sponge.BitsInQueue%8));                                                    
Line 899:            }                                                                                                                                      
Line 900:            sponge.DataQueue[(sponge.Rate - 1)/8] |= (byte) (1 << ((sponge.Rate - 1)%8));                                                          
Line 901:            AbsorbQueue();                                                                                                                         
Line 902:            Extract(sponge.State, sponge.DataQueue, sponge.Rate/64);                                                                               
Line 903:            sponge.BitsAvailableForSqueezing = sponge.Rate;                                                                                        
Line 904:            sponge.Squeezing = true;                                                                                                               
Line 905:        }                                                                                                                                          
Line 906:                                                                                                                                                   
Line 907:        #endregion                                                                                                                                 
Line 908:                                                                                                                                                   
Line 909:        #region Overrides of HashAlgorithm                                                                                                         
Line 910:                                                                                                                                                   
Line 911:        /// <summary>                                                                                                                              
Line 912:        /// Initializes an implementation of the <see cref="T:System.Security.Cryptography.HashAlgorithm"/> class.                                 
Line 913:        /// </summary>                                                                                                                             
Line 914:        public override void Initialize()                                                                                                          
Line 915:        {                                                                                                                                          
Line 916:        }                                                                                                                                          
Line 917:                                                                                                                                                   
Line 918:        /// <summary>                                                                                                                              
Line 919:        /// When overridden in a derived class, routes data written to the object into the hash algorithm for computing the hash.                  
Line 920:        /// </summary>                                                                                                                             
Line 921:        /// <param name="array">The input to compute the hash code for. </param>                                                                   
Line 922:        /// <param name="ibStart">The offset into the byte array from which to begin using data. </param>                                          
Line 923:        /// <param name="cbSize">The number of bytes in the byte array to use as data. </param>                                                    
Line 924:        protected override void HashCore(byte[] array, int ibStart, int cbSize)                                                                    
Line 925:        {                                                                                                                                          
Line 926:            var temp = array;                                                                                                                      
Line 927:            if (ibStart != 0)                                                                                                                      
Line 928:            {                                                                                                                                      
Line 929:                // need local copy                                                                                                                 
Line 930:                temp = new byte[cbSize];                                                                                                           
Line 931:                Array.Copy(array, ibStart, temp, 0, cbSize);                                                                                       
Line 932:            }                                                                                                                                      
Line 933:            Update(temp, cbSize*8);                                                                                                                
Line 934:        }                                                                                                                                          
Line 935:                                                                                                                                                   
Line 936:        /// <summary>                                                                                                                              
Line 937:        /// When overridden in a derived class, finalizes the hash computation after the last data is processed by the cryptographic stream object.
Line 938:        /// </summary>                                                                                                                             
Line 939:        /// <returns>                                                                                                                              
Line 940:        /// The computed hash code.                                                                                                                
Line 941:        /// </returns>                                                                                                                             
Line 942:        protected override byte[] HashFinal()                                                                                                      
Line 943:        {                                                                                                                                          
Line 944:                                                                                                                                                   
Line 945:            var hash = new byte[sponge.FixedOutputLength/8];                                                                                       
Line 946:            Final(hash);                                                                                                                           
Line 947:            return hash;                                                                                                                           
Line 948:        }                                                                                                                                          
Line 949:                                                                                                                                                   
Line 950:        #endregion                                                                                                                                 
Line 951:    }                                                                                                                                              
Line 952:}                                                                                                                                                  
Line 953:                                                                                                                                                   
Line 954:// end of file                                                                                                                                     
Line 955: