Message Authentication Codes
****************************

A message authentication code, or MAC, is akin to a keyed hash function, in that it produces a fixed-length identifier for variable-length data along with a key. The purpose of a MAC is to guarantee the integrity and authenticity of data, as it is computationally infesible to fake a MAC without knowledge of the key. MAC algorithms in GNU Crypto are in the gnu.crypto.mac package, and include:

  * Hash-based MAC. Hash-based MACs, also called HMACs, use a normal message digest algorithm to compute the code based on input data and the key. GNU Crypto therefore implements an HMAC for every message digest it supports, and the name of a HMAC is usually ``HMAC-'' concatenated with the message digest's name; see the previous chapter on message digests for further discussion.

  * The Truncated Multi-Modular Hash function, TMMH. TMMH/16 and TMMH/32 are universal hash functions; GNU Crypto implements TMMH/16. TMMH/16 has a variety of parameters, which are described later in this chapter. TMMH is described in [McG02].

  * UHASH-32. UHASH-32 is a keyed hash function that outputs a hash of 8 bytes. The key supplied to this MAC must be 16 bytes long. UHASH is described in [Kro00].

  * UMAC-32. The UMAC family of algorithms are parameterized, meaning that low-level choices such as endianness and the underlying cryptographic primitive are not fixed. The UMAC algorithms are described in [Kro00]. GNU Crypto implements UMAC-32, which performs well on 32- and 64-bit architectures, and has a key length of 16 bytes and an output length of 8 bytes. See the section on UMAC-32 for further discussion.

IMac Interface
==============

Figure 9: Message Authentication Code (MAC) class diagram

 -- Variable: java.lang.String MAC_KEY_MATERIAL
     A key in the attributes map passed to the init method. The value is taken to be a byte array, which contains the key as raw bytes. The length of the key must be at least the length of the computed hash in the case of hash-based MACs.

 -- Variable: java.lang.String TRUNCATED_SIZE
     The actual size of the returned hash, taken from the first bytes of the raw result. The value must be a java.lang.Integer containing the desired length, which should not be smaller than 80 bits or one half the MAC's usual output length, whichever is larger.

 -- Function: void init (java.util.Map ATTRIBUTES) throws java.security.InvalidKeyException, java.lang.IllegalStateException
     Initializes this MAC instance with a specified attributes map, which maps keys (such as MAC_KEY_MATERIAL) to parameters (such as the key bytes). Throws a java.security.InvalidKeyException if the key is unacceptable or omitted, and trows a java.lang.IllegalStateException if this instance has already been initialized.

 -- Function: void update (byte B)
     Continues the computation of the MAC with a single input byte, B.

 -- Function: void update (byte[] IN, int OFFSET, int LENGTH)
     Continues the computation of the MAC with a portion of the byte array IN, starting at OFFSET and considering LENGTH bytes.

 -- Function: byte[] digest ( )
     Finishes the computation of the MAC and returns it in a new byte array. The instance is reset after this method returns.

 -- Function: void reset ( )
     Resets the internal state of this instance, which may then be re-initialized.

 -- Function: int macSize ( )
     Returns the size of the final MAC, in bytes.

 -- Function: java.lang.String name ( )
     Returns the canonical name of this algorithm.

 -- Function: java.lang.Object clone ( )
     Returns a copy of this instance, which may be used the same way as the original.

 -- Function: boolean selfTest ( )
     Performs a simple conformance test on this implementation; returns true if the test is successful, false if not.

MacFactory Class
================

MAC instances are created with the following factory method:

 -- Function: IMac getInstance (java.lang.String NAME)
     Returns an instance of the MAC algorithm named NAME, or null if no such algorithm exists.

Additionally the MacFactory class defines the following method:

 -- Function: java.util.Set getNames ( )
     Returns a java.util.Set of the names of all available MAC algorithms.

TMMH/16
=======

In addition to the key, the TMMH/16 requires three more parameters passed to its init method, using the following three keys:

 -- Variable: java.lang.String TAG_LENGTH
     The output length, in bytes, represented as a java.lang.Integer. This value must be an even integer between 2 and 64.

 -- Variable: java.lang.String KEYSTREAM
     An instance of gnu.crypto.prng.IRandom, which is to serve as the source of random bytes for this instance.

 -- Variable: java.lang.String PREFIX
     A byte array of TAG_LENGTH bytes. If this parameter is omitted an all-zero byte array will be used. This value is XORed with the digest just before it is returned.

UMAC-32
=======

The UMAC-32 algorithm requires, in addition to the key, a nonce byte array. The byte array must be 1--16 bytes of random data, which is passed to the init method of IMac in the attributes map. UMac32 defined an additional key for this map:

 -- Variable: java.lang.String NONCE_MATERIAL
     The key for the nonce material for the attributes map. The value mapped must be a byte array of size 1--16 bytes.

Example
=======

     IMac mac = MacFactory.getInstance("HMAC-SHA-160");
     HashMap attributes = new HashMap();
     attributes.put(IMac.MAC_KEY_MATERIAL, key_bytes);
     attributes.put(IMac.TRUNCATED_SIZE, new Integer(12));
     mac.init(attributes);

     mac.update(input, 0, input.length);

     byte[] result = mac.digest();