Thanks the comments from everyone.
However, I have to explain this question.
I know that we shouldn't compare the result of encryption by using a fix random generator due to it may reduce the secure. However, I just want to do it in testing and I'll use a original mechanism of random in real running.
The case is that I need to login a server with account/password by the following steps:
- Get info from server: a.b.com/get_cipher.cgi.
- receive the response, parse it and get some info to create a cipher.
- use the cipher to encrypt account/password and then compose the following URL a.b.com/login.cgi?encrypted={encrypted_account_password}
It's a complex process and I can't request the server to change the protocal. I want to test the whole login process. Thus, I tried to provide fake account/password and check if the generated url is correct without deciphering the result (if deciphering the result, it means that, in this test case, I need to decipher the the encrypted result, parse the url, and extract the related info, there are too much not related to the testing. Moreover, if I do some change in the login process, I may need to modify the deciphering and parsing process in the test cases.)
That means a hash function is not proper for me. (The original login process don't use any hash so that I don't want to test it in a test cases. Moreover, even thought I check the hash result is correct, it doesn't prove the login process is correct.)
=== The original question is as the following ===
I have a program which needs login. To void transfer the password in plain text on the network, I need to encipher it. In other word, the login process contains a ciphering phase.
Then, I want to write a test case for the whole login process. I think the encryption result of be the same if it use the same account and password.
Since it may use SecureRandom in the encryption process, I write a fake SecureRandom by Mockito as the following code:
private static final long RANDOM_SEED = 3670875202692512518L;
private Random generateRandomWithFixSeed() {
Random random = new Random(RANDOM_SEED);
return random;
}
private SecureRandom generateSecureRandomWithFixSeed() {
final Random random = generateRandomWithFixSeed();
final SecureRandom secureRandom = new SecureRandom();
final SecureRandom spySecureRandom = Mockito.spy(secureRandom);
Mockito.doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
byte[] bytes = (byte[]) args[0];
random.nextBytes(bytes);
return bytes;
}
})
.when(spySecureRandom)
.nextBytes(Matchers.<byte[]>anyObject());
return spySecureRandom;
}
@Test
public void test_SecureRandom_WithFixSeed() {
final SecureRandom secureRandom1 = generateSecureRandomWithFixSeed();
final SecureRandom secureRandom2 = generateSecureRandomWithFixSeed();
final byte[] bytes1 = new byte[20];
final byte[] bytes2 = new byte[20];
secureRandom1.nextBytes(bytes1);
secureRandom2.nextBytes(bytes2);
boolean isTheSameSeries = true;
for(int i = 0; i < 20; i++) {
isTheSameSeries &= (bytes1[i]==bytes2[i]);
}
assertThat(isTheSameSeries, is(true));
}
The generateRandomWithFixSeed() will new a Random with the same key, so that it will generate the same result. The generateSecureRandomWithFixSeed() uses Makito to detect the function call nextBytes() and always answer the result of the random. the test test_SecureRandom_WithFixSeed() also show two different SecureRandom instances generate the same results.
However, if I use generateSecureRandomWithFixSeed() in the cipher as the following, it can't always return the same result.
@Test
public void test_cipher() {
final SecureRandom secureRandomWithFixSeed = generateSecureRandomWithFixSeed();
final String pkcs = "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAv7n+/uWHHVC7229QLEObeH0vUcOagavDukf/gkveqgZsszzGkZQaXfsrjdPiCnvjozCy1tbnLu5EInDy4w8B+a9gtK8KqsvlsfuaT9kRSMUS8CfgpWj8JcJwijmeZhjR52k0UBpWLfn3JmRYW8xjZW6dlOSnS0yqwREPU7myyqUzhk1vyyUG7wLpk7uK9Bxmup0tnbnD4MeqDboAXlQYnIFVV+CXywlAQfHHCfQRsGhsEtu4excZVw7FD1rjnro9bcWFY9cm/KdDBxZCYQoT/UW0OBbipoINycrmfMKt1r4mGE9/MdVoIEMBc54aI6sb2g5J2GtNCYfEu+1/gA99xY0+5B3ydH74cbqfHYOZIvu11Q7GnpZ6l8zTLlMuF/pvlSily76I45H0YZ3HcdQnf/GoKC942P6fNsynHEX01zASYM8dzyMxHQpNEx7fcXGi+uiBUD/Xdm2jwzr9ZEP5eEVlrpcAvr8c9S5ylE50lwR+Mp3vaZxPoLdSGZrfyXy4v97UZSnYARQBacmn6KgsIHIOKhYOxNgUG0jwCO/zrPvlbjiYTHQYLOCcldTULvXOdn51enJFGVjscGoZfRj6vZgyHVCUW4iip4iSbSKPcPbf0GMZuniS9qJ3Wybve0/xpppdOv1c40ez0NKQyQkEZRb+V0qfesatJKZd/hUGr+MCAwEAAQ==";
final byte bytePKCS[] = Base64.base64ToByteArray(pkcs);
final X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(bytePKCS);
PublicKey pubKey = null;
try {
pubKey = KeyFactory.getInstance("RSA").generatePublic(pubKeySpec);
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
final String targetResultText = "NZqTzuNli92vuXEQNchGeF6faN/NBHykhfqBFcWzBHZhbgljZaWAcAzasFSm/odZZ6vBD2jK7J4oi5BmDjxNdEjkXyv3OZ2sOTLCfudgPwXcXmmhOwWHDLY02OX0X3RwBHzqWczqAd4dwslo59Gp5CT59GWXenJPL8wvG90WH2XAKOmHg5uEZj55ZvErRQ6StPVzLkiNCMPOhga7FZWK/rSEpT6BHDy3CibDZ0PNRtAW4wiYAr0Cw6brqiqkN301Bz6DzrV5380KDHkw26GjM8URSTFekwvZ7FISQ72UaNHhjnh1WgMIPf/QDbrEh5b+rmdZjzc5bdjyONrQuoj0rzrWLN4z8lsrBnKFVo+zVyUeqr0IxqD2aHDLyz5OE4fb5IZJHEMfYr/R79Zfe8IuQ2tusA02ZlFzGRGBhAkb0VygXxJxPXkjbkPaLbZQZOsKLUoIDkcbNoUTxeS9+4LWVg1j5q3HR9OSvmsF5I/SszvVrnXdNaz1IKCfVYkwpIBQ+Y+xI/K360dWIHR/vn7TU4UsGmWtwVciq0jWLuBN/qRE6MV47TDRQu63GzeV00yAM/xUM33qWNXCV1tbGXNZw8jHpakgflTY0hcjOFHPpq2UfJCyxiSBtZ0b7hw9Rvhi8VwYc243jXO9CvGq+J6JYvchvKHjq2+YKn1UB2+gs20=";
final String plainText = "a";
String resultText = "";
try {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, pubKey, secureRandomWithFixSeed);
final byte[] result = cipher.doFinal(plainText.getBytes());
resultText = Base64.byteArrayToBase64(result);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
assertThat(resultText, is(targetResultText));
}
aa