From b63ceb54bb494700b27e493c7486be7641d4ac54 Mon Sep 17 00:00:00 2001
From: Ludovic Poitou <ludovic.poitou@forgerock.com>
Date: Tue, 09 Feb 2016 13:54:57 +0000
Subject: [PATCH] Added BCrypt unit test (port of the original JUnit tests to testNG).

---
 opendj-server-legacy/src/test/java/org/opends/server/extensions/BCryptTest.java |  225 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 225 insertions(+), 0 deletions(-)

diff --git a/opendj-server-legacy/src/test/java/org/opends/server/extensions/BCryptTest.java b/opendj-server-legacy/src/test/java/org/opends/server/extensions/BCryptTest.java
new file mode 100644
index 0000000..32c7c6f
--- /dev/null
+++ b/opendj-server-legacy/src/test/java/org/opends/server/extensions/BCryptTest.java
@@ -0,0 +1,225 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright (c) 2006 Damien Miller <djm@mindrot.org>
+ *      Portions Copyright 2016 ForgeRock AS
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+package org.opends.server.extensions;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.*;
+
+public class BCryptTest extends ExtensionsTestCase {
+
+    /**
+     * Retrieves a set of passwords, salt and expected hashed passwords for tests.
+     */
+    @DataProvider(name = "PasswordsAndHash")
+    public Object[][] getPasswordsAndHash() {
+        return new Object[][]{
+                { "", "$2a$06$DCq7YPn5Rq63x1Lad4cll.",
+                        "$2a$06$DCq7YPn5Rq63x1Lad4cll.TV4S6ytwfsfvkgY8jIucDrjc8deX1s." },
+                { "", "$2a$08$HqWuK6/Ng6sg9gQzbLrgb.",
+                        "$2a$08$HqWuK6/Ng6sg9gQzbLrgb.Tl.ZHfXLhvt/SgVyWhQqgqcZ7ZuUtye" },
+                { "", "$2a$10$k1wbIrmNyFAPwPVPSVa/ze",
+                        "$2a$10$k1wbIrmNyFAPwPVPSVa/zecw2BCEnBwVS2GbrmgzxFUOqW9dk4TCW" },
+                { "", "$2a$12$k42ZFHFWqBp3vWli.nIn8u",
+                        "$2a$12$k42ZFHFWqBp3vWli.nIn8uYyIkbvYRvodzbfbK18SSsY.CsIQPlxO" },
+                { "a", "$2a$06$m0CrhHm10qJ3lXRY.5zDGO",
+                        "$2a$06$m0CrhHm10qJ3lXRY.5zDGO3rS2KdeeWLuGmsfGlMfOxih58VYVfxe" },
+                { "a", "$2a$08$cfcvVd2aQ8CMvoMpP2EBfe",
+                        "$2a$08$cfcvVd2aQ8CMvoMpP2EBfeodLEkkFJ9umNEfPD18.hUF62qqlC/V." },
+                { "a", "$2a$10$k87L/MF28Q673VKh8/cPi.",
+                        "$2a$10$k87L/MF28Q673VKh8/cPi.SUl7MU/rWuSiIDDFayrKk/1tBsSQu4u" },
+                { "a", "$2a$12$8NJH3LsPrANStV6XtBakCe",
+                        "$2a$12$8NJH3LsPrANStV6XtBakCez0cKHXVxmvxIlcz785vxAIZrihHZpeS" },
+                { "abc", "$2a$06$If6bvum7DFjUnE9p2uDeDu",
+                        "$2a$06$If6bvum7DFjUnE9p2uDeDu0YHzrHM6tf.iqN8.yx.jNN1ILEf7h0i" },
+                { "abc", "$2a$08$Ro0CUfOqk6cXEKf3dyaM7O",
+                        "$2a$08$Ro0CUfOqk6cXEKf3dyaM7OhSCvnwM9s4wIX9JeLapehKK5YdLxKcm" },
+                { "abc", "$2a$10$WvvTPHKwdBJ3uk0Z37EMR.",
+                        "$2a$10$WvvTPHKwdBJ3uk0Z37EMR.hLA2W6N9AEBhEgrAOljy2Ae5MtaSIUi" },
+                { "abc", "$2a$12$EXRkfkdmXn2gzds2SSitu.",
+                        "$2a$12$EXRkfkdmXn2gzds2SSitu.MW9.gAVqa9eLS1//RYtYCmB1eLHg.9q" },
+                { "abcdefghijklmnopqrstuvwxyz", "$2a$06$.rCVZVOThsIa97pEDOxvGu",
+                        "$2a$06$.rCVZVOThsIa97pEDOxvGuRRgzG64bvtJ0938xuqzv18d3ZpQhstC" },
+                { "abcdefghijklmnopqrstuvwxyz", "$2a$08$aTsUwsyowQuzRrDqFflhge",
+                        "$2a$08$aTsUwsyowQuzRrDqFflhgekJ8d9/7Z3GV3UcgvzQW3J5zMyrTvlz." },
+                { "abcdefghijklmnopqrstuvwxyz", "$2a$10$fVH8e28OQRj9tqiDXs1e1u",
+                        "$2a$10$fVH8e28OQRj9tqiDXs1e1uxpsjN0c7II7YPKXua2NAKYvM6iQk7dq" },
+                { "abcdefghijklmnopqrstuvwxyz", "$2a$12$D4G5f18o7aMMfwasBL7Gpu",
+                        "$2a$12$D4G5f18o7aMMfwasBL7GpuQWuP3pkrZrOAnqP.bmezbMng.QwJ/pG" },
+                { "~!@#$%^&*()      ~!@#$%^&*()PNBFRD", "$2a$06$fPIsBO8qRqkjj273rfaOI.",
+                        "$2a$06$fPIsBO8qRqkjj273rfaOI.HtSV9jLDpTbZn782DC6/t7qT67P6FfO" },
+                { "~!@#$%^&*()      ~!@#$%^&*()PNBFRD", "$2a$08$Eq2r4G/76Wv39MzSX262hu",
+                        "$2a$08$Eq2r4G/76Wv39MzSX262huzPz612MZiYHVUJe/OcOql2jo4.9UxTW" },
+                { "~!@#$%^&*()      ~!@#$%^&*()PNBFRD", "$2a$10$LgfYWkbzEvQ4JakH7rOvHe",
+                        "$2a$10$LgfYWkbzEvQ4JakH7rOvHe0y8pHKF9OaFgwUZ2q7W2FFZmZzJYlfS" },
+                { "~!@#$%^&*()      ~!@#$%^&*()PNBFRD", "$2a$12$WApznUOJfkEGSmYRfnkrPO",
+                        "$2a$12$WApznUOJfkEGSmYRfnkrPOr466oFDCaj4b6HY3EXGvfxm43seyhgC" }
+        };
+    }
+
+    /**
+     * Retrieves a set of passwords for tests.
+     */
+    @DataProvider(name = "Passwords")
+    public Object[][] getPasswords() {
+        return new Object[][]{
+                {""},
+                {"a"},
+                {"abc"},
+                {"abcdefghijklmnopqrstuvwxyz"},
+                {"~!@#$%^&*()      ~!@#$%^&*()PNBFRD"}
+        };
+    }
+
+    /**
+     * Retrieves a pair of password and hashed passwords that don't match
+     */
+    @DataProvider(name = "BadPasswords")
+    public Object[][] getBadPasswords() {
+        return new Object[][]{
+                { "", "$2a$06$m0CrhHm10qJ3lXRY.5zDGO3rS2KdeeWLuGmsfGlMfOxih58VYVfxe" },
+                { "a", "$2a$06$If6bvum7DFjUnE9p2uDeDu0YHzrHM6tf.iqN8.yx.jNN1ILEf7h0i" },
+                { "abc", "$2a$06$.rCVZVOThsIa97pEDOxvGuRRgzG64bvtJ0938xuqzv18d3ZpQhstC" },
+                { "abcdefghijklmnopqrstuvwxyz", "$2a$06$fPIsBO8qRqkjj273rfaOI.HtSV9jLDpTbZn782DC6/t7qT67P6FfO" },
+                { "~!@#$%^&*()      ~!@#$%^&*()PNBFRD", "$2a$06$DCq7YPn5Rq63x1Lad4cll.TV4S6ytwfsfvkgY8jIucDrjc8deX1s." }
+        };
+    }
+
+
+    /**
+     * Test for BCrypt.hashpw(String, String).
+     *
+     * @param plain The plain text password.
+     * @param salt  The salt to use when hashing the password.
+     * @param expected The expected hashed password.
+     *
+     */
+    @Test(dataProvider = "PasswordsAndHash")
+    public void hashpw(String plain, String salt, String expected) {
+        String hashed = BCrypt.hashpw(plain, salt);
+        assertEquals(hashed, expected);
+    }
+
+    /**
+     * Test for the BCrypt.hashpw(byte[], String) method.
+     *
+     * @param plain The plain text password.
+     * @param salt  The salt to use when hashing the password.
+     * @param expected The expected hashed password.
+     *
+     */
+    @Test(dataProvider = "PasswordsAndHash")
+    public void hashpwBytes(String plain, String salt, String expected) {
+        String hashed = BCrypt.hashpw(plain.getBytes(), salt);
+        assertEquals(hashed, expected);
+    }
+
+    /**
+     * Test for the BCrypt.genSalt(int) method, with a cost varying from 4 to 12.
+     *
+     * @param plain The plain text password.
+     *
+     */
+    @Test(dataProvider = "Passwords")
+    public void genSaltInt(String plain) {
+        for (int i = 4; i <= 12; i++){
+            String salt = BCrypt.gensalt(i);
+            String hashed1 = BCrypt.hashpw(plain, salt);
+            String hashed2 = BCrypt.hashpw(plain, hashed1);
+            assertEquals(hashed1, hashed2);
+        }
+    }
+
+    /**
+     * Tests the BCrypt.genSalt method with default cost
+     *
+     * @param plain The plain text password.
+     *
+     */
+    @Test(dataProvider = "Passwords")
+    public void genSalt(String plain) {
+        String salt = BCrypt.gensalt();
+        String hashed1 = BCrypt.hashpw(plain, salt);
+        String hashed2 = BCrypt.hashpw(plain, hashed1);
+        assertEquals(hashed1, hashed2);
+    }
+
+    /**
+     * Test for the BCrypt.checkpw(String, String) method.
+     *
+     * @param plain The plain text password.
+     * @param salt  The salt to use when hashing the password.
+     * @param expected The expected hashed password.
+     *
+     */
+    @Test(dataProvider = "PasswordsAndHash")
+    public void checkPw(String plain, String salt, String expected) {
+        assertTrue(BCrypt.checkpw(plain, expected));
+    }
+
+    /**
+     * Test for the BCrypt.checkpw(String, String) method, expecting failures.
+     *
+     * @param plain The plain text password.
+     * @param hashedValue A hashed password that doesn't match the plain text password.
+     *
+     */
+    @Test(dataProvider = "BadPasswords")
+    public void checkPw_Failure(String plain, String hashedValue) {
+        assertFalse(BCrypt.checkpw(plain, hashedValue));
+    }
+
+    /**
+     *     Test for correct hashing of non-US-ASCII passwords.
+     */
+    @Test
+    public void testInternationalChars() {
+        String pw1 = "\u2605\u2605\u2605\u2605\u2605\u2605\u2605\u2605";
+        String pw2 = "????????";
+
+        String h1 = BCrypt.hashpw(pw1, BCrypt.gensalt());
+        assertFalse(BCrypt.checkpw(pw2, h1));
+
+        String h2 = BCrypt.hashpw(pw2, BCrypt.gensalt());
+        assertFalse(BCrypt.checkpw(pw1, h2));
+    }
+}

--
Gitblit v1.10.0