private void ReadPacketWithDecryptedHead() { /* SOURCE : _head(packet_size, padding_length) + _buffer(payload + mac) * DESTINATION : _packet(payload) */ int offset = _buffer.Offset; int packet_length = SSHUtil.ReadInt32(_head, 0); if (packet_length <= 0 || packet_length >= MAX_PACKET_LENGTH) { throw new SSHException(String.Format("packet size {0} is invalid", packet_length)); } _packet.AssureCapacity(packet_length + PACKET_LENGTH_FIELD_LEN + SEQUENCE_FIELD_LEN); int padding_length = (int)_head[PACKET_LENGTH_FIELD_LEN]; if (padding_length < 4) { throw new SSHException("padding length is invalid"); } //to compute hash, we write _sequence at the top of _packet.Data SSHUtil.WriteIntToByteArray(_packet.Data, 0, _sequence); Array.Copy(_head, 0, _packet.Data, SEQUENCE_FIELD_LEN, _head.Length); if (packet_length > (_cipher.BlockSize - PACKET_LENGTH_FIELD_LEN)) //in case of _head is NOT the entire of the packet { int decrypting_size = packet_length - (_cipher.BlockSize - PACKET_LENGTH_FIELD_LEN); _cipher.Decrypt(_buffer.Data, _buffer.Offset, decrypting_size, _packet.Data, SEQUENCE_FIELD_LEN + _head.Length); } _packet.SetLength(SEQUENCE_FIELD_LEN + PACKET_LENGTH_FIELD_LEN + PADDING_LENGTH_FIELD_LEN, packet_length - 1 - padding_length); _buffer.Consume(packet_length + PACKET_LENGTH_FIELD_LEN - _head.Length + _mac.Size); if (_macEnabled) { byte[] result = _mac.ComputeHash(_packet.Data, 0, 4 + PACKET_LENGTH_FIELD_LEN + packet_length); if (SSHUtil.memcmp(result, 0, _buffer.Data, _buffer.Offset - _mac.Size, _mac.Size) != 0) { throw new SSHException("MAC mismatch"); } } }