refactor set_key -> position_key

This commit is contained in:
2025-03-20 04:01:15 -05:00
parent 7b92a6b40b
commit 65f3559ef0
8 changed files with 241 additions and 247 deletions

View File

@@ -53,7 +53,7 @@ if __name__ == "__main__":
policy = NKodePolicy( policy = NKodePolicy(
max_nkode_len=10, max_nkode_len=10,
min_nkode_len=4, min_nkode_len=4,
distinct_sets=0, distinct_positions=0,
distinct_properties=4, distinct_properties=4,
byte_len=2, byte_len=2,
) )
@@ -92,14 +92,14 @@ if __name__ == "__main__":
passcode_server_prop = [customer.cipher.property_key[idx] for idx in user_passcode] passcode_server_prop = [customer.cipher.property_key[idx] for idx in user_passcode]
passcode_server_set = customer.cipher.get_props_position_vals(user_passcode) passcode_server_set = customer.cipher.get_props_position_vals(user_passcode)
user_keys = customer.users[username].cipher user_keys = customer.users[username].cipher
# TODO: pad_user_mask is deprecated
padded_passcode_server_set = user_keys.pad_user_mask(np.array(passcode_server_set), customer.cipher.position_key) padded_passcode_server_set = user_keys.pad_user_mask(np.array(passcode_server_set), customer.cipher.position_key)
set_idx = [customer.cipher.get_position_index(set_val) for set_val in padded_passcode_server_set] set_idx = [customer.cipher.get_position_index(set_val) for set_val in padded_passcode_server_set]
mask_set_keys = [user_keys.combined_set_key[idx] for idx in set_idx] mask_set_keys = [user_keys.combined_position_key[idx] for idx in set_idx]
ciphered_mask = mask_set_keys ^ padded_passcode_server_set ^ user_keys.mask_key ciphered_mask = mask_set_keys ^ padded_passcode_server_set ^ user_keys.mask_key
mask = user_keys.encode_base64_str(ciphered_mask) mask = user_keys.encode_base64_str(ciphered_mask)
ciphered_customer_props = customer.cipher.property_key ^ user_keys.prop_key ciphered_customer_props = customer.cipher.property_key ^ user_keys.property_key
passcode_ciphered_props = [ciphered_customer_props[idx] for idx in user_passcode] passcode_ciphered_props = [ciphered_customer_props[idx] for idx in user_passcode]
pad_len = customer.nkode_policy.max_nkode_len - passcode_len pad_len = customer.nkode_policy.max_nkode_len - passcode_len
passcode_ciphered_props.extend([0 for _ in range(pad_len)]) passcode_ciphered_props.extend([0 for _ in range(pad_len)])
@@ -133,7 +133,7 @@ if __name__ == "__main__":
user_mask = user.enciphered_passcode.mask user_mask = user.enciphered_passcode.mask
decoded_mask = user_keys.decode_base64_str(user_mask) decoded_mask = user_keys.decode_base64_str(user_mask)
deciphered_mask = np.bitwise_xor(decoded_mask, user_keys.mask_key) deciphered_mask = np.bitwise_xor(decoded_mask, user_keys.mask_key)
set_key_rand_component = np.bitwise_xor(set_vals, user_keys.combined_set_key) set_key_rand_component = np.bitwise_xor(set_vals, user_keys.combined_position_key)
login_passcode_sets = [] login_passcode_sets = []
for set_cipher in deciphered_mask[:passcode_len]: for set_cipher in deciphered_mask[:passcode_len]:
set_idx = np.where(set_key_rand_component == set_cipher)[0][0] set_idx = np.where(set_key_rand_component == set_cipher)[0][0]
@@ -162,8 +162,8 @@ if __name__ == "__main__":
sets_xor = np.bitwise_xor(new_sets, old_sets) sets_xor = np.bitwise_xor(new_sets, old_sets)
for user in customer.users.values(): for user in customer.users.values():
user.renew = True user.renew = True
user.cipher.combined_set_key = np.bitwise_xor(user.cipher.combined_set_key, sets_xor) user.cipher.combined_position_key = np.bitwise_xor(user.cipher.combined_position_key, sets_xor)
user.cipher.prop_key = np.bitwise_xor(user.cipher.prop_key, props_xor) user.cipher.property_key = np.bitwise_xor(user.cipher.property_key, props_xor)
""" """
REFRESH USER KEYS REFRESH USER KEYS
@@ -184,7 +184,7 @@ if __name__ == "__main__":
'set_property_dict': set_property_dict, 'set_property_dict': set_property_dict,
'set_signup_keypad': signup_keypad, 'set_signup_keypad': signup_keypad,
'username': 'test_user', 'username': 'test_user',
'user_passcode_indices': user_passcode, 'passcode_property_indices': user_passcode,
'selected_keys_set': selected_keys_set, 'selected_keys_set': selected_keys_set,
'server_side_prop': server_side_prop, 'server_side_prop': server_side_prop,
'confirm_keypad': confirm_keypad, 'confirm_keypad': confirm_keypad,

View File

