Class CipherCounterRandom

  • All Implemented Interfaces:
    ByteArrayReseedableRandom, EntropyCountingRandom, Java8CompatRandom, RepeatableRandom, SeekableRandom, Dumpable, Serializable
    Direct Known Subclasses:
    AesCounterRandom

    public abstract class CipherCounterRandom
    extends BaseRandom
    implements SeekableRandom

    Non-linear random number generator based on a cipher that encrypts an incrementing counter. fed. Subclasses must specify the key length for a given total seed length; When reseeded with a seed of less than the maximum key length, the new seed is combined with the existing key using a hash algorithm specified by the subclass.

    All interaction with the cipher is through abstract methods, so that both JCE and other cipher APIs such as Bouncy Castle can be used. If using a JCE cipher, extending AesCounterRandom may be simpler than extending this class directly.

    When used with a fixed seed, the maintainer believes this implementation conforms to NIST SP 800-90A Rev. 1 section 10.2.1. However, the reseeding process differs from section 10.2.1.4.

    Author:
    Daniel Dyer, Chris Hennick
    See Also:
    Serialized Form
    • Field Detail

      • currentBlock

        protected final byte[] currentBlock
        An array holding generated, encrypted bytes.
      • counter

        protected volatile byte[] counter
        The counter. Successive values are encrypted to generate pseudorandom numbers.
      • index

        protected volatile int index
        The offset in currentBlock to draw output from.
    • Constructor Detail

      • CipherCounterRandom

        public CipherCounterRandom​(byte[] seed)
        Creates an instance.
        Parameters:
        seed - the initial seed
    • Method Detail

      • getCounterSizeBytes

        public int getCounterSizeBytes()
        Returns the length of the counter, which should equal the cipher's block size.
        Returns:
        the length of the counter
      • getNewSeedLength

        public int getNewSeedLength()
        Description copied from interface: ByteArrayReseedableRandom
        Returns the preferred length of a new byte-array seed. "Preferred" is implementation-defined when multiple seed lengths are supported, but should probably usually mean the longest one, since the longer the seed, the more random the output.
        Specified by:
        getNewSeedLength in interface ByteArrayReseedableRandom
        Specified by:
        getNewSeedLength in class BaseRandom
        Returns:
        The desired length of a new byte-array seed.
      • getMaxKeyLengthBytes

        public abstract int getMaxKeyLengthBytes()
        Returns the maximum length in bytes of a key for this PRNG's cipher. If the seed is longer than this, part of it becomes the counter's initial value. Otherwise, the full seed becomes the key and the counter is initially zero.
        Returns:
        the maximum length in bytes of a key.
      • advance

        public void advance​(long delta)
        Description copied from interface: SeekableRandom
        Advances the generator forward delta steps, but does so in logarithmic time.
        Specified by:
        advance in interface SeekableRandom
        Parameters:
        delta - the number of steps to advance; can be negative
      • getKeyLength

        protected abstract int getKeyLength​(int inputLength)
        Returns the length of the key that should be extracted from a seed of a given length. During the initial seeding, whatever part of the seed does not become the key, becomes the counter's initial value.
        Parameters:
        inputLength - the length of the whole seed
        Returns:
        the length of the key
      • getBlocksAtOnce

        public abstract int getBlocksAtOnce()
        Returns how many consecutive values of the counter are encrypted at once, in order to reduce the number of calls to Cipher methods. Each counter value encrypts to yield a "block" of pseudorandom data. Changing this value won't change the output if the cipher is running in block mode, but it may impact performance.
        Returns:
        the number of blocks (counter values) to encrypt at once
      • getBytesAtOnce

        protected int getBytesAtOnce()
        Returns the number of random bytes that can be precalculated at once, which is normally getCounterSizeBytes() * getBlocksAtOnce().
        Returns:
        the number of random bytes that can be precalculated at once
      • getMaxTotalSeedLengthBytes

        public int getMaxTotalSeedLengthBytes()
        Returns the maximum seed length, including both the cipher key and a new counter value.
        Returns:
        the maximum seed length
      • initTransientFields

        protected void initTransientFields()
        Description copied from class: BaseRandom
        Called in constructor and readObject to initialize transient fields.
        Overrides:
        initTransientFields in class BaseRandom
      • supportsMultipleSeedLengths

        protected boolean supportsMultipleSeedLengths()
        Returns true, because the seed can either be a counter IV plus a key, or just a key.
        Overrides:
        supportsMultipleSeedLengths in class BaseRandom
        Returns:
        true
      • createHash

        protected abstract MessageDigest createHash()
        Returns the hash that will be used to combine seeds. Only called on construction and deserialization.
        Returns:
        a resettable MessageDigest
      • nextBlock

        protected void nextBlock()
        Generates BLOCKS_AT_ONCE 128-bit (16-byte) blocks. Copies them to currentBlock.
        Throws:
        IllegalStateException - If there is a problem with the cipher that generates the random data.
      • next

        protected final int next​(int bits)
        Description copied from class: BaseRandom
        Generates the next pseudorandom number. Called by all other random-number-generating methods. Should not debit the entropy count, since that's done by the calling methods according to the amount they actually output (see for example BaseRandom.withProbability(double), which uses 53 random bits but outputs only one, and thus debits only 1 bit of entropy).
        Specified by:
        next in class BaseRandom
      • setSeed

        public void setSeed​(byte[] seed)
        Reseed this PRNG.

        Most subclasses should override BaseRandom.setSeedInternal(byte[]) instead of this method, so that they will deserialize properly.

        If the seed is not of the maximum length, it is combined with the existing seed using the hash algorithm.
        Specified by:
        setSeed in interface ByteArrayReseedableRandom
        Overrides:
        setSeed in class BaseRandom
        Parameters:
        seed - The PRNG's new seed.
      • setSeed

        public void setSeed​(long seed)
        Combines the given seed with the existing seed using the hash algorithm.
        Specified by:
        setSeed in interface Java8CompatRandom
        Overrides:
        setSeed in class BaseRandom
      • setSeedInternal

        protected void setSeedInternal​(byte[] seed)
        Description copied from class: BaseRandom
        Sets the seed, and should be overridden to set other state that derives from the seed. Called by BaseRandom.setSeed(byte[]), constructors, and readObject(ObjectInputStream). When called after initialization, the BaseRandom.lock is always held.
        Overrides:
        setSeedInternal in class BaseRandom
        Parameters:
        seed - The new seed.
      • getMinSeedLength

        protected abstract int getMinSeedLength()
        Returns the minimum seed length.
        Returns:
        the minimum seed length
      • setKey

        protected abstract void setKey​(byte[] key)
                                throws InvalidKeyException
        Sets the key on the cipher. Always called with lock held.
        Parameters:
        key - the new key
        Throws:
        InvalidKeyException - if the cipher rejects the key