/**
* Copyright 2011 Google Inc.
*
* 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 com.google.bitcoin.core;
import java.math.BigInteger;
/**
* A custom form of base58 is used to encode BitCoin addresses. Note that this is not the same base58 as used by
* Flickr, which you may see reference to around the internet.<p>
*
* Satoshi says: why base-58 instead of standard base-64 encoding?<p>
*
* <ul>
* <li>Don't want 0OIl characters that look the same in some fonts and
* could be used to create visually identical looking account numbers.</li>
* <li>A string with non-alphanumeric characters is not as easily accepted as an account number.</li>
* <li>E-mail usually won't line-break if there's no punctuation to break at.</li>
* <li>Doubleclicking selects the whole number as one word if it's all alphanumeric.</li>
* </ul>
*/
public class Base58 {
private static final String ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
private static final BigInteger BASE = BigInteger.valueOf(58);
public static String encode(byte[] input) {
// TODO: This could be a lot more efficient.
BigInteger bi = new BigInteger(1, input);
StringBuffer s = new StringBuffer();
while (bi.compareTo(BASE) >= 0) {
BigInteger mod = bi.mod(BASE);
s.insert(0, ALPHABET.charAt(mod.intValue()));
bi = bi.subtract(mod).divide(BASE);
}
s.insert(0, ALPHABET.charAt(bi.intValue()));
// Convert leading zeros too.
for (byte anInput : input) {
if (anInput == 0)
s.insert(0, ALPHABET.charAt(0));
else
break;
}
return s.toString();
}
public static byte[] decode(String input) {
return decodeToBigInteger(input).toByteArray();
}
public static BigInteger decodeToBigInteger(String input) {
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));
bi = bi.add(BigInteger.valueOf(alphaIndex).multiply(BASE.pow(input.length() - 1 - i)));
}
return bi;
}
}