@@ -0,0 +1,2221 @@
+// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)%0A%0Apackage org.xbill.DNS.utils;%0A%0Aimport java.util.Arrays;%0Aimport java.security.*;%0A%0A/**%0A * A pure java implementation of the HMAC-MD5 secure hash algorithm%0A *%0A * @author Brian Wellington%0A */%0A%0Apublic class HMAC %7B%0A%0AMessageDigest digest;%0Aprivate byte %5B%5D ipad, opad;%0A%0Aprivate static final byte IPAD = 0x36;%0Aprivate static final byte OPAD = 0x5c;%0Aprivate static final byte PADLEN = 64;%0A%0Aprivate void%0Ainit(byte %5B%5D key) %7B%0A%09int i;%0A%0A%09if (key.length %3E PADLEN) %7B%0A%09%09key = digest.digest(key);%0A%09%09digest.reset();%0A%09%7D%0A%09ipad = new byte%5BPADLEN%5D;%0A%09opad = new byte%5BPADLEN%5D;%0A%09for (i = 0; i %3C key.length; i++) %7B%0A%09%09ipad%5Bi%5D = (byte) (key%5Bi%5D %5E IPAD);%0A%09%09opad%5Bi%5D = (byte) (key%5Bi%5D %5E OPAD);%0A%09%7D%0A%09for (; i %3C PADLEN; i++) %7B%0A%09%09ipad%5Bi%5D = IPAD;%0A%09%09opad%5Bi%5D = OPAD;%0A%09%7D%0A%09digest.update(ipad);%0A%7D%0A%0A/**%0A * Creates a new HMAC instance%0A * @param key The secret key%0A */%0Apublic%0AHMAC(MessageDigest digest, byte %5B%5D key) %7B%0A%09digest.reset();%0A%09init(key);%0A%7D%0A%0Apublic%0AHMAC(String digestName, byte %5B%5D key) %7B%0A%09try %7B%0A%09%09digest = MessageDigest.getInstance(digestName);%0A%09%7D catch (NoSuchAlgorithmException e) %7B%0A%09%09throw new IllegalArgumentException(%22unknown digest algorithm %22%0A%09%09%09%09%09%09   + digestName);%0A%09%7D%0A%09init(key);%0A%7D%0A%0A/**%0A * Adds data to the current hash%0A * @param b The data%0A * @param offset The index at which to start adding to the hash%0A * @param length The number of bytes to hash%0A */%0Apublic void%0Aupdate(byte %5B%5D b, int offset, int length) %7B%0A%09digest.update(b, offset, length);%0A%7D%0A%0A/**%0A * Adds data to the current hash%0A * @param b The data%0A */%0Apublic void%0Aupdate(byte %5B%5D b) %7B%0A%09digest.update(b);%0A%7D%0A%0A/**%0A * Signs the data (computes the secure hash)%0A * @return An array with the signature%0A */%0Apublic byte %5B%5D%0Asign() %7B%0A%09byte %5B%5D output = digest.digest();%0A%09digest.reset();%0A%09digest.update(opad);%0A%09return digest.digest(output);%0A%7D%0A%0A/**%0A * Verifies the data (computes the secure hash and compares it to the input)%0A * @param signature The signature to compare against%0A * @return true if the signature matched, false otherwise%0A */%0Apublic boolean%0Averify(byte %5B%5D signature) %7B%0A%09return Arrays.equals(signature, sign());%0A%7D%0A%0A/**%0A * Resets the HMAC object for further use%0A */%0Apublic void%0Aclear() %7B%0A%09digest.reset();%0A%09digest.update(ipad);%0A%7D%0A%0A%7D%0A

Add a generic HMAC class, which sits atop an arbitrary MessageDigest.