Password-Hash-Class added
authorMichael <Michael@Michael-LT.bfh.ch>
Wed, 21 Oct 2015 08:54:21 +0000 (10:54 +0200)
committerMichael <Michael@Michael-LT.bfh.ch>
Wed, 21 Oct 2015 08:54:48 +0000 (10:54 +0200)
UserTest-Class added

.classpath
src/main/java/ch/bfh/ti/srs/core/Password.java [new file with mode: 0644]
src/test/java/ch/bfh/ti/srs/core/UserTest.java [new file with mode: 0644]

index af1430b..73d0ecb 100644 (file)
@@ -1,26 +1,27 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-       <classpathentry kind="src" output="target/classes" path="src/main/java">
-               <attributes>
-                       <attribute name="optional" value="true"/>
-                       <attribute name="maven.pomderived" value="true"/>
-               </attributes>
-       </classpathentry>
-       <classpathentry kind="src" output="target/test-classes" path="src/test/java">
-               <attributes>
-                       <attribute name="optional" value="true"/>
-                       <attribute name="maven.pomderived" value="true"/>
-               </attributes>
-       </classpathentry>
-       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
-               <attributes>
-                       <attribute name="maven.pomderived" value="true"/>
-               </attributes>
-       </classpathentry>
-       <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
-               <attributes>
-                       <attribute name="maven.pomderived" value="true"/>
-               </attributes>
-       </classpathentry>
-       <classpathentry kind="output" path="target/classes"/>
-</classpath>
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+       <classpathentry kind="src" output="target/classes" path="src/main/java">\r
+               <attributes>\r
+                       <attribute name="optional" value="true"/>\r
+                       <attribute name="maven.pomderived" value="true"/>\r
+               </attributes>\r
+       </classpathentry>\r
+       <classpathentry kind="src" output="target/test-classes" path="src/test/java">\r
+               <attributes>\r
+                       <attribute name="optional" value="true"/>\r
+                       <attribute name="maven.pomderived" value="true"/>\r
+               </attributes>\r
+       </classpathentry>\r
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">\r
+               <attributes>\r
+                       <attribute name="maven.pomderived" value="true"/>\r
+               </attributes>\r
+       </classpathentry>\r
+       <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">\r
+               <attributes>\r
+                       <attribute name="maven.pomderived" value="true"/>\r
+               </attributes>\r
+       </classpathentry>\r
+       <classpathentry kind="lib" path="C:/Users/Michael/Downloads/commons-codec-1.10/commons-codec-1.10/commons-codec-1.10.jar"/>\r
+       <classpathentry kind="output" path="target/classes"/>\r
+</classpath>\r
diff --git a/src/main/java/ch/bfh/ti/srs/core/Password.java b/src/main/java/ch/bfh/ti/srs/core/Password.java
new file mode 100644 (file)
index 0000000..a097cf8
--- /dev/null
@@ -0,0 +1,49 @@
+package ch.bfh.ti.srs.core;\r
+\r
+import javax.crypto.SecretKey;\r
+import javax.crypto.SecretKeyFactory;\r
+import javax.crypto.spec.PBEKeySpec;\r
+import java.security.SecureRandom;\r
+import org.apache.commons.codec.binary.Base64;\r
+\r
+public class Password {\r
+    // The higher the number of iterations the more \r
+    // expensive computing the hash is for us and\r
+    // also for an attacker.\r
+    private static final int iterations = 20*1000;\r
+    private static final int saltLen = 32;\r
+    private static final int desiredKeyLen = 256;\r
+\r
+    /** Computes a salted PBKDF2 hash of given plaintext password\r
+        suitable for storing in a database. \r
+        Empty passwords are not supported. */\r
+    public static String getSaltedHash(String password) throws Exception {\r
+        byte[] salt = SecureRandom.getInstance("SHA1PRNG").generateSeed(saltLen);\r
+        // store the salt with the password\r
+        return Base64.encodeBase64String(salt) + "$" + hash(password, salt);\r
+    }\r
+\r
+    /** Checks whether given plaintext password corresponds \r
+        to a stored salted hash of the password. */\r
+    public static boolean check(String password, String stored) throws Exception{\r
+        String[] saltAndPass = stored.split("\\$");\r
+        if (saltAndPass.length != 2) {\r
+            throw new IllegalStateException(\r
+                "The stored password have the form 'salt$hash'");\r
+        }\r
+        String hashOfInput = hash(password, Base64.decodeBase64(saltAndPass[0]));\r
+        return hashOfInput.equals(saltAndPass[1]);\r
+    }\r
+\r
+    // using PBKDF2 from Sun, an alternative is https://github.com/wg/scrypt\r
+    // cf. http://www.unlimitednovelty.com/2012/03/dont-use-bcrypt.html\r
+    private static String hash(String password, byte[] salt) throws Exception {\r
+        if (password == null || password.length() == 0)\r
+            throw new IllegalArgumentException("Empty passwords are not supported.");\r
+        SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");\r
+        SecretKey key = f.generateSecret(new PBEKeySpec(\r
+            password.toCharArray(), salt, iterations, desiredKeyLen)\r
+        );\r
+        return Base64.encodeBase64String(key.getEncoded());\r
+    }\r
+}\r
diff --git a/src/test/java/ch/bfh/ti/srs/core/UserTest.java b/src/test/java/ch/bfh/ti/srs/core/UserTest.java
new file mode 100644 (file)
index 0000000..caf2ed8
--- /dev/null
@@ -0,0 +1,38 @@
+/*\r
+ * Copyright (c) 2015 Berner Fachhochschule, Switzerland.\r
+ *\r
+ * Project Smart Reservation System.\r
+ *\r
+ * Distributable under GPL license. See terms of license at gnu.org.\r
+ */\r
+package ch.bfh.ti.srs.core;\r
+\r
+import static org.junit.Assert.*;\r
+\r
+import java.util.Set;\r
+\r
+import org.junit.BeforeClass;\r
+import org.junit.Test;\r
+\r
+public class UserTest {\r
+       private Set<User> userList = new Set<>();\r
+       User TestUser;\r
+       \r
+       @BeforeClass\r
+       public static void setUpBeforeClass() throws Exception {\r
+               \r
+       }\r
+\r
+       @Test\r
+       public void CreateUserTest() {\r
+               TestUser = new User(TestUser,"1234");\r
+               assertEquals("TestUser", TestUser.getUserName());\r
+       }\r
+       \r
+       @Test\r
+       public void CheckPasswordTest() {\r
+               assertTrue(TestUser.checkPassword("1234"));\r
+               assertFalse(TestUser.checkPassword("4321"));\r
+       }\r
+\r
+}\r