Skip to content

Instantly share code, notes, and snippets.

@TheTrunk
Created July 1, 2019 12:29
Show Gist options
  • Save TheTrunk/f22c558fdf4b8ab33916141100a3ed46 to your computer and use it in GitHub Desktop.
Save TheTrunk/f22c558fdf4b8ab33916141100a3ed46 to your computer and use it in GitHub Desktop.
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
public class BitcoinAddressValidator {
private static final String ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
public static boolean validateBitcoinAddress(String addr) {
if (addr.length() < 27 || addr.length() > 36)
return false;
byte[] decoded = decodeBase58To25Bytes(addr);
if (decoded == null)
return false;
byte[] hash1 = sha256(Arrays.copyOfRange(decoded, 0, 22));
byte[] hash2 = sha256(hash1);
return Arrays.equals(Arrays.copyOfRange(hash2, 0, 4), Arrays.copyOfRange(decoded, 22, 26));
}
private static byte[] decodeBase58To25Bytes(String input) {
BigInteger num = BigInteger.ZERO;
if (input.charAt(0) != 't')
return null;
if (input.charAt(1) != '1' && input.charAt(1) != '3')
return null;
for (char t : input.toCharArray()) {
int p = ALPHABET.indexOf(t);
if (p == -1)
return null;
num = num.multiply(BigInteger.valueOf(58)).add(BigInteger.valueOf(p));
}
byte[] result = new byte[26];
byte[] numBytes = num.toByteArray();
System.arraycopy(numBytes, 0, result, result.length - numBytes.length, numBytes.length);
return result;
}
private static byte[] sha256(byte[] data) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(data);
return md.digest();
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException(e);
}
}
public static void main(String[] args) {
assertBitcoin("t1dmNSMGoUXHaoKd48A8qudXhQPK5ughDv5", true);
assertBitcoin("t1Zb6bbGLqrGWr9tVZ22k8SnxKC7TEXWWrW", true);
assertBitcoin("t1Zb6bbGLqrGWr9tVZ22k8SnxKC7TEaWWrW", false);
assertBitcoin("t3LQtHUDoe7ZhhvddRv4vnaoNAhCr2f4oFN", true);
assertBitcoin("t2LQtHUDoe7ZhhvddRv4vnaoNAhCr2f4oFN", false);
assertBitcoin("1M1Xw2rczxkF3p3wiNHaTmxvbpZZ7M6vaa", false);
assertBitcoin("t3LQtHUDoe7ZhhvddRv4vnaoNAhCraf4oFN", false);
assertBitcoin("asdad", false);
}
private static void assertBitcoin(String address, boolean expected) {
boolean actual = validateBitcoinAddress(address);
if (actual != expected)
throw new AssertionError(String.format("Expected %s for %s, but got %s.", expected, address, actual));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment