Bitcoin/address validation: Difference between revisions

Content deleted Content added
→‎{{header|Kotlin}}: Updated example see https://github.com/dkandalov/rosettacode-kotlin for details
→‎{{header|Java}}: code cleanup
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)
return false;
byte[] decoded = decodeBase58(addr, 25);
if (decoded == null)
return false;


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;
}
}

if (p != 0) return null;
return output;
}
}


private static byte[] sha256(byte[] data) {
return output;
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) {
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);
try {
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));
else
}
System.out.println(name + " passed");
}</lang>
}</lang>