diff options
Diffstat (limited to 'src/org/xbill/DNS/utils/HMAC.java')
-rw-r--r-- | src/org/xbill/DNS/utils/HMAC.java | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/src/org/xbill/DNS/utils/HMAC.java b/src/org/xbill/DNS/utils/HMAC.java new file mode 100644 index 0000000..5eb5afd --- /dev/null +++ b/src/org/xbill/DNS/utils/HMAC.java @@ -0,0 +1,182 @@ +// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org) + +package org.xbill.DNS.utils; + +import java.util.Arrays; +import java.security.*; + +/** + * An implementation of the HMAC message authentication code. + * + * @author Brian Wellington + */ + +public class HMAC { + +private MessageDigest digest; +private int blockLength; + +private byte [] ipad, opad; + +private static final byte IPAD = 0x36; +private static final byte OPAD = 0x5c; + +private void +init(byte [] key) { + int i; + + if (key.length > blockLength) { + key = digest.digest(key); + digest.reset(); + } + ipad = new byte[blockLength]; + opad = new byte[blockLength]; + for (i = 0; i < key.length; i++) { + ipad[i] = (byte) (key[i] ^ IPAD); + opad[i] = (byte) (key[i] ^ OPAD); + } + for (; i < blockLength; i++) { + ipad[i] = IPAD; + opad[i] = OPAD; + } + digest.update(ipad); +} + +/** + * Creates a new HMAC instance + * @param digest The message digest object. + * @param blockLength The block length of the message digest. + * @param key The secret key + */ +public +HMAC(MessageDigest digest, int blockLength, byte [] key) { + digest.reset(); + this.digest = digest; + this.blockLength = blockLength; + init(key); +} + +/** + * Creates a new HMAC instance + * @param digestName The name of the message digest function. + * @param blockLength The block length of the message digest. + * @param key The secret key. + */ +public +HMAC(String digestName, int blockLength, byte [] key) { + try { + digest = MessageDigest.getInstance(digestName); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException("unknown digest algorithm " + + digestName); + } + this.blockLength = blockLength; + init(key); +} + +/** + * Creates a new HMAC instance + * @param digest The message digest object. + * @param key The secret key + * @deprecated won't work with digests using a padding length other than 64; + * use {@code HMAC(MessageDigest digest, int blockLength, + * byte [] key)} instead. + * @see HMAC#HMAC(MessageDigest digest, int blockLength, byte [] key) + */ +public +HMAC(MessageDigest digest, byte [] key) { + this(digest, 64, key); +} + +/** + * Creates a new HMAC instance + * @param digestName The name of the message digest function. + * @param key The secret key. + * @deprecated won't work with digests using a padding length other than 64; + * use {@code HMAC(String digestName, int blockLength, byte [] key)} + * instead + * @see HMAC#HMAC(String digestName, int blockLength, byte [] key) + */ +public +HMAC(String digestName, byte [] key) { + this(digestName, 64, key); +} + +/** + * Adds data to the current hash + * @param b The data + * @param offset The index at which to start adding to the hash + * @param length The number of bytes to hash + */ +public void +update(byte [] b, int offset, int length) { + digest.update(b, offset, length); +} + +/** + * Adds data to the current hash + * @param b The data + */ +public void +update(byte [] b) { + digest.update(b); +} + +/** + * Signs the data (computes the secure hash) + * @return An array with the signature + */ +public byte [] +sign() { + byte [] output = digest.digest(); + digest.reset(); + digest.update(opad); + return digest.digest(output); +} + +/** + * Verifies the data (computes the secure hash and compares it to the input) + * @param signature The signature to compare against + * @return true if the signature matches, false otherwise + */ +public boolean +verify(byte [] signature) { + return verify(signature, false); +} + +/** + * Verifies the data (computes the secure hash and compares it to the input) + * @param signature The signature to compare against + * @param truncation_ok If true, the signature may be truncated; only the + * number of bytes in the provided signature are compared. + * @return true if the signature matches, false otherwise + */ +public boolean +verify(byte [] signature, boolean truncation_ok) { + byte [] expected = sign(); + if (truncation_ok && signature.length < expected.length) { + byte [] truncated = new byte[signature.length]; + System.arraycopy(expected, 0, truncated, 0, truncated.length); + expected = truncated; + } + return Arrays.equals(signature, expected); +} + +/** + * Resets the HMAC object for further use + */ +public void +clear() { + digest.reset(); + digest.update(ipad); +} + +/** + * Returns the length of the digest. + */ +public int +digestLength() { + return digest.getDigestLength(); +} + +} |