From 56836e12b0834ae198f8ddbcfcda88f39728a3ce Mon Sep 17 00:00:00 2001 From: pfavre Date: Sat, 11 Aug 2018 16:04:57 +0200 Subject: [PATCH 1/4] Add JMH bcrypt benchmark ref 11 --- CHANGELOG | 1 + README.md | 8 +- modules/bcrypt/pom.xml | 4 +- modules/benchmark-jmh/pom.xml | 82 ++++++++++++++++ .../bcrypt/benchmark/BcryptBenchmark.java | 93 +++++++++++++++++++ pom.xml | 8 ++ 6 files changed, 193 insertions(+), 3 deletions(-) create mode 100644 modules/benchmark-jmh/pom.xml create mode 100644 modules/benchmark-jmh/src/main/java/at/favre/lib/crypto/bcrypt/benchmark/BcryptBenchmark.java diff --git a/CHANGELOG b/CHANGELOG index ba50fd9..d033bf0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -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 diff --git a/README.md b/README.md index 75dc00d..2a641f2 100644 --- a/README.md +++ b/README.md @@ -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 `` 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 @@ -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 diff --git a/modules/bcrypt/pom.xml b/modules/bcrypt/pom.xml index d3b21fd..12b7297 100644 --- a/modules/bcrypt/pom.xml +++ b/modules/bcrypt/pom.xml @@ -147,13 +147,13 @@ org.mindrot jbcrypt - 0.4 + ${project.jbcryptVersion} test org.bouncycastle bcprov-jdk15on - 1.60 + ${project.bcVersion} test diff --git a/modules/benchmark-jmh/pom.xml b/modules/benchmark-jmh/pom.xml new file mode 100644 index 0000000..a4cdfbe --- /dev/null +++ b/modules/benchmark-jmh/pom.xml @@ -0,0 +1,82 @@ + + + 4.0.0 + + + bcrypt-parent + at.favre.lib + 0.5.0 + ../../ + + + benchmark-jmh + jar + + BCrypt JMH Benchmark + + + true + 1.21 + + + + + + com.github.chrisdchristo + capsule-maven-plugin + 1.5.1 + + org.openjdk.jmh.Main + -full + fat + + + + build-fat-jar + package + + build + + + + + + + + + + org.openjdk.jmh + jmh-core + ${jmh.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh.version} + provided + + + at.favre.lib + bcrypt + 0.5.0 + optimized + + + org.mindrot + jbcrypt + ${project.jbcryptVersion} + + + org.bouncycastle + bcprov-jdk15on + ${project.bcVersion} + + + com.github.fzakaria + ascii85 + 1.1 + + + diff --git a/modules/benchmark-jmh/src/main/java/at/favre/lib/crypto/bcrypt/benchmark/BcryptBenchmark.java b/modules/benchmark-jmh/src/main/java/at/favre/lib/crypto/bcrypt/benchmark/BcryptBenchmark.java new file mode 100644 index 0000000..0940c66 --- /dev/null +++ b/modules/benchmark-jmh/src/main/java/at/favre/lib/crypto/bcrypt/benchmark/BcryptBenchmark.java @@ -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 = 3, 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({"5", "6", "8", "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 diff --git a/pom.xml b/pom.xml index ffc06d9..656885f 100644 --- a/pom.xml +++ b/pom.xml @@ -18,11 +18,14 @@ modules/bcrypt modules/bcrypt-cli + modules/benchmark-jmh UTF-8 UTF-8 + 0.4 + 1.60 false @@ -110,6 +113,11 @@ + + + BcryptBenchmark.* + + org.eluder.coveralls From 59793a096456379dba8666e00f2388ee488ebd80 Mon Sep 17 00:00:00 2001 From: pfavre Date: Sat, 11 Aug 2018 16:11:26 +0200 Subject: [PATCH 2/4] Exclude jmh benchmark from checkstyle plugin ref #11 --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index 656885f..a70c4b2 100644 --- a/pom.xml +++ b/pom.xml @@ -66,6 +66,7 @@ 3.0.0 checkstyle.xml + BcryptBenchmark.* From fc29a75d767d3176646221f37f97189e17fc43ff Mon Sep 17 00:00:00 2001 From: pfavre Date: Sat, 11 Aug 2018 16:27:04 +0200 Subject: [PATCH 3/4] Try to fix checkstyle issues with benchmark ref #11 --- .../lib/crypto/bcrypt/benchmark/BcryptBenchmark.java | 8 ++++---- pom.xml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/benchmark-jmh/src/main/java/at/favre/lib/crypto/bcrypt/benchmark/BcryptBenchmark.java b/modules/benchmark-jmh/src/main/java/at/favre/lib/crypto/bcrypt/benchmark/BcryptBenchmark.java index 0940c66..20e7bde 100644 --- a/modules/benchmark-jmh/src/main/java/at/favre/lib/crypto/bcrypt/benchmark/BcryptBenchmark.java +++ b/modules/benchmark-jmh/src/main/java/at/favre/lib/crypto/bcrypt/benchmark/BcryptBenchmark.java @@ -13,7 +13,7 @@ @SuppressWarnings("CheckStyle") @State(Scope.Thread) @Fork(1) -@Warmup(iterations = 3, time = 4) +@Warmup(iterations = 2, time = 4) @Measurement(iterations = 3, time = 12) @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) @@ -30,7 +30,7 @@ public String encode(byte[] bytes, ByteOrder byteOrder) { } }; - @Param({"5", "6", "8", "10", "12"}) + @Param({"10", "12"}) private int cost; private byte[] pw; @@ -51,12 +51,12 @@ public byte[] benchmarkFavreBcrypt() { return benchmark(favreBcrypt, cost, pw); } - @Benchmark + //@Benchmark public byte[] benchmarkJBcrypt() { return benchmark(jBcrypt, cost, pw); } - @Benchmark + //@Benchmark public byte[] benchmarkBcBcrypt() { return benchmark(bcBcrypt, cost, pw); } diff --git a/pom.xml b/pom.xml index a70c4b2..eb310b5 100644 --- a/pom.xml +++ b/pom.xml @@ -66,7 +66,7 @@ 3.0.0 checkstyle.xml - BcryptBenchmark.* + **/benchmark-jmh/** @@ -116,7 +116,7 @@ - BcryptBenchmark.* + **/benchmark-jmh/** From 6cd1c128022adbcf8c3520289be1e330adbbe40e Mon Sep 17 00:00:00 2001 From: pfavre Date: Sat, 11 Aug 2018 16:32:42 +0200 Subject: [PATCH 4/4] Exclude jacoco and checkstyle plugin in benchmark module ref #11 --- modules/benchmark-jmh/pom.xml | 14 ++++++++++++++ pom.xml | 6 ------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/modules/benchmark-jmh/pom.xml b/modules/benchmark-jmh/pom.xml index a4cdfbe..55b55af 100644 --- a/modules/benchmark-jmh/pom.xml +++ b/modules/benchmark-jmh/pom.xml @@ -23,6 +23,20 @@ + + org.apache.maven.plugins + maven-checkstyle-plugin + + true + + + + org.jacoco + jacoco-maven-plugin + + true + + com.github.chrisdchristo capsule-maven-plugin diff --git a/pom.xml b/pom.xml index eb310b5..c12f301 100644 --- a/pom.xml +++ b/pom.xml @@ -66,7 +66,6 @@ 3.0.0 checkstyle.xml - **/benchmark-jmh/** @@ -114,11 +113,6 @@ - - - **/benchmark-jmh/** - - org.eluder.coveralls