rename attribute to property

This commit is contained in:
2025-03-14 09:20:49 -05:00
parent acc5780dc4
commit c6bf401bc5
11 changed files with 225 additions and 241 deletions

View File

@@ -53,7 +53,7 @@ if __name__ == "__main__":
max_nkode_len=10, max_nkode_len=10,
min_nkode_len=4, min_nkode_len=4,
distinct_sets=0, distinct_sets=0,
distinct_attributes=4, distinct_properties=4,
byte_len=2, byte_len=2,
) )
keypad_size = KeypadSize( keypad_size = KeypadSize(
@@ -153,7 +153,7 @@ if __name__ == "__main__":
for idx in range(passcode_len): for idx in range(passcode_len):
key_numb = selected_keys_login[idx] key_numb = selected_keys_login[idx]
set_idx = set_vals_idx[idx] set_idx = set_vals_idx[idx]
selected_attr_idx = customer.users[username].user_keypad.get_attr_idx_by_keynumb_setidx(key_numb, set_idx) selected_attr_idx = customer.users[username].user_keypad.get_prop_idx_by_keynumb_setidx(key_numb, set_idx)
presumed_selected_attributes_idx.append(selected_attr_idx) presumed_selected_attributes_idx.append(selected_attr_idx)
""" """

View File

@@ -13,6 +13,7 @@
"cell_type": "code", "cell_type": "code",
"source": [ "source": [
"from src.user_keypad import UserKeypad\n", "from src.user_keypad import UserKeypad\n",
"from src.utils import random_property_rotation\n",
"from IPython.display import Markdown, display\n", "from IPython.display import Markdown, display\n",
"from src.models import KeypadSize\n", "from src.models import KeypadSize\n",
"import numpy as np\n", "import numpy as np\n",
@@ -93,10 +94,10 @@
{ {
"cell_type": "code", "cell_type": "code",
"source": [ "source": [
"attr_rotation = np.random.choice(range(keypad_size.numb_of_keys), size=keypad_size.props_per_key, replace=False)\n", "prop_rotation = np.random.choice(range(keypad_size.numb_of_keys), size=keypad_size.props_per_key, replace=False)\n",
"dispersed_interface = UserKeypad.random_attribute_rotation(\n", "dispersed_interface = random_property_rotation(\n",
" shuffled_keys,\n", " shuffled_keys,\n",
" attr_rotation\n", " prop_rotation\n",
")\n", ")\n",
"\n", "\n",
"display(Markdown(keypad_md_table(dispersed_interface.reshape(-1), keypad_size)))\n" "display(Markdown(keypad_md_table(dispersed_interface.reshape(-1), keypad_size)))\n"

View File

@@ -12,12 +12,12 @@
"metadata": { "metadata": {
"collapsed": false, "collapsed": false,
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-13T15:40:54.981894Z", "end_time": "2025-03-14T14:18:14.423890Z",
"start_time": "2025-03-13T15:40:54.975972Z" "start_time": "2025-03-14T14:18:14.420788Z"
} }
}, },
"outputs": [], "outputs": [],
"execution_count": 157 "execution_count": 23
}, },
{ {
"cell_type": "code", "cell_type": "code",
@@ -40,12 +40,12 @@
"metadata": { "metadata": {
"collapsed": false, "collapsed": false,
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-13T15:41:02.574902Z", "end_time": "2025-03-14T14:18:14.434459Z",
"start_time": "2025-03-13T15:41:02.566577Z" "start_time": "2025-03-14T14:18:14.430679Z"
} }
}, },
"outputs": [], "outputs": [],
"execution_count": 159 "execution_count": 24
}, },
{ {
"cell_type": "code", "cell_type": "code",
@@ -55,12 +55,12 @@
"metadata": { "metadata": {
"collapsed": false, "collapsed": false,
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-13T15:41:06.702836Z", "end_time": "2025-03-14T14:18:14.453086Z",
"start_time": "2025-03-13T15:41:06.697810Z" "start_time": "2025-03-14T14:18:14.451030Z"
} }
}, },
"outputs": [], "outputs": [],
"execution_count": 160 "execution_count": 25
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
@@ -70,11 +70,11 @@
"A customer defines their NKode Policy and their interface. Below we've set:\n", "A customer defines their NKode Policy and their interface. Below we've set:\n",
"- max nkode length = 10\n", "- max nkode length = 10\n",
"- min nkode length = 4\n", "- min nkode length = 4\n",
"- distinct attributes = 4\n", "- distinct properties = 4\n",
"- distinct set = 0\n", "- distinct set = 0\n",
"- byte len = 2\n", "- byte len = 2\n",
"\n", "\n",
"This customer also has an interface with 5 keys and 6 attributes per key. The number of attributes must be greater than the number of keys to be dispersion resistant." "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": { "metadata": {
"collapsed": false "collapsed": false
@@ -87,7 +87,7 @@
" 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_sets=0,\n",
" distinct_attributes=4,\n", " distinct_properties=4,\n",
" byte_len=2,\n", " byte_len=2,\n",
")\n", ")\n",
"keypad_size = KeypadSize(\n", "keypad_size = KeypadSize(\n",
@@ -100,20 +100,20 @@
"metadata": { "metadata": {
"collapsed": false, "collapsed": false,
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-13T15:41:09.768933Z", "end_time": "2025-03-14T14:18:14.461793Z",
"start_time": "2025-03-13T15:41:09.760522Z" "start_time": "2025-03-14T14:18:14.457601Z"
} }
}, },
"outputs": [], "outputs": [],
"execution_count": 161 "execution_count": 26
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"source": [ "source": [
"### NKode Customer\n", "### NKode Customer\n",
"A customer has users and defines the attributes and set values for all its users.\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 attributes per key, this gives a customer interface of 30 distinct attributes and 6 distinct attribute sets.\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 attribute belongs to one of the 6 sets." "Each properties belongs to one of the 6 sets."
], ],
"metadata": { "metadata": {
"collapsed": false "collapsed": false
@@ -121,9 +121,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"source": [ "source": "#### Customer and Properties Values",
"#### Customer and Attribute Values"
],
"metadata": { "metadata": {
"collapsed": false "collapsed": false
} }
@@ -131,19 +129,17 @@
{ {
"cell_type": "code", "cell_type": "code",
"source": [ "source": [
"set_vals = customer.cipher.set_key\n", "print(f\"Customer Set Key: {customer.cipher.set_key}\")\n",
"attr_vals = customer.cipher.prop_key\n", "print(f\"Customer properties Key:\")\n",
"print(f\"Customer Sets: {set_vals}\")\n", "customer_prop_keypad = customer.cipher.prop_key.reshape(-1, keypad_size.props_per_key)\n",
"print(f\"Customer Attributes:\")\n",
"customer_prop_keypad = attr_vals.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}\")" " print(f\"{key_vals}\")"
], ],
"metadata": { "metadata": {
"collapsed": false, "collapsed": false,
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-13T15:41:11.949505Z", "end_time": "2025-03-14T14:18:14.472200Z",
"start_time": "2025-03-13T15:41:11.941034Z" "start_time": "2025-03-14T14:18:14.469516Z"
} }
}, },
"outputs": [ "outputs": [
@@ -151,23 +147,21 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Customer Sets: [25709 8136 44044 46233 29423 25038]\n", "Customer Set Key: [57513 39162 37238 40595 30029 8573]\n",
"Customer Attributes:\n", "Customer properties Key:\n",
"[57582 3595 14389 48861 6004 53011]\n", "[14659 8841 6728 32702 39675 63074]\n",
"[ 2051 49181 8905 9645 63388 60901]\n", "[19274 15250 33729 24532 34839 38348]\n",
"[ 5952 47243 39367 26329 21337 27385]\n", "[ 2539 51139 60808 11045 55452 61221]\n",
"[ 8812 29822 227 12486 4712 16109]\n", "[55550 11904 10001 59259 26026 26740]\n",
"[28006 29445 47125 35353 35910 6662]\n" "[59910 49698 45525 62003 49414 40644]\n"
] ]
} }
], ],
"execution_count": 162 "execution_count": 27
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"source": [ "source": "#### Customer Set To Properties Map",
"#### Customer Set To Attribute Map"
],
"metadata": { "metadata": {
"collapsed": false "collapsed": false
} }
@@ -175,16 +169,16 @@
{ {
"cell_type": "code", "cell_type": "code",
"source": [ "source": [
"set_attribute_dict = dict(zip(set_vals, customer_prop_keypad.T))\n", "set_properties_dict = dict(zip(customer.cipher.set_key, customer_prop_keypad.T))\n",
"print(f\"Set to Attribute Map:\")\n", "print(f\"Set to Properties Map:\")\n",
"for set_val, attrs in set_attribute_dict.items():\n", "for set_val, attrs in set_properties_dict.items():\n",
" print(f\"{set_val}: {attrs}\")" " print(f\"{set_val}: {attrs}\")"
], ],
"metadata": { "metadata": {
"collapsed": false, "collapsed": false,
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-13T15:41:14.890303Z", "end_time": "2025-03-14T14:18:14.486583Z",
"start_time": "2025-03-13T15:41:14.883511Z" "start_time": "2025-03-14T14:18:14.484301Z"
} }
}, },
"outputs": [ "outputs": [
@@ -192,76 +186,77 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Set to Attribute Map:\n", "Set to Properties Map:\n",
"25709: [57582 2051 5952 8812 28006]\n", "57513: [14659 19274 2539 55550 59910]\n",
"8136: [ 3595 49181 47243 29822 29445]\n", "39162: [ 8841 15250 51139 11904 49698]\n",
"44044: [14389 8905 39367 227 47125]\n", "37238: [ 6728 33729 60808 10001 45525]\n",
"46233: [48861 9645 26329 12486 35353]\n", "40595: [32702 24532 11045 59259 62003]\n",
"29423: [ 6004 63388 21337 4712 35910]\n", "30029: [39675 34839 55452 26026 49414]\n",
"25038: [53011 60901 27385 16109 6662]\n" "8573: [63074 38348 61221 26740 40644]\n"
] ]
} }
], ],
"execution_count": 163 "execution_count": 28
}, },
{ {
"metadata": {},
"cell_type": "markdown", "cell_type": "markdown",
"source": [ "source": [
"### User Signup\n", "### User Signup\n",
"To create a new must call this endpoints in order:\n", "To create a new must call this endpoints in order:\n",
"1. Generate Index Interface\n", "1. Generate Keypad\n",
"2. Set User NKode\n", "2. Set User NKode\n",
"3. Confirm User NKode\n", "3. Confirm User NKode\n",
"\n", "\n",
"#### Generate Index Interface\n", "#### Generate Keypad\n",
" For the server to determine the users nkode, the user's interface must be dispersable. To make the interface dispersable, the server will randomly drop attribute sets to the number of attributes is equal to the number of keys. In our case, the server drops 1 attribute set to give us a 5 X 5 keypad with possible index values ranging from 0-29.\n", " For the server to determine the users nkode, the user's keypad must be dispersable. To make the keypad dispersable, the server will randomly drop properties sets to the number of properties is equal to the number of keys. In our case, the server drops 1 properties set to give us a 5 X 5 keypad with possible index values ranging from 0-29.\n",
" - Run the cell below over and over to see it change. Notice that values never move out of their columns just their rows.\n", " - 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 interface is the index value of a customer attribute\n", " - each value in the keypad is the index value of a customer properties\n",
" - the user never learns what their \"real\" attribute is. All they do is specify an index in the customer interface\n" " - the user never learns what their \"real\" properties is. All they do is specify an index in the customer keypad\n"
], ]
"metadata": {
"collapsed": false
}
}, },
{ {
"metadata": {
"ExecuteTime": {
"end_time": "2025-03-14T14:18:14.510067Z",
"start_time": "2025-03-14T14:18:14.507204Z"
}
},
"cell_type": "code", "cell_type": "code",
"source": [ "source": [
"session_id, signup_keypad = api.generate_signup_keypad(customer_id)\n", "session_id, signup_keypad = api.generate_signup_keypad(customer_id)\n",
"print(signup_keypad.reshape(-1, keypad_size.numb_of_keys))" "print(signup_keypad.reshape(-1, keypad_size.numb_of_keys))"
], ],
"metadata": {
"collapsed": false,
"ExecuteTime": {
"end_time": "2025-03-13T15:41:19.446496Z",
"start_time": "2025-03-13T15:41:19.440194Z"
}
},
"outputs": [ "outputs": [
{ {
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"[[21 3 27 15 9]\n", "[[ 1 7 13 19 25]\n",
" [19 1 25 13 7]\n", " [ 0 6 12 18 24]\n",
" [23 5 29 17 11]\n", " [ 5 11 17 23 29]\n",
" [22 4 28 16 10]\n", " [ 2 8 14 20 26]\n",
" [20 2 26 14 8]]\n" " [ 4 10 16 22 28]]\n"
] ]
} }
], ],
"execution_count": 164 "execution_count": 29
}, },
{ {
"metadata": {},
"cell_type": "markdown", "cell_type": "markdown",
"source": [ "source": [
"#### Set NKode\n", "#### Set nKode\n",
"The user identifies attributes in the interface they want in their nkode. Each attribute in the gui has an index value. Below the user has selected 16, 9, 6, 19. Graphically represent with anything. The only requirement is that the graphical attributes must be associated with the same index value everytime the user goes to login. If the user wants to change anything about their interface(the number of keys, attributes or graphical attributes), they must also change their nkode." "The user identifies properties in the keypad they want in their nkode. Each properties in the gui has an index value. Below the user has selected 16, 9, 6, 19. Graphically represent with anything. The only requirement is that the graphical properties must be associated with the same index value everytime the user goes to login. If the user wants to change anything about their keypad(the number of keys, properties or graphical properties), they must also change their nkode."
], ]
"metadata": {
"collapsed": false
}
}, },
{ {
"metadata": {
"ExecuteTime": {
"end_time": "2025-03-14T14:18:14.535581Z",
"start_time": "2025-03-14T14:18:14.531909Z"
}
},
"cell_type": "code", "cell_type": "code",
"source": [ "source": [
"keypad_view(signup_keypad, keypad_size.numb_of_keys)\n", "keypad_view(signup_keypad, keypad_size.numb_of_keys)\n",
@@ -272,82 +267,73 @@
"print(f\"User Passcode: {user_passcode}\")\n", "print(f\"User Passcode: {user_passcode}\")\n",
"print(f\"Selected Keys\\n{selected_keys_set}\")\n", "print(f\"Selected Keys\\n{selected_keys_set}\")\n",
"server_side_attr = [int(customer.cipher.prop_key[idx]) for idx in user_passcode]\n", "server_side_attr = [int(customer.cipher.prop_key[idx]) for idx in user_passcode]\n",
"print(f\"User Passcode Server-side Attributes: {server_side_attr}\")" "print(f\"User Passcode Server-side properties: {server_side_attr}\")"
], ],
"metadata": {
"collapsed": false,
"ExecuteTime": {
"end_time": "2025-03-13T15:41:22.138365Z",
"start_time": "2025-03-13T15:41:22.130412Z"
}
},
"outputs": [ "outputs": [
{ {
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Keypad View\n", "Keypad View\n",
"Key 0: [21 3 27 15 9]\n", "Key 0: [ 1 7 13 19 25]\n",
"Key 1: [19 1 25 13 7]\n", "Key 1: [ 0 6 12 18 24]\n",
"Key 2: [23 5 29 17 11]\n", "Key 2: [ 5 11 17 23 29]\n",
"Key 3: [22 4 28 16 10]\n", "Key 3: [ 2 8 14 20 26]\n",
"Key 4: [20 2 26 14 8]\n", "Key 4: [ 4 10 16 22 28]\n",
"User Passcode: [21 3 27 15]\n", "User Passcode: [ 1 7 13 19]\n",
"Selected Keys\n", "Selected Keys\n",
"[0, 0, 0, 0]\n", "[0, 0, 0, 0]\n",
"User Passcode Server-side Attributes: [12486, 48861, 35353, 26329]\n" "User Passcode Server-side properties: [8841, 15250, 51139, 11904]\n"
] ]
} }
], ],
"execution_count": 165 "execution_count": 30
}, },
{ {
"cell_type": "code",
"source": [
"confirm_interface = api.set_nkode(username, customer_id, selected_keys_set, session_id)\n",
"keypad_view(confirm_interface, keypad_size.numb_of_keys)\n",
"selected_keys_confirm = select_keys_with_passcode_values(user_passcode, confirm_interface, keypad_size.numb_of_keys)\n",
"print(f\"Selected Keys\\n{selected_keys_confirm}\")"
],
"metadata": { "metadata": {
"collapsed": false,
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-13T15:41:25.094831Z", "end_time": "2025-03-14T14:18:14.556541Z",
"start_time": "2025-03-13T15:41:25.087580Z" "start_time": "2025-03-14T14:18:14.553217Z"
} }
}, },
"cell_type": "code",
"source": [
"confirm_keypad = api.set_nkode(username, customer_id, selected_keys_set, session_id)\n",
"keypad_view(confirm_keypad, keypad_size.numb_of_keys)\n",
"selected_keys_confirm = select_keys_with_passcode_values(user_passcode, confirm_keypad, keypad_size.numb_of_keys)\n",
"print(f\"Selected Keys\\n{selected_keys_confirm}\")"
],
"outputs": [ "outputs": [
{ {
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Keypad View\n", "Keypad View\n",
"Key 0: [22 2 29 15 7]\n", "Key 0: [ 0 11 16 20 25]\n",
"Key 1: [23 4 27 13 8]\n", "Key 1: [ 2 6 13 22 29]\n",
"Key 2: [21 5 25 14 10]\n", "Key 2: [ 4 8 17 19 24]\n",
"Key 3: [19 3 26 16 11]\n", "Key 3: [ 1 10 12 23 26]\n",
"Key 4: [20 1 28 17 9]\n", "Key 4: [ 5 7 14 18 28]\n",
"Selected Keys\n", "Selected Keys\n",
"[2, 3, 1, 0]\n" "[3, 4, 1, 2]\n"
] ]
} }
], ],
"execution_count": 166 "execution_count": 31
}, },
{ {
"metadata": {
"ExecuteTime": {
"end_time": "2025-03-14T14:18:14.884832Z",
"start_time": "2025-03-14T14:18:14.575902Z"
}
},
"cell_type": "code", "cell_type": "code",
"source": [ "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", "# 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", "success = api.confirm_nkode(username, customer_id, selected_keys_confirm, session_id)\n",
"print(success)" "print(success)"
], ],
"metadata": {
"collapsed": false,
"ExecuteTime": {
"end_time": "2025-03-13T15:43:12.401745Z",
"start_time": "2025-03-13T15:42:59.685701Z"
}
},
"outputs": [ "outputs": [
{ {
"name": "stdout", "name": "stdout",
@@ -357,7 +343,7 @@
] ]
} }
], ],
"execution_count": 168 "execution_count": 32
}, },
{ {
"metadata": {}, "metadata": {},
@@ -376,8 +362,8 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-13T15:43:26.496044Z", "end_time": "2025-03-14T14:18:14.894865Z",
"start_time": "2025-03-13T15:43:26.484618Z" "start_time": "2025-03-14T14:18:14.889948Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -413,12 +399,12 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Passcode Set Vals: [46233, 46233, 46233, 46233]\n", "Passcode Set Vals: [39162, 39162, 39162, 39162]\n",
"Passcode Attr Vals: [12486, 48861, 35353, 26329]\n" "Passcode Attr Vals: [8841, 15250, 51139, 11904]\n"
] ]
} }
], ],
"execution_count": 169 "execution_count": 33
}, },
{ {
"metadata": {}, "metadata": {},
@@ -440,8 +426,8 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-13T15:43:30.557640Z", "end_time": "2025-03-14T14:18:14.917821Z",
"start_time": "2025-03-13T15:43:30.550158Z" "start_time": "2025-03-14T14:18:14.914851Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -455,7 +441,7 @@
"mask = user_keys.encode_base64_str(ciphered_mask)" "mask = user_keys.encode_base64_str(ciphered_mask)"
], ],
"outputs": [], "outputs": [],
"execution_count": 170 "execution_count": 34
}, },
{ {
"metadata": {}, "metadata": {},
@@ -472,8 +458,8 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-13T15:43:33.209403Z", "end_time": "2025-03-14T14:18:15.243102Z",
"start_time": "2025-03-13T15:43:32.898812Z" "start_time": "2025-03-14T14:18:14.937865Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -497,13 +483,13 @@
"code = hashed_data.decode(\"utf-8\")" "code = hashed_data.decode(\"utf-8\")"
], ],
"outputs": [], "outputs": [],
"execution_count": 171 "execution_count": 35
}, },
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-13T15:43:35.234325Z", "end_time": "2025-03-14T14:18:15.249186Z",
"start_time": "2025-03-13T15:43:35.229292Z" "start_time": "2025-03-14T14:18:15.247147Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -516,20 +502,24 @@
")" ")"
], ],
"outputs": [], "outputs": [],
"execution_count": 172 "execution_count": 36
}, },
{ {
"metadata": {},
"cell_type": "markdown", "cell_type": "markdown",
"source": [ "source": [
"### User Login\n", "### User Login\n",
"1. Get login interface\n", "1. Get login keypad\n",
"2. Login\n" "2. Login\n"
], ]
"metadata": {
"collapsed": false
}
}, },
{ {
"metadata": {
"ExecuteTime": {
"end_time": "2025-03-14T14:18:15.563030Z",
"start_time": "2025-03-14T14:18:15.257823Z"
}
},
"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",
@@ -539,30 +529,23 @@
"success = api.login(customer_id, username, selected_keys_login)\n", "success = api.login(customer_id, username, selected_keys_login)\n",
"print(success)" "print(success)"
], ],
"metadata": {
"collapsed": false,
"ExecuteTime": {
"end_time": "2025-03-13T15:43:55.881744Z",
"start_time": "2025-03-13T15:43:37.544889Z"
}
},
"outputs": [ "outputs": [
{ {
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Keypad View\n", "Keypad View\n",
"Key 0: [18 19 20 21 22 23]\n", "Key 0: [0 1 2 3 4 5]\n",
"Key 1: [0 1 2 3 4 5]\n", "Key 1: [ 6 7 8 9 10 11]\n",
"Key 2: [24 25 26 27 28 29]\n", "Key 2: [12 13 14 15 16 17]\n",
"Key 3: [12 13 14 15 16 17]\n", "Key 3: [18 19 20 21 22 23]\n",
"Key 4: [ 6 7 8 9 10 11]\n", "Key 4: [24 25 26 27 28 29]\n",
"Selected Keys: [0, 1, 2, 3]\n", "Selected Keys: [0, 1, 2, 3]\n",
"True\n" "True\n"
] ]
} }
], ],
"execution_count": 173 "execution_count": 37
}, },
{ {
"metadata": {}, "metadata": {},
@@ -570,8 +553,8 @@
"source": [ "source": [
"## Validate Login Key Entry\n", "## Validate Login Key Entry\n",
"- decipher user mask and recover nkode set values\n", "- decipher user mask and recover nkode set values\n",
"- get presumed attribute from key selection and set values\n", "- get presumed properties from key selection and set values\n",
"- encipher, salt and hash presumed attribute values and compare it to the users hashed code" "- encipher, salt and hash presumed properties values and compare it to the users hashed code"
] ]
}, },
{ {
@@ -594,8 +577,8 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-13T15:44:12.223540Z", "end_time": "2025-03-14T14:18:15.574718Z",
"start_time": "2025-03-13T15:44:12.215204Z" "start_time": "2025-03-14T14:18:15.571571Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -615,36 +598,36 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"[46233, 46233, 46233, 46233]\n" "[39162, 39162, 39162, 39162]\n"
] ]
} }
], ],
"execution_count": 174 "execution_count": 38
}, },
{ {
"metadata": {}, "metadata": {},
"cell_type": "markdown", "cell_type": "markdown",
"source": "### Get Presumed Attributes\n" "source": "### Get Presumed Properties\n"
}, },
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-13T15:44:41.027416Z", "end_time": "2025-03-14T14:18:15.591180Z",
"start_time": "2025-03-13T15:44:15.077074Z" "start_time": "2025-03-14T14:18:15.587992Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
"source": [ "source": [
"set_vals_idx = [customer.cipher.get_set_index(set_val) for set_val in passcode_sets]\n", "set_vals_idx = [customer.cipher.get_set_index(set_val) for set_val in passcode_sets]\n",
"\n", "\n",
"presumed_selected_attributes_idx = []\n", "presumed_selected_properties_idx = []\n",
"for idx in range(passcode_len):\n", "for idx in range(passcode_len):\n",
" key_numb = selected_keys_login[idx]\n", " key_numb = selected_keys_login[idx]\n",
" set_idx = set_vals_idx[idx]\n", " set_idx = set_vals_idx[idx]\n",
" selected_attr_idx = customer.users[username].user_keypad.get_attr_idx_by_keynumb_setidx(key_numb, set_idx)\n", " selected_attr_idx = customer.users[username].user_keypad.get_prop_idx_by_keynumb_setidx(key_numb, set_idx)\n",
" presumed_selected_attributes_idx.append(selected_attr_idx)\n", " presumed_selected_properties_idx.append(selected_attr_idx)\n",
"\n", "\n",
"print(user_passcode.tolist() == presumed_selected_attributes_idx)" "print(user_passcode.tolist() == presumed_selected_properties_idx)"
], ],
"outputs": [ "outputs": [
{ {
@@ -655,7 +638,7 @@
] ]
} }
], ],
"execution_count": 175 "execution_count": 39
}, },
{ {
"metadata": {}, "metadata": {},
@@ -665,13 +648,13 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-13T15:48:46.158380Z", "end_time": "2025-03-14T14:18:15.916787Z",
"start_time": "2025-03-13T15:48:45.854570Z" "start_time": "2025-03-14T14:18:15.610843Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
"source": [ "source": [
"enciphered_nkode = user.cipher.encipher_salt_hash_code(presumed_selected_attributes_idx, customer.cipher)\n", "enciphered_nkode = user.cipher.encipher_salt_hash_code(presumed_selected_properties_idx, customer.cipher)\n",
"print(enciphered_nkode == user.enciphered_passcode.code)\n" "print(enciphered_nkode == user.enciphered_passcode.code)\n"
], ],
"outputs": [ "outputs": [
@@ -683,26 +666,24 @@
] ]
} }
], ],
"execution_count": 178 "execution_count": 40
}, },
{ {
"metadata": {},
"cell_type": "markdown", "cell_type": "markdown",
"source": [ "source": [
"## Renew Attributes \n", "## Renew Properties\n",
"1. Renew Customer Attributes \n", "1. Renew Customer Properties\n",
"2. Renew User Keys\n", "2. Renew User Keys\n",
"3. Refresh User on Login\n", "3. Refresh User on Login\n",
"\n" "\n"
], ]
"metadata": {
"collapsed": false
}
}, },
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-13T15:50:03.065695Z", "end_time": "2025-03-14T14:18:16.539065Z",
"start_time": "2025-03-13T15:50:02.452807Z" "start_time": "2025-03-14T14:18:15.926843Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -713,7 +694,7 @@
" print(f\"mask: {mask}, code: {code}\")\n", " print(f\"mask: {mask}, code: {code}\")\n",
"\n", "\n",
"print_user_enciphered_code() \n", "print_user_enciphered_code() \n",
"api.renew_attributes(customer_id)\n", "api.renew_keys(customer_id)\n",
"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",
@@ -727,29 +708,29 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"mask: Veawti5Qkgy2y/XtFTZZ7w5oYgA=, code: $2b$12$OHHiqL888FauxiXIVICtouT1xR8iwe79oz63mXkPWKldHoLHPsByy\n", "mask: 4NCIa/fFtx0udGaF1ub+O/6oU04=, code: $2b$12$XuGO.allDcb91peVIjwsq./Ba/TZI3wxAc0acgWkApzkzGWfwPQCC\n",
"mask: Veawti5Qkgy2y/XtFTZZ7w5oYgA=, code: $2b$12$OHHiqL888FauxiXIVICtouT1xR8iwe79oz63mXkPWKldHoLHPsByy\n", "mask: 4NCIa/fFtx0udGaF1ub+O/6oU04=, code: $2b$12$XuGO.allDcb91peVIjwsq./Ba/TZI3wxAc0acgWkApzkzGWfwPQCC\n",
"True\n", "True\n",
"mask: Sxe3AjutJzGrQLgq/RnfK9G3wHc=, code: $2b$12$.wb5cZjbXJBY6/MQxJIlGu/JyqaF78IM.1n3QP6coxOcKLORU/Io6\n" "mask: ceaWZR+hNRpEkj3fq1cfPu1Zyok=, code: $2b$12$q7lqdTj6qBMDDGEog9Pq3.M2Wso0TI8cx4/PhOK/fE1mhsws2FGe.\n"
] ]
} }
], ],
"execution_count": 179 "execution_count": 41
}, },
{ {
"metadata": {}, "metadata": {},
"cell_type": "markdown", "cell_type": "markdown",
"source": [ "source": [
"#### Renew Customer Keys\n", "#### Renew Customer Keys\n",
"- Get old attributes and sets\n", "- Get old properties and sets\n",
"- Replace attributes and sets" "- Replace properties and sets"
] ]
}, },
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-13T15:52:30.906955Z", "end_time": "2025-03-14T14:18:16.551437Z",
"start_time": "2025-03-13T15:52:30.902577Z" "start_time": "2025-03-14T14:18:16.547371Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -761,7 +742,7 @@
"new_sets = customer.cipher.set_key" "new_sets = customer.cipher.set_key"
], ],
"outputs": [], "outputs": [],
"execution_count": 181 "execution_count": 42
}, },
{ {
"metadata": {}, "metadata": {},
@@ -774,8 +755,8 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-13T15:52:39.513715Z", "end_time": "2025-03-14T14:18:16.568881Z",
"start_time": "2025-03-13T15:52:39.510395Z" "start_time": "2025-03-14T14:18:16.566223Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -788,7 +769,7 @@
" user.cipher.prop_key = np.bitwise_xor(user.cipher.prop_key, props_xor)" " user.cipher.prop_key = np.bitwise_xor(user.cipher.prop_key, props_xor)"
], ],
"outputs": [], "outputs": [],
"execution_count": 182 "execution_count": 43
}, },
{ {
"metadata": {}, "metadata": {},
@@ -798,8 +779,8 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-13T15:53:22.653638Z", "end_time": "2025-03-14T14:18:16.884432Z",
"start_time": "2025-03-13T15:53:22.345351Z" "start_time": "2025-03-14T14:18:16.572989Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -809,11 +790,11 @@
" customer.cipher.set_key,\n", " customer.cipher.set_key,\n",
" user.cipher.max_nkode_len\n", " user.cipher.max_nkode_len\n",
")\n", ")\n",
"user.enciphered_passcode = user.cipher.encipher_nkode(presumed_selected_attributes_idx, customer.cipher)\n", "user.enciphered_passcode = user.cipher.encipher_nkode(presumed_selected_properties_idx, customer.cipher)\n",
"user.renew = False" "user.renew = False"
], ],
"outputs": [], "outputs": [],
"execution_count": 186 "execution_count": 44
} }
], ],
"metadata": { "metadata": {

View File

@@ -34,46 +34,46 @@ class Customer:
user.enciphered_passcode.mask, self.cipher.set_key, passcode_len) user.enciphered_passcode.mask, self.cipher.set_key, passcode_len)
set_vals_idx = [self.cipher.get_set_index(set_val) for set_val in passcode_set_vals] set_vals_idx = [self.cipher.get_set_index(set_val) for set_val in passcode_set_vals]
presumed_selected_attributes_idx = [] presumed_property_idxs = []
for idx in range(passcode_len): for idx in range(passcode_len):
key_numb = selected_keys[idx] key_numb = selected_keys[idx]
set_idx = set_vals_idx[idx] set_idx = set_vals_idx[idx]
selected_attr_idx = user.user_keypad.get_attr_idx_by_keynumb_setidx(key_numb, set_idx) selected_attr_idx = user.user_keypad.get_prop_idx_by_keynumb_setidx(key_numb, set_idx)
presumed_selected_attributes_idx.append(selected_attr_idx) presumed_property_idxs.append(selected_attr_idx)
enciphered_attr = user.cipher.encipher_salt_hash_code(presumed_selected_attributes_idx, self.cipher) enciphered_attr = user.cipher.encipher_salt_hash_code(presumed_property_idxs, self.cipher)
if enciphered_attr != user.enciphered_passcode.code: if enciphered_attr != user.enciphered_passcode.code:
return False return False
if user.renew: if user.renew:
user.refresh_passcode(presumed_selected_attributes_idx, self.cipher) user.refresh_passcode(presumed_property_idxs, self.cipher)
return True return True
def renew_keys(self) -> bool: def renew_keys(self) -> bool:
old_attrs = self.cipher.prop_key.copy() old_props = self.cipher.prop_key.copy()
old_sets = self.cipher.set_key.copy() old_sets = self.cipher.set_key.copy()
self.cipher.renew() self.cipher.renew()
new_attrs = self.cipher.prop_key new_props = self.cipher.prop_key
new_sets = self.cipher.set_key new_sets = self.cipher.set_key
attrs_xor = np.bitwise_xor(new_attrs, old_attrs) props_xor = np.bitwise_xor(new_props, old_props)
set_xor = np.bitwise_xor(new_sets, old_sets) set_xor = np.bitwise_xor(new_sets, old_sets)
for user in self.users.values(): for user in self.users.values():
user.renew_keys(set_xor, attrs_xor) user.renew_keys(set_xor, props_xor)
self.users[user.username] = user self.users[user.username] = user
return True return True
def valid_new_nkode(self, passcode_attr_idx: list[int]) -> bool: def valid_new_nkode(self, passcode_prop_idx: list[int]) -> bool:
nkode_len = len(passcode_attr_idx) nkode_len = len(passcode_prop_idx)
passcode_set_values = [ passcode_set_values = [
self.cipher.get_prop_set_val(int(self.cipher.prop_key[attr_idx])) for attr_idx in passcode_attr_idx self.cipher.get_prop_set_val(int(self.cipher.prop_key[prop_idx])) for prop_idx in passcode_prop_idx
] ]
distinct_sets = len(set(passcode_set_values)) distinct_sets = len(set(passcode_set_values))
distinct_attributes = len(set(passcode_attr_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_sets and
distinct_attributes >= self.nkode_policy.distinct_attributes distinct_properties >= self.nkode_policy.distinct_properties
): ):
return True return True
return False return False

