From 0a3189c3b4c84188cdd75dd8c2762b46758b9ef7 Mon Sep 17 00:00:00 2001 From: Mike Hearn Date: Wed, 2 May 2012 17:56:05 +0200 Subject: [PATCH] WalletTool: fix --help and allow privkeys/pubkeys to be parsed as hex or base58. --- .../java/com/google/bitcoin/core/ECKey.java | 3 +++ .../java/com/google/bitcoin/core/Utils.java | 21 ++++++++++++++++++- .../com/google/bitcoin/tools/WalletTool.java | 16 +++++++++----- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/com/google/bitcoin/core/ECKey.java b/core/src/main/java/com/google/bitcoin/core/ECKey.java index 1fcbe612..9c64c505 100644 --- a/core/src/main/java/com/google/bitcoin/core/ECKey.java +++ b/core/src/main/java/com/google/bitcoin/core/ECKey.java @@ -49,6 +49,9 @@ public class ECKey implements Serializable { private static final SecureRandom secureRandom; private static final long serialVersionUID = -728224901792295832L; + /** How many bytes a Bitcoin public key is: 65, that is, two 32 byte co-ordinates plus a one byte header. */ + public static final int PUBLIC_KEY_LENGTH = 65; + static { // All clients must agree on the curve to use by agreement. Bitcoin uses secp256k1. X9ECParameters params = SECNamedCurves.getByName("secp256k1"); diff --git a/core/src/main/java/com/google/bitcoin/core/Utils.java b/core/src/main/java/com/google/bitcoin/core/Utils.java index 5f25196d..2955dd63 100644 --- a/core/src/main/java/com/google/bitcoin/core/Utils.java +++ b/core/src/main/java/com/google/bitcoin/core/Utils.java @@ -69,7 +69,7 @@ public class Utils { * * @param b the integer to format into a byte array * @param numBytes the desired size of the resulting byte array - * @return 32 byte long array. + * @return numBytes byte long array. */ public static byte[] bigIntegerToBytes(BigInteger b, int numBytes) { if (b == null) { @@ -352,4 +352,23 @@ public class Utils { System.arraycopy(in, 0, out, 0, Math.min(length, in.length)); return out; } + + /** + * Attempts to parse the given string as arbitrary-length hex or base58 and then return the results, or null if + * neither parse was successful. + */ + public static BigInteger parseAsHexOrBase58(String data) { + BigInteger decode; + try { + decode = new BigInteger(data, 16); + } catch (Exception e) { + // Didn't decode as hex, try base58. + try { + decode = new BigInteger(1, Base58.decodeChecked(data)); + } catch (AddressFormatException e1) { + return null; + } + } + return decode; + } } diff --git a/tools/src/main/java/com/google/bitcoin/tools/WalletTool.java b/tools/src/main/java/com/google/bitcoin/tools/WalletTool.java index ad255c09..bdd1ad23 100644 --- a/tools/src/main/java/com/google/bitcoin/tools/WalletTool.java +++ b/tools/src/main/java/com/google/bitcoin/tools/WalletTool.java @@ -71,9 +71,9 @@ public class WalletTool { " Will complain and require --force if the wallet already exists.\n" + " --action=ADD_KEY Adds a new key to the wallet, either specified or freshly generated.\n" + " If --date is specified, that's the creation date.\n" + - " If --privkey is specified, use as a hex encoded private key.\n" + + " If --privkey is specified, use as a hex/base58 encoded private key.\n" + " Don't specify --pubkey in that case, it will be derived automatically.\n" + - " If --pubkey is specified, use as a hex encoded non-compressed public key.\n" + + " If --pubkey is specified, use as a hex/base58 encoded non-compressed public key.\n" + " --action=DELETE_KEY Removes the key specified by --pubkey or --addr from the wallet.\n" + " --action=SYNC Sync the wallet with the latest block chain (download new transactions).\n" + " If the chain file does not exist this will RESET the wallet.\n" + @@ -223,7 +223,7 @@ public class WalletTool { conditionFlag = parser.accepts("condition").withRequiredArg(); options = parser.parse(args); - if (args.length == 0 || options.hasArgument("help") || options.nonOptionArguments().size() > 0) { + if (args.length == 0 || options.has("help") || options.nonOptionArguments().size() > 0) { System.out.println(HELP_TEXT); return; } @@ -549,14 +549,20 @@ public class WalletTool { } if (options.has("privkey")) { String data = (String) options.valueOf("privkey"); - key = new ECKey(new BigInteger(1, Hex.decode(data))); + BigInteger decode = Utils.parseAsHexOrBase58(data); + if (decode == null) { + System.err.println("Could not understand --privkey as either hex or base58: " + data); + return; + } + key = new ECKey(decode); if (options.has("pubkey")) { // Give the user a hint. System.out.println("You don't have to specify --pubkey when a private key is supplied."); } key.setCreationTimeSeconds(creationTimeSeconds); } else if (options.has("pubkey")) { - byte[] pubkey = Hex.decode((String)options.valueOf("pubkey")); + BigInteger decode = Utils.parseAsHexOrBase58((String) options.valueOf("pubkey")); + byte[] pubkey = Utils.bigIntegerToBytes(decode, ECKey.PUBLIC_KEY_LENGTH); key = new ECKey(null, pubkey); key.setCreationTimeSeconds(creationTimeSeconds); } else {