@Override
	protected void read(InputBuffer b) throws IOException, ParsingException {
		InputBuffer signed = b.getSubBuffer(0);

		VariableLengthIntegerMessage messageVersion = getMessageFactory().parseVariableLengthIntegerMessage(b);
		b = b.getSubBuffer(messageVersion.length());

		if (messageVersion.getLong() != MESSAGE_VERSION) {
			throw new ParsingException("Cannot understand messages of version: " + messageVersion);
		}

		VariableLengthIntegerMessage vAddressVersion = getMessageFactory().parseVariableLengthIntegerMessage(b);
		b = b.getSubBuffer(vAddressVersion.length());
		addressVersion = vAddressVersion.getLong();

		if (!BMAddress.isSupported(addressVersion)) {
			throw new ParsingException("Unknown address version: " + addressVersion);
		}

		VariableLengthIntegerMessage vStream = getMessageFactory().parseVariableLengthIntegerMessage(b);
		b = b.getSubBuffer(vStream.length());
		stream = vStream.getLong();

		behavior = getMessageFactory().parseBehaviorMessage(b);
		b = b.getSubBuffer(behavior.length());

		publicSigningKey = Util.getPublicKey(b.get(0, 64));

		publicEncryptionKey = Util.getPublicKey(b.get(64, 64));

		destinationRipe = b.get(84, 64);
		b = b.getSubBuffer(148);

		message = getMessageFactory().parseMailMessage(b);
		b = b.getSubBuffer(message.length());

		VariableLengthIntegerMessage vLength = getMessageFactory().parseVariableLengthIntegerMessage(b);
		b = b.getSubBuffer(vLength.length());
		long length = vLength.getLong();

		if (length < 0 || length > b.length()) {
			throw new ParsingException("The acknowlegment data is too long: " + length);
		}

		this.acknowledgment = getMessageFactory().parseBaseMessage(
				new InputBufferInputStream(b.getSubBuffer(0, (int) length)), (int) length);
		b = b.getSubBuffer((int) length);

		vLength = getMessageFactory().parseVariableLengthIntegerMessage(b);
		b = b.getSubBuffer(vLength.length());
		length = vLength.getLong();

		if (length < 0 || length > b.length()) {
			throw new ParsingException("The signature data is too long: " + length);
		}

		signature = b.get(0, (int) length);

		if (!CryptManager.getInstance().verifySignature(signed.get(0, b.getOffset() - signed.getOffset()), signature,
				publicSigningKey)) {
			throw new ParsingException("Wrong signature.");
		}
	}