private Handshake validateHandshake(Socket socket, byte[] peerId)
		throws IOException, ParseException {
		InputStream is = socket.getInputStream();

		//< obfuscated handshake extension
		// Read the handshake from the wire
		byte[] data = new byte[Handshake.BASE_HANDSHAKE_LENGTH + 20];
		is.read(data, 0, data.length);
		int pstrlen = data[0] == 0x13 ? data[0] : 0x13;
		byte[] pstr = Arrays.copyOfRange(data, 1, 20);

		// Parse and check the handshake
		Handshake hs = Handshake.parse(ByteBuffer.wrap(data));
		logger.debug("Validating handshake from " + socket + ": " + Torrent.byteArrayToHexString(hs.getBytes()));
		
		if (hs.isObfuscated()) {
			//byte[] clientPeerId = this.id.getBytes();
			byte[] clientPeerId = this.id;
			byte[] infoHash = this.torrent.getInfoHash();
			byte[] infoHashPeerId = Arrays.copyOf(infoHash, infoHash.length + clientPeerId.length);
			System.arraycopy(clientPeerId, 0, infoHashPeerId, infoHash.length, clientPeerId.length);
			try {
				byte[] sighash = Torrent.hash(infoHashPeerId);
				if (!Arrays.equals(sighash, hs.getSignature())) {
					throw new ParseException("Invalid obfuscated handshake", pstrlen);
				}
			} catch (NoSuchAlgorithmException nsae) {
				// fall through
			}
			// read padding message
			byte[] paddingheader = new byte[5];
			is.read(paddingheader);
			int paddingLen = ByteBuffer.wrap(paddingheader).getInt();
			byte[] paddingBytes = new byte[paddingLen];
			is.read(paddingBytes);
		} else if (!Handshake.BITTORRENT_PROTOCOL_IDENTIFIER.equals(new String(pstr, Torrent.BYTE_ENCODING))) {
			throw new ParseException("Invalid handshake signature", pstrlen);
		}
		//> obfuscated handshake extension
		
		if (!Arrays.equals(hs.getInfoHash(), this.torrent.getInfoHash())) {
			throw new ParseException("Handshake for unknown torrent " +
					Torrent.byteArrayToHexString(hs.getInfoHash()) +
					" from " + this.socketRepr(socket) + ".", pstrlen + 9);
		}

		if (peerId != null && !Arrays.equals(hs.getPeerId(), peerId)) {
			throw new ParseException("Announced peer ID " +
					Torrent.byteArrayToHexString(hs.getPeerId()) +
					" did not match expected peer ID " +
					Torrent.byteArrayToHexString(peerId) + ".", pstrlen + 29);
		}

		return hs;
	}