822 lines
24 KiB
Plaintext
822 lines
24 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "code",
|
|
"source": [
|
|
"from src.nkode_api import NKodeAPI\n",
|
|
"from src.models import NKodePolicy, KeypadSize\n",
|
|
"from secrets import choice\n",
|
|
"from string import ascii_lowercase\n",
|
|
"import numpy as np"
|
|
],
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-14T14:18:14.423890Z",
|
|
"start_time": "2025-03-14T14:18:14.420788Z"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"execution_count": 23
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"source": [
|
|
"def random_username() -> str:\n",
|
|
" return \"test_username\" + \"\".join([choice(ascii_lowercase) for _ in range(6)])\n",
|
|
"\n",
|
|
"\n",
|
|
"def select_keys_with_passcode_values(user_passcode: list[int], keypad: np.ndarray, attrs_per_key: int) -> list[int]:\n",
|
|
" indices = [np.where(keypad == attr)[0][0] for attr in user_passcode]\n",
|
|
" return [int(index // attrs_per_key) for index in indices]\n",
|
|
"\n",
|
|
"\n",
|
|
"def keypad_view(keypad: np.ndarray, attrs_per_key: int):\n",
|
|
" print(\"Keypad View\")\n",
|
|
" interface_keypad = keypad.reshape(-1, attrs_per_key)\n",
|
|
" for idx, key_vals in enumerate(interface_keypad):\n",
|
|
" print(f\"Key {idx}: {key_vals}\")\n"
|
|
],
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-14T14:18:14.434459Z",
|
|
"start_time": "2025-03-14T14:18:14.430679Z"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"execution_count": 24
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"source": [
|
|
"api = NKodeAPI()"
|
|
],
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-14T14:18:14.453086Z",
|
|
"start_time": "2025-03-14T14:18:14.451030Z"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"execution_count": 25
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"# NKode API\n",
|
|
"### Customer NKode Policy and Interface\n",
|
|
"A customer defines their NKode Policy and their interface. Below we've set:\n",
|
|
"- max nkode length = 10\n",
|
|
"- min nkode length = 4\n",
|
|
"- distinct properties = 4\n",
|
|
"- distinct set = 0\n",
|
|
"- byte len = 2\n",
|
|
"\n",
|
|
"This customer also has an interface with 5 keys and 6 properties per key. The number of properties must be greater than the number of keys to be dispersion resistant."
|
|
],
|
|
"metadata": {
|
|
"collapsed": false
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"source": [
|
|
"policy = NKodePolicy(\n",
|
|
" max_nkode_len=10,\n",
|
|
" min_nkode_len=4,\n",
|
|
" distinct_sets=0,\n",
|
|
" distinct_properties=4,\n",
|
|
" byte_len=2,\n",
|
|
")\n",
|
|
"keypad_size = KeypadSize(\n",
|
|
" numb_of_keys = 5,\n",
|
|
" props_per_key = 6 # aka number of sets\n",
|
|
")\n",
|
|
"customer_id = api.create_new_customer(keypad_size, policy)\n",
|
|
"customer = api.customers[customer_id]"
|
|
],
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-14T14:18:14.461793Z",
|
|
"start_time": "2025-03-14T14:18:14.457601Z"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"execution_count": 26
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"### NKode Customer\n",
|
|
"A customer has users and defines the properties and set values for all its users.\n",
|
|
"Since our customer has 5 keys and 6 properties per key, this gives a customer interface of 30 distinct properties and 6 distinct properties sets.\n",
|
|
"Each properties belongs to one of the 6 sets."
|
|
],
|
|
"metadata": {
|
|
"collapsed": false
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": "#### Customer and Properties Values",
|
|
"metadata": {
|
|
"collapsed": false
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"source": [
|
|
"print(f\"Customer Set Key: {customer.cipher.set_key}\")\n",
|
|
"print(f\"Customer properties Key:\")\n",
|
|
"customer_prop_keypad = customer.cipher.prop_key.reshape(-1, keypad_size.props_per_key)\n",
|
|
"for idx, key_vals in enumerate(customer_prop_keypad):\n",
|
|
" print(f\"{key_vals}\")"
|
|
],
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-14T14:18:14.472200Z",
|
|
"start_time": "2025-03-14T14:18:14.469516Z"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Customer Set Key: [57513 39162 37238 40595 30029 8573]\n",
|
|
"Customer properties Key:\n",
|
|
"[14659 8841 6728 32702 39675 63074]\n",
|
|
"[19274 15250 33729 24532 34839 38348]\n",
|
|
"[ 2539 51139 60808 11045 55452 61221]\n",
|
|
"[55550 11904 10001 59259 26026 26740]\n",
|
|
"[59910 49698 45525 62003 49414 40644]\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 27
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": "#### Customer Set To Properties Map",
|
|
"metadata": {
|
|
"collapsed": false
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"source": [
|
|
"set_properties_dict = dict(zip(customer.cipher.set_key, customer_prop_keypad.T))\n",
|
|
"print(f\"Set to Properties Map:\")\n",
|
|
"for set_val, attrs in set_properties_dict.items():\n",
|
|
" print(f\"{set_val}: {attrs}\")"
|
|
],
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-14T14:18:14.486583Z",
|
|
"start_time": "2025-03-14T14:18:14.484301Z"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Set to Properties Map:\n",
|
|
"57513: [14659 19274 2539 55550 59910]\n",
|
|
"39162: [ 8841 15250 51139 11904 49698]\n",
|
|
"37238: [ 6728 33729 60808 10001 45525]\n",
|
|
"40595: [32702 24532 11045 59259 62003]\n",
|
|
"30029: [39675 34839 55452 26026 49414]\n",
|
|
"8573: [63074 38348 61221 26740 40644]\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 28
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"### User Signup\n",
|
|
"To create a new must call this endpoints in order:\n",
|
|
"1. Generate Keypad\n",
|
|
"2. Set User NKode\n",
|
|
"3. Confirm User NKode\n",
|
|
"\n",
|
|
"#### Generate Keypad\n",
|
|
" For the server to determine the users nkode, the user's keypad must be dispersable. To make the keypad dispersable, the server will randomly drop properties sets to the number of properties is equal to the number of keys. In our case, the server drops 1 properties set to give us a 5 X 5 keypad with possible index values ranging from 0-29.\n",
|
|
" - Run the cell below over and over to see it change. Notice that values never move out of their columns just their rows.\n",
|
|
" - each value in the keypad is the index value of a customer properties\n",
|
|
" - the user never learns what their \"real\" properties is. All they do is specify an index in the customer keypad\n"
|
|
]
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-14T14:18:14.510067Z",
|
|
"start_time": "2025-03-14T14:18:14.507204Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"session_id, signup_keypad = api.generate_signup_keypad(customer_id)\n",
|
|
"print(signup_keypad.reshape(-1, keypad_size.numb_of_keys))"
|
|
],
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"[[ 1 7 13 19 25]\n",
|
|
" [ 0 6 12 18 24]\n",
|
|
" [ 5 11 17 23 29]\n",
|
|
" [ 2 8 14 20 26]\n",
|
|
" [ 4 10 16 22 28]]\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 29
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"#### Set nKode\n",
|
|
"The user identifies properties in the keypad they want in their nkode. Each properties in the gui has an index value. Below the user has selected 16, 9, 6, 19. Graphically represent with anything. The only requirement is that the graphical properties must be associated with the same index value everytime the user goes to login. If the user wants to change anything about their keypad(the number of keys, properties or graphical properties), they must also change their nkode."
|
|
]
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-14T14:18:14.535581Z",
|
|
"start_time": "2025-03-14T14:18:14.531909Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"keypad_view(signup_keypad, keypad_size.numb_of_keys)\n",
|
|
"username = random_username()\n",
|
|
"passcode_len = 4\n",
|
|
"user_passcode = signup_keypad[:passcode_len]\n",
|
|
"selected_keys_set = select_keys_with_passcode_values(user_passcode, signup_keypad, keypad_size.numb_of_keys)\n",
|
|
"print(f\"User Passcode: {user_passcode}\")\n",
|
|
"print(f\"Selected Keys\\n{selected_keys_set}\")\n",
|
|
"server_side_attr = [int(customer.cipher.prop_key[idx]) for idx in user_passcode]\n",
|
|
"print(f\"User Passcode Server-side properties: {server_side_attr}\")"
|
|
],
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Keypad View\n",
|
|
"Key 0: [ 1 7 13 19 25]\n",
|
|
"Key 1: [ 0 6 12 18 24]\n",
|
|
"Key 2: [ 5 11 17 23 29]\n",
|
|
"Key 3: [ 2 8 14 20 26]\n",
|
|
"Key 4: [ 4 10 16 22 28]\n",
|
|
"User Passcode: [ 1 7 13 19]\n",
|
|
"Selected Keys\n",
|
|
"[0, 0, 0, 0]\n",
|
|
"User Passcode Server-side properties: [8841, 15250, 51139, 11904]\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 30
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-14T14:18:14.556541Z",
|
|
"start_time": "2025-03-14T14:18:14.553217Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"confirm_keypad = api.set_nkode(username, customer_id, selected_keys_set, session_id)\n",
|
|
"keypad_view(confirm_keypad, keypad_size.numb_of_keys)\n",
|
|
"selected_keys_confirm = select_keys_with_passcode_values(user_passcode, confirm_keypad, keypad_size.numb_of_keys)\n",
|
|
"print(f\"Selected Keys\\n{selected_keys_confirm}\")"
|
|
],
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Keypad View\n",
|
|
"Key 0: [ 0 11 16 20 25]\n",
|
|
"Key 1: [ 2 6 13 22 29]\n",
|
|
"Key 2: [ 4 8 17 19 24]\n",
|
|
"Key 3: [ 1 10 12 23 26]\n",
|
|
"Key 4: [ 5 7 14 18 28]\n",
|
|
"Selected Keys\n",
|
|
"[3, 4, 1, 2]\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 31
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-14T14:18:14.884832Z",
|
|
"start_time": "2025-03-14T14:18:14.575902Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"# the session is deleted after the nkode is confirmed. To rerun this cell, rerun the cells above starting with cell 8 where the username is created\n",
|
|
"success = api.confirm_nkode(username, customer_id, selected_keys_confirm, session_id)\n",
|
|
"print(success)"
|
|
],
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"True\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 32
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"## Enciphering nKode\n",
|
|
"The method UserCipherKeys.encipher_nkode secures a users nKode in the database. This method is called in api.confirm_nkode\n",
|
|
"```\n",
|
|
"class EncipheredNKode(BaseModel):\n",
|
|
" code: str\n",
|
|
" mask: str\n",
|
|
"```\n",
|
|
"\n"
|
|
]
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-14T14:18:14.894865Z",
|
|
"start_time": "2025-03-14T14:18:14.889948Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"from src.user_cipher import UserCipher\n",
|
|
"\n",
|
|
"\n",
|
|
"set_key = np.array([46785, 4782, 4405, 44408, 35377, 55527])\n",
|
|
"set_key = np.bitwise_xor(set_key, customer.cipher.set_key)\n",
|
|
"user_keys = UserCipher(\n",
|
|
" prop_key = np.array([\n",
|
|
" 57200, 8398, 54694, 25997, 30388,\n",
|
|
" 46948, 45549, 30364, 49712, 10447,\n",
|
|
" 9205, 1777, 10731, 30979, 2795,\n",
|
|
" 17068, 56758, 62574, 28641, 11451,\n",
|
|
" 26820, 50373, 48783, 25350, 62177,\n",
|
|
" 60608, 54242, 4637, 3525, 16313\n",
|
|
" ]),\n",
|
|
" pass_key=np.array([16090, 38488, 45111, 32674, 46216, 52013, 48980, 36811, 35296, 17206]),\n",
|
|
" mask_key=np.array([29575, 43518, 44373, 62063, 37651, 31671, 31663, 65514, 36454, 47325]),\n",
|
|
" set_key=np.array(set_key),\n",
|
|
" salt=b'$2b$12$fX.in.GGAjz3QBBwqSWc6e',\n",
|
|
" max_nkode_len=customer.nkode_policy.max_nkode_len, \n",
|
|
")\n",
|
|
"\n",
|
|
"passcode_server_attr = [int(customer.cipher.prop_key[idx]) for idx in user_passcode]\n",
|
|
"passcode_server_set = [int(customer.cipher.get_prop_set_val(attr)) for attr in passcode_server_attr]\n",
|
|
"print(f\"Passcode Set Vals: {passcode_server_set}\")\n",
|
|
"print(f\"Passcode Attr Vals: {passcode_server_attr}\")"
|
|
],
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Passcode Set Vals: [39162, 39162, 39162, 39162]\n",
|
|
"Passcode Attr Vals: [8841, 15250, 51139, 11904]\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 33
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"#### Encipher Mask\n",
|
|
"Recall:\n",
|
|
"1. set_key_i = (set_rand_numb_i ^ set_val_i) \n",
|
|
"2. mask_key_i = mask_rand_numb_i\n",
|
|
"3. padded_passcode_server_set_i = set_val_i\n",
|
|
"4. len(set_key) == len(mask_key) == (padded_passcode_server_set) == max_nkode_len == 10\n",
|
|
"where i is the index\n",
|
|
" \n",
|
|
"- mask_i = mask_key_i ^ padded_passcode_server_set_i ^ set_key_i\n",
|
|
"- mask_i = mask_rand_num_i ^ set_val_i ^ set_rand_numb_i ^ set_val_i\n",
|
|
"- mask_i = mask_rand_num_i ^ set_rand_numb_i # set_val_i is cancelled out"
|
|
]
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-14T14:18:14.917821Z",
|
|
"start_time": "2025-03-14T14:18:14.914851Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"padded_passcode_server_set = user_keys.pad_user_mask(passcode_server_set, customer.cipher.set_key)\n",
|
|
"\n",
|
|
"set_idx = [customer.cipher.get_set_index(set_val) for set_val in padded_passcode_server_set]\n",
|
|
"mask_set_keys = [user_keys.set_key[idx] for idx in set_idx]\n",
|
|
"ciphered_mask = np.bitwise_xor(mask_set_keys, padded_passcode_server_set)\n",
|
|
"ciphered_mask = np.bitwise_xor(ciphered_mask, user_keys.mask_key)\n",
|
|
"mask = user_keys.encode_base64_str(ciphered_mask)"
|
|
],
|
|
"outputs": [],
|
|
"execution_count": 34
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"#### Encipher Passcode\n",
|
|
"UserCipherKeys.encipher_salt_hash_code:\n",
|
|
"\n",
|
|
"- ciphered_customer_attr = alpha_key ^ customer_attr\n",
|
|
"- ciphered_passcode_i = pass_key_i ^ ciphered_customer_attr_i\n",
|
|
"- code = hash(ciphered_passcode, salt)"
|
|
]
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-14T14:18:15.243102Z",
|
|
"start_time": "2025-03-14T14:18:14.937865Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"import bcrypt\n",
|
|
"import hashlib\n",
|
|
"import base64\n",
|
|
"\n",
|
|
"ciphered_customer_attrs = np.bitwise_xor(customer.cipher.prop_key, user_keys.prop_key)\n",
|
|
"passcode_ciphered_attrs = [ciphered_customer_attrs[idx] for idx in user_passcode]\n",
|
|
"pad_len = customer.nkode_policy.max_nkode_len - passcode_len\n",
|
|
"\n",
|
|
"passcode_ciphered_attrs.extend([0 for _ in range(pad_len)])\n",
|
|
"\n",
|
|
"ciphered_code = np.bitwise_xor(passcode_ciphered_attrs, user_keys.pass_key)\n",
|
|
"\n",
|
|
"#passcode_bytes = int_array_to_bytes(ciphered_code)\n",
|
|
"passcode_bytes = ciphered_code.tobytes()\n",
|
|
"passcode_digest = base64.b64encode(hashlib.sha256(passcode_bytes).digest())\n",
|
|
"hashed_data = bcrypt.hashpw(passcode_digest, user_keys.salt)\n",
|
|
"code = hashed_data.decode(\"utf-8\")"
|
|
],
|
|
"outputs": [],
|
|
"execution_count": 35
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-14T14:18:15.249186Z",
|
|
"start_time": "2025-03-14T14:18:15.247147Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"from src.models import EncipheredNKode\n",
|
|
"\n",
|
|
"enciphered_nkode = EncipheredNKode(\n",
|
|
" mask=mask,\n",
|
|
" code=code,\n",
|
|
")"
|
|
],
|
|
"outputs": [],
|
|
"execution_count": 36
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"### User Login\n",
|
|
"1. Get login keypad\n",
|
|
"2. Login\n"
|
|
]
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-14T14:18:15.563030Z",
|
|
"start_time": "2025-03-14T14:18:15.257823Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"login_keypad = api.get_login_keypad(username, customer_id)\n",
|
|
"keypad_view(login_keypad, keypad_size.props_per_key)\n",
|
|
"selected_keys_login = select_keys_with_passcode_values(user_passcode, login_keypad, keypad_size.props_per_key)\n",
|
|
"print(f\"Selected Keys: {selected_keys_login}\")\n",
|
|
"success = api.login(customer_id, username, selected_keys_login)\n",
|
|
"print(success)"
|
|
],
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Keypad View\n",
|
|
"Key 0: [0 1 2 3 4 5]\n",
|
|
"Key 1: [ 6 7 8 9 10 11]\n",
|
|
"Key 2: [12 13 14 15 16 17]\n",
|
|
"Key 3: [18 19 20 21 22 23]\n",
|
|
"Key 4: [24 25 26 27 28 29]\n",
|
|
"Selected Keys: [0, 1, 2, 3]\n",
|
|
"True\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 37
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"## Validate Login Key Entry\n",
|
|
"- decipher user mask and recover nkode set values\n",
|
|
"- get presumed properties from key selection and set values\n",
|
|
"- encipher, salt and hash presumed properties values and compare it to the users hashed code"
|
|
]
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"### Decipher Mask\n",
|
|
"Recall:\n",
|
|
"- set_key_i = (set_key_rand_numb_i ^ set_val_i) \n",
|
|
"- mask_i = mask_key_rand_num_i ^ set_key_rand_numb_i\n",
|
|
"\n",
|
|
"Recover nKode set values: \n",
|
|
"- decode mask from base64 to int\n",
|
|
"- deciphered_mask = mask ^ mask_key\n",
|
|
"- deciphered_mask_i = set_key_rand_numb # mask_key_rand_num_i is cancelled out\n",
|
|
"- set_key_rand_component = set_key ^ set_values\n",
|
|
"- deduce the set value"
|
|
]
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-14T14:18:15.574718Z",
|
|
"start_time": "2025-03-14T14:18:15.571571Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"user = api.customers[customer_id].users[username]\n",
|
|
"decoded_mask = user.cipher.decode_base64_str(user.enciphered_passcode.mask)\n",
|
|
"deciphered_mask = np.bitwise_xor(decoded_mask, user.cipher.mask_key)\n",
|
|
"set_key = np.bitwise_xor(customer.cipher.set_key, user.cipher.set_key)\n",
|
|
"passcode_sets = []\n",
|
|
"for set_cipher in deciphered_mask[:passcode_len]:\n",
|
|
" set_idx = np.where(set_key == set_cipher)[0][0]\n",
|
|
" passcode_sets.append(int(customer.cipher.set_key[set_idx]))\n",
|
|
"print(passcode_sets)"
|
|
],
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"[39162, 39162, 39162, 39162]\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 38
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": "### Get Presumed Properties\n"
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-14T14:18:15.591180Z",
|
|
"start_time": "2025-03-14T14:18:15.587992Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"set_vals_idx = [customer.cipher.get_set_index(set_val) for set_val in passcode_sets]\n",
|
|
"\n",
|
|
"presumed_selected_properties_idx = []\n",
|
|
"for idx in range(passcode_len):\n",
|
|
" key_numb = selected_keys_login[idx]\n",
|
|
" set_idx = set_vals_idx[idx]\n",
|
|
" selected_attr_idx = customer.users[username].user_keypad.get_prop_idx_by_keynumb_setidx(key_numb, set_idx)\n",
|
|
" presumed_selected_properties_idx.append(selected_attr_idx)\n",
|
|
"\n",
|
|
"print(user_passcode.tolist() == presumed_selected_properties_idx)"
|
|
],
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"True\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 39
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": "### Compare Enciphered Passcodes"
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-14T14:18:15.916787Z",
|
|
"start_time": "2025-03-14T14:18:15.610843Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"enciphered_nkode = user.cipher.encipher_salt_hash_code(presumed_selected_properties_idx, customer.cipher)\n",
|
|
"print(enciphered_nkode == user.enciphered_passcode.code)\n"
|
|
],
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"True\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 40
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"## Renew Properties\n",
|
|
"1. Renew Customer Properties\n",
|
|
"2. Renew User Keys\n",
|
|
"3. Refresh User on Login\n",
|
|
"\n"
|
|
]
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-14T14:18:16.539065Z",
|
|
"start_time": "2025-03-14T14:18:15.926843Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"def print_user_enciphered_code():\n",
|
|
" mask = api.customers[customer_id].users[username].enciphered_passcode.mask\n",
|
|
" code = api.customers[customer_id].users[username].enciphered_passcode.code\n",
|
|
" print(f\"mask: {mask}, code: {code}\")\n",
|
|
"\n",
|
|
"print_user_enciphered_code() \n",
|
|
"api.renew_keys(customer_id)\n",
|
|
"print_user_enciphered_code()\n",
|
|
"\n",
|
|
"login_keypad = api.get_login_keypad(username, customer_id)\n",
|
|
"selected_keys_login = select_keys_with_passcode_values(user_passcode, login_keypad, keypad_size.props_per_key)\n",
|
|
"success = api.login(customer_id, username, selected_keys_login)\n",
|
|
"print(success)\n",
|
|
"print_user_enciphered_code()"
|
|
],
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"mask: 4NCIa/fFtx0udGaF1ub+O/6oU04=, code: $2b$12$XuGO.allDcb91peVIjwsq./Ba/TZI3wxAc0acgWkApzkzGWfwPQCC\n",
|
|
"mask: 4NCIa/fFtx0udGaF1ub+O/6oU04=, code: $2b$12$XuGO.allDcb91peVIjwsq./Ba/TZI3wxAc0acgWkApzkzGWfwPQCC\n",
|
|
"True\n",
|
|
"mask: ceaWZR+hNRpEkj3fq1cfPu1Zyok=, code: $2b$12$q7lqdTj6qBMDDGEog9Pq3.M2Wso0TI8cx4/PhOK/fE1mhsws2FGe.\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 41
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"#### Renew Customer Keys\n",
|
|
"- Get old properties and sets\n",
|
|
"- Replace properties and sets"
|
|
]
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-14T14:18:16.551437Z",
|
|
"start_time": "2025-03-14T14:18:16.547371Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"old_props = customer.cipher.prop_key.copy()\n",
|
|
"old_sets = customer.cipher.set_key.copy()\n",
|
|
"customer.cipher.renew()\n",
|
|
"new_props = customer.cipher.prop_key\n",
|
|
"new_sets = customer.cipher.set_key"
|
|
],
|
|
"outputs": [],
|
|
"execution_count": 42
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"### Renew User\n",
|
|
"\n"
|
|
]
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-14T14:18:16.568881Z",
|
|
"start_time": "2025-03-14T14:18:16.566223Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"props_xor = np.bitwise_xor(new_props, old_props)\n",
|
|
"sets_xor = np.bitwise_xor(new_sets, old_sets)\n",
|
|
"for user in customer.users.values():\n",
|
|
" user.renew = True\n",
|
|
" user.cipher.set_key = np.bitwise_xor(user.cipher.set_key, sets_xor)\n",
|
|
" user.cipher.prop_key = np.bitwise_xor(user.cipher.prop_key, props_xor)"
|
|
],
|
|
"outputs": [],
|
|
"execution_count": 43
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": "### Refresh User Keys"
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-14T14:18:16.884432Z",
|
|
"start_time": "2025-03-14T14:18:16.572989Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"user.cipher = UserCipher.create(\n",
|
|
" customer.cipher.keypad_size,\n",
|
|
" customer.cipher.set_key,\n",
|
|
" user.cipher.max_nkode_len\n",
|
|
")\n",
|
|
"user.enciphered_passcode = user.cipher.encipher_nkode(presumed_selected_properties_idx, customer.cipher)\n",
|
|
"user.renew = False"
|
|
],
|
|
"outputs": [],
|
|
"execution_count": 44
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "Python 3",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 2
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython2",
|
|
"version": "2.7.6"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 0
|
|
}
|