From ab7351ff786a94808a283263f2ee9b363327e2e8 Mon Sep 17 00:00:00 2001 From: Mike Hearn Date: Tue, 24 May 2011 20:19:18 +0000 Subject: [PATCH] Fix bug in Base58.decode that caused failures when the MSB of the decoded byte array was 1. Thanks to BitterTea and sipa for help with debugging this. --- src/com/google/bitcoin/core/Base58.java | 15 +++++++++++++-- tests/com/google/bitcoin/core/Base58Test.java | 4 ++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/com/google/bitcoin/core/Base58.java b/src/com/google/bitcoin/core/Base58.java index ce9f62aa..aaed4bd4 100644 --- a/src/com/google/bitcoin/core/Base58.java +++ b/src/com/google/bitcoin/core/Base58.java @@ -56,9 +56,20 @@ public class Base58 { } return s.toString(); } - + public static byte[] decode(String input) throws AddressFormatException { - return decodeToBigInteger(input).toByteArray(); + byte[] bytes = decodeToBigInteger(input).toByteArray(); + // We may have got one more byte than we wanted, if the high bit of the next-to-last byte was not zero. This + // is because BigIntegers are represented with twos-compliment notation, thus if the high bit of the last + // byte happens to be 1 another 8 zero bits will be added to ensure the number parses as positive. Detect + // that case here and chop it off. + if ((bytes.length > 1) && (bytes[0] == 0) && (bytes[1] < 0)) { + // Java 6 has a convenience for this, but Android can't use it. + byte[] tmp = new byte[bytes.length - 1]; + System.arraycopy(bytes, 1, tmp, 0, bytes.length - 1); + bytes = tmp; + } + return bytes; } public static BigInteger decodeToBigInteger(String input) throws AddressFormatException { diff --git a/tests/com/google/bitcoin/core/Base58Test.java b/tests/com/google/bitcoin/core/Base58Test.java index ce592a39..18df1a07 100644 --- a/tests/com/google/bitcoin/core/Base58Test.java +++ b/tests/com/google/bitcoin/core/Base58Test.java @@ -42,5 +42,9 @@ public class Base58Test extends TestCase { } Base58.decodeChecked("4stwEBjT6FYyVV"); + + // Now check we can correctly decode the case where the high bit of the first byte is not zero, so BigInteger + // sign extends. Fix for a bug that stopped us parsing keys exported using sipas patch. + Base58.decodeChecked("93VYUMzRG9DdbRP72uQXjaWibbQwygnvaCu9DumcqDjGybD864T"); } }