class SecondFactor::OTP

Public Class Methods

generate_hmac(seed_based, step) click to toggle source
# File lib/secondfactor/otp.rb, line 10
def self.generate_hmac(seed_based, step)
  seed_bytes = Base32.decode(seed_based)
  hmac = OpenSSL::HMAC.digest(OpenSSL::Digest.new("sha1"), seed_bytes, self.intbytes(step))

  # https://tools.ietf.org/html/rfc4226#section-5.4
  offset = hmac[-1].ord & 0xF
  truncated = (hmac[offset].ord & 0x7F) << 24 | (hmac[offset + 1].ord & 0xFF) << 16 | (hmac[offset + 2].ord & 0xFF) << 8 | (hmac[offset + 3].ord & 0xFF)

  return truncated
end
generate_seed(length=10) click to toggle source
# File lib/secondfactor/otp.rb, line 3
def self.generate_seed(length=10)
  seed_bytes = (0...length).map { rand(255).chr }
  seed_based = Base32.encode(seed_bytes.join)

  return seed_based
end
intbytes(int) click to toggle source

Roughly adapted from github.com/aeyris/otp

# File lib/secondfactor/otp.rb, line 22
def self.intbytes(int)
  result = ""

  8.times do
    result << (int & 0xFF).chr
    int >>=  8
  end

  return result.reverse.rjust(8, 0.chr)
end