class TOTP

Overview

Crystal implementation for the Time-based One-Time PAssword (TOTP) two factor authentication algorithm. To get this to work you:

  1. Use generate_base32_secret() to generate a secret key for a user
  2. Store the secret key in the database associated with the user account
  3. Display the QR image URL returned by qrImageUrl(...) to the user
  4. User uses the image to load the secrey key into his authenticator application

Whenever the user logs in:

  1. The user enters the numnber from the authenticator application into the login form
  2. Read the secret associated with the user account from the database
  3. The server compares theuser input with the output form generate_current_number(...)
  4. If they are equal then the user is allowed to log in

See: https://github.com/SushiChain/crystal-two-factor-auth

For more details about this magic algorithm, see: http://en.wikipedia.org/wiki/Time-based_One-time_Password_Algorithm

Defined in:

crystal-two-factor-auth.cr

Constant Summary

DEFAULT_TIME_STEP_SECONDS = 30

default time-step which is part of the spec, 30 seconds is default

Class Method Summary

Class Method Detail

def self.generate_base32_secret(length : Int32 = 16) #

Generate and return a 16-character secret key in base32 format (A-Z2-7) using cystal-base32. Could be used to generate the QR image to be shared with the user. Other lengths should use generate_base32_secret(Int32).


[View source]
def self.generate_number_string(base32_secret : String, time_millis : Int64 = Time.now.to_unix_ms, time_step_seconds : Int32 = DEFAULT_TIME_STEP_SECONDS) #

Generate the authenticator number that is shown in the users app e.g. Google authenticator or Authy By default returns the current number but a time and time step can also be supplied. The returned number is zero padded if required.


[View source]
def self.otp_auth_url(key_id : String, secret : String) #

Return the otp-auth part of the QR image which is suitable to be injected into other QR generators (e.g. JS generator)

  • key_id: Name of the key that you want to show up in the users authentication application. Should already be URL encoded.
  • secret: Secret string that will be used when generating the current number.

[View source]
def self.qr_code_url(key_id : String, secret : String) #

Return the QR image url thanks to Google. This can be shown to the user and scanned by the authenticator program as an easy way to enter the secret.

  • key_id: Name of the key that you want to show up in the users authentication application. Should already be URL encoded.
  • secret: Secret string that will be used when generating the current number.

[View source]
def self.validate_number_string(base32_secret : String, auth_number : String, window_millis : Int32 = 10000, time_millis : Int64 = Time.now.epoch_ms, time_step_seconds : Int32 = DEFAULT_TIME_STEP_SECONDS) #

Validates if the auth number supplied matches the code generated from the base32_secret By default it works on the current time and uses the default time step

  • base32_secret: Secret string encoded using base-32 that was used to generate the QR code or shared with the user.
  • auth_number: Time based number provided by the user from their authenticator application.
  • window_millis: Number of milliseconds that they are allowed to be off and still match. This checks before and after the current time to account for clock variance. Set to 0 for no window. Defaults to 10 seconds
  • time_millis: Time in milliseconds.
  • time_step_seconds: Time step in seconds. The default value is 30 seconds here

[View source]