From d36603c2ba876c519d823e48b3fc1f232f80c3c0 Mon Sep 17 00:00:00 2001 From: Andreas Schildbach Date: Wed, 1 May 2019 19:12:02 +0200 Subject: [PATCH] Use Bouncy Castle's Scrypt implementation rather than the standalone library. Amazingly, on a Pixel 2 this implementation is a bit quicker than Will Glozer/Colin Percival's native code. --- core/build.gradle | 1 - .../main/java/org/bitcoinj/crypto/BIP38PrivateKey.java | 9 +++++---- .../main/java/org/bitcoinj/crypto/KeyCrypterScrypt.java | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index d8fda868..7db94ac4 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -9,7 +9,6 @@ eclipse.project.name = 'bitcoinj-core' dependencies { compile 'org.bouncycastle:bcprov-jdk15on:1.60' - implementation 'com.lambdaworks:scrypt:1.4.0' implementation 'com.google.guava:guava:27.0.1-android' compile 'com.google.protobuf:protobuf-java:3.6.1' implementation 'com.squareup.okhttp3:okhttp:3.12.1' diff --git a/core/src/main/java/org/bitcoinj/crypto/BIP38PrivateKey.java b/core/src/main/java/org/bitcoinj/crypto/BIP38PrivateKey.java index 80748dae..45fcee64 100644 --- a/core/src/main/java/org/bitcoinj/crypto/BIP38PrivateKey.java +++ b/core/src/main/java/org/bitcoinj/crypto/BIP38PrivateKey.java @@ -17,8 +17,9 @@ package org.bitcoinj.crypto; import org.bitcoinj.core.*; +import org.bouncycastle.crypto.generators.SCrypt; + import com.google.common.primitives.Bytes; -import com.lambdaworks.crypto.SCrypt; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; @@ -126,7 +127,7 @@ public class BIP38PrivateKey extends PrefixedChecksummedBytes { private ECKey decryptNoEC(String normalizedPassphrase) { try { - byte[] derived = SCrypt.scrypt(normalizedPassphrase.getBytes(StandardCharsets.UTF_8), addressHash, 16384, 8, 8, 64); + byte[] derived = SCrypt.generate(normalizedPassphrase.getBytes(StandardCharsets.UTF_8), addressHash, 16384, 8, 8, 64); byte[] key = Arrays.copyOfRange(derived, 32, 64); SecretKeySpec keyspec = new SecretKeySpec(key, "AES"); @@ -148,7 +149,7 @@ public class BIP38PrivateKey extends PrefixedChecksummedBytes { byte[] ownerEntropy = Arrays.copyOfRange(content, 0, 8); byte[] ownerSalt = hasLotAndSequence ? Arrays.copyOfRange(ownerEntropy, 0, 4) : ownerEntropy; - byte[] passFactorBytes = SCrypt.scrypt(normalizedPassphrase.getBytes(StandardCharsets.UTF_8), ownerSalt, 16384, 8, 8, 32); + byte[] passFactorBytes = SCrypt.generate(normalizedPassphrase.getBytes(StandardCharsets.UTF_8), ownerSalt, 16384, 8, 8, 32); if (hasLotAndSequence) { byte[] hashBytes = Bytes.concat(passFactorBytes, ownerEntropy); checkState(hashBytes.length == 40); @@ -159,7 +160,7 @@ public class BIP38PrivateKey extends PrefixedChecksummedBytes { byte[] salt = Bytes.concat(addressHash, ownerEntropy); checkState(salt.length == 12); - byte[] derived = SCrypt.scrypt(k.getPubKey(), salt, 1024, 1, 1, 64); + byte[] derived = SCrypt.generate(k.getPubKey(), salt, 1024, 1, 1, 64); byte[] aeskey = Arrays.copyOfRange(derived, 32, 64); SecretKeySpec keyspec = new SecretKeySpec(aeskey, "AES"); diff --git a/core/src/main/java/org/bitcoinj/crypto/KeyCrypterScrypt.java b/core/src/main/java/org/bitcoinj/crypto/KeyCrypterScrypt.java index cff7e038..74d6a05d 100644 --- a/core/src/main/java/org/bitcoinj/crypto/KeyCrypterScrypt.java +++ b/core/src/main/java/org/bitcoinj/crypto/KeyCrypterScrypt.java @@ -20,12 +20,12 @@ package org.bitcoinj.crypto; import com.google.common.base.Objects; import com.google.common.base.Stopwatch; import com.google.protobuf.ByteString; -import com.lambdaworks.crypto.SCrypt; import org.bitcoinj.core.Utils; import org.bitcoinj.wallet.Protos; import org.bitcoinj.wallet.Protos.ScryptParameters; import org.bitcoinj.wallet.Protos.Wallet.EncryptionType; import org.bouncycastle.crypto.engines.AESEngine; +import org.bouncycastle.crypto.generators.SCrypt; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.bouncycastle.crypto.BufferedBlockCipher; @@ -157,7 +157,7 @@ public class KeyCrypterScrypt implements KeyCrypter { } final Stopwatch watch = Stopwatch.createStarted(); - byte[] keyBytes = SCrypt.scrypt(passwordBytes, salt, (int) scryptParameters.getN(), scryptParameters.getR(), scryptParameters.getP(), KEY_LENGTH); + byte[] keyBytes = SCrypt.generate(passwordBytes, salt, (int) scryptParameters.getN(), scryptParameters.getR(), scryptParameters.getP(), KEY_LENGTH); watch.stop(); log.info("Deriving key took {} for {} scrypt iterations.", watch, scryptParameters.getN()); return new KeyParameter(keyBytes);