public byte
verify(Message m, byte [] b, int length, TSIGRecord old) {
	m.tsigState = Message.TSIG_FAILED;
	TSIGRecord tsig = m.getTSIG();
	hmac.reset();
	if (tsig == null)
		return Rcode.FORMERR;

	if (!tsig.getName().equals(name) || !tsig.getAlgorithm().equals(alg)) {
		if (Options.check("verbose"))
			System.err.println("BADKEY failure");
		return Rcode.BADKEY;
	}
	long now = System.currentTimeMillis();
	long then = tsig.getTimeSigned().getTime();
	long fudge = tsig.getFudge();
	if (Math.abs(now - then) > fudge * 1000) {
		if (Options.check("verbose"))
			System.err.println("BADTIME failure");
		return Rcode.BADTIME;
	}

	if (old != null && tsig.getError() != Rcode.BADKEY &&
	    tsig.getError() != Rcode.BADSIG)
	{
		DNSOutput out = new DNSOutput();
		out.writeU16(old.getSignature().length);
		hmac.update(out.toByteArray());
		hmac.update(old.getSignature());
	}
	m.getHeader().decCount(Section.ADDITIONAL);
	byte [] header = m.getHeader().toWire();
	m.getHeader().incCount(Section.ADDITIONAL);
	hmac.update(header);

	int len = m.tsigstart - header.length;	
	hmac.update(b, header.length, len);

	DNSOutput out = new DNSOutput();
	tsig.getName().toWireCanonical(out);
	out.writeU16(tsig.dclass);
	out.writeU32(tsig.ttl);
	tsig.getAlgorithm().toWireCanonical(out);
	long time = tsig.getTimeSigned().getTime() / 1000;
	int timeHigh = (int) (time >> 32);
	long timeLow = (time & 0xFFFFFFFFL);
	out.writeU16(timeHigh);
	out.writeU32(timeLow);
	out.writeU16(tsig.getFudge());
	out.writeU16(tsig.getError());
	if (tsig.getOther() != null) {
		out.writeU16(tsig.getOther().length);
		out.writeByteArray(tsig.getOther());
	} else {
		out.writeU16(0);
	}

	hmac.update(out.toByteArray());

	byte [] signature = tsig.getSignature();
	int digestLength = hmac.getMacLength();
	int minDigestLength;
	if (hmac.getAlgorithm().toLowerCase().contains("md5"))
		minDigestLength = 10;
	else
		minDigestLength = digestLength / 2;

	if (signature.length > digestLength) {
		if (Options.check("verbose"))
			System.err.println("BADSIG: signature too long");
		return Rcode.BADSIG;
	} else if (signature.length < minDigestLength) {
		if (Options.check("verbose"))
			System.err.println("BADSIG: signature too short");
		return Rcode.BADSIG;
	} else if (!verify(hmac, signature, true)) {
		if (Options.check("verbose"))
			System.err.println("BADSIG: signature verification");
		return Rcode.BADSIG;
	}

	m.tsigState = Message.TSIG_VERIFIED;
	return Rcode.NOERROR;
}
Verifies a TSIG record on an incoming message.  Since this is only called
in the context where a TSIG is expected to be present, it is an error
if one is not present.  After calling this routine, Message.isVerified() may
be called on this message.
@param m The message
@param b An array containing the message in unparsed form.  This is
necessary since TSIG signs the message in wire format, and we can't
recreate the exact wire format (with the same name compression).
@param length The length of the message in the array.
@param old If this message is a response, the TSIG from the request
@return The result of the verification (as an Rcode)
@see Rcode
src/main/java/core/org/xbill/DNS/TSIG.java