public TransformBlock ( byte inputBuffer, int inputOffset, int inputCount, byte outputBuffer, int outputOffset ) : int | ||
inputBuffer | byte | |
inputOffset | int | |
inputCount | int | |
outputBuffer | byte | |
outputOffset | int | |
return | int |
public override int Read(byte[] outBuffer, int offset, int count) { int num = 0; while (num < count) { int num2 = _slideBufFreePos - _slideBufStartPos; int num3 = _blockAndAuth - num2; if (_slideBuffer.Length - _slideBufFreePos < num3) { int num4 = 0; int num5 = _slideBufStartPos; while (num5 < _slideBufFreePos) { _slideBuffer[num4] = _slideBuffer[num5]; num5++; num4++; } _slideBufFreePos -= _slideBufStartPos; _slideBufStartPos = 0; } int num6 = _stream.Read(_slideBuffer, _slideBufFreePos, num3); _slideBufFreePos += num6; num2 = _slideBufFreePos - _slideBufStartPos; if (num2 >= _blockAndAuth) { _transform.TransformBlock(_slideBuffer, _slideBufStartPos, 16, outBuffer, offset); num += 16; offset += 16; _slideBufStartPos += 16; continue; } if (num2 > 10) { int num7 = num2 - 10; _transform.TransformBlock(_slideBuffer, _slideBufStartPos, num7, outBuffer, offset); num += num7; _slideBufStartPos += num7; } else if (num2 < 10) { throw new Exception("Internal error missed auth code"); } byte[] authCode = _transform.GetAuthCode(); for (int i = 0; i < 10; i++) { if (authCode[i] != _slideBuffer[_slideBufStartPos + i]) { throw new Exception("AES Authentication Code does not match. This is a super-CRC check on the data in the file after compression and encryption. \r\nThe file may be damaged."); } } break; } return(num); }
// Perform the crypto transform, and buffer the data if less than one block has been requested. private int TransformAndBufferBlock(byte[] buffer, int offset, int count, int blockSize) { // If the requested data is greater than one block, transform it directly into the output // If it's smaller, do it into a temporary buffer and copy the requested part bool bufferRequired = (blockSize > count); if (bufferRequired && _transformBuffer == null) { _transformBuffer = new byte[CRYPTO_BLOCK_SIZE]; } var targetBuffer = bufferRequired ? _transformBuffer : buffer; var targetOffset = bufferRequired ? 0 : offset; // Transform the data _transform.TransformBlock(_slideBuffer, _slideBufStartPos, blockSize, targetBuffer, targetOffset); _slideBufStartPos += blockSize; if (!bufferRequired) { return(blockSize); } else { Array.Copy(_transformBuffer, 0, buffer, offset, count); _transformBufferStartPos = count; _transformBufferFreePos = blockSize; return(count); } }
// Blocksize is always 16 here, even for AES-256 which has transform.InputBlockSize of 32. /// <summary> /// Reads a sequence of bytes from the current CryptoStream into buffer, /// and advances the position within the stream by the number of bytes read. /// </summary> public override int Read(byte[] outBuffer, int offset, int count) { int nBytes = 0; while (nBytes < count) { // Calculate buffer quantities vs read-ahead size, and check for sufficient free space int byteCount = _slideBufFreePos - _slideBufStartPos; // Need to handle final block and Auth Code specially, but don't know total data length. // Maintain a read-ahead equal to the length of (crypto block + Auth Code). // When that runs out we can detect these final sections. int lengthToRead = _blockAndAuth - byteCount; if (_slideBuffer.Length - _slideBufFreePos < lengthToRead) { // Shift the data to the beginning of the buffer int iTo = 0; for (int iFrom = _slideBufStartPos; iFrom < _slideBufFreePos; iFrom++, iTo++) { _slideBuffer[iTo] = _slideBuffer[iFrom]; } _slideBufFreePos -= _slideBufStartPos; // Note the -= _slideBufStartPos = 0; } int obtained = _stream.Read(_slideBuffer, _slideBufFreePos, lengthToRead); _slideBufFreePos += obtained; // Recalculate how much data we now have byteCount = _slideBufFreePos - _slideBufStartPos; if (byteCount >= _blockAndAuth) { // At least a 16 byte block and an auth code remains. _transform.TransformBlock(_slideBuffer, _slideBufStartPos, CRYPTO_BLOCK_SIZE, outBuffer, offset); nBytes += CRYPTO_BLOCK_SIZE; offset += CRYPTO_BLOCK_SIZE; _slideBufStartPos += CRYPTO_BLOCK_SIZE; } else { // Last round. if (byteCount > AUTH_CODE_LENGTH) { // At least one byte of data plus auth code int finalBlock = byteCount - AUTH_CODE_LENGTH; _transform.TransformBlock(_slideBuffer, _slideBufStartPos, finalBlock, outBuffer, offset); nBytes += finalBlock; _slideBufStartPos += finalBlock; } else if (byteCount < AUTH_CODE_LENGTH) { throw new Exception("Internal error missed auth code"); // Coding bug } // Final block done. Check Auth code. byte[] calcAuthCode = _transform.GetAuthCode(); for (int i = 0; i < AUTH_CODE_LENGTH; i++) { if (calcAuthCode[i] != _slideBuffer[_slideBufStartPos + i]) { throw new Exception("AES Authentication Code does not match. This is a super-CRC check on the data in the file after compression and encryption. \r\n" + "The file may be damaged."); } } break; // Reached the auth code } } return(nBytes); }