Line   1:// Copyright Chris Lomont 2009-2011.                                                                                                        
Line   2:// Implements Skein version 1.3, http://www.skein-hash.info/                                                                                
Line   3:// Versions 1.0-1.2 are still possible by changing an ifdef below.                                                                          
Line   4:// For bugs or comments, contact me through www.lomont.org                                                                                  
Line   5:// C#, Visual Studio 2008, 2010                                                                                                             
Line   6:#define SKEIN13 // define this to get Skein1.3, else you have a previous version                                                            
Line   7:using System;                                                                                                                               
Line   8:using System.Diagnostics;                                                                                                                   
Line   9:using System.Collections.Generic;                                                                                                           
Line  10:using System.Security.Cryptography;                                                                                                         
Line  11:                                                                                                                                            
Line  12:namespace Lomont{ namespace Crypto                                                                                                          
Line  13:    {                                                                                                                                       
Line  14:    // todo - implement rest of spec: tree functions, etc.                                                                                  
Line  15:    // todo - make Threefish a complete .NET citizen by subclassing it properly                                                             
Line  16:    // todo - walk code looking for endian problems, use BitConverter.IsLittleEndian to fix?                                                
Line  17:    // todo - rewrite for speed                                                                                                             
Line  18:    // todo - comment thoroughly, give usage cases, polish                                                                                  
Line  19:    // todo - see JavaScript at http://www.h2database.com/skein/index.html for a way to do more in place operations                         
Line  20:    // todo -change interface uint, int, ulong, etc., to make class nicely useable                                                          
Line  21:                                                                                                                                            
Line  22:                                                                                                                                            
Line  23:    /// <summary>                                                                                                                           
Line  24:    /// The Skein hash function                                                                                                             
Line  25:    /// Create a class using internal length 256, 512, or 1024 bits                                                                         
Line  26:    /// Then use the Hash function to create hashes, usually of the                                                                         
Line  27:    /// same size.                                                                                                                          
Line  28:    /// </summary>                                                                                                                          
Line  29:    public class Skein : HashAlgorithm                                                                                                      
Line  30:    {                                                                                                                                       
Line  31:        /// <summary>                                                                                                                       
Line  32:        /// Create a Skein hash                                                                                                             
Line  33:        /// Length is 256, 512, or 1024 bits for block/key size.                                                                            
Line  34:        /// </summary>                                                                                                                      
Line  35:        /// <param name="stateSize">The length of the internal state: 256, 512, or 1024 bits.</param>                                       
Line  36:        /// <param name="outputLength">Output size in bits. Must be a multiple of 8 and greater than 0.</param>                             
Line  37:        /// todo - output length ('No' in spec) should be allowed to be any value >= 0 by the spec?                                         
Line  38:        public Skein(uint stateSize, uint outputLength)                                                                                     
Line  39:            {                                                                                                                               
Line  40:            if ((stateSize != 256) && (stateSize != 512) && (stateSize != 1024))                                                            
Line  41:                throw new ArgumentOutOfRangeException("stateSize""Must be one of 256, 512, 1024.");                                       
Line  42:            if ((outputLength <= 0) || ((outputLength&7) != 0))                                                                             
Line  43:                throw new ArgumentOutOfRangeException("outputLength""Must be a multiple of 8 and greater than 0.");                       
Line  44:            threeFishCipher = new Threefish(stateSize);                                                                                     
Line  45:            Nb = stateSize / 8;                                                                                                             
Line  46:                                                                                                                                            
Line  47:            // set configuration to default values                                                                                          
Line  48:            Configuration = new ulong[4];                                                                                                   
Line  49:            Schema = 0x33414853U; // ASCII 'SHA3' // todo - check endianess                                                                 
Line  50:            Version = 1;                                                                                                                    
Line  51:            OutputLength = outputLength;                                                                                                    
Line  52:            TreeLeafSize = 0;                                                                                                               
Line  53:            TreeFanOutSize = 0;                                                                                                             
Line  54:            TreeMaximumHeight = 0;                                                                                                          
Line  55:                                                                                                                                            
Line  56:            // set fields in base class                                                                                                     
Line  57:            HashSizeValue = (int)outputLength;                                                                                              
Line  58:            // todo - more?                                                                                                                 
Line  59:            }                                                                                                                               
Line  60:                                                                                                                                            
Line  61:        private readonly Threefish threeFishCipher;                                                                                         
Line  62:                                                                                                                                            
Line  63:        #region Configuration                                                                                                               
Line  64:                                                                                                                                            
Line  65:        /// <summary>                                                                                                                       
Line  66:        /// The 32 byte configuration data. This is modified by setting Skein parameters.                                                   
Line  67:        /// Setting these values here and reading the parameters decodes a configuration block.                                             
Line  68:        /// </summary>                                                                                                                      
Line  69:        public ulong[] Configuration { getprivate set; }                                                                                  
Line  70:                                                                                                                                            
Line  71:        /// <summary>                                                                                                                       
Line  72:        /// A schema is 4 bytes. Currently it is ASCII 'SHA3'                                                                               
Line  73:        /// </summary>                                                                                                                      
Line  74:        public uint Schema                                                                                                                  
Line  75:        {                                                                                                                                   
Line  76:            get { return (uint)Configuration[0];  }                                                                                         
Line  77:            set {                                                                                                                           
Line  78:                Configuration[0] &= ~0xFFFFFFFFUL;                                                                                          
Line  79:                Configuration[0] |= value;                                                                                                  
Line  80:            }                                                                                                                               
Line  81:        }                                                                                                                                   
Line  82:                                                                                                                                            
Line  83:        /// <summary>                                                                                                                       
Line  84:        /// Version. Currently set to 1 for Skein version 1.3                                                                               
Line  85:        /// </summary>                                                                                                                      
Line  86:        public ushort Version                                                                                                               
Line  87:        {                                                                                                                                   
Line  88:            get { return (ushort)(Configuration[0] >> 32); }                                                                                
Line  89:            set                                                                                                                             
Line  90:            {                                                                                                                               
Line  91:                Configuration[0] &= 0xFFFF0000FFFFFFFFUL;                                                                                   
Line  92:                Configuration[0] |= ((ulong)value) << 32;                                                                                   
Line  93:            }                                                                                                                               
Line  94:        }                                                                                                                                   
Line  95:        /// <summary>                                                                                                                       
Line  96:        /// The output length. Must be set in the constructor.                                                                              
Line  97:        /// </summary>                                                                                                                      
Line  98:        public ulong OutputLength                                                                                                           
Line  99:        {                                                                                                                                   
Line 100:            get { return Configuration[1]; }                                                                                                
Line 101:            private set { Configuration[1] = value; }                                                                                       
Line 102:        }                                                                                                                                   
Line 103:        /// <summary>                                                                                                                       
Line 104:        /// Tree leaf size 0-255.                                                                                                           
Line 105:        /// </summary>                                                                                                                      
Line 106:        public byte TreeLeafSize                                                                                                            
Line 107:        {                                                                                                                                   
Line 108:            get { return (byte)(Configuration[2]); }                                                                                        
Line 109:            set                                                                                                                             
Line 110:            {                                                                                                                               
Line 111:                Configuration[2] &= 0xFFFFFFFFFFFFFF00UL;                                                                                   
Line 112:                Configuration[2] |= ((ulong)value);                                                                                         
Line 113:            }                                                                                                                               
Line 114:        }                                                                                                                                   
Line 115:        /// <summary>                                                                                                                       
Line 116:        /// Tree fan factor 0-255                                                                                                           
Line 117:        /// </summary>                                                                                                                      
Line 118:        public byte TreeFanOutSize                                                                                                          
Line 119:        {                                                                                                                                   
Line 120:            get { return (byte)(Configuration[2]>>8); }                                                                                     
Line 121:            set                                                                                                                             
Line 122:            {                                                                                                                               
Line 123:                Configuration[2] &= 0xFFFFFFFFFFFF00FFUL;                                                                                   
Line 124:                Configuration[2] |= ((ulong)value)<<8;                                                                                      
Line 125:            }                                                                                                                               
Line 126:        }                                                                                                                                   
Line 127:                                                                                                                                            
Line 128:        /// <summary>                                                                                                                       
Line 129:        /// Max tree height 0-255. 255 denotes unlimited tree height.                                                                       
Line 130:        /// </summary>                                                                                                                      
Line 131:        public byte TreeMaximumHeight                                                                                                       
Line 132:        {                                                                                                                                   
Line 133:            get { return (byte)(Configuration[2]>>16); }                                                                                    
Line 134:            set                                                                                                                             
Line 135:            {                                                                                                                               
Line 136:                Configuration[2] &= 0xFFFFFFFFFF00FFFFUL;                                                                                   
Line 137:                Configuration[2] |= ((ulong)value)<<16;                                                                                     
Line 138:            }                                                                                                                               
Line 139:        }                                                                                                                                   
Line 140:                                                                                                                                            
Line 141:                                                                                                                                            
Line 142:        #endregion                                                                                                                          
Line 143:                                                                                                                                            
Line 144:        /// <summary>                                                                                                                       
Line 145:        /// Given an array of byte data, compute the hash                                                                                   
Line 146:        /// </summary>                                                                                                                      
Line 147:        /// <param name="data">The data to hash.</param>                                                                                    
Line 148:        /// <returns>The hashed byte data</returns>                                                                                         
Line 149:        byte[] HashSkein(byte[] data)                                                                                                       
Line 150:        {                                                                                                                                   
Line 151:            Debug.Assert((Nb == 32) || (Nb == 64) || (Nb == 128));                                                                          
Line 152:            var No = OutputLength*8; // number of output bits                                                                               
Line 153:            byte [] M = data;   // alias for the data                                                                                       
Line 154:                                                                                                                                            
Line 155:            var K = new ulong[Nb/8];                                                                                                        
Line 156:            var tweak = new UbiTweak();                                                                                                     
Line 157:            tweak.BlockType = UbiType.Config; // Set configuration block Tcfg                                                               
Line 158:            var G0 = UBI(K, SkeinByteConverter.WordsToBytes(Configuration), tweak, Nb * 8);                                                 
Line 159:                                                                                                                                            
Line 160:            tweak = new UbiTweak();                                                                                                         
Line 161:            tweak.BlockType = UbiType.Message; // set message block Tmsg                                                                    
Line 162:            var G1 = UBI(G0, M, tweak, 8 * (ulong)M.Length);                                                                                
Line 163:                                                                                                                                            
Line 164:            byte[] H = Output(G1, No);                                                                                                      
Line 165:            return H;                                                                                                                       
Line 166:            }                                                                                                                               
Line 167:                                                                                                                                            
Line 168:        #region Implementation                                                                                                              
Line 169:                                                                                                                                            
Line 170:        /// <summary>                                                                                                                       
Line 171:        /// Number of bytes 32, 64, or 128                                                                                                  
Line 172:        /// </summary>                                                                                                                      
Line 173:        ulong Nb = 0UL;                                                                                                                     
Line 174:                                                                                                                                            
Line 175:        /// <summary>                                                                                                                       
Line 176:        /// Perform the UBI compression on G, return compression.                                                                           
Line 177:        /// </summary>                                                                                                                      
Line 178:        /// <param name="G">From spec. Starting value of some bytes.</param>                                                                
Line 179:        /// <param name="M">Message from spec</param>                                                                                       
Line 180:        /// <param name="T">Tweak from spec. This can be modified by this function.</param>                                                 
Line 181:        /// <param name="bits">The number of bits to hash</param>                                                                           
Line 182:        /// <returns>The byte array</returns>                                                                                               
Line 183:        ulong [] UBI(ulong [] G, byte [] M, UbiTweak Ts, ulong bits)                                                                        
Line 184:            { // todo need bits <= 2^99 - 8, this only holds 2^64 - 1.                                                                      
Line 185:            //Debug.Assert((Nb == 32) || (Nb == 64) || (Nb == 128));                                                                        
Line 186:                                                                                                                                            
Line 187:            // pad message if needed. See page 12 of spec.                                                                                  
Line 188:            int B = 0;                                                                                                                      
Line 189:            byte [] Mp = M;                                                                                                                 
Line 190:            if ((bits & 7) != 0)                                                                                                            
Line 191:            {                                                                                                                               
Line 192:                B = 1;                                                                                                                      
Line 193:                Mp = new byte[M.Length];                                                                                                    
Line 194:                M.CopyTo(M, 0);                                                                                                             
Line 195:                Mp[M.Length - 1] |= (byte) (1 << (int) (7 - (bits & 7)));                                                                   
Line 196:            }                                                                                                                               
Line 197:            ulong Nm = (ulong)Mp.Length;                                                                                                    
Line 198:            ulong k = (Nm + Nb - 1) / Nb; // number of blocks of bitLength Nb                                                               
Line 199:            if (k == 0) k = 1; // at least one block                                                                                        
Line 200:            ulong [] Mpp = new ulong[k*Nb/8];                                                                                               
Line 201:            SkeinByteConverter.BytesToWords(Mp).CopyTo(Mpp, 0);                                                                             
Line 202:                                                                                                                                            
Line 203:            ulong[] H = G;                                                                                                                  
Line 204:            ulong [] temp = new ulong[Nb / 8];                                                                                              
Line 205:                                                                                                                                            
Line 206:            for (ulong i = 0; i < k ; ++i)                                                                                                  
Line 207:            {                                                                                                                               
Line 208:                // prepare tweak value                                                                                                      
Line 209:                Ts.Position = Math.Min(Nm, (i + 1) * Nb); // bitLength                                                                      
Line 210:                Ts.IsFirstBlock = i == 0;                                                                                                   
Line 211:                Ts.IsFinalBlock = i == k - 1;                                                                                               
Line 212:                if (Ts.IsFinalBlock)                                                                                                        
Line 213:                    Ts.IsPadded = B != 0;                                                                                                   
Line 214:                                                                                                                                            
Line 215:                for (ulong j = 0; j < Nb / 8; ++j)                                                                                          
Line 216:                    temp[j] = Mpp[j + i * Nb / 8];                                                                                          
Line 217:                                                                                                                                            
Line 218:                threeFishCipher.EncryptBlock(H,Ts.Value,temp,0);                                                                            
Line 219:                for (ulong j = 0; j < Nb/8; ++j)                                                                                            
Line 220:                    H[j] = temp[j] ^ Mpp[j + i * Nb / 8];                                                                                   
Line 221:                }                                                                                                                           
Line 222:                                                                                                                                            
Line 223:            return H;                                                                                                                       
Line 224:            }                                                                                                                               
Line 225:                                                                                                                                            
Line 226:        /// <summary>                                                                                                                       
Line 227:        /// The Output function from the spec.                                                                                              
Line 228:        /// Converts the internal state to the desired output size.                                                                         
Line 229:        /// </summary>                                                                                                                      
Line 230:        /// <param name="G">Internal state</param>                                                                                          
Line 231:        /// <param name="No">Number of desired output bytes</param>                                                                         
Line 232:        /// <returns>The output bytes</returns>                                                                                             
Line 233:        byte[] Output(ulong [] G, ulong No)                                                                                                 
Line 234:        {                                                                                                                                   
Line 235:            var tweak = new UbiTweak();                                                                                                     
Line 236:            tweak.BlockType = UbiType.Out;                                                                                                  
Line 237:                                                                                                                                            
Line 238:            byte [] ans = new byte[(No+7)/8];                                                                                               
Line 239:                                                                                                                                            
Line 240:            ulong bitsDone = 0;                                                                                                             
Line 241:            ulong i = 0;                                                                                                                    
Line 242:            ulong bits = 64*(ulong)G.Length;                                                                                                
Line 243:            while (bitsDone < No)                                                                                                           
Line 244:                {                                                                                                                           
Line 245:                byte [] O =                                                                                                                 
Line 246:                    SkeinByteConverter.WordsToBytes(                                                                                        
Line 247:                    UBI(G, SkeinByteConverter.ToBytes(i,8), tweak, 8*8));                                                                   
Line 248:                ulong start= bitsDone / 8;                                                                                                  
Line 249:                ulong length = Math.Min((ulong)O.Length, (ulong)ans.Length-start);                                                          
Line 250:                for (ulong index = 0; index < length; ++index)                                                                              
Line 251:                    ans[index+start] = O[index];                                                                                            
Line 252:                ++i;                                                                                                                        
Line 253:                bitsDone += bits; // todo - correct?                                                                                        
Line 254:                }                                                                                                                           
Line 255:            return ans;                                                                                                                     
Line 256:            }                                                                                                                               
Line 257:                                                                                                                                            
Line 258:        #endregion   // Implementation                                                                                                      
Line 259:                                                                                                                                            
Line 260:        protected override void HashCore(byte[] array, int ibStart, int cbSize)                                                             
Line 261:        {                                                                                                                                   
Line 262:            if ((ibStart != 0) || (array.Length != cbSize))                                                                                 
Line 263:                throw new NotImplementedException("Style of hashing not implemented");                                                      
Line 264:            base.HashValue = HashSkein(array);                                                                                              
Line 265:        }                                                                                                                                   
Line 266:                                                                                                                                            
Line 267:        protected override byte[] HashFinal()                                                                                               
Line 268:        {                                                                                                                                   
Line 269:            return HashValue;                                                                                                               
Line 270:        }                                                                                                                                   
Line 271:                                                                                                                                            
Line 272:        public override void Initialize()                                                                                                   
Line 273:        {                                                                                                                                   
Line 274:        }                                                                                                                                   
Line 275:    } // Skein                                                                                                                              
Line 276:                                                                                                                                            
Line 277:    /// <summary>                                                                                                                           
Line 278:    /// Type values from the spec, Table 6                                                                                                  
Line 279:    /// </summary>                                                                                                                          
Line 280:    public enum UbiType : ulong                                                                                                             
Line 281:    {                                                                                                                                       
Line 282:        /// <summary>                                                                                                                       
Line 283:        /// Key used for MAC and KDF                                                                                                        
Line 284:        /// </summary>                                                                                                                      
Line 285:        Key = 0,                                                                                                                            
Line 286:        /// <summary>                                                                                                                       
Line 287:        /// Configuration block                                                                                                             
Line 288:        /// </summary>                                                                                                                      
Line 289:        Config = 4,                                                                                                                         
Line 290:        /// <summary>                                                                                                                       
Line 291:        /// Personalization string                                                                                                          
Line 292:        /// </summary>                                                                                                                      
Line 293:        Personalization = 8,                                                                                                                
Line 294:        /// <summary>                                                                                                                       
Line 295:        /// Public key for digital signature hashing                                                                                        
Line 296:        /// </summary>                                                                                                                      
Line 297:        PublicKey = 12,                                                                                                                     
Line 298:        /// <summary>                                                                                                                       
Line 299:        /// Key identifier for KDF                                                                                                          
Line 300:        /// </summary>                                                                                                                      
Line 301:        KeyIdentifier = 16,                                                                                                                 
Line 302:        /// <summary>                                                                                                                       
Line 303:        /// Nonce for stream cipher or randomized hashing                                                                                   
Line 304:        /// </summary>                                                                                                                      
Line 305:        Nonce = 20,                                                                                                                         
Line 306:        /// <summary>                                                                                                                       
Line 307:        /// Message to hash                                                                                                                 
Line 308:        /// </summary>                                                                                                                      
Line 309:        Message = 48,                                                                                                                       
Line 310:        /// <summary>                                                                                                                       
Line 311:        /// Output                                                                                                                          
Line 312:        /// </summary>                                                                                                                      
Line 313:        Out = 63                                                                                                                            
Line 314:    }                                                                                                                                       
Line 315:                                                                                                                                            
Line 316:    /// <summary>                                                                                                                           
Line 317:    /// Store the values for the Tweak parameters for Threefish                                                                             
Line 318:    /// </summary>                                                                                                                          
Line 319:    public class UbiTweak                                                                                                                   
Line 320:    {                                                                                                                                       
Line 321:        /// <summary>                                                                                                                       
Line 322:        /// Create a new tweak structure                                                                                                    
Line 323:        /// </summary>                                                                                                                      
Line 324:        public UbiTweak() {Value = new ulong[2];}                                                                                           
Line 325:        /// <summary>                                                                                                                       
Line 326:        /// The 128 bit tweak value                                                                                                         
Line 327:        /// </summary>                                                                                                                      
Line 328:        public ulong[] Value { get;  private set; }                                                                                         
Line 329:        #region Helper functions                                                                                                            
Line 330:        void Set(ulong mask, bool value)                                                                                                    
Line 331:        {                                                                                                                                   
Line 332:            if (value)                                                                                                                      
Line 333:                Value[1] |= mask;                                                                                                           
Line 334:            else                                                                                                                            
Line 335:                Value[1] &= ~mask;                                                                                                          
Line 336:        }                                                                                                                                   
Line 337:        bool Get(ulong mask)                                                                                                                
Line 338:        {                                                                                                                                   
Line 339:            return (Value[1] & mask) != 0;                                                                                                  
Line 340:        }                                                                                                                                   
Line 341:        #endregion                                                                                                                          
Line 342:        /// <summary>                                                                                                                       
Line 343:        /// Is this the first block?                                                                                                        
Line 344:        /// </summary>                                                                                                                      
Line 345:        public bool IsFirstBlock                                                                                                            
Line 346:        {                                                                                                                                   
Line 347:            get { return Get(1UL<<62); }                                                                                                    
Line 348:            set{ Set(1UL<<62,value); }                                                                                                      
Line 349:        }                                                                                                                                   
Line 350:        /// <summary>                                                                                                                       
Line 351:        /// Is this the final block?                                                                                                        
Line 352:        /// </summary>                                                                                                                      
Line 353:        public bool IsFinalBlock                                                                                                            
Line 354:        {                                                                                                                                   
Line 355:            get { return Get(1UL << 63); }                                                                                                  
Line 356:            set { Set(1UL << 63, value); }                                                                                                  
Line 357:        }                                                                                                                                   
Line 358:                                                                                                                                            
Line 359:        /// <summary>                                                                                                                       
Line 360:        /// Is this block padded due to not using all bits in last byte?                                                                    
Line 361:        /// </summary>                                                                                                                      
Line 362:        public bool IsPadded                                                                                                                
Line 363:        {                                                                                                                                   
Line 364:            get { return Get(1UL << 54); }                                                                                                  
Line 365:            set { Set(1UL << 54, value); }                                                                                                  
Line 366:        }                                                                                                                                   
Line 367:                                                                                                                                            
Line 368:        /// <summary>                                                                                                                       
Line 369:        /// Get/Set tree level 0-63                                                                                                         
Line 370:        /// </summary>                                                                                                                      
Line 371:        public byte TreeLevel {                                                                                                             
Line 372:            get { return (byte) ((Value[1] >> 48) & 0x3f); }                                                                                
Line 373:            set {                                                                                                                           
Line 374:                if (value > 63)                                                                                                             
Line 375:                    throw new ArgumentOutOfRangeException("TreeLevel""TreeLevel must be in 0-63");                                        
Line 376:                Value[1] &= ~(0x3FUL << 48); // mask out                                                                                    
Line 377:                Value[1] |= ((ulong)value << 48);   // or in                                                                                
Line 378:            }                                                                                                                               
Line 379:        }                                                                                                                                   
Line 380:                                                                                                                                            
Line 381:        /// <summary>                                                                                                                       
Line 382:        /// Get/set UBI block type                                                                                                          
Line 383:        /// </summary>                                                                                                                      
Line 384:        public UbiType BlockType                                                                                                            
Line 385:        {                                                                                                                                   
Line 386:            get { return (UbiType)((Value[1] >> 56)&0x3f); }                                                                                
Line 387:            set                                                                                                                             
Line 388:            {                                                                                                                               
Line 389:                Value[1] &= ~(0x3FUL << 56);      // mask out                                                                               
Line 390:                Value[1] |= ((ulong)value << 56); // or in                                                                                  
Line 391:            }                                                                                                                               
Line 392:        }                                                                                                                                   
Line 393:                                                                                                                                            
Line 394:        /// <summary>                                                                                                                       
Line 395:        /// The bit position. TODO  - only supports 64 bits but needs to do 96 bits.                                                        
Line 396:        /// </summary>                                                                                                                      
Line 397:        public ulong Position { get { return Value[0]; } set { Value[0] = value; } }                                                        
Line 398:                                                                                                                                            
Line 399:    }                                                                                                                                       
Line 400:                                                                                                                                            
Line 401:    /// <summary>                                                                                                                           
Line 402:    /// An implementation of the Threefish encryption function.                                                                             
Line 403:    /// TODO - make it implement .NET SymmetricAlgorithm and ICryptoTransform interfaces                                                    
Line 404:    /// </summary>                                                                                                                          
Line 405:    public class Threefish                                                                                                                  
Line 406:        {                                                                                                                                   
Line 407:        /// <summary>                                                                                                                       
Line 408:        /// Create a Threefish encryption/decryption object.                                                                                
Line 409:        /// Requires bitLength in bits of key and plaintext blocks.                                                                         
Line 410:        /// Length must be one of 256, 512, or 1024.                                                                                        
Line 411:        /// </summary>                                                                                                                      
Line 412:        /// <param name="bitLength">Length in bits of key (256, 512, or 1024)</param>                                                       
Line 413:        public Threefish(uint bitLength)                                                                                                    
Line 414:            {                                                                                                                               
Line 415:            if ((bitLength != 256) && (bitLength != 512) && (bitLength != 1024))                                                            
Line 416:                throw new ArgumentOutOfRangeException("bitLength""Threefish bit length must be one of 256, 512, or 1024");                
Line 417:            Nw = bitLength / 64; // number of 64 bit words                                                                                  
Line 418:            Nr = 72;          // number of rounds                                                                                           
Line 419:            if (Nw == 16) Nr = 80;                                                                                                          
Line 420:                                                                                                                                            
Line 421:            // set up tables and functions                                                                                                  
Line 422:            if (Nw == 4)                                                                                                                    
Line 423:                {                                                                                                                           
Line 424:                R = Rtbl4;                                                                                                                  
Line 425:                Permute = Permute4;                                                                                                         
Line 426:                Unpermute = Unpermute4;                                                                                                     
Line 427:                }                                                                                                                           
Line 428:            else if (Nw == 8)                                                                                                               
Line 429:                {                                                                                                                           
Line 430:                R = Rtbl8;                                                                                                                  
Line 431:                Permute = Permute8;                                                                                                         
Line 432:                Unpermute = Unpermute8;                                                                                                     
Line 433:                }                                                                                                                           
Line 434:            else if (Nw == 16)                                                                                                              
Line 435:                {                                                                                                                           
Line 436:                R = Rtbl16;                                                                                                                 
Line 437:                Permute = Permute16;                                                                                                        
Line 438:                Unpermute = Unpermute16;                                                                                                    
Line 439:                }                                                                                                                           
Line 440:                                                                                                                                            
Line 441:            Ks = new ulong[Nw + 1]; // sub-key storage                                                                                      
Line 442:            t = new ulong[3];       // t0,t1,t2 tweak values                                                                                
Line 443:            } // constructor                                                                                                                
Line 444:                                                                                                                                            
Line 445:        /// <summary>                                                                                                                       
Line 446:        /// Encrypt a block.                                                                                                                
Line 447:        /// Requires key, plaintext, and a tweak value.                                                                                     
Line 448:        /// Returns encrypted text.                                                                                                         
Line 449:        /// </summary>                                                                                                                      
Line 450:        /// <param name="K">Key to encrypt. Must be 32, 64, or 128 bytes and same size as plaintext P.</param>                              
Line 451:        /// <param name="T">16 byte tweak value (2 ulongs). Must be the same for decryption.</param>                                        
Line 452:        /// <param name="P">Plaintext to encrypt. Must be 32, 64, or 128 bytes and same size as key K.</param>                              
Line 453:        /// <returns>The encrypted bytes.</returns>                                                                                         
Line 454:        public byte[] EncryptBlock(byte[] K, ulong[] T, byte[] P)                                                                           
Line 455:            {                                                                                                                               
Line 456:            int keylen = K.Length;                                                                                                          
Line 457:            if ((keylen != 32) && (keylen != 64) && (keylen != 128))                                                                        
Line 458:                throw new ArgumentException("Key bitLength not 32, 64, or 128 bytes.");                                                     
Line 459:            int textlen = P.Length;                                                                                                         
Line 460:            if ((textlen != 32) && (textlen != 64) && (textlen != 128))                                                                     
Line 461:                throw new ArgumentException("Plaintext bitLength not 32, 64, or 128 bytes.");                                               
Line 462:            if (keylen != textlen)                                                                                                          
Line 463:                throw new ArgumentException("Plaintext bitLength must match key bitLength.");                                               
Line 464:            if (T.Length != 2)                                                                                                              
Line 465:                throw new ArgumentException("Tweak must be 16 bytes (2 longs)");                                                            
Line 466:                                                                                                                                            
Line 467:            var P1 = SkeinByteConverter.BytesToWords(P);                                                                                    
Line 468:            EncryptBlock(SkeinByteConverter.BytesToWords(K), T, P1, 0);                                                                     
Line 469:            return SkeinByteConverter.WordsToBytes(P1);                                                                                     
Line 470:            }                                                                                                                               
Line 471:                                                                                                                                            
Line 472:        /// <summary>                                                                                                                       
Line 473:        /// Decrypt a block.                                                                                                                
Line 474:        /// Requires key, ciphertext, and a tweak value.                                                                                    
Line 475:        /// Returns decrypted text.                                                                                                         
Line 476:        /// </summary>                                                                                                                      
Line 477:        /// <param name="K">Key to decrypt. Must be 32, 64, or 128 bytes and same size as ciphertext C.</param>                             
Line 478:        /// <param name="T">16 byte tweak value (2 ulongs). Must be the same for encryption.</param>                                        
Line 479:        /// <param name="C">Ciphertext to decrypt. Must be 32, 64, or 128 bytes and same size as key K.</param>                             
Line 480:        /// <returns>The decrypted bytes.</returns>                                                                                         
Line 481:        public byte[] DecryptBlock(byte[] K, ulong [] T, byte[] C)                                                                          
Line 482:            {                                                                                                                               
Line 483:            int keylen = K.Length;                                                                                                          
Line 484:            if ((keylen != 32) && (keylen != 64) && (keylen != 128))                                                                        
Line 485:                throw new ArgumentException("Key bitLength not 32, 64, or 128 bytes.");                                                     
Line 486:            int cipherlen = C.Length;                                                                                                       
Line 487:            if ((cipherlen != 32) && (cipherlen != 64) && (cipherlen != 128))                                                               
Line 488:                throw new ArgumentException("Ciphertext bitLength not 32, 64, or 128 bytes.");                                              
Line 489:            if (keylen != cipherlen)                                                                                                        
Line 490:                throw new ArgumentException("Ciphertext bitLength must match key bitLength.");                                              
Line 491:            if (T.Length != 2)                                                                                                              
Line 492:                throw new ArgumentException("Tweak must be 16 bytes (2 ulongs)");                                                           
Line 493:                                                                                                                                            
Line 494:            ulong [] C1 = SkeinByteConverter.BytesToWords(C);                                                                               
Line 495:            DecryptBlock(SkeinByteConverter.BytesToWords(K), T, C1, 0);                                                                     
Line 496:            return SkeinByteConverter.WordsToBytes(C1);                                                                                     
Line 497:            }                                                                                                                               
Line 498:                                                                                                                                            
Line 499:                                                                                                                                            
Line 500:        #region Implementation                                                                                                              
Line 501:        /// <summary>                                                                                                                       
Line 502:        /// Number of 64 bit words per block Nw, and number of rounds Nr                                                                    
Line 503:        /// </summary>                                                                                                                      
Line 504:        uint Nw, Nr;                                                                                                                        
Line 505:        /// <summary>                                                                                                                       
Line 506:        /// The lengthened key state                                                                                                        
Line 507:        /// </summary>                                                                                                                      
Line 508:        ulong[] Ks = null;                                                                                                                  
Line 509:        /// <summary>                                                                                                                       
Line 510:        /// The lengthened tweak values                                                                                                     
Line 511:        /// </summary>                                                                                                                      
Line 512:        ulong[] t = null;                                                                                                                   
Line 513:                                                                                                                                            
Line 514:#if SKEIN13                                                                                                                                 
Line 515:        const ulong KeyScheduleConstant = 0x1BD11BDAA9FC1A22UL;                                                                             
Line 516:#else                                                                                                                                       
Line 517:        const ulong KeyScheduleConstant = 0x5555555555555555UL; // Floor[2^64 / 3]                                                          
Line 518:#endif                                                                                                                                      
Line 519:                                                                                                                                            
Line 520:                                                                                                                                            
Line 521:        /// <summary>                                                                                                                       
Line 522:        /// Encrypt a block in place. Thus P is the plaintext on input, and the cipertext on output                                         
Line 523:        /// </summary>                                                                                                                      
Line 524:        /// <param name="K">Key is 4, 8, or 16 64-bit values</param>                                                                        
Line 525:        /// <param name="T">Two 64-bit values for the tweak value.</param>                                                                  
Line 526:        /// <param name="P">Plaintext. A block of data, same bitLength as key K</param>                                                     
Line 527:        /// <param name="start">Start offset into P for encryption</param>                                                                  
Line 528:        public void EncryptBlock(ulong[] K, ulong[] T, ulong[] P, ulong start)                                                              
Line 529:            {                                                                                                                               
Line 530:            if ((K.Length != 4) && (K.Length != 8) && (K.Length != 16))                                                                     
Line 531:                throw new ArgumentOutOfRangeException("K""K must be 4,8, or 16 values in bitLength");                                     
Line 532:            if (K.Length > P.Length - (int)start)                                                                                           
Line 533:                throw new ArgumentOutOfRangeException("K and block""Block must have at least the bitLength of the key K");                
Line 534:                                                                                                                                            
Line 535:            // copy key to longer key for key scheduling                                                                                    
Line 536:            Ks[Nw] = KeyScheduleConstant;                                                                                                   
Line 537:            for (int i = 0; i < Nw; ++i)                                                                                                    
Line 538:                {                                                                                                                           
Line 539:                Ks[i] = K[i];                                                                                                               
Line 540:                Ks[Nw] ^= K[i];                                                                                                             
Line 541:                }                                                                                                                           
Line 542:                                                                                                                                            
Line 543:            // more key schedule parameters                                                                                                 
Line 544:            t[0] = T[0];                                                                                                                    
Line 545:            t[1] = T[1];                                                                                                                    
Line 546:            t[2] = T[0] ^ T[1];                                                                                                             
Line 547:                                                                                                                                            
Line 548:            for (uint d = 0; d < Nr; ++d) // d is round number as in spec                                                                   
Line 549:                {                                                                                                                           
Line 550:                if ((d & 3) == 0)                                                                                                           
Line 551:                    AddSubkey(d / 4, P, start);                                                                                             
Line 552:                // apply MIX to data two words at a time                                                                                    
Line 553:                for (uint j = 0; j < Nw / 2; ++j) // i is word number as in spec                                                            
Line 554:                    {                                                                                                                       
Line 555:                    MIX(P,2*j+start,R[d&7,j]);                                                                                              
Line 556:                    }                                                                                                                       
Line 557:                Permute(P, start);                                                                                                          
Line 558:                }                                                                                                                           
Line 559:                                                                                                                                            
Line 560:            // final cipertext                                                                                                              
Line 561:            AddSubkey(Nr / 4, P, start);                                                                                                    
Line 562:            } // EncryptBlock                                                                                                               
Line 563:                                                                                                                                            
Line 564:        /// <summary>                                                                                                                       
Line 565:        /// Decrypt a block in place. Thus C is the ciphertext on input, and the plaintext on output                                        
Line 566:        /// </summary>                                                                                                                      
Line 567:        /// <param name="K">Key, 4,8, or 16 64-bit values</param>                                                                           
Line 568:        /// <param name="T">2 64-bit values</param>                                                                                         
Line 569:        /// <param name="C">Ciphertext. A block of data, same bitLength as key K</param>                                                    
Line 570:        protected void DecryptBlock(ulong[] K, ulong[] T, ulong[] C, ulong start)                                                           
Line 571:            {                                                                                                                               
Line 572:            if ((K.Length != 4) && (K.Length != 8) && (K.Length != 16))                                                                     
Line 573:                throw new ArgumentOutOfRangeException("K""K must be 4,8, or 16 values in bitLength");                                     
Line 574:            if (K.Length < C.Length - (int)start)                                                                                           
Line 575:                throw new ArgumentOutOfRangeException("K and block""Block must have at least the bitLength of the key K");                
Line 576:                                                                                                                                            
Line 577:            // copy key to longer key                                                                                                       
Line 578:            Ks[Nw] = KeyScheduleConstant;                                                                                                   
Line 579:            for (int i = 0; i < Nw; ++i)                                                                                                    
Line 580:                {                                                                                                                           
Line 581:                Ks[i] = K[i];                                                                                                               
Line 582:                Ks[Nw] ^= K[i];                                                                                                             
Line 583:                }                                                                                                                           
Line 584:                                                                                                                                            
Line 585:            // key schedule                                                                                                                 
Line 586:            t[0] = T[0];                                                                                                                    
Line 587:            t[1] = T[1];                                                                                                                    
Line 588:            t[2] = T[0] ^ T[1];                                                                                                             
Line 589:                                                                                                                                            
Line 590:            // initial key                                                                                                                  
Line 591:            SubtractSubkey(Nr / 4, C, start);                                                                                               
Line 592:                                                                                                                                            
Line 593:            for (long d = (Nr - 1); d >= 0; --d) // d is round number as in spec                                                            
Line 594:                {                                                                                                                           
Line 595:                Unpermute(C, start);                                                                                                        
Line 596:                                                                                                                                            
Line 597:                // apply MIX to data                                                                                                        
Line 598:                for (int j = 0; j < Nw / 2; ++j) // i is word number as in spec                                                             
Line 599:                    {                                                                                                                       
Line 600:                    ulong y0, y1;                                                                                                           
Line 601:                    UnMIX(out y0, out y1, C[2 * j], C[2 * j + 1], R[d & 7, j]);                                                             
Line 602:                    C[2 * j] = y0;                                                                                                          
Line 603:                    C[2 * j + 1] = y1;                                                                                                      
Line 604:                    }                                                                                                                       
Line 605:                if ((d & 3) == 0)                                                                                                           
Line 606:                    SubtractSubkey((ulong)(d / 4), C, start);                                                                               
Line 607:                }                                                                                                                           
Line 608:            } // DecryptBlock                                                                                                               
Line 609:                                                                                                                                            
Line 610:                                                                                                                                            
Line 611:#if SKEIN13 // use this for Skein 1.3 round tables                                                                                          
Line 612:        /// <summary>                                                                                                                       
Line 613:        /// Table 4, R[d,j] for Nw = 4,8,16                                                                                                 
Line 614:        /// These tables give the rotate word amounts for                                                                                   
Line 615:        /// each round and word                                                                                                             
Line 616:        /// </summary>                                                                                                                      
Line 617:        int[,] R = null;                                                                                                                    
Line 618:        static int[,] Rtbl4 = {                                                                                                             
Line 619:                {14,16},                                                                                                                    
Line 620:                {52,57},                                                                                                                    
Line 621:                {23,40},                                                                                                                    
Line 622:                { 5,37},                                                                                                                    
Line 623:                {25,33},                                                                                                                    
Line 624:                {46,12},                                                                                                                    
Line 625:                {58,22},                                                                                                                    
Line 626:                {32,32}};                                                                                                                   
Line 627:        static int[,] Rtbl8 = {                                                                                                             
Line 628:                {46, 36,19,37},                                                                                                             
Line 629:                {33, 27,14,42},                                                                                                             
Line 630:                {17, 49,36,39},                                                                                                             
Line 631:                {44,  9,54,56},                                                                                                             
Line 632:                {39, 30,34,24},                                                                                                             
Line 633:                {13, 50,10,17},                                                                                                             
Line 634:                {25, 29,39,43},                                                                                                             
Line 635:                { 8, 35,56,22}};                                                                                                            
Line 636:        static int[,] Rtbl16 = {                                                                                                            
Line 637:                {24, 13, 8,47, 8,17,22,37},                                                                                                 
Line 638:                {38, 19,10,55,49,18,23,52},                                                                                                 
Line 639:                {33,  4,51,13,34,41,59,17},                                                                                                 
Line 640:                { 5, 20,48,41,47,28,16,25},                                                                                                 
Line 641:                {41,  9,37,31,12,47,44,30},                                                                                                 
Line 642:                {16, 34,56,51, 4,53,42,41},                                                                                                 
Line 643:                {31, 44,47,46,19,42,44,25},                                                                                                 
Line 644:                { 9, 48,35,52,23,31,37,20}};                                                                                                
Line 645:#else                                                                                                                                       
Line 646:        /// <summary>                                                                                                                       
Line 647:        /// Table 4, R[d,j] for Nw = 4,8,16                                                                                                 
Line 648:        /// These tables give the rotate word amounts for                                                                                   
Line 649:        /// each round and word                                                                                                             
Line 650:        /// </summary>                                                                                                                      
Line 651:        int[,] R = null;                                                                                                                    
Line 652:        static int[,] Rtbl4 = {                                                                                                             
Line 653:                { 5,56},                                                                                                                    
Line 654:                {36,28},                                                                                                                    
Line 655:                {13,46},                                                                                                                    
Line 656:                {58,44},                                                                                                                    
Line 657:                {26,20},                                                                                                                    
Line 658:                {53,35},                                                                                                                    
Line 659:                {11,42},                                                                                                                    
Line 660:                {59,50}};                                                                                                                   
Line 661:        static int[,] Rtbl8 = {                                                                                                             
Line 662:                {38,30,50,53},                                                                                                              
Line 663:                {48,20,43,31},                                                                                                              
Line 664:                {34,14,15,27},                                                                                                              
Line 665:                {26,12,58,7},                                                                                                               
Line 666:                {33,49,8,42},                                                                                                               
Line 667:                {39,27,41,14},                                                                                                              
Line 668:                {29,26,11,9},                                                                                                               
Line 669:                {33,51,39,35}};                                                                                                             
Line 670:        static int[,] Rtbl16 = {                                                                                                            
Line 671:                {55,43,37,40,16,22,38,12},                                                                                                  
Line 672:                {25,25,46,13,14,13,52,57},                                                                                                  
Line 673:                {33, 8,18,57,21,12,32,54},                                                                                                  
Line 674:                {34,43,25,60,44, 9,59,34},                                                                                                  
Line 675:                {28, 7,47,48,51, 9,35,41},                                                                                                  
Line 676:                {17, 6,18,25,43,42,40,15},                                                                                                  
Line 677:                {58, 7,32,45,19,18, 2,56},                                                                                                  
Line 678:                {47,49,27,58,37,48,53,56}};                                                                                                 
Line 679:#endif                                                                                                                                      
Line 680:                                                                                                                                            
Line 681:                                                                                                                                            
Line 682:        /// <summary>                                                                                                                       
Line 683:        /// The MIX function from the spec                                                                                                  
Line 684:        /// </summary>                                                                                                                      
Line 685:        /// <param name="P"></param>                                                                                                        
Line 686:        /// <param name="index"></param>                                                                                                    
Line 687:        /// <param name="Rdj"></param>                                                                                                      
Line 688:        void MIX(ulong [] P, ulong index, int Rdj)                                                                                          
Line 689:        {                                                                                                                                   
Line 690:            var x0 = P[index];                                                                                                              
Line 691:            var x1 = P[index + 1];                                                                                                          
Line 692:            var y0 = x0 + x1; // wraps mod 2^64                                                                                             
Line 693:            var y1 = (x1 << Rdj) | (x1 >> (64 - Rdj));                                                                                      
Line 694:            Debug.Assert(x1 == ((y1 >> Rdj) | (y1 << (64 - Rdj))), "Rotation failed");                                                      
Line 695:            P[index] = y0;                                                                                                                  
Line 696:            P[index + 1] = y1^y0;                                                                                                           
Line 697:        }                                                                                                                                   
Line 698:                                                                                                                                            
Line 699:        /// <summary>                                                                                                                       
Line 700:        /// The reverse of the mix function from the spec                                                                                   
Line 701:        /// </summary>                                                                                                                      
Line 702:        /// <param name="x0"></param>                                                                                                       
Line 703:        /// <param name="x1"></param>                                                                                                       
Line 704:        /// <param name="y0"></param>                                                                                                       
Line 705:        /// <param name="y1"></param>                                                                                                       
Line 706:        /// <param name="Rdj"></param>                                                                                                      
Line 707:        void UnMIX(out ulong x0, out ulong x1, ulong y0, ulong y1, int Rdj)                                                                 
Line 708:            {                                                                                                                               
Line 709:            y1 ^= y0;                                                                                                                       
Line 710:            x1 = (y1 >> Rdj) | (y1 << (64 - Rdj));                                                                                          
Line 711:            x0 = y0 - x1;                                                                                                                   
Line 712:            }                                                                                                                               
Line 713:                                                                                                                                            
Line 714:                                                                                                                                            
Line 715:        /// <summary>                                                                                                                       
Line 716:        /// Permutation table 3, implemented as functions to call                                                                           
Line 717:        /// </summary>                                                                                                                      
Line 718:        delegate void PermuteDelegate(ulong[] P, ulong start);                                                                              
Line 719:        PermuteDelegate Permute = null;                                                                                                     
Line 720:        PermuteDelegate Unpermute = null;                                                                                                   
Line 721:                                                                                                                                            
Line 722:        static void Permute4(ulong[] P, ulong start)                                                                                        
Line 723:            {                                                                                                                               
Line 724:            // permutation                                                                                                                  
Line 725:            // 0 1 2 3                                                                                                                      
Line 726:            // 0 3 2 1                                                                                                                      
Line 727:            // swap C[1] and C[3]                                                                                                           
Line 728:            P[3 + start] ^= P[1 + start];                                                                                                   
Line 729:            P[1 + start] ^= P[3 + start];                                                                                                   
Line 730:            P[3 + start] ^= P[1 + start];                                                                                                   
Line 731:            }                                                                                                                               
Line 732:                                                                                                                                            
Line 733:        static void Unpermute4(ulong[] P, ulong start)                                                                                      
Line 734:            { // todo - same as permute4, merge?                                                                                            
Line 735:            // permutation                                                                                                                  
Line 736:            // 0 1 2 3                                                                                                                      
Line 737:            // 0 3 2 1                                                                                                                      
Line 738:            // swap C[1] and C[3]                                                                                                           
Line 739:            P[3 + start] ^= P[1 + start];                                                                                                   
Line 740:            P[1 + start] ^= P[3 + start];                                                                                                   
Line 741:            P[3 + start] ^= P[1 + start];                                                                                                   
Line 742:            }                                                                                                                               
Line 743:                                                                                                                                            
Line 744:        static void Unpermute8(ulong[] P, ulong start)                                                                                      
Line 745:            {                                                                                                                               
Line 746:            // Perform reverse permutation                                                                                                  
Line 747:            //  0 1 2 3 4 5 6 7                                                                                                             
Line 748:            //  2 1 4 7 6 5 0 3                                                                                                             
Line 749:            // 0<-2<-4<-6<-0                                                                                                                
Line 750:            // 3<->7                                                                                                                        
Line 751:            ulong v = P[0 + start];                                                                                                         
Line 752:            P[0 + start] = P[6 + start];                                                                                                    
Line 753:            P[6 + start] = P[4 + start];                                                                                                    
Line 754:            P[4 + start] = P[2 + start];                                                                                                    
Line 755:            P[2 + start] = v;                                                                                                               
Line 756:            P[3 + start] ^= P[7 + start];                                                                                                   
Line 757:            P[7 + start] ^= P[3 + start];                                                                                                   
Line 758:            P[3 + start] ^= P[7 + start];                                                                                                   
Line 759:            }                                                                                                                               
Line 760:                                                                                                                                            
Line 761:        static void Permute8(ulong[] P, ulong start)                                                                                        
Line 762:            {                                                                                                                               
Line 763:            // Perform permutation                                                                                                          
Line 764:            //  0 1 2 3 4 5 6 7                                                                                                             
Line 765:            //  2 1 4 7 6 5 0 3                                                                                                             
Line 766:            // 0<-2<-4<-6<-0                                                                                                                
Line 767:            // 3<->7                                                                                                                        
Line 768:            ulong v = P[0 + start];                                                                                                         
Line 769:            P[0 + start] = P[2 + start];                                                                                                    
Line 770:            P[2 + start] = P[4 + start];                                                                                                    
Line 771:            P[4 + start] = P[6 + start];                                                                                                    
Line 772:            P[6 + start] = v;                                                                                                               
Line 773:            P[3 + start] ^= P[7 + start];                                                                                                   
Line 774:            P[7 + start] ^= P[3 + start];                                                                                                   
Line 775:            P[3 + start] ^= P[7 + start];                                                                                                   
Line 776:            }                                                                                                                               
Line 777:                                                                                                                                            
Line 778:        static void Permute16(ulong[] P, ulong start)                                                                                       
Line 779:            {                                                                                                                               
Line 780:            // 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15                                                                               
Line 781:            // 0  9  2 13  6 11  4 15 10  7 12  3 14  5  8  1                                                                               
Line 782:            // 1<-9<-7<-15<-1                                                                                                               
Line 783:            // 3<-13<-5<-11<-3                                                                                                              
Line 784:            // 4<->6                                                                                                                        
Line 785:            // 8<-10<-12<-14<-8                                                                                                             
Line 786:            ulong v;                                                                                                                        
Line 787:            v = P[1 + start]; P[1 + start] = P[9 + start]; P[9 + start] = P[7 + start]; P[7 + start] = P[15 + start]; P[15 + start] = v;    
Line 788:            v = P[3 + start]; P[3 + start] = P[13 + start]; P[13 + start] = P[5 + start]; P[5 + start] = P[11 + start]; P[11 + start] = v;  
Line 789:            P[4 + start] ^= P[6 + start]; P[6 + start] ^= P[4 + start]; P[4 + start] ^= P[6 + start];                                       
Line 790:            v = P[8 + start]; P[8 + start] = P[10 + start]; P[10 + start] = P[12 + start]; P[12 + start] = P[14 + start]; P[14 + start] = v;
Line 791:            }                                                                                                                               
Line 792:                                                                                                                                            
Line 793:        static void Unpermute16(ulong[] P, ulong start)                                                                                     
Line 794:            {                                                                                                                               
Line 795:            // 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15                                                                               
Line 796:            // 0  9  2 13  6 11  4 15 10  7 12  3 14  5  8  1                                                                               
Line 797:            // 1<-9<-7<-15<-1                                                                                                               
Line 798:            // 3<-13<-5<-11<-3                                                                                                              
Line 799:            // 4<->6                                                                                                                        
Line 800:            // 8<-10<-12<-14<-8                                                                                                             
Line 801:            ulong v;                                                                                                                        
Line 802:            v = P[1 + start]; P[1 + start] = P[15 + start]; P[15 + start] = P[7 + start]; P[7 + start] = P[9 + start]; P[9 + start] = v;    
Line 803:            v = P[3 + start]; P[3 + start] = P[11 + start]; P[11 + start] = P[5 + start]; P[5 + start] = P[13 + start]; P[13 + start] = v;  
Line 804:            P[4 + start] ^= P[6 + start]; P[6 + start] ^= P[4 + start]; P[4 + start] ^= P[6 + start];                                       
Line 805:            v = P[8 + start]; P[8 + start] = P[14 + start]; P[14 + start] = P[12 + start]; P[12 + start] = P[10 + start]; P[10 + start] = v;
Line 806:            }                                                                                                                               
Line 807:                                                                                                                                            
Line 808:        void AddSubkey(ulong s, ulong[] P, ulong start)                                                                                     
Line 809:            { // todo - note this is merely a rotation of Ks and ti, perhaps implement them that way?                                       
Line 810:            uint top = Nw + 1;                                                                                                              
Line 811:            for (ulong i = 0; i <= Nw - 4; ++i)                                                                                             
Line 812:                P[i + start] += Ks[(s + i) % top];                                                                                          
Line 813:            P[Nw - 3 + start] += Ks[(s + Nw - 3) % top] + t[s % 3];                                                                         
Line 814:            P[Nw - 2 + start] += Ks[(s + Nw - 2) % top] + t[(s + 1) % 3];                                                                   
Line 815:            P[Nw - 1 + start] += Ks[(s + Nw - 1) % top] + s;                                                                                
Line 816:            }                                                                                                                               
Line 817:                                                                                                                                            
Line 818:        void SubtractSubkey(ulong s, ulong[] P, ulong start)                                                                                
Line 819:            { // todo - note this is merely a rotation of Ks and ti, perhaps implement them that way?                                       
Line 820:            var top = Nw + 1;                                                                                                               
Line 821:            for (ulong i = 0; i <= Nw - 4; ++i)                                                                                             
Line 822:                P[i + start] -= Ks[(s + i) % top];                                                                                          
Line 823:            P[Nw - 3 + start] -= Ks[(s + Nw - 3) % top] + t[s % 3];                                                                         
Line 824:            P[Nw - 2 + start] -= Ks[(s + Nw - 2) % top] + t[(s + 1) % 3];                                                                   
Line 825:            P[Nw - 1 + start] -= Ks[(s + Nw - 1) % top] + s;                                                                                
Line 826:            }                                                                                                                               
Line 827:        #endregion                                                                                                                          
Line 828:                                                                                                                                            
Line 829:        } // Threefish                                                                                                                      
Line 830:                                                                                                                                            
Line 831:    #region Helper                                                                                                                          
Line 832:    /// <summary>                                                                                                                           
Line 833:    /// This class provides methods to convert between                                                                                      
Line 834:    /// ulong[]  and byte [] using the byte ordering of Skein                                                                               
Line 835:    /// </summary>                                                                                                                          
Line 836:    class SkeinByteConverter                                                                                                                
Line 837:        {                                                                                                                                   
Line 838:        /// <summary>                                                                                                                       
Line 839:        /// Given bytes b0,b1,b2,...,bn, return the corresponding                                                                           
Line 840:        /// 64 bit ulong using at most the first 8 bytes.                                                                                   
Line 841:        /// </summary>                                                                                                                      
Line 842:        /// <param name="list">A list of bytes to convert to ulongs </param>                                                                
Line 843:        /// <param name="start">The start index in the array</param>                                                                        
Line 844:        /// <returns></returns>                                                                                                             
Line 845:        static public ulong ToInt(byte[] list, int start)                                                                                   
Line 846:            {                                                                                                                               
Line 847:            int shift = 0;                                                                                                                  
Line 848:            ulong val = 0, temp;                                                                                                            
Line 849:            for (int i = 0; i < 8; ++i)                                                                                                     
Line 850:                {                                                                                                                           
Line 851:                if (start + i < list.Length)                                                                                                
Line 852:                    temp = list[start + i];                                                                                                 
Line 853:                else                                                                                                                        
Line 854:                    temp = 0;                                                                                                               
Line 855:                temp <<= shift;                                                                                                             
Line 856:                val |= temp;                                                                                                                
Line 857:                shift += 8;                                                                                                                 
Line 858:                }                                                                                                                           
Line 859:            return val;                                                                                                                     
Line 860:            }                                                                                                                               
Line 861:        /// <summary>                                                                                                                       
Line 862:        /// Convert a value v into n bytes                                                                                                  
Line 863:        /// </summary>                                                                                                                      
Line 864:        /// <param name="v">A 64 bit value</param>                                                                                          
Line 865:        /// <param name="n">The number of bytes to parse</param>                                                                            
Line 866:        /// <returns>An array of converted bytes</returns>                                                                                  
Line 867:        static public byte[] ToBytes(ulong v, int n)                                                                                        
Line 868:            {                                                                                                                               
Line 869:            Trace.Assert(n <= 8);  // otherwise we need to redesign this function                                                           
Line 870:            List<byte> b = new List<byte>();                                                                                                
Line 871:            for (int i = 0; i < n; ++i)                                                                                                     
Line 872:                b.Add((byte)(v >> (8 * i)));                                                                                                
Line 873:            return b.ToArray();                                                                                                             
Line 874:            }                                                                                                                               
Line 875:                                                                                                                                            
Line 876:        /// <summary>                                                                                                                       
Line 877:        /// Convert an array of 8n bytes to n ulongs                                                                                        
Line 878:        /// </summary>                                                                                                                      
Line 879:        /// <param name="arr"></param>                                                                                                      
Line 880:        /// <returns>An array of converted longs</returns>                                                                                  
Line 881:        static public ulong[] BytesToWords(byte[] arr)                                                                                      
Line 882:            {                                                                                                                               
Line 883:            int n = arr.Length;                                                                                                             
Line 884:            ulong [] w = new ulong[(n + 7) / 8];                                                                                            
Line 885:            for (int i = 0; i < n; i += 8)                                                                                                  
Line 886:                w[i / 8] = ToInt(arr, i);                                                                                                   
Line 887:            return w;                                                                                                                       
Line 888:            }                                                                                                                               
Line 889:        /// <summary>                                                                                                                       
Line 890:        /// Convert n words to 8n bytes                                                                                                     
Line 891:        /// </summary>                                                                                                                      
Line 892:        /// <param name="w">An array of ulongs to convert </param>                                                                          
Line 893:        /// <returns>The array of bytes</returns>                                                                                           
Line 894:        static public byte[] WordsToBytes(ulong[] w)                                                                                        
Line 895:            {                                                                                                                               
Line 896:            byte [] v = new byte[w.Length * 8];                                                                                             
Line 897:            for (int i = 0; i < w.Length; ++i)                                                                                              
Line 898:                ToBytes(w[i], 8).CopyTo(v, i * 8);                                                                                          
Line 899:            return v;                                                                                                                       
Line 900:            }                                                                                                                               
Line 901:                                                                                                                                            
Line 902:        } // SkeinByteConverter                                                                                                             
Line 903:    #endregion                                                                                                                              
Line 904:                                                                                                                                            
Line 905:    } // namespace Crypto                                                                                                                   
Line 906:    } // namespace Lomont                                                                                                                   
Line 907:                                                                                                                                            
Line 908: