Files
pynkode/notebooks/nkode_tutorial.ipynb
2025-03-17 04:31:01 -05:00

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\n",
"import bcrypt"
],
"metadata": {
"collapsed": false,
"ExecuteTime": {
"end_time": "2025-03-16T12:51:50.430038Z",
"start_time": "2025-03-16T12:51:50.426267Z"
}
},
"outputs": [],
"execution_count": 17
},
{
"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(\"Keypad 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-16T12:51:50.441672Z",
"start_time": "2025-03-16T12:51:50.437979Z"
}
},
"outputs": [],
"execution_count": 18
},
{
"cell_type": "code",
"source": [
"api = NKodeAPI()"
],
"metadata": {
"collapsed": false,
"ExecuteTime": {
"end_time": "2025-03-16T12:51:50.451921Z",
"start_time": "2025-03-16T12:51:50.449896Z"
}
},
"outputs": [],
"execution_count": 19
},
{
"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-16T12:51:50.462932Z",
"start_time": "2025-03-16T12:51:50.458899Z"
}
},
"outputs": [],
"execution_count": 20
},
{
"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-16T12:51:50.471838Z",
"start_time": "2025-03-16T12:51:50.469241Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Customer Set Key: [29252 55146 27501 36339 61988 56812]\n",
"Customer Properties Key:\n",
"[58958 438 23479 56544 19227 62335]\n",
"[19972 45333 49189 28952 25210 7101]\n",
"[27924 36712 27932 6192 11310 25890]\n",
"[41961 42300 62264 30572 21755 25167]\n",
"[56659 59117 55559 18611 58570 62570]\n"
]
}
],
"execution_count": 21
},
{
"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-16T12:51:50.482832Z",
"start_time": "2025-03-16T12:51:50.480624Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Set to Properties Map:\n",
"29252: [58958 19972 27924 41961 56659]\n",
"55146: [ 438 45333 36712 42300 59117]\n",
"27501: [23479 49189 27932 62264 55559]\n",
"36339: [56544 28952 6192 30572 18611]\n",
"61988: [19227 25210 11310 21755 58570]\n",
"56812: [62335 7101 25890 25167 62570]\n"
]
}
],
"execution_count": 22
},
{
"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-16T12:51:50.496968Z",
"start_time": "2025-03-16T12:51:50.494830Z"
}
},
"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": [
"[[10 4 22 16 28]\n",
" [11 5 23 17 29]\n",
" [ 9 3 21 15 27]\n",
" [ 8 2 20 14 26]\n",
" [ 7 1 19 13 25]]\n"
]
}
],
"execution_count": 23
},
{
"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-16T12:51:50.521411Z",
"start_time": "2025-03-16T12:51:50.518203Z"
}
},
"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": [
"Keypad View\n",
"Key 0: [10 4 22 16 28]\n",
"Key 1: [11 5 23 17 29]\n",
"Key 2: [ 9 3 21 15 27]\n",
"Key 3: [ 8 2 20 14 26]\n",
"Key 4: [ 7 1 19 13 25]\n",
"User Passcode: [10 4 22 16]\n",
"Selected Keys\n",
"[0, 0, 0, 0]\n",
"User Passcode Server-side properties: [25210, 19227, 21755, 11310]\n"
]
}
],
"execution_count": 24
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-03-16T12:51:50.539870Z",
"start_time": "2025-03-16T12:51:50.536979Z"
}
},
"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: [ 7 2 22 15 29]\n",
"Key 1: [ 9 4 23 14 25]\n",
"Key 2: [ 8 5 19 16 27]\n",
"Key 3: [10 1 21 17 26]\n",
"Key 4: [11 3 20 13 28]\n",
"Selected Keys\n",
"[3, 1, 0, 2]\n"
]
}
],
"execution_count": 25
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-03-16T12:51:50.790192Z",
"start_time": "2025-03-16T12:51:50.552031Z"
}
},
"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": 26
},
{
"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-16T12:51:50.801004Z",
"start_time": "2025-03-16T12:51:50.797001Z"
}
},
"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: [61988, 61988, 61988, 61988]\n",
"Passcode Prop Vals: [25210 19227 21755 11310]\n"
]
}
],
"execution_count": 27
},
{
"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-16T12:51:50.811181Z",
"start_time": "2025-03-16T12:51:50.808721Z"
}
},
"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": 28
},
{
"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-16T12:51:51.058527Z",
"start_time": "2025-03-16T12:51:50.823135Z"
}
},
"cell_type": "code",
"source": [
"import hashlib\n",
"import base64\n",
"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": 29
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-03-16T12:51:51.063978Z",
"start_time": "2025-03-16T12:51:51.061965Z"
}
},
"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": 30
},
{
"metadata": {},
"cell_type": "markdown",
"source": [
"### User Login\n",
"1. Get login keypad\n",
"2. Login\n"
]
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-03-16T12:51:51.305419Z",
"start_time": "2025-03-16T12:51:51.071190Z"
}
},
"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: [ 6 7 8 9 10 11]\n",
"Key 1: [0 1 2 3 4 5]\n",
"Key 2: [18 19 20 21 22 23]\n",
"Key 3: [12 13 14 15 16 17]\n",
"Key 4: [24 25 26 27 28 29]\n",
"Selected Keys: [0, 1, 2, 3]\n",
"True\n"
]
}
],
"execution_count": 31
},
{
"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-16T12:51:51.315072Z",
"start_time": "2025-03-16T12:51:51.312249Z"
}
},
"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": [
"[61988, 61988, 61988, 61988]\n"
]
}
],
"execution_count": 32
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### Get Presumed Properties\n"
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-03-16T12:51:51.324331Z",
"start_time": "2025-03-16T12:51:51.321676Z"
}
},
"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_prop_idx = customer.users[username].user_keypad.get_prop_idx_by_keynumb_setidx(key_numb, set_idx)\n",
" presumed_selected_properties_idx.append(selected_prop_idx)\n",
"\n",
"print(user_passcode.tolist() == presumed_selected_properties_idx)"
],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"True\n"
]
}
],
"execution_count": 33
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### Compare Enciphered Passcodes"
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-03-16T12:51:51.571291Z",
"start_time": "2025-03-16T12:51:51.338129Z"
}
},
"cell_type": "code",
"source": [
"enciphered_nkode = user.cipher.compare_nkode(presumed_selected_properties_idx, customer.cipher, user.enciphered_passcode.code)\n",
"print(enciphered_nkode)\n"
],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"True\n"
]
}
],
"execution_count": 34
},
{
"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-16T12:51:52.048827Z",
"start_time": "2025-03-16T12:51:51.579003Z"
}
},
"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: 8T1ZD3B2c6v+ofoNRIzBbqxVYFw=, code: $2b$12$lAmbDegOx03xLmrB//ZCh.1dyrjtpEmAdv1TWNUO/XjjPofQItzVq\n",
"mask: 8T1ZD3B2c6v+ofoNRIzBbqxVYFw=, code: $2b$12$lAmbDegOx03xLmrB//ZCh.1dyrjtpEmAdv1TWNUO/XjjPofQItzVq\n",
"True\n",
"mask: rY763sxEo+aU8G2h7Avf9btV0h8=, code: $2b$12$ZB.x5hSFVjDg4niUAL7TsOtwkTG2uXedMsnFqXNjm0Y0SDf5fgOui\n"
]
}
],
"execution_count": 35
},
{
"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-16T12:51:52.059119Z",
"start_time": "2025-03-16T12:51:52.055816Z"
}
},
"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": 36
},
{
"metadata": {},
"cell_type": "markdown",
"source": [
"### Renew User\n",
"\n"
]
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-03-16T12:51:52.068302Z",
"start_time": "2025-03-16T12:51:52.065921Z"
}
},
"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": 37
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### Refresh User Keys"
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-03-16T12:51:52.311112Z",
"start_time": "2025-03-16T12:51:52.074783Z"
}
},
"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": 38
}
],
"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
}