1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
#!/usr/bin/env python2
"""
Copyright (c) 2015-2018 Nitrokey UG
This file is part of libnitrokey.
libnitrokey is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
any later version.
libnitrokey is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with libnitrokey. If not, see <http://www.gnu.org/licenses/>.
SPDX-License-Identifier: LGPL-3.0
"""
import cffi
from enum import Enum
"""
This example will print 10 HOTP codes from just written HOTP#2 slot.
For more examples of use please refer to unittest/test_*.py files.
"""
ffi = cffi.FFI()
get_string = ffi.string
class DeviceErrorCode(Enum):
STATUS_OK = 0
NOT_PROGRAMMED = 3
WRONG_PASSWORD = 4
STATUS_NOT_AUTHORIZED = 5
STATUS_AES_DEC_FAILED = 0xa
def get_library():
fp = 'NK_C_API.h' # path to C API header
declarations = []
with open(fp, 'r') as f:
declarations = f.readlines()
cnt = 0
a = iter(declarations)
for declaration in a:
if declaration.strip().startswith('NK_C_API'):
declaration = declaration.replace('NK_C_API', '').strip()
while ';' not in declaration:
declaration += (next(a)).strip()
# print(declaration)
ffi.cdef(declaration, override=True)
cnt +=1
print('Imported {} declarations'.format(cnt))
C = None
import os, sys
path_build = os.path.join(".", "build")
paths = [
os.environ.get('LIBNK_PATH', None),
os.path.join(path_build,"libnitrokey.so"),
os.path.join(path_build,"libnitrokey.dylib"),
os.path.join(path_build,"libnitrokey.dll"),
os.path.join(path_build,"nitrokey.dll"),
]
for p in paths:
if not p: continue
print("Trying " +p)
p = os.path.abspath(p)
if os.path.exists(p):
print("Found: "+p)
C = ffi.dlopen(p)
break
else:
print("File does not exist: " + p)
if not C:
print("No library file found")
print("Please set the path using LIBNK_PATH environment variable to existing library or compile it (see "
"README.md for details)")
sys.exit(1)
return C
def get_hotp_code(lib, i):
return get_string(lib.NK_get_hotp_code(i))
def to_hex(ss):
return ''.join([ format(ord(s),'02x') for s in ss ])
print('Warning!')
print('This example will change your configuration on inserted stick and overwrite your HOTP#2 slot.')
print('Please write "continue" to continue or any other string to quit')
a = raw_input()
if not a == 'continue':
exit()
ADMIN = raw_input('Please enter your admin PIN (empty string uses 12345678) ')
ADMIN = ADMIN or '12345678' # use default if empty string
show_log = raw_input('Should log messages be shown (please write "yes" to enable; this will make harder reading script output) ') == 'yes'
libnitrokey = get_library()
if show_log:
log_level = raw_input('Please select verbosity level (0-5, 2 is library default, 3 will be selected on empty input) ')
log_level = log_level or '3'
log_level = int(log_level)
libnitrokey.NK_set_debug_level(log_level)
else:
libnitrokey.NK_set_debug_level(2)
ADMIN_TEMP = '123123123'
RFC_SECRET = to_hex('12345678901234567890')
# libnitrokey.NK_login('S') # connect only to Nitrokey Storage device
# libnitrokey.NK_login('P') # connect only to Nitrokey Pro device
device_connected = libnitrokey.NK_login_auto() # connect to any Nitrokey Stick
if device_connected:
print('Connected to Nitrokey device!')
else:
print('Could not connect to Nitrokey device!')
exit()
use_8_digits = True
pin_correct = libnitrokey.NK_first_authenticate(ADMIN, ADMIN_TEMP) == DeviceErrorCode.STATUS_OK
if pin_correct:
print('Your PIN is correct!')
else:
print('Your PIN is not correct! Please try again. Please be careful to not lock your stick!')
retry_count_left = libnitrokey.NK_get_admin_retry_count()
print('Retry count left: %d' % retry_count_left )
exit()
# For function parameters documentation please check NK_C_API.h
assert libnitrokey.NK_write_config(255, 255, 255, False, True, ADMIN_TEMP) == DeviceErrorCode.STATUS_OK
libnitrokey.NK_first_authenticate(ADMIN, ADMIN_TEMP)
libnitrokey.NK_write_hotp_slot(1, 'python_test', RFC_SECRET, 0, use_8_digits, False, False, "",
ADMIN_TEMP)
# RFC test according to: https://tools.ietf.org/html/rfc4226#page-32
test_data = [
1284755224, 1094287082, 137359152, 1726969429, 1640338314, 868254676, 1918287922, 82162583, 673399871,
645520489,
]
print('Getting HOTP code from Nitrokey Stick (RFC test, 8 digits): ')
for i in range(10):
hotp_slot_1_code = get_hotp_code(libnitrokey, 1)
correct_str = "correct!" if hotp_slot_1_code == str(test_data[i])[-8:] else "not correct"
print('%d: %s, should be %s -> %s' % (i, hotp_slot_1_code, str(test_data[i])[-8:], correct_str))
libnitrokey.NK_logout() # disconnect device
|