summaryrefslogtreecommitdiffstats
path: root/src/test
diff options
context:
space:
mode:
authorFlorian Zschocke <florian.zschocke@devolo.de>2019-11-05 13:43:06 +0100
committerFlorian Zschocke <florian.zschocke@devolo.de>2019-11-05 22:20:37 +0100
commitd1ee233d27fae23b1d0a69bbb6b9a363c3a76abe (patch)
tree1dff0e74dbc06858715e1441c2b60a799c8d8aeb /src/test
parent4068b152e530305f588bd56e753045936e87ede0 (diff)
downloadgitblit-d1ee233d27fae23b1d0a69bbb6b9a363c3a76abe.tar.gz
gitblit-d1ee233d27fae23b1d0a69bbb6b9a363c3a76abe.zip
Add support for PBKDF2 to PasswordHash
Integrate the work of pingunaut to add support for PBKDF2 password hashing. A new class `PasswordHashPbkdf2` is added, which builds on his `SecurePasswordHashUtils` class, but makes it a subclass of `PasswordHash`. This will replace the original class when integrating the new PasswordHash way into GitBlit.
Diffstat (limited to 'src/test')
-rw-r--r--src/test/java/com/gitblit/utils/PasswordHashTest.java186
1 files changed, 181 insertions, 5 deletions
diff --git a/src/test/java/com/gitblit/utils/PasswordHashTest.java b/src/test/java/com/gitblit/utils/PasswordHashTest.java
index 12686692..c5a485dc 100644
--- a/src/test/java/com/gitblit/utils/PasswordHashTest.java
+++ b/src/test/java/com/gitblit/utils/PasswordHashTest.java
@@ -36,6 +36,15 @@ public class PasswordHashTest {
static final String CMD5_USERNAME_1 = "Joe Black";
static final String CMD5_PASSWORD_1 = "ThisIsAWeirdScheme.Weird";
static final String CMD5_HASHED_ENTRY_1 = "cmd5:5c154768287e32fa605656b98894da89";
+ static final String PBKDF2_PASSWORD_0 = "password";
+ static final String PBKDF2_HASHED_ENTRY_0 = "PBKDF2:70617373776f726450415353574f524470617373776f726450415353574f52440f17d16621b32ae1bb2b1041fcb19e294b35d514d361c08eed385766e38f6f3a";
+ static final String PBKDF2_PASSWORD_1 = "A REALLY better scheme than MD5";
+ static final String PBKDF2_HASHED_ENTRY_1 = "PBKDF2:$0$46726573682066726f6d207468652053414c54206d696e65206f6620446f6f6de8e50b035679b25ce8b6ab41440938b7b1f97fc0c797fcf59302c2916f6c8fef";
+ static final String PBKDF2_PASSWORD_2 = "passwordPASSWORDpassword";
+ static final String PBKDF2_HASHED_ENTRY_2 = "pbkdf2:$0$73616c7453414c5473616c7453414c5473616c7453414c5473616c7453414c54560d0f02b565e37695da15141044506d54cb633a5a70b41c574069ea50a1247a";
+ static final String PBKDF2_PASSWORD_3 = "foo";
+ static final String PBKDF2_HASHED_ENTRY_3 = "PBKDF2WITHHMACSHA256:2d7d3ccaa277787f288e9f929247361bfc83607c6a8447bf496267512e360ba0a97b3114937213b23230072517d65a2e00695a1cbc47a732510840817f22c1bc";
+
/**
@@ -98,6 +107,32 @@ public class PasswordHashTest {
+ /**
+ * Test method for {@link com.gitblit.utils.PasswordHash#instanceOf(java.lang.String)} for PBKDF2.
+ */
+ @Test
+ public void testInstanceOfPBKDF2() {
+ PasswordHash pwdh = PasswordHash.instanceOf("PBKDF2");
+ assertNotNull(pwdh);
+ assertEquals(PasswordHash.Type.PBKDF2, pwdh.type);
+ assertTrue("Failed to match " +PBKDF2_HASHED_ENTRY_0, pwdh.matches(PBKDF2_HASHED_ENTRY_0, PBKDF2_PASSWORD_0.toCharArray(), null));
+
+ pwdh = PasswordHash.instanceOf("pbkdf2");
+ assertNotNull(pwdh);
+ assertEquals(PasswordHash.Type.PBKDF2, pwdh.type);
+ assertTrue("Failed to match " +PBKDF2_HASHED_ENTRY_1, pwdh.matches(PBKDF2_HASHED_ENTRY_1, PBKDF2_PASSWORD_1.toCharArray(), null));
+
+ pwdh = PasswordHash.instanceOf("pbKDF2");
+ assertNotNull(pwdh);
+ assertEquals(PasswordHash.Type.PBKDF2, pwdh.type);
+ assertTrue("Failed to match " +PBKDF2_HASHED_ENTRY_1, pwdh.matches(PBKDF2_HASHED_ENTRY_1, PBKDF2_PASSWORD_1.toCharArray(), null));
+
+
+ pwdh = PasswordHash.instanceOf("md5");
+ assertNotNull(pwdh);
+ assertNotEquals(PasswordHash.Type.PBKDF2, pwdh.type);
+ assertFalse("Failed to match " +PBKDF2_HASHED_ENTRY_1, pwdh.matches(PBKDF2_HASHED_ENTRY_1, PBKDF2_PASSWORD_1.toCharArray(), null));
+ }
@@ -165,6 +200,20 @@ public class PasswordHashTest {
assertTrue("Failed to match " +CMD5_HASHED_ENTRY_1, pwdh.matches(CMD5_HASHED_ENTRY_1, CMD5_PASSWORD_1.toCharArray(), CMD5_USERNAME_1));
+ pwdh = PasswordHash.instanceFor(PBKDF2_HASHED_ENTRY_0);
+ assertNotNull(pwdh);
+ assertEquals(PasswordHash.Type.PBKDF2, pwdh.type);
+ assertTrue("Failed to match " +PBKDF2_HASHED_ENTRY_0, pwdh.matches(PBKDF2_HASHED_ENTRY_0, PBKDF2_PASSWORD_0.toCharArray(), null));
+
+ pwdh = PasswordHash.instanceFor(PBKDF2_HASHED_ENTRY_1);
+ assertNotNull(pwdh);
+ assertEquals(PasswordHash.Type.PBKDF2, pwdh.type);
+ assertTrue("Failed to match " +PBKDF2_HASHED_ENTRY_1, pwdh.matches(PBKDF2_HASHED_ENTRY_1, PBKDF2_PASSWORD_1.toCharArray(), null));
+
+ pwdh = PasswordHash.instanceFor(PBKDF2_HASHED_ENTRY_3);
+ assertNotNull(pwdh);
+ assertEquals(PasswordHash.Type.PBKDF2, pwdh.type);
+ assertTrue("Failed to match " +PBKDF2_HASHED_ENTRY_3, pwdh.matches(PBKDF2_HASHED_ENTRY_3, PBKDF2_PASSWORD_3.toCharArray(), null));
}
/**
@@ -210,6 +259,10 @@ public class PasswordHashTest {
assertTrue(MD5_HASHED_ENTRY_1, PasswordHash.isHashedEntry(MD5_HASHED_ENTRY_1));
assertTrue(CMD5_HASHED_ENTRY_0, PasswordHash.isHashedEntry(CMD5_HASHED_ENTRY_0));
assertTrue(CMD5_HASHED_ENTRY_1, PasswordHash.isHashedEntry(CMD5_HASHED_ENTRY_1));
+ assertTrue(PBKDF2_HASHED_ENTRY_0, PasswordHash.isHashedEntry(PBKDF2_HASHED_ENTRY_0));
+ assertTrue(PBKDF2_HASHED_ENTRY_1, PasswordHash.isHashedEntry(PBKDF2_HASHED_ENTRY_1));
+ assertTrue(PBKDF2_HASHED_ENTRY_2, PasswordHash.isHashedEntry(PBKDF2_HASHED_ENTRY_2));
+ assertTrue(PBKDF2_HASHED_ENTRY_3, PasswordHash.isHashedEntry(PBKDF2_HASHED_ENTRY_3));
assertFalse(MD5_PASSWORD_1, PasswordHash.isHashedEntry(MD5_PASSWORD_1));
assertFalse("topsecret", PasswordHash.isHashedEntry("topsecret"));
@@ -228,6 +281,8 @@ public class PasswordHashTest {
public void testIsHashedEntryCaseInsenitive() {
assertTrue(MD5_HASHED_ENTRY_1.toLowerCase(), PasswordHash.isHashedEntry(MD5_HASHED_ENTRY_1.toLowerCase()));
assertTrue(CMD5_HASHED_ENTRY_1.toLowerCase(), PasswordHash.isHashedEntry(CMD5_HASHED_ENTRY_1.toLowerCase()));
+ assertTrue(PBKDF2_HASHED_ENTRY_1.toLowerCase(), PasswordHash.isHashedEntry(PBKDF2_HASHED_ENTRY_1.toLowerCase()));
+ assertTrue(PBKDF2_HASHED_ENTRY_3.toLowerCase(), PasswordHash.isHashedEntry(PBKDF2_HASHED_ENTRY_3.toLowerCase()));
}
/**
@@ -248,7 +303,7 @@ public class PasswordHashTest {
* Test creating a hashed entry for scheme MD5. In this scheme there is no salt, so a direct
* comparison to a constant value is possible.
*
- * Test method for {@link com.gitblit.utils.PasswordHash#toHashedEntry(String, String)} for MD5.
+ * Test method for {@link PasswordHash#toHashedEntry(String, String)} for MD5.
*/
@Test
public void testToHashedEntryMD5() {
@@ -269,7 +324,7 @@ public class PasswordHashTest {
@Test(expected = IllegalArgumentException.class)
public void testToHashedEntryMD5NullPassword() {
PasswordHash pwdh = PasswordHash.instanceOf("MD5");
- pwdh.toHashedEntry(null, null);
+ pwdh.toHashedEntry((String)null, null);
}
@@ -277,7 +332,7 @@ public class PasswordHashTest {
* Test creating a hashed entry for scheme Combined-MD5. In this scheme there is no salt, so a direct
* comparison to a constant value is possible.
*
- * Test method for {@link com.gitblit.utils.PasswordHash#toHashedEntry(String, String)} for CMD5.
+ * Test method for {@link PasswordHash#toHashedEntry(String, String)} for CMD5.
*/
@Test
public void testToHashedEntryCMD5() {
@@ -295,14 +350,14 @@ public class PasswordHashTest {
@Test(expected = IllegalArgumentException.class)
public void testToHashedEntryCMD5NullPassword() {
PasswordHash pwdh = PasswordHash.instanceOf("CMD5");
- pwdh.toHashedEntry(null, CMD5_USERNAME_1);
+ pwdh.toHashedEntry((String)null, CMD5_USERNAME_1);
}
/**
* Test creating a hashed entry for scheme Combined-MD5, when no user is given.
* This should never happen in the application, so we expect an exception to be thrown.
*
- * Test method for {@link com.gitblit.utils.PasswordHash#toHashedEntry(String, String)} for broken CMD5.
+ * Test method for {@link PasswordHash#toHashedEntry(String, String)} for broken CMD5.
*/
@Test
public void testToHashedEntryCMD5NoUsername() {
@@ -332,7 +387,40 @@ public class PasswordHashTest {
catch (IllegalArgumentException ignored) { /*success*/ }
}
+ /**
+ * Test creating a hashed entry for scheme PBKDF2.
+ * Since this scheme uses a salt, we test by running a match. This is a bit backwards,
+ * but recreating the PBKDF2 here seems a little overkill.
+ *
+ * Test method for {@link PasswordHash#toHashedEntry(String, String)} for PBKDF2.
+ */
+ @Test
+ public void testToHashedEntryPBKDF2() {
+ PasswordHash pwdh = PasswordHash.instanceOf("PBKDF2");
+ String hashedEntry = pwdh.toHashedEntry(PBKDF2_PASSWORD_1, null);
+ assertTrue("Type identifier is incorrect.", hashedEntry.startsWith(PasswordHash.Type.PBKDF2.name()));
+ PasswordHash pwdhverify = PasswordHash.instanceFor(hashedEntry);
+ assertNotNull(pwdhverify);
+ assertTrue(PBKDF2_PASSWORD_1, pwdhverify.matches(hashedEntry, PBKDF2_PASSWORD_1.toCharArray(), null));
+
+ hashedEntry = pwdh.toHashedEntry(PBKDF2_PASSWORD_2, "");
+ assertTrue("Type identifier is incorrect.", hashedEntry.startsWith(PasswordHash.Type.PBKDF2.name()));
+ pwdhverify = PasswordHash.instanceFor(hashedEntry);
+ assertNotNull(pwdhverify);
+ assertTrue(PBKDF2_PASSWORD_2, pwdhverify.matches(hashedEntry, PBKDF2_PASSWORD_2.toCharArray(), null));
+
+ hashedEntry = pwdh.toHashedEntry(PBKDF2_PASSWORD_0, "alpha");
+ assertTrue("Type identifier is incorrect.", hashedEntry.startsWith(PasswordHash.Type.PBKDF2.name()));
+ pwdhverify = PasswordHash.instanceFor(hashedEntry);
+ assertNotNull(pwdhverify);
+ assertTrue(PBKDF2_PASSWORD_0, pwdhverify.matches(hashedEntry, PBKDF2_PASSWORD_0.toCharArray(), null));
+ }
+ @Test(expected = IllegalArgumentException.class)
+ public void testToHashedEntryPBKDF2NullPassword() {
+ PasswordHash pwdh = PasswordHash.instanceOf("PBKDF2");
+ pwdh.toHashedEntry((String)null, null);
+ }
/**
@@ -379,6 +467,7 @@ public class PasswordHashTest {
assertFalse("Matched wrong scheme", pwdh.matches(CMD5_HASHED_ENTRY_0, MD5_PASSWORD_0.toCharArray(), null));
+ assertFalse("Matched wrong scheme", pwdh.matches(PBKDF2_HASHED_ENTRY_0, MD5_PASSWORD_0.toCharArray(), ""));
assertFalse("Matched wrong scheme", pwdh.matches(CMD5_HASHED_ENTRY_0, CMD5_PASSWORD_0.toCharArray(), CMD5_USERNAME_0));
}
@@ -414,7 +503,94 @@ public class PasswordHashTest {
assertFalse("Matched wrong scheme", pwdh.matches(MD5_HASHED_ENTRY_0, CMD5_PASSWORD_0.toCharArray(), null));
+ assertFalse("Matched wrong scheme", pwdh.matches(PBKDF2_HASHED_ENTRY_0, CMD5_PASSWORD_0.toCharArray(), ""));
assertFalse("Matched wrong scheme", pwdh.matches(MD5_HASHED_ENTRY_0, CMD5_PASSWORD_0.toCharArray(), CMD5_USERNAME_0));
assertFalse("Matched wrong scheme", pwdh.matches(MD5_HASHED_ENTRY_0, MD5_PASSWORD_0.toCharArray(), CMD5_USERNAME_0));
}
+
+
+
+ /**
+ * Test method for {@link com.gitblit.utils.PasswordHash#matches(String, char[], String)} for PBKDF2.
+ */
+ @Test
+ public void testMatchesPBKDF2() {
+ PasswordHash pwdh = PasswordHash.instanceOf("PBKDF2");
+
+ assertTrue("PWD0, Null user", pwdh.matches(PBKDF2_HASHED_ENTRY_0, PBKDF2_PASSWORD_0.toCharArray(), null));
+ assertTrue("PWD0, Empty user", pwdh.matches(PBKDF2_HASHED_ENTRY_0, PBKDF2_PASSWORD_0.toCharArray(), ""));
+ assertTrue("PWD0, With user", pwdh.matches(PBKDF2_HASHED_ENTRY_0, PBKDF2_PASSWORD_0.toCharArray(), "maxine"));
+
+ assertTrue("PWD1, Null user", pwdh.matches(PBKDF2_HASHED_ENTRY_1, PBKDF2_PASSWORD_1.toCharArray(), null));
+ assertTrue("PWD1, Empty user", pwdh.matches(PBKDF2_HASHED_ENTRY_1, PBKDF2_PASSWORD_1.toCharArray(), ""));
+ assertTrue("PWD1, With user", pwdh.matches(PBKDF2_HASHED_ENTRY_1, PBKDF2_PASSWORD_1.toCharArray(), "Maxim Gorki"));
+
+ assertTrue("PWD2, Null user", pwdh.matches(PBKDF2_HASHED_ENTRY_2, PBKDF2_PASSWORD_2.toCharArray(), null));
+ assertTrue("PWD2, Empty user", pwdh.matches(PBKDF2_HASHED_ENTRY_2, PBKDF2_PASSWORD_2.toCharArray(), ""));
+ assertTrue("PWD2, With user", pwdh.matches(PBKDF2_HASHED_ENTRY_2, PBKDF2_PASSWORD_2.toCharArray(), "Epson"));
+
+
+
+ assertFalse("Matched wrong password", pwdh.matches(PBKDF2_HASHED_ENTRY_1, "wrongpassword".toCharArray(), null));
+ assertFalse("Matched wrong password, with empty user", pwdh.matches(PBKDF2_HASHED_ENTRY_1, "wrongpassword".toCharArray(), " "));
+ assertFalse("Matched wrong password, with user", pwdh.matches(PBKDF2_HASHED_ENTRY_1, "wrongpassword".toCharArray(), "someuser"));
+
+ assertFalse("Matched empty password", pwdh.matches(PBKDF2_HASHED_ENTRY_2, "".toCharArray(), null));
+ assertFalse("Matched empty password, with empty user", pwdh.matches(PBKDF2_HASHED_ENTRY_2, " ".toCharArray(), " "));
+ assertFalse("Matched empty password, with user", pwdh.matches(PBKDF2_HASHED_ENTRY_2, " ".toCharArray(), "someuser"));
+
+ assertFalse("Matched null password", pwdh.matches(PBKDF2_HASHED_ENTRY_0, null, null));
+ assertFalse("Matched null password, with empty user", pwdh.matches(PBKDF2_HASHED_ENTRY_0, null, " "));
+ assertFalse("Matched null password, with user", pwdh.matches(PBKDF2_HASHED_ENTRY_0, null, "someuser"));
+
+
+ assertFalse("Matched wrong hashed entry", pwdh.matches(PBKDF2_HASHED_ENTRY_1, PBKDF2_PASSWORD_0.toCharArray(), null));
+ assertFalse("Matched wrong hashed entry, with empty user", pwdh.matches(PBKDF2_HASHED_ENTRY_1, PBKDF2_PASSWORD_0.toCharArray(), ""));
+ assertFalse("Matched wrong hashed entry, with user", pwdh.matches(PBKDF2_HASHED_ENTRY_1, PBKDF2_PASSWORD_0.toCharArray(), "someuser"));
+
+ assertFalse("Matched empty hashed entry", pwdh.matches("", PBKDF2_PASSWORD_0.toCharArray(), null));
+ assertFalse("Matched empty hashed entry, with empty user", pwdh.matches(" ", PBKDF2_PASSWORD_0.toCharArray(), ""));
+ assertFalse("Matched empty hashed entry, with user", pwdh.matches(" ", PBKDF2_PASSWORD_0.toCharArray(), "someuser"));
+
+ assertFalse("Matched null entry", pwdh.matches(null, PBKDF2_PASSWORD_0.toCharArray(), null));
+ assertFalse("Matched null entry, with empty user", pwdh.matches(null, PBKDF2_PASSWORD_0.toCharArray(), ""));
+ assertFalse("Matched null entry, with user", pwdh.matches(null, PBKDF2_PASSWORD_0.toCharArray(), "someuser"));
+
+
+ assertFalse("Matched wrong scheme", pwdh.matches(CMD5_HASHED_ENTRY_0, PBKDF2_PASSWORD_0.toCharArray(), null));
+ assertFalse("Matched wrong scheme", pwdh.matches(MD5_HASHED_ENTRY_0, PBKDF2_PASSWORD_0.toCharArray(), ""));
+ assertFalse("Matched wrong scheme", pwdh.matches(CMD5_HASHED_ENTRY_0, PBKDF2_PASSWORD_0.toCharArray(), CMD5_USERNAME_0));
+ }
+
+
+ /**
+ * Test method for {@link com.gitblit.utils.PasswordHash#matches(String, char[], String)}
+ * for old existing entries with the "PBKDF2WITHHMACSHA256" type identifier.
+ */
+ @Test
+ public void testMatchesPBKDF2Compat() {
+ PasswordHash pwdh = PasswordHash.instanceOf("PBKDF2");
+
+ assertTrue("PWD3, Null user", pwdh.matches(PBKDF2_HASHED_ENTRY_3, PBKDF2_PASSWORD_3.toCharArray(), null));
+ assertTrue("PWD3, Empty user", pwdh.matches(PBKDF2_HASHED_ENTRY_3, PBKDF2_PASSWORD_3.toCharArray(), ""));
+ assertTrue("PWD3, With user", pwdh.matches(PBKDF2_HASHED_ENTRY_3, PBKDF2_PASSWORD_3.toCharArray(), "maxine"));
+
+
+ assertFalse("Matched wrong password", pwdh.matches(PBKDF2_HASHED_ENTRY_3, "bar".toCharArray(), null));
+ assertFalse("Matched wrong password, with empty user", pwdh.matches(PBKDF2_HASHED_ENTRY_3, "bar".toCharArray(), " "));
+ assertFalse("Matched wrong password, with user", pwdh.matches(PBKDF2_HASHED_ENTRY_3, "bar".toCharArray(), "someuser"));
+
+ assertFalse("Matched empty password", pwdh.matches(PBKDF2_HASHED_ENTRY_3, "".toCharArray(), null));
+ assertFalse("Matched empty password, with empty user", pwdh.matches(PBKDF2_HASHED_ENTRY_3, " ".toCharArray(), " "));
+ assertFalse("Matched empty password, with user", pwdh.matches(PBKDF2_HASHED_ENTRY_3, " ".toCharArray(), "someuser"));
+
+ assertFalse("Matched null password", pwdh.matches(PBKDF2_HASHED_ENTRY_3, null, null));
+ assertFalse("Matched null password, with empty user", pwdh.matches(PBKDF2_HASHED_ENTRY_3, null, " "));
+ assertFalse("Matched null password, with user", pwdh.matches(PBKDF2_HASHED_ENTRY_3, null, "someuser"));
+
+
+ assertFalse("Matched wrong hashed entry", pwdh.matches(PBKDF2_HASHED_ENTRY_3, PBKDF2_PASSWORD_0.toCharArray(), null));
+ assertFalse("Matched wrong hashed entry, with empty user", pwdh.matches(PBKDF2_HASHED_ENTRY_3, PBKDF2_PASSWORD_0.toCharArray(), ""));
+ assertFalse("Matched wrong hashed entry, with user", pwdh.matches(PBKDF2_HASHED_ENTRY_3, PBKDF2_PASSWORD_0.toCharArray(), "someuser"));
+ }
}