Skip to content

Instantly share code, notes, and snippets.

@bcoughlan
Created April 14, 2015 23:44
Show Gist options
  • Save bcoughlan/9940b5a349c5f872395e to your computer and use it in GitHub Desktop.
Save bcoughlan/9940b5a349c5f872395e to your computer and use it in GitHub Desktop.
Replacing a SecureRandom.getInstance() algorithm in Java for mocking
When writing tests, it can be a burden to make assertions about code with non-deterministic behavior such as random number generation. The above class shows a way of mocking SecureRandom.getInstance() to produce deterministic behaviour without using bytecode-modifying mocking frameworks such as PowerMock or jMockIt, which often cause headaches by interfering with code coverage tools.
Probably no-one besides me will ever need to do this, but after dealing with the side effects of power-mocking tools all week, I liked the solution too much to share :)
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.SecureRandomSpi;
import java.security.Security;
public class ReplaceAlgorithms {
public static void main(String[] args) throws NoSuchAlgorithmException {
byte[] bytes = new byte[16];
SecureRandom.getInstance("SHA1PRNG").nextBytes(bytes);
System.out.println(new String(bytes));
}
static {
// Give fake provider highest priority
Security.insertProviderAt(new FakeSha1Provider(), 1);
}
public static class FakeSha1Provider extends Provider {
protected FakeSha1Provider() {
super("FakeSha1Provider", 1.0, null);
put("SecureRandom.SHA1PRNG", FakeAlgorithm.class.getName());
}
}
public static class FakeAlgorithm extends SecureRandomSpi {
@Override
protected void engineSetSeed(byte[] seed) {
for (int i = 0; i < seed.length; i++) {
// Deterministic result for a given length
seed[i] = (byte) ('a' + (i % 26));
}
}
@Override
protected void engineNextBytes(byte[] bytes) {
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte) ('a' + (i % 26));
}
}
@Override
protected byte[] engineGenerateSeed(int numBytes) {
byte[] bytes = new byte[numBytes];
for (int i = 0; i < numBytes; i++) {
bytes[i] = (byte) ('a' + (i % 26));
}
return bytes;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment