From 5aaf6a25db3d70242ffc59fdaec3c429bf4e3d75 Mon Sep 17 00:00:00 2001 From: Andreas Schildbach Date: Wed, 10 Dec 2014 15:56:48 +0100 Subject: [PATCH] When running on Android, automatically insert LinuxSecureRandom provider. --- core/src/main/java/org/bitcoinj/core/ECKey.java | 4 ++++ .../java/org/bitcoinj/crypto/HDKeyDerivation.java | 10 +++++++++- .../java/org/bitcoinj/crypto/KeyCrypterScrypt.java | 12 +++++++++++- .../main/java/org/bitcoinj/wallet/KeyChainGroup.java | 8 ++++++++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/bitcoinj/core/ECKey.java b/core/src/main/java/org/bitcoinj/core/ECKey.java index 4feb80b2..c999f47c 100644 --- a/core/src/main/java/org/bitcoinj/core/ECKey.java +++ b/core/src/main/java/org/bitcoinj/core/ECKey.java @@ -128,6 +128,10 @@ public class ECKey implements EncryptableItem, Serializable { private static final long serialVersionUID = -728224901792295832L; static { + // Init proper random number generator, as some old Android installations have bugs that make it unsecure. + if (Utils.isAndroidRuntime()) + new LinuxSecureRandom(); + // Tell Bouncy Castle to precompute data that's needed during secp256k1 calculations. Increasing the width // number makes calculations faster, but at a cost of extra memory usage and with decreasing returns. 12 was // picked after consulting with the BC team. diff --git a/core/src/main/java/org/bitcoinj/crypto/HDKeyDerivation.java b/core/src/main/java/org/bitcoinj/crypto/HDKeyDerivation.java index 3e21e81f..6bd37f9a 100644 --- a/core/src/main/java/org/bitcoinj/crypto/HDKeyDerivation.java +++ b/core/src/main/java/org/bitcoinj/crypto/HDKeyDerivation.java @@ -35,8 +35,16 @@ import static com.google.common.base.Preconditions.checkState; * deterministic wallet child key generation algorithm. */ public final class HDKeyDerivation { + static { + // Init proper random number generator, as some old Android installations have bugs that make it unsecure. + if (Utils.isAndroidRuntime()) + new LinuxSecureRandom(); + + RAND_INT = new BigInteger(256, new SecureRandom()); + } + // Some arbitrary random number. Doesn't matter what it is. - private static final BigInteger RAND_INT = new BigInteger(256, new SecureRandom()); + private static final BigInteger RAND_INT; private HDKeyDerivation() { } diff --git a/core/src/main/java/org/bitcoinj/crypto/KeyCrypterScrypt.java b/core/src/main/java/org/bitcoinj/crypto/KeyCrypterScrypt.java index cf595a2e..17b694bc 100644 --- a/core/src/main/java/org/bitcoinj/crypto/KeyCrypterScrypt.java +++ b/core/src/main/java/org/bitcoinj/crypto/KeyCrypterScrypt.java @@ -19,6 +19,7 @@ package org.bitcoinj.crypto; import com.google.common.base.Objects; 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; @@ -52,6 +53,7 @@ import static com.google.common.base.Preconditions.checkNotNull; * the AES symmetric cipher. Eight bytes of salt is used to prevent dictionary attacks.

*/ public class KeyCrypterScrypt implements KeyCrypter, Serializable { + private static final Logger log = LoggerFactory.getLogger(KeyCrypterScrypt.class); private static final long serialVersionUID = 949662512049152670L; @@ -71,7 +73,15 @@ public class KeyCrypterScrypt implements KeyCrypter, Serializable { */ public static final int SALT_LENGTH = 8; - private static final transient SecureRandom secureRandom = new SecureRandom(); + static { + // Init proper random number generator, as some old Android installations have bugs that make it unsecure. + if (Utils.isAndroidRuntime()) + new LinuxSecureRandom(); + + secureRandom = new SecureRandom(); + } + + private static final transient SecureRandom secureRandom; private static byte[] randomSalt() { byte[] salt = new byte[SALT_LENGTH]; diff --git a/core/src/main/java/org/bitcoinj/wallet/KeyChainGroup.java b/core/src/main/java/org/bitcoinj/wallet/KeyChainGroup.java index f4549e1d..80118538 100644 --- a/core/src/main/java/org/bitcoinj/wallet/KeyChainGroup.java +++ b/core/src/main/java/org/bitcoinj/wallet/KeyChainGroup.java @@ -21,6 +21,7 @@ import org.bitcoinj.core.*; import org.bitcoinj.crypto.ChildNumber; import org.bitcoinj.crypto.DeterministicKey; import org.bitcoinj.crypto.KeyCrypter; +import org.bitcoinj.crypto.LinuxSecureRandom; import org.bitcoinj.script.Script; import org.bitcoinj.script.ScriptBuilder; import org.bitcoinj.store.UnreadableWalletException; @@ -64,6 +65,13 @@ import static com.google.common.base.Preconditions.*; * class docs for {@link DeterministicKeyChain} for more information on this topic.

*/ public class KeyChainGroup implements KeyBag { + + static { + // Init proper random number generator, as some old Android installations have bugs that make it unsecure. + if (Utils.isAndroidRuntime()) + new LinuxSecureRandom(); + } + private static final Logger log = LoggerFactory.getLogger(KeyChainGroup.class); private BasicKeyChain basic;