Skip to content

Commit

Permalink
Integer overflow fix (jBCrypt 0.4)
Browse files Browse the repository at this point in the history
 This corrects an integer overflow that occurs with very large log_rounds values, first reported by Marcus Rathsfeld.
  • Loading branch information
jeremyh committed Feb 2, 2015
1 parent 296f01f commit e015c2c
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 13 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ This is an alternative distribution of [jBCrypt](http://www.mindrot.org/projects
packaged to ease use in existing applications — especially those using
Apache Maven.

The code is unchanged from the original jBCrypt 0.3, however:
The code is unchanged from the original jBCrypt 0.4, however:

- The classes have been moved to a java package to avoid pollution of the
global namespace. *org.mindrot* was chosen to reflect their original origin.
- The JBCrypt class javadoc has been changed to version 0.3. The official
- The JBCrypt class javadoc has been changed to version 0.4. The official
package incorrectly contains 0.2 as the stated version.
- A pom.xml file has been added for use with Maven

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>org.mindrot</groupId>
<artifactId>jbcrypt</artifactId>
<version>0.3</version>
<version>0.4</version>
<packaging>jar</packaging>

<name>jbcrypt</name>
Expand Down
44 changes: 35 additions & 9 deletions src/main/java/org/mindrot/BCrypt.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@
* <p>
* The amount of work increases exponentially (2**log_rounds), so
* each increment is twice as much work. The default log_rounds is
* 10, and the valid range is 4 to 31.
* 10, and the valid range is 4 to 30.
*
* @author Damien Miller
* @version 0.3
* @version 0.4
*/
public class BCrypt {
// BCrypt parameters
Expand Down Expand Up @@ -336,7 +336,9 @@ public class BCrypt {
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
};

// bcrypt IV: "OrpheanBeholderScryDoubt"
// bcrypt IV: "OrpheanBeholderScryDoubt". The C implementation calls
// this "ciphertext", but it is really plaintext or an IV. We keep
// the name to make code comparison easier.
static private final int bf_crypt_ciphertext[] = {
0x4f727068, 0x65616e42, 0x65686f6c,
0x64657253, 0x63727944, 0x6f756274
Expand Down Expand Up @@ -602,23 +604,24 @@ private void ekskey(byte data[], byte key[]) {
* @param salt the binary salt to hash with the password
* @param log_rounds the binary logarithm of the number
* of rounds of hashing to apply
* @param cdata the plaintext to encrypt
* @return an array containing the binary hashed password
*/
private byte[] crypt_raw(byte password[], byte salt[], int log_rounds) {
public byte[] crypt_raw(byte password[], byte salt[], int log_rounds,
int cdata[]) {
int rounds, i, j;
int cdata[] = (int[])bf_crypt_ciphertext.clone();
int clen = cdata.length;
byte ret[];

if (log_rounds < 4 || log_rounds > 31)
if (log_rounds < 4 || log_rounds > 30)
throw new IllegalArgumentException ("Bad number of rounds");
rounds = 1 << log_rounds;
if (salt.length != BCRYPT_SALT_LEN)
throw new IllegalArgumentException ("Bad salt length");

init_key();
ekskey(salt, password);
for (i = 0; i < rounds; i++) {
for (i = 0; i != rounds; i++) {
key(password);
key(salt);
}
Expand Down Expand Up @@ -679,14 +682,19 @@ public static String hashpw(String password, String salt) {
saltb = decode_base64(real_salt, BCRYPT_SALT_LEN);

B = new BCrypt();
hashed = B.crypt_raw(passwordb, saltb, rounds);
hashed = B.crypt_raw(passwordb, saltb, rounds,
(int[])bf_crypt_ciphertext.clone());

rs.append("$2");
if (minor >= 'a')
rs.append(minor);
rs.append("$");
if (rounds < 10)
rs.append("0");
if (rounds > 30) {
throw new IllegalArgumentException(
"rounds exceeds maximum (30)");
}
rs.append(Integer.toString(rounds));
rs.append("$");
rs.append(encode_base64(saltb, saltb.length));
Expand All @@ -712,6 +720,10 @@ public static String gensalt(int log_rounds, SecureRandom random) {
rs.append("$2a$");
if (log_rounds < 10)
rs.append("0");
if (log_rounds > 30) {
throw new IllegalArgumentException(
"log_rounds exceeds maximum (30)");
}
rs.append(Integer.toString(log_rounds));
rs.append("$");
rs.append(encode_base64(rnd, rnd.length));
Expand Down Expand Up @@ -747,6 +759,20 @@ public static String gensalt() {
* @return true if the passwords match, false otherwise
*/
public static boolean checkpw(String plaintext, String hashed) {
return (hashed.compareTo(hashpw(plaintext, hashed)) == 0);
byte hashed_bytes[];
byte try_bytes[];
try {
String try_pw = hashpw(plaintext, hashed);
hashed_bytes = hashed.getBytes("UTF-8");
try_bytes = try_pw.getBytes("UTF-8");
} catch (UnsupportedEncodingException uee) {
return false;
}
if (hashed_bytes.length != try_bytes.length)
return false;
byte ret = 0;
for (int i = 0; i < try_bytes.length; i++)
ret |= hashed_bytes[i] ^ try_bytes[i];
return ret == 0;
}
}
2 changes: 1 addition & 1 deletion src/test/java/org/mindrot/TestBCrypt.java
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ public void testCheckpw_failure() {
*/
public void testInternationalChars() {
System.out.print("BCrypt.hashpw w/ international chars: ");
String pw1 = "ππππππππ";
String pw1 = "\u2605\u2605\u2605\u2605\u2605\u2605\u2605\u2605";
String pw2 = "????????";

String h1 = BCrypt.hashpw(pw1, BCrypt.gensalt());
Expand Down

0 comments on commit e015c2c

Please sign in to comment.