summaryrefslogtreecommitdiff
path: root/016/ch2.pl
diff options
context:
space:
mode:
Diffstat (limited to '016/ch2.pl')
-rwxr-xr-x016/ch2.pl46
1 files changed, 46 insertions, 0 deletions
diff --git a/016/ch2.pl b/016/ch2.pl
new file mode 100755
index 0000000..c8e2733
--- /dev/null
+++ b/016/ch2.pl
@@ -0,0 +1,46 @@
+#!/usr/bin/env perl
+#
+# Write a script to validate a given bitcoin address. Most Bitcoin addresses are
+# 34 characters. They consist of random digits and uppercase and lowercase
+# letters, with the exception that the uppercase letter “O”, uppercase letter
+# “I”, lowercase letter “l”, and the number “0” are never used to prevent visual
+# ambiguity. A bitcoin address encodes 25 bytes. The last four bytes are a
+# checksum check. They are the first four bytes of a double SHA-256 digest of
+# the previous 21 bytes. For more information, please refer wiki page. Here are
+# some valid bitcoin addresses:
+# 1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2
+# 3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy
+################################################################################
+
+use strict;
+use warnings;
+
+use bigint;
+use Digest::SHA qw<sha256 sha256_hex>;
+
+my $addr = shift or die "Usage: $0 <btc_address>\n";
+my $len = length $addr;
+
+my $B58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
+
+# Basic checks
+# die "Invalid length (must be 26-35)\n" unless $len >= 26 && $len <= 34;
+die "Invalid characters\n" unless $addr =~ /^[$B58]+$/;
+
+# Fill with zeroes if address is shorter than 34 characters
+# $addr = '0' x (34 - $len) . $addr;
+
+my $dec_addr;
+my $base = 1;
+for (my $i = length($addr)-1; $i >= 0; $i--) {
+ $dec_addr += $base * index $B58, substr($addr, $i, 1);
+ $base *= 58;
+}
+
+my $checksum = $dec_addr & (2**32 - 1); # Get last 4 bytes
+my $payload = pack("H*", ($dec_addr >> 32)->as_hex);
+my $digest = sha256_hex(pack("a*", sha256_hex($payload))); # Get version+payload
+
+print $dec_addr->as_hex, "\n";
+print $payload, " - ", $checksum->as_hex, "\n";
+print $digest, "\n";