Changeset 443
- Timestamp:
- 10/17/2008 10:04:30 AM (5 years ago)
- File:
-
- 1 edited
-
branches/eraser6/Manager/PRNG.cs (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/eraser6/Manager/PRNG.cs
r348 r443 3 3 * Copyright 2008 The Eraser Project 4 4 * Original Author: Joel Low <lowjoel@users.sourceforge.net> 5 * Modified By: 5 * Modified By: Kasra Nasiri <cjax@users.sourceforge.net> @10/7/2008 6 6 * 7 7 * This file is part of Eraser. … … 215 215 { 216 216 public EntropyThread() 217 { 217 { 218 218 //Create the pool. 219 pool = new byte[ 512];219 pool = new byte[poolSize]; // {512,1024} bytes 220 220 221 221 //Initialize the pool with some default information. … … 233 233 FastAddEntropy(); 234 234 SlowAddEntropy(); 235 236 // set the default PRF algorithm 237 PRFAlgorithm = PRFAlgorithms.SHA512; 235 238 MixPool(); 236 239 } 240 241 // apply whitening effect 242 PRFAlgorithm = PRFAlgorithms.RIPEMD160; 243 MixPool(); 244 245 // set back to default hash algorithm 246 PRFAlgorithm = PRFAlgorithms.SHA512; 237 247 238 248 //Then start the thread which maintains the pool. … … 243 253 ); 244 254 thread.Start(); 255 } 256 257 /// <summary> 258 /// The algorithm used for mixing 259 /// </summary> 260 public enum PRFAlgorithms : int 261 { 262 MD5, 263 SHA1, 264 RIPEMD160, 265 SHA256, 266 SHA384, 267 SHA512, 268 }; 269 270 /// <summary> 271 /// Property sheet for PRF algorithm 272 /// </summary> 273 public PRFAlgorithms PRFAlgorithm 274 { 275 get 276 { 277 return prfAlgorithm; 278 } 279 set 280 { 281 prfAlgorithm = value; 282 } 245 283 } 246 284 … … 262 300 //This entropy thread will utilize a polling loop. 263 301 DateTime lastAddedEntropy = DateTime.Now; 302 TimeSpan ManagerEntropySpan = new TimeSpan(0, 10, 0); 303 System.Diagnostics.Stopwatch st = new System.Diagnostics.Stopwatch(); 264 304 while (thread.ThreadState != ThreadState.AbortRequested) 265 305 { 266 FastAddEntropy(); 267 SlowAddEntropy(); 268 Thread.Sleep(3000); 306 st.Start(); 307 { 308 FastAddEntropy(); 309 SlowAddEntropy(); 310 } 311 312 st.Stop(); 313 Thread.Sleep(2000 + (int)(st.ElapsedTicks % 2049L)); 314 st.Reset(); 269 315 270 316 //Send entropy to the PRNGs for new seeds. 271 if (DateTime.Now - lastAddedEntropy > new TimeSpan(0, 10, 0))317 if (DateTime.Now - lastAddedEntropy > ManagerEntropySpan) 272 318 ManagerLibrary.Instance.PRNGManager.AddEntropy(GetPool()); 273 319 } … … 300 346 { 301 347 lock (poolLock) 302 unsafe 303 { 304 fixed (byte* fPool = pool) 305 { 306 int* pPool = (int*)fPool; 307 int poolLength = pool.Length / sizeof(int); 308 while (poolLength-- != 0) 309 *pPool = (int)(*pPool++ ^ unchecked((uint)-1)); 310 } 348 unsafe 349 { 350 fixed (byte* fPool = pool) 351 { 352 uint* pPool = (uint*)fPool; 353 uint poolLength = (uint)(pool.Length / sizeof(uint)); 354 while (poolLength-- != 0) 355 *pPool = (uint)(*pPool++ ^ unchecked((uint)-1)); 356 } 357 } 358 } 359 360 /// <summary> 361 /// Creates an instance of the requested PRF 362 /// </summary> 363 private void CheckPRF() 364 { 365 switch (prfAlgorithm) 366 { 367 case PRFAlgorithms.MD5: PRF = new MD5CryptoServiceProvider(); break; 368 case PRFAlgorithms.SHA1: PRF = new SHA1Managed(); break; 369 case PRFAlgorithms.RIPEMD160: PRF = new RIPEMD160Managed(); break; 370 case PRFAlgorithms.SHA256: PRF = new SHA256Managed(); break; 371 case PRFAlgorithms.SHA384: PRF = new SHA384Managed(); break; 372 default: /*SHA512: */ PRF = new SHA512Managed(); break; 311 373 } 312 374 } … … 317 379 private void MixPool() 318 380 { 381 CheckPRF(); 382 319 383 lock (poolLock) 320 using (SHA512 hash = SHA512.Create())321 384 { 322 385 //Mix the last 128 bytes first. 323 386 const int mixBlockSize = 128; 324 int hashSize = hash.HashSize / 8;325 hash.ComputeHash(pool, pool.Length - mixBlockSize, mixBlockSize).CopyTo(pool, 0);387 int hashSize = PRF.HashSize / 8; 388 PRF.ComputeHash(pool, pool.Length - mixBlockSize, mixBlockSize).CopyTo(pool, 0); 326 389 327 390 //Then mix the following bytes until wraparound is required 328 391 int i = 0; 329 392 for (; i < pool.Length - hashSize; i += hashSize) 330 hash.ComputeHash(pool, i, mixBlockSize).CopyTo(pool, i); 331 393 Buffer.BlockCopy(PRF.ComputeHash(pool, i, 394 i + mixBlockSize >= pool.Length ? pool.Length - i : mixBlockSize), 395 0, pool, i, i + hashSize >= pool.Length ? pool.Length - i : hashSize); 396 332 397 //Mix the remaining blocks which require copying from the front 333 398 byte[] combinedBuffer = new byte[mixBlockSize]; 334 399 for (; i < pool.Length; i += hashSize) 335 400 { 336 for (int j = i; j < pool.Length; ++j) 337 combinedBuffer[j - i] = pool[j]; 338 for (int j = 0, k = mixBlockSize - (pool.Length - i); j < k; ++j) 339 combinedBuffer[j + pool.Length - i] = pool[j]; 340 hash.ComputeHash(combinedBuffer, 0, mixBlockSize).CopyTo(pool, i); 401 Buffer.BlockCopy(pool, i, combinedBuffer, 0, pool.Length - i); 402 403 Buffer.BlockCopy(pool, 0, combinedBuffer, pool.Length - i, 404 mixBlockSize - (pool.Length - i)); 405 406 Buffer.BlockCopy(PRF.ComputeHash(combinedBuffer, 0, mixBlockSize), 0, 407 pool, i, pool.Length-i > hashSize ? hashSize : pool.Length-i); 341 408 } 342 409 } … … 351 418 { 352 419 lock (poolLock) 353 fixed (byte* pEntropy = entropy) 354 { 355 //Add entropy to the pool by XORing every value with the given entropy. 356 byte* bytes = (byte*)pEntropy; 357 for (int i = 0; i < entropy.Length; ++i) 358 { 359 if (poolPosition == pool.Length) 360 poolPosition = 0; 361 pool[poolPosition++] ^= bytes[i]; 362 } 420 fixed (byte* pEntropy = entropy) 421 fixed (byte* pPool = pool) 422 { 423 //Add entropy to the pool by XORing every value with the given entropy. 424 poolPosition = CircularMemoryXor(new IntPtr(pPool), new IntPtr(pEntropy), 425 poolPosition, poolSize, entropy.Length); 426 } 427 } 428 429 /// <summary> 430 /// Optomised unmanaged circular memory xor 431 /// </summary> 432 /// <param name="dest">Destination Pointer</param> 433 /// <param name="source">Source Pointer</param> 434 /// <param name="size">Size in bytes</param> 435 private unsafe static int CircularMemoryXor(IntPtr destination, IntPtr source, 436 int destOffset, int destLength, int size) 437 { 438 uint* dest = (uint*)destination.ToPointer(); 439 uint* src = (uint*)source.ToPointer(); 440 while (size > 0) 441 { 442 if (size + destOffset < destLength) 443 { 444 IntPtr _gc = new IntPtr(destination.ToInt32() + destOffset); 445 MemoryXor(_gc, source, size); 446 destOffset += size; 447 size = 0; 448 } 449 else // (size + destOffset >= destLength) 450 { 451 IntPtr _gc = new IntPtr(destination.ToInt32() + destOffset); 452 MemoryXor(_gc, source, destLength - destOffset); 453 source = new IntPtr(source.ToInt32() + destLength - destOffset); 454 size -= destLength - destOffset; 455 destOffset = 0; 456 } 457 } 458 459 return destOffset; 460 } 461 462 private static unsafe void MemoryXor(IntPtr destination, IntPtr source, int size) 463 { 464 int wsize = size / sizeof(int); size -= wsize * sizeof(int); 465 uint* d = (uint*)destination.ToPointer(); 466 uint* s = (uint*)source.ToPointer(); 467 468 while (wsize-- > 0) *d++ ^= *s++; 469 470 if (size > 0) 471 { 472 byte* db = (byte*)d, ds = (byte*)s; 473 while (size-- > 0) *db++ ^= *ds++; 363 474 } 364 475 } … … 371 482 public unsafe void AddEntropy<T>(T entropy) where T : struct 372 483 { 373 int sizeofObject = Marshal.SizeOf(entropy);374 IntPtr memory = Marshal.AllocHGlobal(sizeofObject);375 484 try 376 485 { 377 Marshal.StructureToPtr(entropy, memory, false); 378 byte* pMemory = (byte*)memory.ToPointer(); 379 byte[] dest = new byte[sizeofObject]; 380 381 //Copy the memory 382 for (int i = 0; i != dest.Length; ++i) 383 dest[i] = *pMemory++; 384 385 //Add entropy 386 AddEntropy(dest); 387 } 388 finally 389 { 390 Marshal.FreeHGlobal(memory); 391 } 392 } 486 int sizeofObject = Marshal.SizeOf(entropy); 487 IntPtr memory = Marshal.AllocHGlobal(sizeofObject); 488 try 489 { 490 Marshal.StructureToPtr(entropy, memory, false); 491 byte[] dest = new byte[sizeofObject]; 492 493 //Copy the memory 494 Marshal.Copy(memory, dest, 0, sizeofObject); 495 496 //Add entropy 497 AddEntropy(dest); 498 } 499 finally 500 { 501 Marshal.FreeHGlobal(memory); 502 } 503 } 504 catch (OutOfMemoryException ex1) 505 { 506 // ignore this entropy source, we don't have enough memory! 507 string ignored = ex1.Message; 508 } 509 } 510 #if false 511 512 /// <summary> 513 /// Optomosed constant memory xor 514 /// </summary> 515 /// <param name="dest">Destination buffer</param> 516 /// <param name="value">value the destination should be xored against</param> 517 /// <param name="size">size of destination in bytes</param> 518 private static unsafe void MemoryXor(IntPtr dest, byte value, int size) 519 { 520 int wsize = size / sizeof(int); size -= wsize * sizeof(int); 521 uint* d = (uint*)dest.ToPointer(); 522 uint wvalue = 0; // a word containing values in correct endian 523 for (int i = 0; i < sizeof(uint); i++, wvalue <<= 8) wvalue |= value; 524 525 while (wsize-- > 0) *d++ ^= wvalue; 526 527 if (size > 0) // size%4 == 0 ? 528 { 529 byte* db = (byte*)d; 530 while (size-- > 0) 531 *db++ ^= value; 532 } 533 } 534 #endif 393 535 394 536 /// <summary> … … 430 572 AddEntropy(memoryStatus.ullAvailPhys); 431 573 AddEntropy(memoryStatus.ullAvailVirtual); 574 AddEntropy(memoryStatus); 432 575 } 433 576 … … 483 626 0, 0, out netAPIStats) == 0) 484 627 { 485 //Get the size of the buffer 486 uint size = 0; 487 NetAPI.NetApiBufferSize(netAPIStats, out size); 488 byte[] entropy = new byte[size]; 489 490 //Copy the buffer 491 fixed (byte* fEntropy = entropy) 628 try 492 629 { 493 byte* pSrc = (byte*)netAPIStats.ToPointer(); 494 byte* pEntropy = fEntropy; 495 while (size-- != 0) 496 *pEntropy++ = *pSrc++; 630 //Get the size of the buffer 631 uint size = 0; 632 NetAPI.NetApiBufferSize(netAPIStats, out size); 633 byte[] entropy = new byte[size]; 634 635 //Copy the buffer 636 Marshal.Copy(entropy, 0, netAPIStats, entropy.Length); 637 638 //And add it to the pool 639 AddEntropy(entropy); 497 640 } 498 499 //And add it to the pool 500 AddEntropy(entropy); 501 502 //Free the statistics buffer 503 NetAPI.NetApiBufferFree(netAPIStats); 641 finally 642 { 643 //Free the statistics buffer 644 NetAPI.NetApiBufferFree(netAPIStats); 645 } 504 646 } 505 647 } … … 554 696 { 555 697 byte[] entropy = new byte[dataWritten]; 556 for (int i = 0; i < dataWritten; ++i) 557 entropy[i] = infoBuffer[i]; 698 Buffer.BlockCopy(infoBuffer, 0, entropy, 0, (int)dataWritten); 558 699 AddEntropy(entropy); 559 700 totalEntropy += dataWritten; 560 701 } 561 702 } 703 704 AddEntropy(totalEntropy); 562 705 563 706 //Finally, our good friend CryptGenRandom() … … 568 711 569 712 /// <summary> 713 /// PRF algorithm handle 714 /// </summary> 715 private HashAlgorithm PRF; 716 717 /// <summary> 718 /// PRF algorithm identifier 719 /// </summary> 720 private PRFAlgorithms prfAlgorithm; 721 722 /// <summary> 570 723 /// The thread object. 571 724 /// </summary> 572 725 Thread thread; 726 727 /// <summary> 728 /// size of the netropy pool, should allways be exponent of 2. 729 /// </summary> 730 const int poolSize = sizeof(uint) * 128; 731 732 /// <summary> 733 /// Modulus of pool size 734 /// </summary> 735 const int poolMod = poolSize - 1; 573 736 574 737 /// <summary>
Note: See TracChangeset
for help on using the changeset viewer.
