Created
September 15, 2016 21:29
-
-
Save pablotron/89544a840211a8412ff7bfe0f22694aa to your computer and use it in GitHub Desktop.
ROTP and Google Authenticator Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# install dependency | |
pabs@meh:~/git/test/rotp> sudo gem install rotp | |
# generate new secret and QR code URL | |
pabs@meh:~/git/test/rotp> ruby ./rotp-example.rb new asdf@example.com | |
QR Code URL: https://chart.googleapis.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth%3A%2F%2Ftotp%2FAlonzo%27s%2520Totally%2520Secure%2520App%3Aasdf%40example.com%3Fsecret%3Dr7eslax2okb2dkr4%26issuer%3DAlonzo%2527s%2BTotally%2BSecure%2BApp | |
Secret: r7eslax2okb2dkr4 | |
Provisioning URL: otpauth://totp/Alonzo's%20Totally%20Secure%20App:asdf@example.com?secret=r7eslax2okb2dkr4&issuer=Alonzo%27s+Totally+Secure+App | |
# at this point i used the QR Code URL above to configure Google Authenticator on my phone | |
# if this was a real application, it would store the secret along with the email in a database here | |
# then the "510461" code below came from my phone | |
# test with correct code | |
pabs@meh:~/git/test/rotp> ruby ./rotp-example.rb test r7eslax2okb2dkr4 510461 | |
Result: success | |
# test with incorrect code | |
pabs@meh:~/git/test/rotp> ruby ./rotp-example.rb test r7eslax2okb2dkr4 123356 | |
Result: failure |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'rotp' | |
require 'erb' | |
# require 'optparse' | |
module ROTPExample | |
APP_NAME = "Alonzo's Totally Secure App" | |
TEMPLATES = { | |
qr: %{ | |
https://chart.googleapis.com/chart?chs=200x200&chld=M|0&cht=qr&chl=%s | |
}.strip, | |
new: %{ | |
QR Code URL: %s | |
Secret: %s | |
Provisioning URL: %s | |
}.strip, | |
usage: %{ | |
Usage: %s [ new EMAIL | test SECRET CODE ] | |
Examples: | |
# create new shared secret for hello@example.com | |
%s new hello@example.com | |
# test code | |
%s test | |
}.strip, | |
} | |
class QRCode | |
def initialize(data) | |
@data = data | |
end | |
def to_s | |
TEMPLATES[:qr] % [ERB::Util.url_encode(@data)] | |
end | |
end | |
class Generator | |
def initialize(secret, email, app_name = APP_NAME) | |
@secret, @email, @app_name = secret, email, app_name | |
# generate provisioning uri | |
@uri = ROTP::TOTP.new(@secret, issuer: @app_name).provisioning_uri(@email) | |
end | |
def to_s | |
TEMPLATES[:new] % [QRCode.new(@uri), @secret, @uri] | |
end | |
end | |
def self.print_usage(app) | |
$stderr.puts TEMPLATES[:usage] % ([app] * 3) | |
exit -1 | |
end | |
def self.run(app, args) | |
print_usage(app) unless args.length > 1 | |
case args.shift | |
when 'new' | |
# get email from args | |
email = args.shift | |
# generate shared secret | |
secret = ROTP::Base32.random_base32 | |
# generate and print result | |
puts Generator.new(secret, email) | |
when 'test' | |
print_usage unless args.length == 2 | |
secret, code = args | |
# verify code with 120 seconds of drift | |
ok = ROTP::TOTP.new(secret).verify_with_drift(code, 60, Time.now - 30) | |
# print result | |
puts 'Result: %s' % [ok ? 'success' : 'failure'] | |
else | |
print_usage(app) | |
end | |
end | |
end | |
# run app | |
ROTPExample.run($0, ARGV) if __FILE__ == $0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment