Class: HOTP

Inherits:
Object
  • Object
show all
Defined in:
lib/HOTP.rb

Overview

This implements HOTP: An HMAC-Based One-Time Password Algorithm as described in RFC 4226 (www.ietf.org/rfc/rfc4226.txt)

Constant Summary collapse

@@logger =

The default logger to use when reporting an error. (Defaults to STDERR)

Logger.new(STDERR)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(secret = nil, count = nil, digits = 6) ⇒ HOTP

puts(HOTP::hotp(secret,count)) # => “755224”



89
90
91
92
93
94
95
96
97
# File 'lib/HOTP.rb', line 89

def initialize(secret=nil,count=nil,digits=6)
	begin
		@secret = secret
		@count = count
		@digits = digits
	rescue Exception => e
		@@logger.fatal{"Unable to initialize HOTP properly. Reason: #{e}"}
	end
end

Instance Attribute Details

#countObject

The count used to start the calculation ©



62
63
64
# File 'lib/HOTP.rb', line 62

def count
  @count
end

#digitsObject

The length of the HOTP value (Digit) (Defaults to 6)



64
65
66
# File 'lib/HOTP.rb', line 64

def digits
  @digits
end

#secretObject

The secret key in ascii (K)



60
61
62
# File 'lib/HOTP.rb', line 60

def secret
  @secret
end

Class Method Details

.hotp(secret, count, digits = 6) ⇒ Object

Class method that returns the HOTP value as a string



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/HOTP.rb', line 116

def self.hotp(secret,count,digits=6)
	begin
		# The secret is plain text
		# i.e "1234567891234567890"
		# The count needs to be in hex so we need to convert it into a padded hex string
		# i.e. 10 = "\x00\x00\x00\x00\x00\x00\x00\x0a"
		# The digits are the number of digits to use when calculating the HOTP. (defaults to 6)
		sha1_hash = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new("SHA1"), secret, string_to_hex_value(count,8))
		#the last hex value is the offset
		offset = sha1_hash[-1].chr.hex
		#get the string in the offset range
		dbc1 = sha1_hash[(offset*2)...((offset*2)+8)]
		#31bits
		dbc2 = dbc1.hex & "7fffffff".hex
		hotp = dbc2%(10**digits.to_i)
		hotp = sprintf("%0#{digits}d", hotp)
		return hotp
	rescue Exception => e
		@@logger.fatal{"Unable to calculate the HOTP value. Reason: #{e}"}
	end
end

.logger=(logger) ⇒ Object

Set the Logger object. By default this logs to STDERR



112
113
114
# File 'lib/HOTP.rb', line 112

def self.logger=(logger)
	@@logger = logger
end

Instance Method Details

#calculate_hotp(secret, count, digits = 6) ⇒ Object

Returns the HOTP value as a string



108
109
110
# File 'lib/HOTP.rb', line 108

def calculate_hotp(secret,count,digits=6)
	return HOTP::hotp(secret,count,digits)
end

#updateObject Also known as: hotp

Returns the HOTP value as a string



99
100
101
102
103
104
105
# File 'lib/HOTP.rb', line 99

def update
	begin
		return calculate_hotp(@secret, @count, @digits)
	rescue Exception => e
		@@logger.fatal{"Unable to update. Reason #{e}"}
	end
end