package org.springframework.security.core.token;
import java.io.InputStream;
import java.security.SecureRandom;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
import org.springframework.util.FileCopyUtils;
/**
* Creates a {@link SecureRandom} instance.
*
* @author Ben Alex
* @since 2.0.1
*/
public class SecureRandomFactoryBean implements FactoryBean<SecureRandom> {
private String algorithm = "SHA1PRNG";
private Resource seed;
public SecureRandom getObject() throws Exception {
SecureRandom rnd = SecureRandom.getInstance(algorithm);
if (seed != null) {
// Seed specified, so use it
byte[] seedBytes = FileCopyUtils.copyToByteArray(seed.getInputStream());
rnd.setSeed(seedBytes);
} else {
// Request the next bytes, thus eagerly incurring the expense of default seeding
rnd.nextBytes(new byte[1]);
}
return rnd;
}
public Class<SecureRandom> getObjectType() {
return SecureRandom.class;
}
public boolean isSingleton() {
return false;
}
/**
* Allows the Pseudo Random Number Generator (PRNG) algorithm to be nominated. Defaults to "SHA1PRNG".
*
* @param algorithm to use (mandatory)
*/
public void setAlgorithm(String algorithm) {
Assert.hasText(algorithm, "Algorithm required");
this.algorithm = algorithm;
}
/**
* Allows the user to specify a resource which will act as a seed for the {@link SecureRandom}
* instance. Specifically, the resource will be read into an {@link InputStream} and those
* bytes presented to the {@link SecureRandom#setSeed(byte[])} method. Note that this will
* simply supplement, rather than replace, the existing seed. As such, it is always safe to
* set a seed using this method (it never reduces randomness).
*
* @param seed to use, or <code>null</code> if no additional seeding is needed
*/
public void setSeed(Resource seed) {
this.seed = seed;
}
}