}// DeriveKey() internal static void DeriveKey(HMAC keyedHmac, ArraySegment<byte> bufferSegment, ArraySegment<byte> derivedOutput, uint counter = 1) { int derivedOutputCount = derivedOutput.Count, derivedOutputOffset = derivedOutput.Offset; byte[] K_i = null; HMAC2 keyedHmac2 = keyedHmac as HMAC2; checked { // Calculate each K_i value and copy the leftmost bits to the output buffer as appropriate. for (var counterStruct = new Utils.IntStruct { UintValue = counter }; derivedOutputCount > 0; ++counterStruct.UintValue) { counterStruct.ToBEBytes(bufferSegment.Array, bufferSegment.Offset); // update the counter within the buffer if (keyedHmac2 == null) { K_i = keyedHmac.ComputeHash(bufferSegment.Array, bufferSegment.Offset, bufferSegment.Count); } else { keyedHmac2.TransformBlock(bufferSegment.Array, bufferSegment.Offset, bufferSegment.Count, null, 0); keyedHmac2.TransformFinalBlock(bufferSegment.Array, 0, 0); K_i = keyedHmac2.HashInner; } // copy the leftmost bits of K_i into the output buffer int numBytesToCopy = derivedOutputCount > K_i.Length ? K_i.Length : derivedOutputCount;//Math.Min(derivedOutputCount, K_i.Length); Utils.BlockCopy(K_i, 0, derivedOutput.Array, derivedOutputOffset, numBytesToCopy); derivedOutputOffset += numBytesToCopy; derivedOutputCount -= numBytesToCopy; }// for }// checked if (keyedHmac2 == null && K_i != null) Array.Clear(K_i, 0, K_i.Length); /* clean up needed only when HMAC implementation is not HMAC2 */ }// DeriveKey()
public override byte[] GetBytes(int countBytes) { var okm = new byte[countBytes]; if (k_unused > 0) { var min = k_unused > countBytes ? countBytes : k_unused;//Math.Min(k_unused, countBytes); Utils.BlockCopy(k, hashLength - k_unused, okm, 0, min); countBytes -= min; k_unused -= min; } if (countBytes == 0) return okm; int n = countBytes / hashLength + 1; int contextLength = context != null ? context.Length : 0; byte[] hmac_msg = new byte[hashLength + contextLength + 1]; for (var i = 1; i <= n; ++i) { Utils.BlockCopy(k, 0, hmac_msg, 0, k.Length); if (contextLength > 0) Utils.BlockCopy(context, 0, hmac_msg, k.Length, contextLength); hmac_msg[k.Length + contextLength] = checked(++counter); if (hmac2 != null) { hmac2.TransformBlock(hmac_msg, 0, k.Length + contextLength + 1, null, 0); hmac2.TransformFinalBlock(hmac_msg, 0, 0); k = hmac2.HashInner; } else k = hmac.ComputeHash(hmac_msg, 0, k.Length + contextLength + 1); Utils.BlockCopy(k, 0, okm, okm.Length - countBytes, i < n ? hashLength : countBytes); countBytes -= hashLength; } k_unused = -countBytes; return okm; }// GetBytes()
byte[] Func() { new Utils.IntStruct { UintValue = this.block }.ToBEBytes(inputBuffer); this.hmac.TransformBlock(inputBuffer: this.salt, inputOffset: 0, inputCount: this.salt.Length, outputBuffer: null, outputOffset: 0); this.hmac.TransformBlock(inputBuffer: inputBuffer, inputOffset: 0, inputCount: inputBuffer.Length, outputBuffer: null, outputOffset: 0); this.hmac.TransformFinalBlock(inputBuffer: inputBuffer, inputOffset: 0, inputCount: 0); byte[] hash = this.hmac.Hash; // creates a copy this.hmac.Initialize(); byte[] buffer3 = hash; for (int i = 2; i <= this.iterations; i++) { if (hmac2 != null) { hmac2.TransformBlock(hash, 0, BlockSize, null, 0); hmac2.TransformFinalBlock(hash, 0, 0); hash = hmac2.HashInner; } else hash = this.hmac.ComputeHash(hash); Utils.Xor(dest: buffer3, destOffset: 0, left: hash, leftOffset: 0, byteCount: BlockSize); } this.block++; return buffer3; }