/* See LICENSE for licensing and NOTICE for copyright. */
package org.cryptacular.generator.sp80038a;
import java.math.BigInteger;
import java.util.Arrays;
import org.cryptacular.generator.LimitException;
import org.cryptacular.generator.Nonce;
/**
* Uses a {@link BigInteger} to back a counter in order to produce nonces of arbitrary length.
*
* <p>A common use case for this component is creation of IVs for ciphers with 16-byte block size, e.g. AES.</p>
*
* <p>Instances of this class are thread safe.</p>
*
* @author Middleware Services
*/
public class BigIntegerCounterNonce implements Nonce
{
/** Counter. */
private BigInteger counter;
/** Length of generated counter nonce values in bytes. */
private final int length;
/**
* Creates a new instance with given parameters.
*
* @param counter Initial counter value.
* @param length Maximum length of generated counter values in bytes.
*/
public BigIntegerCounterNonce(final BigInteger counter, final int length)
{
if (length < 1) {
throw new IllegalArgumentException("Length must be positive");
}
this.length = length;
this.counter = counter;
}
@Override
public byte[] generate()
throws LimitException
{
final byte[] value;
synchronized (this) {
counter = counter.add(BigInteger.ONE);
value = counter.toByteArray();
}
if (value.length > length) {
throw new LimitException("Counter value exceeded max byte length " + length);
}
if (value.length < length) {
final byte[] temp = new byte[length];
Arrays.fill(temp, (byte) 0);
System.arraycopy(value, 0, temp, temp.length - value.length, value.length);
return temp;
}
return value;
}
@Override
public int getLength()
{
return length;
}
}