Changeset 478
- Timestamp:
- 11/9/2008 8:54:16 AM (5 years ago)
- File:
-
- 1 edited
-
branches/eraser6/Manager/PRNG.cs (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/eraser6/Manager/PRNG.cs
r476 r478 4 4 * Original Author: Joel Low <lowjoel@users.sourceforge.net> 5 5 * Modified By: Kasra Nasiri <cjax@users.sourceforge.net> @10/7/2008 6 * Modified By: 6 7 * 7 8 * This file is part of Eraser. … … 27 28 using System.Security.Cryptography; 28 29 using System.Runtime.InteropServices; 30 using System.Diagnostics; 31 using System.Reflection; 32 using System.IO; 33 using Microsoft.Win32.SafeHandles; 29 34 using Eraser.Util; 30 using Microsoft.Win32.SafeHandles;31 using System.IO;32 35 33 36 namespace Eraser.Manager … … 201 204 /// The entropy thread gathering entropy for the RNGs. 202 205 /// </summary> 203 internal Entropy Thread entropyThread = new EntropyThread();206 internal EntropyPoller entropyThread = new EntropyPoller(); 204 207 205 208 /// <summary> … … 211 214 /// <summary> 212 215 /// A class which uses EntropyPoll class to fetch system data as a source of 213 /// randomness at "re qular" but "random" intervals216 /// randomness at "regular" but "random" intervals 214 217 /// </summary> 215 class EntropyPoller : EntropySource218 class EntropyPoller 216 219 { 217 220 public EntropyPoller() … … 225 228 thread.Start(); 226 229 } 227 230 228 231 /// <summary> 229 232 /// The PRNG entropy thread. This thread will run in the background, getting … … 236 239 DateTime lastAddedEntropy = DateTime.Now; 237 240 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) 240 244 { 241 245 st.Start(); 242 { 243 FastAddEntropy();246 { 247 FastAddEntropy(); 244 248 SlowAddEntropy(); 245 249 } … … 275 279 public class EntropySource 276 280 { 277 public EntropySource()278 {279 //Create the pool.280 pool = new byte[poolSize]; // {512,1024} bytes281 282 //Initialize the pool with some default information.283 {284 //Process startup information285 KernelAPI.STARTUPINFO startupInfo = new KernelAPI.STARTUPINFO();286 KernelAPI.GetStartupInfo(out startupInfo);287 AddEntropy(startupInfo);288 289 //System information290 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 algorithm298 PRFAlgorithm = PRFAlgorithms.SHA512;299 MixPool();300 }301 302 // apply whitening effect303 PRFAlgorithm = PRFAlgorithms.RIPEMD160;304 MixPool();305 306 // set back to default hash algorithm307 PRFAlgorithm = PRFAlgorithms.SHA512;308 }309 310 281 /// <summary> 311 282 /// The algorithm used for mixing 312 283 /// </summary> 313 p ublic enum PRFAlgorithms : int284 private enum PRFAlgorithms 314 285 { 315 286 MD5, … … 321 292 }; 322 293 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 338 327 /// <summary> 339 328 /// Retrieves the current contents of the entropy pool. … … 357 346 358 347 /// <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> 359 400 /// Adds data which is random to the pool 360 401 /// </summary> … … 367 408 fixed (byte* pPool = pool) 368 409 { 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 } 373 449 } 374 450 … … 411 487 /// quickly. 412 488 /// </summary> 413 p ublicvoid FastAddEntropy()489 private void FastAddEntropy() 414 490 { 415 491 //Add the free disk space to the pool … … 490 566 /// relatively slowly compared to the FastAddEntropy function. 491 567 /// </summary> 492 p ublicvoid SlowAddEntropy()568 private void SlowAddEntropy() 493 569 { 494 570 //NetAPI statistics … … 582 658 AddEntropy(cryptGenRandom); 583 659 } 584 585 /// <summary>586 /// Inverts the contents of the pool587 /// </summary>588 private void InvertPool()589 {590 lock (poolLock)591 unsafe592 {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 PRF605 /// </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 required634 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 front641 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 }654 660 655 661 /// <summary> 656 662 /// PRF algorithm handle 657 663 /// </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; 659 702 660 703 /// <summary> 661 704 /// PRF algorithm identifier 662 705 /// </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; 674 707 675 708 /// <summary> 676 709 /// The pool of data which we currently maintain. 677 710 /// </summary> 678 byte[] pool;711 private byte[] pool; 679 712 680 713 /// <summary> 681 714 /// The next position where entropy will be added to the pool. 682 715 /// </summary> 683 int poolPosition = 0;716 private int poolPosition = 0; 684 717 685 718 /// <summary> 686 719 /// The lock guarding the pool array and the current entropy addition index. 687 720 /// </summary> 688 object poolLock = new object();721 private object poolLock = new object(); 689 722 } 690 723 }
Note: See TracChangeset
for help on using the changeset viewer.
