71 lines
2.6 KiB
Java
71 lines
2.6 KiB
Java
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() < 26 || addr.length() > 35)
|
|
return false;
|
|
byte[] decoded = decodeBase58(addr, 25);
|
|
if (decoded == null)
|
|
return false;
|
|
|
|
byte[] hash1 = sha256(Arrays.copyOfRange(decoded, 0, 21));
|
|
byte[] hash2 = sha256(hash1);
|
|
|
|
return Arrays.equals(Arrays.copyOfRange(hash2, 0, 4), Arrays.copyOfRange(decoded, 21, 25));
|
|
}
|
|
|
|
private static byte[] decodeBase58(String input, int len) {
|
|
byte[] output = new byte[len];
|
|
for (char t : input.toCharArray()) {
|
|
int p = ALPHABET.indexOf(t);
|
|
if (p == -1)
|
|
return null;
|
|
for (int j = len - 1; j >= 0; j--) {
|
|
p += 58 * (output[j] & 0xFF);
|
|
output[j] = (byte) (p % 256);
|
|
p /= 256;
|
|
}
|
|
if (p != 0)
|
|
return null;
|
|
}
|
|
|
|
return output;
|
|
}
|
|
|
|
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("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", true);
|
|
assertBitcoin("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62j", false);
|
|
assertBitcoin("1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9", true);
|
|
assertBitcoin("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62X", false);
|
|
assertBitcoin("1ANNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", false);
|
|
assertBitcoin("1A Na15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", false);
|
|
assertBitcoin("BZbvjr", false);
|
|
assertBitcoin("i55j", false);
|
|
assertBitcoin("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62!", false);
|
|
assertBitcoin("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62iz", false);
|
|
assertBitcoin("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62izz", false);
|
|
assertBitcoin("1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nJ9", false);
|
|
assertBitcoin("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62I", 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));
|
|
}
|
|
}
|