Class: Yubikey::OTP

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

Defined Under Namespace

Classes: BadCRCError, InvalidKeyError, InvalidOTPError, Verify

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(otp, key) ⇒ OTP

Decode/decrypt a Yubikey one-time password

otp

ModHex encoded Yubikey OTP (at least 32 characters)

key

32-character hex AES key

Raises:


24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/yubikey/otp.rb', line 24

def initialize(otp, key)
  raise InvalidOTPError, 'OTP must be at least 32 characters of modhex' unless otp.modhex? && otp.length >= 32
  raise InvalidKeyError, 'Key must be 32 hex characters' unless key.hex? && key.length == 32

  # Get the public ID first
  @public_id = otp[0, 12]

  # Strip prefix so otp will decode (following from yubico-c library)
  otp = otp[-32,32] if otp.length > 32

  @token = Yubikey::ModHex.decode(otp[-32,32])
  @aes_key = key.to_bin

  decrypter = OpenSSL::Cipher.new('AES-128-ECB').decrypt
  decrypter.key = @aes_key
  decrypter.padding = 0

  @token = decrypter.update(@token) + decrypter.final

  raise BadCRCError unless crc_valid?

  @secret_id, @insert_counter, @timestamp, @timestamp_lo, @session_counter, @random_number, @crc = @token.unpack('H12vvCCvv')
  @timestamp += @timestamp_lo * 65536
end

Instance Attribute Details

#aes_keyObject (readonly)

binary AES key


7
8
9
# File 'lib/yubikey/otp.rb', line 7

def aes_key
  @aes_key
end

#insert_counterObject (readonly)

integer that increments each time the Yubikey is plugged in


11
12
13
# File 'lib/yubikey/otp.rb', line 11

def insert_counter
  @insert_counter
end

#public_idObject (readonly)

first few modhex encoded characters of the OTP


3
4
5
# File 'lib/yubikey/otp.rb', line 3

def public_id
  @public_id
end

#random_numberObject (readonly)

random integer used as padding and extra random noise


17
18
19
# File 'lib/yubikey/otp.rb', line 17

def random_number
  @random_number
end

#secret_idObject (readonly)

hex id (encrypted in OTP)


9
10
11
# File 'lib/yubikey/otp.rb', line 9

def secret_id
  @secret_id
end

#session_counterObject (readonly)

activation counter, reset on every insert


15
16
17
# File 'lib/yubikey/otp.rb', line 15

def session_counter
  @session_counter
end

#timestampObject (readonly)

~8hz timer, reset on every insert


13
14
15
# File 'lib/yubikey/otp.rb', line 13

def timestamp
  @timestamp
end

#tokenObject (readonly)

decrypted binary token


5
6
7
# File 'lib/yubikey/otp.rb', line 5

def token
  @token
end