Files
pynkode/notebooks/nkode_tutorial.ipynb
2025-03-17 09:58:28 -05:00

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
}