mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2024-11-19 01:40:26 +01:00
AesKey: replace o.bouncycastle.c.p.KeyParameter
We were using KeyParameter as a wrapper for a byte[] containing an AES Key and passing it around our API. This introduced an unnecessary API dependency on Bouncy Castle. This PR adds an AesKey class for the same purpose to replace it. This is a breaking change, but one that should be easy to accommodate.
This commit is contained in:
parent
46dcfc6bda
commit
c41128b4df
@ -25,6 +25,7 @@ import org.bitcoinj.base.Coin;
|
||||
import org.bitcoinj.base.Sha256Hash;
|
||||
import org.bitcoinj.base.VarInt;
|
||||
import org.bitcoinj.base.internal.TimeUtils;
|
||||
import org.bitcoinj.crypto.AesKey;
|
||||
import org.bitcoinj.base.utils.ByteUtils;
|
||||
import org.bitcoinj.core.TransactionConfidence.ConfidenceType;
|
||||
import org.bitcoinj.crypto.ECKey;
|
||||
@ -40,7 +41,6 @@ import org.bitcoinj.signers.TransactionSigner;
|
||||
import org.bitcoinj.utils.ExchangeRate;
|
||||
import org.bitcoinj.wallet.Wallet;
|
||||
import org.bitcoinj.wallet.WalletTransaction.Pool;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -1188,7 +1188,7 @@ public class Transaction extends ChildMessage {
|
||||
* @return A newly calculated signature object that wraps the r, s and sighash components.
|
||||
*/
|
||||
public TransactionSignature calculateSignature(int inputIndex, ECKey key,
|
||||
@Nullable KeyParameter aesKey,
|
||||
@Nullable AesKey aesKey,
|
||||
byte[] redeemScript,
|
||||
SigHash hashType, boolean anyoneCanPay) {
|
||||
Sha256Hash hash = hashForSignature(inputIndex, redeemScript, hashType, anyoneCanPay);
|
||||
@ -1209,7 +1209,7 @@ public class Transaction extends ChildMessage {
|
||||
* @return A newly calculated signature object that wraps the r, s and sighash components.
|
||||
*/
|
||||
public TransactionSignature calculateSignature(int inputIndex, ECKey key,
|
||||
@Nullable KeyParameter aesKey,
|
||||
@Nullable AesKey aesKey,
|
||||
Script redeemScript,
|
||||
SigHash hashType, boolean anyoneCanPay) {
|
||||
Sha256Hash hash = hashForSignature(inputIndex, redeemScript.getProgram(), hashType, anyoneCanPay);
|
||||
@ -1372,7 +1372,7 @@ public class Transaction extends ChildMessage {
|
||||
public TransactionSignature calculateWitnessSignature(
|
||||
int inputIndex,
|
||||
ECKey key,
|
||||
@Nullable KeyParameter aesKey,
|
||||
@Nullable AesKey aesKey,
|
||||
byte[] scriptCode,
|
||||
Coin value,
|
||||
SigHash hashType,
|
||||
@ -1384,7 +1384,7 @@ public class Transaction extends ChildMessage {
|
||||
public TransactionSignature calculateWitnessSignature(
|
||||
int inputIndex,
|
||||
ECKey key,
|
||||
@Nullable KeyParameter aesKey,
|
||||
@Nullable AesKey aesKey,
|
||||
Script scriptCode,
|
||||
Coin value,
|
||||
SigHash hashType,
|
||||
|
80
core/src/main/java/org/bitcoinj/crypto/AesKey.java
Normal file
80
core/src/main/java/org/bitcoinj/crypto/AesKey.java
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright by the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.bitcoinj.crypto;
|
||||
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
|
||||
/**
|
||||
* Wrapper for a {@code byte[]} containing an AES Key. This is a replacement for Bouncy Castle's {@link KeyParameter} which
|
||||
* was used for this purpose in previous versions of <b>bitcoinj</b>. Unfortunately, this created a Gradle _API_ dependency
|
||||
* on Bouncy Castle when that wasn't strictly necessary.
|
||||
* <p>
|
||||
* We have made this change without deprecation because it affected many method signatures and because updating is a trivial change.
|
||||
* If for some reason you have code that uses the Bouncy Castle {@link KeyParameter} type and need to convert
|
||||
* to or from {@code AesKey}, you can temporarily use {@link #ofKeyParameter(KeyParameter)} or {@link #toKeyParameter()}
|
||||
*/
|
||||
public class AesKey {
|
||||
private final byte[] bytes;
|
||||
|
||||
/**
|
||||
* Wrapper for a {@code byte[]} containing an AES Key
|
||||
* @param keyBytes implementation-dependent AES Key bytes
|
||||
*/
|
||||
public AesKey(byte[] keyBytes) {
|
||||
// Make defensive copy, so AesKey is effectively immutable
|
||||
this.bytes = new byte[keyBytes.length];
|
||||
System.arraycopy(keyBytes, 0, this.bytes, 0, keyBytes.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The key bytes
|
||||
*/
|
||||
public byte[] bytes() {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provided to ease migration from {@link KeyParameter}.
|
||||
* @return The key bytes
|
||||
* @deprecated Use {@link #bytes()}
|
||||
*/
|
||||
@Deprecated
|
||||
public byte[] getKey() {
|
||||
return bytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provided to ease migration from {@link KeyParameter}.
|
||||
* @param keyParameter instance to convert
|
||||
* @return new, preferred container for AES keys
|
||||
* @deprecated Use {@code new AesKey(keyParameter.bytes())}
|
||||
*/
|
||||
@Deprecated
|
||||
public static AesKey ofKeyParameter(KeyParameter keyParameter) {
|
||||
return new AesKey(keyParameter.getKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* Provided to ease migration from {@link KeyParameter}.
|
||||
* @return if for some reason you still need (temporarily, we hope) a {@link KeyParameter}
|
||||
* @deprecated Use {@code new KeyParameter(key.bytes)}
|
||||
*/
|
||||
@Deprecated
|
||||
public KeyParameter toKeyParameter() {
|
||||
return new KeyParameter(this.bytes());
|
||||
}
|
||||
}
|
@ -26,7 +26,6 @@ import org.bitcoinj.base.Base58;
|
||||
import org.bitcoinj.core.NetworkParameters;
|
||||
import org.bitcoinj.base.Sha256Hash;
|
||||
import org.bitcoinj.crypto.internal.CryptoUtils;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
import org.bouncycastle.math.ec.ECPoint;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
@ -295,11 +294,11 @@ public class DeterministicKey extends ECKey {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeterministicKey encrypt(KeyCrypter keyCrypter, KeyParameter aesKey) throws KeyCrypterException {
|
||||
public DeterministicKey encrypt(KeyCrypter keyCrypter, AesKey aesKey) throws KeyCrypterException {
|
||||
throw new UnsupportedOperationException("Must supply a new parent for encryption");
|
||||
}
|
||||
|
||||
public DeterministicKey encrypt(KeyCrypter keyCrypter, KeyParameter aesKey, @Nullable DeterministicKey newParent) throws KeyCrypterException {
|
||||
public DeterministicKey encrypt(KeyCrypter keyCrypter, AesKey aesKey, @Nullable DeterministicKey newParent) throws KeyCrypterException {
|
||||
// Same as the parent code, except we construct a DeterministicKey instead of an ECKey.
|
||||
checkNotNull(keyCrypter);
|
||||
if (newParent != null)
|
||||
@ -357,7 +356,7 @@ public class DeterministicKey extends ECKey {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ECDSASignature sign(Sha256Hash input, @Nullable KeyParameter aesKey) throws KeyCrypterException {
|
||||
public ECDSASignature sign(Sha256Hash input, @Nullable AesKey aesKey) throws KeyCrypterException {
|
||||
if (isEncrypted()) {
|
||||
// If the key is encrypted, ECKey.sign will decrypt it first before rerunning sign. Decryption walks the
|
||||
// key hierarchy to find the private key (see below), so, we can just run the inherited method.
|
||||
@ -374,7 +373,7 @@ public class DeterministicKey extends ECKey {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeterministicKey decrypt(KeyCrypter keyCrypter, KeyParameter aesKey) throws KeyCrypterException {
|
||||
public DeterministicKey decrypt(KeyCrypter keyCrypter, AesKey aesKey) throws KeyCrypterException {
|
||||
checkNotNull(keyCrypter);
|
||||
// Check that the keyCrypter matches the one used to encrypt the keys, if set.
|
||||
if (this.keyCrypter != null && !this.keyCrypter.equals(keyCrypter))
|
||||
@ -389,13 +388,13 @@ public class DeterministicKey extends ECKey {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeterministicKey decrypt(KeyParameter aesKey) throws KeyCrypterException {
|
||||
public DeterministicKey decrypt(AesKey aesKey) throws KeyCrypterException {
|
||||
return (DeterministicKey) super.decrypt(aesKey);
|
||||
}
|
||||
|
||||
// For when a key is encrypted, either decrypt our encrypted private key bytes, or work up the tree asking parents
|
||||
// to decrypt and re-derive.
|
||||
private BigInteger findOrDeriveEncryptedPrivateKey(KeyCrypter keyCrypter, KeyParameter aesKey) {
|
||||
private BigInteger findOrDeriveEncryptedPrivateKey(KeyCrypter keyCrypter, AesKey aesKey) {
|
||||
if (encryptedPrivateKey != null) {
|
||||
byte[] decryptedKey = keyCrypter.decrypt(encryptedPrivateKey, aesKey);
|
||||
if (decryptedKey.length != 32)
|
||||
@ -753,7 +752,7 @@ public class DeterministicKey extends ECKey {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void formatKeyWithAddress(boolean includePrivateKeys, @Nullable KeyParameter aesKey, StringBuilder builder,
|
||||
public void formatKeyWithAddress(boolean includePrivateKeys, @Nullable AesKey aesKey, StringBuilder builder,
|
||||
Network network, ScriptType outputScriptType, @Nullable String comment) {
|
||||
builder.append(" addr:").append(toAddress(outputScriptType, network).toString());
|
||||
builder.append(" hash160:").append(ByteUtils.formatHex(getPubKeyHash()));
|
||||
@ -767,11 +766,11 @@ public class DeterministicKey extends ECKey {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #formatKeyWithAddress(boolean, KeyParameter, StringBuilder, Network, ScriptType, String)}
|
||||
* @deprecated Use {@link #formatKeyWithAddress(boolean, AesKey, StringBuilder, Network, ScriptType, String)}
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public void formatKeyWithAddress(boolean includePrivateKeys, @Nullable KeyParameter aesKey, StringBuilder builder,
|
||||
public void formatKeyWithAddress(boolean includePrivateKeys, @Nullable AesKey aesKey, StringBuilder builder,
|
||||
NetworkParameters params, ScriptType outputScriptType, @Nullable String comment) {
|
||||
formatKeyWithAddress(includePrivateKeys, aesKey, builder, params.network(), outputScriptType, comment);
|
||||
}
|
||||
|
@ -59,7 +59,6 @@ import org.bouncycastle.crypto.params.ECDomainParameters;
|
||||
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
|
||||
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
|
||||
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
import org.bouncycastle.crypto.signers.ECDSASigner;
|
||||
import org.bouncycastle.crypto.signers.HMacDSAKCalculator;
|
||||
import org.bouncycastle.math.ec.ECAlgorithms;
|
||||
@ -570,7 +569,7 @@ public class ECKey implements EncryptableItem {
|
||||
* @throws KeyCrypterException if there's something wrong with aesKey.
|
||||
* @throws ECKey.MissingPrivateKeyException if this key cannot sign because it's pubkey only.
|
||||
*/
|
||||
public ECDSASignature sign(Sha256Hash input, @Nullable KeyParameter aesKey) throws KeyCrypterException {
|
||||
public ECDSASignature sign(Sha256Hash input, @Nullable AesKey aesKey) throws KeyCrypterException {
|
||||
KeyCrypter crypter = getKeyCrypter();
|
||||
if (crypter != null) {
|
||||
if (aesKey == null)
|
||||
@ -804,10 +803,10 @@ public class ECKey implements EncryptableItem {
|
||||
*
|
||||
* @throws IllegalStateException if this ECKey does not have the private part.
|
||||
* @throws KeyCrypterException if this ECKey is encrypted and no AESKey is provided or it does not decrypt the ECKey.
|
||||
* @deprecated use {@link #signMessage(String, KeyParameter, ScriptType)} instead and specify the correct script type
|
||||
* @deprecated use {@link #signMessage(String, AesKey, ScriptType)} instead and specify the correct script type
|
||||
*/
|
||||
@Deprecated
|
||||
public String signMessage(String message, @Nullable KeyParameter aesKey) throws KeyCrypterException {
|
||||
public String signMessage(String message, @Nullable AesKey aesKey) throws KeyCrypterException {
|
||||
return signMessage(message, aesKey, ScriptType.P2PKH);
|
||||
}
|
||||
|
||||
@ -819,7 +818,7 @@ public class ECKey implements EncryptableItem {
|
||||
* @throws IllegalStateException if this ECKey does not have the private part.
|
||||
* @throws KeyCrypterException if this ECKey is encrypted and no AESKey is provided or it does not decrypt the ECKey.
|
||||
*/
|
||||
public String signMessage(String message, @Nullable KeyParameter aesKey, ScriptType scriptType) throws KeyCrypterException {
|
||||
public String signMessage(String message, @Nullable AesKey aesKey, ScriptType scriptType) throws KeyCrypterException {
|
||||
if (!isCompressed() && (scriptType == ScriptType.P2WPKH || scriptType == ScriptType.P2SH)) {
|
||||
throw new IllegalArgumentException("Segwit P2WPKH and P2SH-P2WPKH script types only can be used with compressed keys. See BIP 141.");
|
||||
}
|
||||
@ -1101,7 +1100,7 @@ public class ECKey implements EncryptableItem {
|
||||
* @param aesKey The KeyParameter with the AES encryption key (usually constructed with keyCrypter#deriveKey and cached as it is slow to create).
|
||||
* @return encryptedKey
|
||||
*/
|
||||
public ECKey encrypt(KeyCrypter keyCrypter, KeyParameter aesKey) throws KeyCrypterException {
|
||||
public ECKey encrypt(KeyCrypter keyCrypter, AesKey aesKey) throws KeyCrypterException {
|
||||
checkNotNull(keyCrypter);
|
||||
final byte[] privKeyBytes = getPrivKeyBytes();
|
||||
EncryptedData encryptedPrivateKey = keyCrypter.encrypt(privKeyBytes, aesKey);
|
||||
@ -1118,7 +1117,7 @@ public class ECKey implements EncryptableItem {
|
||||
* @param keyCrypter The keyCrypter that specifies exactly how the decrypted bytes are created.
|
||||
* @param aesKey The KeyParameter with the AES encryption key (usually constructed with keyCrypter#deriveKey and cached).
|
||||
*/
|
||||
public ECKey decrypt(KeyCrypter keyCrypter, KeyParameter aesKey) throws KeyCrypterException {
|
||||
public ECKey decrypt(KeyCrypter keyCrypter, AesKey aesKey) throws KeyCrypterException {
|
||||
checkNotNull(keyCrypter);
|
||||
// Check that the keyCrypter matches the one used to encrypt the keys, if set.
|
||||
if (this.keyCrypter != null && !this.keyCrypter.equals(keyCrypter))
|
||||
@ -1142,7 +1141,7 @@ public class ECKey implements EncryptableItem {
|
||||
*
|
||||
* @param aesKey The KeyParameter with the AES encryption key (usually constructed with keyCrypter#deriveKey and cached).
|
||||
*/
|
||||
public ECKey decrypt(KeyParameter aesKey) throws KeyCrypterException {
|
||||
public ECKey decrypt(AesKey aesKey) throws KeyCrypterException {
|
||||
final KeyCrypter crypter = getKeyCrypter();
|
||||
if (crypter == null)
|
||||
throw new KeyCrypterException("No key crypter available");
|
||||
@ -1152,7 +1151,7 @@ public class ECKey implements EncryptableItem {
|
||||
/**
|
||||
* Creates decrypted private key if needed.
|
||||
*/
|
||||
public ECKey maybeDecrypt(@Nullable KeyParameter aesKey) throws KeyCrypterException {
|
||||
public ECKey maybeDecrypt(@Nullable AesKey aesKey) throws KeyCrypterException {
|
||||
return isEncrypted() && aesKey != null ? decrypt(aesKey) : this;
|
||||
}
|
||||
|
||||
@ -1163,11 +1162,11 @@ public class ECKey implements EncryptableItem {
|
||||
* bitcoins controlled by the private key) you can use this method to check when you *encrypt* a wallet that
|
||||
* it can definitely be decrypted successfully.</p>
|
||||
*
|
||||
* <p>See {@link Wallet#encrypt(KeyCrypter keyCrypter, KeyParameter aesKey)} for example usage.</p>
|
||||
* <p>See {@link Wallet#encrypt(KeyCrypter keyCrypter, AesKey aesKey)} for example usage.</p>
|
||||
*
|
||||
* @return true if the encrypted key can be decrypted back to the original key successfully.
|
||||
*/
|
||||
public static boolean encryptionIsReversible(ECKey originalKey, ECKey encryptedKey, KeyCrypter keyCrypter, KeyParameter aesKey) {
|
||||
public static boolean encryptionIsReversible(ECKey originalKey, ECKey encryptedKey, KeyCrypter keyCrypter, AesKey aesKey) {
|
||||
try {
|
||||
ECKey rebornUnencryptedKey = encryptedKey.decrypt(keyCrypter, aesKey);
|
||||
byte[] originalPrivateKeyBytes = originalKey.getPrivKeyBytes();
|
||||
@ -1267,17 +1266,17 @@ public class ECKey implements EncryptableItem {
|
||||
* Produce a string rendering of the ECKey INCLUDING the private key.
|
||||
* Unless you absolutely need the private key it is better for security reasons to just use {@link #toString()}.
|
||||
*/
|
||||
public String toStringWithPrivate(@Nullable KeyParameter aesKey, Network network) {
|
||||
public String toStringWithPrivate(@Nullable AesKey aesKey, Network network) {
|
||||
return toString(true, aesKey, network);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a string rendering of the ECKey INCLUDING the private key.
|
||||
* Unless you absolutely need the private key it is better for security reasons to just use {@link #toString()}.
|
||||
* @deprecated Use {@link #toStringWithPrivate(KeyParameter, Network)}
|
||||
* @deprecated Use {@link #toStringWithPrivate(AesKey, Network)}
|
||||
*/
|
||||
@Deprecated
|
||||
public String toStringWithPrivate(@Nullable KeyParameter aesKey, NetworkParameters params) {
|
||||
public String toStringWithPrivate(@Nullable AesKey aesKey, NetworkParameters params) {
|
||||
return toStringWithPrivate(aesKey, params.network());
|
||||
}
|
||||
|
||||
@ -1302,7 +1301,7 @@ public class ECKey implements EncryptableItem {
|
||||
return getPrivateKeyAsWiF(params.network());
|
||||
}
|
||||
|
||||
private String toString(boolean includePrivate, @Nullable KeyParameter aesKey, Network network) {
|
||||
private String toString(boolean includePrivate, @Nullable AesKey aesKey, Network network) {
|
||||
final MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(this).omitNullValues();
|
||||
helper.add("pub HEX", getPublicKeyAsHex());
|
||||
if (includePrivate) {
|
||||
@ -1328,16 +1327,16 @@ public class ECKey implements EncryptableItem {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #toString(boolean, KeyParameter, Network)}
|
||||
* @deprecated Use {@link #toString(boolean, AesKey, Network)}
|
||||
*/
|
||||
@Deprecated
|
||||
private String toString(boolean includePrivate, @Nullable KeyParameter aesKey, @Nullable NetworkParameters params) {
|
||||
private String toString(boolean includePrivate, @Nullable AesKey aesKey, @Nullable NetworkParameters params) {
|
||||
Network network = (params != null) ? params.network() : BitcoinNetwork.MAINNET;
|
||||
return toString(includePrivate, aesKey, network);
|
||||
}
|
||||
|
||||
|
||||
public void formatKeyWithAddress(boolean includePrivateKeys, @Nullable KeyParameter aesKey, StringBuilder builder,
|
||||
public void formatKeyWithAddress(boolean includePrivateKeys, @Nullable AesKey aesKey, StringBuilder builder,
|
||||
Network network, ScriptType outputScriptType, @Nullable String comment) {
|
||||
builder.append(" addr:");
|
||||
if (outputScriptType != null) {
|
||||
@ -1365,10 +1364,10 @@ public class ECKey implements EncryptableItem {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #formatKeyWithAddress(boolean, KeyParameter, StringBuilder, Network, ScriptType, String)}
|
||||
* @deprecated Use {@link #formatKeyWithAddress(boolean, AesKey, StringBuilder, Network, ScriptType, String)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void formatKeyWithAddress(boolean includePrivateKeys, @Nullable KeyParameter aesKey, StringBuilder builder,
|
||||
public void formatKeyWithAddress(boolean includePrivateKeys, @Nullable AesKey aesKey, StringBuilder builder,
|
||||
NetworkParameters params, ScriptType outputScriptType, @Nullable String comment) {
|
||||
formatKeyWithAddress(includePrivateKeys, aesKey, builder, params.network(), outputScriptType, comment);
|
||||
}
|
||||
|
@ -17,7 +17,6 @@
|
||||
package org.bitcoinj.crypto;
|
||||
|
||||
import org.bitcoinj.wallet.Protos.Wallet.EncryptionType;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
|
||||
/**
|
||||
* <p>A KeyCrypter can be used to encrypt and decrypt a message. The sequence of events to encrypt and then decrypt
|
||||
@ -41,19 +40,19 @@ public interface KeyCrypter {
|
||||
EncryptionType getUnderstoodEncryptionType();
|
||||
|
||||
/**
|
||||
* Create a KeyParameter (which typically contains an AES key)
|
||||
* Create an AESKey (which typically contains an AES key)
|
||||
* @param password
|
||||
* @return KeyParameter The KeyParameter which typically contains the AES key to use for encrypting and decrypting
|
||||
* @return AESKey which typically contains the AES key to use for encrypting and decrypting
|
||||
* @throws KeyCrypterException
|
||||
*/
|
||||
KeyParameter deriveKey(CharSequence password) throws KeyCrypterException;
|
||||
AesKey deriveKey(CharSequence password) throws KeyCrypterException;
|
||||
|
||||
/**
|
||||
* Decrypt the provided encrypted bytes, converting them into unencrypted bytes.
|
||||
*
|
||||
* @throws KeyCrypterException if decryption was unsuccessful.
|
||||
*/
|
||||
byte[] decrypt(EncryptedData encryptedBytesToDecode, KeyParameter aesKey) throws KeyCrypterException;
|
||||
byte[] decrypt(EncryptedData encryptedBytesToDecode, AesKey aesKey) throws KeyCrypterException;
|
||||
|
||||
/**
|
||||
* Encrypt the supplied bytes, converting them into ciphertext.
|
||||
@ -61,5 +60,5 @@ public interface KeyCrypter {
|
||||
* @return encryptedPrivateKey An encryptedPrivateKey containing the encrypted bytes and an initialisation vector.
|
||||
* @throws KeyCrypterException if encryption was unsuccessful
|
||||
*/
|
||||
EncryptedData encrypt(byte[] plainBytes, KeyParameter aesKey) throws KeyCrypterException;
|
||||
EncryptedData encrypt(byte[] plainBytes, AesKey aesKey) throws KeyCrypterException;
|
||||
}
|
||||
|
@ -135,11 +135,11 @@ public class KeyCrypterScrypt implements KeyCrypter {
|
||||
* This is a very slow operation compared to encrypt/ decrypt so it is normally worth caching the result.
|
||||
*
|
||||
* @param password The password to use in key generation
|
||||
* @return The KeyParameter containing the created AES key
|
||||
* @return The AesKey containing the created AES key
|
||||
* @throws KeyCrypterException
|
||||
*/
|
||||
@Override
|
||||
public KeyParameter deriveKey(CharSequence password) throws KeyCrypterException {
|
||||
public AesKey deriveKey(CharSequence password) throws KeyCrypterException {
|
||||
byte[] passwordBytes = null;
|
||||
try {
|
||||
passwordBytes = convertToByteArray(password);
|
||||
@ -155,7 +155,7 @@ public class KeyCrypterScrypt implements KeyCrypter {
|
||||
Instant start = TimeUtils.currentTime();
|
||||
byte[] keyBytes = SCrypt.generate(passwordBytes, salt, (int) scryptParameters.getN(), scryptParameters.getR(), scryptParameters.getP(), KEY_LENGTH);
|
||||
log.info("Deriving key took {} ms for {}.", TimeUtils.elapsedTime(start).toMillis(), scryptParametersString());
|
||||
return new KeyParameter(keyBytes);
|
||||
return new AesKey(keyBytes);
|
||||
} catch (Exception e) {
|
||||
throw new KeyCrypterException("Could not generate key from password and salt.", e);
|
||||
} finally {
|
||||
@ -170,7 +170,7 @@ public class KeyCrypterScrypt implements KeyCrypter {
|
||||
* Password based encryption using AES - CBC 256 bits.
|
||||
*/
|
||||
@Override
|
||||
public EncryptedData encrypt(byte[] plainBytes, KeyParameter aesKey) throws KeyCrypterException {
|
||||
public EncryptedData encrypt(byte[] plainBytes, AesKey aesKey) throws KeyCrypterException {
|
||||
checkNotNull(plainBytes);
|
||||
checkNotNull(aesKey);
|
||||
|
||||
@ -179,7 +179,7 @@ public class KeyCrypterScrypt implements KeyCrypter {
|
||||
byte[] iv = new byte[BLOCK_LENGTH];
|
||||
secureRandom.nextBytes(iv);
|
||||
|
||||
ParametersWithIV keyWithIv = new ParametersWithIV(aesKey, iv);
|
||||
ParametersWithIV keyWithIv = new ParametersWithIV(new KeyParameter(aesKey.bytes()), iv);
|
||||
|
||||
// Encrypt using AES.
|
||||
BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESEngine()));
|
||||
@ -203,12 +203,12 @@ public class KeyCrypterScrypt implements KeyCrypter {
|
||||
* @throws KeyCrypterException if bytes could not be decrypted
|
||||
*/
|
||||
@Override
|
||||
public byte[] decrypt(EncryptedData dataToDecrypt, KeyParameter aesKey) throws KeyCrypterException {
|
||||
public byte[] decrypt(EncryptedData dataToDecrypt, AesKey aesKey) throws KeyCrypterException {
|
||||
checkNotNull(dataToDecrypt);
|
||||
checkNotNull(aesKey);
|
||||
|
||||
try {
|
||||
ParametersWithIV keyWithIv = new ParametersWithIV(new KeyParameter(aesKey.getKey()), dataToDecrypt.initialisationVector);
|
||||
ParametersWithIV keyWithIv = new ParametersWithIV(new KeyParameter(aesKey.bytes()), dataToDecrypt.initialisationVector);
|
||||
|
||||
// Decrypt the message.
|
||||
BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESEngine()));
|
||||
|
@ -18,6 +18,7 @@
|
||||
package org.bitcoinj.wallet;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import org.bitcoinj.crypto.AesKey;
|
||||
import org.bitcoinj.core.BloomFilter;
|
||||
import org.bitcoinj.crypto.ECKey;
|
||||
import org.bitcoinj.core.NetworkParameters;
|
||||
@ -29,12 +30,10 @@ import org.bitcoinj.crypto.KeyCrypterScrypt;
|
||||
import org.bitcoinj.utils.ListenerRegistration;
|
||||
import org.bitcoinj.utils.Threading;
|
||||
import org.bitcoinj.wallet.listeners.KeyChainEventListener;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
@ -462,7 +461,7 @@ public class BasicKeyChain implements EncryptableKeyChain {
|
||||
|
||||
/**
|
||||
* Convenience wrapper around {@link #toEncrypted(KeyCrypter,
|
||||
* org.bouncycastle.crypto.params.KeyParameter)} which uses the default Scrypt key derivation algorithm and
|
||||
* AesKey)} which uses the default Scrypt key derivation algorithm and
|
||||
* parameters, derives a key from the given password and returns the created key.
|
||||
*/
|
||||
@Override
|
||||
@ -470,7 +469,7 @@ public class BasicKeyChain implements EncryptableKeyChain {
|
||||
checkNotNull(password);
|
||||
checkArgument(password.length() > 0);
|
||||
KeyCrypter scrypt = new KeyCrypterScrypt();
|
||||
KeyParameter derivedKey = scrypt.deriveKey(password);
|
||||
AesKey derivedKey = scrypt.deriveKey(password);
|
||||
return toEncrypted(scrypt, derivedKey);
|
||||
}
|
||||
|
||||
@ -484,7 +483,7 @@ public class BasicKeyChain implements EncryptableKeyChain {
|
||||
* @throws KeyCrypterException Thrown if the wallet encryption fails. If so, the wallet state is unchanged.
|
||||
*/
|
||||
@Override
|
||||
public BasicKeyChain toEncrypted(KeyCrypter keyCrypter, KeyParameter aesKey) {
|
||||
public BasicKeyChain toEncrypted(KeyCrypter keyCrypter, AesKey aesKey) {
|
||||
lock.lock();
|
||||
try {
|
||||
checkNotNull(keyCrypter);
|
||||
@ -513,12 +512,12 @@ public class BasicKeyChain implements EncryptableKeyChain {
|
||||
@Override
|
||||
public BasicKeyChain toDecrypted(CharSequence password) {
|
||||
checkNotNull(keyCrypter, "Wallet is already decrypted");
|
||||
KeyParameter aesKey = keyCrypter.deriveKey(password);
|
||||
AesKey aesKey = keyCrypter.deriveKey(password);
|
||||
return toDecrypted(aesKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicKeyChain toDecrypted(KeyParameter aesKey) {
|
||||
public BasicKeyChain toDecrypted(AesKey aesKey) {
|
||||
lock.lock();
|
||||
try {
|
||||
checkState(keyCrypter != null, "Wallet is already decrypted");
|
||||
@ -555,7 +554,7 @@ public class BasicKeyChain implements EncryptableKeyChain {
|
||||
* @return true if AES key supplied can decrypt the first encrypted private key in the wallet, false otherwise.
|
||||
*/
|
||||
@Override
|
||||
public boolean checkAESKey(KeyParameter aesKey) {
|
||||
public boolean checkAESKey(AesKey aesKey) {
|
||||
lock.lock();
|
||||
try {
|
||||
// If no keys then cannot decrypt.
|
||||
@ -652,7 +651,7 @@ public class BasicKeyChain implements EncryptableKeyChain {
|
||||
}
|
||||
}
|
||||
|
||||
public String toString(boolean includePrivateKeys, @Nullable KeyParameter aesKey, NetworkParameters params) {
|
||||
public String toString(boolean includePrivateKeys, @Nullable AesKey aesKey, NetworkParameters params) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
List<ECKey> keys = getKeys();
|
||||
Collections.sort(keys, ECKey.AGE_COMPARATOR);
|
||||
|
@ -17,8 +17,8 @@
|
||||
package org.bitcoinj.wallet;
|
||||
|
||||
import org.bitcoinj.base.ScriptType;
|
||||
import org.bitcoinj.crypto.AesKey;
|
||||
import org.bitcoinj.crypto.ECKey;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
@ -33,9 +33,9 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||
*/
|
||||
public class DecryptingKeyBag implements KeyBag {
|
||||
protected final KeyBag target;
|
||||
protected final KeyParameter aesKey;
|
||||
protected final AesKey aesKey;
|
||||
|
||||
public DecryptingKeyBag(KeyBag target, @Nullable KeyParameter aesKey) {
|
||||
public DecryptingKeyBag(KeyBag target, @Nullable AesKey aesKey) {
|
||||
this.target = checkNotNull(target);
|
||||
this.aesKey = aesKey;
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import com.google.protobuf.ByteString;
|
||||
import org.bitcoinj.base.Network;
|
||||
import org.bitcoinj.base.ScriptType;
|
||||
import org.bitcoinj.base.internal.TimeUtils;
|
||||
import org.bitcoinj.crypto.AesKey;
|
||||
import org.bitcoinj.base.utils.ByteUtils;
|
||||
import org.bitcoinj.base.internal.StreamUtils;
|
||||
import org.bitcoinj.core.BloomFilter;
|
||||
@ -42,7 +43,6 @@ import org.bitcoinj.script.Script;
|
||||
import org.bitcoinj.utils.ListenerRegistration;
|
||||
import org.bitcoinj.utils.Threading;
|
||||
import org.bitcoinj.wallet.listeners.KeyChainEventListener;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -401,12 +401,12 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
|
||||
}
|
||||
|
||||
/**
|
||||
* For use in encryption when {@link #toEncrypted(KeyCrypter, KeyParameter)} is called, so that
|
||||
* For use in encryption when {@link #toEncrypted(KeyCrypter, AesKey)} is called, so that
|
||||
* subclasses can override that method and create an instance of the right class.
|
||||
*
|
||||
* See also {@link #makeKeyChainFromSeed(DeterministicSeed, List, ScriptType)}
|
||||
*/
|
||||
protected DeterministicKeyChain(KeyCrypter crypter, KeyParameter aesKey, DeterministicKeyChain chain) {
|
||||
protected DeterministicKeyChain(KeyCrypter crypter, AesKey aesKey, DeterministicKeyChain chain) {
|
||||
// Can't encrypt a watching chain.
|
||||
checkNotNull(chain.rootKey);
|
||||
checkNotNull(chain.seed);
|
||||
@ -453,7 +453,7 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
|
||||
return outputScriptType;
|
||||
}
|
||||
|
||||
private DeterministicKey encryptNonLeaf(KeyParameter aesKey, DeterministicKeyChain chain,
|
||||
private DeterministicKey encryptNonLeaf(AesKey aesKey, DeterministicKeyChain chain,
|
||||
DeterministicKey parent, List<ChildNumber> path) {
|
||||
DeterministicKey key = chain.hierarchy.get(path, false, false);
|
||||
key = key.encrypt(checkNotNull(basicKeyChain.getKeyCrypter()), aesKey, parent);
|
||||
@ -1017,12 +1017,12 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
|
||||
checkState(seed != null, "Attempt to encrypt a watching chain.");
|
||||
checkState(!seed.isEncrypted());
|
||||
KeyCrypter scrypt = new KeyCrypterScrypt();
|
||||
KeyParameter derivedKey = scrypt.deriveKey(password);
|
||||
AesKey derivedKey = scrypt.deriveKey(password);
|
||||
return toEncrypted(scrypt, derivedKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeterministicKeyChain toEncrypted(KeyCrypter keyCrypter, KeyParameter aesKey) {
|
||||
public DeterministicKeyChain toEncrypted(KeyCrypter keyCrypter, AesKey aesKey) {
|
||||
return new DeterministicKeyChain(keyCrypter, aesKey, this);
|
||||
}
|
||||
|
||||
@ -1032,12 +1032,12 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
|
||||
checkArgument(password.length() > 0);
|
||||
KeyCrypter crypter = getKeyCrypter();
|
||||
checkState(crypter != null, "Chain not encrypted");
|
||||
KeyParameter derivedKey = crypter.deriveKey(password);
|
||||
AesKey derivedKey = crypter.deriveKey(password);
|
||||
return toDecrypted(derivedKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeterministicKeyChain toDecrypted(KeyParameter aesKey) {
|
||||
public DeterministicKeyChain toDecrypted(AesKey aesKey) {
|
||||
checkState(getKeyCrypter() != null, "Key chain not encrypted");
|
||||
checkState(seed != null, "Can't decrypt a watching chain");
|
||||
checkState(seed.isEncrypted());
|
||||
@ -1080,7 +1080,7 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkAESKey(KeyParameter aesKey) {
|
||||
public boolean checkAESKey(AesKey aesKey) {
|
||||
checkState(rootKey != null, "Can't check password for a watching chain");
|
||||
checkNotNull(aesKey);
|
||||
checkState(getKeyCrypter() != null, "Key chain not encrypted");
|
||||
@ -1422,7 +1422,7 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
|
||||
return helper.toString();
|
||||
}
|
||||
|
||||
public String toString(boolean includeLookahead, boolean includePrivateKeys, @Nullable KeyParameter aesKey, NetworkParameters params) {
|
||||
public String toString(boolean includeLookahead, boolean includePrivateKeys, @Nullable AesKey aesKey, NetworkParameters params) {
|
||||
final DeterministicKey watchingKey = getWatchingKey();
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
if (seed != null) {
|
||||
@ -1451,7 +1451,7 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
protected void formatAddresses(boolean includeLookahead, boolean includePrivateKeys, @Nullable KeyParameter aesKey,
|
||||
protected void formatAddresses(boolean includeLookahead, boolean includePrivateKeys, @Nullable AesKey aesKey,
|
||||
NetworkParameters params, StringBuilder builder) {
|
||||
for (DeterministicKey key : getKeys(includeLookahead, true)) {
|
||||
String comment = null;
|
||||
|
@ -20,12 +20,12 @@ package org.bitcoinj.wallet;
|
||||
import com.google.common.base.MoreObjects;
|
||||
import org.bitcoinj.base.internal.TimeUtils;
|
||||
import org.bitcoinj.base.internal.InternalUtils;
|
||||
import org.bitcoinj.crypto.AesKey;
|
||||
import org.bitcoinj.crypto.EncryptableItem;
|
||||
import org.bitcoinj.crypto.EncryptedData;
|
||||
import org.bitcoinj.crypto.KeyCrypter;
|
||||
import org.bitcoinj.crypto.MnemonicCode;
|
||||
import org.bitcoinj.crypto.MnemonicException;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@ -193,7 +193,7 @@ public class DeterministicSeed implements EncryptableItem {
|
||||
this.creationTimeSeconds = creationTimeSeconds;
|
||||
}
|
||||
|
||||
public DeterministicSeed encrypt(KeyCrypter keyCrypter, KeyParameter aesKey) {
|
||||
public DeterministicSeed encrypt(KeyCrypter keyCrypter, AesKey aesKey) {
|
||||
checkState(encryptedMnemonicCode == null, "Trying to encrypt seed twice");
|
||||
checkState(mnemonicCode != null, "Mnemonic missing so cannot encrypt");
|
||||
EncryptedData encryptedMnemonic = keyCrypter.encrypt(getMnemonicAsBytes(), aesKey);
|
||||
@ -205,7 +205,7 @@ public class DeterministicSeed implements EncryptableItem {
|
||||
return getMnemonicString().getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public DeterministicSeed decrypt(KeyCrypter crypter, String passphrase, KeyParameter aesKey) {
|
||||
public DeterministicSeed decrypt(KeyCrypter crypter, String passphrase, AesKey aesKey) {
|
||||
checkState(isEncrypted());
|
||||
checkNotNull(encryptedMnemonicCode);
|
||||
List<String> mnemonic = decodeMnemonicCode(crypter.decrypt(encryptedMnemonicCode, aesKey));
|
||||
|
@ -16,10 +16,10 @@
|
||||
|
||||
package org.bitcoinj.wallet;
|
||||
|
||||
import org.bitcoinj.crypto.AesKey;
|
||||
import org.bitcoinj.crypto.KeyCrypter;
|
||||
import org.bitcoinj.crypto.KeyCrypterException;
|
||||
import org.bitcoinj.crypto.KeyCrypterScrypt;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@ -29,7 +29,7 @@ import javax.annotation.Nullable;
|
||||
public interface EncryptableKeyChain extends KeyChain {
|
||||
/**
|
||||
* Takes the given password, which should be strong, derives a key from it and then invokes
|
||||
* {@link #toEncrypted(KeyCrypter, KeyParameter)} with
|
||||
* {@link #toEncrypted(KeyCrypter, AesKey)} with
|
||||
* {@link KeyCrypterScrypt} as the crypter.
|
||||
*
|
||||
* @return The derived key, in case you wish to cache it for future use.
|
||||
@ -40,10 +40,10 @@ public interface EncryptableKeyChain extends KeyChain {
|
||||
* Returns a new keychain holding identical/cloned keys to this chain, but encrypted under the given key.
|
||||
* Old keys and keychains remain valid and so you should ensure you don't accidentally hold references to them.
|
||||
*/
|
||||
EncryptableKeyChain toEncrypted(KeyCrypter keyCrypter, KeyParameter aesKey);
|
||||
EncryptableKeyChain toEncrypted(KeyCrypter keyCrypter, AesKey aesKey);
|
||||
|
||||
/**
|
||||
* Decrypts the key chain with the given password. See {@link #toDecrypted(KeyParameter)}
|
||||
* Decrypts the key chain with the given password. See {@link #toDecrypted(AesKey)}
|
||||
* for details.
|
||||
*/
|
||||
EncryptableKeyChain toDecrypted(CharSequence password);
|
||||
@ -57,10 +57,10 @@ public interface EncryptableKeyChain extends KeyChain {
|
||||
* create from a password)
|
||||
* @throws KeyCrypterException Thrown if the wallet decryption fails. If so, the wallet state is unchanged.
|
||||
*/
|
||||
EncryptableKeyChain toDecrypted(KeyParameter aesKey);
|
||||
EncryptableKeyChain toDecrypted(AesKey aesKey);
|
||||
|
||||
boolean checkPassword(CharSequence password);
|
||||
boolean checkAESKey(KeyParameter aesKey);
|
||||
boolean checkAESKey(AesKey aesKey);
|
||||
|
||||
/** Returns the key crypter used by this key chain, or null if it's not encrypted. */
|
||||
@Nullable
|
||||
|
@ -20,6 +20,7 @@ package org.bitcoinj.wallet;
|
||||
import com.google.protobuf.ByteString;
|
||||
import org.bitcoinj.base.BitcoinNetwork;
|
||||
import org.bitcoinj.base.Address;
|
||||
import org.bitcoinj.crypto.AesKey;
|
||||
import org.bitcoinj.core.BloomFilter;
|
||||
import org.bitcoinj.crypto.ECKey;
|
||||
import org.bitcoinj.base.LegacyAddress;
|
||||
@ -36,7 +37,6 @@ import org.bitcoinj.utils.ListenerRegistration;
|
||||
import org.bitcoinj.utils.Threading;
|
||||
import org.bitcoinj.wallet.listeners.CurrentKeyChangeEventListener;
|
||||
import org.bitcoinj.wallet.listeners.KeyChainEventListener;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -71,7 +71,7 @@ import static com.google.common.base.Preconditions.checkState;
|
||||
* (see {@link #getActiveKeyChain(ScriptType, long)}) are meant as fallback for if a sender doesn't understand a
|
||||
* certain new script type (e.g. P2WPKH which comes with the new Bech32 address format). Active keychains
|
||||
* share the same seed, so that upgrading the wallet
|
||||
* (see {@link #upgradeToDeterministic(ScriptType, KeyChainGroupStructure, long, KeyParameter)}) to understand
|
||||
* (see {@link #upgradeToDeterministic(ScriptType, KeyChainGroupStructure, long, AesKey)}) to understand
|
||||
* a new script type doesn't require a fresh backup.</p>
|
||||
*
|
||||
* <p>If a key rotation time is set, it may be necessary to add a new DeterministicKeyChain with a fresh seed
|
||||
@ -569,7 +569,7 @@ public class KeyChainGroup implements KeyBag {
|
||||
return checkAESKey(keyCrypter.deriveKey(password));
|
||||
}
|
||||
|
||||
public boolean checkAESKey(KeyParameter aesKey) {
|
||||
public boolean checkAESKey(AesKey aesKey) {
|
||||
checkState(keyCrypter != null, "Not encrypted");
|
||||
if (basic.numKeys() > 0)
|
||||
return basic.checkAESKey(aesKey);
|
||||
@ -577,7 +577,7 @@ public class KeyChainGroup implements KeyBag {
|
||||
}
|
||||
|
||||
/** Imports the given unencrypted keys into the basic chain, encrypting them along the way with the given key. */
|
||||
public int importKeysAndEncrypt(final List<ECKey> keys, KeyParameter aesKey) {
|
||||
public int importKeysAndEncrypt(final List<ECKey> keys, AesKey aesKey) {
|
||||
// TODO: Firstly check if the aes key can decrypt any of the existing keys successfully.
|
||||
checkState(keyCrypter != null, "Not encrypted");
|
||||
LinkedList<ECKey> encryptedKeys = new LinkedList<>();
|
||||
@ -756,7 +756,7 @@ public class KeyChainGroup implements KeyBag {
|
||||
* leaving the group unchanged.
|
||||
* @throws DeterministicUpgradeRequiredException Thrown if there are random keys but no HD chain.
|
||||
*/
|
||||
public void encrypt(KeyCrypter keyCrypter, KeyParameter aesKey) {
|
||||
public void encrypt(KeyCrypter keyCrypter, AesKey aesKey) {
|
||||
checkNotNull(keyCrypter);
|
||||
checkNotNull(aesKey);
|
||||
checkState((chains != null && !chains.isEmpty()) || basic.numKeys() != 0, "can't encrypt entirely empty wallet");
|
||||
@ -783,7 +783,7 @@ public class KeyChainGroup implements KeyBag {
|
||||
*
|
||||
* @throws org.bitcoinj.crypto.KeyCrypterException Thrown if the wallet decryption fails for some reason, leaving the group unchanged.
|
||||
*/
|
||||
public void decrypt(KeyParameter aesKey) {
|
||||
public void decrypt(AesKey aesKey) {
|
||||
checkNotNull(aesKey);
|
||||
|
||||
BasicKeyChain newBasic = basic.toDecrypted(aesKey);
|
||||
@ -1011,7 +1011,7 @@ public class KeyChainGroup implements KeyBag {
|
||||
* and you should provide the users encryption key.
|
||||
*/
|
||||
public void upgradeToDeterministic(ScriptType preferredScriptType, KeyChainGroupStructure structure,
|
||||
@Nullable Instant keyRotationTime, @Nullable KeyParameter aesKey)
|
||||
@Nullable Instant keyRotationTime, @Nullable AesKey aesKey)
|
||||
throws DeterministicUpgradeRequiresPassword {
|
||||
checkState(supportsDeterministicChains(), "doesn't support deterministic chains");
|
||||
checkNotNull(structure);
|
||||
@ -1038,16 +1038,16 @@ public class KeyChainGroup implements KeyBag {
|
||||
}
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #upgradeToDeterministic(ScriptType, KeyChainGroupStructure, Instant, KeyParameter)} */
|
||||
/** @deprecated use {@link #upgradeToDeterministic(ScriptType, KeyChainGroupStructure, Instant, AesKey)} */
|
||||
@Deprecated
|
||||
public void upgradeToDeterministic(ScriptType preferredScriptType, KeyChainGroupStructure structure,
|
||||
long keyRotationTimeSecs, @Nullable KeyParameter aesKey) {
|
||||
long keyRotationTimeSecs, @Nullable AesKey aesKey) {
|
||||
Instant keyRotationTime = keyRotationTimeSecs > 0 ? Instant.ofEpochSecond(keyRotationTimeSecs) : null;
|
||||
upgradeToDeterministic(preferredScriptType, structure, keyRotationTime, aesKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a call to {@link #upgradeToDeterministic(ScriptType, KeyChainGroupStructure, long, KeyParameter)} is required
|
||||
* Returns true if a call to {@link #upgradeToDeterministic(ScriptType, KeyChainGroupStructure, long, AesKey)} is required
|
||||
* in order to have an active deterministic keychain of the desired script type.
|
||||
*/
|
||||
public boolean isDeterministicUpgradeRequired(ScriptType preferredScriptType, @Nullable Instant keyRotationTime) {
|
||||
@ -1108,7 +1108,7 @@ public class KeyChainGroup implements KeyBag {
|
||||
}
|
||||
}
|
||||
|
||||
public String toString(boolean includeLookahead, boolean includePrivateKeys, @Nullable KeyParameter aesKey) {
|
||||
public String toString(boolean includeLookahead, boolean includePrivateKeys, @Nullable AesKey aesKey) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
if (basic != null)
|
||||
builder.append(basic.toString(includePrivateKeys, aesKey, params));
|
||||
|
@ -19,6 +19,7 @@ package org.bitcoinj.wallet;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.protobuf.ByteString;
|
||||
import org.bitcoinj.base.ScriptType;
|
||||
import org.bitcoinj.crypto.AesKey;
|
||||
import org.bitcoinj.base.utils.ByteUtils;
|
||||
import org.bitcoinj.core.BloomFilter;
|
||||
import org.bitcoinj.crypto.ECKey;
|
||||
@ -28,7 +29,6 @@ import org.bitcoinj.crypto.DeterministicKey;
|
||||
import org.bitcoinj.crypto.KeyCrypter;
|
||||
import org.bitcoinj.script.Script;
|
||||
import org.bitcoinj.script.ScriptBuilder;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
@ -237,7 +237,7 @@ public class MarriedKeyChain extends DeterministicKeyChain {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void formatAddresses(boolean includeLookahead, boolean includePrivateKeys, @Nullable KeyParameter aesKey,
|
||||
protected void formatAddresses(boolean includeLookahead, boolean includePrivateKeys, @Nullable AesKey aesKey,
|
||||
NetworkParameters params, StringBuilder builder) {
|
||||
for (DeterministicKeyChain followingChain : followingKeyChains)
|
||||
builder.append("Following chain: ").append(followingChain.getWatchingKey().serializePubB58(params.network()))
|
||||
|
@ -21,6 +21,7 @@ import com.google.common.base.MoreObjects;
|
||||
import org.bitcoin.protocols.payments.Protos.PaymentDetails;
|
||||
import org.bitcoinj.base.Address;
|
||||
import org.bitcoinj.base.Coin;
|
||||
import org.bitcoinj.crypto.AesKey;
|
||||
import org.bitcoinj.core.Context;
|
||||
import org.bitcoinj.crypto.ECKey;
|
||||
import org.bitcoinj.core.NetworkParameters;
|
||||
@ -29,7 +30,6 @@ import org.bitcoinj.core.TransactionOutput;
|
||||
import org.bitcoinj.utils.ExchangeRate;
|
||||
import org.bitcoinj.wallet.KeyChain.KeyPurpose;
|
||||
import org.bitcoinj.wallet.Wallet.MissingSigsMode;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
@ -109,7 +109,7 @@ public class SendRequest {
|
||||
* If null then no decryption will be performed and if decryption is required an exception will be thrown.
|
||||
* You can get this from a password by doing wallet.getKeyCrypter().deriveKey(password).
|
||||
*/
|
||||
public KeyParameter aesKey = null;
|
||||
public AesKey aesKey = null;
|
||||
|
||||
/**
|
||||
* If not null, the {@link CoinSelector} to use instead of the wallets default. Coin selectors are
|
||||
|
@ -30,6 +30,7 @@ import org.bitcoinj.base.exceptions.AddressFormatException;
|
||||
import org.bitcoinj.base.internal.PlatformUtils;
|
||||
import org.bitcoinj.base.internal.TimeUtils;
|
||||
import org.bitcoinj.base.internal.StreamUtils;
|
||||
import org.bitcoinj.crypto.AesKey;
|
||||
import org.bitcoinj.core.AbstractBlockChain;
|
||||
import org.bitcoinj.base.Address;
|
||||
import org.bitcoinj.base.Base58;
|
||||
@ -98,7 +99,6 @@ import org.bitcoinj.wallet.listeners.WalletChangeEventListener;
|
||||
import org.bitcoinj.wallet.listeners.WalletCoinsReceivedEventListener;
|
||||
import org.bitcoinj.wallet.listeners.WalletCoinsSentEventListener;
|
||||
import org.bitcoinj.wallet.listeners.WalletReorganizeEventListener;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -792,7 +792,7 @@ public class Wallet extends BaseTaggableObject
|
||||
* to do this will result in an exception being thrown. For non-encrypted wallets, the upgrade will be done for
|
||||
* you automatically the first time a new key is requested (this happens when spending due to the change address).
|
||||
*/
|
||||
public void upgradeToDeterministic(ScriptType outputScriptType, @Nullable KeyParameter aesKey)
|
||||
public void upgradeToDeterministic(ScriptType outputScriptType, @Nullable AesKey aesKey)
|
||||
throws DeterministicUpgradeRequiresPassword {
|
||||
upgradeToDeterministic(outputScriptType, KeyChainGroupStructure.BIP32, aesKey);
|
||||
}
|
||||
@ -805,7 +805,7 @@ public class Wallet extends BaseTaggableObject
|
||||
* you automatically the first time a new key is requested (this happens when spending due to the change address).
|
||||
*/
|
||||
public void upgradeToDeterministic(ScriptType outputScriptType, KeyChainGroupStructure structure,
|
||||
@Nullable KeyParameter aesKey) throws DeterministicUpgradeRequiresPassword {
|
||||
@Nullable AesKey aesKey) throws DeterministicUpgradeRequiresPassword {
|
||||
keyChainGroupLock.lock();
|
||||
try {
|
||||
Instant keyRotationTime = vKeyRotationTime;
|
||||
@ -817,7 +817,7 @@ public class Wallet extends BaseTaggableObject
|
||||
|
||||
/**
|
||||
* Returns true if the wallet contains random keys and no HD chains, in which case you should call
|
||||
* {@link #upgradeToDeterministic(ScriptType, KeyParameter)} before attempting to do anything
|
||||
* {@link #upgradeToDeterministic(ScriptType, AesKey)} before attempting to do anything
|
||||
* that would require a new address or key.
|
||||
*/
|
||||
public boolean isDeterministicUpgradeRequired(ScriptType outputScriptType) {
|
||||
@ -945,7 +945,7 @@ public class Wallet extends BaseTaggableObject
|
||||
}
|
||||
|
||||
/** Takes a list of keys and an AES key, then encrypts and imports them in one step using the current keycrypter. */
|
||||
public int importKeysAndEncrypt(final List<ECKey> keys, KeyParameter aesKey) {
|
||||
public int importKeysAndEncrypt(final List<ECKey> keys, AesKey aesKey) {
|
||||
keyChainGroupLock.lock();
|
||||
try {
|
||||
checkNoDeterministicKeys(keys);
|
||||
@ -1341,7 +1341,7 @@ public class Wallet extends BaseTaggableObject
|
||||
|
||||
/**
|
||||
* Convenience wrapper around {@link Wallet#encrypt(KeyCrypter,
|
||||
* org.bouncycastle.crypto.params.KeyParameter)} which uses the default Scrypt key derivation algorithm and
|
||||
* AesKey)} which uses the default Scrypt key derivation algorithm and
|
||||
* parameters to derive a key from the given password.
|
||||
*/
|
||||
public void encrypt(CharSequence password) {
|
||||
@ -1363,7 +1363,7 @@ public class Wallet extends BaseTaggableObject
|
||||
* @param aesKey AES key to use (normally created using KeyCrypter#deriveKey and cached as it is time consuming to create from a password)
|
||||
* @throws KeyCrypterException Thrown if the wallet encryption fails. If so, the wallet state is unchanged.
|
||||
*/
|
||||
public void encrypt(KeyCrypter keyCrypter, KeyParameter aesKey) {
|
||||
public void encrypt(KeyCrypter keyCrypter, AesKey aesKey) {
|
||||
keyChainGroupLock.lock();
|
||||
try {
|
||||
keyChainGroup.encrypt(keyCrypter, aesKey);
|
||||
@ -1399,7 +1399,7 @@ public class Wallet extends BaseTaggableObject
|
||||
* @throws BadWalletEncryptionKeyException Thrown if the given aesKey is wrong. If so, the wallet state is unchanged.
|
||||
* @throws KeyCrypterException Thrown if the wallet decryption fails. If so, the wallet state is unchanged.
|
||||
*/
|
||||
public void decrypt(KeyParameter aesKey) throws BadWalletEncryptionKeyException {
|
||||
public void decrypt(AesKey aesKey) throws BadWalletEncryptionKeyException {
|
||||
keyChainGroupLock.lock();
|
||||
try {
|
||||
keyChainGroup.decrypt(aesKey);
|
||||
@ -1432,7 +1432,7 @@ public class Wallet extends BaseTaggableObject
|
||||
*
|
||||
* @return boolean true if AES key supplied can decrypt the first encrypted private key in the wallet, false otherwise.
|
||||
*/
|
||||
public boolean checkAESKey(KeyParameter aesKey) {
|
||||
public boolean checkAESKey(AesKey aesKey) {
|
||||
keyChainGroupLock.lock();
|
||||
try {
|
||||
return keyChainGroup.checkAESKey(aesKey);
|
||||
@ -1498,7 +1498,7 @@ public class Wallet extends BaseTaggableObject
|
||||
* @throws BadWalletEncryptionKeyException Thrown if the given currentAesKey is wrong. If so, the wallet state is unchanged.
|
||||
* @throws KeyCrypterException Thrown if the wallet decryption fails. If so, the wallet state is unchanged.
|
||||
*/
|
||||
public void changeEncryptionKey(KeyCrypter keyCrypter, KeyParameter currentAesKey, KeyParameter newAesKey) throws BadWalletEncryptionKeyException {
|
||||
public void changeEncryptionKey(KeyCrypter keyCrypter, AesKey currentAesKey, AesKey newAesKey) throws BadWalletEncryptionKeyException {
|
||||
keyChainGroupLock.lock();
|
||||
try {
|
||||
decrypt(currentAesKey);
|
||||
@ -3458,7 +3458,7 @@ public class Wallet extends BaseTaggableObject
|
||||
* @param chain If set, will be used to estimate lock times for block time-locked transactions.
|
||||
* @return Human-readable wallet debugging information
|
||||
*/
|
||||
public String toString(boolean includeLookahead, boolean includePrivateKeys, @Nullable KeyParameter aesKey,
|
||||
public String toString(boolean includeLookahead, boolean includePrivateKeys, @Nullable AesKey aesKey,
|
||||
boolean includeTransactions, boolean includeExtensions, @Nullable AbstractBlockChain chain) {
|
||||
lock.lock();
|
||||
keyChainGroupLock.lock();
|
||||
@ -5318,7 +5318,7 @@ public class Wallet extends BaseTaggableObject
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Once set up, calling {@link #doMaintenance(KeyParameter, boolean)} will create and possibly send rotation
|
||||
* Once set up, calling {@link #doMaintenance(AesKey, boolean)} will create and possibly send rotation
|
||||
* transactions: but it won't be done automatically (because you might have to ask for the users password). This may
|
||||
* need to be repeated regularly in case new coins keep coming in on rotating addresses/keys.
|
||||
* </p>
|
||||
@ -5392,7 +5392,7 @@ public class Wallet extends BaseTaggableObject
|
||||
* @return A list of transactions that the wallet just made/will make for internal maintenance. Might be empty.
|
||||
* @throws org.bitcoinj.wallet.DeterministicUpgradeRequiresPassword if key rotation requires the users password.
|
||||
*/
|
||||
public ListenableCompletableFuture<List<Transaction>> doMaintenance(@Nullable KeyParameter aesKey, boolean signAndSend)
|
||||
public ListenableCompletableFuture<List<Transaction>> doMaintenance(@Nullable AesKey aesKey, boolean signAndSend)
|
||||
throws DeterministicUpgradeRequiresPassword {
|
||||
return doMaintenance(KeyChainGroupStructure.BIP32, aesKey, signAndSend);
|
||||
}
|
||||
@ -5413,7 +5413,7 @@ public class Wallet extends BaseTaggableObject
|
||||
* @throws org.bitcoinj.wallet.DeterministicUpgradeRequiresPassword if key rotation requires the users password.
|
||||
*/
|
||||
public ListenableCompletableFuture<List<Transaction>> doMaintenance(KeyChainGroupStructure structure,
|
||||
@Nullable KeyParameter aesKey, boolean signAndSend) throws DeterministicUpgradeRequiresPassword {
|
||||
@Nullable AesKey aesKey, boolean signAndSend) throws DeterministicUpgradeRequiresPassword {
|
||||
List<Transaction> txns;
|
||||
lock.lock();
|
||||
keyChainGroupLock.lock();
|
||||
@ -5448,7 +5448,7 @@ public class Wallet extends BaseTaggableObject
|
||||
|
||||
// Checks to see if any coins are controlled by rotating keys and if so, spends them.
|
||||
@GuardedBy("keyChainGroupLock")
|
||||
private List<Transaction> maybeRotateKeys(KeyChainGroupStructure structure, @Nullable KeyParameter aesKey,
|
||||
private List<Transaction> maybeRotateKeys(KeyChainGroupStructure structure, @Nullable AesKey aesKey,
|
||||
boolean sign) throws DeterministicUpgradeRequiresPassword {
|
||||
checkState(lock.isHeldByCurrentThread());
|
||||
checkState(keyChainGroupLock.isHeldByCurrentThread());
|
||||
@ -5525,7 +5525,7 @@ public class Wallet extends BaseTaggableObject
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Transaction rekeyOneBatch(Instant time, @Nullable KeyParameter aesKey, List<Transaction> others, boolean sign) {
|
||||
private Transaction rekeyOneBatch(Instant time, @Nullable AesKey aesKey, List<Transaction> others, boolean sign) {
|
||||
lock.lock();
|
||||
try {
|
||||
// Build the transaction using some custom logic for our special needs. Last parameter to
|
||||
|
@ -22,7 +22,6 @@ import org.bitcoinj.base.Sha256Hash;
|
||||
import static org.bitcoinj.base.BitcoinNetwork.MAINNET;
|
||||
import static org.bitcoinj.base.BitcoinNetwork.TESTNET;
|
||||
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.bitcoinj.base.utils.ByteUtils;
|
||||
@ -172,7 +171,7 @@ public class ChildKeyDerivationTest {
|
||||
// Check that encrypting a parent key in the hierarchy and then deriving from it yields a DeterministicKey
|
||||
// with no private key component, and that the private key bytes are derived on demand.
|
||||
KeyCrypter scrypter = new KeyCrypterScrypt(SCRYPT_ITERATIONS);
|
||||
KeyParameter aesKey = scrypter.deriveKey("we never went to the moon");
|
||||
AesKey aesKey = scrypter.deriveKey("we never went to the moon");
|
||||
|
||||
DeterministicKey key1 = HDKeyDerivation.createMasterPrivateKey("it was all a hoax".getBytes());
|
||||
DeterministicKey encryptedKey1 = key1.encrypt(scrypter, aesKey, null);
|
||||
|
@ -30,7 +30,6 @@ import org.bitcoinj.core.Transaction;
|
||||
import org.bitcoinj.crypto.ECKey.ECDSASignature;
|
||||
import org.bitcoinj.crypto.internal.CryptoUtils;
|
||||
import org.bitcoinj.base.internal.FutureUtils;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
@ -48,7 +47,6 @@ import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import org.bitcoinj.base.utils.ByteUtils;
|
||||
import static org.bitcoinj.base.utils.ByteUtils.reverseBytes;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@ -415,7 +413,7 @@ public class ECKeyTest {
|
||||
@Test
|
||||
public void keyRecoveryWithEncryptedKey() {
|
||||
ECKey unencryptedKey = new ECKey();
|
||||
KeyParameter aesKey = keyCrypter.deriveKey(PASSWORD1);
|
||||
AesKey aesKey = keyCrypter.deriveKey(PASSWORD1);
|
||||
ECKey encryptedKey = unencryptedKey.encrypt(keyCrypter, aesKey);
|
||||
|
||||
String message = "Goodbye Jupiter!";
|
||||
|
@ -19,7 +19,6 @@ package org.bitcoinj.crypto;
|
||||
|
||||
import org.bitcoinj.base.utils.ByteUtils;
|
||||
import org.bitcoinj.crypto.HDKeyDerivation.PublicDeriveMode;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.math.BigInteger;
|
||||
@ -36,7 +35,7 @@ import static org.junit.Assert.fail;
|
||||
*/
|
||||
public class HDKeyDerivationTest {
|
||||
private static final KeyCrypterScrypt KEY_CRYPTER = new KeyCrypterScrypt(2);
|
||||
private static final KeyParameter AES_KEY = KEY_CRYPTER.deriveKey("password");
|
||||
private static final AesKey AES_KEY = KEY_CRYPTER.deriveKey("password");
|
||||
private static final ChildNumber CHILD_NUMBER = ChildNumber.ONE;
|
||||
private static final String EXPECTED_CHILD_CHAIN_CODE = "c4341fe988a2ae6240788c6b21df268b9286769915bed23c7649f263b3643ee8";
|
||||
private static final String EXPECTED_CHILD_PRIVATE_KEY = "48516d403070bc93f5e4d78c984cf2d71fc9799293b4eeb3de4f88e3892f523d";
|
||||
|
@ -22,6 +22,7 @@ import org.bitcoinj.base.Network;
|
||||
import org.bitcoinj.base.ScriptType;
|
||||
import org.bitcoinj.base.Address;
|
||||
import org.bitcoinj.base.internal.TimeUtils;
|
||||
import org.bitcoinj.crypto.AesKey;
|
||||
import org.bitcoinj.core.BloomFilter;
|
||||
import org.bitcoinj.crypto.ECKey;
|
||||
import org.bitcoinj.base.LegacyAddress;
|
||||
@ -34,7 +35,6 @@ import org.bitcoinj.crypto.HDPath;
|
||||
import org.bitcoinj.utils.BriefLogFormatter;
|
||||
import org.bitcoinj.utils.Threading;
|
||||
import org.bitcoinj.wallet.listeners.AbstractKeyChainEventListener;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
@ -356,7 +356,7 @@ public class DeterministicKeyChainTest {
|
||||
assertFalse(key1.isEncrypted());
|
||||
assertTrue(encKey1.isEncrypted());
|
||||
assertEquals(encKey1.getPubKeyPoint(), key1.getPubKeyPoint());
|
||||
final KeyParameter aesKey = checkNotNull(encChain.getKeyCrypter()).deriveKey("open secret");
|
||||
final AesKey aesKey = checkNotNull(encChain.getKeyCrypter()).deriveKey("open secret");
|
||||
encKey1.sign(Sha256Hash.ZERO_HASH, aesKey);
|
||||
encKey2.sign(Sha256Hash.ZERO_HASH, aesKey);
|
||||
assertTrue(encChain.checkAESKey(aesKey));
|
||||
|
@ -19,6 +19,7 @@ package org.bitcoinj.wallet;
|
||||
|
||||
import org.bitcoinj.base.Address;
|
||||
import org.bitcoinj.base.internal.TimeUtils;
|
||||
import org.bitcoinj.crypto.AesKey;
|
||||
import org.bitcoinj.core.BloomFilter;
|
||||
import org.bitcoinj.crypto.ECKey;
|
||||
import org.bitcoinj.core.NetworkParameters;
|
||||
@ -33,7 +34,6 @@ import org.bitcoinj.utils.BriefLogFormatter;
|
||||
import org.bitcoinj.utils.Threading;
|
||||
import org.bitcoinj.wallet.KeyChain.KeyPurpose;
|
||||
import org.bitcoinj.wallet.listeners.KeyChainEventListener;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
@ -60,7 +60,7 @@ public class KeyChainGroupTest {
|
||||
private static final String XPUB = "xpub68KFnj3bqUx1s7mHejLDBPywCAKdJEu1b49uniEEn2WSbHmZ7xbLqFTjJbtx1LUcAt1DwhoqWHmo2s5WMJp6wi38CiF2hYD49qVViKVvAoi";
|
||||
private static final byte[] ENTROPY = Sha256Hash.hash("don't use a string seed like this in real life".getBytes());
|
||||
private static final KeyCrypterScrypt KEY_CRYPTER = new KeyCrypterScrypt(2);
|
||||
private static final KeyParameter AES_KEY = KEY_CRYPTER.deriveKey("password");
|
||||
private static final AesKey AES_KEY = KEY_CRYPTER.deriveKey("password");
|
||||
private KeyChainGroup group;
|
||||
private DeterministicKey watchingAccountKey;
|
||||
|
||||
|
@ -21,6 +21,7 @@ import com.google.common.collect.Lists;
|
||||
import org.bitcoinj.base.BitcoinNetwork;
|
||||
import org.bitcoinj.base.ScriptType;
|
||||
import org.bitcoinj.base.internal.TimeUtils;
|
||||
import org.bitcoinj.crypto.AesKey;
|
||||
import org.bitcoinj.base.utils.ByteUtils;
|
||||
import org.bitcoinj.core.AbstractBlockChain;
|
||||
import org.bitcoinj.base.Address;
|
||||
@ -69,7 +70,6 @@ import org.bitcoinj.wallet.KeyChain.KeyPurpose;
|
||||
import org.bitcoinj.wallet.Protos.Wallet.EncryptionType;
|
||||
import org.bitcoinj.wallet.Wallet.BalanceType;
|
||||
import org.bitcoinj.wallet.WalletTransaction.Pool;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
import org.easymock.EasyMock;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@ -87,7 +87,6 @@ import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@ -106,7 +105,6 @@ import static org.bitcoinj.base.Coin.MILLICOIN;
|
||||
import static org.bitcoinj.base.Coin.SATOSHI;
|
||||
import static org.bitcoinj.base.Coin.ZERO;
|
||||
import static org.bitcoinj.base.Coin.valueOf;
|
||||
import org.bitcoinj.base.utils.ByteUtils;
|
||||
import static org.bitcoinj.testing.FakeTxBuilder.createFakeBlock;
|
||||
import static org.bitcoinj.testing.FakeTxBuilder.createFakeTx;
|
||||
import static org.bitcoinj.testing.FakeTxBuilder.createFakeTxWithoutChangeAddress;
|
||||
@ -389,8 +387,8 @@ public class WalletTest extends TestWithWallet {
|
||||
|
||||
if (encryptedWallet != null) {
|
||||
KeyCrypter keyCrypter = encryptedWallet.getKeyCrypter();
|
||||
KeyParameter aesKey = keyCrypter.deriveKey(PASSWORD1);
|
||||
KeyParameter wrongAesKey = keyCrypter.deriveKey(WRONG_PASSWORD);
|
||||
AesKey aesKey = keyCrypter.deriveKey(PASSWORD1);
|
||||
AesKey wrongAesKey = keyCrypter.deriveKey(WRONG_PASSWORD);
|
||||
|
||||
// Try to create a send with a fee but no password (this should fail).
|
||||
try {
|
||||
@ -504,7 +502,7 @@ public class WalletTest extends TestWithWallet {
|
||||
assertEquals(1, txns.size());
|
||||
}
|
||||
|
||||
private Wallet spendUnconfirmedChange(Wallet wallet, Transaction t2, KeyParameter aesKey) throws Exception {
|
||||
private Wallet spendUnconfirmedChange(Wallet wallet, Transaction t2, AesKey aesKey) throws Exception {
|
||||
if (wallet.getTransactionSigners().size() == 1) // don't bother reconfiguring the p2sh wallet
|
||||
wallet = roundTrip(wallet);
|
||||
Coin v3 = valueOf(0, 50);
|
||||
@ -1924,7 +1922,7 @@ public class WalletTest extends TestWithWallet {
|
||||
Wallet encryptedWallet = Wallet.createDeterministic(TESTNET, ScriptType.P2PKH);
|
||||
encryptedWallet.encrypt(PASSWORD1);
|
||||
KeyCrypter keyCrypter = encryptedWallet.getKeyCrypter();
|
||||
KeyParameter aesKey = keyCrypter.deriveKey(PASSWORD1);
|
||||
AesKey aesKey = keyCrypter.deriveKey(PASSWORD1);
|
||||
|
||||
assertEquals(EncryptionType.ENCRYPTED_SCRYPT_AES, encryptedWallet.getEncryptionType());
|
||||
assertTrue(encryptedWallet.checkPassword(PASSWORD1));
|
||||
@ -1965,7 +1963,7 @@ public class WalletTest extends TestWithWallet {
|
||||
Wallet encryptedWallet = Wallet.createDeterministic(TESTNET, ScriptType.P2PKH);
|
||||
encryptedWallet.encrypt(PASSWORD1);
|
||||
KeyCrypter keyCrypter = encryptedWallet.getKeyCrypter();
|
||||
KeyParameter wrongAesKey = keyCrypter.deriveKey(WRONG_PASSWORD);
|
||||
AesKey wrongAesKey = keyCrypter.deriveKey(WRONG_PASSWORD);
|
||||
|
||||
// Check the wallet is currently encrypted
|
||||
assertEquals("Wallet is not an encrypted wallet", EncryptionType.ENCRYPTED_SCRYPT_AES, encryptedWallet.getEncryptionType());
|
||||
@ -1996,10 +1994,10 @@ public class WalletTest extends TestWithWallet {
|
||||
encryptedWallet.encrypt(PASSWORD1);
|
||||
|
||||
KeyCrypter keyCrypter = encryptedWallet.getKeyCrypter();
|
||||
KeyParameter aesKey = keyCrypter.deriveKey(PASSWORD1);
|
||||
AesKey aesKey = keyCrypter.deriveKey(PASSWORD1);
|
||||
|
||||
CharSequence newPassword = "My name is Tom";
|
||||
KeyParameter newAesKey = keyCrypter.deriveKey(newPassword);
|
||||
AesKey newAesKey = keyCrypter.deriveKey(newPassword);
|
||||
|
||||
encryptedWallet.changeEncryptionKey(keyCrypter, aesKey, newAesKey);
|
||||
|
||||
@ -2012,7 +2010,7 @@ public class WalletTest extends TestWithWallet {
|
||||
Wallet encryptedWallet = Wallet.createDeterministic(TESTNET, ScriptType.P2PKH);
|
||||
encryptedWallet.encrypt(PASSWORD1);
|
||||
KeyCrypter keyCrypter = encryptedWallet.getKeyCrypter();
|
||||
KeyParameter aesKey = keyCrypter.deriveKey(PASSWORD1);
|
||||
AesKey aesKey = keyCrypter.deriveKey(PASSWORD1);
|
||||
|
||||
// Check the wallet is currently encrypted
|
||||
assertEquals("Wallet is not an encrypted wallet", EncryptionType.ENCRYPTED_SCRYPT_AES, encryptedWallet.getEncryptionType());
|
||||
@ -2071,7 +2069,7 @@ public class WalletTest extends TestWithWallet {
|
||||
Wallet encryptedWallet = Wallet.createDeterministic(TESTNET, ScriptType.P2PKH);
|
||||
encryptedWallet.encrypt(PASSWORD1);
|
||||
KeyCrypter keyCrypter = encryptedWallet.getKeyCrypter();
|
||||
KeyParameter aesKey = keyCrypter.deriveKey(PASSWORD1);
|
||||
AesKey aesKey = keyCrypter.deriveKey(PASSWORD1);
|
||||
|
||||
// Try added an ECKey that was encrypted with a differenct ScryptParameters (i.e. a non-homogenous key).
|
||||
// This is not allowed as the ScryptParameters is stored at the Wallet level.
|
||||
@ -3247,7 +3245,7 @@ public class WalletTest extends TestWithWallet {
|
||||
assertFalse(wallet.isDeterministicUpgradeRequired(ScriptType.P2PKH));
|
||||
assertTrue(wallet.isDeterministicUpgradeRequired(ScriptType.P2WPKH));
|
||||
|
||||
KeyParameter aesKey = new KeyCrypterScrypt(SCRYPT_ITERATIONS).deriveKey("abc");
|
||||
AesKey aesKey = new KeyCrypterScrypt(SCRYPT_ITERATIONS).deriveKey("abc");
|
||||
wallet.encrypt(new KeyCrypterScrypt(), aesKey);
|
||||
assertTrue(wallet.isEncrypted());
|
||||
assertEquals(ScriptType.P2PKH, wallet.currentReceiveAddress().getOutputScriptType());
|
||||
|
@ -16,13 +16,13 @@
|
||||
|
||||
package org.bitcoinj.walletfx.utils;
|
||||
|
||||
import org.bitcoinj.crypto.AesKey;
|
||||
import org.bitcoinj.crypto.KeyCrypterScrypt;
|
||||
import com.google.common.util.concurrent.Uninterruptibles;
|
||||
import javafx.beans.property.ReadOnlyDoubleProperty;
|
||||
import javafx.concurrent.Task;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
|
||||
import javax.annotation.*;
|
||||
import java.time.Duration;
|
||||
@ -36,7 +36,7 @@ import static org.bitcoinj.walletfx.utils.GuiUtils.checkGuiThread;
|
||||
public class KeyDerivationTasks {
|
||||
private static final Logger log = LoggerFactory.getLogger(KeyDerivationTasks.class);
|
||||
|
||||
public final Task<KeyParameter> keyDerivationTask;
|
||||
public final Task<AesKey> keyDerivationTask;
|
||||
public final ReadOnlyDoubleProperty progress;
|
||||
|
||||
private final Task<Void> progressTask;
|
||||
@ -46,11 +46,11 @@ public class KeyDerivationTasks {
|
||||
public KeyDerivationTasks(KeyCrypterScrypt scrypt, String password, @Nullable Duration targetTime) {
|
||||
keyDerivationTask = new Task<>() {
|
||||
@Override
|
||||
protected KeyParameter call() throws Exception {
|
||||
protected AesKey call() throws Exception {
|
||||
long start = System.currentTimeMillis();
|
||||
try {
|
||||
log.info("Started key derivation");
|
||||
KeyParameter result = scrypt.deriveKey(password);
|
||||
AesKey result = scrypt.deriveKey(password);
|
||||
timeTakenMsec = (int) (System.currentTimeMillis() - start);
|
||||
log.info("Key derivation done in {}ms", timeTakenMsec);
|
||||
return result;
|
||||
@ -64,7 +64,7 @@ public class KeyDerivationTasks {
|
||||
// And the fake progress meter ... if the vals were calculated correctly progress bar should reach 100%
|
||||
// a brief moment after the keys were derived successfully.
|
||||
progressTask = new Task<>() {
|
||||
private KeyParameter aesKey;
|
||||
private AesKey aesKey;
|
||||
|
||||
@Override
|
||||
protected Void call() throws Exception {
|
||||
@ -102,6 +102,6 @@ public class KeyDerivationTasks {
|
||||
new Thread(progressTask, "Progress ticker").start();
|
||||
}
|
||||
|
||||
protected void onFinish(KeyParameter aesKey, int timeTakenMsec) {
|
||||
protected void onFinish(AesKey aesKey, int timeTakenMsec) {
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ package wallettemplate;
|
||||
import javafx.scene.layout.HBox;
|
||||
import org.bitcoinj.base.Address;
|
||||
import org.bitcoinj.base.Coin;
|
||||
import org.bitcoinj.crypto.AesKey;
|
||||
import org.bitcoinj.core.*;
|
||||
import org.bitcoinj.crypto.ECKey;
|
||||
import org.bitcoinj.wallet.SendRequest;
|
||||
@ -35,7 +36,6 @@ import javafx.scene.control.TextField;
|
||||
import org.bitcoinj.walletfx.application.WalletApplication;
|
||||
import org.bitcoinj.walletfx.overlay.OverlayController;
|
||||
import org.bitcoinj.walletfx.overlay.OverlayableStackPaneController;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
import org.bitcoinj.walletfx.controls.BitcoinAddressValidator;
|
||||
import org.bitcoinj.walletfx.utils.TextFieldValidator;
|
||||
import org.bitcoinj.walletfx.utils.WTUtils;
|
||||
@ -58,7 +58,7 @@ public class SendMoneyController implements OverlayController<SendMoneyControlle
|
||||
private OverlayableStackPaneController.OverlayUI<? extends OverlayController<SendMoneyController>> overlayUI;
|
||||
|
||||
private Wallet.SendResult sendResult;
|
||||
private KeyParameter aesKey;
|
||||
private AesKey aesKey;
|
||||
|
||||
@Override
|
||||
public void initOverlay(OverlayableStackPaneController overlayableStackPaneController, OverlayableStackPaneController.OverlayUI<? extends OverlayController<SendMoneyController>> ui) {
|
||||
|
@ -17,6 +17,7 @@
|
||||
package wallettemplate;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import org.bitcoinj.crypto.AesKey;
|
||||
import org.bitcoinj.crypto.KeyCrypterScrypt;
|
||||
import com.google.common.primitives.Longs;
|
||||
import com.google.protobuf.ByteString;
|
||||
@ -35,7 +36,6 @@ import org.bitcoinj.walletfx.overlay.OverlayController;
|
||||
import org.bitcoinj.walletfx.overlay.OverlayableStackPaneController;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
import org.bitcoinj.walletfx.utils.KeyDerivationTasks;
|
||||
|
||||
import java.time.Duration;
|
||||
@ -61,7 +61,7 @@ public class WalletPasswordController implements OverlayController<WalletPasswor
|
||||
private OverlayableStackPaneController rootController;
|
||||
private OverlayableStackPaneController.OverlayUI<? extends OverlayController<WalletPasswordController>> overlayUI;
|
||||
|
||||
private SimpleObjectProperty<KeyParameter> aesKey = new SimpleObjectProperty<>();
|
||||
private SimpleObjectProperty<AesKey> aesKey = new SimpleObjectProperty<>();
|
||||
|
||||
@Override
|
||||
public void initOverlay(OverlayableStackPaneController overlayableStackPaneController, OverlayableStackPaneController.OverlayUI<? extends OverlayController<WalletPasswordController>> ui) {
|
||||
@ -86,7 +86,7 @@ public class WalletPasswordController implements OverlayController<WalletPasswor
|
||||
checkNotNull(keyCrypter); // We should never arrive at this GUI if the wallet isn't actually encrypted.
|
||||
KeyDerivationTasks tasks = new KeyDerivationTasks(keyCrypter, password, getTargetTime()) {
|
||||
@Override
|
||||
protected final void onFinish(KeyParameter aesKey, int timeTakenMsec) {
|
||||
protected final void onFinish(AesKey aesKey, int timeTakenMsec) {
|
||||
checkGuiThread();
|
||||
if (app.walletAppKit().wallet().checkAESKey(aesKey)) {
|
||||
WalletPasswordController.this.aesKey.set(aesKey);
|
||||
@ -114,7 +114,7 @@ public class WalletPasswordController implements OverlayController<WalletPasswor
|
||||
overlayUI.done();
|
||||
}
|
||||
|
||||
public ReadOnlyObjectProperty<KeyParameter> aesKeyProperty() {
|
||||
public ReadOnlyObjectProperty<AesKey> aesKeyProperty() {
|
||||
return aesKey;
|
||||
}
|
||||
|
||||
|
@ -16,18 +16,17 @@
|
||||
|
||||
package wallettemplate;
|
||||
|
||||
import javafx.application.*;
|
||||
import javafx.event.*;
|
||||
import javafx.fxml.*;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.layout.*;
|
||||
import org.bitcoinj.crypto.AesKey;
|
||||
import org.bitcoinj.crypto.*;
|
||||
import org.bitcoinj.wallet.*;
|
||||
import org.bitcoinj.walletfx.application.WalletApplication;
|
||||
import org.bitcoinj.walletfx.overlay.OverlayController;
|
||||
import org.bitcoinj.walletfx.overlay.OverlayableStackPaneController;
|
||||
import org.slf4j.*;
|
||||
import org.bouncycastle.crypto.params.*;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
|
||||
@ -124,7 +123,7 @@ public class WalletSetPasswordController implements OverlayController<WalletSetP
|
||||
// Deriving the actual key runs on a background thread. 500msec is empirical on my laptop (actual val is more like 333 but we give padding time).
|
||||
KeyDerivationTasks tasks = new KeyDerivationTasks(scrypt, password, estimatedKeyDerivationTime) {
|
||||
@Override
|
||||
protected final void onFinish(KeyParameter aesKey, int timeTakenMsec) {
|
||||
protected final void onFinish(AesKey aesKey, int timeTakenMsec) {
|
||||
// Write the target time to the wallet so we can make the progress bar work when entering the password.
|
||||
WalletPasswordController.setTargetTime(Duration.ofMillis(timeTakenMsec));
|
||||
// The actual encryption part doesn't take very long as most private keys are derived on demand.
|
||||
|
@ -17,6 +17,7 @@
|
||||
package wallettemplate;
|
||||
|
||||
import org.bitcoinj.base.internal.InternalUtils;
|
||||
import org.bitcoinj.crypto.AesKey;
|
||||
import org.bitcoinj.crypto.MnemonicCode;
|
||||
import org.bitcoinj.wallet.DeterministicSeed;
|
||||
import com.google.common.util.concurrent.Service;
|
||||
@ -32,7 +33,6 @@ import org.bitcoinj.walletfx.overlay.OverlayController;
|
||||
import org.bitcoinj.walletfx.overlay.OverlayableStackPaneController;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
import org.bitcoinj.walletfx.utils.TextFieldValidator;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
@ -61,7 +61,7 @@ public class WalletSettingsController implements OverlayController<WalletSetting
|
||||
private OverlayableStackPaneController rootController;
|
||||
private OverlayableStackPaneController.OverlayUI<? extends OverlayController<WalletSettingsController>> overlayUI;
|
||||
|
||||
private KeyParameter aesKey;
|
||||
private AesKey aesKey;
|
||||
|
||||
@Override
|
||||
public void initOverlay(OverlayableStackPaneController overlayableStackPaneController, OverlayableStackPaneController.OverlayUI<? extends OverlayController<WalletSettingsController>> ui) {
|
||||
@ -70,7 +70,7 @@ public class WalletSettingsController implements OverlayController<WalletSetting
|
||||
}
|
||||
|
||||
// Note: NOT called by FXMLLoader!
|
||||
public void initialize(@Nullable KeyParameter aesKey) {
|
||||
public void initialize(@Nullable AesKey aesKey) {
|
||||
app = WalletApplication.instance();
|
||||
DeterministicSeed seed = app.walletAppKit().wallet().getKeyChainSeed();
|
||||
if (aesKey == null) {
|
||||
|
@ -20,6 +20,7 @@ package org.bitcoinj.wallettool;
|
||||
import org.bitcoinj.base.BitcoinNetwork;
|
||||
import org.bitcoinj.base.Sha256Hash;
|
||||
import org.bitcoinj.base.internal.TimeUtils;
|
||||
import org.bitcoinj.crypto.AesKey;
|
||||
import org.bitcoinj.base.utils.ByteUtils;
|
||||
import org.bitcoinj.core.TransactionOutput;
|
||||
import org.bitcoinj.crypto.*;
|
||||
@ -38,7 +39,6 @@ import org.bitcoinj.wallet.CoinSelector;
|
||||
import org.bitcoinj.wallet.DeterministicKeyChain;
|
||||
import org.bitcoinj.wallet.DeterministicSeed;
|
||||
|
||||
import com.google.common.io.BaseEncoding;
|
||||
import com.google.common.io.Resources;
|
||||
import com.google.protobuf.ByteString;
|
||||
|
||||
@ -78,7 +78,6 @@ import org.bitcoinj.wallet.listeners.WalletCoinsSentEventListener;
|
||||
import org.bitcoinj.wallet.listeners.WalletReorganizeEventListener;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
import picocli.CommandLine;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
@ -574,7 +573,7 @@ public class WalletTool implements Callable<Integer> {
|
||||
+ " to " + outputScriptType);
|
||||
return;
|
||||
}
|
||||
KeyParameter aesKey = null;
|
||||
AesKey aesKey = null;
|
||||
if (wallet.isEncrypted()) {
|
||||
aesKey = passwordToKey(true);
|
||||
if (aesKey == null)
|
||||
@ -597,7 +596,7 @@ public class WalletTool implements Callable<Integer> {
|
||||
}
|
||||
log.info("Setting wallet key rotation time to {}", rotationTimeSecs);
|
||||
wallet.setKeyRotationTime(rotationTimeSecs);
|
||||
KeyParameter aesKey = null;
|
||||
AesKey aesKey = null;
|
||||
if (wallet.isEncrypted()) {
|
||||
aesKey = passwordToKey(true);
|
||||
if (aesKey == null)
|
||||
@ -1157,7 +1156,7 @@ public class WalletTool implements Callable<Integer> {
|
||||
}
|
||||
try {
|
||||
if (wallet.isEncrypted()) {
|
||||
KeyParameter aesKey = passwordToKey(true);
|
||||
AesKey aesKey = passwordToKey(true);
|
||||
if (aesKey == null)
|
||||
return; // Error message already printed.
|
||||
key = key.encrypt(checkNotNull(wallet.getKeyCrypter()), aesKey);
|
||||
@ -1177,7 +1176,7 @@ public class WalletTool implements Callable<Integer> {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private KeyParameter passwordToKey(boolean printError) {
|
||||
private AesKey passwordToKey(boolean printError) {
|
||||
if (password == null) {
|
||||
if (printError)
|
||||
System.err.println("You must provide a password.");
|
||||
@ -1258,7 +1257,7 @@ public class WalletTool implements Callable<Integer> {
|
||||
|
||||
if (dumpPrivKeys && wallet.isEncrypted()) {
|
||||
if (password != null) {
|
||||
final KeyParameter aesKey = passwordToKey(true);
|
||||
final AesKey aesKey = passwordToKey(true);
|
||||
if (aesKey == null)
|
||||
return; // Error message already printed.
|
||||
printWallet( aesKey);
|
||||
@ -1271,7 +1270,7 @@ public class WalletTool implements Callable<Integer> {
|
||||
}
|
||||
}
|
||||
|
||||
private void printWallet(@Nullable KeyParameter aesKey) {
|
||||
private void printWallet(@Nullable AesKey aesKey) {
|
||||
System.out.println(wallet.toString(dumpLookAhead, dumpPrivKeys, aesKey, true, true, chain));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user