public static Handshake craft_obfuscated(byte[] torrentInfoHash,
			byte[] clientPeerId, byte[] remotePeerId, boolean obfuscate) {
		
		// craft random padding message
		Message.PaddingMessage padding = Message.PaddingMessage.craft();
		
		/*ByteBuffer buffer = ByteBuffer.allocate(
				Handshake.BASE_HANDSHAKE_LENGTH +
				Handshake.BITTORRENT_PROTOCOL_IDENTIFIER.length());
		*/
		ByteBuffer buffer = ByteBuffer.allocate(
				Handshake.BASE_HANDSHAKE_LENGTH +
				Handshake.BITTORRENT_PROTOCOL_IDENTIFIER.length() +
				padding.length() + 5
		);
		
		byte[] reserved = new byte[8];
		ByteBuffer infoHash = ByteBuffer.wrap(torrentInfoHash);
		ByteBuffer peerId = ByteBuffer.wrap(clientPeerId);
		
		try {
			byte[] infoHashPeerId = Arrays.copyOf(torrentInfoHash, torrentInfoHash.length + remotePeerId.length);
			System.arraycopy(remotePeerId, 0, infoHashPeerId, torrentInfoHash.length, remotePeerId.length);
			byte[] sighash = Torrent.hash(infoHashPeerId);
			buffer.put(sighash, 0, Handshake.BITTORRENT_PROTOCOL_IDENTIFIER.length() + 1);
			
			byte[] peerIdInfoHash = Arrays.copyOf(remotePeerId, torrentInfoHash.length + remotePeerId.length);
			System.arraycopy(torrentInfoHash, 0, peerIdInfoHash, torrentInfoHash.length, remotePeerId.length);
			byte[] opthash = Torrent.hash(peerIdInfoHash);
			long options = ByteBuffer.wrap(reserved).getLong();
			long mask = ByteBuffer.wrap(opthash).getLong();
			options = options ^ mask;
			ByteBuffer optbuf = ByteBuffer.wrap(reserved);
			optbuf.putLong(options);
		}  catch (NoSuchAlgorithmException e) {
			obfuscate = false;
			buffer.put((byte)Handshake
					.BITTORRENT_PROTOCOL_IDENTIFIER.length());
			try {
				buffer.put(Handshake
					.BITTORRENT_PROTOCOL_IDENTIFIER.getBytes(Torrent.BYTE_ENCODING));
			} catch (UnsupportedEncodingException uee) {
				return null;
			}
		}
		
		buffer.put(reserved);
		buffer.put(infoHash);
		buffer.put(peerId);

		// add random padding
		buffer.put(padding.toBytes());
		
		return new Handshake(buffer, infoHash, peerId, obfuscate);
	}