Import Upstream version 1.3.3
This commit is contained in:
132
util/yubikey-totp
Executable file
132
util/yubikey-totp
Executable file
@@ -0,0 +1,132 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (c) 2011, Yubico AB
|
||||
# See the file COPYING for licence statement.
|
||||
#
|
||||
|
||||
"""
|
||||
This program lets you use the HMAC-SHA-1 in your YubiKey to produce
|
||||
OATH TOTP (RFC 6238) codes.
|
||||
|
||||
To verify the output of this program, first program a YubiKey with the
|
||||
RFC 6238 test key "12345678901234567890" (ASCII) :
|
||||
|
||||
$ ykpersonalize -2 -ochal-resp -ochal-hmac -ohmac-lt64 \
|
||||
-o serial-api-visible \
|
||||
-a 3132333435363738393031323334353637383930
|
||||
|
||||
and then examine the OATH codes for the test values (Time) in Appendix B
|
||||
of RFC 6238 (SHA1) :
|
||||
|
||||
Time SHA1
|
||||
59 -> 94287082
|
||||
1111111109 -> 07081804
|
||||
1234567890 -> 89005924
|
||||
20000000000 -> 65353130
|
||||
|
||||
Like this :
|
||||
|
||||
$ yubikey-totp --step 30 --digits 8 --time 59
|
||||
94287082
|
||||
$
|
||||
|
||||
"""
|
||||
|
||||
|
||||
import sys
|
||||
import time
|
||||
import struct
|
||||
import yubico
|
||||
import argparse
|
||||
import binascii
|
||||
|
||||
default_slot=2
|
||||
default_time=int(time.time())
|
||||
default_step=30
|
||||
default_digits=6
|
||||
|
||||
def parse_args():
|
||||
"""
|
||||
Parse the command line arguments
|
||||
"""
|
||||
parser = argparse.ArgumentParser(description = "Generate OATH TOTP codes using a YubiKey",
|
||||
add_help = True,
|
||||
formatter_class = argparse.ArgumentDefaultsHelpFormatter,
|
||||
)
|
||||
parser.add_argument('-v', '--verbose',
|
||||
dest='verbose',
|
||||
action='store_true', default=False,
|
||||
help='Enable verbose operation'
|
||||
)
|
||||
parser.add_argument('--debug',
|
||||
dest='debug',
|
||||
action='store_true', default=False,
|
||||
help='Enable debug operation'
|
||||
)
|
||||
parser.add_argument('--time',
|
||||
dest='time',
|
||||
type=int, default=default_time,
|
||||
required=False,
|
||||
help='Time to use as number of seconds since epoch',
|
||||
)
|
||||
parser.add_argument('--step',
|
||||
dest='step',
|
||||
type=int, default=default_step,
|
||||
required=False,
|
||||
help='Time step in use (in seconds)',
|
||||
)
|
||||
parser.add_argument('--digits',
|
||||
dest='digits',
|
||||
type=int, default=default_digits,
|
||||
required=False,
|
||||
help='Length of OTP in decimal digits',
|
||||
)
|
||||
parser.add_argument('--slot',
|
||||
dest='slot',
|
||||
type=int, default=default_slot,
|
||||
required=False,
|
||||
help='YubiKey slot configured for Challenge-Response',
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
return args
|
||||
|
||||
def make_totp(args):
|
||||
"""
|
||||
Create an OATH TOTP OTP and return it as a string (to disambiguate leading zeros).
|
||||
"""
|
||||
YK = yubico.find_yubikey(debug=args.debug)
|
||||
if args.debug or args.verbose:
|
||||
print("Version : %s " % YK.version())
|
||||
if args.debug:
|
||||
print("Serial : %i" % YK.serial())
|
||||
print("")
|
||||
# Do challenge-response
|
||||
secret = struct.pack("> Q", args.time / args.step).ljust(64, chr(0x0))
|
||||
if args.debug:
|
||||
print("Sending challenge : %s\n" % (binascii.hexlify(secret)))
|
||||
response = YK.challenge_response(secret, slot=args.slot)
|
||||
# format with appropriate number of leading zeros
|
||||
totp_str = '%.*i' % (args.digits, yubico.yubico_util.hotp_truncate(response, length=args.digits))
|
||||
return totp_str
|
||||
|
||||
def main():
|
||||
""" Main program. """
|
||||
args = parse_args()
|
||||
|
||||
otp = None
|
||||
try:
|
||||
otp = make_totp(args)
|
||||
except yubico.yubico_exception.YubicoError as e:
|
||||
print("ERROR: %s" % (e.reason))
|
||||
return 1
|
||||
|
||||
if not otp:
|
||||
return 1
|
||||
|
||||
print(otp)
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user