Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## v0.9.0
* fix license headers and correct credits to jBcrypt
* add long-password strategy to verifier #21
* fix not returning correct hash version when verifying #24

### Breaking Changes
Expand Down
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,14 @@ The API supports passing a custom handling in that case, to mimic the behaviour
truncate the password.

```java
BCrypt.with(LongPasswordStrategies.truncate()).hash(6, new byte[100]);
BCrypt.with(LongPasswordStrategies.hashSha512()).hash(6, new byte[100]); //allows to honour all pw bytes
BCrypt.with(LongPasswordStrategies.truncate()).hash(6, pw);
BCrypt.with(LongPasswordStrategies.hashSha512()).hash(6, pw); //allows to honour all pw bytes
```

Don't forget to use the same strategy when verifying:

```java
BCrypt.verifyer(LongPasswordStrategies.truncate()).verify(pw, hash);
```

The password will only be transformed if it is longer than 71 bytes. *It is important to note, however, that using any
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,19 @@ public static Hasher with(Version version, SecureRandom secureRandom, LongPasswo
* @return new verifier instance
*/
public static Verifyer verifyer() {
return new Verifyer();
return verifyer(LongPasswordStrategies.none());
}

/**
* Creates a new instance of bcrypt verifier to verify a password against a given hash.
* This verify also respects the passed {@link LongPasswordStrategy} for creating the reference hash - use this
* if you use one while hashing.
*
* @param longPasswordStrategy used to create the reference hash.
* @return new verifier instance
*/
public static Verifyer verifyer(LongPasswordStrategy longPasswordStrategy) {
return new Verifyer(longPasswordStrategy);
}

/**
Expand Down Expand Up @@ -364,8 +376,10 @@ public String toString() {
*/
public static final class Verifyer {
private final Charset defaultCharset = DEFAULT_CHARSET;
private final LongPasswordStrategy longPasswordStrategy;

private Verifyer() {
private Verifyer(LongPasswordStrategy longPasswordStrategy) {
this.longPasswordStrategy = longPasswordStrategy;
}

/**
Expand Down Expand Up @@ -549,7 +563,7 @@ public Result verify(byte[] password, int cost, byte[] salt, byte[] rawBcryptHas
Objects.requireNonNull(rawBcryptHash23Bytes);
Objects.requireNonNull(salt);

HashData hashData = BCrypt.with(version).hashRaw(cost, salt, password);
HashData hashData = BCrypt.with(version, new SecureRandom(), longPasswordStrategy).hashRaw(cost, salt, password);
return new Result(hashData, Bytes.wrap(hashData.rawHash).equalsConstantTime(rawBcryptHash23Bytes));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,13 @@ public static LongPasswordStrategy hashSha512() {
public static LongPasswordStrategy strict() {
return new LongPasswordStrategy.StrictMaxPasswordLengthStrategy(BCrypt.MAX_PW_LENGTH_BYTE);
}

/**
* See {@link LongPasswordStrategy.PassThroughStrategy}
*
* @return new instance
*/
public static LongPasswordStrategy none() {
return new LongPasswordStrategy.PassThroughStrategy();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,13 @@ public byte[] innerDerive(byte[] rawPassword) {
}
}

/**
* A simple strategy that just returns the provided password without changing it.
*/
final class PassThroughStrategy implements LongPasswordStrategy {
@Override
public byte[] derive(byte[] rawPassword) {
return rawPassword;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -413,4 +413,15 @@ public void testVersionPojoMethods() {
assertNotEquals(BCrypt.Version.VERSION_2A.hashCode(), BCrypt.Version.VERSION_2B.hashCode());
assertNotEquals(BCrypt.Version.VERSION_2X.hashCode(), BCrypt.Version.VERSION_2Y.hashCode());
}

@Test
public void testVerifierWithLongPasswordStrategy() {
LongPasswordStrategy truncate = LongPasswordStrategies.truncate();

byte[] pw = Bytes.random(200).array();
byte[] hash = BCrypt.with(truncate).hash(4, pw);

assertTrue(BCrypt.verifyer(truncate).verify(pw, hash).verified);
assertFalse(BCrypt.verifyer().verify(pw, hash).verified);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public class LongPasswordStrategyTest {
public void testFactory() {
assertNotNull(LongPasswordStrategies.hashSha512().derive(Bytes.random(100).array()));
assertNotNull(LongPasswordStrategies.truncate().derive(Bytes.random(100).array()));
assertNotNull(LongPasswordStrategies.none().derive(Bytes.random(100).array()));
}

@Test(expected = IllegalArgumentException.class)
Expand Down Expand Up @@ -92,4 +93,15 @@ public void testSha512HashStrategy() {
System.out.println(Bytes.wrap(byteArray).encodeHex());
}
}

@Test
public void testPassThroughStrategy() {
LongPasswordStrategy strategy = new LongPasswordStrategy.PassThroughStrategy();
byte[] byteArray;

for (int i = 1; i < 64; i++) {
byteArray = Bytes.random(i).array();
assertSame(byteArray, strategy.derive(byteArray));
}
}
}