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); }
// Read data from the underlying stream and decrypt it private int ReadAndTransform(byte[] buffer, int offset, int count) { int nBytes = 0; while (nBytes < count) { int bytesLeftToRead = count - nBytes; // 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 = BLOCK_AND_AUTH - 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 = StreamUtils.ReadRequestedBytes(_stream, _slideBuffer, _slideBufFreePos, lengthToRead); _slideBufFreePos += obtained; // Recalculate how much data we now have byteCount = _slideBufFreePos - _slideBufStartPos; if (byteCount >= BLOCK_AND_AUTH) { var read = TransformAndBufferBlock(buffer, offset, bytesLeftToRead, CRYPTO_BLOCK_SIZE); nBytes += read; offset += read; } else { // Last round. if (byteCount > AUTH_CODE_LENGTH) { // At least one byte of data plus auth code int finalBlock = byteCount - AUTH_CODE_LENGTH; nBytes += TransformAndBufferBlock(buffer, offset, bytesLeftToRead, finalBlock); } else if (byteCount < AUTH_CODE_LENGTH) { throw new ZipException("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 ZipException("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."); } } // don't need this any more, so use it as a 'complete' flag _slideBuffer = null; break; // Reached the auth code } } return(nBytes); }
// 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); }