116 lines
5.8 KiB
Python
116 lines
5.8 KiB
Python
import base64
|
|
import hashlib
|
|
from pathlib import Path
|
|
|
|
import bcrypt
|
|
import numpy as np
|
|
from secrets import choice
|
|
from string import ascii_lowercase
|
|
from docs.scripts.utils import render_markdown_template, emojis
|
|
from src.models import NKodePolicy, KeypadSize
|
|
from src.nkode_api import NKodeAPI
|
|
from src.user_cipher import UserCipher
|
|
from src.utils import select_keys_with_passcode_values
|
|
|
|
def display_keypad(icons_array: np.ndarray, props_per_key: int) -> str:
|
|
icons = ""
|
|
for idx, row in enumerate(icons_array.reshape(-1, props_per_key)):
|
|
icons += f"Key {idx}: "
|
|
icons += str(row)
|
|
icons += "\n"
|
|
return icons
|
|
|
|
if __name__ == "__main__":
|
|
api = NKodeAPI()
|
|
|
|
policy = NKodePolicy(
|
|
max_nkode_len=10,
|
|
min_nkode_len=4,
|
|
distinct_positions=0,
|
|
distinct_properties=4,
|
|
)
|
|
keypad_size = KeypadSize(
|
|
numb_of_keys=6,
|
|
props_per_key=9
|
|
)
|
|
customer_id = api.create_new_customer(keypad_size, policy)
|
|
customer = api.get_customer(customer_id)
|
|
username = "test_username" + "".join([choice(ascii_lowercase) for _ in range(6)])
|
|
signup_session_id, set_signup_keypad = api.generate_signup_keypad(customer_id, username)
|
|
ordered_set_icons = emojis[set_signup_keypad]
|
|
passcode_len = 4
|
|
passcode_property_indices = np.random.choice(set_signup_keypad.reshape(-1), size=passcode_len,
|
|
replace=False).tolist()
|
|
selected_keys_set = select_keys_with_passcode_values(passcode_property_indices, set_signup_keypad,
|
|
keypad_size.numb_of_keys)
|
|
confirm_keypad = api.set_nkode(customer_id, selected_keys_set, signup_session_id)
|
|
selected_keys_confirm = select_keys_with_passcode_values(passcode_property_indices, confirm_keypad,
|
|
keypad_size.numb_of_keys)
|
|
ordered_confirm_icons = emojis[confirm_keypad]
|
|
success = api.confirm_nkode(customer_id, selected_keys_confirm, signup_session_id)
|
|
user = api.customers[customer_id].users[username]
|
|
combined_prop_key = user.cipher.property_key ^ customer.cipher.property_key
|
|
user_passcode = combined_prop_key[passcode_property_indices]
|
|
pad_len = customer.nkode_policy.max_nkode_len - passcode_len
|
|
padded_passcode = np.concatenate((user_passcode, np.zeros(pad_len, dtype=user_passcode.dtype)))
|
|
ciphered_passcode = padded_passcode ^ user.cipher.pass_key
|
|
passcode_prehash = base64.b64encode(hashlib.sha256(ciphered_passcode.tobytes()).digest())
|
|
passcode_hash = bcrypt.hashpw(passcode_prehash, bcrypt.gensalt(rounds=12)).decode("utf-8")
|
|
|
|
padded_passcode_position_indices = customer.cipher.get_passcode_position_indices_padded(
|
|
list(passcode_property_indices), customer.nkode_policy.max_nkode_len)
|
|
user_position_key = user.cipher.combined_position_key ^ customer.cipher.position_key
|
|
ordered_user_position_key = user_position_key[padded_passcode_position_indices]
|
|
mask = ordered_user_position_key ^ user.cipher.mask_key
|
|
encoded_mask = user.cipher.encode_base64_str(mask)
|
|
login_keypad = api.get_login_keypad(username, customer_id)
|
|
selected_keys_login = select_keys_with_passcode_values(passcode_property_indices, login_keypad,
|
|
keypad_size.props_per_key)
|
|
|
|
old_props = customer.cipher.property_key.copy()
|
|
old_pos = customer.cipher.position_key.copy()
|
|
customer.cipher.property_key = np.random.choice(2 ** 16, size=keypad_size.total_props, replace=False)
|
|
customer.cipher.position_key = np.random.choice(2 ** 16, size=keypad_size.props_per_key, replace=False)
|
|
new_props = customer.cipher.property_key
|
|
new_pos = customer.cipher.position_key
|
|
props_xor = new_props ^ old_props
|
|
pos_xor = new_pos ^ old_pos
|
|
user = customer.users[username]
|
|
new_user_cipher = UserCipher.create(keypad_size, customer.cipher.position_key, policy.max_nkode_len)
|
|
context = {
|
|
"max_nkode_len": policy.max_nkode_len,
|
|
"numb_of_keys": keypad_size.numb_of_keys,
|
|
"props_per_key": keypad_size.props_per_key,
|
|
"customer_property_key": customer.cipher.property_key,
|
|
"customer_position_key": customer.cipher.position_key,
|
|
"user_property_key": user.cipher.property_key,
|
|
"pass_key": user.cipher.pass_key,
|
|
"combined_position_key": user.cipher.combined_position_key,
|
|
"user_position_key": user_position_key,
|
|
"mask_key": user.cipher.mask_key,
|
|
"user_passcode_idxs": passcode_property_indices,
|
|
"combined_property_key": combined_prop_key,
|
|
"user_passcode_props": user_passcode,
|
|
"padded_passcode": padded_passcode,
|
|
"ciphered_passcode": ciphered_passcode,
|
|
"code": passcode_hash,
|
|
"passcode_position_idxs": padded_passcode_position_indices[:passcode_len],
|
|
"pad_user_passcode_idxs": padded_passcode_position_indices,
|
|
"ordered_user_position_key":ordered_user_position_key,
|
|
"mask": mask,
|
|
"selected_keys": selected_keys_login,
|
|
"login_keypad": display_keypad(login_keypad, keypad_size.props_per_key),
|
|
"ordered_keys": login_keypad.reshape(-1, keypad_size.props_per_key)[selected_keys_login],
|
|
"old_props": old_props,
|
|
"new_props": new_props,
|
|
"old_pos": old_pos,
|
|
"new_pos": new_pos,
|
|
"xor_props": props_xor,
|
|
"xor_pos": pos_xor,
|
|
"inter_user_position": user.cipher.combined_position_key ^ pos_xor,
|
|
"inter_user_property_key": user.cipher.property_key ^ props_xor,
|
|
"new_user_position": new_user_cipher.combined_position_key,
|
|
"new_user_property_key": new_user_cipher.property_key,
|
|
}
|
|
render_markdown_template(Path("../templates/encipher_decipher_renew_nkode.template.md"), Path("../encipher_decipher_renew_nkode.md"), context)
|