Changeset 2566
- Timestamp:
- 3/21/2012 10:26:45 AM (15 months ago)
- Location:
- trunk/eraser
- Files:
-
- 2 edited
-
. (modified) (1 prop)
-
Eraser.Manager/EntropyPoller.cs (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/eraser
- Property svn:mergeinfo changed
/branches/eraser6/6.0 merged: 2563,2565
- Property svn:mergeinfo changed
-
trunk/eraser/Eraser.Manager/EntropyPoller.cs
r2516 r2566 42 42 { 43 43 /// <summary> 44 /// The algorithm used for mixing45 /// </summary>46 private enum PRFAlgorithms47 {48 Md5,49 Sha1,50 Ripemd160,51 Sha256,52 Sha384,53 Sha512,54 };55 56 /// <summary>57 44 /// Constructor. 58 45 /// </summary> … … 60 47 { 61 48 //Create the pool. 62 pool = new byte[sizeof(uint) << 7];49 Pool = new byte[sizeof(uint) << 7]; 63 50 64 51 //Then start the thread which maintains the pool. … … 74 61 private void Main() 75 62 { 76 //This entropy thread will utilize a polling loop. 63 //Maintain the time we last provided entropy to the PRNGs. We will only 64 //provide entropy every 10 minutes. 77 65 DateTime lastAddedEntropy = DateTime.Now; 78 66 TimeSpan managerEntropySpan = new TimeSpan(0, 10, 0); 79 Stopwatch st = new Stopwatch();80 67 81 68 while (Thread.ThreadState != System.Threading.ThreadState.AbortRequested) 82 69 { 83 st.Start();84 70 lock (EntropySources) 85 71 foreach (IEntropySource src in EntropySources) … … 89 75 } 90 76 91 st.Stop(); 92 // 2049 = bin '100000000001' ==> great avalanche 93 Thread.Sleep(2000 + (int)(st.ElapsedTicks % 2049L)); 94 st.Reset(); 77 //Sleep for a "random" period between roughly [2, 5) seconds from now 78 Thread.Sleep(2000 + (int)(DateTime.Now.Ticks % 2999)); 95 79 96 80 // Send entropy to the PRNGs for new seeds. 97 if (DateTime.Now - lastAddedEntropy > managerEntropySpan) 81 DateTime now = DateTime.Now; 82 if (now - lastAddedEntropy > managerEntropySpan) 83 { 98 84 Host.Instance.Prngs.AddEntropy(GetPool()); 85 lastAddedEntropy = now; 86 } 99 87 } 100 88 } … … 120 108 MixPool(); 121 109 122 //Apply whitening effect 123 PRFAlgorithm = PRFAlgorithms.Ripemd160; 124 MixPool(); 125 PRFAlgorithm = PRFAlgorithms.Sha512; 110 //Apply "whitening" effect. Try to mix the pool using RIPEMD-160 to strengthen 111 //the cryptographic strength of the pool. 112 //There is a need to catch the InvalidOperationException because if Eraser is 113 //running under an OS with FIPS-compliance mode the RIPEMD-160 algorithm cannot 114 //be used. 115 try 116 { 117 using (HashAlgorithm hash = new RIPEMD160Managed()) 118 MixPool(hash); 119 } 120 catch (InvalidOperationException) 121 { 122 } 126 123 } 127 124 … … 137 134 138 135 //Return a safe copy 139 lock ( poolLock)140 { 141 byte[] result = new byte[ pool.Length];142 pool.CopyTo(result, 0);136 lock (PoolLock) 137 { 138 byte[] result = new byte[Pool.Length]; 139 Pool.CopyTo(result, 0); 143 140 144 141 return result; … … 151 148 private void InvertPool() 152 149 { 153 lock ( poolLock)150 lock (PoolLock) 154 151 unsafe 155 152 { 156 fixed (byte* fPool = pool)153 fixed (byte* fPool = Pool) 157 154 { 158 155 uint* pPool = (uint*)fPool; 159 uint poolLength = (uint)( pool.Length / sizeof(uint));156 uint poolLength = (uint)(Pool.Length / sizeof(uint)); 160 157 while (poolLength-- != 0) 161 158 *pPool = (uint)(*pPool++ ^ uint.MaxValue); … … 167 164 /// Mixes the contents of the pool. 168 165 /// </summary> 169 private void MixPool( )170 { 171 lock ( poolLock)166 private void MixPool(HashAlgorithm hash) 167 { 168 lock (PoolLock) 172 169 { 173 170 //Mix the last 128 bytes first. 174 171 const int mixBlockSize = 128; 175 int hashSize = PRF.HashSize / 8;176 PRF.ComputeHash(pool, pool.Length - mixBlockSize, mixBlockSize).CopyTo(pool, 0);172 int hashSize = hash.HashSize / 8; 173 hash.ComputeHash(Pool, Pool.Length - mixBlockSize, mixBlockSize).CopyTo(Pool, 0); 177 174 178 175 //Then mix the following bytes until wraparound is required 179 176 int i = 0; 180 for (; i < pool.Length - hashSize; i += hashSize)181 Buffer.BlockCopy( PRF.ComputeHash(pool, i,182 i + mixBlockSize >= pool.Length ? pool.Length - i : mixBlockSize),183 0, pool, i, i + hashSize >= pool.Length ? pool.Length - i : hashSize);177 for (; i < Pool.Length - hashSize; i += hashSize) 178 Buffer.BlockCopy(hash.ComputeHash(Pool, i, 179 i + mixBlockSize >= Pool.Length ? Pool.Length - i : mixBlockSize), 180 0, Pool, i, i + hashSize >= Pool.Length ? Pool.Length - i : hashSize); 184 181 185 182 //Mix the remaining blocks which require copying from the front 186 183 byte[] combinedBuffer = new byte[mixBlockSize]; 187 for (; i < pool.Length; i += hashSize) 188 { 189 Buffer.BlockCopy(pool, i, combinedBuffer, 0, pool.Length - i); 190 191 Buffer.BlockCopy(pool, 0, combinedBuffer, pool.Length - i, 192 mixBlockSize - (pool.Length - i)); 193 194 Buffer.BlockCopy(PRF.ComputeHash(combinedBuffer, 0, mixBlockSize), 0, 195 pool, i, pool.Length - i > hashSize ? hashSize : pool.Length - i); 196 } 197 } 184 for (; i < Pool.Length; i += hashSize) 185 { 186 Buffer.BlockCopy(Pool, i, combinedBuffer, 0, Pool.Length - i); 187 188 Buffer.BlockCopy(Pool, 0, combinedBuffer, Pool.Length - i, 189 mixBlockSize - (Pool.Length - i)); 190 191 Buffer.BlockCopy(hash.ComputeHash(combinedBuffer, 0, mixBlockSize), 0, 192 Pool, i, Pool.Length - i > hashSize ? hashSize : Pool.Length - i); 193 } 194 } 195 } 196 197 /// <summary> 198 /// Mixes the contents of the entropy pool using the currently specified default 199 /// algorithm. 200 /// </summary> 201 private void MixPool() 202 { 203 using (HashAlgorithm hash = new SHA1CryptoServiceProvider()) 204 MixPool(hash); 198 205 } 199 206 … … 205 212 public unsafe void AddEntropy(byte[] entropy) 206 213 { 207 lock ( poolLock)214 lock (PoolLock) 208 215 fixed (byte* pEntropy = entropy) 209 fixed (byte* pPool = pool)216 fixed (byte* pPool = Pool) 210 217 { 211 218 int size = entropy.Length; … … 214 221 { 215 222 //Bring the pool position back to the front if we are at our end 216 if ( poolPosition >= pool.Length)217 poolPosition = 0;218 219 int amountToMix = Math.Min(size, pool.Length - poolPosition);220 MemoryXor(pPool + poolPosition, mpEntropy, amountToMix);223 if (PoolPosition >= Pool.Length) 224 PoolPosition = 0; 225 226 int amountToMix = Math.Min(size, Pool.Length - PoolPosition); 227 MemoryXor(pPool + PoolPosition, mpEntropy, amountToMix); 221 228 mpEntropy = mpEntropy + amountToMix; 222 229 size -= amountToMix; … … 255 262 256 263 /// <summary> 257 /// PRF algorithm handle258 /// </summary>259 private HashAlgorithm PRF260 {261 get262 {263 Type type = null;264 switch (PRFAlgorithm)265 {266 case PRFAlgorithms.Md5:267 type = typeof(MD5CryptoServiceProvider);268 break;269 case PRFAlgorithms.Sha1:270 type = typeof(SHA1Managed);271 break;272 case PRFAlgorithms.Ripemd160:273 type = typeof(RIPEMD160Managed);274 break;275 case PRFAlgorithms.Sha256:276 type = typeof(SHA256Managed);277 break;278 case PRFAlgorithms.Sha384:279 type = typeof(SHA384Managed);280 break;281 default:282 type = typeof(SHA512Managed);283 break;284 }285 286 if (type.IsInstanceOfType(prfCache))287 return prfCache;288 ConstructorInfo hashConstructor = type.GetConstructor(Type.EmptyTypes);289 return prfCache = (HashAlgorithm)hashConstructor.Invoke(null);290 }291 }292 293 /// <summary>294 /// The last created PRF algorithm handle.295 /// </summary>296 private HashAlgorithm prfCache;297 298 /// <summary>299 /// PRF algorithm identifier300 /// </summary>301 private PRFAlgorithms PRFAlgorithm = PRFAlgorithms.Sha512;302 303 /// <summary>304 264 /// The pool of data which we currently maintain. 305 265 /// </summary> 306 private byte[] pool;266 private byte[] Pool; 307 267 308 268 /// <summary> 309 269 /// The next position where entropy will be added to the pool. 310 270 /// </summary> 311 private int poolPosition;271 private int PoolPosition; 312 272 313 273 /// <summary> 314 274 /// The lock guarding the pool array and the current entropy addition index. 315 275 /// </summary> 316 private object poolLock = new object();276 private object PoolLock = new object(); 317 277 318 278 /// <summary>
Note: See TracChangeset
for help on using the changeset viewer.
