/* See LICENSE for licensing and NOTICE for copyright. */ package org.cryptacular.generator.sp80038a; import javax.crypto.SecretKey; import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.params.KeyParameter; import org.cryptacular.generator.LimitException; import org.cryptacular.generator.Nonce; import org.cryptacular.spec.Spec; import org.cryptacular.util.NonceUtil; /** * Nonce generation strategy that produces a random value according to NIST <a href="http://goo.gl/S9z8qF"> * SP-800-38a</a>, appendix C, method 1 (encrypted nonce), suitable for use with any block cipher mode described in that * standard except OFB. * * <p>Instances of this class are thread safe.</p> * * @author Middleware Services */ public class EncryptedNonce implements Nonce { /** Block cipher. */ private final BlockCipher cipher; /** Encryption key. */ private final SecretKey key; /** * Creates a new instance. * * @param cipherSpec Block cipher specification. * @param key Symmetric key. */ public EncryptedNonce(final Spec<BlockCipher> cipherSpec, final SecretKey key) { this(cipherSpec.newInstance(), key); } /** * Creates a new instance. * * @param cipher Block cipher to use. * @param key Symmetric key. */ public EncryptedNonce(final BlockCipher cipher, final SecretKey key) { this.cipher = cipher; this.key = key; } @Override public byte[] generate() throws LimitException { final byte[] result = new byte[cipher.getBlockSize()]; final byte[] nonce = NonceUtil.timestampNonce(result.length); synchronized (cipher) { cipher.init(true, new KeyParameter(key.getEncoded())); cipher.processBlock(nonce, 0, result, 0); cipher.reset(); } return result; } @Override public int getLength() { return cipher.getBlockSize(); } }