Make Base58 throw on decode if the input is not valid base58, add test.

Add a decodeChecked method that uses the last 4 bytes as a checksum, for IRC support.
This commit is contained in:
Mike Hearn 2011-05-02 11:44:14 +00:00
parent 3e267f1327
commit 37cb9cb6e5
2 changed files with 38 additions and 5 deletions

View File

@ -17,6 +17,7 @@
package com.google.bitcoin.core;
import java.math.BigInteger;
import java.util.Arrays;
/**
* A custom form of base58 is used to encode BitCoin addresses. Note that this is not the same base58 as used by
@ -33,7 +34,6 @@ import java.math.BigInteger;
* </ul>
*/
public class Base58 {
private static final String ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
private static final BigInteger BASE = BigInteger.valueOf(58);
@ -57,17 +57,42 @@ public class Base58 {
return s.toString();
}
public static byte[] decode(String input) {
public static byte[] decode(String input) throws AddressFormatException {
return decodeToBigInteger(input).toByteArray();
}
public static BigInteger decodeToBigInteger(String input) {
public static BigInteger decodeToBigInteger(String input) throws AddressFormatException {
BigInteger bi = BigInteger.valueOf(0);
// Work backwards through the string.
for (int i = input.length() - 1; i >= 0; i--) {
int alphaIndex = ALPHABET.indexOf(input.charAt(i));
if (alphaIndex == -1) {
throw new AddressFormatException("Illegal character " + input.charAt(i) + " at " + i);
}
bi = bi.add(BigInteger.valueOf(alphaIndex).multiply(BASE.pow(input.length() - 1 - i)));
}
return bi;
}
/**
* Uses the checksum in the last 4 bytes of the decoded data to verify the rest are correct. The checksum is
* removed from the returned data.
*
* @throws AddressFormatException if the input is not base 58 or the checksum does not validate.
*/
public static byte[] decodeChecked(String input) throws AddressFormatException {
byte[] tmp = decode(input);
if (tmp.length < 4)
throw new AddressFormatException("Input too short");
byte[] checksum = new byte[4];
System.arraycopy(tmp, tmp.length - 4, checksum, 0, 4);
byte[] bytes = new byte[tmp.length - 4];
System.arraycopy(tmp, 0, bytes, 0, tmp.length - 4);
tmp = Utils.doubleDigest(bytes);
byte[] hash = new byte[4];
System.arraycopy(tmp, 0, hash, 0, 4);
if (!Arrays.equals(hash, checksum))
throw new AddressFormatException("Checksum does not validate");
return bytes;
}
}

View File

@ -22,7 +22,7 @@ import java.math.BigInteger;
import java.util.Arrays;
public class Base58Test extends TestCase {
public void testEncode() {
public void testEncode() throws Exception {
byte[] testbytes = "Hello World".getBytes();
assertEquals("JxF12TrwUP45BMd", Base58.encode(testbytes));
@ -30,9 +30,17 @@ public class Base58Test extends TestCase {
assertEquals("16Ho7Hs", Base58.encode(bi.toByteArray()));
}
public void testDecode() {
public void testDecode() throws Exception {
byte[] testbytes = "Hello World".getBytes();
byte[] actualbytes = Base58.decode("JxF12TrwUP45BMd");
assertTrue(new String(actualbytes), Arrays.equals(testbytes, actualbytes));
try {
Base58.decode("This isn't valid base58");
fail();
} catch (AddressFormatException e) {
}
Base58.decodeChecked("4stwEBjT6FYyVV");
}
}