@@ -30,12 +30,12 @@
"metadata": { "metadata": {
"collapsed": false, "collapsed": false,
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-19T14:18:48.405476Z", "end_time": "2025-03-20T08:32:08.092320Z",
"start_time": "2025-03-19T14:18:48.400091Z" "start_time": "2025-03-20T08:32:08.087658Z"
} }
}, },
"outputs": [], "outputs": [],
"execution_count": 195 "execution_count": 27
}, },
{ {
"cell_type": "code", "cell_type": "code",
@@ -53,12 +53,12 @@
"metadata": { "metadata": {
"collapsed": false, "collapsed": false,
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-19T14:18:48.416324Z", "end_time": "2025-03-20T08:32:08.113043Z",
"start_time": "2025-03-19T14:18:48.413345Z" "start_time": "2025-03-20T08:32:08.110624Z"
} }
}, },
"outputs": [], "outputs": [],
"execution_count": 196 "execution_count": 28
}, },
{ {
"metadata": {}, "metadata": {},
@@ -77,8 +77,8 @@
"Each customer has unique cipher keys.\n", "Each customer has unique cipher keys.\n",
"These keys are used to encipher and decipher user nKode.\n", "These keys are used to encipher and decipher user nKode.\n",
"There are two types of Customer Cipher Keys:\n", "There are two types of Customer Cipher Keys:\n",
"1. property key: Combined with the user property key to get the server-side representation of a users icons. Each property belongs to a set.\n", "1. property key: Combined with the user property key to get the server-side representation of a users icons.\n",
"2. set key: Combined with the user set Key to the the server-side representation the position in each key.\n" "2. position key: Combined with the user position key to the server-side representation the position in each key.\n"
], ],
"metadata": { "metadata": {
"collapsed": false "collapsed": false
@@ -90,7 +90,7 @@
"policy = NKodePolicy(\n", "policy = NKodePolicy(\n",
" max_nkode_len=10,\n", " max_nkode_len=10,\n",
" min_nkode_len=4,\n", " min_nkode_len=4,\n",
" distinct_sets=0,\n", " distinct_positions=0,\n",
" distinct_properties=4,\n", " distinct_properties=4,\n",
")\n", ")\n",
"keypad_size = KeypadSize(\n", "keypad_size = KeypadSize(\n",
@@ -99,21 +99,21 @@
")\n", ")\n",
"customer_id = api.create_new_customer(keypad_size, policy)\n", "customer_id = api.create_new_customer(keypad_size, policy)\n",
"customer = api.customers[customer_id]\n", "customer = api.customers[customer_id]\n",
"print(f\"Customer Set Key: {customer.cipher.position_key}\")\n", "print(f\"Customer Position Key: {customer.cipher.position_key}\")\n",
"print(f\"Customer Properties Key:\")\n", "print(f\"Customer Properties Key:\")\n",
"customer_prop_keypad = customer.cipher.property_key.reshape(-1, keypad_size.props_per_key)\n", "customer_prop_keypad = customer.cipher.property_key.reshape(-1, keypad_size.props_per_key)\n",
"for idx, key_vals in enumerate(customer_prop_keypad):\n", "for idx, key_vals in enumerate(customer_prop_keypad):\n",
" print(f\"{key_vals}\")\n", " print(f\"{key_vals}\")\n",
"set_properties_dict = dict(zip(customer.cipher.position_key, customer_prop_keypad.T))\n", "position_properties_dict = dict(zip(customer.cipher.position_key, customer_prop_keypad.T))\n",
"print(f\"Set to Properties Map:\")\n", "print(f\"Position to Properties Map:\")\n",
"for set_val, props in set_properties_dict.items():\n", "for pos_val, props in position_properties_dict.items():\n",
" print(f\"{set_val}: {props}\")" " print(f\"{pos_val}: {props}\")"
], ],
"metadata": { "metadata": {
"collapsed": false, "collapsed": false,
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-19T14:18:48.432441Z", "end_time": "2025-03-20T08:32:08.198233Z",
"start_time": "2025-03-19T14:18:48.426289Z" "start_time": "2025-03-20T08:32:08.193182Z"
} }
}, },
"outputs": [ "outputs": [
@@ -121,56 +121,56 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Customer Set Key: [52236 1143 22391 5610 24876 51604]\n", "Customer Position Key: [21284 3999 4057 48308 14680 46323]\n",
"Customer Properties Key:\n", "Customer Properties Key:\n",
"[48274 26421 59355 34554 61533 13623]\n", "[45633 21215 48438 45863 52540 14191]\n",
"[22492 47901 17487 10515 61939 8923]\n", "[11907 4042 56372 63103 45179 58318]\n",
"[32708 61921 973 1449 52341 29868]\n", "[28909 48497 31171 15125 2886 9246]\n",
"[10212 24136 41690 31747 29169 19891]\n", "[15651 10936 5595 16546 8096 13333]\n",
"[18093 29532 18702 45116 15485 53514]\n", "[41923 43364 15227 43001 11056 62605]\n",
"Set to Properties Map:\n", "Position to Properties Map:\n",
"52236: [48274 22492 32708 10212 18093]\n", "21284: [45633 11907 28909 15651 41923]\n",
"1143: [26421 47901 61921 24136 29532]\n", "3999: [21215 4042 48497 10936 43364]\n",
"22391: [59355 17487 973 41690 18702]\n", "4057: [48438 56372 31171 5595 15227]\n",
"5610: [34554 10515 1449 31747 45116]\n", "48308: [45863 63103 15125 16546 43001]\n",
"24876: [61533 61939 52341 29169 15485]\n", "14680: [52540 45179 2886 8096 11056]\n",
"51604: [13623 8923 29868 19891 53514]\n" "46323: [14191 58318 9246 13333 62605]\n"
] ]
} }
], ],
"execution_count": 197 "execution_count": 29
}, },
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-19T14:18:48.443885Z", "end_time": "2025-03-20T08:32:08.226660Z",
"start_time": "2025-03-19T14:18:48.441137Z" "start_time": "2025-03-20T08:32:08.224216Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
"source": [ "source": [
"user_icon_keypad = user_icons.reshape(-1, keypad_size.props_per_key)\n", "user_icon_keypad = user_icons.reshape(-1, keypad_size.props_per_key)\n",
"set_icons_dict = dict(zip(customer.cipher.position_key, user_icon_keypad.T))\n", "pos_icons_dict = dict(zip(customer.cipher.position_key, user_icon_keypad.T))\n",
"print(\"Set to Icons Map:\")\n", "print(\"Position Value to Icons Map:\")\n",
"for set_val, icons in set_icons_dict.items():\n", "for pos_val, icons in pos_icons_dict.items():\n",
" print(f\"{set_val}: {icons}\")\n" " print(f\"{pos_val}: {icons}\")\n"
], ],
"outputs": [ "outputs": [
{ {
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Set to Icons Map:\n", "Position Value to Icons Map:\n",
"52236: ['😀' '🥺' '🤔' '🐱' '🦄']\n", "21284: ['😀' '🥺' '🤔' '🐱' '🦄']\n",
"1143: ['😂' '😡' '🙃' '🐶' '🌟']\n", "3999: ['😂' '😡' '🙃' '🐶' '🌟']\n",
"22391: ['🥳' '😱' '😇' '🦁' '⚡']\n", "4057: ['🥳' '😱' '😇' '🦁' '⚡']\n",
"5610: ['😍' '🤯' '🤖' '🐻' '🔥']\n", "48308: ['😍' '🤯' '🤖' '🐻' '🔥']\n",
"24876: ['🤓' '🥰' '👽' '🐸' '🍕']\n", "14680: ['🤓' '🥰' '👽' '🐸' '🍕']\n",
"51604: ['😎' '😴' '👾' '🐙' '🎉']\n" "46323: ['😎' '😴' '👾' '🐙' '🎉']\n"
] ]
} }
], ],
"execution_count": 198 "execution_count": 30
}, },
{ {
"metadata": {}, "metadata": {},
@@ -184,8 +184,8 @@
"\n", "\n",
"#### Generate Keypad\n", "#### Generate Keypad\n",
" For the server to determine the users nkode, the user's keypad must be dispersable.\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", " To make the keypad dispersable, the server will randomly drop key positions so the number of properties per key 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", " In our case, the server drops 1 key position 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", " - 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", " - each value in the keypad is the index value of a customer properties\n",
" - the user never learns what their server-side properties" " - the user never learns what their server-side properties"
@@ -194,8 +194,8 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-19T14:21:05.988739Z", "end_time": "2025-03-20T08:32:08.256237Z",
"start_time": "2025-03-19T14:21:05.981809Z" "start_time": "2025-03-20T08:32:08.250147Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -223,11 +223,11 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Key 0: ['🙃' '🥳' '🔥' '🐸' '👾']\n", "Key 0: ['🦄' '😂' '😇' '👽' '😴']\n",
"Key 1: ['😡' '😱' '🤯' '🥰' '😴']\n", "Key 1: ['🐱' '🌟' '😱' '🐸' '😎']\n",
"Key 2: ['🌟' '🦁' '🐻' '🍕' '😎']\n", "Key 2: ['🤔' '🙃' '🦁' '🥰' '🐙']\n",
"Key 3: ['🐶' '' '🤖' '👽' '🎉']\n", "Key 3: ['😀' '😡' '' '🍕' '👾']\n",
"Key 4: ['😂' '😇' '😍' '🤓' '🐙']\n" "Key 4: ['🥺' '🐶' '🥳' '🤓' '🎉']\n"
] ]
}, },
{ {
@@ -244,11 +244,11 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Key 0: [13 2 27 22 17]\n", "Key 0: [24 1 14 16 11]\n",
"Key 1: [ 7 8 9 10 11]\n", "Key 1: [18 25 8 22 5]\n",
"Key 2: [25 20 21 28 5]\n", "Key 2: [12 13 20 10 23]\n",
"Key 3: [19 26 15 16 29]\n", "Key 3: [ 0 7 26 28 17]\n",
"Key 4: [ 1 14 3 4 23]\n" "Key 4: [ 6 19 2 4 29]\n"
] ]
}, },
{ {
@@ -265,15 +265,15 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Key 0: [32049 6729 60466 26997 1309]\n", "Key 0: [41923 21215 31171 2886 58318]\n",
"Key 1: [61686 12369 40030 7765 16822]\n", "Key 1: [15651 43364 56372 8096 14191]\n",
"Key 2: [29442 13543 37604 7572 18665]\n", "Key 2: [28909 48497 5595 45179 13333]\n",
"Key 3: [29124 1259 53208 47841 51215]\n", "Key 3: [45633 4042 15227 11056 9246]\n",
"Key 4: [48741 14803 46096 27958 19258]\n" "Key 4: [11907 10936 48438 52540 62605]\n"
] ]
} }
], ],
"execution_count": 229 "execution_count": 31
}, },
{ {
"metadata": {}, "metadata": {},
@@ -286,19 +286,19 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-19T14:22:48.143268Z", "end_time": "2025-03-20T08:32:08.280568Z",
"start_time": "2025-03-19T14:22:48.140039Z" "start_time": "2025-03-20T08:32:08.277339Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
"source": [ "source": [
"username = random_username()\n", "username = random_username()\n",
"passcode_len = 4\n", "passcode_len = 4\n",
"user_passcode_indices = np.random.choice(set_signup_keypad.reshape(-1), size=passcode_len, replace=False).tolist()\n", "passcode_property_indices = np.random.choice(set_signup_keypad.reshape(-1), size=passcode_len, replace=False).tolist()\n",
"selected_keys_set = select_keys_with_passcode_values(user_passcode_indices, set_signup_keypad, keypad_size.numb_of_keys)\n", "selected_keys_set = select_keys_with_passcode_values(passcode_property_indices, set_signup_keypad, keypad_size.numb_of_keys)\n",
"print(f\"User Passcode Indices: {user_passcode_indices}\")\n", "print(f\"User Passcode Indices: {passcode_property_indices}\")\n",
"print(f\"User Passcode Icons: {user_icons[user_passcode_indices]}\")\n", "print(f\"User Passcode Icons: {user_icons[passcode_property_indices]}\")\n",
"print(f\"User Passcode Server-side properties: {customer.cipher.property_key[user_passcode_indices]}\")\n", "print(f\"User Passcode Server-side properties: {customer.cipher.property_key[passcode_property_indices]}\")\n",
"print(f\"Selected Keys: {selected_keys_set}\")" "print(f\"Selected Keys: {selected_keys_set}\")"
], ],
"outputs": [ "outputs": [
@@ -306,27 +306,27 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"User Passcode Indices: [11, 22, 1, 23]\n", "User Passcode Indices: [19, 7, 10, 6]\n",
"User Passcode Icons: ['😴' '🐸' '😂' '🐙']\n", "User Passcode Icons: ['🐶' '😡' '🥰' '🥺']\n",
"User Passcode Server-side properties: [16822 26997 48741 19258]\n", "User Passcode Server-side properties: [10936 4042 45179 11907]\n",
"Selected Keys: [1, 0, 4, 4]\n" "Selected Keys: [4, 3, 2, 4]\n"
] ]
} }
], ],
"execution_count": 237 "execution_count": 32
}, },
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-19T14:18:48.697364Z", "end_time": "2025-03-20T08:32:08.316148Z",
"start_time": "2025-03-19T14:18:48.694055Z" "start_time": "2025-03-20T08:32:08.313495Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
"source": [ "source": [
"confirm_keypad = api.set_nkode(username, customer_id, selected_keys_set, signup_session_id)\n", "confirm_keypad = api.set_nkode(username, customer_id, selected_keys_set, signup_session_id)\n",
"keypad_view(confirm_keypad, keypad_size.numb_of_keys)\n", "keypad_view(confirm_keypad, keypad_size.numb_of_keys)\n",
"selected_keys_confirm = select_keys_with_passcode_values(user_passcode_indices, confirm_keypad, keypad_size.numb_of_keys)\n", "selected_keys_confirm = select_keys_with_passcode_values(passcode_property_indices, confirm_keypad, keypad_size.numb_of_keys)\n",
"print(f\"Selected Keys\\n{selected_keys_confirm}\")" "print(f\"Selected Keys\\n{selected_keys_confirm}\")"
], ],
"outputs": [ "outputs": [
@@ -334,23 +334,23 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Key 0: [13 14 9 10 23]\n", "Key 0: [18 7 20 4 11]\n",
"Key 1: [25 20 21 4 17]\n", "Key 1: [12 1 26 22 29]\n",
"Key 2: [ 1 8 15 22 5]\n", "Key 2: [ 0 19 14 10 5]\n",
"Key 3: [19 26 27 28 11]\n", "Key 3: [24 25 2 28 23]\n",
"Key 4: [ 7 2 3 16 29]\n", "Key 4: [ 6 13 8 16 17]\n",
"Selected Keys\n", "Selected Keys\n",
"[2, 2, 3, 0]\n" "[2, 0, 2, 4]\n"
] ]
} }
], ],
"execution_count": 202 "execution_count": 33
}, },
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-19T14:18:49.028822Z", "end_time": "2025-03-20T08:32:08.575664Z",
"start_time": "2025-03-19T14:18:48.719642Z" "start_time": "2025-03-20T08:32:08.337518Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -360,7 +360,7 @@
"assert success" "assert success"
], ],
"outputs": [], "outputs": [],
"execution_count": 203 "execution_count": 34
}, },
{ {
"metadata": {}, "metadata": {},
@@ -369,9 +369,9 @@
"## User Cipher\n", "## User Cipher\n",
"\n", "\n",
"Users have 4 cipher keys:\n", "Users have 4 cipher keys:\n",
"1. prop_key: Half of the user's server-side passcode. the counterpart to the `customer_prop_key`. A user's passcode is made from elements in `user_prop_key XOR customer_prop_key`. Each property belongs to a set.\n", "1. property_key: The counterpart to the `customer_prop_key`. A user's server-side passcode is composed of elements in `user_prop_key XOR customer_prop_key`.\n",
"2. pass_key: The passcode key is used to encipher user passcode\n", "2. pass_key: The passcode key is used to encipher user passcode\n",
"3. combined_set_key: The combined set key is `user_set_key XOR customer_set_key`. The user_set_key isn't stored and can't be recovered with the `customer_set_key`\n", "3. combined_position_key: The combined position key is `user_pos_key XOR customer_pos_key`.\n",
"4. mask_key: The mask key used to encipher user nKode\n", "4. mask_key: The mask key used to encipher user nKode\n",
"\n", "\n",
"\n" "\n"
@@ -380,24 +380,24 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-19T14:18:49.044808Z", "end_time": "2025-03-20T08:32:08.588049Z",
"start_time": "2025-03-19T14:18:49.038903Z" "start_time": "2025-03-20T08:32:08.583087Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
"source": [ "source": [
"from src.user_cipher import UserCipher\n", "from src.user_cipher import UserCipher\n",
"user_cipher = UserCipher.create(keypad_size, customer.cipher.position_key, customer.nkode_policy.max_nkode_len)\n", "user_cipher = UserCipher.create(keypad_size, customer.cipher.position_key, customer.nkode_policy.max_nkode_len)\n",
"user_prop_key_keypad = user_cipher.prop_key.reshape(-1, keypad_size.props_per_key)" "user_prop_key_keypad = user_cipher.property_key.reshape(-1, keypad_size.props_per_key)"
], ],
"outputs": [], "outputs": [],
"execution_count": 204 "execution_count": 35
}, },
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-19T14:18:49.056184Z", "end_time": "2025-03-20T08:32:08.596984Z",
"start_time": "2025-03-19T14:18:49.053919Z" "start_time": "2025-03-20T08:32:08.595221Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -408,21 +408,21 @@
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Property Key:\n", "Property Key:\n",
"[[42472 31697 42349 63196 42777 61068]\n", "[[43643 58945 45655 10493 17462 5635]\n",
" [ 7243 387 55065 19589 60418 22963]\n", " [42071 15680 60860 39600 15784 4102]\n",
" [26541 59081 11622 22333 35608 42306]\n", " [60857 21300 14877 25869 12858 50934]\n",
" [58621 57412 35828 19293 16394 53334]\n", " [55451 44486 22660 41758 36853 37697]\n",
" [ 5908 43761 45282 44085 8881 21753]]\n" " [24236 53340 57175 52425 5167 2017]]\n"
] ]
} }
], ],
"execution_count": 205 "execution_count": 36
}, },
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-19T14:18:49.080744Z", "end_time": "2025-03-20T08:32:08.615012Z",
"start_time": "2025-03-19T14:18:49.078469Z" "start_time": "2025-03-20T08:32:08.613119Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -432,17 +432,17 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Passcode Key: [15958 16933 12810 19682 61534 54403 52645 54893 63261 22611]\n" "Passcode Key: [31049 4633 40678 55986 14115 22499 3470 53359 20871 60539]\n"
] ]
} }
], ],
"execution_count": 206 "execution_count": 37
}, },
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-19T14:18:49.125439Z", "end_time": "2025-03-20T08:32:08.639696Z",
"start_time": "2025-03-19T14:18:49.123Z" "start_time": "2025-03-20T08:32:08.637469Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -452,119 +452,112 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Mask Key: [11511 36348 3693 57612 7883 59516 54039 57361 15218 43846]\n" "Mask Key: [55361 38182 36656 63013 26815 17961 23911 65497 28524 60226]\n"
] ]
} }
], ],
"execution_count": 207 "execution_count": 38
}, },
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-19T14:18:49.154768Z", "end_time": "2025-03-20T08:32:08.658960Z",
"start_time": "2025-03-19T14:18:49.152444Z" "start_time": "2025-03-20T08:32:08.657009Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
"source": "print(f\"Combined Set Key: {user_cipher.combined_set_key}\")", "source": "print(f\"Combined Position Key: {user_cipher.combined_position_key}\")",
"outputs": [ "outputs": [
{ {
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Combined Set Key: [16302 28740 39642 59999 35588 576]\n" "Combined Position Key: [33934 3750 42586 25190 7504 35546]\n"
] ]
} }
], ],
"execution_count": 208 "execution_count": 39
}, },
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-19T14:18:49.188943Z", "end_time": "2025-03-20T08:32:08.678360Z",
"start_time": "2025-03-19T14:18:49.186648Z" "start_time": "2025-03-20T08:32:08.676228Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
"source": "print(f\"User Set Key = combined_set_key XOR customer_set_key: {user_cipher.combined_set_key ^ customer.cipher.position_key}\")", "source": "print(f\"User Position Key = combined_pos_key XOR customer_pos_key: {user_cipher.combined_position_key ^ customer.cipher.position_key}\")",
"outputs": [ "outputs": [
{ {
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"User Set Key = combined_set_key XOR customer_set_key: [62370 29747 52653 65461 59944 52180]\n" "User Position Key = combined_pos_key XOR customer_pos_key: [55210 313 43395 57042 9224 15913]\n"
] ]
} }
], ],
"execution_count": 209 "execution_count": 40
}, },
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-19T14:18:49.217942Z", "end_time": "2025-03-20T08:32:08.698976Z",
"start_time": "2025-03-19T14:18:49.215165Z" "start_time": "2025-03-20T08:32:08.696420Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
"source": [ "source": [
"set_properties_dict = dict(zip(user_cipher.combined_set_key, user_prop_key_keypad.T))\n", "position_properties_dict = dict(zip(user_cipher.combined_position_key, user_prop_key_keypad.T))\n",
"print(f\"Combined Set to Properties Map:\")\n", "print(f\"Combined Position to Properties Map:\")\n",
"for set_val, props in set_properties_dict.items():\n", "for pos_val, props in position_properties_dict.items():\n",
" print(f\"{set_val}: {props}\")" " print(f\"{pos_val}: {props}\")"
], ],
"outputs": [ "outputs": [
{ {
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Combined Set to Properties Map:\n", "Combined Position to Properties Map:\n",
"16302: [42472 7243 26541 58621 5908]\n", "33934: [43643 42071 60857 55451 24236]\n",
"28740: [31697 387 59081 57412 43761]\n", "3750: [58945 15680 21300 44486 53340]\n",
"39642: [42349 55065 11622 35828 45282]\n", "42586: [45655 60860 14877 22660 57175]\n",
"59999: [63196 19589 22333 19293 44085]\n", "25190: [10493 39600 25869 41758 52425]\n",
"35588: [42777 60418 35608 16394 8881]\n", "7504: [17462 15784 12858 36853 5167]\n",
"576: [61068 22963 42306 53334 21753]\n" "35546: [ 5635 4102 50934 37697 2017]\n"
] ]
} }
], ],
"execution_count": 210 "execution_count": 41
}, },
{ {
"metadata": {}, "metadata": {},
"cell_type": "markdown", "cell_type": "markdown",
"source": [ "source": [
"#### Encipher Mask\n", "#### Encipher Mask\n",
"1. Order customer properties by user passcode.\n", "1. Get the `padded_passcode_position_indices`; padded with random position indices to equal length `max_nkode_len`.\n",
"2. Get the set indices (`set_indices`) of the ordered customer properties.\n", "2. Recover the `user_position_key`. Recall `user.cipher.combined_position_key = user_position_key XOR customer.cipher.positon_key`\n",
"3. Pad the\n", "3. Order the `user_position_key` by the `padded_passcode_position_indices`\n",
"1. combined_set_key = user_set_key ^ customer_set_key\n", "4. Mask the `ordered_user_position_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", "5. Base 64 encode the mask"
"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": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-19T14:18:49.244375Z", "end_time": "2025-03-20T08:32:08.762578Z",
"start_time": "2025-03-19T14:18:49.241861Z" "start_time": "2025-03-20T08:32:08.760236Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
"source": [ "source": [
"set_indices = customer.cipher.get_passcode_position_indices_padded(list(user_passcode_indices), customer.nkode_policy.max_nkode_len)\n", "padded_passcode_position_indices = customer.cipher.get_passcode_position_indices_padded(list(passcode_property_indices), customer.nkode_policy.max_nkode_len)\n",
"ordered_combined_set_key = user_cipher.combined_set_key[set_indices]\n", "user_position_key = user_cipher.combined_position_key ^ customer.cipher.position_key\n",
"ordered_customer_set_key = customer.cipher.position_key[set_indices]\n", "ordered_user_position_key = user_position_key[padded_passcode_position_indices]\n",
"ordered_user_set_key = ordered_customer_set_key ^ ordered_combined_set_key\n", "mask = ordered_user_position_key ^ user_cipher.mask_key\n",
"mask = ordered_user_set_key ^ user_cipher.mask_key\n",
"encoded_mask = user_cipher.encode_base64_str(mask)" "encoded_mask = user_cipher.encode_base64_str(mask)"
], ],
"outputs": [], "outputs": [],
"execution_count": 211 "execution_count": 42
}, },
{ {
"metadata": {}, "metadata": {},
@@ -581,14 +574,14 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-19T14:18:49.575573Z", "end_time": "2025-03-20T08:32:09.024060Z",
"start_time": "2025-03-19T14:18:49.268784Z" "start_time": "2025-03-20T08:32:08.789902Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
"source": [ "source": [
"combined_prop_key = customer.cipher.property_key ^ user_cipher.prop_key\n", "combined_prop_key = customer.cipher.property_key ^ user_cipher.property_key\n",
"user_passcode = combined_prop_key[user_passcode_indices]\n", "user_passcode = combined_prop_key[passcode_property_indices]\n",
"pad_len = customer.nkode_policy.max_nkode_len - passcode_len\n", "pad_len = customer.nkode_policy.max_nkode_len - passcode_len\n",
"user_passcode_padded = np.concatenate((user_passcode, np.zeros(pad_len, dtype=user_passcode.dtype)))\n", "user_passcode_padded = np.concatenate((user_passcode, np.zeros(pad_len, dtype=user_passcode.dtype)))\n",
"ciphered_passcode = user_passcode_padded ^ user_cipher.pass_key\n", "ciphered_passcode = user_passcode_padded ^ user_cipher.pass_key\n",
@@ -596,7 +589,7 @@
"passcode_hash = bcrypt.hashpw(passcode_prehash, bcrypt.gensalt(rounds=12)).decode(\"utf-8\")" "passcode_hash = bcrypt.hashpw(passcode_prehash, bcrypt.gensalt(rounds=12)).decode(\"utf-8\")"
], ],
"outputs": [], "outputs": [],
"execution_count": 212 "execution_count": 43
}, },
{ {
"metadata": {}, "metadata": {},
@@ -617,8 +610,8 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-19T14:18:49.585161Z", "end_time": "2025-03-20T08:32:09.032955Z",
"start_time": "2025-03-19T14:18:49.583132Z" "start_time": "2025-03-20T08:32:09.030937Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -631,7 +624,7 @@
")" ")"
], ],
"outputs": [], "outputs": [],
"execution_count": 213 "execution_count": 44
}, },
{ {
"metadata": {}, "metadata": {},
@@ -645,16 +638,16 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-19T14:18:49.901534Z", "end_time": "2025-03-20T08:32:09.273099Z",
"start_time": "2025-03-19T14:18:49.594710Z" "start_time": "2025-03-20T08:32:09.040255Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
"source": [ "source": [
"login_keypad = api.get_login_keypad(username, customer_id)\n", "login_keypad = api.get_login_keypad(username, customer_id)\n",
"keypad_view(login_keypad, keypad_size.props_per_key)\n", "keypad_view(login_keypad, keypad_size.props_per_key)\n",
"selected_keys_login = select_keys_with_passcode_values(user_passcode_indices, login_keypad, keypad_size.props_per_key)\n", "selected_keys_login = select_keys_with_passcode_values(passcode_property_indices, login_keypad, keypad_size.props_per_key)\n",
"print(f\"User Passcode: {user_passcode_indices}\\n\")\n", "print(f\"User Passcode: {passcode_property_indices}\\n\")\n",
"print(f\"Selected Keys:\\n {selected_keys_login}\\n\")\n", "print(f\"Selected Keys:\\n {selected_keys_login}\\n\")\n",
"success = api.login(customer_id, username, selected_keys_login)\n", "success = api.login(customer_id, username, selected_keys_login)\n",
"assert success" "assert success"
@@ -664,20 +657,20 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Key 0: [ 6 19 8 3 4 23]\n", "Key 0: [24 1 14 27 16 11]\n",
"Key 1: [18 13 2 21 28 5]\n", "Key 1: [18 25 8 3 22 5]\n",
"Key 2: [12 25 14 15 16 11]\n", "Key 2: [12 13 20 21 10 23]\n",
"Key 3: [24 7 26 9 22 17]\n", "Key 3: [ 0 7 26 9 28 17]\n",
"Key 4: [ 0 1 20 27 10 29]\n", "Key 4: [ 6 19 2 15 4 29]\n",
"User Passcode: [15, 1, 19, 23]\n", "User Passcode: [19, 7, 10, 6]\n",
"\n", "\n",
"Selected Keys:\n", "Selected Keys:\n",
" [2, 4, 0, 0]\n", " [4, 3, 2, 4]\n",
"\n" "\n"
] ]
} }
], ],
"execution_count": 214 "execution_count": 45
}, },
{ {
"metadata": {}, "metadata": {},
@@ -708,24 +701,24 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-19T14:18:49.914512Z", "end_time": "2025-03-20T08:32:09.282728Z",
"start_time": "2025-03-19T14:18:49.911338Z" "start_time": "2025-03-20T08:32:09.279895Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
"source": [ "source": [
"login_keypad = api.get_login_keypad(username, customer_id)\n", "login_keypad = api.get_login_keypad(username, customer_id)\n",
"selected_keys_login = select_keys_with_passcode_values(user_passcode_indices, login_keypad, keypad_size.props_per_key)\n", "selected_keys_login = select_keys_with_passcode_values(passcode_property_indices, login_keypad, keypad_size.props_per_key)\n",
"user = api.customers[customer_id].users[username]\n", "user = api.customers[customer_id].users[username]\n",
"mask = user.cipher.decode_base64_str(user.enciphered_passcode.mask)\n", "mask = user.cipher.decode_base64_str(user.enciphered_passcode.mask)\n",
"deciphered_mask = mask ^ user.cipher.mask_key\n", "deciphered_mask = mask ^ user.cipher.mask_key\n",
"set_key = customer.cipher.position_key ^ user.cipher.combined_set_key\n", "set_key = customer.cipher.position_key ^ user.cipher.combined_position_key\n",
"passcode_set_index = [int(np.where(set_key == set_cipher)[0][0]) for set_cipher in deciphered_mask[:passcode_len]]\n", "passcode_set_index = [int(np.where(set_key == set_cipher)[0][0]) for set_cipher in deciphered_mask[:passcode_len]]\n",
"presumed_selected_properties_idx = customer.users[username].user_keypad.get_prop_idxs_by_keynumb_setidx(selected_keys_login, passcode_set_index)\n", "presumed_selected_properties_idx = customer.users[username].user_keypad.get_prop_idxs_by_keynumb_setidx(selected_keys_login, passcode_set_index)\n",
"assert user_passcode_indices == presumed_selected_properties_idx\n" "assert passcode_property_indices == presumed_selected_properties_idx\n"
], ],
"outputs": [], "outputs": [],
"execution_count": 215 "execution_count": 46
}, },
{ {
"metadata": {}, "metadata": {},
@@ -735,8 +728,8 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-19T14:18:50.236818Z", "end_time": "2025-03-20T08:32:09.526068Z",
"start_time": "2025-03-19T14:18:49.932427Z" "start_time": "2025-03-20T08:32:09.295445Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -745,7 +738,7 @@
"assert valid_nkode\n" "assert valid_nkode\n"
], ],
"outputs": [], "outputs": [],
"execution_count": 216 "execution_count": 47
}, },
{ {
"metadata": {}, "metadata": {},
@@ -761,8 +754,8 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-19T14:18:50.851576Z", "end_time": "2025-03-20T08:32:09.996256Z",
"start_time": "2025-03-19T14:18:50.240709Z" "start_time": "2025-03-20T08:32:09.529950Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -777,7 +770,7 @@
"print_user_enciphered_code()\n", "print_user_enciphered_code()\n",
"\n", "\n",
"login_keypad = api.get_login_keypad(username, customer_id)\n", "login_keypad = api.get_login_keypad(username, customer_id)\n",
"selected_keys_login = select_keys_with_passcode_values(user_passcode_indices, login_keypad, keypad_size.props_per_key)\n", "selected_keys_login = select_keys_with_passcode_values(passcode_property_indices, login_keypad, keypad_size.props_per_key)\n",
"success = api.login(customer_id, username, selected_keys_login)\n", "success = api.login(customer_id, username, selected_keys_login)\n",
"assert success\n", "assert success\n",
"print_user_enciphered_code()" "print_user_enciphered_code()"
@@ -787,16 +780,16 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"mask: tBqaWnmsGlsclLRq7qdFeuZ/Krg=, code: $2b$12$iBdtB4bRMx9VnWKwAInkwecUx5wwiL1C0DVWO.sk9EG1syVVe2CaS\n", "mask: cz9m1OunYlEK42X0jRrGAzKvheg=, code: $2b$12$Z.N7qwUTMgSVJFQC9hKgjeQ8owBpZMm5Aa14RQdiJH7C8l61QJENS\n",
"\n", "\n",
"mask: tBqaWnmsGlsclLRq7qdFeuZ/Krg=, code: $2b$12$iBdtB4bRMx9VnWKwAInkwecUx5wwiL1C0DVWO.sk9EG1syVVe2CaS\n", "mask: cz9m1OunYlEK42X0jRrGAzKvheg=, code: $2b$12$Z.N7qwUTMgSVJFQC9hKgjeQ8owBpZMm5Aa14RQdiJH7C8l61QJENS\n",
"\n", "\n",
"mask: DpuEwDyPrOF4pAxxozyqUHigaak=, code: $2b$12$ngd6PgpZo/UhIANnrRimlOliRIGwAaS6zbe5gqTzYHPBaeAa3vJsy\n", "mask: e+RtDYeB1G1RfuTOjCna6K9xLUU=, code: $2b$12$DHdD52jbBdVoXYArhWCm7eABlnch.tNhO/1Eipygj8fpoUFuPzyEC\n",
"\n" "\n"
] ]
} }
], ],
"execution_count": 217 "execution_count": 48
}, },
{ {
"metadata": {}, "metadata": {},
@@ -810,8 +803,8 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-19T14:18:50.865243Z", "end_time": "2025-03-20T08:32:10.012897Z",
"start_time": "2025-03-19T14:18:50.861260Z" "start_time": "2025-03-20T08:32:10.009292Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -823,7 +816,7 @@
"new_sets = customer.cipher.position_key" "new_sets = customer.cipher.position_key"
], ],
"outputs": [], "outputs": [],
"execution_count": 218 "execution_count": 49
}, },
{ {
"metadata": {}, "metadata": {},
@@ -836,8 +829,8 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-19T14:18:50.876670Z", "end_time": "2025-03-20T08:32:10.019285Z",
"start_time": "2025-03-19T14:18:50.874092Z" "start_time": "2025-03-20T08:32:10.017224Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -846,11 +839,11 @@
"sets_xor = np.bitwise_xor(new_sets, old_sets)\n", "sets_xor = np.bitwise_xor(new_sets, old_sets)\n",
"for user in customer.users.values():\n", "for user in customer.users.values():\n",
" user.renew = True\n", " user.renew = True\n",
" user.cipher.combined_set_key = np.bitwise_xor(user.cipher.combined_set_key, sets_xor)\n", " user.cipher.combined_position_key = np.bitwise_xor(user.cipher.combined_position_key, sets_xor)\n",
" user.cipher.prop_key = np.bitwise_xor(user.cipher.prop_key, props_xor)" " user.cipher.property_key = np.bitwise_xor(user.cipher.property_key, props_xor)"
], ],
"outputs": [], "outputs": [],
"execution_count": 219 "execution_count": 50
}, },
{ {
"metadata": {}, "metadata": {},
@@ -860,8 +853,8 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-19T14:18:51.191895Z", "end_time": "2025-03-20T08:32:10.260051Z",
"start_time": "2025-03-19T14:18:50.885862Z" "start_time": "2025-03-20T08:32:10.026503Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -875,7 +868,7 @@
"user.renew = False" "user.renew = False"
], ],
"outputs": [], "outputs": [],
"execution_count": 220 "execution_count": 51
} }
], ],
"metadata": { "metadata": {

View File

@@ -16,7 +16,7 @@ class Customer:
@classmethod @classmethod
def create(cls, nkode_policy: NKodePolicy, cipher: CustomerCipher) -> 'Customer': def create(cls, nkode_policy: NKodePolicy, cipher: CustomerCipher) -> 'Customer':
if nkode_policy.distinct_sets > cipher.keypad_size.numb_of_keys: if nkode_policy.distinct_positions > cipher.keypad_size.numb_of_keys:
raise ValueError("Distinct sets cannot be greater than the number of keys") raise ValueError("Distinct sets cannot be greater than the number of keys")
if nkode_policy.distinct_properties > cipher.keypad_size.total_props: if nkode_policy.distinct_properties > cipher.keypad_size.total_props:
raise ValueError("Distinct properties cannot be greater than the total number of properties") raise ValueError("Distinct properties cannot be greater than the total number of properties")
@@ -76,7 +76,7 @@ class Customer:
distinct_properties = len(set(passcode_prop_idx)) distinct_properties = len(set(passcode_prop_idx))
if ( if (
self.nkode_policy.min_nkode_len <= nkode_len <= self.nkode_policy.max_nkode_len and self.nkode_policy.min_nkode_len <= nkode_len <= self.nkode_policy.max_nkode_len and
distinct_sets >= self.nkode_policy.distinct_sets and distinct_sets >= self.nkode_policy.distinct_positions and
distinct_properties >= self.nkode_policy.distinct_properties distinct_properties >= self.nkode_policy.distinct_properties
): ):
return True return True

View File

@@ -10,7 +10,7 @@ class EncipheredNKode:
class NKodePolicy: class NKodePolicy:
max_nkode_len: int = 10 max_nkode_len: int = 10
min_nkode_len: int = 4 min_nkode_len: int = 4
distinct_sets: int = 0 distinct_positions: int = 0
distinct_properties: int = 4 distinct_properties: int = 4
byte_len: int = 2 # Todo: this should change the total number of bytes an properties or set value can be byte_len: int = 2 # Todo: this should change the total number of bytes an properties or set value can be
lock_out: int = 5 lock_out: int = 5

View File

@@ -18,8 +18,8 @@ class User:
def renew_keys(self, set_xor: np.ndarray, prop_xor: np.ndarray): def renew_keys(self, set_xor: np.ndarray, prop_xor: np.ndarray):
self.renew = True self.renew = True
self.cipher.combined_set_key = self.cipher.combined_set_key ^ set_xor self.cipher.combined_position_key = self.cipher.combined_position_key ^ set_xor
self.cipher.prop_key = self.cipher.prop_key ^ prop_xor self.cipher.property_key = self.cipher.property_key ^ prop_xor
def refresh_passcode(self, passcode_prop_idxs: list[int], customer_cipher: CustomerCipher): def refresh_passcode(self, passcode_prop_idxs: list[int], customer_cipher: CustomerCipher):
self.cipher = UserCipher.create( self.cipher = UserCipher.create(

View File

@@ -9,30 +9,31 @@ from src.customer_cipher import CustomerCipher
@dataclass @dataclass
class UserCipher: class UserCipher:
prop_key: np.ndarray property_key: np.ndarray
combined_set_key: np.ndarray combined_position_key: np.ndarray
pass_key: np.ndarray pass_key: np.ndarray
mask_key: np.ndarray mask_key: np.ndarray
max_nkode_len: int max_nkode_len: int
@classmethod @classmethod
def create(cls, keypad_size: KeypadSize, customer_set_key: np.ndarray, max_nkode_len: int) -> 'UserCipher': def create(cls, keypad_size: KeypadSize, customer_pos_key: np.ndarray, max_nkode_len: int) -> 'UserCipher':
if len(customer_set_key) != keypad_size.props_per_key: if len(customer_pos_key) != keypad_size.props_per_key:
raise ValueError("Invalid set values") raise ValueError("Invalid position values")
user_set_key = np.random.choice(2**16,size=keypad_size.props_per_key, replace=False) user_pos_key = np.random.choice(2**16,size=keypad_size.props_per_key, replace=False)
return UserCipher( return UserCipher(
prop_key=np.random.choice(2 ** 16, size=keypad_size.total_props, replace=False), property_key=np.random.choice(2 ** 16, size=keypad_size.total_props, replace=False),
pass_key=np.random.choice(2 ** 16, size=max_nkode_len, replace=False), pass_key=np.random.choice(2 ** 16, size=max_nkode_len, replace=False),
mask_key=np.random.choice(2**16, size=max_nkode_len, replace=False), mask_key=np.random.choice(2**16, size=max_nkode_len, replace=False),
combined_set_key=user_set_key ^ customer_set_key, combined_position_key=user_pos_key ^ customer_pos_key,
max_nkode_len=max_nkode_len max_nkode_len=max_nkode_len
) )
def pad_user_mask(self, user_mask: np.ndarray, set_vals: np.ndarray) -> np.ndarray: def pad_user_mask(self, user_mask: np.ndarray, pos_vals: np.ndarray) -> np.ndarray:
# TODO: replace with new method
if len(user_mask) >= self.max_nkode_len: if len(user_mask) >= self.max_nkode_len:
raise ValueError("User encoded_mask is too long") raise ValueError("User encoded_mask is too long")
padding_size = self.max_nkode_len - len(user_mask) padding_size = self.max_nkode_len - len(user_mask)
padding = np.random.choice(set_vals, size=padding_size, replace=True).astype(np.uint16) padding = np.random.choice(pos_vals, size=padding_size, replace=True).astype(np.uint16)
return np.concatenate([user_mask, padding]) return np.concatenate([user_mask, padding])
@staticmethod @staticmethod
@@ -90,7 +91,7 @@ class UserCipher:
passcode_cipher = self.pass_key.copy() passcode_cipher = self.pass_key.copy()
passcode_cipher[:passcode_len] = ( passcode_cipher[:passcode_len] = (
passcode_cipher[:passcode_len] ^ passcode_cipher[:passcode_len] ^
self.prop_key[passcode_prop_idx] ^ self.property_key[passcode_prop_idx] ^
customer_prop.property_key[passcode_prop_idx] customer_prop.property_key[passcode_prop_idx]
) )
return passcode_cipher.astype(np.uint16).tobytes() return passcode_cipher.astype(np.uint16).tobytes()
@@ -100,21 +101,21 @@ class UserCipher:
passcode_prop_idx: list[int], passcode_prop_idx: list[int],
customer_cipher: CustomerCipher customer_cipher: CustomerCipher
) -> str: ) -> str:
set_idxs = customer_cipher.get_passcode_position_indices_padded(passcode_prop_idx, len(self.mask_key)) pos_idxs = customer_cipher.get_passcode_position_indices_padded(passcode_prop_idx, len(self.mask_key))
ordered_set_key = self.combined_set_key[set_idxs] ordered_pos_key = self.combined_position_key[pos_idxs]
ordered_customer_key = customer_cipher.position_key[set_idxs] ordered_customer_pos_key = customer_cipher.position_key[pos_idxs]
mask = ordered_set_key ^ ordered_customer_key ^ self.mask_key mask = ordered_pos_key ^ ordered_customer_pos_key ^ self.mask_key
encoded_mask = self.encode_base64_str(mask) encoded_mask = self.encode_base64_str(mask)
return encoded_mask return encoded_mask
def decipher_mask(self, encoded_mask: str, customer_set_key: np.ndarray, passcode_len: int) -> list[int]: def decipher_mask(self, encoded_mask: str, customer_pos_key: np.ndarray, passcode_len: int) -> list[int]:
mask = self.decode_base64_str(encoded_mask) mask = self.decode_base64_str(encoded_mask)
# user_set_key ordered by the user's nkode and padded to be length max_nkode_len # user_pos_key ordered by the user's nkode and padded to be length max_nkode_len
ordered_set_key = mask ^ self.mask_key ordered_user_pos_key = mask ^ self.mask_key
user_set_key = customer_set_key ^ self.combined_set_key user_pos_key = customer_pos_key ^ self.combined_position_key
passcode_sets = [] passcode_position = []
for partial_set in ordered_set_key[:passcode_len]: for position_val in ordered_user_pos_key[:passcode_len]:
set_idx = np.where(user_set_key == partial_set)[0][0] position_idx = np.where(user_pos_key == position_val)[0][0]
passcode_sets.append(int(customer_set_key[set_idx])) passcode_position.append(int(customer_pos_key[position_idx]))
return passcode_sets return passcode_position

View File

@@ -83,16 +83,16 @@ class UserKeypad:
if not (0 <= key_numb < self.keypad_size.numb_of_keys): if not (0 <= key_numb < self.keypad_size.numb_of_keys):
raise ValueError(f"key_numb must be between 0 and {self.keypad_size.numb_of_keys - 1}") raise ValueError(f"key_numb must be between 0 and {self.keypad_size.numb_of_keys - 1}")
if not (0 <= set_idx < self.keypad_size.props_per_key): if not (0 <= set_idx < self.keypad_size.props_per_key):
raise ValueError(f"set_indices must be between 0 and {self.keypad_size.props_per_key - 1}") raise ValueError(f"padded_passcode_position_indices must be between 0 and {self.keypad_size.props_per_key - 1}")
keypad_prop_idx = self.keypad_matrix() keypad_prop_idx = self.keypad_matrix()
return int(keypad_prop_idx[key_numb][set_idx]) return int(keypad_prop_idx[key_numb][set_idx])
def get_prop_idxs_by_keynumb_setidx(self, key_numb: list[int], set_idx: list[int]) -> list[int]: def get_prop_idxs_by_keynumb_setidx(self, key_numb: list[int], set_idx: list[int]) -> list[int]:
if len(key_numb) != len(set_idx): if len(key_numb) != len(set_idx):
raise ValueError("key_numb and set_indices must be the same length") raise ValueError("key_numb and padded_passcode_position_indices must be the same length")
if not all(0 <= kn < self.keypad_size.numb_of_keys for kn in key_numb): if not all(0 <= kn < self.keypad_size.numb_of_keys for kn in key_numb):
raise ValueError(f"All key_numb must be between 0 and {self.keypad_size.numb_of_keys - 1}") raise ValueError(f"All key_numb must be between 0 and {self.keypad_size.numb_of_keys - 1}")
if not all(0 <= si < self.keypad_size.props_per_key for si in set_idx): if not all(0 <= si < self.keypad_size.props_per_key for si in set_idx):
raise ValueError(f"All set_indices must be between 0 and {self.keypad_size.props_per_key - 1}") raise ValueError(f"All padded_passcode_position_indices must be between 0 and {self.keypad_size.props_per_key - 1}")
keypad_matrix = self.keypad_matrix() keypad_matrix = self.keypad_matrix()
return keypad_matrix[key_numb, set_idx].reshape(-1).tolist() return keypad_matrix[key_numb, set_idx].reshape(-1).tolist()

View File

@@ -29,10 +29,10 @@ def test_decode_mask(keypad_size, max_nkode_len):
customer = CustomerCipher.create(keypad_size) customer = CustomerCipher.create(keypad_size)
passcode_entry = np.random.choice(keypad_size.total_props, 4, replace=False) passcode_entry = np.random.choice(keypad_size.total_props, 4, replace=False)
passcode_values = [customer.property_key[idx] for idx in passcode_entry] passcode_values = [customer.property_key[idx] for idx in passcode_entry]
set_vals = customer.position_key customer_pos_vals = customer.position_key
user_keys = UserCipher.create(keypad_size, set_vals, max_nkode_len) user_keys = UserCipher.create(keypad_size, customer_pos_vals, max_nkode_len)
passcode = user_keys.encipher_nkode(passcode_entry, customer) passcode = user_keys.encipher_nkode(passcode_entry, customer)
orig_passcode_set_vals = customer.get_props_position_vals(passcode_values) orig_passcode_pos_vals = customer.get_props_position_vals(passcode_values)
passcode_set_vals = user_keys.decipher_mask(passcode.mask, set_vals, len(passcode_entry)) passcode_pos_vals = user_keys.decipher_mask(passcode.mask, customer_pos_vals, len(passcode_entry))
assert (len(passcode_set_vals) == len(orig_passcode_set_vals)) assert (len(passcode_pos_vals) == len(orig_passcode_pos_vals))
assert (all(orig_passcode_set_vals[idx] == passcode_set_vals[idx] for idx in range(len(passcode_set_vals)))) assert (all(orig_passcode_pos_vals[idx] == passcode_pos_vals[idx] for idx in range(len(passcode_pos_vals))))