View File

@@ -11,7 +11,7 @@ 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_sets: int = 0
distinct_attributes: int = 4 distinct_properties: int = 4
byte_len: int = 2 # Todo: this should change the total number of bytes an attribute or set value can be byte_len: int = 2 # Todo: this should change the total number of bytes an attribute or set value can be
lock_out: int = 5 lock_out: int = 5
expiration: int = -1 # in seconds -1 means nkode never expires expiration: int = -1 # in seconds -1 means nkode never expires

View File

@@ -107,7 +107,7 @@ class NKodeAPI:
customer = self.customers[customer_id] customer = self.customers[customer_id]
return customer.valid_key_entry(username, key_selection) return customer.valid_key_entry(username, key_selection)
def renew_attributes(self, customer_id: UUID) -> bool: def renew_keys(self, customer_id: UUID) -> bool:
if customer_id not in self.customers.keys(): if customer_id not in self.customers.keys():
raise ValueError("Customer ID not found") raise ValueError("Customer ID not found")
return self.customers[customer_id].renew_keys() return self.customers[customer_id].renew_keys()

View File

@@ -21,11 +21,11 @@ class User:
self.cipher.set_key = np.bitwise_xor(self.cipher.set_key, set_xor) self.cipher.set_key = np.bitwise_xor(self.cipher.set_key, set_xor)
self.cipher.prop_key = np.bitwise_xor(self.cipher.prop_key, prop_xor) self.cipher.prop_key = np.bitwise_xor(self.cipher.prop_key, prop_xor)
def refresh_passcode(self, passcode_attr_idx: list[int], customer_attributes: CustomerCipher): def refresh_passcode(self, passcode_prop_idxs: list[int], customer_cipher: CustomerCipher):
self.cipher = UserCipher.create( self.cipher = UserCipher.create(
customer_attributes.keypad_size, customer_cipher.keypad_size,
customer_attributes.set_key, customer_cipher.set_key,
self.cipher.max_nkode_len self.cipher.max_nkode_len
) )
self.enciphered_passcode = self.cipher.encipher_nkode(passcode_attr_idx, customer_attributes) self.enciphered_passcode = self.cipher.encipher_nkode(passcode_prop_idxs, customer_cipher)
self.renew = False self.renew = False

View File

@@ -1,5 +1,6 @@
from dataclasses import dataclass from dataclasses import dataclass
import numpy as np import numpy as np
from src.utils import random_property_rotation
from src.models import KeypadSize from src.models import KeypadSize
@dataclass @dataclass
@@ -54,9 +55,9 @@ class UserKeypad:
user_keypad_matrix = self.keypad_matrix() user_keypad_matrix = self.keypad_matrix()
#shuffled_keys = secure_fisher_yates_shuffle(user_keypad_matrix) #shuffled_keys = secure_fisher_yates_shuffle(user_keypad_matrix)
shuffled_keys = rng.permutation(user_keypad_matrix, axis=0) shuffled_keys = rng.permutation(user_keypad_matrix, axis=0)
#attr_rotation = secure_fisher_yates_shuffle(list(range(self.keypad_size.numb_of_keys)))[:self.keypad_size.props_per_key] #prop_rotation = secure_fisher_yates_shuffle(list(range(self.keypad_size.numb_of_keys)))[:self.keypad_size.props_per_key]
attr_rotation = rng.permutation(list(range(self.keypad_size.numb_of_keys)))[:self.keypad_size.props_per_key] attr_rotation = rng.permutation(list(range(self.keypad_size.numb_of_keys)))[:self.keypad_size.props_per_key]
dispersed_keypad = self.random_attribute_rotation( dispersed_keypad = random_property_rotation(
shuffled_keys, shuffled_keys,
attr_rotation.tolist(), attr_rotation.tolist(),
) )
@@ -79,21 +80,8 @@ class UserKeypad:
#self.keypad = matrix_to_list(matrix_transpose(keypad_by_sets)) #self.keypad = matrix_to_list(matrix_transpose(keypad_by_sets))
pass pass
@staticmethod
def random_attribute_rotation(
user_keypad: np.ndarray,
attr_rotation: list[int]
) -> np.ndarray:
transposed = user_keypad.T
if len(attr_rotation) != len(transposed):
raise ValueError("attr_rotation must be the same length as the number of attributes")
for idx, attr_set in enumerate(transposed):
rotation = attr_rotation[idx]
rotation = rotation % len(attr_set) if len(attr_set) > 0 else 0
transposed[idx] = np.roll(attr_set, rotation)
return transposed.T
def attribute_adjacency_graph(self) -> dict[int, set[int]]: def property_adjacency_graph(self) -> dict[int, set[int]]:
user_keypad_keypad = self.keypad_matrix() user_keypad_keypad = self.keypad_matrix()
graph = {} graph = {}
for key in user_keypad_keypad: for key in user_keypad_keypad:
@@ -102,7 +90,7 @@ class UserKeypad:
graph[attr].remove(attr) graph[attr].remove(attr)
return graph return graph
def get_attr_idx_by_keynumb_setidx(self, key_numb: int, set_idx: int) -> int: def get_prop_idx_by_keynumb_setidx(self, key_numb: int, set_idx: int) -> int:
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):

