⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tsig.java

📁 linux下建立JAVA虚拟机的源码KAFFE
💻 JAVA
字号:
// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)package org.xbill.DNS;import java.util.*;import org.xbill.DNS.utils.*;/** * Transaction signature handling.  This class generates and verifies * TSIG records on messages, which provide transaction security. * @see TSIGRecord * * @author Brian Wellington */public class TSIG {private static final String HMAC_MD5_STR = "HMAC-MD5.SIG-ALG.REG.INT.";private static final String HMAC_SHA1_STR = "hmac-sha1.";private static final String HMAC_SHA256_STR = "hmac-sha256.";/** The domain name representing the HMAC-MD5 algorithm. */public static final Name HMAC_MD5 = Name.fromConstantString(HMAC_MD5_STR);/** The domain name representing the HMAC-MD5 algorithm (deprecated). */public static final Name HMAC = HMAC_MD5;/** The domain name representing the HMAC-SHA1 algorithm. */public static final Name HMAC_SHA1 = Name.fromConstantString(HMAC_SHA1_STR);/** The domain name representing the HMAC-SHA256 algorithm. */public static final Name HMAC_SHA256 = Name.fromConstantString(HMAC_SHA256_STR);/** * The default fudge value for outgoing packets.  Can be overriden by the * tsigfudge option. */public static final short FUDGE		= 300;private Name name, alg;private String digest;private byte [] key;private voidgetDigest() {	if (alg.equals(HMAC_MD5))		digest = "md5";	else if (alg.equals(HMAC_SHA1))		digest = "sha-1";	else if (alg.equals(HMAC_SHA256))		digest = "sha-256";	else		throw new IllegalArgumentException("Invalid algorithm");}/** * Creates a new TSIG key, which can be used to sign or verify a message. * @param algorithm The algorithm of the shared key. * @param name The name of the shared key. * @param key The shared key's data. */publicTSIG(Name algorithm, Name name, byte [] key) {	this.name = name;	this.alg = algorithm;	this.key = key;	getDigest();}/** * Creates a new TSIG key with the hmac-md5 algorithm, which can be used to * sign or verify a message. * @param name The name of the shared key. * @param key The shared key's data. */publicTSIG(Name name, byte [] key) {	this(HMAC_MD5, name, key);}/** * Creates a new TSIG object, which can be used to sign or verify a message. * @param name The name of the shared key * @param key The shared key's data represented as a base64 encoded string. * @throws IllegalArgumentException The key name is an invalid name * @throws IllegalArgumentException The key data is improperly encoded */publicTSIG(Name algorithm, String name, String key) {	this.key = base64.fromString(key);	if (this.key == null)		throw new IllegalArgumentException("Invalid TSIG key string");	try {		this.name = Name.fromString(name, Name.root);	}	catch (TextParseException e) {		throw new IllegalArgumentException("Invalid TSIG key name");	}	this.alg = algorithm;	getDigest();}/** * Creates a new TSIG object with the hmac-md5 algorithm, which can be used to * sign or verify a message. * @param name The name of the shared key * @param key The shared key's data, represented as a base64 encoded string. * @throws IllegalArgumentException The key name is an invalid name * @throws IllegalArgumentException The key data is improperly encoded */publicTSIG(String name, String key) {	this(HMAC_MD5, name, key);}/** * Creates a new TSIG object with the hmac-md5 algorithm, which can be used to * sign or verify a message. * @param str The TSIG key, in the form name/secret or name:secret. * @throws IllegalArgumentException The string does not contain both a name * and secret. * @throws IllegalArgumentException The key name is an invalid name * @throws IllegalArgumentException The key data is improperly encoded */static public TSIGfromString(String str) {	int index = str.indexOf('/');	if (index < 0)		index = str.indexOf(':');	if (index < 0)		throw new IllegalArgumentException("String does not contain " +						   "both name and secret");	return new TSIG(str.substring(0, index), str.substring(index + 1));}/** * Generates a TSIG record with a specific error for a message that has * been rendered. * @param m The message * @param b The rendered message * @param error The error * @param old If this message is a response, the TSIG from the request * @return The TSIG record to be added to the message */public TSIGRecordgenerate(Message m, byte [] b, int error, TSIGRecord old) {	Date timeSigned;	if (error != Rcode.BADTIME)		timeSigned = new Date();	else		timeSigned = old.getTimeSigned();	int fudge;	HMAC hmac = null;	if (error == Rcode.NOERROR || error == Rcode.BADTIME)		hmac = new HMAC(digest, key);	fudge = Options.intValue("tsigfudge");	if (fudge < 0 || fudge > 0x7FFF)		fudge = FUDGE;	if (old != null) {		DNSOutput out = new DNSOutput();		out.writeU16(old.getSignature().length);		if (hmac != null) {			hmac.update(out.toByteArray());			hmac.update(old.getSignature());		}	}	/* Digest the message */	if (hmac != null)		hmac.update(b);	DNSOutput out = new DNSOutput();	name.toWireCanonical(out);	out.writeU16(DClass.ANY);	/* class */	out.writeU32(0);		/* ttl */	alg.toWireCanonical(out);	long time = timeSigned.getTime() / 1000;	int timeHigh = (int) (time >> 32);	long timeLow = (time & 0xFFFFFFFFL);	out.writeU16(timeHigh);	out.writeU32(timeLow);	out.writeU16(fudge);	out.writeU16(error);	out.writeU16(0); /* No other data */	if (hmac != null)		hmac.update(out.toByteArray());	byte [] signature;	if (hmac != null)		signature = hmac.sign();	else		signature = new byte[0];	byte [] other = null;	if (error == Rcode.BADTIME) {		out = new DNSOutput();		time = new Date().getTime() / 1000;		timeHigh = (int) (time >> 32);		timeLow = (time & 0xFFFFFFFFL);		out.writeU16(timeHigh);		out.writeU32(timeLow);		other = out.toByteArray();	}	return (new TSIGRecord(name, DClass.ANY, 0, alg, timeSigned, fudge,			       signature, m.getHeader().getID(), error, other));}/** * Generates a TSIG record with a specific error for a message and adds it * to the message. * @param m The message * @param error The error * @param old If this message is a response, the TSIG from the request */public voidapply(Message m, int error, TSIGRecord old) {	Record r = generate(m, m.toWire(), error, old);	m.addRecord(r, Section.ADDITIONAL);	m.tsigState = Message.TSIG_SIGNED;}/** * Generates a TSIG record for a message and adds it to the message * @param m The message * @param old If this message is a response, the TSIG from the request */public voidapply(Message m, TSIGRecord old) {	apply(m, Rcode.NOERROR, old);}/** * Generates a TSIG record for a message and adds it to the message * @param m The message * @param old If this message is a response, the TSIG from the request */public voidapplyStream(Message m, TSIGRecord old, boolean first) {	if (first) {		apply(m, old);		return;	}	Date timeSigned = new Date();	int fudge;	HMAC hmac = new HMAC(digest, key);	fudge = Options.intValue("tsigfudge");	if (fudge < 0 || fudge > 0x7FFF)		fudge = FUDGE;	DNSOutput out = new DNSOutput();	out.writeU16(old.getSignature().length);	hmac.update(out.toByteArray());	hmac.update(old.getSignature());	/* Digest the message */	hmac.update(m.toWire());	out = new DNSOutput();	long time = timeSigned.getTime() / 1000;	int timeHigh = (int) (time >> 32);	long timeLow = (time & 0xFFFFFFFFL);	out.writeU16(timeHigh);	out.writeU32(timeLow);	out.writeU16(fudge);	hmac.update(out.toByteArray());	byte [] signature = hmac.sign();	byte [] other = null;	Record r = new TSIGRecord(name, DClass.ANY, 0, alg, timeSigned, fudge,				  signature, m.getHeader().getID(),				  Rcode.NOERROR, other);	m.addRecord(r, Section.ADDITIONAL);	m.tsigState = Message.TSIG_SIGNED;}/** * 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. * @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 */public byteverify(Message m, byte [] b, int length, TSIGRecord old) {	TSIGRecord tsig = m.getTSIG();	HMAC hmac = new HMAC(digest, key);	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());	if (hmac.verify(tsig.getSignature()))		return Rcode.NOERROR;	else {		if (Options.check("verbose"))			System.err.println("BADSIG failure");		return Rcode.BADSIG;	}}/** * 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. * @param m The message * @param b 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 old If this message is a response, the TSIG from the request * @return The result of the verification (as an Rcode) * @see Rcode */public intverify(Message m, byte [] b, TSIGRecord old) {	return verify(m, b, b.length, old);}/** * Returns the maximum length of a TSIG record generated by this key. * @see TSIGRecord */public intrecordLength() {	return (name.length() + 10 +		alg.length() +		8 +	// time signed, fudge		18 +	// 2 byte MAC length, 16 byte MAC		4 +	// original id, error		8);	// 2 byte error length, 6 byte max error field.}public static class StreamVerifier {	/**	 * A helper class for verifying multiple message responses.	 */	private TSIG key;	private HMAC verifier;	private int nresponses;	private int lastsigned;	private TSIGRecord lastTSIG;	/** Creates an object to verify a multiple message response */	public	StreamVerifier(TSIG tsig, TSIGRecord old) {		key = tsig;		verifier = new HMAC(key.digest, key.key);		nresponses = 0;		lastTSIG = old;	}	/**	 * Verifies a TSIG record on an incoming message that is part of a	 * multiple message response.	 * TSIG records must be present on the first and last messages, and	 * at least every 100 records in between.	 * @param m The message	 * @param b The message in unparsed form	 * @return The result of the verification (as an Rcode)	 * @see Rcode	 */	public int	verify(Message m, byte [] b) {		TSIGRecord tsig = m.getTSIG();			nresponses++;		if (nresponses == 1) {			int result = key.verify(m, b, lastTSIG);			if (result == Rcode.NOERROR) {				byte [] signature = tsig.getSignature();				DNSOutput out = new DNSOutput();				out.writeU16(signature.length);				verifier.update(out.toByteArray());				verifier.update(signature);			}			lastTSIG = tsig;			return result;		}		if (tsig != null)			m.getHeader().decCount(Section.ADDITIONAL);		byte [] header = m.getHeader().toWire();		if (tsig != null)			m.getHeader().incCount(Section.ADDITIONAL);		verifier.update(header);		int len;		if (tsig == null)			len = b.length - header.length;		else			len = m.tsigstart - header.length;		verifier.update(b, header.length, len);		if (tsig != null) {			lastsigned = nresponses;			lastTSIG = tsig;		}		else {			boolean required = (nresponses - lastsigned >= 100);			if (required)				return Rcode.FORMERR;			else				return Rcode.NOERROR;		}		if (!tsig.getName().equals(key.name) ||		    !tsig.getAlgorithm().equals(key.alg))		{			if (Options.check("verbose"))				System.err.println("BADKEY failure");			return Rcode.BADKEY;		}		DNSOutput out = new DNSOutput();		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());		verifier.update(out.toByteArray());		if (verifier.verify(tsig.getSignature()) == false) {			if (Options.check("verbose"))				System.err.println("BADSIG failure");			return Rcode.BADSIG;		}		verifier.clear();		out = new DNSOutput();		out.writeU16(tsig.getSignature().length);		verifier.update(out.toByteArray());		verifier.update(tsig.getSignature());		return Rcode.NOERROR;	}}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -