summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCalvin Morrison <calvin@fastmailteam.com>2018-10-16 09:55:28 -0400
committerCalvin Morrison <calvin@fastmailteam.com>2018-10-16 09:55:28 -0400
commit8e624684ab3c3db83febcb2d76be208a96f234da (patch)
tree65bb853cd07ef7d5decdc4ecd304234528c0297f
add working totp.pl
-rw-r--r--totp.pl75
1 files changed, 75 insertions, 0 deletions
diff --git a/totp.pl b/totp.pl
new file mode 100644
index 0000000..21a0c00
--- /dev/null
+++ b/totp.pl
@@ -0,0 +1,75 @@
+use MIME::Base32;
+use POSIX ;
+use Digest::SHA;
+use v5.14;
+
+# take a string, make it a hex and run HMAC on it
+sub hmac_sha1_hex_string {
+ my ($data, $key) = map pack('H*', $_), @_;
+ return Digest::SHA::hmac_sha1_hex($data, $key);
+}
+
+# everything is 2 here because we are looking at the byte level.. probably
+# should just convert this into a byte array but I'm a noob
+sub hotp_truncate {
+ my ($hex) = @_;
+ my $lastbyte= substr $hex, -2;
+ my $offset = (hex $lastbyte) & 0xf;
+ my $offset = $offset * 2;
+
+ my $truncate = (
+ (hex substr($hex, $offset , 2) & 0x7f) << 24 |
+ (hex substr($hex, $offset + 2, 2) & 0xff) << 16 |
+ (hex substr($hex, $offset + 4, 2) & 0xff) << 8 |
+ (hex substr($hex, $offset + 6, 2) & 0xff)
+ );
+
+ # 6 letter;
+ $truncate = substr($truncate, -6);
+
+ return $truncate;
+}
+
+# TOTP is HOTP(K,c) where counter c is time based and changed every 30 seconds (here)
+# HOTP
+sub totp {
+ my ($time, $secret) = @_;
+
+ # definition for otp(K,c) where c is the counter -> with totp, we use time / 30
+ $time = floor($time / 30);
+
+ # do the work
+ my $otp = hotp($time, $secret);
+
+ return $otp;
+}
+sub hotp {
+ my ($time, $secret) = @_;
+
+ my $secret_hex = unpack "H*", decode_base32($secret);
+ my $time_hex= sprintf("%016s", sprintf("%x", $time));
+
+
+ # SHA-1 Hex your secret
+ my $hash = hmac_sha1_hex_string($time_hex, $secret_hex);
+
+ my $otp = hotp_truncate($hash);
+
+ return $otp;
+
+}
+
+my $secret = "";
+if($#ARGV != 0) {
+ $secret = <STDIN>;
+ chomp $secret;
+} else {
+ $secret = $ARGV[0] ;
+}
+
+my $starttime = time;
+
+my $otp = totp($starttime, $secret);
+
+printf("%ds left: %06d, in your clipboard\n", 30 - $starttime % 30, $otp);
+system("echo $otp | xclip /dev/stdin");