14
src/utils.py Normal file
View File

@@ -0,0 +1,14 @@
import numpy as np
def random_property_rotation(
user_keypad: np.ndarray,
attr_rotation: list[int]
) -> np.ndarray:
transposed = user_keypad.T
if len(attr_rotation) != len(transposed):
raise ValueError("prop_rotation must be the same length as the number of attributes")
for idx, attr_set in enumerate(transposed):
rotation = attr_rotation[idx]
rotation = rotation % len(attr_set) if len(attr_set) > 0 else 0
transposed[idx] = np.roll(attr_set, rotation)
return transposed.T

View File

@@ -39,7 +39,7 @@ def test_create_new_user_and_renew_keys(nkode_api, keypad_size, passocode_len):
successful_login = nkode_api.login(customer_id, username, login_key_selection) successful_login = nkode_api.login(customer_id, username, login_key_selection)
assert successful_login assert successful_login
successful_renew = nkode_api.renew_attributes(customer_id) successful_renew = nkode_api.renew_keys(customer_id)
assert successful_renew assert successful_renew
login_keypad = nkode_api.get_login_keypad(username, customer_id) login_keypad = nkode_api.get_login_keypad(username, customer_id)

View File

@@ -10,9 +10,9 @@ def user_keypad():
def test_dispersion(user_keypad): def test_dispersion(user_keypad):
for _ in range(10000): for _ in range(10000):
pre_dispersion_graph = user_keypad.attribute_adjacency_graph() pre_dispersion_graph = user_keypad.property_adjacency_graph()
user_keypad.disperse_keypad() user_keypad.disperse_keypad()
post_dispersion_graph = user_keypad.attribute_adjacency_graph() post_dispersion_graph = user_keypad.property_adjacency_graph()
for attr, adj_graph in pre_dispersion_graph.items(): for attr, adj_graph in pre_dispersion_graph.items():
assert (adj_graph.isdisjoint(post_dispersion_graph[attr])) assert (adj_graph.isdisjoint(post_dispersion_graph[attr]))