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.
This commit is contained in:
Andreas Schildbach
2019-05-01 19:12:02 +02:00
parent 90ae0d8785
commit d36603c2ba
3 changed files with 7 additions and 7 deletions

View File

@@ -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'

View File

@@ -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");

View File

@@ -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);