diff options
Diffstat (limited to 'gnu/javax/crypto/mac')
-rw-r--r-- | gnu/javax/crypto/mac/BaseMac.java | 43 | ||||
-rw-r--r-- | gnu/javax/crypto/mac/HMac.java | 195 | ||||
-rw-r--r-- | gnu/javax/crypto/mac/HMacFactory.java | 65 | ||||
-rw-r--r-- | gnu/javax/crypto/mac/IMac.java | 154 | ||||
-rw-r--r-- | gnu/javax/crypto/mac/MacFactory.java | 78 | ||||
-rw-r--r-- | gnu/javax/crypto/mac/MacInputStream.java | 42 | ||||
-rw-r--r-- | gnu/javax/crypto/mac/MacOutputStream.java | 59 | ||||
-rw-r--r-- | gnu/javax/crypto/mac/OMAC.java | 209 | ||||
-rw-r--r-- | gnu/javax/crypto/mac/TMMH16.java | 195 | ||||
-rw-r--r-- | gnu/javax/crypto/mac/UHash32.java | 499 | ||||
-rw-r--r-- | gnu/javax/crypto/mac/UMac32.java | 287 |
11 files changed, 605 insertions, 1221 deletions
diff --git a/gnu/javax/crypto/mac/BaseMac.java b/gnu/javax/crypto/mac/BaseMac.java index 1b42a1644..16922130f 100644 --- a/gnu/javax/crypto/mac/BaseMac.java +++ b/gnu/javax/crypto/mac/BaseMac.java @@ -40,35 +40,26 @@ package gnu.javax.crypto.mac; import gnu.java.security.hash.IMessageDigest; -import java.util.Map; import java.security.InvalidKeyException; +import java.util.Map; /** - * <p>A base abstract class to facilitate <i>MAC</i> (Message Authentication - * Code) implementations.</p> + * A base abstract class to facilitate <i>MAC</i> (Message Authentication Code) + * implementations. */ -public abstract class BaseMac implements IMac +public abstract class BaseMac + implements IMac { - - // Constants and variables - // ------------------------------------------------------------------------- - /** The canonical name prefix of the <i>MAC</i>. */ protected String name; - /** Reference to the underlying hash algorithm instance. */ protected IMessageDigest underlyingHash; - /** The length of the truncated output in bytes. */ protected int truncatedSize; - /** The authentication key for this instance. */ - // protected transient byte[] K; - // Constructor(s) - // ------------------------------------------------------------------------- /** - * <p>Trivial constructor for use by concrete subclasses.</p> - * + * Trivial constructor for use by concrete subclasses. + * * @param name the canonical name of this instance. */ protected BaseMac(String name) @@ -79,8 +70,8 @@ public abstract class BaseMac implements IMac } /** - * <p>Trivial constructor for use by concrete subclasses.</p> - * + * Trivial constructor for use by concrete subclasses. + * * @param name the canonical name of this instance. * @param underlyingHash the underlying message digest algorithm instance. */ @@ -89,20 +80,10 @@ public abstract class BaseMac implements IMac this(name); if (underlyingHash != null) - { - truncatedSize = underlyingHash.hashSize(); - } + truncatedSize = underlyingHash.hashSize(); this.underlyingHash = underlyingHash; } - // Class methods - // ------------------------------------------------------------------------- - - // Instance methods - // ------------------------------------------------------------------------- - - // gnu.crypto.mac.IMac interface implementation ---------------------------- - public String name() { return name; @@ -137,12 +118,10 @@ public abstract class BaseMac implements IMac return result; } - // methods to be implemented by concrete subclasses ------------------------ - public abstract void init(Map attributes) throws InvalidKeyException, IllegalStateException; public abstract byte[] digest(); public abstract boolean selfTest(); -}
\ No newline at end of file +} diff --git a/gnu/javax/crypto/mac/HMac.java b/gnu/javax/crypto/mac/HMac.java index c1f97b541..f0e588d18 100644 --- a/gnu/javax/crypto/mac/HMac.java +++ b/gnu/javax/crypto/mac/HMac.java @@ -48,70 +48,51 @@ import java.util.HashMap; import java.util.Map; /** - * <p>The implementation of the <i>HMAC</i> (Keyed-Hash Message Authentication - * Code).</p> - * - * <p><i>HMAC</i> can be used in combination with any iterated cryptographic - * hash function. <i>HMAC</i> also uses a <i>secret key</i> for calculation and + * The implementation of the <i>HMAC</i> (Keyed-Hash Message Authentication + * Code). + * <p> + * <i>HMAC</i> can be used in combination with any iterated cryptographic hash + * function. <i>HMAC</i> also uses a <i>secret key</i> for calculation and * verification of the message authentication values. The main goals behind this - * construction are</p> - * + * construction are: * <ul> - * <li>To use, without modifications, available hash functions. In - * particular, hash functions that perform well in software, and for which - * code is freely and widely available.</li> - * - * <li>To preserve the original performance of the hash function without - * incurring a significant degradation.</li> - * - * <li>To use and handle keys in a simple way.</li> - * - * <li>To have a well understood cryptographic analysis of the strength of - * the authentication mechanism based on reasonable assumptions on the - * underlying hash function.</li> - * - * <li>To allow for easy replaceability of the underlying hash function in - * case that faster or more secure hash functions are found or required.</li> + * <li>To use, without modifications, available hash functions. In particular, + * hash functions that perform well in software, and for which code is freely + * and widely available.</li> + * <li>To preserve the original performance of the hash function without + * incurring a significant degradation.</li> + * <li>To use and handle keys in a simple way.</li> + * <li>To have a well understood cryptographic analysis of the strength of the + * authentication mechanism based on reasonable assumptions on the underlying + * hash function.</li> + * <li>To allow for easy replaceability of the underlying hash function in case + * that faster or more secure hash functions are found or required.</li> * </ul> - * - * <p>References:</p> - * + * <p> + * References: * <ol> - * <li><a href="http://www.ietf.org/rfc/rfc-2104.txt">RFC 2104</a>HMAC: - * Keyed-Hashing for Message Authentication.<br> - * H. Krawczyk, M. Bellare, and R. Canetti.</li> + * <li><a href="http://www.ietf.org/rfc/rfc-2104.txt">RFC 2104</a>HMAC: + * Keyed-Hashing for Message Authentication.<br> + * H. Krawczyk, M. Bellare, and R. Canetti.</li> * </ol> */ -public class HMac extends BaseMac implements Cloneable +public class HMac + extends BaseMac + implements Cloneable { - - // Constants and variables - // ------------------------------------------------------------------------- - public static final String USE_WITH_PKCS5_V2 = "gnu.crypto.hmac.pkcs5"; - private static final byte IPAD_BYTE = 0x36; - private static final byte OPAD_BYTE = 0x5C; - /** caches the result of the correctness test, once executed. */ private static Boolean valid; - protected int macSize; - protected int blockSize; - protected IMessageDigest ipadHash; - protected IMessageDigest opadHash; - protected byte[] ipad; - // Constructor(s) - // ------------------------------------------------------------------------- - /** - * <p>Trivial constructor for use by concrete subclasses.</p> + * Trivial constructor for use by concrete subclasses. * * @param underlyingHash the underlying hash algorithm instance. */ @@ -124,14 +105,6 @@ public class HMac extends BaseMac implements Cloneable ipadHash = opadHash = null; } - // Class methods - // ------------------------------------------------------------------------- - - // Instance methods - // ------------------------------------------------------------------------- - - // java.lang.Cloneable interface implementation ---------------------------- - public Object clone() throws CloneNotSupportedException { HMac result = (HMac) super.clone(); @@ -145,88 +118,65 @@ public class HMac extends BaseMac implements Cloneable return result; } - // implementation of abstract methods in BaseMac --------------------------- - public void init(Map attributes) throws InvalidKeyException, IllegalStateException { Integer ts = (Integer) attributes.get(TRUNCATED_SIZE); truncatedSize = (ts == null ? macSize : ts.intValue()); if (truncatedSize < (macSize / 2)) - { - throw new IllegalArgumentException("Truncated size too small"); - } + throw new IllegalArgumentException("Truncated size too small"); else if (truncatedSize < 10) - { - throw new IllegalArgumentException("Truncated size less than 80 bits"); - } + throw new IllegalArgumentException("Truncated size less than 80 bits"); // we dont use/save the key outside this method byte[] K = (byte[]) attributes.get(MAC_KEY_MATERIAL); if (K == null) { // take it as an indication to re-use previous key if set if (ipadHash == null) - { - throw new InvalidKeyException("Null key"); - } + throw new InvalidKeyException("Null key"); // we already went through the motions; ie. up to step #4. re-use underlyingHash = (IMessageDigest) ipadHash.clone(); return; } - // for HMACs used in key-derivation functions (e.g. PBKDF2) the key - // material need not be >= the (output) block size of the underlying - // algorithm + // for HMACs used in key-derivation functions (e.g. PBKDF2) the key material + // need not be >= the (output) block size of the underlying algorithm Boolean pkcs5 = (Boolean) attributes.get(USE_WITH_PKCS5_V2); if (pkcs5 == null) - { - pkcs5 = Boolean.FALSE; - } - if (K.length < macSize && !pkcs5.booleanValue()) - { - throw new InvalidKeyException("Key too short"); - } + pkcs5 = Boolean.FALSE; + if (K.length < macSize && ! pkcs5.booleanValue()) + throw new InvalidKeyException("Key too short"); if (K.length > blockSize) { - // (0) replace K with HASH(K) if K is larger than the hash's - // block size. Then pad with zeros until it is the correct - // size (the next `if'). + // (0) replace K with HASH(K) if K is larger than the hash's block size. + // Then pad with zeros until it is the correct size (the next `if'). underlyingHash.update(K, 0, K.length); K = underlyingHash.digest(); } if (K.length < blockSize) { - // (1) append zeros to the end of K to create a B byte string - // (e.g., if K is of length 20 bytes and B=64, then K will be - // appended with 44 zero bytes 0x00) + // (1) append zeros to the end of K to create a B byte string (e.g., if + // K is of length 20 bytes and B=64, then K will be appended with 44 + // zero bytes 0x00) int limit = (K.length > blockSize) ? blockSize : K.length; byte[] newK = new byte[blockSize]; System.arraycopy(K, 0, newK, 0, limit); K = newK; } - underlyingHash.reset(); opadHash = (IMessageDigest) underlyingHash.clone(); if (ipad == null) - { - ipad = new byte[blockSize]; - } - // (2) XOR (bitwise exclusive-OR) the B byte string computed in step - // (1) with ipad - // (3) append the stream of data 'text' to the B byte string resulting - // from step (2) + ipad = new byte[blockSize]; + // (2) XOR (bitwise exclusive-OR) the B byte string computed in step (1) + // with ipad + // (3) append the stream of data 'text' to the B byte string resulting from + // step (2) // (4) apply H to the stream generated in step (3) for (int i = 0; i < blockSize; i++) - { - // underlyingHash.update((byte)(K[i] ^ IPAD_BYTE)); - ipad[i] = (byte) (K[i] ^ IPAD_BYTE); - } + ipad[i] = (byte)(K[i] ^ IPAD_BYTE); for (int i = 0; i < blockSize; i++) - { - opadHash.update((byte) (K[i] ^ OPAD_BYTE)); - } - + opadHash.update((byte)(K[i] ^ OPAD_BYTE)); underlyingHash.update(ipad, 0, blockSize); ipadHash = (IMessageDigest) underlyingHash.clone(); K = null; @@ -245,28 +195,21 @@ public class HMac extends BaseMac implements Cloneable public byte[] digest() { if (ipadHash == null) - { - throw new IllegalStateException("HMAC not initialised"); - } - + throw new IllegalStateException("HMAC not initialised"); byte[] out = underlyingHash.digest(); - // (5) XOR (bitwise exclusive-OR) the B byte string computed in - // step (1) with opad + // (5) XOR (bitwise exclusive-OR) the B byte string computed in step (1) + // with opad underlyingHash = (IMessageDigest) opadHash.clone(); - // (6) append the H result from step (4) to the B byte string - // resulting from step (5) + // (6) append the H result from step (4) to the B byte string resulting from + // step (5) underlyingHash.update(out, 0, macSize); - // (7) apply H to the stream generated in step (6) and output - // the result + // (7) apply H to the stream generated in step (6) and output the result out = underlyingHash.digest(); // which also resets the underlying hash - // truncate and return if (truncatedSize == macSize) return out; - byte[] result = new byte[truncatedSize]; System.arraycopy(out, 0, result, 0, truncatedSize); - return result; } @@ -279,31 +222,25 @@ public class HMac extends BaseMac implements Cloneable IMac mac = new HMac(new MD5()); // use rfc-2104 test vectors String tv1 = "9294727A3638BB1C13F48EF8158BFC9D"; String tv3 = "56BE34521D144C88DBB8C733F0E8B3F6"; - byte[] k1 = new byte[] { 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, - 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, - 0x0B, 0x0B }; - byte[] k3 = new byte[] { (byte) 0xAA, (byte) 0xAA, (byte) 0xAA, - (byte) 0xAA, (byte) 0xAA, (byte) 0xAA, - (byte) 0xAA, (byte) 0xAA, (byte) 0xAA, - (byte) 0xAA, (byte) 0xAA, (byte) 0xAA, - (byte) 0xAA, (byte) 0xAA, (byte) 0xAA, - (byte) 0xAA }; + byte[] k1 = new byte[] { + 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, + 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B }; + byte[] k3 = new byte[] { + (byte) 0xAA, (byte) 0xAA, (byte) 0xAA, (byte) 0xAA, + (byte) 0xAA, (byte) 0xAA, (byte) 0xAA, (byte) 0xAA, + (byte) 0xAA, (byte) 0xAA, (byte) 0xAA, (byte) 0xAA, + (byte) 0xAA, (byte) 0xAA, (byte) 0xAA, (byte) 0xAA }; byte[] data = new byte[50]; for (int i = 0; i < 50;) - { - data[i++] = (byte) 0xDD; - } + data[i++] = (byte) 0xDD; HashMap map = new HashMap(); - // test vector #1 map.put(MAC_KEY_MATERIAL, k1); mac.init(map); mac.update("Hi There".getBytes("ASCII"), 0, 8); - if (!tv1.equals(Util.toString(mac.digest()))) - { - valid = Boolean.FALSE; - } + if (! tv1.equals(Util.toString(mac.digest()))) + valid = Boolean.FALSE; // test #2 is not used since it causes a "Key too short" exception @@ -311,10 +248,8 @@ public class HMac extends BaseMac implements Cloneable map.put(MAC_KEY_MATERIAL, k3); mac.init(map); mac.update(data, 0, 50); - if (!tv3.equals(Util.toString(mac.digest()))) - { - valid = Boolean.FALSE; - } + if (! tv3.equals(Util.toString(mac.digest()))) + valid = Boolean.FALSE; valid = Boolean.TRUE; } catch (Exception x) diff --git a/gnu/javax/crypto/mac/HMacFactory.java b/gnu/javax/crypto/mac/HMacFactory.java index 156e6ced5..bc70e8b66 100644 --- a/gnu/javax/crypto/mac/HMacFactory.java +++ b/gnu/javax/crypto/mac/HMacFactory.java @@ -47,68 +47,56 @@ import java.util.Iterator; import java.util.Set; /** - * <p>A <i>Factory</i> to instantiate Keyed-Hash Message Authentication Code - * (HMAC) algorithm instances.</p> + * A <i>Factory</i> to instantiate Keyed-Hash Message Authentication Code + * (HMAC) algorithm instances. */ -public class HMacFactory implements Registry +public class HMacFactory + implements Registry { - - // Constants and variables - // ------------------------------------------------------------------------- - - // Constructor(s) - // ------------------------------------------------------------------------- - /** Trivial constructor to enforce <i>Singleton</i> pattern. */ private HMacFactory() { super(); } - // Class methods - // ------------------------------------------------------------------------- - /** - * <p>Return an instance of a <i>HMAC</i> algorithm given the name of its + * Return an instance of a <i>HMAC</i> algorithm given the name of its * underlying hash function, prefixed with the literal defined in - * {@link Registry#HMAC_NAME_PREFIX}.</p> - * + * {@link Registry#HMAC_NAME_PREFIX}. + * * @param name the fully qualified name of the underlying algorithm: composed - * as the concatenation of a literal prefix (see {@link Registry#HMAC_NAME_PREFIX}) - * and the name of the underlying hash algorithm. - * @return an instance of the <i>HMAC</i> algorithm, or <code>null</code> if - * none can be constructed. + * as the concatenation of a literal prefix (see + * {@link Registry#HMAC_NAME_PREFIX}) and the name of the underlying + * hash algorithm. + * @return an instance of the <i>HMAC</i> algorithm, or <code>null</code> + * if none can be constructed. * @exception InternalError if the implementation does not pass its self-test. */ public static IMac getInstance(String name) { if (name == null) - { - return null; - } + return null; name = name.trim(); name = name.toLowerCase(); - if (!name.startsWith(HMAC_NAME_PREFIX)) - { - return null; - } + if (! name.startsWith(HMAC_NAME_PREFIX)) + return null; // strip the prefix name = name.substring(HMAC_NAME_PREFIX.length()).trim(); IMac result = new HMac(HashFactory.getInstance(name)); - if (result != null && !result.selfTest()) - { - throw new InternalError(result.name()); - } + if (result != null && ! result.selfTest()) + throw new InternalError(result.name()); return result; } /** - * <p>Returns a {@link java.util.Set} of names of <i>HMAC</i> algorithms - * supported by this <i>Factory</i>.</p> - * + * <p> + * Returns a {@link java.util.Set} of names of <i>HMAC</i> algorithms + * supported by this <i>Factory</i>. + * </p> + * * @return a {@link java.util.Set} of HMAC algorithm names (Strings). */ public static final Set getNames() @@ -116,13 +104,8 @@ public class HMacFactory implements Registry Set hashNames = HashFactory.getNames(); HashSet hs = new HashSet(); for (Iterator it = hashNames.iterator(); it.hasNext();) - { - hs.add(HMAC_NAME_PREFIX + ((String) it.next())); - } + hs.add(HMAC_NAME_PREFIX + ((String) it.next())); return Collections.unmodifiableSet(hs); } - - // Instance methods - // ------------------------------------------------------------------------- -}
\ No newline at end of file +} diff --git a/gnu/javax/crypto/mac/IMac.java b/gnu/javax/crypto/mac/IMac.java index c4170c42c..a9da9eefb 100644 --- a/gnu/javax/crypto/mac/IMac.java +++ b/gnu/javax/crypto/mac/IMac.java @@ -38,108 +38,93 @@ exception statement from your version. */ package gnu.javax.crypto.mac; -import java.util.Map; import java.security.InvalidKeyException; +import java.util.Map; /** - * <p>The basic visible methods of any MAC (Message Authentication Code) - * algorithm.</p> - * - * <p>A <i>MAC</i> provides a way to check the integrity of information + * The basic visible methods of any MAC (Message Authentication Code) algorithm. + * <p> + * A <i>MAC</i> provides a way to check the integrity of information * transmitted over, or stored in, an unreliable medium, based on a secret key. * Typically, <i>MAC</i>s are used between two parties, that share a common - * secret key, in order to validate information transmitted between them.</p> - * - * <p>When a <i>MAC</i> algorithm is based on a cryptographic hash function, it - * is then called to a <i>HMAC</i> (Hashed Message Authentication Code) --see - * <a href="http://www.ietf.org/rfc/rfc-2104.txt">RFC-2104</a>.</p> - * + * secret key, in order to validate information transmitted between them. + * <p> + * When a <i>MAC</i> algorithm is based on a cryptographic hash function, it is + * then called to a <i>HMAC</i> (Hashed Message Authentication Code) --see <a + * href="http://www.ietf.org/rfc/rfc-2104.txt">RFC-2104</a>. + * <p> * Another type of <i>MAC</i> algorithms exist: UMAC or <i>Universal Message - * Authentication Code</i>, described in - * <a href="http://www.ietf.org/internet-drafts/draft-krovetz-umac-01.txt"> - * draft-krovetz-umac-01.txt</a>.</p> - * - * <p>With <i>UMAC</i>s, the sender and receiver share a common secret key (the - * <i>MAC</i> key) which determines:</p> - * + * Authentication Code</i>, described in <a + * href="http://www.ietf.org/internet-drafts/draft-krovetz-umac-01.txt"> + * draft-krovetz-umac-01.txt</a>. + * <p> + * With <i>UMAC</i>s, the sender and receiver share a common secret key (the + * <i>MAC</i> key) which determines: * <ul> - * <li>The key for a <i>universal hash function</i>. This hash function is - * <i>non-cryptographic</i>, in the sense that it does not need to have any - * cryptographic <i>hardness</i> property. Rather, it needs to satisfy some - * combinatorial property, which can be proven to hold without relying on - * unproven hardness assumptions.</li> - * - * <li>The key for a <i>pseudorandom function</i>. This is where one needs a - * cryptographic hardness assumption. The pseudorandom function may be - * obtained from a <i>block cipher</i> or a <i>cryptographic hash function</i>. - * </li> + * <li>The key for a <i>universal hash function</i>. This hash function is + * <i>non-cryptographic</i>, in the sense that it does not need to have any + * cryptographic <i>hardness</i> property. Rather, it needs to satisfy some + * combinatorial property, which can be proven to hold without relying on + * unproven hardness assumptions.</li> + * <li>The key for a <i>pseudorandom function</i>. This is where one needs a + * cryptographic hardness assumption. The pseudorandom function may be obtained + * from a <i>block cipher</i> or a <i>cryptographic hash function</i>. </li> * </ul> - * - * <p>References:</p> - * + * <p> + * References: * <ol> - * <li><a href="http://www.ietf.org/rfc/rfc-2104.txt">RFC 2104</a>HMAC: - * Keyed-Hashing for Message Authentication.<br> - * H. Krawczyk, M. Bellare, and R. Canetti.</li> - * - * <li><a href="http://www.ietf.org/internet-drafts/draft-krovetz-umac-01.txt"> - * UMAC</a>: Message Authentication Code using Universal Hashing.<br> - * T. Krovetz, J. Black, S. Halevi, A. Hevia, H. Krawczyk, and P. Rogaway.</li> + * <li><a href="http://www.ietf.org/rfc/rfc-2104.txt">RFC 2104</a>HMAC: + * Keyed-Hashing for Message Authentication.<br> + * H. Krawczyk, M. Bellare, and R. Canetti.</li> + * <li><a href="http://www.ietf.org/internet-drafts/draft-krovetz-umac-01.txt"> + * UMAC</a>: Message Authentication Code using Universal Hashing.<br> + * T. Krovetz, J. Black, S. Halevi, A. Hevia, H. Krawczyk, and P. Rogaway.</li> * </ol> */ public interface IMac { - - // Constants - // ------------------------------------------------------------------------- - /** * Property name of the user-supplied key material. The value associated to * this property name is taken to be a byte array. */ String MAC_KEY_MATERIAL = "gnu.crypto.mac.key.material"; - /** - * <p>Property name of the desired truncated output size in bytes. The value - * associated to this property name is taken to be an integer. If no value - * is specified in the attributes map at initialisation time, then all bytes - * of the underlying hash algorithm's output are emitted.</p> - * - * <p>This implementation, follows the recommendation of the <i>RFC 2104</i> - * authors; specifically:</p> - * + * Property name of the desired truncated output size in bytes. The value + * associated to this property name is taken to be an integer. If no value is + * specified in the attributes map at initialisation time, then all bytes of + * the underlying hash algorithm's output are emitted. + * <p> + * This implementation, follows the recommendation of the <i>RFC 2104</i> + * authors; specifically: * <pre> - * We recommend that the output length t be not less than half the - * length of the hash output (to match the birthday attack bound) - * and not less than 80 bits (a suitable lower bound on the number - * of bits that need to be predicted by an attacker). + * We recommend that the output length t be not less than half the + * length of the hash output (to match the birthday attack bound) + * and not less than 80 bits (a suitable lower bound on the number + * of bits that need to be predicted by an attacker). * </pre> */ String TRUNCATED_SIZE = "gnu.crypto.mac.truncated.size"; - // Methods - // ------------------------------------------------------------------------- - /** - * <p>Returns the canonical name of this algorithm.</p> - * + * Returns the canonical name of this algorithm. + * * @return the canonical name of this algorithm. */ String name(); /** - * <p>Returns the output length in bytes of this <i>MAC</i> algorithm.</p> - * + * Returns the output length in bytes of this <i>MAC</i> algorithm. + * * @return the output length in bytes of this <i>MAC</i> algorithm. */ int macSize(); /** - * <p>Initialises the algorithm with designated attributes. Permissible names - * and values are described in the class documentation above.</p> - * + * Initialises the algorithm with designated attributes. Permissible names and + * values are described in the class documentation above. + * * @param attributes a set of name-value pairs that describe the desired - * future instance behaviour. + * future instance behaviour. * @exception InvalidKeyException if the key data is invalid. * @exception IllegalStateException if the instance is already initialised. * @see #MAC_KEY_MATERIAL @@ -147,18 +132,17 @@ public interface IMac void init(Map attributes) throws InvalidKeyException, IllegalStateException; /** - * <p>Continues a <i>MAC</i> operation using the input byte.</p> - * + * Continues a <i>MAC</i> operation using the input byte. + * * @param b the input byte to digest. */ void update(byte b); /** - * <p>Continues a <i>MAC</i> operation, by filling the buffer, processing - * data in the algorithm's MAC_SIZE-bit block(s), updating the context and - * count, and buffering the remaining bytes in buffer for the next - * operation.</p> - * + * Continues a <i>MAC</i> operation, by filling the buffer, processing data + * in the algorithm's MAC_SIZE-bit block(s), updating the context and count, + * and buffering the remaining bytes in buffer for the next operation. + * * @param in the input block. * @param offset start of meaningful bytes in input block. * @param length number of bytes, in input block, to consider. @@ -166,32 +150,32 @@ public interface IMac void update(byte[] in, int offset, int length); /** - * <p>Completes the <i>MAC</i> by performing final operations such as - * padding and resetting the instance.</p> - * + * Completes the <i>MAC</i> by performing final operations such as padding + * and resetting the instance. + * * @return the array of bytes representing the <i>MAC</i> value. */ byte[] digest(); /** - * <p>Resets the algorithm instance for re-initialisation and use with other - * characteristics. This method always succeeds.</p> + * Resets the algorithm instance for re-initialisation and use with other + * characteristics. This method always succeeds. */ void reset(); /** - * <p>A basic test. Ensures that the MAC of a pre-determined message is equal - * to a known pre-computed value.</p> - * + * A basic test. Ensures that the MAC of a pre-determined message is equal to + * a known pre-computed value. + * * @return <code>true</code> if the implementation passes a basic self-test. - * Returns <code>false</code> otherwise. + * Returns <code>false</code> otherwise. */ boolean selfTest(); /** - * <p>Returns a clone copy of this instance.</p> - * + * Returns a clone copy of this instance. + * * @return a clone copy of this instance. */ Object clone() throws CloneNotSupportedException; -}
\ No newline at end of file +} diff --git a/gnu/javax/crypto/mac/MacFactory.java b/gnu/javax/crypto/mac/MacFactory.java index d8f8bcfce..5d4a56182 100644 --- a/gnu/javax/crypto/mac/MacFactory.java +++ b/gnu/javax/crypto/mac/MacFactory.java @@ -48,17 +48,13 @@ import java.util.Iterator; import java.util.Set; /** - * <p>A <i>Factory</i> that instantiates instances of every supported Message - * Authentication Code algorithms, including all <i>HMAC</i> algorithms.</p> + * A <i>Factory</i> that instantiates instances of every supported Message + * Authentication Code algorithms, including all <i>HMAC</i> algorithms. */ -public class MacFactory implements Registry +public class MacFactory + implements Registry { - - // Constants and variables - // ------------------------------------------------------------------------- - - // Constructor(s) - // ------------------------------------------------------------------------- + private static Set names; /** Trivial constructor to enforce <i>Singleton</i> pattern. */ private MacFactory() @@ -66,72 +62,51 @@ public class MacFactory implements Registry super(); } - // Class methods - // ------------------------------------------------------------------------- - /** - * <p>Returns an instance of a <i>MAC</i> algorithm given its name.</p> - * + * Returns an instance of a <i>MAC</i> algorithm given its name. + * * @param name the name of the MAC algorithm. * @return an instance of the <i>MAC</i> algorithm, or <code>null</code> if - * none can be constructed. + * none can be constructed. * @exception InternalError if the implementation does not pass its self-test. */ public static IMac getInstance(String name) { if (name == null) - { - return null; - } + return null; name = name.trim(); name = name.toLowerCase(); if (name.startsWith(HMAC_NAME_PREFIX)) - { - return HMacFactory.getInstance(name); - } + return HMacFactory.getInstance(name); if (name.startsWith(OMAC_PREFIX)) { name = name.substring(OMAC_PREFIX.length()); IBlockCipher cipher = CipherFactory.getInstance(name); if (cipher == null) - { - return null; - } + return null; return new OMAC(cipher); } - IMac result = null; if (name.equalsIgnoreCase(UHASH32)) - { - result = new UHash32(); - } + result = new UHash32(); else if (name.equalsIgnoreCase(UMAC32)) - { - result = new UMac32(); - } + result = new UMac32(); else if (name.equalsIgnoreCase(TMMH16)) - { - result = new TMMH16(); - } - // else if (name.equalsIgnoreCase(TMMH32)) { - // result = new TMMH32(); - // } + result = new TMMH16(); - if (result != null && !result.selfTest()) - { - throw new InternalError(result.name()); - } + if (result != null && ! result.selfTest()) + throw new InternalError(result.name()); return result; } /** - * <p>Returns a {@link java.util.Set} of names of <i>MAC</i> algorithms - * supported by this <i>Factory</i>.</p> - * - * @return a {@link java.util.Set} of MAC names (Strings). + * Returns a {@link Set} of names of <i>MAC</i> algorithms supported by this + * <i>Factory</i>. + * + * @return a {@link Set} of MAC names (Strings). */ public static final Set getNames() { @@ -144,21 +119,12 @@ public class MacFactory implements Registry hs.add(UHASH32); hs.add(UMAC32); hs.add(TMMH16); - // hs.add(TMMH32); - for (Iterator it = CipherFactory.getNames().iterator(); it.hasNext();) - { - hs.add(OMAC_PREFIX + it.next()); - } + hs.add(OMAC_PREFIX + it.next()); names = Collections.unmodifiableSet(hs); } } return names; } - - private static Set names; - - // Instance methods - // ------------------------------------------------------------------------- -}
\ No newline at end of file +} diff --git a/gnu/javax/crypto/mac/MacInputStream.java b/gnu/javax/crypto/mac/MacInputStream.java index 9acd18b19..e734b1bbb 100644 --- a/gnu/javax/crypto/mac/MacInputStream.java +++ b/gnu/javax/crypto/mac/MacInputStream.java @@ -46,30 +46,19 @@ import java.io.IOException; * A filtering input stream that computes a MAC (message authentication code) * over all data read from the stream. */ -public class MacInputStream extends FilterInputStream +public class MacInputStream + extends FilterInputStream { - - // Field. - // ------------------------------------------------------------------------ - - /** - * The digesting state. The MAC is updated only if this flag is true. - */ + /** The digesting state. The MAC is updated only if this flag is true. */ private boolean digesting; - - /** - * The MAC being updated. - */ + /** The MAC being updated. */ private IMac mac; - // Constructor. - // ------------------------------------------------------------------------ - /** - * Creates a new MacInputStream. The stream is initially set to digest - * data written, the <i>mac</i> argument must have already been initialized, - * and the <i>mac</i> argument is <b>not</b> cloned. - * + * Creates a new MacInputStream. The stream is initially set to digest data + * written, the <i>mac</i> argument must have already been initialized, and + * the <i>mac</i> argument is <b>not</b> cloned. + * * @param in The underlying input stream. * @param mac The mac instance to use. */ @@ -82,12 +71,9 @@ public class MacInputStream extends FilterInputStream digesting = true; } - // Instance methods. - // ------------------------------------------------------------------------ - /** * Returns the MAC this stream is updating. - * + * * @return The MAC. */ public IMac getMac() @@ -98,7 +84,7 @@ public class MacInputStream extends FilterInputStream /** * Sets the MAC this stream is updating, which must have already been * initialized. The argument is not cloned by this method. - * + * * @param mac The new MAC. * @throws NullPointerException If the argument is null. */ @@ -110,9 +96,9 @@ public class MacInputStream extends FilterInputStream } /** - * Turns the digesting state on or off. When off, the MAC will not be - * updated when data is written to the stream. - * + * Turns the digesting state on or off. When off, the MAC will not be updated + * when data is written to the stream. + * * @param flag The new digesting state. */ public void on(boolean flag) @@ -135,4 +121,4 @@ public class MacInputStream extends FilterInputStream mac.update(buf, off, i); return i; } -}
\ No newline at end of file +} diff --git a/gnu/javax/crypto/mac/MacOutputStream.java b/gnu/javax/crypto/mac/MacOutputStream.java index a48d25ba3..739a78497 100644 --- a/gnu/javax/crypto/mac/MacOutputStream.java +++ b/gnu/javax/crypto/mac/MacOutputStream.java @@ -43,29 +43,23 @@ import java.io.IOException; import java.io.OutputStream; /** - * <p>A filtering output stream that computes a MAC (message authentication - * code) over all data written to the stream.</p> + * A filtering output stream that computes a MAC (message authentication code) + * over all data written to the stream. */ -public class MacOutputStream extends FilterOutputStream +public class MacOutputStream + extends FilterOutputStream { - - // Constants and variables - // ------------------------------------------------------------------------- - /** The digesting state. The MAC is updated only if this flag is true. */ private boolean digesting; - /** The MAC being updated. */ private IMac mac; - // Constructor(s) - // ------------------------------------------------------------------------- - /** - * <p>Creates a new <code>MacOutputStream</code>. The stream is initially set + * Creates a new <code>MacOutputStream</code>. The stream is initially set * to digest data written, the <code>mac</code> argument must have already - * been initialized, and the <code>mac</code> argument is <b>not</b> cloned.</p> - * + * been initialized, and the <code>mac</code> argument is <b>not</b> + * cloned. + * * @param out The underlying output stream. * @param mac The mac instance to use. */ @@ -73,19 +67,14 @@ public class MacOutputStream extends FilterOutputStream { super(out); if (mac == null) - { - throw new NullPointerException(); - } + throw new NullPointerException(); this.mac = mac; digesting = true; } - // Instance methods - // ------------------------------------------------------------------------- - /** - * <p>Returns the MAC this stream is updating.</p> - * + * Returns the MAC this stream is updating. + * * @return The MAC. */ public IMac getMac() @@ -94,25 +83,23 @@ public class MacOutputStream extends FilterOutputStream } /** - * <p>Sets the MAC this stream is updating, which must have already been - * initialized. The argument is not cloned by this method.</p> - * + * Sets the MAC this stream is updating, which must have already been + * initialized. The argument is not cloned by this method. + * * @param mac The non-null new MAC. * @throws NullPointerException If the argument is null. */ public void setMac(IMac mac) { if (mac == null) - { - throw new NullPointerException(); - } + throw new NullPointerException(); this.mac = mac; } /** - * <p>Turns the digesting state on or off. When off, the MAC will not be - * updated when data is written to the stream.</p> - * + * Turns the digesting state on or off. When off, the MAC will not be updated + * when data is written to the stream. + * * @param flag The new digesting state. */ public void on(boolean flag) @@ -123,18 +110,14 @@ public class MacOutputStream extends FilterOutputStream public void write(int b) throws IOException { if (digesting) - { - mac.update((byte) b); - } + mac.update((byte) b); out.write(b); } public void write(byte[] buf, int off, int len) throws IOException { if (digesting) - { - mac.update(buf, off, len); - } + mac.update(buf, off, len); out.write(buf, off, len); } -}
\ No newline at end of file +} diff --git a/gnu/javax/crypto/mac/OMAC.java b/gnu/javax/crypto/mac/OMAC.java index 21156ac63..cd753acaf 100644 --- a/gnu/javax/crypto/mac/OMAC.java +++ b/gnu/javax/crypto/mac/OMAC.java @@ -38,6 +38,7 @@ exception statement from your version. */ package gnu.javax.crypto.mac; +import gnu.java.security.Configuration; import gnu.java.security.Registry; import gnu.java.security.util.Util; import gnu.javax.crypto.cipher.CipherFactory; @@ -48,76 +49,49 @@ import java.security.InvalidKeyException; import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import java.util.logging.Logger; /** - * <p>The One-Key CBC MAC, OMAC. This message authentication code is based on - * a block cipher in CBC mode.</p> - * - * <p>References:</p> + * The One-Key CBC MAC, OMAC. This message authentication code is based on a + * block cipher in CBC mode. + * <p> + * References: * <ol> * <li>Tetsu Iwata and Kaoru Kurosawa, <i><a * href="http://crypt.cis.ibaraki.ac.jp/omac/docs/omac.pdf">OMAC: One-Key CBC * MAC</a></i>.</li> * </ol> */ -public class OMAC implements IMac +public class OMAC + implements IMac { - - // Constants and fields. - // ------------------------------------------------------------------------ - - private static final boolean DEBUG = false; - - private static void debug(String msg) - { - System.out.print(">>> OMAC: "); - System.out.println(msg); - } - + private static final Logger log = Logger.getLogger(OMAC.class.getName()); private static final byte C1 = (byte) 0x87; - private static final byte C2 = 0x1b; - // Test key for OMAC-AES-128 - private static final byte[] KEY0 = Util.toBytesFromString("2b7e151628aed2a6abf7158809cf4f3c"); - + private static final byte[] KEY0 = + Util.toBytesFromString("2b7e151628aed2a6abf7158809cf4f3c"); // Test MAC for zero-length input. - private static final byte[] DIGEST0 = Util.toBytesFromString("bb1d6929e95937287fa37d129b756746"); - + private static final byte[] DIGEST0 = + Util.toBytesFromString("bb1d6929e95937287fa37d129b756746"); private static Boolean valid; - private final IBlockCipher cipher; - private final String name; - private IMode mode; - private int blockSize; - private int outputSize; - private byte[] Lu, Lu2; - private byte[] M; - private byte[] Y; - private boolean init; - private int index; - // Constructor. - // ------------------------------------------------------------------------ - public OMAC(IBlockCipher cipher) { this.cipher = cipher; this.name = "OMAC-" + cipher.name(); } - // Instance methods. - // ------------------------------------------------------------------------ - public Object clone() { return new OMAC(cipher); @@ -139,135 +113,89 @@ public class OMAC implements IMac attrib2.put(IBlockCipher.KEY_MATERIAL, attrib.get(MAC_KEY_MATERIAL)); cipher.reset(); cipher.init(attrib2); - blockSize = cipher.currentBlockSize(); Integer os = (Integer) attrib.get(TRUNCATED_SIZE); if (os != null) { outputSize = os.intValue(); if (outputSize < 0 || outputSize > blockSize) - { - throw new IllegalArgumentException("truncated size out of range"); - } + throw new IllegalArgumentException("truncated size out of range"); } else - { - outputSize = blockSize; - } + outputSize = blockSize; byte[] L = new byte[blockSize]; cipher.encryptBlock(L, 0, L, 0); - - if (DEBUG) - { - debug("L = " + Util.toString(L).toLowerCase()); - } - + if (Configuration.DEBUG) + log.fine("L = " + Util.toString(L).toLowerCase()); if (Lu != null) { Arrays.fill(Lu, (byte) 0); if (Lu.length != blockSize) - { - Lu = new byte[blockSize]; - } + Lu = new byte[blockSize]; } else - { - Lu = new byte[blockSize]; - } + Lu = new byte[blockSize]; if (Lu2 != null) { Arrays.fill(Lu2, (byte) 0); if (Lu2.length != blockSize) - { - Lu2 = new byte[blockSize]; - } + Lu2 = new byte[blockSize]; } else - { - Lu2 = new byte[blockSize]; - } + Lu2 = new byte[blockSize]; boolean msb = (L[0] & 0x80) != 0; for (int i = 0; i < blockSize; i++) { - Lu[i] = (byte) (L[i] << 1 & 0xFF); + Lu[i] = (byte)(L[i] << 1 & 0xFF); if (i + 1 < blockSize) - { - Lu[i] |= (byte) ((L[i + 1] & 0x80) >> 7); - } + Lu[i] |= (byte)((L[i + 1] & 0x80) >> 7); } if (msb) { if (blockSize == 16) - { - Lu[Lu.length - 1] ^= C1; - } + Lu[Lu.length - 1] ^= C1; else if (blockSize == 8) - { - Lu[Lu.length - 1] ^= C2; - } + Lu[Lu.length - 1] ^= C2; else - { - throw new IllegalArgumentException( - "unsupported cipher block size: " - + blockSize); - } + throw new IllegalArgumentException("unsupported cipher block size: " + + blockSize); } - if (DEBUG) - { - debug("Lu = " + Util.toString(Lu).toLowerCase()); - } - + if (Configuration.DEBUG) + log.fine("Lu = " + Util.toString(Lu).toLowerCase()); msb = (Lu[0] & 0x80) != 0; for (int i = 0; i < blockSize; i++) { - Lu2[i] = (byte) (Lu[i] << 1 & 0xFF); + Lu2[i] = (byte)(Lu[i] << 1 & 0xFF); if (i + 1 < blockSize) - { - Lu2[i] |= (byte) ((Lu[i + 1] & 0x80) >> 7); - } + Lu2[i] |= (byte)((Lu[i + 1] & 0x80) >> 7); } if (msb) { if (blockSize == 16) - { - Lu2[Lu2.length - 1] ^= C1; - } + Lu2[Lu2.length - 1] ^= C1; else - { - Lu2[Lu2.length - 1] ^= C2; - } + Lu2[Lu2.length - 1] ^= C2; } - if (DEBUG) - { - debug("Lu2 = " + Util.toString(Lu2).toLowerCase()); - } - + if (Configuration.DEBUG) + log.fine("Lu2 = " + Util.toString(Lu2).toLowerCase()); if (M != null) { Arrays.fill(M, (byte) 0); if (M.length != blockSize) - { - M = new byte[blockSize]; - } + M = new byte[blockSize]; } else - { - M = new byte[blockSize]; - } + M = new byte[blockSize]; if (Y != null) { Arrays.fill(Y, (byte) 0); if (Y.length != blockSize) - { - Y = new byte[blockSize]; - } + Y = new byte[blockSize]; } else - { - Y = new byte[blockSize]; - } + Y = new byte[blockSize]; index = 0; init = true; @@ -275,10 +203,8 @@ public class OMAC implements IMac public void update(byte b) { - if (!init) - { - throw new IllegalStateException("not initialized"); - } + if (! init) + throw new IllegalStateException("not initialized"); if (index == M.length) { process(); @@ -289,15 +215,11 @@ public class OMAC implements IMac public void update(byte[] buf, int off, int len) { - if (!init) - { - throw new IllegalStateException("not initialized"); - } + if (! init) + throw new IllegalStateException("not initialized"); if (off < 0 || len < 0 || off + len > buf.length) - { - throw new IndexOutOfBoundsException("size=" + buf.length + "; off=" - + off + "; len=" + len); - } + throw new IndexOutOfBoundsException("size=" + buf.length + "; off=" + off + + "; len=" + len); for (int i = 0; i < len;) { if (index == blockSize) @@ -321,30 +243,22 @@ public class OMAC implements IMac public void digest(byte[] out, int off) { - if (!init) - { - throw new IllegalStateException("not initialized"); - } + if (! init) + throw new IllegalStateException("not initialized"); if (off < 0 || off + outputSize > out.length) - { - throw new IndexOutOfBoundsException("size=" + out.length + "; off=" - + off + "; len=" + outputSize); - } + throw new IndexOutOfBoundsException("size=" + out.length + "; off=" + off + + "; len=" + outputSize); byte[] T = new byte[blockSize]; byte[] L = Lu; if (index < blockSize) { M[index++] = (byte) 0x80; while (index < blockSize) - { - M[index++] = 0; - } + M[index++] = 0; L = Lu2; } for (int i = 0; i < blockSize; i++) - { - T[i] = (byte) (M[i] ^ Y[i] ^ L[i]); - } + T[i] = (byte)(M[i] ^ Y[i] ^ L[i]); cipher.encryptBlock(T, 0, T, 0); System.arraycopy(T, 0, out, off, outputSize); reset(); @@ -354,13 +268,9 @@ public class OMAC implements IMac { index = 0; if (Y != null) - { - Arrays.fill(Y, (byte) 0); - } + Arrays.fill(Y, (byte) 0); if (M != null) - { - Arrays.fill(M, (byte) 0); - } + Arrays.fill(M, (byte) 0); } public boolean selfTest() @@ -380,21 +290,14 @@ public class OMAC implements IMac return false; } if (digest == null) - { - return false; - } + return false; return Arrays.equals(DIGEST0, digest); } - // Own methods. - // ------------------------------------------------------------------------ - private void process() { for (int i = 0; i < blockSize; i++) - { - M[i] = (byte) (M[i] ^ Y[i]); - } + M[i] = (byte)(M[i] ^ Y[i]); cipher.encryptBlock(M, 0, Y, 0); } -}
\ No newline at end of file +} diff --git a/gnu/javax/crypto/mac/TMMH16.java b/gnu/javax/crypto/mac/TMMH16.java index af6e78fcf..0a7b4a6ca 100644 --- a/gnu/javax/crypto/mac/TMMH16.java +++ b/gnu/javax/crypto/mac/TMMH16.java @@ -46,91 +46,63 @@ import java.security.InvalidKeyException; import java.util.Map; /** - * <p><i>TMMH</i> is a <i>universal</i> hash function suitable for message + * <i>TMMH</i> is a <i>universal</i> hash function suitable for message * authentication in the Wegman-Carter paradigm, as in the Stream Cipher * Security Transform. It is simple, quick, and especially appropriate for * Digital Signal Processors and other processors with a fast multiply * operation, though a straightforward implementation requires storage equal in - * length to the largest message to be hashed.</p> - * - * <p><i>TMMH</i> is a simple hash function which maps a key and a message to a + * length to the largest message to be hashed. + * <p> + * <i>TMMH</i> is a simple hash function which maps a key and a message to a * hash value. There are two versions of TMMH: TMMH/16 and TMMH/32. <i>TMMH</i> * can be used as a message authentication code, as described in Section 5 (see - * References).</p> - * - * <p>The key, message, and hash value are all octet strings, and the lengths of + * References). + * <p> + * The key, message, and hash value are all octet strings, and the lengths of * these quantities are denoted as <code>KEY_LENGTH</code>, - * <code>MESSAGE_LENGTH</code>, and <code>TAG_LENGTH</code>, respectively. The - * values of <code>KEY_LENGTH</code> and <code>TAG_LENGTH</code> + * <code>MESSAGE_LENGTH</code>, and <code>TAG_LENGTH</code>, respectively. + * The values of <code>KEY_LENGTH</code> and <code>TAG_LENGTH</code> * <bold>MUST</bold> be fixed for any particular fixed value of the key, and - * must obey the alignment restrictions described below.</p> - * - * <p>The parameter <code>MAX_HASH_LENGTH</code>, which denotes the maximum + * must obey the alignment restrictions described below. + * <p> + * The parameter <code>MAX_HASH_LENGTH</code>, which denotes the maximum * value which <code>MESSAGE_LENGTH</code> may take, is equal to - * <code>KEY_LENGTH - TAG_LENGTH</code>.</p> - * - * <p>References:</p> - * + * <code>KEY_LENGTH - TAG_LENGTH</code>. + * <p> + * References: * <ol> - * <li><a - href="http://www.ietf.org/internet-drafts/draft-mcgrew-saag-tmmh-01.txt"> - * The Truncated Multi-Modular Hash Function (TMMH)</a>, David A. McGrew.</li> + * <li><a + * href="http://www.ietf.org/internet-drafts/draft-mcgrew-saag-tmmh-01.txt"> The + * Truncated Multi-Modular Hash Function (TMMH)</a>, David A. McGrew.</li> * </ol> */ -public class TMMH16 extends BaseMac implements Cloneable +public class TMMH16 + extends BaseMac + implements Cloneable { - - // Constants and variables - // ------------------------------------------------------------------------- - public static final String TAG_LENGTH = "gnu.crypto.mac.tmmh.tag.length"; - public static final String KEYSTREAM = "gnu.crypto.mac.tmmh.keystream"; - public static final String PREFIX = "gnu.crypto.mac.tmmh.prefix"; - private static final int P = (1 << 16) + 1; // the TMMH/16 prime - /** caches the result of the correctness test, once executed. */ private static Boolean valid; - private int tagWords = 0; // the tagLength expressed in words - private IRandom keystream = null; // the keystream generator - private byte[] prefix; // mask to use when operating as an authentication f. - private long keyWords; // key words counter - private long msgLength; // in bytes - private long msgWords; // should be = msgLength * WORD_LENGTH - private int[] context; // the tmmh running context; length == TAG_WORDS - private int[] K0; // the first TAG_WORDS words of the keystream - private int[] Ki; // the sliding TAG_WORDS words of the keystream - private int Mi; // current message word being constructed - // Constructor(s) - // ------------------------------------------------------------------------- - /** Trivial 0-arguments constructor. */ public TMMH16() { super(Registry.TMMH16); } - // Class methods - // ------------------------------------------------------------------------- - - // Instance methods - // ------------------------------------------------------------------------- - - // gnu.crypto.mac.IMac interface implementation ---------------------------- - public int macSize() { return tagWords * 2; @@ -143,22 +115,17 @@ public class TMMH16 extends BaseMac implements Cloneable Integer tagLength = (Integer) attributes.get(TAG_LENGTH); // get tag length if (tagLength == null) { - if (tagWords == 0) - { // was never set - throw new IllegalArgumentException(TAG_LENGTH); - } // else re-use + if (tagWords == 0) // was never set + throw new IllegalArgumentException(TAG_LENGTH); + // else re-use } - else - { // check if positive and is divisible by WORD_LENGTH + else // check if positive and is divisible by WORD_LENGTH + { wantTagLength = tagLength.intValue(); if (wantTagLength < 2 || (wantTagLength % 2 != 0)) - { - throw new IllegalArgumentException(TAG_LENGTH); - } - else if (wantTagLength > (512 / 8)) - { // 512-bits is our maximum - throw new IllegalArgumentException(TAG_LENGTH); - } + throw new IllegalArgumentException(TAG_LENGTH); + else if (wantTagLength > (512 / 8)) // 512-bits is our maximum + throw new IllegalArgumentException(TAG_LENGTH); tagWords = wantTagLength / 2; // init local vars K0 = new int[tagWords]; @@ -167,36 +134,27 @@ public class TMMH16 extends BaseMac implements Cloneable } prefix = (byte[]) attributes.get(PREFIX); - if (prefix == null) - { // default to all-zeroes - prefix = new byte[tagWords * 2]; - } - else - { // ensure it's as long as it should + if (prefix == null) // default to all-zeroes + prefix = new byte[tagWords * 2]; + else // ensure it's as long as it should + { if (prefix.length != tagWords * 2) - { - throw new IllegalArgumentException(PREFIX); - } + throw new IllegalArgumentException(PREFIX); } IRandom prng = (IRandom) attributes.get(KEYSTREAM); // get keystream if (prng == null) { if (keystream == null) - { - throw new IllegalArgumentException(KEYSTREAM); - } // else reuse + throw new IllegalArgumentException(KEYSTREAM); + // else reuse } else - { - keystream = prng; - } + keystream = prng; reset(); // reset context variables - for (int i = 0; i < tagWords; i++) - { // init starting key words - Ki[i] = K0[i] = getNextKeyWord(keystream); - } + for (int i = 0; i < tagWords; i++) // init starting key words + Ki[i] = K0[i] = getNextKeyWord(keystream); } // The words of the key are denoted as K[1], K[2], ..., K[KEY_WORDS], and the @@ -206,12 +164,12 @@ public class TMMH16 extends BaseMac implements Cloneable // // If MESSAGE_LENGTH is greater than MAX_HASH_LENGTH, then the value of // TMMH/16 is undefined. Implementations MUST indicate an error if asked to - // hash a message with such a length. Otherwise, the hash value is defined + // hash a message with such a length. Otherwise, the hash value is defined // to be the length TAG_WORDS sequence of words in which the j-th word in the // sequence is defined as // // [ [ K[j] * MESSAGE_LENGTH +32 K[j+1] * M[1] +32 K[j+2] * M[2] - // +32 ... K[j+MSG_WORDS] * M[MSG_WORDS] ] modulo p ] modulo 2^16 + // +32 ... K[j+MSG_WORDS] * M[MSG_WORDS] ] modulo p ] modulo 2^16 // // where j ranges from 1 to TAG_WORDS. public void update(byte b) @@ -222,23 +180,21 @@ public class TMMH16 extends BaseMac implements Cloneable public void update(byte[] b, int offset, int len) { for (int i = 0; i < len; i++) - { - this.update(b[offset + i], keystream); - } + this.update(b[offset + i], keystream); } // For TMMH/16, KEY_LENGTH and TAG_LENGTH MUST be a multiple of two. The key, // message, and hash value are treated as a sequence of unsigned sixteen bit - // integers in network byte order. (In this section, we call such an integer - // a word.) If MESSAGE_LENGTH is odd, then a zero byte is appended to the + // integers in network byte order. (In this section, we call such an integer + // a word.) If MESSAGE_LENGTH is odd, then a zero byte is appended to the // message to align it on a word boundary, though this process does not // change the value of MESSAGE_LENGTH. // - // ... Otherwise, the hash value is defined to be the length TAG_WORDS + // ... Otherwise, the hash value is defined to be the length TAG_WORDS // sequence of words in which the j-th word in the sequence is defined as // // [ [ K[j] * MESSAGE_LENGTH +32 K[j+1] * M[1] +32 K[j+2] * M[2] - // +32 ... K[j+MSG_WORDS] * M[MSG_WORDS] ] modulo p ] modulo 2^16 + // +32 ... K[j+MSG_WORDS] * M[MSG_WORDS] ] modulo p ] modulo 2^16 // // where j ranges from 1 to TAG_WORDS. // @@ -255,9 +211,7 @@ public class TMMH16 extends BaseMac implements Cloneable msgLength = msgWords = keyWords = 0L; Mi = 0; for (int i = 0; i < tagWords; i++) - { - context[i] = 0; - } + context[i] = 0; } public boolean selfTest() @@ -265,42 +219,31 @@ public class TMMH16 extends BaseMac implements Cloneable if (valid == null) { // TODO: compute and test equality with one known vector - valid = Boolean.TRUE; } return valid.booleanValue(); } - // Cloneable interface implementation --------------------------------------- - public Object clone() throws CloneNotSupportedException { TMMH16 result = (TMMH16) super.clone(); - if (this.keystream != null) result.keystream = (IRandom) this.keystream.clone(); - if (this.prefix != null) result.prefix = (byte[]) this.prefix.clone(); - if (this.context != null) result.context = (int[]) this.context.clone(); - if (this.K0 != null) result.K0 = (int[]) this.K0.clone(); - if (this.Ki != null) result.Ki = (int[]) this.Ki.clone(); - return result; } - // own methods ------------------------------------------------------------- - /** - * <p>Similar to the same method with one argument, but uses the designated - * random number generator to compute needed keying material.</p> - * + * Similar to the same method with one argument, but uses the designated + * random number generator to compute needed keying material. + * * @param b the byte to process. * @param prng the source of randomness to use. */ @@ -309,14 +252,14 @@ public class TMMH16 extends BaseMac implements Cloneable Mi <<= 8; // update message buffer Mi |= b & 0xFF; msgLength++; // update message length (bytes) - if (msgLength % 2 == 0) - { // got a full word + if (msgLength % 2 == 0) // got a full word + { msgWords++; // update message words counter System.arraycopy(Ki, 1, Ki, 0, tagWords - 1); // 1. shift Ki up by 1 Ki[tagWords - 1] = getNextKeyWord(prng); // 2. fill last box of Ki long t; // temp var to allow working in modulo 2^32 - for (int i = 0; i < tagWords; i++) - { // 3. update context + for (int i = 0; i < tagWords; i++) // 3. update context + { t = context[i] & 0xFFFFFFFFL; t += Ki[i] * Mi; context[i] = (int) t; @@ -326,28 +269,26 @@ public class TMMH16 extends BaseMac implements Cloneable } /** - * <p>Similar to the same method with three arguments, but uses the - * designated random number generator to compute needed keying material.</p> - * + * Similar to the same method with three arguments, but uses the designated + * random number generator to compute needed keying material. + * * @param b the byte array to process. * @param offset the starting offset in <code>b</code> to start considering - * the bytes to process. + * the bytes to process. * @param len the number of bytes in <code>b</code> starting from - * <code>offset</code> to process. + * <code>offset</code> to process. * @param prng the source of randomness to use. */ public void update(byte[] b, int offset, int len, IRandom prng) { for (int i = 0; i < len; i++) - { - this.update(b[offset + i], prng); - } + this.update(b[offset + i], prng); } /** - * <p>Similar to the same method with no arguments, but uses the designated - * random number generator to compute needed keying material.</p> - * + * Similar to the same method with no arguments, but uses the designated + * random number generator to compute needed keying material. + * * @param prng the source of randomness to use. * @return the final result of the algorithm. */ @@ -357,12 +298,11 @@ public class TMMH16 extends BaseMac implements Cloneable byte[] result = new byte[tagWords * 2]; for (int i = 0, j = 0; i < tagWords; i++) { - result[j] = (byte) ((context[i] >>> 8) ^ prefix[j]); + result[j] = (byte)((context[i] >>> 8) ^ prefix[j]); j++; - result[j] = (byte) (context[i] ^ prefix[j]); + result[j] = (byte)(context[i] ^ prefix[j]); j++; } - reset(); return result; } @@ -378,7 +318,6 @@ public class TMMH16 extends BaseMac implements Cloneable { throw new RuntimeException(String.valueOf(x)); } - keyWords++; // update key words counter return result; } @@ -387,9 +326,7 @@ public class TMMH16 extends BaseMac implements Cloneable { long limit = msgLength; // formula works on real message length while (msgLength % 2 != 0) - { - update((byte) 0x00, prng); - } + update((byte) 0x00, prng); long t; for (int i = 0; i < tagWords; i++) { diff --git a/gnu/javax/crypto/mac/UHash32.java b/gnu/javax/crypto/mac/UHash32.java index 8abb0255e..737e9ce24 100644 --- a/gnu/javax/crypto/mac/UHash32.java +++ b/gnu/javax/crypto/mac/UHash32.java @@ -40,7 +40,6 @@ package gnu.javax.crypto.mac; import gnu.java.security.prng.IRandom; import gnu.java.security.prng.LimitReachedException; - import gnu.javax.crypto.cipher.IBlockCipher; import gnu.javax.crypto.prng.UMacGenerator; @@ -51,103 +50,63 @@ import java.util.HashMap; import java.util.Map; /** - * <p><i>UHASH</i> is a keyed hash function, which takes as input a string of + * <i>UHASH</i> is a keyed hash function, which takes as input a string of * arbitrary length, and produces as output a string of fixed length (such as 8 - * bytes). The actual output length depends on the parameter UMAC-OUTPUT-LEN.</p> - * - * <p><i>UHASH</i> has been shown to be <i>epsilon-ASU</i> ("Almost Strongly + * bytes). The actual output length depends on the parameter UMAC-OUTPUT-LEN. + * <p> + * <i>UHASH</i> has been shown to be <i>epsilon-ASU</i> ("Almost Strongly * Universal"), where epsilon is a small (parameter-dependent) real number. * Informally, saying that a keyed hash function is <i>epsilon-ASU</i> means * that for any two distinct fixed input strings, the two outputs of the hash * function with a random key "look almost like a pair of random strings". The - * number epsilon measures how non-random the output strings may be.</p> - * - * <i>UHASH</i> has been designed to be fast by exploiting several architectural - * features of modern commodity processors. It was specifically designed for use - * in <i>UMAC</i>. But <i>UHASH</i> is useful beyond that domain, and can be - * easily adopted for other purposes.</p> - * + * number epsilon measures how non-random the output strings may be. + * <p> + * <i>UHASH</i> has been designed to be fast by exploiting several + * architectural features of modern commodity processors. It was specifically + * designed for use in <i>UMAC</i>. But <i>UHASH</i> is useful beyond that + * domain, and can be easily adopted for other purposes. + * <p> * <i>UHASH</i> does its work in three layers. First, a hash function called * <code>NH</code> is used to compress input messages into strings which are * typically many times smaller than the input message. Second, the compressed * message is hashed with an optimized <i>polynomial hash function</i> into a * fixed-length 16-byte string. Finally, the 16-byte string is hashed using an - * <i>inner-product hash</i> into a string of length WORD-LEN bytes. These three - * layers are repeated (with a modified key) until the outputs total - * UMAC-OUTPUT-LEN bytes.</p> - * - * <p>References:</p> - * + * <i>inner-product hash</i> into a string of length WORD-LEN bytes. These + * three layers are repeated (with a modified key) until the outputs total + * UMAC-OUTPUT-LEN bytes. + * <p> + * References: * <ol> - * <li><a href="http://www.ietf.org/internet-drafts/draft-krovetz-umac-01.txt"> - * UMAC</a>: Message Authentication Code using Universal Hashing.<br> - * T. Krovetz, J. Black, S. Halevi, A. Hevia, H. Krawczyk, and P. Rogaway.</li> + * <li><a href="http://www.ietf.org/internet-drafts/draft-krovetz-umac-01.txt"> + * UMAC</a>: Message Authentication Code using Universal Hashing.<br> + * T. Krovetz, J. Black, S. Halevi, A. Hevia, H. Krawczyk, and P. Rogaway.</li> * </ol> */ -public class UHash32 extends BaseMac +public class UHash32 + extends BaseMac { - - // Constants and variables - // ------------------------------------------------------------------------- - // UMAC prime values private static final BigInteger PRIME_19 = BigInteger.valueOf(0x7FFFFL); - private static final BigInteger PRIME_32 = BigInteger.valueOf(0xFFFFFFFBL); - private static final BigInteger PRIME_36 = BigInteger.valueOf(0xFFFFFFFFBL); - - private static final BigInteger PRIME_64 = new BigInteger( - 1, - new byte[] { - (byte) 0xFF, - (byte) 0xFF, - (byte) 0xFF, - (byte) 0xFF, - (byte) 0xFF, - (byte) 0xFF, - (byte) 0xFF, - (byte) 0xC5 }); - - private static final BigInteger PRIME_128 = new BigInteger( - 1, - new byte[] { - (byte) 0xFF, - (byte) 0xFF, - (byte) 0xFF, - (byte) 0xFF, - (byte) 0xFF, - (byte) 0xFF, - (byte) 0xFF, - (byte) 0xFF, - (byte) 0xFF, - (byte) 0xFF, - (byte) 0xFF, - (byte) 0xFF, - (byte) 0xFF, - (byte) 0xFF, - (byte) 0xFF, - (byte) 0x61 }); - + private static final BigInteger PRIME_64 = new BigInteger(1, new byte[] { + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xC5 }); + private static final BigInteger PRIME_128 = new BigInteger(1, new byte[] { + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x61 }); static final BigInteger TWO = BigInteger.valueOf(2L); - static final long BOUNDARY = TWO.shiftLeft(17).longValue(); - // 2**64 - 2**32 static final BigInteger LOWER_RANGE = TWO.pow(64).subtract(TWO.pow(32)); - // 2**128 - 2**96 static final BigInteger UPPER_RANGE = TWO.pow(128).subtract(TWO.pow(96)); - static final byte[] ALL_ZEROES = new byte[32]; - int streams; - L1Hash32[] l1hash; - // Constructor(s) - // ------------------------------------------------------------------------- - /** Trivial 0-arguments constructor. */ public UHash32() { @@ -155,7 +114,7 @@ public class UHash32 extends BaseMac } /** - * <p>Private constructor for cloning purposes.</p> + * Private constructor for cloning purposes. * * @param that the instance to clone. */ @@ -166,24 +125,15 @@ public class UHash32 extends BaseMac this.streams = that.streams; if (that.l1hash != null) { - // this.l1hash = new L1Hash32[that.l1hash.length]; this.l1hash = new L1Hash32[that.streams]; - // for (int i = 0; i < that.l1hash.length; i++) { for (int i = 0; i < that.streams; i++) - { - if (that.l1hash[i] != null) - { - this.l1hash[i] = (L1Hash32) that.l1hash[i].clone(); - } - } + if (that.l1hash[i] != null) + this.l1hash[i] = (L1Hash32) that.l1hash[i].clone(); } } - // Class methods - // ------------------------------------------------------------------------- - /** - * <p>The prime numbers used in UMAC are:</p> + * The prime numbers used in UMAC are: * <pre> * +-----+--------------------+---------------------------------------+ * | x | prime(x) [Decimal] | prime(x) [Hexadecimal] | @@ -219,18 +169,11 @@ public class UHash32 extends BaseMac } } - // Instance methods - // ------------------------------------------------------------------------- - - // java.lang.Cloneable interface implementation ---------------------------- - public Object clone() { return new UHash32(this); } - // gnu.crypto.mac.IMac interface implementation ---------------------------- - public int macSize() { return UMac32.OUTPUT_LEN; @@ -241,18 +184,12 @@ public class UHash32 extends BaseMac { byte[] K = (byte[]) attributes.get(MAC_KEY_MATERIAL); if (K == null) - { - throw new InvalidKeyException("Null Key"); - } + throw new InvalidKeyException("Null Key"); if (K.length != UMac32.KEY_LEN) - { - throw new InvalidKeyException("Invalid Key length: " - + String.valueOf(K.length)); - } - + throw new InvalidKeyException("Invalid Key length: " + + String.valueOf(K.length)); // Calculate iterations needed to make UMAC-OUTPUT-LEN bytes streams = (UMac32.OUTPUT_LEN + 3) / 4; - // Define total key needed for all iterations using UMacGenerator. // L1Key and L3Key1 both reuse most key between iterations. IRandom kdf1 = new UMacGenerator(); @@ -261,15 +198,14 @@ public class UHash32 extends BaseMac IRandom kdf4 = new UMacGenerator(); Map map = new HashMap(); map.put(IBlockCipher.KEY_MATERIAL, K); - map.put(UMacGenerator.INDEX, new Integer(0)); + map.put(UMacGenerator.INDEX, Integer.valueOf(0)); kdf1.init(map); - map.put(UMacGenerator.INDEX, new Integer(1)); + map.put(UMacGenerator.INDEX, Integer.valueOf(1)); kdf2.init(map); - map.put(UMacGenerator.INDEX, new Integer(2)); + map.put(UMacGenerator.INDEX, Integer.valueOf(2)); kdf3.init(map); - map.put(UMacGenerator.INDEX, new Integer(3)); + map.put(UMacGenerator.INDEX, Integer.valueOf(3)); kdf4.init(map); - // need to generate all bytes for use later in a Toepliz construction byte[] L1Key = new byte[UMac32.L1_KEY_LEN + (streams - 1) * 16]; try @@ -297,7 +233,6 @@ public class UHash32 extends BaseMac x.printStackTrace(System.err); throw new RuntimeException("KDF for L2Key reached limit"); } - byte[] k31 = new byte[64]; try { @@ -308,7 +243,6 @@ public class UHash32 extends BaseMac x.printStackTrace(System.err); throw new RuntimeException("KDF for L3Key1 reached limit"); } - byte[] k32 = new byte[4]; try { @@ -319,7 +253,6 @@ public class UHash32 extends BaseMac x.printStackTrace(System.err); throw new RuntimeException("KDF for L3Key2 reached limit"); } - L1Hash32 mac = new L1Hash32(); mac.init(k1, k2, k31, k32); l1hash[i] = mac; @@ -329,17 +262,13 @@ public class UHash32 extends BaseMac public void update(byte b) { for (int i = 0; i < streams; i++) - { - l1hash[i].update(b); - } + l1hash[i].update(b); } public void update(byte[] b, int offset, int len) { for (int i = 0; i < len; i++) - { - this.update(b[offset + i]); - } + this.update(b[offset + i]); } public byte[] digest() @@ -357,9 +286,7 @@ public class UHash32 extends BaseMac public void reset() { for (int i = 0; i < streams; i++) - { - l1hash[i].reset(); - } + l1hash[i].reset(); } public boolean selfTest() @@ -367,38 +294,20 @@ public class UHash32 extends BaseMac return true; } - // helper methods ---------------------------------------------------------- - - // Inner classes - // ========================================================================= - /** * First hash stage of the UHash32 algorithm. */ - class L1Hash32 implements Cloneable + class L1Hash32 + implements Cloneable { - - // Constants and variables - // ---------------------------------------------------------------------- - private int[] key; // key material as an array of 32-bit ints - private byte[] buffer; // work buffer L1_KEY_LEN long - private int count; // meaningful bytes in buffer - private ByteArrayOutputStream Y; - - // private byte[] y; private long totalCount; - private L2Hash32 l2hash; - private L3Hash32 l3hash; - // Constructor(s) - // ---------------------------------------------------------------------- - /** Trivial 0-arguments constructor. */ L1Hash32() { @@ -412,7 +321,7 @@ public class UHash32 extends BaseMac } /** - * <p>Private constructor for cloning purposes.</p> + * Private constructor for cloning purposes. * * @param that the instance to clone. */ @@ -427,38 +336,23 @@ public class UHash32 extends BaseMac this.Y.write(otherY, 0, otherY.length); this.totalCount = that.totalCount; if (that.l2hash != null) - { - this.l2hash = (L2Hash32) that.l2hash.clone(); - } + this.l2hash = (L2Hash32) that.l2hash.clone(); if (that.l3hash != null) - { - this.l3hash = (L3Hash32) that.l3hash.clone(); - } + this.l3hash = (L3Hash32) that.l3hash.clone(); } - // Class methods - // ---------------------------------------------------------------------- - - // Instance methods - // ---------------------------------------------------------------------- - - // java.lang.Cloneable interface implementation ------------------------- - public Object clone() { return new L1Hash32(this); } - // other instance methods ----------------------------------------------- - public void init(byte[] k1, byte[] k2, byte[] k31, byte[] k32) { for (int i = 0, j = 0; i < (UMac32.L1_KEY_LEN / 4); i++) - { - key[i] = k1[j++] << 24 | (k1[j++] & 0xFF) << 16 - | (k1[j++] & 0xFF) << 8 | (k1[j++] & 0xFF); - } - + key[i] = k1[j++] << 24 + | (k1[j++] & 0xFF) << 16 + | (k1[j++] & 0xFF) << 8 + | (k1[j++] & 0xFF); l2hash = new L2Hash32(k2); l3hash = new L3Hash32(k31, k32); } @@ -484,8 +378,8 @@ public class UHash32 extends BaseMac // For each iteration, extract key and three-layer hash. // If length(M) <= L1_KEY_LEN, then skip L2-HASH. - if (Y.size() == 16) - { // we already hashed twice L1_KEY_LEN + if (Y.size() == 16) // we already hashed twice L1_KEY_LEN + { byte[] A = Y.toByteArray(); Y.reset(); l2hash.update(A, 0, 16); @@ -508,19 +402,16 @@ public class UHash32 extends BaseMac byte[] y = nh32(count); Y.write(y, 0, 8); } - byte[] A = Y.toByteArray(); Y.reset(); byte[] B; if (totalCount <= UMac32.L1_KEY_LEN) { // we might have 'update'd the bytes already. check - if (A.length == 0) - { // we did - B = l2hash.digest(); - } - else - { // did not + if (A.length == 0) // we did + B = l2hash.digest(); + else // did not + { B = new byte[16]; System.arraycopy(A, 0, B, 8, 8); } @@ -528,12 +419,9 @@ public class UHash32 extends BaseMac else { if (A.length != 0) - { - l2hash.update(A, 0, A.length); - } + l2hash.update(A, 0, A.length); B = l2hash.digest(); } - byte[] result = l3hash.digest(B); reset(); return result; @@ -545,13 +433,9 @@ public class UHash32 extends BaseMac Y.reset(); totalCount = 0L; if (l2hash != null) - { - l2hash.reset(); - } + l2hash.reset(); } - // helper methods ------------------------------------------------------- - /** * 5.1 NH-32: NH hashing with a 32-bit word size. * @@ -562,116 +446,87 @@ public class UHash32 extends BaseMac { // Break M and K into 4-byte chunks int t = len / 4; - // Let M_1, M_2, ..., M_t be 4-byte strings // so that M = M_1 || M_2 || .. || M_t. // Let K_1, K_2, ..., K_t be 4-byte strings // so that K_1 || K_2 || .. || K_t is a prefix of K. int[] m = new int[t]; - int i; int j = 0; for (i = 0, j = 0; i < t; i++) - { - m[i] = buffer[j++] << 24 | (buffer[j++] & 0xFF) << 16 - | (buffer[j++] & 0xFF) << 8 | (buffer[j++] & 0xFF); - } - + m[i] = buffer[j++] << 24 + | (buffer[j++] & 0xFF) << 16 + | (buffer[j++] & 0xFF) << 8 + | (buffer[j++] & 0xFF); // Perform NH hash on the chunks, pairing words for multiplication // which are 4 apart to accommodate vector-parallelism. long result = len * 8L; for (i = 0; i < t; i += 8) { result += ((m[i + 0] + key[i + 0]) & 0xFFFFFFFFL) - * ((m[i + 4] + key[i + 4]) & 0xFFFFFFFFL); + * ((m[i + 4] + key[i + 4]) & 0xFFFFFFFFL); result += ((m[i + 1] + key[i + 1]) & 0xFFFFFFFFL) - * ((m[i + 5] + key[i + 5]) & 0xFFFFFFFFL); + * ((m[i + 5] + key[i + 5]) & 0xFFFFFFFFL); result += ((m[i + 2] + key[i + 2]) & 0xFFFFFFFFL) - * ((m[i + 6] + key[i + 6]) & 0xFFFFFFFFL); + * ((m[i + 6] + key[i + 6]) & 0xFFFFFFFFL); result += ((m[i + 3] + key[i + 3]) & 0xFFFFFFFFL) - * ((m[i + 7] + key[i + 7]) & 0xFFFFFFFFL); + * ((m[i + 7] + key[i + 7]) & 0xFFFFFFFFL); } - - return new byte[] { (byte) (result >>> 56), (byte) (result >>> 48), - (byte) (result >>> 40), (byte) (result >>> 32), - (byte) (result >>> 24), (byte) (result >>> 16), - (byte) (result >>> 8), (byte) result }; + return new byte[] { + (byte)(result >>> 56), (byte)(result >>> 48), + (byte)(result >>> 40), (byte)(result >>> 32), + (byte)(result >>> 24), (byte)(result >>> 16), + (byte)(result >>> 8), (byte) result }; } } - // ========================================================================= - /** - * <p>Second hash stage of the UHash32 algorithm.</p> - * - * 5.4 L2-HASH-32: Second-layer hash.<p> + * Second hash stage of the UHash32 algorithm. + * <p> + * 5.4 L2-HASH-32: Second-layer hash. * <ul> - * <li>Input:<br> - * K string of length 24 bytes.<br> - * M string of length less than 2^64 bytes.</li> - * <li>Returns:<br> - * Y, string of length 16 bytes.</li> + * <li>Input:<br> + * K string of length 24 bytes.<br> + * M string of length less than 2^64 bytes.</li> + * <li>Returns:<br> + * Y, string of length 16 bytes.</li> * </ul> */ - class L2Hash32 implements Cloneable + class L2Hash32 + implements Cloneable { - - // Constants and variables - // ---------------------------------------------------------------------- - private BigInteger k64, k128; - private BigInteger y; - private boolean highBound; - private long bytesSoFar; - private ByteArrayOutputStream buffer; - // Constructor(s) - // ---------------------------------------------------------------------- - L2Hash32(byte[] K) { super(); if (K.length != 24) - { - throw new ExceptionInInitializerError("K length is not 24"); - } - + throw new ExceptionInInitializerError("K length is not 24"); // Extract keys and restrict to special key-sets // Mask64 = uint2str(0x01FFFFFF01FFFFFF, 8); // Mask128 = uint2str(0x01FFFFFF01FFFFFF01FFFFFF01FFFFFF, 16); // k64 = str2uint(K[1..8] and Mask64); // k128 = str2uint(K[9..24] and Mask128); int i = 0; - k64 = new BigInteger(1, new byte[] { (byte) (K[i++] & 0x01), - (byte) (K[i++] & 0xFF), - (byte) (K[i++] & 0xFF), - (byte) (K[i++] & 0xFF), - (byte) (K[i++] & 0x01), - (byte) (K[i++] & 0xFF), - (byte) (K[i++] & 0xFF), - (byte) (K[i++] & 0xFF) }); - k128 = new BigInteger(1, new byte[] { (byte) (K[i++] & 0x01), - (byte) (K[i++] & 0xFF), - (byte) (K[i++] & 0xFF), - (byte) (K[i++] & 0xFF), - (byte) (K[i++] & 0x01), - (byte) (K[i++] & 0xFF), - (byte) (K[i++] & 0xFF), - (byte) (K[i++] & 0xFF), - (byte) (K[i++] & 0x01), - (byte) (K[i++] & 0xFF), - (byte) (K[i++] & 0xFF), - (byte) (K[i++] & 0xFF), - (byte) (K[i++] & 0x01), - (byte) (K[i++] & 0xFF), - (byte) (K[i++] & 0xFF), - (byte) (K[i++] & 0xFF) }); - + k64 = new BigInteger(1, new byte[] { + (byte)(K[i++] & 0x01), (byte)(K[i++] & 0xFF), + (byte)(K[i++] & 0xFF), (byte)(K[i++] & 0xFF), + (byte)(K[i++] & 0x01), (byte)(K[i++] & 0xFF), + (byte)(K[i++] & 0xFF), (byte)(K[i++] & 0xFF) }); + k128 = new BigInteger(1, new byte[] { + (byte)(K[i++] & 0x01), (byte)(K[i++] & 0xFF), + (byte)(K[i++] & 0xFF), (byte)(K[i++] & 0xFF), + (byte)(K[i++] & 0x01), (byte)(K[i++] & 0xFF), + (byte)(K[i++] & 0xFF), (byte)(K[i++] & 0xFF), + (byte)(K[i++] & 0x01), (byte)(K[i++] & 0xFF), + (byte)(K[i++] & 0xFF), (byte)(K[i++] & 0xFF), + (byte)(K[i++] & 0x01), (byte)(K[i++] & 0xFF), + (byte)(K[i++] & 0xFF), (byte)(K[i++] & 0xFF) }); y = BigInteger.ONE; highBound = false; bytesSoFar = 0L; @@ -694,36 +549,24 @@ public class UHash32 extends BaseMac } } - // Class methods - // ---------------------------------------------------------------------- - - // Instance methods - // ---------------------------------------------------------------------- - - // java.lang.Cloneable interface implementation ------------------------- - public Object clone() { return new L2Hash32(this); } - // other instance methods ----------------------------------------------- - // this is called with either 8-bytes or 16-bytes void update(byte[] b, int offset, int len) { if (len == 0) - { - return; - } + return; - if (!highBound) - { // do the first (only?) 8-bytes + if (! highBound) // do the first (only?) 8-bytes + { poly(64, LOWER_RANGE, k64, b, offset, 8); bytesSoFar += 8L; highBound = (bytesSoFar > BOUNDARY); - if (highBound) - { // if we just crossed the limit then process y + if (highBound) // if we just crossed the limit then process y + { poly(128, UPPER_RANGE, k128, yTo16bytes(), 0, 16); buffer = new ByteArrayOutputStream(); } @@ -739,9 +582,7 @@ public class UHash32 extends BaseMac byte[] bb = buffer.toByteArray(); poly(128, UPPER_RANGE, k128, bb, 0, 16); if (bb.length > 16) - { - buffer.write(bb, 16, bb.length - 16); - } + buffer.write(bb, 16, bb.length - 16); } } } @@ -751,19 +592,18 @@ public class UHash32 extends BaseMac // If M no more than 2^17 bytes, hash under 64-bit prime, // otherwise, hash first 2^17 bytes under 64-bit prime and // remainder under 128-bit prime. - if (!highBound) - { // y is up-to-date + if (! highBound) // y is up-to-date + { // do nothing } - else - { // we may have some bytes in buffer + else // we may have some bytes in buffer + { byte[] bb = buffer.toByteArray(); byte[] lastBlock = new byte[16]; System.arraycopy(bb, 0, lastBlock, 0, bb.length); lastBlock[bb.length] = (byte) 0x80; poly(128, UPPER_RANGE, k128, lastBlock, 0, 16); } - byte[] result = yTo16bytes(); reset(); return result; @@ -775,38 +615,29 @@ public class UHash32 extends BaseMac highBound = false; bytesSoFar = 0L; if (buffer != null) - { - buffer.reset(); - } + buffer.reset(); } - // helper methods ------------------------------------------------------- - private byte[] yTo16bytes() { byte[] yy = y.toByteArray(); byte[] result = new byte[16]; if (yy.length > 16) - { - System.arraycopy(yy, yy.length - 16, result, 0, 16); - } + System.arraycopy(yy, yy.length - 16, result, 0, 16); else - { - System.arraycopy(yy, 0, result, 16 - yy.length, yy.length); - } + System.arraycopy(yy, 0, result, 16 - yy.length, yy.length); return result; } /** - * 5.3 POLY: Polynomial hash - * Function Name: POLY - * + * 5.3 POLY: Polynomial hash Function Name: POLY + * * @param wordbits positive integer divisible by 8: called with 64 or 128. * @param maxwordrange positive integer less than 2**wordbits. * @param k integer in the range 0 .. prime(wordbits) - 1. - * @param M string with length divisible by (wordbits / 8) bytes. - * return y, integer in the range 0 .. prime(wordbits) - 1. + * @param M string with length divisible by (wordbits / 8) bytes. return y, + * integer in the range 0 .. prime(wordbits) - 1. */ private void poly(int wordbits, BigInteger maxwordrange, BigInteger k, byte[] M, int off, int len) @@ -814,12 +645,9 @@ public class UHash32 extends BaseMac byte[] mag = new byte[len]; System.arraycopy(M, off, mag, 0, len); // Define constants used for fixing out-of-range words - // int wordbytes = wordbits / 8; - BigInteger p = prime(wordbits); BigInteger offset = TWO.pow(wordbits).subtract(p); // 2^wordbits - p; BigInteger marker = p.subtract(BigInteger.ONE); - // Break M into chunks of length wordbytes bytes // long n = M.length / wordbytes; // Let M_1, M_2, ..., M_n be strings of length wordbytes bytes @@ -829,48 +657,34 @@ public class UHash32 extends BaseMac // then hash the words 'marker' and (m - offset), both in range. // for (int i = 0; i < n; i++) { BigInteger m = new BigInteger(1, mag); - if (m.compareTo(maxwordrange) >= 0) - { // m >= maxwordrange + if (m.compareTo(maxwordrange) >= 0) // m >= maxwordrange + { y = y.multiply(k).add(marker).mod(p); // (k * y + marker) % p; y = y.multiply(k).add(m.subtract(offset)).mod(p); // (k * y + (m - offset)) % p; } else - { - y = y.multiply(k).add(m).mod(p); // (k * y + m) % p; - } - // } - - // return y; + y = y.multiply(k).add(m).mod(p); // (k * y + m) % p; } } - // ========================================================================= - /** * Third hash stage of the UHash32 algorithm. - * - * Input: - * K1 string of length 64 bytes. - * K2 string of length 4 bytes. - * M string of length 16 bytes. - * Returns: - * Y, string of length 4 bytes. + * <ul> + * <li>Input:<br/> + * K1 string of length 64 bytes.<br/> + * K2 string of length 4 bytes.<br/> + * M string of length 16 bytes.</li> + * <li>Returns:<br/> + * Y, string of length 4 bytes.</li> + * </ul> */ - class L3Hash32 implements Cloneable + class L3Hash32 + implements Cloneable { - - // Constants and variables - // ---------------------------------------------------------------------- - private static final long PRIME_36 = 0x0000000FFFFFFFFBL; - private int[] k = new int[9]; - // Constructor(s) - // ---------------------------------------------------------------------- - /** - * * @param K1 string of length 64 bytes. * @param K2 string of length 4 bytes. */ @@ -880,29 +694,26 @@ public class UHash32 extends BaseMac // pre-conditions if (K1.length != 64) - { - throw new ExceptionInInitializerError("K1 length is not 64"); - } + throw new ExceptionInInitializerError("K1 length is not 64"); if (K2.length != 4) - { - throw new ExceptionInInitializerError("K2 length is not 4"); - } - + throw new ExceptionInInitializerError("K2 length is not 4"); // Break K1 into 8 chunks and convert to integers - // int i = 0; - // for (int j = 0; i < 8; ) { for (int i = 0, j = 0; i < 8; i++) { - long kk = (K1[j++] & 0xFFL) << 56 | (K1[j++] & 0xFFL) << 48 - | (K1[j++] & 0xFFL) << 40 | (K1[j++] & 0xFFL) << 32 - | (K1[j++] & 0xFFL) << 24 | (K1[j++] & 0xFFL) << 16 - | (K1[j++] & 0xFFL) << 8 | (K1[j++] & 0xFFL); - // k[i++] = (int)(kk % PRIME_36); - k[i] = (int) (kk % PRIME_36); + long kk = (K1[j++] & 0xFFL) << 56 + | (K1[j++] & 0xFFL) << 48 + | (K1[j++] & 0xFFL) << 40 + | (K1[j++] & 0xFFL) << 32 + | (K1[j++] & 0xFFL) << 24 + | (K1[j++] & 0xFFL) << 16 + | (K1[j++] & 0xFFL) << 8 + | (K1[j++] & 0xFFL); + k[i] = (int)(kk % PRIME_36); } - // k[i] = K2[0] << 24 | (K2[1] & 0xFF) << 16 | (K2[2] & 0xFF) << 8 | (K2[3] & 0xFF); - k[8] = K2[0] << 24 | (K2[1] & 0xFF) << 16 | (K2[2] & 0xFF) << 8 - | (K2[3] & 0xFF); + k[8] = K2[0] << 24 + | (K2[1] & 0xFF) << 16 + | (K2[2] & 0xFF) << 8 + | (K2[3] & 0xFF); } private L3Hash32(int[] k) @@ -912,21 +723,11 @@ public class UHash32 extends BaseMac this.k = k; } - // Class methods - // ---------------------------------------------------------------------- - - // Instance methods - // ---------------------------------------------------------------------- - - // java.lang.Cloneable interface implementation ------------------------- - public Object clone() { return new L3Hash32((int[]) k.clone()); } - // other instance methods ----------------------------------------------- - /** * @param M string of length 16 bytes. * @return Y, string of length 4 bytes. @@ -934,24 +735,24 @@ public class UHash32 extends BaseMac byte[] digest(byte[] M) { if (M.length != 16) - { - throw new IllegalArgumentException("M length is not 16"); - } + throw new IllegalArgumentException("M length is not 16"); long m, y = 0L; for (int i = 0, j = 0; i < 8; i++) { // Break M into 8 chunks and convert to integers m = (M[j++] & 0xFFL) << 8 | (M[j++] & 0xFFL); - // Inner-product hash, extract last 32 bits and affine-translate // y = (m_1 * k_1 + ... + m_8 * k_8) mod prime(36); // y = y mod 2^32; y += (m * (k[i] & 0xFFFFFFFFL)) % PRIME_36; } int Y = ((int) y) ^ k[8]; - return new byte[] { (byte) (Y >>> 24), (byte) (Y >>> 16), - (byte) (Y >>> 8), (byte) Y }; + return new byte[] { + (byte)(Y >>> 24), + (byte)(Y >>> 16), + (byte)(Y >>> 8), + (byte) Y }; } } -}
\ No newline at end of file +} diff --git a/gnu/javax/crypto/mac/UMac32.java b/gnu/javax/crypto/mac/UMac32.java index 013888856..8e913db71 100644 --- a/gnu/javax/crypto/mac/UMac32.java +++ b/gnu/javax/crypto/mac/UMac32.java @@ -53,123 +53,105 @@ import java.util.HashMap; import java.util.Map; /** - * <p>The implementation of the <i>UMAC</i> (Universal Message Authentication - * Code).</p> - * - * <p>The <i>UMAC</i> algorithms described are <i>parameterized</i>. This means + * The implementation of the <i>UMAC</i> (Universal Message Authentication + * Code). + * <p> + * The <i>UMAC</i> algorithms described are <i>parameterized</i>. This means * that various low-level choices, like the endian convention and the underlying * cryptographic primitive, have not been fixed. One must choose values for * these parameters before the authentication tag generated by <i>UMAC</i> (for - * a given message, key, and nonce) becomes fully-defined. In this document - * we provide two collections of parameter settings, and have named the sets - * <i>UMAC16</i> and <i>UMAC32</i>. The parameter sets have been chosen based on - * experimentation and provide good performance on a wide variety of processors. - * <i>UMAC16</i> is designed to excel on processors which provide small-scale - * SIMD parallelism of the type found in Intel's MMX and Motorola's AltiVec - * instruction sets, while <i>UMAC32</i> is designed to do well on processors - * with good 32- and 64- bit support. <i>UMAC32</i> may take advantage of SIMD - * parallelism in future processors.</p> - * - * <p><i>UMAC</i> has been designed to allow implementations which accommodate - * <i>on-line</i> authentication. This means that pieces of the message may - * be presented to <i>UMAC</i> at different times (but in correct order) and an + * a given message, key, and nonce) becomes fully-defined. In this document we + * provide two collections of parameter settings, and have named the sets + * <i>UMAC16</i> and <i>UMAC32</i>. The parameter sets have been chosen based + * on experimentation and provide good performance on a wide variety of + * processors. <i>UMAC16</i> is designed to excel on processors which provide + * small-scale SIMD parallelism of the type found in Intel's MMX and Motorola's + * AltiVec instruction sets, while <i>UMAC32</i> is designed to do well on + * processors with good 32- and 64- bit support. <i>UMAC32</i> may take + * advantage of SIMD parallelism in future processors. + * <p> + * <i>UMAC</i> has been designed to allow implementations which accommodate + * <i>on-line</i> authentication. This means that pieces of the message may be + * presented to <i>UMAC</i> at different times (but in correct order) and an * on-line implementation will be able to process the message correctly without * the need to buffer more than a few dozen bytes of the message. For * simplicity, the algorithms in this specification are presented as if the - * entire message being authenticated were available at once.</p> - * - * <p>To authenticate a message, <code>Msg</code>, one first applies the + * entire message being authenticated were available at once. + * <p> + * To authenticate a message, <code>Msg</code>, one first applies the * universal hash function, resulting in a string which is typically much - * shorter than the original message. The pseudorandom function is applied to a + * shorter than the original message. The pseudorandom function is applied to a * nonce, and the result is used in the manner of a Vernam cipher: the * authentication tag is the xor of the output from the hash function and the * output from the pseudorandom function. Thus, an authentication tag is - * generated as</p> - * + * generated as * <pre> - * AuthTag = f(Nonce) xor h(Msg) + * AuthTag = f(Nonce) xor h(Msg) * </pre> - * - * <p>Here <code>f</code> is the pseudorandom function shared between the sender + * <p> + * Here <code>f</code> is the pseudorandom function shared between the sender * and the receiver, and h is a universal hash function shared by the sender and * the receiver. In <i>UMAC</i>, a shared key is used to key the pseudorandom * function <code>f</code>, and then <code>f</code> is used for both tag * generation and internally to generate all of the bits needed by the universal - * hash function.</p> - * - * <p>The universal hash function that we use is called <code>UHASH</code>. It + * hash function. + * <p> + * The universal hash function that we use is called <code>UHASH</code>. It * combines several software-optimized algorithms into a multi-layered * structure. The algorithm is moderately complex. Some of this complexity comes - * from extensive speed optimizations.</p> - * - * <p>For the pseudorandom function we use the block cipher of the <i>Advanced - * Encryption Standard</i> (AES).</p> - * - * <p>The UMAC32 parameters, considered in this implementation are:</p> + * from extensive speed optimizations. + * <p> + * For the pseudorandom function we use the block cipher of the <i>Advanced + * Encryption Standard</i> (AES). + * <p> + * The UMAC32 parameters, considered in this implementation are: * <pre> - * UMAC32 - * ------ - * WORD-LEN 4 - * UMAC-OUTPUT-LEN 8 - * L1-KEY-LEN 1024 - * UMAC-KEY-LEN 16 - * ENDIAN-FAVORITE BIG * - * L1-OPERATIONS-SIGN UNSIGNED + * UMAC32 + * ------ + * WORD-LEN 4 + * UMAC-OUTPUT-LEN 8 + * L1-KEY-LEN 1024 + * UMAC-KEY-LEN 16 + * ENDIAN-FAVORITE BIG * + * L1-OPERATIONS-SIGN UNSIGNED * </pre> - * - * <p>Please note that this UMAC32 differs from the one described in the paper - * by the <i>ENDIAN-FAVORITE</i> value.</p> - * - * <p>References:</p> - * + * <p> + * Please note that this UMAC32 differs from the one described in the paper by + * the <i>ENDIAN-FAVORITE</i> value. + * <p> + * References: * <ol> - * <li><a href="http://www.ietf.org/internet-drafts/draft-krovetz-umac-01.txt"> - * UMAC</a>: Message Authentication Code using Universal Hashing.<br> - * T. Krovetz, J. Black, S. Halevi, A. Hevia, H. Krawczyk, and P. Rogaway.</li> + * <li><a href="http://www.ietf.org/internet-drafts/draft-krovetz-umac-01.txt"> + * UMAC</a>: Message Authentication Code using Universal Hashing.<br> + * T. Krovetz, J. Black, S. Halevi, A. Hevia, H. Krawczyk, and P. Rogaway.</li> * </ol> */ -public class UMac32 extends BaseMac +public class UMac32 + extends BaseMac { - - // Constants and variables - // ------------------------------------------------------------------------- - /** * Property name of the user-supplied <i>Nonce</i>. The value associated to * this property name is taken to be a byte array. */ public static final String NONCE_MATERIAL = "gnu.crypto.umac.nonce.material"; - /** Known test vector. */ - // private static final String TV1 = "3E5A0E09198B0F94"; - // private static final String TV1 = "5FD764A6D3A9FD9D"; - // private static final String TV1 = "48658DE1D9A70304"; + // private static final String TV1 = "3E5A0E09198B0F94"; + // private static final String TV1 = "5FD764A6D3A9FD9D"; + // private static final String TV1 = "48658DE1D9A70304"; private static final String TV1 = "455ED214A6909F20"; - private static final BigInteger MAX_NONCE_ITERATIONS = BigInteger.ONE.shiftLeft(16 * 8); - // UMAC32 parameters static final int OUTPUT_LEN = 8; - static final int L1_KEY_LEN = 1024; - static final int KEY_LEN = 16; - /** caches the result of the correctness test, once executed. */ private static Boolean valid; - private byte[] nonce; - private UHash32 uhash32; - private BigInteger nonceReuseCount; - /** The authentication key for this instance. */ private transient byte[] K; - // Constructor(s) - // ------------------------------------------------------------------------- - /** Trivial 0-arguments constructor. */ public UMac32() { @@ -177,8 +159,8 @@ public class UMac32 extends BaseMac } /** - * <p>Private constructor for cloning purposes.</p> - * + * Private constructor for cloning purposes. + * * @param that the instance to clone. */ private UMac32(UMac32 that) @@ -186,136 +168,103 @@ public class UMac32 extends BaseMac this(); if (that.K != null) - { - this.K = (byte[]) that.K.clone(); - } + this.K = (byte[]) that.K.clone(); if (that.nonce != null) - { - this.nonce = (byte[]) that.nonce.clone(); - } + this.nonce = (byte[]) that.nonce.clone(); if (that.uhash32 != null) - { - this.uhash32 = (UHash32) that.uhash32.clone(); - } + this.uhash32 = (UHash32) that.uhash32.clone(); this.nonceReuseCount = that.nonceReuseCount; } - // Class methods - // ------------------------------------------------------------------------- - - // Instance methods - // ------------------------------------------------------------------------- - - // java.lang.Cloneable interface implementation ---------------------------- - public Object clone() { return new UMac32(this); } - // gnu.crypto.mac.IMac interface implementation ---------------------------- - public int macSize() { return OUTPUT_LEN; } /** - * <p>Initialising a <i>UMAC</i> instance consists of defining values for - * the following parameters:</p> - * + * Initialising a <i>UMAC</i> instance consists of defining values for the + * following parameters: * <ol> - * <li>Key Material: as the value of the attribute entry keyed by - * {@link #MAC_KEY_MATERIAL}. The value is taken to be a byte array - * containing the user-specified key material. The length of this array, - * if/when defined SHOULD be exactly equal to {@link #KEY_LEN}.</li> - * - * <li>Nonce Material: as the value of the attribute entry keyed by - * {@link #NONCE_MATERIAL}. The value is taken to be a byte array - * containing the user-specified nonce material. The length of this array, - * if/when defined SHOULD be (a) greater than zero, and (b) less or equal - * to 16 (the size of the AES block).</li> + * <li>Key Material: as the value of the attribute entry keyed by + * {@link #MAC_KEY_MATERIAL}. The value is taken to be a byte array + * containing the user-specified key material. The length of this array, + * if/when defined SHOULD be exactly equal to {@link #KEY_LEN}.</li> + * <li>Nonce Material: as the value of the attribute entry keyed by + * {@link #NONCE_MATERIAL}. The value is taken to be a byte array containing + * the user-specified nonce material. The length of this array, if/when + * defined SHOULD be (a) greater than zero, and (b) less or equal to 16 (the + * size of the AES block).</li> * </ol> - * - * <p>For convenience, this implementation accepts that not both parameters - * be always specified.</p> - * + * <p> + * For convenience, this implementation accepts that not both parameters be + * always specified. * <ul> - * <li>If the <i>Key Material</i> is specified, but the <i>Nonce Material</i> - * is not, then this implementation, re-uses the previously set <i>Nonce - * Material</i> after (a) converting the bytes to an unsigned integer, - * (b) incrementing the number by one, and (c) converting it back to 16 - * bytes.</li> - * - * <li>If the <i>Nonce Material</i> is specified, but the <i>Key Material</i> - * is not, then this implementation re-uses the previously set <i>Key - * Material</i>.</li> + * <li>If the <i>Key Material</i> is specified, but the <i>Nonce Material</i> + * is not, then this implementation, re-uses the previously set <i>Nonce + * Material</i> after (a) converting the bytes to an unsigned integer, (b) + * incrementing the number by one, and (c) converting it back to 16 bytes.</li> + * <li>If the <i>Nonce Material</i> is specified, but the <i>Key Material</i> + * is not, then this implementation re-uses the previously set <i>Key Material</i>. + * </li> * </ul> - * - * <p>This method throws an exception if no <i>Key Material</i> is specified - * in the input map, and there is no previously set/defined <i>Key Material</i> + * <p> + * This method throws an exception if no <i>Key Material</i> is specified in + * the input map, and there is no previously set/defined <i>Key Material</i> * (from an earlier invocation of this method). If a <i>Key Material</i> can - * be used, but no <i>Nonce Material</i> is defined or previously set/defined, - * then a default value of all-zeroes shall be used.</p> - * + * be used, but no <i>Nonce Material</i> is defined or previously + * set/defined, then a default value of all-zeroes shall be used. + * * @param attributes one or both of required parameters. * @throws InvalidKeyException the key material specified is not of the - * correct length. + * correct length. */ public void init(Map attributes) throws InvalidKeyException, IllegalStateException { byte[] key = (byte[]) attributes.get(MAC_KEY_MATERIAL); byte[] n = (byte[]) attributes.get(NONCE_MATERIAL); - boolean newKey = (key != null); boolean newNonce = (n != null); - if (newKey) { if (key.length != KEY_LEN) - { - throw new InvalidKeyException("Key length: " - + String.valueOf(key.length)); - } + throw new InvalidKeyException("Key length: " + + String.valueOf(key.length)); K = key; } else { if (K == null) - { - throw new InvalidKeyException("Null Key"); - } + throw new InvalidKeyException("Null Key"); } - if (newNonce) { if (n.length < 1 || n.length > 16) + throw new IllegalArgumentException("Invalid Nonce length: " + + String.valueOf(n.length)); + if (n.length < 16) // pad with zeroes { - throw new IllegalArgumentException("Invalid Nonce length: " - + String.valueOf(n.length)); - } - - if (n.length < 16) - { // pad with zeroes byte[] newN = new byte[16]; System.arraycopy(n, 0, newN, 0, n.length); nonce = newN; } else - { - nonce = n; - } + nonce = n; nonceReuseCount = BigInteger.ZERO; } - else if (nonce == null) - { // use all-0 nonce if 1st time + else if (nonce == null) // use all-0 nonce if 1st time + { nonce = new byte[16]; nonceReuseCount = BigInteger.ZERO; } - else if (!newKey) - { // increment nonce if still below max count + else if (! newKey) // increment nonce if still below max count + { nonceReuseCount = nonceReuseCount.add(BigInteger.ONE); if (nonceReuseCount.compareTo(MAX_NONCE_ITERATIONS) >= 0) { @@ -326,9 +275,7 @@ public class UMac32 extends BaseMac N = N.add(BigInteger.ONE).mod(MAX_NONCE_ITERATIONS); n = N.toByteArray(); if (n.length == 16) - { - nonce = n; - } + nonce = n; else if (n.length < 16) { nonce = new byte[16]; @@ -340,15 +287,11 @@ public class UMac32 extends BaseMac System.arraycopy(n, n.length - 16, nonce, 0, 16); } } - else - { // do nothing, re-use old nonce value - nonceReuseCount = BigInteger.ZERO; - } + else // do nothing, re-use old nonce value + nonceReuseCount = BigInteger.ZERO; if (uhash32 == null) - { - uhash32 = new UHash32(); - } + uhash32 = new UHash32(); Map map = new HashMap(); map.put(MAC_KEY_MATERIAL, K); @@ -370,9 +313,7 @@ public class UMac32 extends BaseMac byte[] result = uhash32.digest(); byte[] pad = pdf(); // pdf(K, nonce); for (int i = 0; i < OUTPUT_LEN; i++) - { - result[i] = (byte) (result[i] ^ pad[i]); - } + result[i] = (byte)(result[i] ^ pad[i]); return result; } @@ -380,9 +321,7 @@ public class UMac32 extends BaseMac public void reset() { if (uhash32 != null) - { - uhash32.reset(); - } + uhash32.reset(); } public boolean selfTest() @@ -412,43 +351,32 @@ public class UMac32 extends BaseMac x.printStackTrace(System.err); return false; } - byte[] data = new byte[128]; data[0] = (byte) 0x80; - mac.update(data, 0, 128); byte[] result = mac.digest(); - // System.out.println("UMAC test vector: "+Util.toString(result)); valid = Boolean.valueOf(TV1.equals(Util.toString(result))); } return valid.booleanValue(); } - // helper methods ---------------------------------------------------------- - /** - * * @return byte array of length 8 (or OUTPUT_LEN) bytes. */ private byte[] pdf() { // Make Nonce 16 bytes by prepending zeroes. done (see init()) - // one AES invocation is enough for more than one PDF invocation // number of index bits needed = 1 - // Extract index bits and zero low bits of Nonce BigInteger Nonce = new BigInteger(1, nonce); int nlowbitsnum = Nonce.testBit(0) ? 1 : 0; Nonce = Nonce.clearBit(0); - // Generate subkey, AES and extract indexed substring IRandom kdf = new UMacGenerator(); Map map = new HashMap(); map.put(IBlockCipher.KEY_MATERIAL, K); - // map.put(IBlockCipher.CIPHER_BLOCK_SIZE, new Integer(128/8)); - map.put(UMacGenerator.INDEX, new Integer(128)); - // map.put(UMacGenerator.CIPHER, Registry.AES_CIPHER); + map.put(UMacGenerator.INDEX, Integer.valueOf(128)); kdf.init(map); byte[] Kp = new byte[KEY_LEN]; try @@ -485,7 +413,6 @@ public class UMac32 extends BaseMac aes.encryptBlock(nonce, 0, T, 0); byte[] result = new byte[OUTPUT_LEN]; System.arraycopy(T, nlowbitsnum, result, 0, OUTPUT_LEN); - return result; } -}
\ No newline at end of file +} |