Mintotp

Mintotp is a minimal TOTP generator written in Ruby. Inspired by this library.

Mintotp

GitHub issues GitHub license

Installation

Add this line to your application's Gemfile:

gem 'mintotp'

And then execute:

$ bundle install

Or install it yourself as:

$ gem install mintotp

Usage

    SECRET1 = "ZYTYYE5FOAGW5ML7LRWUL4WTZLNJAMZS"
    minTotp = Mintotp::TOTP.new()
    minTotp.totp(SECRET1) # => return the same time based token from Google Authenticator

Source Code

At the heart of the TOTP algorithm lies the HOTP algorithm. HOTP stands for HMAC-based One-Time Password. HMAC stands for Hash-based Message Authentication Code. Here are the relevant RFCs to learn more about these algorithms:

  • RFC 2104: HMAC: Keyed-Hashing for Message Authentication
  • RFC 4226: HOTP: An HMAC-Based One-Time Password Algorithm
  • RFC 6238: TOTP: Time-Based One-Time Password Algorithm

The source code in totp.rb generates TOTP values from a secret key and current time. Here is the entire code presented once again for convenience:

require 'base32'
require 'openssl'

module Mintotp
  class TOTP
    #
    # @key : secret key
    # @time_step : TimeStep Second Default is 30 Second
    # @digits : Number of digits that will generate
    # @digest : hash name
    #
    def totp(key, time_step=30, digits=6, digest='sha1')
      hotp(key, Time.now.to_i / time_step, digits, digest)
    end

    def hotp(key, counter, digits=6, digest='sha1')
      key = Base32.decode "#{key}#{"="* ((8-key.length)%8)}"
      sha = OpenSSL::Digest::Digest.new(digest)
      counter = [counter].pack('Q>')
      hmac= OpenSSL::HMAC.digest(sha, key, counter)

      offset = hmac.bytes.last & 0x0f   
      bytes = hmac.bytes[offset..offset+4]

      # unpack by bytes shifting
      bytes[0] = bytes[0] & 0x7f
      bytes_as_integer = (bytes[0] << 24) + (bytes[1] << 16) + (bytes[2] << 8) + bytes[3]
      bytes_as_integer.modulo(10 ** digits).to_s.rjust(digits,'0')
    end
  end
end

In the code above, we use the hmac module available in the Ruby standard library to implement HOTP. The implementation can be found in the hotp() function. It is a pretty straightforward implementation of RFC 2104: Section 5: HOTP Algorithm. It takes a Base32-encoded secret key and a counter as input. It returns a 6-digit HOTP value as output.

The totp() function implements the TOTP algorithm. It is a thin wrapper around the HOTP algorithm. The TOTP value is obtained by invoking the HOTP function with the secret key and the number of time intervals (30 second intervals by default) that have elapsed since Unix epoch (1970-01-01 00:00:00 UTC).

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Test

$ rspec

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/winhtaikaung/mintotp.

License

The gem is available as open source under the terms of the MIT License.