Skip to content

Instantly share code, notes, and snippets.

@emmahsax
Last active August 10, 2023 18:49
Show Gist options
  • Save emmahsax/e9d8ff571a8ed57a31c07f6cfa82a4f9 to your computer and use it in GitHub Desktop.
Save emmahsax/e9d8ff571a8ed57a31c07f6cfa82a4f9 to your computer and use it in GitHub Desktop.
A helpful file that shows how to generate TOTP rotating codes using Ruby

Generating TOTP tokens from a seeds file on your machine in Ruby

This file assumes you have a file (~/.totp.yml) on your machine where you store the SERVICEs, and their secret keys:

aws: rAndOmCharaCTeRsHerE
google: rAndOmCharaCTeRsHerE

Then, you can call like this:

ruby totp.rb SERVICE

The repsonse should look like this:

$ ruby totp.rb aws

This code automatically regenerates every 30 seconds

6 seconds remaining

283646

Code copied to clipboard
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'rotp'
require 'yaml'
SERVICE = ARGV[0]
DOT_FILE = '.totp.yml'
def services
return @services if @services
@services = YAML.load_file("#{Dir.home}/#{DOT_FILE}")
rescue StandardError
raise_error( \
"It looks like your #{DOT_FILE} file isn't set up yet." \
' Please complete this before proceeding.'
)
end
def pbcopy(input)
str = input.to_s
IO.popen('pbcopy', 'w') { |f| f << str }
str
end
def generate_time_remaining
seconds = Time.now.sec
seconds >= 30 ? 60 - seconds : 30 - seconds
end
def totp(totp_key)
@totp ||= ROTP::TOTP.new(totp_key)
end
def raise_error(message)
raise StandardError, message
end
def list_services
"Here's a list of available services:\n\n #{services.keys.join(', ')}"
end
begin
raise_error("Please provide a service. #{list_services}") unless SERVICE
if (totp_key = services[SERVICE])
puts "\nThis code automatically regenerates every 30 seconds"
puts "\n#{generate_time_remaining} seconds remaining"
puts "\n#{pbcopy(totp(totp_key).now)}"
puts "\nCode copied to clipboard\n\n"
else
raise_error( \
"Unable to find TOTP key for '#{SERVICE}' in your #{DOT_FILE} file." \
' Please ensure the key is available and formatted correctly.'
)
end
rescue StandardError => e
puts "\n#{e.message}\n\n"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment