|
|
Line 899: |
Line 899: |
|
|
|
|
|
=={{header|Java}}== |
|
=={{header|Java}}== |
|
|
<lang java>import java.security.MessageDigest; |
⚫ |
<lang java>private final static String ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; |
|
|
⚫ |
import java.security.NoSuchAlgorithmException ; |
|
|
import java.util.Arrays; |
|
|
|
|
|
public static void main(String[] args) { |
|
public class BitcoinAddressValidator { |
⚫ |
Assert("Test 01", ValidateBitcoinAddress("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i" ), true); |
|
⚫ |
Assert("Test 02", ValidateBitcoinAddress("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62j" ), false); |
|
⚫ |
Assert("Test 03", ValidateBitcoinAddress("1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9" ), true); |
|
⚫ |
Assert("Test 04", ValidateBitcoinAddress("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62X" ), false); |
|
⚫ |
Assert("Test 05", ValidateBitcoinAddress("1ANNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i" ), false); |
|
⚫ |
Assert("Test 06", ValidateBitcoinAddress("1A Na15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i" ), false); |
|
|
Assert("Test 07", ValidateBitcoinAddress("BZbvjr"), false); |
|
|
Assert("Test 08", ValidateBitcoinAddress("i55j"), false); |
|
⚫ |
Assert("Test 09", ValidateBitcoinAddress("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62!" ), false); |
|
⚫ |
Assert("Test 10", ValidateBitcoinAddress("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62iz" ), false); |
|
⚫ |
Assert("Test 11", ValidateBitcoinAddress("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62izz" ), false); |
|
⚫ |
Assert("Test 12", ValidateBitcoinAddress("1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nJ9" ), false); |
|
⚫ |
Assert("Test 13", ValidateBitcoinAddress("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62I" ), false); |
|
|
} |
|
|
|
|
|
|
⚫ |
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 , 58, 25); |
|
⚫ |
if (decoded == null) return false; |
|
|
|
|
|
|
⚫ |
public static boolean validateBitcoinAddress(String addr) { |
|
byte[] hash = Sha256(decoded, 0, 21, 2); |
|
|
⚫ |
if (addr.length() < 26 || addr.length() > 35) |
|
⚫ |
|
|
⚫ |
byte[] decoded = decodeBase58(addr, 25); |
|
⚫ |
|
|
⚫ |
|
|
|
|
|
|
return Arrays.equals(Arrays.copyOfRange(hash, 0, 4), Arrays.copyOfRange(decoded, 21, 25)); |
|
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 base, int len) { |
|
|
⚫ |
|
|
byte[] output = new byte[len]; |
|
⚫ |
for (int i = 0; i < input.length(); i++) { |
|
⚫ |
char t = input. charAt( i); |
|
|
|
|
|
|
⚫ |
private static byte[] decodeBase58(String input, int len) { |
|
int p = ALPHABET.indexOf(t); |
|
|
if (p == -1) return null; |
|
byte[] output = new byte[len]; |
|
for (int j = len - 1; j >= 0; j--, p /= 256) { |
|
for (char t : input.toCharArray()) { |
|
p += base * (output[j] & 0xFF); |
|
int p = ALPHABET.indexOf(t); |
|
output[j] = (byte) (p % 256); |
|
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; |
|
} |
|
} |
|
|
|
⚫ |
|
|
|
⚫ |
|
|
} |
|
} |
|
|
|
|
|
⚫ |
private static byte[] sha256(byte[] data) { |
⚫ |
|
|
|
⚫ |
|
|
} |
|
|
⚫ |
MessageDigest md = MessageDigest.getInstance("SHA-256"); |
|
⚫ |
|
|
⚫ |
|
|
|
} catch (NoSuchAlgorithmException e) { |
|
|
throw new IllegalStateException(e); |
|
|
} |
|
|
} |
|
|
|
|
|
|
public static void main(String[] args) { |
⚫ |
private static byte[] Sha256(byte[] data , int start, int len, int recursion) { |
|
|
⚫ |
assertBitcoin("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", true); |
⚫ |
if (recursion == 0) return data; |
|
|
⚫ |
assertBitcoin("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62j", false); |
|
|
|
|
⚫ |
assertBitcoin("1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9", true); |
⚫ |
|
|
|
⚫ |
assertBitcoin("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62X", false); |
⚫ |
MessageDigest md = MessageDigest.getInstance("SHA-256"); |
|
|
⚫ |
assertBitcoin("1ANNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", false); |
|
md.update(Arrays.copyOfRange(data, start, start + len)); |
|
|
⚫ |
assertBitcoin("1A Na15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", false); |
⚫ |
return Sha256(md.digest( ), 0, 32, recursion - 1); |
|
|
|
assertBitcoin("BZbvjr", false); |
⚫ |
} catch (NoSuchAlgorithmException e) { |
|
|
return null; |
|
assertBitcoin("i55j", false); |
|
⚫ |
assertBitcoin("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62!", false); |
|
⚫ |
assertBitcoin("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62iz", false); |
|
⚫ |
assertBitcoin("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62izz", false); |
|
⚫ |
assertBitcoin("1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nJ9", false); |
|
⚫ |
assertBitcoin("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62I", false); |
|
} |
|
} |
|
} |
|
|
|
|
|
|
public static void Assert(String name, boolean value, boolean expected) {
|
|
private static void assertBitcoin(String address, boolean expected) { |
|
|
boolean actual = validateBitcoinAddress(address); |
|
if (value ^ expected) |
|
|
throw new Error("Test " + name + " failed"); |
|
if (actual != expected) |
|
|
throw new AssertionError(String.format("Expected %s for %s, but got %s.", expected, address, actual)); |
⚫ |
|
|
|
|
} |
|
System.out.println(name + " passed"); |
|
|
}</lang> |
|
}</lang> |
|
|
|
|