• Stars
    star
    1,525
  • Rank 29,574 (Top 0.6 %)
  • Language
    Ruby
  • License
    MIT License
  • Created about 13 years ago
  • Updated 8 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Ruby One Time Password library

Webauthn and the future of 2FA

Although this library will continue to be maintained, if you're implementing a 2FA solution today, you should take a look at Webauthn. It doesn't involve shared secrets and it's supported by most modern browsers and operating systems.

Ruby resources for Webauthn


The Ruby One Time Password Library

Build Status Gem Version Documentation License

A ruby library for generating and validating one time passwords (HOTP & TOTP) according to RFC 4226 and RFC 6238.

ROTP is compatible with Google Authenticator available for Android and iPhone and any other TOTP based implementations.

Many websites use this for multi-factor authentication, such as GMail, Facebook, Amazon EC2, WordPress, and Salesforce. You can find a more complete list here.

Dependencies

  • OpenSSL
  • Ruby 2.3 or higher

Breaking changes

Breaking changes in >= 6.0

  • Dropping support for Ruby <2.3

Breaking changes in >= 5.0

  • ROTP::Base32.random_base32 is now ROTP::Base32.random and the argument has changed from secret string length to byte length to allow for more precision. There is an alias to allow for random_base32 for the time being.
  • Cleaned up the Base32 implementation to match Google Authenticator's version.

Breaking changes in >= 4.0

  • Simplified API
    • verify now takes options for drift and after,padding is no longer an option
    • verify returns a timestamp if true, nil if false
  • Dropping support for Ruby < 2.0
  • Docs for 3.x can be found here

Installation

gem install rotp

Library Usage

Time based OTP's

totp = ROTP::TOTP.new("base32secret3232", issuer: "My Service")
totp.now # => "492039"

# OTP verified for current time - returns timestamp of the current interval
# period.
totp.verify("492039") # => 1474590700

sleep 30

# OTP fails to verify - returns nil
totp.verify("492039") # => nil

Counter based OTP's

hotp = ROTP::HOTP.new("base32secretkey3232")
hotp.at(0) # => "786922"
hotp.at(1) # => "595254"
hotp.at(1401) # => "259769"

# OTP verified with a counter
hotp.verify("259769", 1401) # => 1401
hotp.verify("259769", 1402) # => nil

Preventing reuse of Time based OTP's

By keeping track of the last time a user's OTP was verified, we can prevent token reuse during the interval window (default 30 seconds)

The following is an example of this in action:

user = User.find(someUserID)
totp = ROTP::TOTP.new(user.otp_secret)
totp.now # => "492039"

# Let's take a look at the last time the user authenticated with an OTP
user.last_otp_at # => 1432703530

# Verify the OTP
last_otp_at = totp.verify("492039", after: user.last_otp_at) #=> 1472145760
# ROTP returns the timestamp(int) of the current period

# Store this on the user's account
user.update(last_otp_at: last_otp_at)

# Someone attempts to reuse the OTP inside the 30s window
last_otp_at = totp.verify("492039", after: user.last_otp_at) #=> nil
# It fails to verify because we are still in the same 30s interval window

Verifying a Time based OTP with drift

Some users may enter a code just after it has expired. By adding 'drift' you can allow for a recently expired token to remain valid.

totp = ROTP::TOTP.new("base32secret3232")
now = Time.at(1474590600) #2016-09-23 00:30:00 UTC
totp.at(now) # => "250939"

# OTP verified for current time along with 15 seconds earlier
# ie. User enters a code just after it expired
totp.verify("250939", drift_behind: 15, at: now + 35) # => 1474590600
# User waits too long. Fails to validate previous OTP
totp.verify("250939", drift_behind: 15, at: now + 45) # => nil

Generating a Base32 Secret key

ROTP::Base32.random  # returns a 160 bit (32 character) base32 secret. Compatible with Google Authenticator

Note: The Base32 format conforms to RFC 4648 Base32

Generating QR Codes for provisioning mobile apps

Provisioning URI's generated by ROTP are compatible with most One Time Password applications, including Google Authenticator.

totp = ROTP::TOTP.new("base32secret3232", issuer: "My Service")
totp.provisioning_uri("[email protected]") # => 'otpauth://totp/My%20Service:alice%40google.com?secret=base32secret3232&issuer=My%20Service'

hotp = ROTP::HOTP.new("base32secret3232", issuer: "My Service")
hotp.provisioning_uri("[email protected]", 0) # => 'otpauth://hotp/My%20Service:alice%40google.com?secret=base32secret3232&issuer=My%20Service&counter=0'

This can then be rendered as a QR Code which the user can scan using their mobile phone and the appropriate application.

Working example

Scan the following barcode with your phone, using Google Authenticator

QR Code for OTP

Now run the following and compare the output

require 'rubygems'
require 'rotp'
totp = ROTP::TOTP.new("JBSWY3DPEHPK3PXP")
p "Current OTP: #{totp.now}"

Testing

bundle install
bundle exec rspec

Testing with Docker

In order to make it easier to test against different ruby version, ROTP comes with a set of Dockerfiles for each version that we test against in Travis

docker build -f Dockerfile-2.6 -t rotp_2.6 .
docker run --rm -v $(pwd):/usr/src/app rotp_2.6

Alternately, you may use docker-compose to run all the tests:

docker-compose up

Executable Usage

The rotp rubygem includes CLI version to help with testing and debugging

# Try this to get an overview of the commands
rotp --help

# Examples
rotp --secret p4ssword                       # Generates a time-based one-time password
rotp --hmac --secret p4ssword --counter 42   # Generates a counter-based one-time password

Contributors

Have a look at the contributors graph on Github.

License

MIT Copyright (C) 2019 by Mark Percival, see LICENSE for details.

Other implementations

A list can be found at Wikipedia.

More Repositories

1

gibberish-aes

A fully OpenSSL compliant javascript library for AES encryption.
JavaScript
471
star
2

qrterminal

QR Codes in your terminal
Go
432
star
3

gibberish

Simple Ruby encryption module
Ruby
375
star
4

JsPoker

Texas Hold'em as played by bots written in JS
JavaScript
192
star
5

PlaneBoard

Read your tweets on the go via DNS TXT records
Go
83
star
6

MachinePoker

Gambling.js
CoffeeScript
75
star
7

middlefiddle

Fiddle in the middle with HTTP/HTTPS traffic using Node.js
JavaScript
58
star
8

divining_rod

A mobile phone web request profiler
Ruby
48
star
9

AtlantaWaterMeter

