Changeset 478


Ignore:
Timestamp:
11/9/2008 8:54:16 AM (6 years ago)
Author:
lowjoel
Message:

Reapplied my changes and reorganisations after Kaz accidentally removed them.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/eraser6/Manager/PRNG.cs

    r476 r478  
    44 * Original Author: Joel Low <lowjoel@users.sourceforge.net> 
    55 * Modified By: Kasra Nasiri <cjax@users.sourceforge.net> @10/7/2008 
     6 * Modified By: 
    67 *  
    78 * This file is part of Eraser. 
     
    2728using System.Security.Cryptography; 
    2829using System.Runtime.InteropServices; 
     30using System.Diagnostics; 
     31using System.Reflection; 
     32using System.IO; 
     33using Microsoft.Win32.SafeHandles; 
    2934using Eraser.Util; 
    30 using Microsoft.Win32.SafeHandles; 
    31 using System.IO; 
    3235 
    3336namespace Eraser.Manager 
     
    201204        /// The entropy thread gathering entropy for the RNGs. 
    202205        /// </summary> 
    203         internal EntropyThread entropyThread = new EntropyThread(); 
     206        internal EntropyPoller entropyThread = new EntropyPoller(); 
    204207 
    205208        /// <summary> 
     
    211214    /// <summary> 
    212215    /// A class which uses EntropyPoll class to fetch system data as a source of 
    213     /// randomness at "reqular" but "random" intervals 
     216    /// randomness at "regular" but "random" intervals 
    214217    /// </summary> 
    215     class EntropyPoller : EntropySource 
     218    class EntropyPoller 
    216219    { 
    217220        public EntropyPoller() 
     
    225228            thread.Start(); 
    226229        } 
    227          
     230 
    228231        /// <summary> 
    229232        /// The PRNG entropy thread. This thread will run in the background, getting 
     
    236239            DateTime lastAddedEntropy = DateTime.Now; 
    237240            TimeSpan managerEntropySpan = new TimeSpan(0, 10, 0); 
    238             System.Diagnostics.Stopwatch st = new System.Diagnostics.Stopwatch(); 
    239             while (thread.ThreadState != ThreadState.AbortRequested) 
     241            Stopwatch st = new Stopwatch(); 
     242 
     243            while (thread.ThreadState != System.Threading.ThreadState.AbortRequested) 
    240244            { 
    241245                st.Start(); 
    242                 {                    
    243                     FastAddEntropy(); 
     246                { 
     247                    FastAddEntropy(); 
    244248                    SlowAddEntropy(); 
    245249                } 
     
    275279    public class EntropySource 
    276280    { 
    277         public EntropySource() 
    278         { 
    279             //Create the pool. 
    280             pool = new byte[poolSize]; // {512,1024} bytes 
    281  
    282             //Initialize the pool with some default information. 
    283             { 
    284                 //Process startup information 
    285                 KernelAPI.STARTUPINFO startupInfo = new KernelAPI.STARTUPINFO(); 
    286                 KernelAPI.GetStartupInfo(out startupInfo); 
    287                 AddEntropy(startupInfo); 
    288  
    289                 //System information 
    290                 KernelAPI.SYSTEM_INFO systemInfo = new KernelAPI.SYSTEM_INFO(); 
    291                 KernelAPI.GetSystemInfo(out systemInfo); 
    292                 AddEntropy(systemInfo); 
    293  
    294                 FastAddEntropy(); 
    295                 SlowAddEntropy(); 
    296  
    297                 // set the default PRF algorithm 
    298                 PRFAlgorithm = PRFAlgorithms.SHA512; 
    299                 MixPool(); 
    300             } 
    301  
    302             // apply whitening effect 
    303             PRFAlgorithm = PRFAlgorithms.RIPEMD160; 
    304             MixPool(); 
    305  
    306             // set back to default hash algorithm 
    307             PRFAlgorithm = PRFAlgorithms.SHA512; 
    308         } 
    309  
    310281        /// <summary> 
    311282        /// The algorithm used for mixing 
    312283        /// </summary> 
    313         public enum PRFAlgorithms : int 
     284        private enum PRFAlgorithms 
    314285        { 
    315286            MD5, 
     
    321292        }; 
    322293 
    323         /// <summary> 
    324         /// Property sheet for PRF algorithm 
    325         /// </summary> 
    326         public PRFAlgorithms PRFAlgorithm 
    327         { 
    328             get 
    329             { 
    330                 return prfAlgorithm; 
    331             } 
    332             set 
    333             { 
    334                 prfAlgorithm = value; 
    335             } 
    336         } 
    337          
     294        public EntropySource() 
     295        { 
     296            //Create the pool. 
     297            pool = new byte[sizeof(uint) * 128]; 
     298 
     299            //Initialize the pool with some default information. 
     300            { 
     301                //Process startup information 
     302                KernelAPI.STARTUPINFO startupInfo = new KernelAPI.STARTUPINFO(); 
     303                KernelAPI.GetStartupInfo(out startupInfo); 
     304                AddEntropy(startupInfo); 
     305 
     306                //System information 
     307                KernelAPI.SYSTEM_INFO systemInfo = new KernelAPI.SYSTEM_INFO(); 
     308                KernelAPI.GetSystemInfo(out systemInfo); 
     309                AddEntropy(systemInfo); 
     310 
     311                FastAddEntropy(); 
     312                SlowAddEntropy(); 
     313 
     314                // set the default PRF algorithm 
     315                PRFAlgorithm = PRFAlgorithms.SHA512; 
     316                MixPool(); 
     317            } 
     318 
     319            // apply whitening effect 
     320            PRFAlgorithm = PRFAlgorithms.RIPEMD160; 
     321            MixPool(); 
     322 
     323            // set back to default hash algorithm 
     324            PRFAlgorithm = PRFAlgorithms.SHA512; 
     325        } 
     326 
    338327        /// <summary> 
    339328        /// Retrieves the current contents of the entropy pool. 
     
    357346 
    358347        /// <summary> 
     348        /// Inverts the contents of the pool 
     349        /// </summary> 
     350        private void InvertPool() 
     351        { 
     352            lock (poolLock) 
     353                unsafe 
     354                { 
     355                    fixed (byte* fPool = pool) 
     356                    { 
     357                        uint* pPool = (uint*)fPool; 
     358                        uint poolLength = (uint)(pool.Length / sizeof(uint)); 
     359                        while (poolLength-- != 0) 
     360                            *pPool = (uint)(*pPool++ ^ unchecked((uint)-1)); 
     361                    } 
     362                } 
     363        } 
     364 
     365        /// <summary> 
     366        /// Mixes the contents of the pool. 
     367        /// </summary> 
     368        private void MixPool() 
     369        { 
     370            lock (poolLock) 
     371            { 
     372                //Mix the last 128 bytes first. 
     373                const int mixBlockSize = 128; 
     374                int hashSize = PRF.HashSize / 8; 
     375                PRF.ComputeHash(pool, pool.Length - mixBlockSize, mixBlockSize).CopyTo(pool, 0); 
     376 
     377                //Then mix the following bytes until wraparound is required 
     378                int i = 0; 
     379                for (; i < pool.Length - hashSize; i += hashSize) 
     380                    Buffer.BlockCopy(PRF.ComputeHash(pool, i, 
     381                        i + mixBlockSize >= pool.Length ? pool.Length - i : mixBlockSize), 
     382                        0, pool, i, i + hashSize >= pool.Length ? pool.Length - i : hashSize); 
     383 
     384                //Mix the remaining blocks which require copying from the front 
     385                byte[] combinedBuffer = new byte[mixBlockSize]; 
     386                for (; i < pool.Length; i += hashSize) 
     387                { 
     388                    Buffer.BlockCopy(pool, i, combinedBuffer, 0, pool.Length - i); 
     389 
     390                    Buffer.BlockCopy(pool, 0, combinedBuffer, pool.Length - i, 
     391                                mixBlockSize - (pool.Length - i)); 
     392 
     393                    Buffer.BlockCopy(PRF.ComputeHash(combinedBuffer, 0, mixBlockSize), 0, 
     394                        pool, i, pool.Length - i > hashSize ? hashSize : pool.Length - i); 
     395                } 
     396            } 
     397        } 
     398 
     399        /// <summary> 
    359400        /// Adds data which is random to the pool 
    360401        /// </summary> 
     
    367408                fixed (byte* pPool = pool) 
    368409                { 
    369                     //Add entropy to the pool by XORing every value with the given entropy. 
    370                     poolPosition = Unsafe.CircularMemoryXor(new IntPtr(pPool), new IntPtr(pEntropy), 
    371                                         poolPosition, poolSize, entropy.Length); 
    372                 } 
     410                    int size = entropy.Length; 
     411                    byte* mpEntropy = pEntropy; 
     412                    while (size > 0) 
     413                    { 
     414                        //Bring the pool position back to the front if we are at our end 
     415                        if (poolPosition >= pool.Length) 
     416                            poolPosition = 0; 
     417 
     418                        int amountToMix = Math.Min(size, pool.Length - poolPosition); 
     419                        MemoryXor(pPool + poolPosition, mpEntropy, amountToMix); 
     420                        mpEntropy = mpEntropy + amountToMix; 
     421                        size -= amountToMix; 
     422                    } 
     423                } 
     424        } 
     425 
     426        /// <summary> 
     427        /// XOR's memory a DWORD at a time. 
     428        /// </summary> 
     429        /// <param name="destination">The destination buffer to be XOR'ed</param> 
     430        /// <param name="source">The source buffer to XOR with</param> 
     431        /// <param name="size">The size of the source buffer</param> 
     432        private static unsafe void MemoryXor(byte* destination, byte* source, int size) 
     433        { 
     434            int wsize = size / sizeof(uint); 
     435            size -= wsize * sizeof(uint); 
     436            uint* d = (uint*)destination; 
     437            uint* s = (uint*)source; 
     438             
     439            while (wsize-- > 0) 
     440                *d++ ^= *s++; 
     441 
     442            if (size > 0) 
     443            { 
     444                byte* db = (byte*)d, 
     445                      ds = (byte*)s; 
     446                while (size-- > 0) 
     447                    *db++ ^= *ds++; 
     448            } 
    373449        } 
    374450 
     
    411487        /// quickly. 
    412488        /// </summary> 
    413         public void FastAddEntropy() 
     489        private void FastAddEntropy() 
    414490        { 
    415491            //Add the free disk space to the pool 
     
    490566        /// relatively slowly compared to the FastAddEntropy function. 
    491567        /// </summary> 
    492         public void SlowAddEntropy() 
     568        private void SlowAddEntropy() 
    493569        { 
    494570            //NetAPI statistics 
     
    582658                AddEntropy(cryptGenRandom); 
    583659        } 
    584          
    585         /// <summary> 
    586         /// Inverts the contents of the pool 
    587         /// </summary> 
    588         private void InvertPool() 
    589         { 
    590             lock (poolLock) 
    591                 unsafe 
    592                 { 
    593                     fixed (byte* fPool = pool) 
    594                     { 
    595                         uint* pPool = (uint*)fPool; 
    596                         uint poolLength = (uint)(pool.Length / sizeof(uint)); 
    597                         while (poolLength-- != 0) 
    598                             *pPool = (uint)(*pPool++ ^ unchecked((uint)-1)); 
    599                     } 
    600                 } 
    601         } 
    602  
    603         /// <summary> 
    604         /// Creates an instance of the requested PRF 
    605         /// </summary> 
    606         private void CheckPRF() 
    607         { 
    608             switch (prfAlgorithm) 
    609             { 
    610                 case PRFAlgorithms.MD5: PRF = new MD5CryptoServiceProvider(); break; 
    611                 case PRFAlgorithms.SHA1: PRF = new SHA1Managed(); break; 
    612                 case PRFAlgorithms.RIPEMD160: PRF = new RIPEMD160Managed(); break; 
    613                 case PRFAlgorithms.SHA256: PRF = new SHA256Managed(); break; 
    614                 case PRFAlgorithms.SHA384: PRF = new SHA384Managed(); break; 
    615                 default: /*SHA512: */ PRF = new SHA512Managed(); break; 
    616             } 
    617         } 
    618  
    619         /// <summary> 
    620         /// Mixes the contents of the pool. 
    621         /// </summary> 
    622         private void MixPool() 
    623         { 
    624             CheckPRF(); 
    625  
    626             lock (poolLock) 
    627             { 
    628                 //Mix the last 128 bytes first. 
    629                 const int mixBlockSize = 128; 
    630                 int hashSize = PRF.HashSize / 8; 
    631                 PRF.ComputeHash(pool, pool.Length - mixBlockSize, mixBlockSize).CopyTo(pool, 0); 
    632  
    633                 //Then mix the following bytes until wraparound is required 
    634                 int i = 0; 
    635                 for (; i < pool.Length - hashSize; i += hashSize) 
    636                     Buffer.BlockCopy(PRF.ComputeHash(pool, i, 
    637                         i + mixBlockSize >= pool.Length ? pool.Length - i : mixBlockSize), 
    638                         0, pool, i, i + hashSize >= pool.Length ? pool.Length - i : hashSize); 
    639  
    640                 //Mix the remaining blocks which require copying from the front 
    641                 byte[] combinedBuffer = new byte[mixBlockSize]; 
    642                 for (; i < pool.Length; i += hashSize) 
    643                 { 
    644                     Buffer.BlockCopy(pool, i, combinedBuffer, 0, pool.Length - i); 
    645  
    646                     Buffer.BlockCopy(pool, 0, combinedBuffer, pool.Length - i, 
    647                                 mixBlockSize - (pool.Length - i)); 
    648  
    649                     Buffer.BlockCopy(PRF.ComputeHash(combinedBuffer, 0, mixBlockSize), 0, 
    650                         pool, i, pool.Length - i > hashSize ? hashSize : pool.Length - i); 
    651                 } 
    652             } 
    653         } 
    654660 
    655661        /// <summary> 
    656662        /// PRF algorithm handle 
    657663        /// </summary> 
    658         private HashAlgorithm PRF; 
     664        private HashAlgorithm PRF 
     665        { 
     666            get 
     667            { 
     668                Type type = null; 
     669                switch (PRFAlgorithm) 
     670                { 
     671                    case PRFAlgorithms.MD5: 
     672                        type = typeof(MD5CryptoServiceProvider); 
     673                        break; 
     674                    case PRFAlgorithms.SHA1: 
     675                        type = typeof(SHA1Managed); 
     676                        break; 
     677                    case PRFAlgorithms.RIPEMD160: 
     678                        type = typeof(RIPEMD160Managed); 
     679                        break; 
     680                    case PRFAlgorithms.SHA256: 
     681                        type = typeof(SHA256Managed); 
     682                        break; 
     683                    case PRFAlgorithms.SHA384: 
     684                        type = typeof(SHA384Managed); 
     685                        break; 
     686                    default: 
     687                        type = typeof(SHA512Managed); 
     688                        break; 
     689                } 
     690 
     691                if (type.IsInstanceOfType(prfCache)) 
     692                    return prfCache; 
     693                ConstructorInfo hashConstructor = type.GetConstructor(Type.EmptyTypes); 
     694                return prfCache = (HashAlgorithm)hashConstructor.Invoke(null); 
     695            } 
     696        } 
     697 
     698        /// <summary> 
     699        /// The last created PRF algorithm handle. 
     700        /// </summary> 
     701        private HashAlgorithm prfCache; 
    659702 
    660703        /// <summary> 
    661704        /// PRF algorithm identifier 
    662705        /// </summary> 
    663         private PRFAlgorithms prfAlgorithm; 
    664  
    665         /// <summary> 
    666         /// size of the netropy pool, should allways be exponent of 2. 
    667         /// </summary> 
    668         const int poolSize = sizeof(uint) * 128; 
    669  
    670         /// <summary> 
    671         /// Modulus of pool size 
    672         /// </summary> 
    673         const int poolMod = poolSize - 1; 
     706        private PRFAlgorithms PRFAlgorithm; 
    674707 
    675708        /// <summary> 
    676709        /// The pool of data which we currently maintain. 
    677710        /// </summary> 
    678         byte[] pool; 
     711        private byte[] pool; 
    679712 
    680713        /// <summary> 
    681714        /// The next position where entropy will be added to the pool. 
    682715        /// </summary> 
    683         int poolPosition = 0; 
     716        private int poolPosition = 0; 
    684717 
    685718        /// <summary> 
    686719        /// The lock guarding the pool array and the current entropy addition index. 
    687720        /// </summary> 
    688         object poolLock = new object(); 
     721        private object poolLock = new object(); 
    689722    } 
    690723} 
Note: See TracChangeset for help on using the changeset viewer.