From 2d874ca902fb5cf0bc34fa927af386af937d1d23 Mon Sep 17 00:00:00 2001 From: Lorenz Quack Date: Sun, 20 Sep 2015 11:48:53 +0100 Subject: [PATCH 1/3] add Bcrypt.getsalt() and Bcrypt.getlogrounds() --- src/main/java/org/mindrot/jbcrypt/BCrypt.java | 59 +++++++++++++++++++ .../java/org/mindrot/jbcrypt/BCryptTest.java | 18 ++++++ 2 files changed, 77 insertions(+) diff --git a/src/main/java/org/mindrot/jbcrypt/BCrypt.java b/src/main/java/org/mindrot/jbcrypt/BCrypt.java index 3a1dca1..e30e76b 100755 --- a/src/main/java/org/mindrot/jbcrypt/BCrypt.java +++ b/src/main/java/org/mindrot/jbcrypt/BCrypt.java @@ -770,6 +770,65 @@ public static boolean checkpw(String plaintext, String hashed) { return equalsNoEarlyReturn(hashed, hashpw(plaintext, hashed)); } + /** + * Retrieve the salt from a hashed password + * @param hashed the previously-hashed password + * @return the salt the password has been hashed with + */ + public static String getsalt(String hashed) { + int minor, off = 0; + if (hashed.charAt(0) != '$' || hashed.charAt(1) != '2') { + throw new IllegalArgumentException("Invalid salt version"); + } + if (hashed.charAt(2) == '$') { + off = 3; + } else { + minor = hashed.charAt(2); + if (minor != 'a' || hashed.charAt(3) != '$') { + throw new IllegalArgumentException("Invalid salt revision"); + } + off = 4; + } + if (hashed.charAt(off + 2) != '$') { + throw new IllegalArgumentException("Missing salt rounds"); + } + if (hashed.length() - off < 25) { + throw new IllegalArgumentException("Invalid salt"); + } + return hashed.substring(0, off + 25); + } + + /** + * Retrieve the log2 of the number of rounds of hashing applied + * @param saltOrHashed the salt generated by BCrypt.gensalt() or + * the previously-hashed password + * @return the log2 of the number of rounds of hashing applied. + */ + public static int getlogrounds(String saltOrHashed) { + Integer log_rounds = null; + int minor, off = 0; + if (saltOrHashed.charAt(0) != '$' || saltOrHashed.charAt(1) != '2') { + throw new IllegalArgumentException("Invalid saltOrHashed version"); + } + if (saltOrHashed.charAt(2) == '$') { + off = 3; + } else { + minor = saltOrHashed.charAt(2); + if (minor != 'a' || saltOrHashed.charAt(3) != '$') { + throw new IllegalArgumentException("Invalid saltOrHashed revision"); + } + off = 4; + } + if (saltOrHashed.charAt(off + 2) != '$') { + throw new IllegalArgumentException("Missing saltOrHashed rounds"); + } + log_rounds = Integer.parseInt(saltOrHashed.substring(off, off + 2)); + if (log_rounds == null) { + throw new IllegalArgumentException("Invalid saltOrHashed rounds"); + } + return log_rounds; + } + static boolean equalsNoEarlyReturn(String a, String b) { char[] caa = a.toCharArray(); char[] cab = b.toCharArray(); diff --git a/src/test/java/org/mindrot/jbcrypt/BCryptTest.java b/src/test/java/org/mindrot/jbcrypt/BCryptTest.java index 30cf35a..191fa3e 100755 --- a/src/test/java/org/mindrot/jbcrypt/BCryptTest.java +++ b/src/test/java/org/mindrot/jbcrypt/BCryptTest.java @@ -341,4 +341,22 @@ public void equalsOnStringsIsCorrect() assertFalse(BCrypt.equalsNoEarlyReturn("test", "pass")); } + + @Test + public void testGetSalt() + { + String password = "password"; + String salt = BCrypt.gensalt(); + String hashedPassword = BCrypt.hashpw(password, salt); + assertEquals(salt, BCrypt.getsalt(hashedPassword)); + } + + @Test + public void testGetLogRounds() + { + String password = "password"; + int logRounds = 11; + String salt = BCrypt.gensalt(logRounds); + assertEquals(logRounds, BCrypt.getlogrounds(salt)); + } } From 3b38307d295f22ee2e60242e6fb6ed75a4348600 Mon Sep 17 00:00:00 2001 From: Lorenz Quack Date: Sun, 20 Sep 2015 12:04:01 +0100 Subject: [PATCH 2/3] minor cleanup --- src/main/java/org/mindrot/jbcrypt/BCrypt.java | 8 ++------ src/test/java/org/mindrot/jbcrypt/BCryptTest.java | 1 - 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/mindrot/jbcrypt/BCrypt.java b/src/main/java/org/mindrot/jbcrypt/BCrypt.java index e30e76b..49530e9 100755 --- a/src/main/java/org/mindrot/jbcrypt/BCrypt.java +++ b/src/main/java/org/mindrot/jbcrypt/BCrypt.java @@ -776,7 +776,7 @@ public static boolean checkpw(String plaintext, String hashed) { * @return the salt the password has been hashed with */ public static String getsalt(String hashed) { - int minor, off = 0; + int minor, off; if (hashed.charAt(0) != '$' || hashed.charAt(1) != '2') { throw new IllegalArgumentException("Invalid salt version"); } @@ -805,8 +805,7 @@ public static String getsalt(String hashed) { * @return the log2 of the number of rounds of hashing applied. */ public static int getlogrounds(String saltOrHashed) { - Integer log_rounds = null; - int minor, off = 0; + int log_rounds, minor, off; if (saltOrHashed.charAt(0) != '$' || saltOrHashed.charAt(1) != '2') { throw new IllegalArgumentException("Invalid saltOrHashed version"); } @@ -823,9 +822,6 @@ public static int getlogrounds(String saltOrHashed) { throw new IllegalArgumentException("Missing saltOrHashed rounds"); } log_rounds = Integer.parseInt(saltOrHashed.substring(off, off + 2)); - if (log_rounds == null) { - throw new IllegalArgumentException("Invalid saltOrHashed rounds"); - } return log_rounds; } diff --git a/src/test/java/org/mindrot/jbcrypt/BCryptTest.java b/src/test/java/org/mindrot/jbcrypt/BCryptTest.java index 191fa3e..3a74c4c 100755 --- a/src/test/java/org/mindrot/jbcrypt/BCryptTest.java +++ b/src/test/java/org/mindrot/jbcrypt/BCryptTest.java @@ -354,7 +354,6 @@ public void testGetSalt() @Test public void testGetLogRounds() { - String password = "password"; int logRounds = 11; String salt = BCrypt.gensalt(logRounds); assertEquals(logRounds, BCrypt.getlogrounds(salt)); From 752a0f813a504cc06fce2fef34692d963556fb73 Mon Sep 17 00:00:00 2001 From: Lorenz Quack Date: Sun, 20 Sep 2015 12:06:27 +0100 Subject: [PATCH 3/3] added testGetLogRoundsFromHashed --- src/test/java/org/mindrot/jbcrypt/BCryptTest.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/test/java/org/mindrot/jbcrypt/BCryptTest.java b/src/test/java/org/mindrot/jbcrypt/BCryptTest.java index 3a74c4c..7bcb1cd 100755 --- a/src/test/java/org/mindrot/jbcrypt/BCryptTest.java +++ b/src/test/java/org/mindrot/jbcrypt/BCryptTest.java @@ -352,10 +352,20 @@ public void testGetSalt() } @Test - public void testGetLogRounds() + public void testGetLogRoundsFromSalt() { int logRounds = 11; String salt = BCrypt.gensalt(logRounds); assertEquals(logRounds, BCrypt.getlogrounds(salt)); } + + @Test + public void testGetLogRoundsFromHashed() + { + String password = "password"; + int logRounds = 11; + String salt = BCrypt.gensalt(logRounds); + String hashed = BCrypt.hashpw(password, salt); + assertEquals(logRounds, BCrypt.getlogrounds(hashed)); + } }