115 lines
No EOL
4.5 KiB
Java
115 lines
No EOL
4.5 KiB
Java
package com.tangem.wallet;
|
|
|
|
import java.math.BigInteger;
|
|
|
|
/**
|
|
* Created by Ilia on 15.02.2018.
|
|
*/
|
|
|
|
public class Base58 {
|
|
private static final char[] BASE58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".toCharArray();
|
|
|
|
private static final int BASE58_CHUNK_DIGITS = 10;//how many base 58 digits fits in long
|
|
private static final BigInteger BASE58_CHUNK_MOD = BigInteger.valueOf(0x5fa8624c7fba400L); //58^BASE58_CHUNK_DIGITS
|
|
private static final byte[] BASE58_VALUES = new byte[]{-1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1,
|
|
-1, 9, 10, 11, 12, 13, 14, 15, 16, -1, 17, 18, 19, 20, 21, -1,
|
|
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, -1,
|
|
-1, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, -1, 44, 45, 46,
|
|
47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
|
|
|
|
public static byte[] decodeBase58(String input) {
|
|
if (input == null) {
|
|
return null;
|
|
}
|
|
input = input.trim();
|
|
if (input.length() == 0) {
|
|
return new byte[0];
|
|
}
|
|
BigInteger resultNum = BigInteger.ZERO;
|
|
int nLeadingZeros = 0;
|
|
while (nLeadingZeros < input.length() && input.charAt(nLeadingZeros) == BASE58[0]) {
|
|
nLeadingZeros++;
|
|
}
|
|
long acc = 0;
|
|
int nDigits = 0;
|
|
int p = nLeadingZeros;
|
|
while (p < input.length()) {
|
|
int v = BASE58_VALUES[input.charAt(p) & 0xff];
|
|
if (v >= 0) {
|
|
acc *= 58;
|
|
acc += v;
|
|
nDigits++;
|
|
if (nDigits == BASE58_CHUNK_DIGITS) {
|
|
resultNum = resultNum.multiply(BASE58_CHUNK_MOD).add(BigInteger.valueOf(acc));
|
|
acc = 0;
|
|
nDigits = 0;
|
|
}
|
|
p++;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
if (nDigits > 0) {
|
|
long mul = 58;
|
|
while (--nDigits > 0) {
|
|
mul *= 58;
|
|
}
|
|
resultNum = resultNum.multiply(BigInteger.valueOf(mul)).add(BigInteger.valueOf(acc));
|
|
}
|
|
final int BASE58_SPACE = -2;
|
|
while (p < input.length() && BASE58_VALUES[input.charAt(p) & 0xff] == BASE58_SPACE) {
|
|
p++;
|
|
}
|
|
if (p < input.length()) {
|
|
return null;
|
|
}
|
|
byte[] plainNumber = resultNum.toByteArray();
|
|
int plainNumbersOffs = plainNumber[0] == 0 ? 1 : 0;
|
|
byte[] result = new byte[nLeadingZeros + plainNumber.length - plainNumbersOffs];
|
|
System.arraycopy(plainNumber, plainNumbersOffs, result, nLeadingZeros, plainNumber.length - plainNumbersOffs);
|
|
return result;
|
|
}
|
|
|
|
public static String encodeBase58(byte[] input) {
|
|
if (input == null) {
|
|
return null;
|
|
}
|
|
StringBuilder str = new StringBuilder((input.length * 350) / 256 + 1);
|
|
BigInteger bn = new BigInteger(1, input);
|
|
long rem;
|
|
while (true) {
|
|
BigInteger[] divideAndRemainder = bn.divideAndRemainder(BASE58_CHUNK_MOD);
|
|
bn = divideAndRemainder[0];
|
|
rem = divideAndRemainder[1].longValue();
|
|
if (bn.compareTo(BigInteger.ZERO) == 0) {
|
|
break;
|
|
}
|
|
for (int i = 0; i < BASE58_CHUNK_DIGITS; i++) {
|
|
str.append(BASE58[(int) (rem % 58)]);
|
|
rem /= 58;
|
|
}
|
|
}
|
|
while (rem != 0) {
|
|
str.append(BASE58[(int) (rem % 58)]);
|
|
rem /= 58;
|
|
}
|
|
str.reverse();
|
|
int nLeadingZeros = 0;
|
|
while (nLeadingZeros < input.length && input[nLeadingZeros] == 0) {
|
|
str.insert(0, BASE58[0]);
|
|
nLeadingZeros++;
|
|
}
|
|
return str.toString();
|
|
}
|
|
} |