Skip to content

Commit

Permalink
Merge pull request #12 from patrickfav/feat-11-jmh-benchmark
Browse files Browse the repository at this point in the history
Add JMH Benchmark
  • Loading branch information
patrickfav authored Aug 11, 2018
2 parents 30dd367 + 6cd1c12 commit 66fa301
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

* allow actual 2^31 rounds (fix integer overflow issue with `1<<31`) #7
* use Apache v2 compatible Radix 64 impl and skip OpenJDK one #8
* add JMH benchmark module #11

## v0.4.0

Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,12 @@ Compare this to other benchmarks, [like this one in node.js](https://github.com/
**Disclaimer:** Micro benchmarks are [usually a really bad way to measure performance](https://mrale.ph/blog/2012/12/15/microbenchmarks-fairy-tale.html).
These numbers are only informal tests and should not be used to derive any security relevant decisions.

#### JMH Benchmark

Additionally there is JMH benchmark module, which is probably better than my home-brew micro benchmark. Build it with
maven `./mvnw clean install` (you may want to disable jar signing with `<project.skipJarSign>` property) and execute
it with `java -jar modules/benchmark-jmh/target/benchmark-jmh-x.y.z-full.jar`.

### Test Vectors and Reference Implementations

This implementation is tested against the bcrypt implementation jBcrypt and Bouncy Castle. It includes test vectors
Expand Down Expand Up @@ -366,7 +372,7 @@ If you want to skip jar signing just change the skip configuration in the

Use the Maven wrapper to create a jar including all dependencies

mvnw clean install
./mvnw clean install

## Tech Stack

Expand Down
4 changes: 2 additions & 2 deletions modules/bcrypt/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -147,13 +147,13 @@
<dependency>
<groupId>org.mindrot</groupId>
<artifactId>jbcrypt</artifactId>
<version>0.4</version>
<version>${project.jbcryptVersion}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.60</version>
<version>${project.bcVersion}</version>
<scope>test</scope>
</dependency>
<dependency>
Expand Down
96 changes: 96 additions & 0 deletions modules/benchmark-jmh/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<artifactId>bcrypt-parent</artifactId>
<groupId>at.favre.lib</groupId>
<version>0.5.0</version>
<relativePath>../../</relativePath>
</parent>

<artifactId>benchmark-jmh</artifactId>
<packaging>jar</packaging>

<name>BCrypt JMH Benchmark</name>

<properties>
<maven.deploy.skip>true</maven.deploy.skip>
<jmh.version>1.21</jmh.version>
</properties>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>com.github.chrisdchristo</groupId>
<artifactId>capsule-maven-plugin</artifactId>
<version>1.5.1</version>
<configuration>
<appClass>org.openjdk.jmh.Main</appClass>
<fileDesc>-full</fileDesc>
<type>fat</type>
</configuration>
<executions>
<execution>
<id>build-fat-jar</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

<dependencies>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>${jmh.version}</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>${jmh.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>at.favre.lib</groupId>
<artifactId>bcrypt</artifactId>
<version>0.5.0</version>
<classifier>optimized</classifier>
</dependency>
<dependency>
<groupId>org.mindrot</groupId>
<artifactId>jbcrypt</artifactId>
<version>${project.jbcryptVersion}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>${project.bcVersion}</version>
</dependency>
<dependency>
<groupId>com.github.fzakaria</groupId>
<artifactId>ascii85</artifactId>
<version>1.1</version>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package at.favre.lib.crypto.bcrypt.benchmark;

import at.favre.lib.bytes.BinaryToTextEncoding;
import at.favre.lib.bytes.Bytes;
import at.favre.lib.crypto.bcrypt.BCrypt;
import com.github.fzakaria.ascii85.Ascii85;
import org.openjdk.jmh.annotations.*;

import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

@SuppressWarnings("CheckStyle")
@State(Scope.Thread)
@Fork(1)
@Warmup(iterations = 2, time = 4)
@Measurement(iterations = 3, time = 12)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
//CHECKSTYLE.OFF
public class BcryptBenchmark {

private AbstractBcrypt favreBcrypt;
private AbstractBcrypt jBcrypt;
private AbstractBcrypt bcBcrypt;
private BinaryToTextEncoding.Encoder ascii85 = new BinaryToTextEncoding.Encoder() {
@Override
public String encode(byte[] bytes, ByteOrder byteOrder) {
return Ascii85.encode(bytes);
}
};

@Param({"10", "12"})
private int cost;
private byte[] pw;

@Setup(Level.Trial)
public void setupBenchmark() {
favreBcrypt = new FavreBcrypt();
jBcrypt = new JBcrypt();
bcBcrypt = new BC();
}

@Setup(Level.Invocation)
public void setup() {
pw = Bytes.random(36).encode(ascii85).getBytes(StandardCharsets.UTF_8);
}

@Benchmark
public byte[] benchmarkFavreBcrypt() {
return benchmark(favreBcrypt, cost, pw);
}

//@Benchmark
public byte[] benchmarkJBcrypt() {
return benchmark(jBcrypt, cost, pw);
}

//@Benchmark
public byte[] benchmarkBcBcrypt() {
return benchmark(bcBcrypt, cost, pw);
}

private byte[] benchmark(AbstractBcrypt bcrypt, int logRounds, byte[] pw) {
return bcrypt.bcrypt(logRounds, pw);
}

static final class FavreBcrypt implements AbstractBcrypt {
@Override
public byte[] bcrypt(int cost, byte[] password) {
return BCrypt.withDefaults().hash(cost, password);
}
}

static final class JBcrypt implements AbstractBcrypt {
@Override
public byte[] bcrypt(int cost, byte[] password) {
return org.mindrot.jbcrypt.BCrypt.hashpw(new String(password, StandardCharsets.UTF_8), org.mindrot.jbcrypt.BCrypt.gensalt(cost)).getBytes(StandardCharsets.UTF_8);
}
}

static final class BC implements AbstractBcrypt {
@Override
public byte[] bcrypt(int cost, byte[] password) {
return org.bouncycastle.crypto.generators.BCrypt.generate(Bytes.from(password).append((byte) 0).array(), Bytes.random(16).array(), cost);
}
}

interface AbstractBcrypt {
byte[] bcrypt(int cost, byte[] password);
}
}
//CHECKSTYLE.ON
3 changes: 3 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@
<modules>
<module>modules/bcrypt</module>
<module>modules/bcrypt-cli</module>
<module>modules/benchmark-jmh</module>
</modules>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<project.jbcryptVersion>0.4</project.jbcryptVersion>
<project.bcVersion>1.60</project.bcVersion>
<project.skipJarSign>false
</project.skipJarSign> <!-- set this to true if fail because of missing credentials -->
</properties>
Expand Down

0 comments on commit 66fa301

Please sign in to comment.