All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gnu.crypto.prng.UMacGenerator Maven / Gradle / Ivy

The newest version!
package gnu.crypto.prng;

// ----------------------------------------------------------------------------
// $Id: UMacGenerator.java,v 1.5 2002/11/07 17:17:45 raif Exp $
//
// Copyright (C) 2001, 2002, Free Software Foundation, Inc.
//
// This file is part of GNU Crypto.
//
// GNU Crypto is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// GNU Crypto is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; see the file COPYING.  If not, write to the
//
//    Free Software Foundation Inc.,
//    59 Temple Place - Suite 330,
//    Boston, MA 02111-1307
//    USA
//
// Linking this library statically or dynamically with other modules is
// making a combined work based on this library.  Thus, the terms and
// conditions of the GNU General Public License cover the whole
// combination.
//
// As a special exception, the copyright holders of this library give
// you permission to link this library with independent modules to
// produce an executable, regardless of the license terms of these
// independent modules, and to copy and distribute the resulting
// executable under terms of your choice, provided that you also meet,
// for each linked independent module, the terms and conditions of the
// license of that module.  An independent module is a module which is
// not derived from or based on this library.  If you modify this
// library, you may extend this exception to your version of the
// library, but you are not obligated to do so.  If you do not wish to
// do so, delete this exception statement from your version.
// ----------------------------------------------------------------------------

import gnu.crypto.Registry;
import gnu.crypto.cipher.CipherFactory;
import gnu.crypto.cipher.IBlockCipher;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.security.InvalidKeyException;

/**
 * 

KDFs (Key Derivation Functions) are used to stretch user-supplied * key material to specific size(s) required by high level cryptographic * primitives. Described in the UMAC * paper, this function basically operates an underlying symmetric key block * cipher instance in output feedback mode (OFB), as a strong * pseudo-random number generator.

* *

UMacGenerator requires an index parameter * (initialisation parameter gnu.crypto.prng.umac.kdf.index taken * to be an instance of {@link java.lang.Integer} with a value between * 0 and 255). Using the same key, but different * indices, generates different pseudorandom outputs.

* *

This implementation generalises the definition of the * UmacGenerator algorithm to allow for other than the AES symetric * key block cipher algorithm (initialisation parameter * gnu.crypto.prng.umac.cipher.name taken to be an instance of * {@link java.lang.String}). If such a parameter is not defined/included in the * initialisation Map, then the "Rijndael" algorithm is used. * Furthermore, if the initialisation parameter * gnu.crypto.cipher.block.size (taken to be a instance of {@link * java.lang.Integer}) is missing or undefined in the initialisation Map * , then the cipher's default block size is used.

* *

NOTE: Rijndael is used as the default symmetric key block cipher * algorithm because, with its default block and key sizes, it is the AES. Yet * being Rijndael, the algorithm offers more versatile block and key sizes which * may prove to be useful for generating "longer" key streams.

* *

References:

* *
    *
  1. * UMAC: Message Authentication Code using Universal Hashing.
    * T. Krovetz, J. Black, S. Halevi, A. Hevia, H. Krawczyk, and P. Rogaway.
  2. *
* * @version $Revision: 1.5 $ */ public class UMacGenerator extends BasePRNG { // Constants and variables // ------------------------------------------------------------------------- /** *

Property name of the KDF index value to use in this * instance. The value is taken to be an {@link Integer} less than * 256.

*/ public static final String INDEX = "gnu.crypto.prng.umac.index"; /** The name of the underlying symmetric key block cipher algorithm. */ public static final String CIPHER = "gnu.crypto.prng.umac.cipher.name"; /** The generator's underlying block cipher. */ private IBlockCipher cipher; // Constructor(s) // ------------------------------------------------------------------------- /** Trivial 0-arguments constructor. */ public UMacGenerator() { super(Registry.UMAC_PRNG); } /** *

Private constructor for cloning purposes.

* * @param that the instance to clone. */ private UMacGenerator(UMacGenerator that) { this(); this.cipher = (that.cipher == null ? null : (IBlockCipher) that.cipher.clone()); this.initialised = that.initialised; this.buffer = (byte[]) that.buffer.clone(); this.ndx = that.ndx; } // Class methods // ------------------------------------------------------------------------- // Instance methods // ------------------------------------------------------------------------- // java.lang.Cloneable interface implementation ---------------------------- public Object clone() { return new UMacGenerator(this); } // Implementation of abstract methods in BasePRNG -------------------------- public void setup(Map attributes) { boolean newCipher = true; String cipherName = (String) attributes.get(CIPHER); if (cipherName == null) { if (cipher == null) { // happy birthday cipher = CipherFactory.getInstance(Registry.RIJNDAEL_CIPHER); } else { // we already have one. use it as is newCipher = false; } } else { cipher = CipherFactory.getInstance(cipherName); } // find out what block size we should use it in int cipherBlockSize = 0; Integer bs = (Integer) attributes.get(IBlockCipher.CIPHER_BLOCK_SIZE); if (bs != null) { cipherBlockSize = bs.intValue(); } else { if (newCipher) { // assume we'll use its default block size cipherBlockSize = cipher.defaultBlockSize(); } // else use as is } // get the key material byte[] key = (byte[]) attributes.get(IBlockCipher.KEY_MATERIAL); if (key == null) { throw new IllegalArgumentException(IBlockCipher.KEY_MATERIAL); } int keyLength = key.length; // ensure that keyLength is valid for the chosen underlying cipher boolean ok = false; for (Iterator it = cipher.keySizes(); it.hasNext(); ) { ok = (keyLength == ((Integer) it.next()).intValue()); if (ok) { break; } } if (!ok) { throw new IllegalArgumentException("key length"); } // ensure that remaining params make sense int index = -1; Integer i = (Integer) attributes.get(INDEX); if (i != null) { index = i.intValue(); if (index < 0 || index > 255) { throw new IllegalArgumentException(INDEX); } } // now initialise the underlying cipher Map map = new HashMap(); if (cipherBlockSize != 0) { // only needed if new or changed map.put(IBlockCipher.CIPHER_BLOCK_SIZE, new Integer(cipherBlockSize)); } map.put(IBlockCipher.KEY_MATERIAL, key); try { cipher.init(map); } catch (InvalidKeyException x) { throw new IllegalArgumentException(IBlockCipher.KEY_MATERIAL); } buffer = new byte[cipher.currentBlockSize()]; buffer[cipher.currentBlockSize() - 1] = (byte) index; try { fillBlock(); } catch (LimitReachedException impossible) { } } public void fillBlock() throws LimitReachedException { cipher.encryptBlock(buffer, 0, buffer, 0); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy