Files
pynkode/docs/render_markdown.py

217 lines
8.2 KiB
Python

from jinja2 import Environment, FileSystemLoader
import os
from src.nkode_api import NKodeAPI
from src.models import NKodePolicy, KeypadSize, EncipheredNKode
from src.user_cipher_keys import UserCipher
from src.utils import list_to_matrix, matrix_transpose, xor_lists
from secrets import choice
from string import ascii_lowercase
import bcrypt
import hashlib
import base64
from src.utils import int_array_to_bytes
def random_username() -> str:
return "test_username" + "".join([choice(ascii_lowercase) for _ in range(6)])
def select_keys_with_passcode_values(user_passcode: list[int], interface: list[int], attrs_per_key: int) -> list[int]:
return [interface.index(attr) // attrs_per_key for attr in user_passcode]
def keypad_view(interface: list[int], attrs_per_key: int):
print("Keypad View")
interface_keypad = list_to_matrix(interface, attrs_per_key)
for idx, key_vals in enumerate(interface_keypad):
print(f"Key {idx}: {key_vals}")
def render_nkode_authentication(data: dict):
# Set up the Jinja2 environment and template loader
file_loader = FileSystemLoader('')
env = Environment(loader=file_loader)
# Load the template
template = env.get_template('nkode_authentication_template.md')
print(os.getcwd())
# Render the template with the data
output = template.render(data)
# Print or save the output
output_file = "/Users/donov/Desktop/NKode_documentation/nkode/docs/nkode_authentication.md"
with open(output_file, 'w') as fp:
fp.write(output)
print("File written successfully")
if __name__ == "__main__":
api = NKodeAPI()
policy = NKodePolicy(
max_nkode_len=10,
min_nkode_len=4,
distinct_sets=0,
distinct_attributes=4,
byte_len=2,
)
keypad_size = KeypadSize(
numb_of_keys=5,
props_per_key=6 # aka number of sets
)
customer_id = api.create_new_customer(keypad_size, policy)
customer = api.customers[customer_id]
set_vals = customer.customer_cipher.set_key
attr_vals = customer.customer_cipher.prop_key
customer_attr_view = list_to_matrix(attr_vals, keypad_size.props_per_key)
attr_keypad_view = list_to_matrix(attr_vals, keypad_size.props_per_key)
attr_set_view = matrix_transpose(attr_keypad_view)
set_attribute_dict = dict(zip(set_vals, attr_set_view))
session_id, signup_interface = api.generate_signup_interface(customer_id)
signup_keypad = list_to_matrix(signup_interface, keypad_size.numb_of_keys)
username = random_username()
passcode_len = 4
user_passcode = signup_interface[:passcode_len]
selected_keys_set = select_keys_with_passcode_values(user_passcode, signup_interface, keypad_size.numb_of_keys)
server_side_attr = [customer.customer_cipher.prop_key[idx] for idx in user_passcode]
confirm_interface = api.set_nkode(username, customer_id, selected_keys_set, session_id)
confirm_keypad = list_to_matrix(confirm_interface, keypad_size.numb_of_keys)
selected_keys_confirm = select_keys_with_passcode_values(user_passcode, confirm_interface, keypad_size.numb_of_keys)
success = api.confirm_nkode(username, customer_id, selected_keys_confirm, session_id)
assert success
passcode_server_attr = [customer.customer_cipher.prop_key[idx] for idx in user_passcode]
passcode_server_set = [customer.customer_cipher.get_prop_set_val(attr) for attr in passcode_server_attr]
user_keys = customer.users[username].user_keys
padded_passcode_server_set = user_keys.pad_user_mask(passcode_server_set, customer.customer_cipher.set_key)
set_idx = [customer.customer_cipher.get_set_index(set_val) for set_val in padded_passcode_server_set]
mask_set_keys = [user_keys.set_key[idx] for idx in set_idx]
ciphered_mask = xor_lists(mask_set_keys, padded_passcode_server_set)
ciphered_mask = xor_lists(ciphered_mask, user_keys.mask_key)
mask = user_keys.encode_base64_str(ciphered_mask)
ciphered_customer_attrs = xor_lists(customer.customer_cipher.prop_key, user_keys.alpha_key)
passcode_ciphered_attrs = [ciphered_customer_attrs[idx] for idx in user_passcode]
pad_len = customer.nkode_policy.max_nkode_len - passcode_len
passcode_ciphered_attrs.extend([0 for _ in range(pad_len)])
ciphered_code = xor_lists(passcode_ciphered_attrs, user_keys.pass_key)
passcode_bytes = int_array_to_bytes(ciphered_code)
passcode_digest = base64.b64encode(hashlib.sha256(passcode_bytes).digest())
hashed_data = bcrypt.hashpw(passcode_digest, user_keys.salt)
code = hashed_data.decode("utf-8")
enciphered_nkode = EncipheredNKode(
mask=mask,
code=code,
)
"""
USER LOGIN
"""
login_interface = api.get_login_interface(username, customer_id)
login_keypad = list_to_matrix(login_interface, keypad_size.props_per_key)
selected_keys_login = select_keys_with_passcode_values(user_passcode, login_interface, keypad_size.props_per_key)
success = api.login(customer_id, username, selected_keys_login)
assert success
"""
VALIDATE LOGIN KEY ENTRY
DECIPHER MASK
"""
user = customer.users[username]
set_vals = customer.customer_cipher.set_key
user_keys = user.user_keys
user_mask = user.enciphered_passcode.mask
decoded_mask = user_keys.decode_base64_str(user_mask)
deciphered_mask = xor_lists(decoded_mask, user_keys.mask_key)
set_key_rand_component = xor_lists(set_vals, user_keys.set_key)
login_passcode_sets = []
for set_cipher in deciphered_mask[:passcode_len]:
set_idx = set_key_rand_component.index(set_cipher)
login_passcode_sets.append(set_vals[set_idx])
"""
GET PRESUMED ATTRIBUTES
"""
set_vals_idx = [customer.customer_cipher.get_set_index(set_val) for set_val in login_passcode_sets]
presumed_selected_attributes_idx = []
for idx in range(passcode_len):
key_numb = selected_keys_login[idx]
set_idx = set_vals_idx[idx]
selected_attr_idx = customer.users[username].user_interface.get_attr_idx_by_keynumb_setidx(key_numb, set_idx)
presumed_selected_attributes_idx.append(selected_attr_idx)
"""
RENEW KEYS
"""
old_attrs = customer.customer_cipher.prop_key.copy()
old_sets = customer.customer_cipher.set_key.copy()
customer.customer_cipher.renew()
new_attrs = customer.customer_cipher.prop_key
new_sets = customer.customer_cipher.set_key
customer_new_attr_view = list_to_matrix(new_attrs, keypad_size.props_per_key)
"""
RENEW USER
"""
attrs_xor = xor_lists(new_attrs, old_attrs)
sets_xor = xor_lists(new_sets, old_sets)
for user in customer.users.values():
user.renew = True
user.user_keys.set_key = xor_lists(user.user_keys.set_key, sets_xor)
user.user_keys.alpha_key = xor_lists(user.user_keys.alpha_key, attrs_xor)
"""
REFRESH USER KEYS
"""
user.user_keys = UserCipher.create(
customer.customer_cipher.keypad_size,
customer.customer_cipher.set_key,
user.user_keys.max_nkode_len
)
user.enciphered_passcode = user.user_keys.encipher_nkode(presumed_selected_attributes_idx, customer.customer_cipher)
user.renew = False
# Define some data to pass to the template
data = {
'keypad_size': keypad_size,
'customer_set_vals': set_vals,
'customer_attr_view': customer_attr_view,
'set_attribute_dict': set_attribute_dict,
'signup_keypad': signup_keypad,
'username': 'test_user',
'user_passcode': user_passcode,
'selected_keys_set': selected_keys_set,
'server_side_attr': server_side_attr,
'confirm_keypad': confirm_keypad,
'selected_keys_confirm': selected_keys_confirm,
'user_keys': user_keys,
'passcode_server_attr': passcode_server_attr,
'passcode_server_set': passcode_server_set,
'enciphered_nkode': enciphered_nkode,
'login_keypad': login_keypad,
'selected_login_keys': selected_keys_login,
'login_passcode_sets': login_passcode_sets,
'presumed_selected_attributes_idx': presumed_selected_attributes_idx,
'customer_new_attr_view': customer_new_attr_view,
'customer_new_set_vals': new_sets,
}
render_nkode_authentication(data)