diff options
| author | Sven Ebenfeld <sven.ebenfeld@gmail.com> | 2020-04-28 15:03:33 +0200 | 
|---|---|---|
| committer | Sven Ebenfeld <sven.ebenfeld@gmail.com> | 2020-04-28 15:04:26 +0200 | 
| commit | 5f0d4ace04ec1c99e5e851cf79559c80c5f7f379 (patch) | |
| tree | 4c545e3b7093c7c22ffd1a70f46ad203509ca7c0 | |
| parent | 2e38681cd0b34e1ce36a6417445f3a7ca75f246c (diff) | |
| download | libnitrokey-5f0d4ace04ec1c99e5e851cf79559c80c5f7f379.tar.gz libnitrokey-5f0d4ace04ec1c99e5e851cf79559c80c5f7f379.tar.bz2 | |
add python_bindings_example for python3
Signed-off-by: Sven Ebenfeld <sven.ebenfeld@gmail.com>
| -rw-r--r-- | python3_bindings_example.py | 157 | 
1 files changed, 157 insertions, 0 deletions
| diff --git a/python3_bindings_example.py b/python3_bindings_example.py new file mode 100644 index 0000000..fb24eff --- /dev/null +++ b/python3_bindings_example.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python3 +""" +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 = input() + +if not a == 'continue': +    exit() + +ADMIN = input('Please enter your admin PIN (empty string uses 12345678) ') +ADMIN = ADMIN or '12345678'  # use default if empty string + +show_log = 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 = 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.encode('ascii'), ADMIN_TEMP.encode('ascii')) == DeviceErrorCode.STATUS_OK.value +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.encode('ascii')) == DeviceErrorCode.STATUS_OK.value +libnitrokey.NK_first_authenticate(ADMIN.encode('ascii'), ADMIN_TEMP.encode('ascii')) +libnitrokey.NK_write_hotp_slot(1, 'python_test'.encode('ascii'), RFC_SECRET.encode('ascii'), 0, use_8_digits, False, False, "".encode('ascii'), +                            ADMIN_TEMP.encode('ascii')) +# 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.decode('ascii') == str(test_data[i])[-8:] else  "not correct" +    print('%d: %s, should be %s -> %s' % (i, hotp_slot_1_code.decode('ascii'), str(test_data[i])[-8:], correct_str)) +libnitrokey.NK_logout()  # disconnect device | 