Read the Neptune R900 (Atlanta's) smart water meters with a raspberry pi and an RTL-SDR
Shell
41
star
10

bluemonday-js

The bluemonday sanitizer compiled to JavaScript
JavaScript
38
star
11

GistEvernoteImport

Import your gists to Evernote for searching
Ruby
32
star
12

GSMTracker

Use an unactivated prepaid Android phone to track it's own location.
Java
30
star
13

honeypot.go

SSH Honeypot written in Go
Go
26
star
14

u2fdemo

U2F Demo and Debugger
JavaScript
26
star
15

morse.mdp.im

Morse code app and podcast focused on head copy
TypeScript
25
star
16

hoyle

A javascript poker hand evaluator
CoffeeScript
24
star
17

iMessageChatDecompile

A decompilation of iMessage Chat from Huluwa
22
star
18

runnel

A really simple Ruby ssh tunnel manager
Ruby
21
star
19

SlidePrint

Print and Capture any DocSend deck or document
TypeScript
20
star
20

monochromeoled

Golang Library for working with SSD1306 OLEDs
Go
18
star
21

binions

A javascript Texas Holdem tournament engine
CoffeeScript
17
star
22

gibberish-libsodium

An example of using Libsodium in the browser for simple secret key based encryption
JavaScript
16
star
23

gloss

Super simple HTTPS reverse proxy written in Go
Go
14
star
24

u2fcli

Command line tool for using U2F tokens
Go
13
star
25

cist

Curl to Gist
JavaScript
12
star
26

dotp

Decentralized One Time Passwords
JavaScript
12
star
27

sodiumbox

Libsodium's crypto_box_sealed in pure golang
Go
10
star
28

hoganjs-brunch

A brunch compiler for Mustache template, using Hogan.js
JavaScript
9
star
29

node-at-yahoo

Shameless ploy to recruit via npm
JavaScript
8
star
30

plentyofstats

Ruby
7
star
31

gotraceroute

A very half-ass version of traceroute in Go
Go
6
star
32

pitboss

Run dubious code in node!
CoffeeScript
6
star
33

smallfont

Small monospaced pixel font (8x8) and rasterizer for LED/LCD projects
Go
6
star
34

Economist-Kindle

No longer actively maintained. Use Michael Kaiser's project below
Ruby
6
star
35

dns_leak_client

Leak information via DNS queries. Perfect for communicating with servers from behind a firewall/pay portal/restricted network
Java
6
star
36

quickadmin

A merb slice to quickly add admin only access via OpenID
Ruby
4
star
37

gibberish-aes-ruby

A fork of Alex Boussinet's Ruby AES library modified to support OpenSSL AES
Ruby
4
star
38

delo

Utility for writing to an OLED on Raspberry Pi
Go
4
star
39

sjcl_rb

The SJCL project in Ruby for compatibility
Ruby
4
star
40

NCoinbase

NodeJS library to interface with Coinbase via OAuth 2.0
JavaScript
3
star
41

docker-pdf-tools

My hacky but useful PDF tools
Shell
3
star
42

dnstime

Get the current time from a dns query
Go
3
star
43

json-zips

Zip codes in JSON and mirrored on Google Code for easy querying.
Ruby
3
star
44

BaseCJK

BaseCJK encoding in Javascript
JavaScript
3
star
45

dns_leak_server

The counter party to dns_leak
JavaScript
2
star
46

will_it_dial

A paranoid phone number validator
Ruby
2
star
47

go-statx

Simple CLI and library for StatX API
Go
2
star
48

simple_admin

A simple Open ID auth plugin for userless apps
Ruby
2
star
49

privacy_policy

My Privacy Policy for apps I make.
2
star
50

ESP32_DNS_Tracker

Rust
2
star
51

prisma_hyperdx

A quick sample of tracing in Prisma with OpenTelemetry and sending it to HyperDX
TypeScript
2
star
52

optimus_prime

A lazy sunday hack - crack RSA keys in JS
JavaScript
1
star
53

pingtags_dmca

Copyright 2018 Mark Percival - All rights reserved
JavaScript
1
star
54

docker-shallot

Run shallot in docker
1
star
55

ephemeral_twitter

Ephemeral Twitter
Ruby
1
star
56

four_bites_aes

A cipher for encoding 4 byte integers - i.e. Obfuscate your MySQL record id's
Ruby
1
star
57

UiPathTextAndFileEncryptionFlaw

The technical details and information related to a severe flaw in the handling of encryption in a popular UiPath plugin
C#
1
star
58

webpacker-docker

An example application for Rails 5.2 + Webpacker 3.4.3 on Docker/Docker Compose
Ruby
1
star
59

BitcoinArtAttack

JavaScript
1
star
60

twitter_getter

A simple ruby gem for accessing the Twitter API
Ruby
1
star
61

emailparse

Command line email parser - Personal use: bash scripts involving inbound email from SES
Go
1
star
62

dAuth

The dAuth App
JavaScript
1
star
63

pulley

Send pull requests to github via the command line - Gem now maintained by HQMQ at https://github.com/hqmq/pulley
Ruby
1
star
64

rsc

RSC mirror of the QR code from code.google.com
Go
1
star
65

openobserve_github_action_logs

Send Github Action logs to an OpenObserve instance
TypeScript
1
star
66

baroku

Demo for Codepath Nodejs Class
JavaScript
1
star
67

docker-awscli

AWS and Elastic Beanstalk CLI in Docker
1
star
68

pls

Parse PLS files (Typically MP3 stream playlists)
CoffeeScript
1
star
69

CellIdToGeo

Convert GSMTracker logs to Lat Long coordinates and display it on a map
JavaScript
1
star
70

dotfiles

My dotfiles
Shell
1
star