// Generate a mask using a specific set and byte count. // // This implementation is based on the description in PKCS #1 v2.1. // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf public override byte[] GenerateMask(byte[] rgbSeed, int cbReturn) { // Validate the parameters. if (rgbSeed == null) { throw new ArgumentNullException("rgbSeed"); } else if (cbReturn < 0) { throw new ArgumentOutOfRangeException ("cbReturn", _("ArgRange_NonNegative")); } // Create the final mask buffer. byte[] mask = new byte [cbReturn]; // Create the hash algorithm instance. HashAlgorithm alg = HashAlgorithm.Create(hashName); // Create the mask. byte[] numbuf = new byte [4]; byte[] hash; int hashSize = alg.HashSize; int count = 0; int index = 0; while (index < cbReturn) { numbuf[0] = (byte)(count >> 24); numbuf[1] = (byte)(count >> 16); numbuf[2] = (byte)(count >> 8); numbuf[3] = (byte)count; alg.InternalHashCore(rgbSeed, 0, rgbSeed.Length); alg.InternalHashCore(numbuf, 0, 4); hash = alg.InternalHashFinal(); if (hashSize <= (cbReturn - index)) { Array.Copy(hash, 0, mask, index, hashSize); } else { Array.Copy(hash, 0, mask, index, cbReturn - index); } Array.Clear(hash, 0, hash.Length); alg.Initialize(); ++count; index += hashSize; } Array.Clear(numbuf, 0, numbuf.Length); // The mask has been generated. return(null); }
// Prepare the hash for the initial call to "HashCore" or "HashFinal". private void Prepare() { if (alg == null) { alg = SHA1.Create(algName); if (KeyValue != null) { alg.InternalHashCore(KeyValue, 0, KeyValue.Length); } } }
// Write data to the underlying hash algorithm. protected override void HashCore(byte[] array, int ibStart, int cbSize) { Prepare(); alg.InternalHashCore(array, ibStart, cbSize); }
// Get the pseudo-random key bytes. public override byte[] GetBytes(int cb) { // Initialize the pseudo-random generator. if (hashAlgorithm == null) { if (strHashName == null) { strHashName = "MD5"; } hashAlgorithm = HashAlgorithm.Create(strHashName); blockNum = 1; size = hashAlgorithm.HashSize; posn = size; } // Allocate the result array and then fill it. byte[] result = new byte [cb]; int index = 0; int templen; while (cb > 0) { // Copy existing data from the previous block. if (posn < size) { templen = (size - posn); if (cb < templen) { templen = cb; } Array.Copy(block, posn, result, index, templen); cb -= templen; index -= templen; posn = size; if (cb <= 0) { break; } } // Generate a new block using the hash algorithm. if (strPassword != null) { byte[] pwd = Encoding.UTF8.GetBytes(strPassword); hashAlgorithm.InternalHashCore(pwd, 0, pwd.Length); Array.Clear(pwd, 0, pwd.Length); } if (rgbSalt != null) { hashAlgorithm.InternalHashCore (rgbSalt, 0, rgbSalt.Length); } byte[] numbuf = new byte [4]; numbuf[0] = (byte)(blockNum >> 24); numbuf[1] = (byte)(blockNum >> 16); numbuf[2] = (byte)(blockNum >> 8); numbuf[3] = (byte)blockNum; hashAlgorithm.InternalHashCore(numbuf, 0, 4); Array.Clear(numbuf, 0, numbuf.Length); byte[] lastHash = hashAlgorithm.InternalHashFinal(); hashAlgorithm.Initialize(); templen = iterations; byte[] temphash; while (templen > 1) { hashAlgorithm.InternalHashCore (lastHash, 0, lastHash.Length); temphash = hashAlgorithm.InternalHashFinal(); hashAlgorithm.Initialize(); for (int tempindex = 0; tempindex < lastHash.Length; ++tempindex) { lastHash[tempindex] ^= temphash[tempindex]; } Array.Clear(temphash, 0, temphash.Length); --templen; } if (block != null) { Array.Clear(block, 0, block.Length); } block = lastHash; ++blockNum; posn = 0; } // Return the result array to the caller. return(result); }
// Prepare the hash for the initial call to "HashCore" or "HashFinal". private void Prepare() { if(alg == null) { alg = SHA1.Create(algName); if(KeyValue != null) { alg.InternalHashCore(KeyValue, 0, KeyValue.Length); } } }