#!/usr/bin/env ruby # totp - print a TOTP password for the Base32 secret passed on standard input require 'openssl' secret = gets.chomp decoded = secret.chars.each_slice(8).map { |s| c = s.inject(0) { |a,e| (a<<5) + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'.index(e) } 4.downto(0).map { |i| ((c>>i * 8) & 0xff).chr } }.join code = OpenSSL::HMAC.digest("SHA1", decoded, [Time.now.to_i / 30].pack('q>')) hash = code[code[-1].ord & 0x0F, 4] printf "%06d\n", (hash.unpack('L>').first & 0x7FFFFFFF) % 1000000