Design review: JEP 273: DRBG-Based SecureRandom Implementations
Wang Weijun
weijun.wang at oracle.com
Mon Nov 9 14:54:37 UTC 2015
Hi All
The following is API/SPI to support NIST 800-90A DRBGs. The JEP is at
https://bugs.openjdk.java.net/browse/JDK-8051408
Some notes before the text:
1. Mainly, new methods are added to SecureRandom to match DRBG functions:
- configure: choosing the algorithms and parameters
- reseed: reseed using configured entropy. This is not same as existing setSeed() which reseeds using a caller-provided seed
- nextBytes: random bits generation, with support for additional input
Like the existing ones, DRBGs will still be initiated automatically when nextBytes() is called.
SecureRandomSpi is also updated with related engine methods.
2. The new APIs will apply to all existing SecureRandom implementations, although some is just a no-op. We believe the concepts apply to all.
3. An EntropyInput interface is introduced to model source of entropy input. We will provide some internal implementations so these DRBGs work out of box. However, we won't expose any implementation that an application can use directly. If you have a special entropy source, just implement the interface yourself. Also note the interface is super simple now. New methods (or getInstance() methods) might be added in the future.
4. Three new SecureRandom algorithms are provided by the SUN provider - HashDRBG, HmacDRBH, and CTRDRBG.
Here is an example:
SecureRandom sr = SecureRandom.getInstance("HashDRBG");
hd.configure(new DrbgSpec("SHA-512", -1, true, false,
nonce, person), new MyEntropyInput());
hg.nextBytes(output, additional);
hg.reseed(additional2);
Any suggestion is welcome.
Thanks
Max
-----API START-----
package java.security;
/**
*
* ....
*
* <p> Some SecureRandom implementations can be further configured by
* calling {@link #configure}. For example, a DRBG mechanism can be configured
* by a {@link DrbgSpec} object.
*
* ....
*
* <p> A SecureRandom can be reseeded by itself by calling {@link #reseed}.
* A caller can also reseed it a user-provided seed by calling
* {@link #setSeed(byte[])}.
*
* ....
*
* <p> Except for one created by {@link #SecureRandom(byte[])},
* a newly created SecureRandom object is usually not seeded. To seed the
* returned object, call the {@code setSeed} method.
* If {@code setSeed} is not called, the first call to
* {@code nextBytes} or {@code reseed} will force the SecureRandom
* object to seed itself. This self-seeding will not occur
* if {@code setSeed} was previously called.
*
* <p>
* Note: Depending on the implementation, the {@code generateSeed},
* {@code reseed} and {@code nextBytes} methods may block as entropy is being
* gathered, for example, if they need to read from /dev/random on various
* Unix-like operating systems.
*/
public class SecureRandom {
....
/**
* Configure this {@code SecureRandom} with an {@link AlgorithmParameterSpec}
* object and a source of entropy input.
*
* @implNote The actual type of {@code spec} must match the algorithm of this
* {@code SecureRandom} object. Fo example, a DRBG must be configured by
* a {@link DrbgSpec}. Otherwise, an {@link IllegalArgumentException}
* should be thrown.
* <p>
* If {@code ei} is null, a default EntropyInput will be chosen. If not
* null, the caller needs to make sure the EntropyInput matches the
* {@code SecureRandom} to be configured with enough security strength,
* live entropy, and other features.
*
* @param spec the {@link AlgorithmParameterSpec} object. Null if not needed.
* @param ei the source of entropy input. Null if not user-chosen.
* @throws IllegalArgumentException if {@code spec} is not recognized by
* this {@code SecureRandom} object.
* @since 1.9
*/
public void configure(AlgorithmParameterSpec spec, EntropyInput ei);
/**
* Generates a user-specified number of random bytes with an optional
* additional input argument.
*
* @param bytes the array to be filled in with random bytes.
* @param additionalInput an optional additional input argument.
* @since 1.9
*/
public void nextBytes(byte[] bytes, byte[] additionalInput);
/**
* Reseeds this {@code SecureRandom} with entropy read from its
* {@code EntropyInput} and an optional additional data.
* <p>
* Note that the entropy is obtained from {@code EntropyInput}. While
* {@code additional} may contain entropy but its main usage is to
* provide diversity.
*
* @param additionalInput an optional additional input argument.
* @since 1.9
*/
public void reseed(byte[] additionalInput);
....
}
public abstract class SecureRandomSpi {
/**
* Configure this random object.
*
* @param spec the {@link AlgorithmParameterSpec} object. Null if not needed.
* @param ei the source of entropy input. Null if not user-chosen.
* @throws IllegalArgumentException if this random object does not need
* to be configured or it does not recongize {@code spec}.
* @since 1.9
*/
protected void engineConfigure(AlgorithmParameterSpec spec, EntropyInput ei);
/**
* Generates random bits.
*
* @param bytes output.
* @param additionalInput optional additional input.
* @since 1.9
*/
public void engineGenerate(byte[] bytes, byte[] additionalInput);
/**
* Reseeds this random object with entropy read from its
* {@code EntropyInput} and an optional additional data.
*
* @param additional optional additional string.
* @since 1.9
*/
protected void engineReseed(byte[] additional);
}
/**
* An interface of a source of entropy input.
*
* @since 1.9
*/
public interface EntropyInput {
/**
* Fills a byte array with full entropy.
*
* <p>This method might block and/or fail.
*
* @param entropy the byte array with filled entropy.
* @throws EntropyNotAvailableException if not enough entropy is available.
*/
public void getFullEntropy(byte[] entropy);
}
/**
* A RuntimeException thrown when not enough entropy is available.
*
* @since 1.9
*/
public class EntropyNotAvailableException extends RuntimeException {
private static final long serialVersionUID = 9L;
/**
* Creates one
* @param msg the message
*/
public EntropyNotAvailableException(String msg);
}
/**
* This class specifies the configuration of a DRBG.
* <p>
* DRBG (deterministic random bits generator) is defined in
* <a href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf">
* NIST Special Publication 800-90A Revision 1, Recommendation for Random
* Number Generation Using Deterministic Random Bit Generators</a>.
* A DRBG mechanism should extend this class.
* <p>
* The following {@link SecureRandom} methods match to DRBG functions:
* <ul>
* <li>{@link SecureRandom#configure} to configure.
* <li>A DRBG will be automatically instantiated.
* <li>{@link SecureRandom#nextBytes(byte[], byte[])} to generate.
* <li>{@link SecureRandom#reseed} to reseed.
* </ul>
* <p>
* Calling {@link SecureRandom#generateSeed} is equivalent to calling
* {@link EntropyInput#getFullEntropy} on its entropy source.
* <p>
* A DRBG {@code SecureRandom} can be configured before generating random
* bits or reseeding. Otherwise, it will be configured with default values
* defined by the DRBG mechanism at the first call of
* {@link SecureRandom#nextBytes} or {@link SecureRandom#reseed}.
* <p>
* If {@link SecureRandom#setSeed} is the first call on a DRBG, the DRBG
* will be configured by default but instantiated with the argument of this
* method, therefore will not block. Callers should make sure the argument
* must contain enough entropy to ensure the security of this DRBG.
* <p>
* A DRBG will be reseeded aotomatically if the seed period is bigger
* than the maximum seedlife defined by the DRBG mechanism.
* <p>
* A Source of Entropy Input (SEI) can be provided at configure time,
* otherwise, a default SEI defined by the DRBG mechanism will be chosen.
*
* @see SecureRandom#configure
* @since 1.9
*/
public class DrbgSpec implements AlgorithmParameterSpec {
/**
* Return the nonce used by this DRBG
*
* @return the nonce.
*/
public byte[] getNonce();
/**
* Return the personalization string used by this DRBG
*
* @return the personalization string.
*/
public byte[] getPersonal();
/**
* Return the source of entropy input used by this DRBG
*
* @return the source of entropy input.
*/
public EntropyInput getEntropyInput();
/**
* Return the algorithm used by this DRBG.
*
* @return the algorithm.
*/
public String getAlgorithm();
/**
* Returns the strength used by this DRBG.
*
* @return the strength.
*/
public int getStrength();
/**
* Returns whether a derivation function is used by this DRBG
*
* @return whether a derivation function is used.
*/
public boolean isUsedf();
/**
* Returns whether prediction resistance is provided by this DRBG.
*
* @return whether prediction resistance is provided.
*/
public boolean isPr();
/**
* Creates a {@code DrbgSpec}.
*
* @param algorithm the algorithm used by the DRBG mechanism. For example,
* "SHA-256" for HashDRBG, or "AES-256" for CtrDRBG. If null,
* the algorithm will be determined by the requested strength.
* @param strength the requested strength, ignored if algorithm is null,
* -1 means a strength automatically chosen.
* @param pr if prediction resistance is requested.
* @param usedf if a derivation function will be used.
* @param nonce the nonce used.
* @param personal an optional personalization string.
*/
public DrbgSpec(String algorithm, int strength, boolean pr,
boolean usedf, byte[] nonce, byte[] personal);
}
-----API END-----
More information about the security-dev
mailing list