org.cryptacular.generator.sp80038d.CounterNonce Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cryptacular Show documentation
Show all versions of cryptacular Show documentation
The spectacular complement to the Bouncy Castle crypto API for Java.
/* See LICENSE for licensing and NOTICE for copyright. */
package org.cryptacular.generator.sp80038d;
import java.util.concurrent.atomic.AtomicLong;
import org.cryptacular.generator.LimitException;
import org.cryptacular.generator.Nonce;
import org.cryptacular.util.ByteUtil;
/**
* Deterministic nonce generation strategy that uses a counter for the invocation field as described in NIST SP-800-38D, section 8.2.1. The
* invocation part of the sequence is always 64 bits (8 bytes) due to the use of a long
, thus the length of
* the nonce is determined by the length of the fixed part: length = 8 + fixed.length
.
*
* NOTE: users of this class are responsible for maintaining the invocation count in order to
* support enforcement of constraints described in section 8.3; namely the following:
*
* The total number of invocations of the authenticated encryption function shall not exceed 232,
* including all IV lengths and all instances of the authenticated encryption function with the given key.
*
* Instances of this class enforce this constraint by considering the nonce length, which determines whether the
* constraint applies, and the invocation count. The invocation count is incremented upon every invocation of {@link
* #generate()} method. The current invocation count is accessible via {@link #getInvocations()}.
*
* Instances of this class are thread safe.
*
* @author Middleware Services
*/
public class CounterNonce implements Nonce
{
/** Default nonce getLength is {@value} bytes. */
public static final int DEFAULT_LENGTH = 12;
/**
* Maximum invocations is 232. Does not apply to nonces with default getLength, {@value #DEFAULT_LENGTH}.
*/
public static final long MAX_INVOCATIONS = 0xFFFFFFFFL;
/** Fixed field value. */
private final byte[] fixed;
/** Invocation count. */
private final AtomicLong count;
/**
* Creates a new instance.
*
* @param fixed User-defined fixed field value.
* @param invocations Initial invocation count. The invocations field is incremented _before_ use in {@link
* #generate()}.
*/
public CounterNonce(final String fixed, final long invocations)
{
this(ByteUtil.toBytes(fixed), invocations);
}
/**
* Creates a new instance. Instances of this method produces nonces of the default length, {@value #DEFAULT_LENGTH},
* and are not subject to constraints on the number of invocations.
*
* @param fixed User-defined fixed field value.
* @param invocations Initial invocation count. The invocations field is incremented _before_ use in {@link
* #generate()}.
*/
public CounterNonce(final int fixed, final long invocations)
{
this(ByteUtil.toBytes(fixed), invocations);
}
/**
* Creates a new instance.
*
* @param fixed User-defined fixed field value.
* @param invocations Initial invocation count. The invocations field is incremented _before_ use in {@link
* #generate()}.
*/
public CounterNonce(final long fixed, final long invocations)
{
this(ByteUtil.toBytes(fixed), invocations);
}
/**
* Creates a new instance.
*
* @param fixed User-defined fixed field value.
* @param invocations Initial invocation count. The invocations field is incremented _before_ use in {@link
* #generate()}.
*/
public CounterNonce(final byte[] fixed, final long invocations)
{
if (fixed == null || fixed.length == 0) {
throw new IllegalArgumentException("Fixed part cannot be null or empty.");
}
this.count = new AtomicLong(invocations);
this.fixed = fixed;
}
@Override
public byte[] generate()
throws LimitException
{
final byte[] value = new byte[getLength()];
System.arraycopy(fixed, 0, value, 0, fixed.length);
final long next = count.incrementAndGet();
if (value.length != DEFAULT_LENGTH) {
// Enforce constraints described in section 8.3
if (next > MAX_INVOCATIONS) {
throw new LimitException("Exceeded 2^32 invocations.");
}
}
ByteUtil.toBytes(next, value, fixed.length);
return value;
}
@Override
public int getLength()
{
return fixed.length + 8;
}
/** @return Current invocation count. */
public long getInvocations()
{
return count.get();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy