package helpers;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import org.junit.Test;
public class TestScryptHelper {
private static final Charset utf8 = StandardCharsets.UTF_8;
@Test
public void testStandardVector1() throws Exception {
/*
Check against the test vectors described at:
https://tools.ietf.org/html/rfc7914#section-12
*/
byte[] standardVector = new byte[]{(byte) 0x70, (byte) 0x23, (byte) 0xbd,
(byte) 0xcb, (byte) 0x3a, (byte) 0xfd, (byte) 0x73, (byte) 0x48,
(byte) 0x46, (byte) 0x1c, (byte) 0x06, (byte) 0xcd, (byte) 0x81,
(byte) 0xfd, (byte) 0x38, (byte) 0xeb, (byte) 0xfd, (byte) 0xa8,
(byte) 0xfb, (byte) 0xba, (byte) 0x90, (byte) 0x4f, (byte) 0x8e,
(byte) 0x3e, (byte) 0xa9, (byte) 0xb5, (byte) 0x43, (byte) 0xf6,
(byte) 0x54, (byte) 0x5d, (byte) 0xa1, (byte) 0xf2, (byte) 0xd5,
(byte) 0x43, (byte) 0x29, (byte) 0x55, (byte) 0x61, (byte) 0x3f,
(byte) 0x0f, (byte) 0xcf, (byte) 0x62, (byte) 0xd4, (byte) 0x97,
(byte) 0x05, (byte) 0x24, (byte) 0x2a, (byte) 0x9a, (byte) 0xf9,
(byte) 0xe6, (byte) 0x1e, (byte) 0x85, (byte) 0xdc, (byte) 0x0d,
(byte) 0x65, (byte) 0x1e, (byte) 0x40, (byte) 0xdf, (byte) 0xcf,
(byte) 0x01, (byte) 0x7b, (byte) 0x45, (byte) 0x57, (byte) 0x58,
(byte) 0x87};
String password = "pleaseletmein";
byte[] salt = "SodiumChloride".getBytes(utf8);
byte[] hash = ScryptHelper.hash(password, salt, 16384, 8, 1, 64);
assertThat(hash, is(standardVector));
}
@Test
public void testStandardVector2() throws Exception {
/*
Check against the test vectors described at:
https://tools.ietf.org/html/rfc7914#section-12
*/
byte[] standardVector = new byte[]{(byte) 0xfd, (byte) 0xba, (byte) 0xbe,
(byte) 0x1c, (byte) 0x9d, (byte) 0x34, (byte) 0x72, (byte) 0x00,
(byte) 0x78, (byte) 0x56, (byte) 0xe7, (byte) 0x19, (byte) 0x0d,
(byte) 0x01, (byte) 0xe9, (byte) 0xfe, (byte) 0x7c, (byte) 0x6a,
(byte) 0xd7, (byte) 0xcb, (byte) 0xc8, (byte) 0x23, (byte) 0x78,
(byte) 0x30, (byte) 0xe7, (byte) 0x73, (byte) 0x76, (byte) 0x63,
(byte) 0x4b, (byte) 0x37, (byte) 0x31, (byte) 0x62, (byte) 0x2e,
(byte) 0xaf, (byte) 0x30, (byte) 0xd9, (byte) 0x2e, (byte) 0x22,
(byte) 0xa3, (byte) 0x88, (byte) 0x6f, (byte) 0xf1, (byte) 0x09,
(byte) 0x27, (byte) 0x9d, (byte) 0x98, (byte) 0x30, (byte) 0xda,
(byte) 0xc7, (byte) 0x27, (byte) 0xaf, (byte) 0xb9, (byte) 0x4a,
(byte) 0x83, (byte) 0xee, (byte) 0x6d, (byte) 0x83, (byte) 0x60,
(byte) 0xcb, (byte) 0xdf, (byte) 0xa2, (byte) 0xcc, (byte) 0x06,
(byte) 0x40};
String password = "password";
byte[] salt = "NaCl".getBytes(utf8);
byte[] hash = ScryptHelper.hash(password, salt, 1024, 8, 16, 64);
assertThat(hash, is(standardVector));
}
@Test
public void testUTF8Password() throws Exception {
String password = "\uD83D\uDCA9\uD83D\uDCA9\uD83D\uDCA9\uD83D\uDCA9\uD83D\uDCA9";
String hash = ScryptHelper.hash(password).toString();
boolean result = ScryptHelper.check(hash, password);
assertThat(result, is(true));
}
@Test
public void testSimplePassword() throws Exception {
String password = "testing123";
String hash = ScryptHelper.hash(password).toString();
boolean result = ScryptHelper.check(hash, password);
assertThat(result, is(true));
}
@Test
public void testLongPassword() throws Exception {
String password = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
String hash = ScryptHelper.hash(password).toString();
boolean result = ScryptHelper.check(hash, password);
assertThat(result, is(true));
}
@Test
public void testEmptyPassword() throws Exception {
String password = "";
String hash = ScryptHelper.hash(password).toString();
boolean result = ScryptHelper.check(hash, password);
assertThat(result, is(true));
}
@Test
public void testBadPassword() throws Exception {
String password = "testing123";
String bad = "testing321";
String hash = ScryptHelper.hash(password).toString();
boolean result = ScryptHelper.check(hash, bad);
assertThat(result, is(false));
}
@Test
public void testCharBufferPassword() throws Exception {
CharBuffer password = CharBuffer.wrap("testing123");
String hash = ScryptHelper.hash(password).toString();
boolean result = ScryptHelper.check(hash, password);
assertThat(result, is(true));
}
@Test(expected = Exception.class)
public void testMalformedBase64() {
String badB64 = "$2097160$!!!$!!!$"; // Invalid Base64 characters
ScryptHelper.check(badB64, "password");
}
@Test(expected = IllegalArgumentException.class)
public void testMissingParts() {
String missingParts = "$2097160$salt$"; // Missing the hash part
ScryptHelper.check(missingParts, "password");
}
@Test
public void testHashTiming() throws Exception {
final int REPS = 100;
long startTime = System.currentTimeMillis();
for (int i = 0; i < REPS; i++) {
ScryptHelper.hash("wibble" + i);
}
long endTime = System.currentTimeMillis();
System.out.println("Mean time per hash(): " + (endTime - startTime) / (float) REPS + " ms");
}
@Test
public void testCheckTiming() throws Exception {
final int REPS = 100;
CharBuffer hash = ScryptHelper.hash("wibble42");
long startTime = System.currentTimeMillis();
for (int i = 0; i < REPS; i++) {
ScryptHelper.check(hash, "wibble" + i);
}
long endTime = System.currentTimeMillis();
System.out.println("Mean time per check(): " + (endTime - startTime) / (float) REPS + " ms");
}
}