806 lines
24 KiB
Plaintext
806 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\n",
|
|
"import bcrypt"
|
|
],
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-17T14:56:54.677924Z",
|
|
"start_time": "2025-03-17T14:56:54.674055Z"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"execution_count": 52
|
|
},
|
|
{
|
|
"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, props_per_key: int) -> list[int]:\n",
|
|
" indices = [np.where(keypad == prop)[0][0] for prop in user_passcode]\n",
|
|
" return [int(index // props_per_key) for index in indices]\n",
|
|
"\n",
|
|
"\n",
|
|
"def keypad_view(keypad: np.ndarray, props_per_key: int):\n",
|
|
" print(\"\\nKeypad View\")\n",
|
|
" interface_keypad = keypad.reshape(-1, props_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-17T14:56:54.687467Z",
|
|
"start_time": "2025-03-17T14:56:54.683811Z"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"execution_count": 53
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"source": [
|
|
"api = NKodeAPI()"
|
|
],
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-17T14:56:54.698258Z",
|
|
"start_time": "2025-03-17T14:56:54.696478Z"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"execution_count": 54
|
|
},
|
|
{
|
|
"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-17T14:56:54.710370Z",
|
|
"start_time": "2025-03-17T14:56:54.706283Z"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"execution_count": 55
|
|
},
|
|
{
|
|
"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-17T14:56:54.735642Z",
|
|
"start_time": "2025-03-17T14:56:54.732921Z"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Customer Set Key: [15749 12291 52872 49860 5208 28289]\n",
|
|
"Customer Properties Key:\n",
|
|
"[42849 39396 49203 20824 30786 27252]\n",
|
|
"[16470 25626 64566 34252 23582 48009]\n",
|
|
"[20454 51880 19394 58106 12995 59391]\n",
|
|
"[43703 4483 7702 5423 24081 57678]\n",
|
|
"[43822 27495 59095 24249 60164 21395]\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 56
|
|
},
|
|
{
|
|
"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, props in set_properties_dict.items():\n",
|
|
" print(f\"{set_val}: {props}\")"
|
|
],
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-17T14:56:54.781223Z",
|
|
"start_time": "2025-03-17T14:56:54.778381Z"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Set to Properties Map:\n",
|
|
"15749: [42849 16470 20454 43703 43822]\n",
|
|
"12291: [39396 25626 51880 4483 27495]\n",
|
|
"52872: [49203 64566 19394 7702 59095]\n",
|
|
"49860: [20824 34252 58106 5423 24249]\n",
|
|
"5208: [30786 23582 12995 24081 60164]\n",
|
|
"28289: [27252 48009 59391 57678 21395]\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 57
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"### User Signup\n",
|
|
"To create a new must call this endpoints in order:\n",
|
|
"1. Generate a randomly shuffled 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.\n",
|
|
" To make the keypad dispersable, the server will randomly drop properties sets to the number of properties is equal to the number of keys.\n",
|
|
" 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-17T14:56:54.814781Z",
|
|
"start_time": "2025-03-17T14:56:54.812317Z"
|
|
}
|
|
},
|
|
"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": [
|
|
"[[24 7 2 3 29]\n",
|
|
" [12 13 26 9 11]\n",
|
|
" [ 6 1 8 15 23]\n",
|
|
" [ 0 25 20 21 5]\n",
|
|
" [18 19 14 27 17]]\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 58
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"#### Set nKode\n",
|
|
"The user identifies properties in the keypad they want in their nkode.\n",
|
|
"Each properties in the gui has an index value.\n",
|
|
"Below the user has selected 16, 9, 6, 19.\n",
|
|
"Graphically represent with anything.\n",
|
|
"The only requirement is that the graphical properties must be associated with the same index value everytime the user goes to login.\n",
|
|
"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-17T14:56:54.845027Z",
|
|
"start_time": "2025-03-17T14:56:54.840926Z"
|
|
}
|
|
},
|
|
"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_prop = [int(customer.cipher.prop_key[idx]) for idx in user_passcode]\n",
|
|
"print(f\"User Passcode Server-side properties: {server_side_prop}\")"
|
|
],
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"\n",
|
|
"Keypad View\n",
|
|
"Key 0: [24 7 2 3 29]\n",
|
|
"Key 1: [12 13 26 9 11]\n",
|
|
"Key 2: [ 6 1 8 15 23]\n",
|
|
"Key 3: [ 0 25 20 21 5]\n",
|
|
"Key 4: [18 19 14 27 17]\n",
|
|
"User Passcode: [24 7 2 3]\n",
|
|
"Selected Keys\n",
|
|
"[0, 0, 0, 0]\n",
|
|
"User Passcode Server-side properties: [43822, 25626, 49203, 20824]\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 59
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-17T14:56:54.869735Z",
|
|
"start_time": "2025-03-17T14:56:54.866365Z"
|
|
}
|
|
},
|
|
"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": [
|
|
"\n",
|
|
"Keypad View\n",
|
|
"Key 0: [24 13 20 15 17]\n",
|
|
"Key 1: [ 6 7 14 21 11]\n",
|
|
"Key 2: [ 0 1 26 27 29]\n",
|
|
"Key 3: [18 25 2 9 23]\n",
|
|
"Key 4: [12 19 8 3 5]\n",
|
|
"Selected Keys\n",
|
|
"[0, 1, 3, 4]\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 60
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-17T14:56:55.202903Z",
|
|
"start_time": "2025-03-17T14:56:54.894565Z"
|
|
}
|
|
},
|
|
"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",
|
|
"assert success"
|
|
],
|
|
"outputs": [],
|
|
"execution_count": 61
|
|
},
|
|
{
|
|
"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-17T14:56:55.227304Z",
|
|
"start_time": "2025-03-17T14:56:55.222844Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"from src.user_cipher import UserCipher\n",
|
|
"\n",
|
|
"user_set_key = np.array([46785, 4782, 4405, 44408, 35377, 55527])\n",
|
|
"combined_set_key = user_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",
|
|
" combined_set_key=np.array(combined_set_key),\n",
|
|
" max_nkode_len=customer.nkode_policy.max_nkode_len,\n",
|
|
")\n",
|
|
"\n",
|
|
"ordered_customer_prop_key = customer.cipher.prop_key[user_passcode] # [int(customer.cipher.prop_key[idx]) for idx in user_passcode]\n",
|
|
"ordered_customer_set_key = [int(customer.cipher.get_prop_set_val(prop)) for prop in ordered_customer_prop_key]\n",
|
|
"print(f\"Passcode Set Vals: {ordered_customer_set_key}\")\n",
|
|
"print(f\"Passcode Prop Vals: {ordered_customer_prop_key}\")"
|
|
],
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Passcode Set Vals: [15749, 12291, 52872, 49860]\n",
|
|
"Passcode Prop Vals: [43822 25626 49203 20824]\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 62
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"#### Encipher Mask\n",
|
|
"Recall:\n",
|
|
"1. combined_set_key = (user_set_key ^ customer_set_key)\n",
|
|
"2. padded_ordered_customer_set = customer_set_key # ordered by user passcode and padded with extra set key values to be equal to max_nkode_len\n",
|
|
"3. len(set_key) == len(mask_key) == len(padded_ordered_customer_set) == max_nkode_len == 10\n",
|
|
"where i is the index\n",
|
|
" \n",
|
|
"- mask = mask_key ^ padded_ordered_customer_set ^ ordered_combined_set_key\n",
|
|
"- mask = mask_key ^ (customer_set_key) ^ set_rand_numb ^ set_val\n",
|
|
"- mask = mask_rand_num ^ set_rand_numb # set_val is cancelled out"
|
|
]
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-17T14:56:55.260751Z",
|
|
"start_time": "2025-03-17T14:56:55.258152Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"padded_ordered_customer_set = user_keys.pad_user_mask(ordered_customer_set_key, customer.cipher.set_key)\n",
|
|
"set_idx = [customer.cipher.get_set_index(set_val) for set_val in padded_ordered_customer_set]\n",
|
|
"ordered_set_key = user_keys.combined_set_key[set_idx]\n",
|
|
"mask = ordered_set_key ^ padded_ordered_customer_set ^ user_keys.mask_key\n",
|
|
"encoded_mask = user_keys.encode_base64_str(mask)"
|
|
],
|
|
"outputs": [],
|
|
"execution_count": 63
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"#### Encipher Passcode\n",
|
|
"UserCipherKeys.encipher_salt_hash_code:\n",
|
|
"\n",
|
|
"- ciphered_customer_prop = alpha_key ^ customer_prop\n",
|
|
"- ciphered_passcode_i = pass_key_i ^ ciphered_customer_prop_i\n",
|
|
"- code = hash(ciphered_passcode, salt)"
|
|
]
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-17T14:56:55.590495Z",
|
|
"start_time": "2025-03-17T14:56:55.285097Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"ciphered_customer_props = np.bitwise_xor(customer.cipher.prop_key, user_keys.prop_key)\n",
|
|
"passcode_ciphered_props = [ciphered_customer_props[idx] for idx in user_passcode]\n",
|
|
"pad_len = customer.nkode_policy.max_nkode_len - passcode_len\n",
|
|
"\n",
|
|
"passcode_ciphered_props.extend([0 for _ in range(pad_len)])\n",
|
|
"\n",
|
|
"ciphered_code = np.bitwise_xor(passcode_ciphered_props, user_keys.pass_key)\n",
|
|
"\n",
|
|
"passcode_bytes = ciphered_code.tobytes()\n",
|
|
"passcode_digest = user_keys.prehash_passcode(user_passcode, customer.cipher)# base64.b64encode(hashlib.sha256(passcode_bytes).digest())\n",
|
|
"hashed_data = bcrypt.hashpw(passcode_digest, bcrypt.gensalt(rounds=12))\n",
|
|
"code = hashed_data.decode(\"utf-8\")"
|
|
],
|
|
"outputs": [],
|
|
"execution_count": 64
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-17T14:56:55.595860Z",
|
|
"start_time": "2025-03-17T14:56:55.593975Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"from src.models import EncipheredNKode\n",
|
|
"\n",
|
|
"enciphered_nkode = EncipheredNKode(\n",
|
|
" mask=encoded_mask,\n",
|
|
" code=code,\n",
|
|
")"
|
|
],
|
|
"outputs": [],
|
|
"execution_count": 65
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"### User Login\n",
|
|
"1. Get login keypad\n",
|
|
"2. Login\n"
|
|
]
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-17T14:56:55.910640Z",
|
|
"start_time": "2025-03-17T14:56:55.605472Z"
|
|
}
|
|
},
|
|
"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\"User Passcode: {user_passcode}\\n\")\n",
|
|
"print(f\"Selected Keys:\\n {selected_keys_login}\\n\")\n",
|
|
"success = api.login(customer_id, username, selected_keys_login)\n",
|
|
"assert success"
|
|
],
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"\n",
|
|
"Keypad View\n",
|
|
"Key 0: [24 7 2 3 28 29]\n",
|
|
"Key 1: [12 13 26 9 16 11]\n",
|
|
"Key 2: [ 6 1 8 15 10 23]\n",
|
|
"Key 3: [ 0 25 20 21 22 5]\n",
|
|
"Key 4: [18 19 14 27 4 17]\n",
|
|
"User Passcode: [24 7 2 3]\n",
|
|
"\n",
|
|
"Selected Keys:\n",
|
|
" [0, 0, 0, 0]\n",
|
|
"\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 66
|
|
},
|
|
{
|
|
"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 = (set_key_rand_numb ^ set_val)\n",
|
|
"- mask = mask_key_rand_num ^ set_key_rand_numb\n",
|
|
"\n",
|
|
"Recover nKode set values: \n",
|
|
"- decode mask from base64 to int\n",
|
|
"- deciphered_mask = mask ^ mask_key\n",
|
|
"- deciphered_mask = set_key_rand_numb # mask_key_rand_num is cancelled out\n",
|
|
"- set_key_rand_component = set_key ^ set_values\n",
|
|
"- deduce the set value"
|
|
]
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-17T14:56:55.922451Z",
|
|
"start_time": "2025-03-17T14:56:55.919172Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"user = api.customers[customer_id].users[username]\n",
|
|
"mask = user.cipher.decode_base64_str(user.enciphered_passcode.mask)\n",
|
|
"deciphered_mask = mask ^ user.cipher.mask_key\n",
|
|
"set_key = customer.cipher.set_key ^ user.cipher.combined_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": [
|
|
"[15749, 12291, 52872, 49860]\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 67
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": "### Get Presumed Properties\n"
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-17T14:56:55.943804Z",
|
|
"start_time": "2025-03-17T14:56:55.940721Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"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",
|
|
"set_vals_idx = [customer.cipher.get_set_index(set_val) for set_val in passcode_sets]\n",
|
|
"presumed_selected_properties_idx = customer.users[username].user_keypad.get_prop_idxs_by_keynumb_setidx(selected_keys_login, set_vals_idx)\n",
|
|
"assert user_passcode.tolist() == presumed_selected_properties_idx"
|
|
],
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"[24, 7, 2, 3]\n",
|
|
"[24, 7, 2, 3]\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 68
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": "### Compare Enciphered Passcodes"
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-17T14:56:56.297835Z",
|
|
"start_time": "2025-03-17T14:56:55.992586Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"enciphered_nkode = user.cipher.compare_nkode(presumed_selected_properties_idx, customer.cipher, user.enciphered_passcode.code)\n",
|
|
"assert enciphered_nkode\n"
|
|
],
|
|
"outputs": [],
|
|
"execution_count": 69
|
|
},
|
|
{
|
|
"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-17T14:56:56.923156Z",
|
|
"start_time": "2025-03-17T14:56:56.306667Z"
|
|
}
|
|
},
|
|
"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",
|
|
"assert success\n",
|
|
"print_user_enciphered_code()"
|
|
],
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"mask: h7xMhd4kK3faZ6C1Ofi+oVjSI4c=, code: $2b$12$/wwEjbTk90oCnD2Ny6KTWeNJ6YPEyc9yJgY00FGddkQ8cE4LNkSvK\n",
|
|
"mask: h7xMhd4kK3faZ6C1Ofi+oVjSI4c=, code: $2b$12$/wwEjbTk90oCnD2Ny6KTWeNJ6YPEyc9yJgY00FGddkQ8cE4LNkSvK\n",
|
|
"mask: nzxGInaKD4KfAP9Djc4tz6ROuko=, code: $2b$12$PZ6j.Ccq8/LEWpht4Bnw1.JLXS0dMrgpzBLsnPA33ND7BjsT3CqxW\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 70
|
|
},
|
|
{
|
|
"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-17T14:56:56.935444Z",
|
|
"start_time": "2025-03-17T14:56:56.931244Z"
|
|
}
|
|
},
|
|
"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": 71
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"### Renew User\n",
|
|
"\n"
|
|
]
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-17T14:56:56.954373Z",
|
|
"start_time": "2025-03-17T14:56:56.952101Z"
|
|
}
|
|
},
|
|
"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.combined_set_key = np.bitwise_xor(user.cipher.combined_set_key, sets_xor)\n",
|
|
" user.cipher.prop_key = np.bitwise_xor(user.cipher.prop_key, props_xor)"
|
|
],
|
|
"outputs": [],
|
|
"execution_count": 72
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": "### Refresh User Keys"
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2025-03-17T14:56:57.298001Z",
|
|
"start_time": "2025-03-17T14:56:56.988801Z"
|
|
}
|
|
},
|
|
"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": 73
|
|
}
|
|
],
|
|
"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
|
|
}
|