diff --git a/docs/enrollment_diagram.md b/docs/enrollment_diagram.md
new file mode 100644
index 0000000..e6c52bd
--- /dev/null
+++ b/docs/enrollment_diagram.md
@@ -0,0 +1,37 @@
+# nKode Enrollment
+```mermaid
+sequenceDiagram
+ participant User
+ participant Client
+ participant Server
+ Note over User,Client: Enrollment
+ Client->>User: Signup Form
+ Note left of User: email: user@example.com
+ User->>Client: Submit Email
+ Client->>+Server: Signup Session: user@example.com
+ Server->>Server: Create Signup Session
+ Note over User,Client: Set nKode
+ Server-->>-Client: signup_session_id, set_keypad, icons
+ Note left of Server: signup_session_id:
92a2a1c6-3146-4d47-ac00-5160a7ebf104
+ Note left of Server: set_keypad:
Key 0: [ 7 14 3 28 23]
Key 1: [ 1 26 15 10 5]
Key 2: [13 20 27 4 29]
Key 3: [25 8 21 16 11]
Key 4: [19 2 9 22 17]
+ Note left of Server: Icons:
[😀,😂,🥳,😍,🤓
😎,🥺,😡,😱,🤯
🥰,😴,🤔,🙃,😇
🤖,👽,👾,🐱,🐶
🦁,🐻,🐸,🐙,🦄
🌟,⚡,🔥,🍕,🎉]
+ Client->>Client: Order Icons by keypad
+ Client->>User: Display Keypad
+ Note left of Client: Key 0: ['😡' '😇' '😍' '🍕' '🐙']
Key 1: ['😂' '⚡' '🤖' '🥰' '😎']
Key 2: ['🙃' '🦁' '🔥' '🤓' '🎉']
Key 3: ['🌟' '😱' '🐻' '👽' '😴']
Key 4: ['🐶' '🥳' '🤯' '🐸' '👾']
+ Note left of User: User icons: ['😍' '🤓' '😇' '😡']
+ User->>Client: Set Key Selection: [0, 2, 0, 0]
+ Client->>+Server: Set nKode:
92a2a1c6-3146-4d47-ac00-5160a7ebf104
[0, 2, 0, 0]
+ Server->>Server: Disperse Set Keypad
+ Note over User,Client: Confirm nKode
+ Server-->>-Client: signup_session_id, confirm_keypad, icons
+ Note left of Server: signup_session_id:
92a2a1c6-3146-4d47-ac00-5160a7ebf104
+ Note left of Server: confirm_keypad:
Key 0: [ 7 26 21 4 17]
Key 1: [19 20 3 16 5]
Key 2: [ 1 8 9 28 29]
Key 3: [13 14 15 22 11]
Key 4: [25 2 27 10 23]
+ Client->>Client: Order Icons by keypad
+ Client->>User: Display Keypad
+ Note left of Client: Key 0: ['😡' '⚡' '🐻' '🤓' '👾']
Key 1: ['🐶' '🦁' '😍' '👽' '😎']
Key 2: ['😂' '😱' '🤯' '🍕' '🎉']
Key 3: ['🙃' '😇' '🤖' '🐸' '😴']
Key 4: ['🌟' '🥳' '🔥' '🥰' '🐙']
+ Note left of User: User icons: ['😍' '🤓' '😇' '😡']
+ User->>Client: Key Selection: [1, 0, 3, 0]
+ Client->>+Server: Confirm nKode:
92a2a1c6-3146-4d47-ac00-5160a7ebf104
[1, 0, 3, 0]
+ Server->>Server: Create User
+ Server-->-Client: Success
+```
\ No newline at end of file
diff --git a/docs/enrollment_diagram.template.md b/docs/enrollment_diagram.template.md
new file mode 100644
index 0000000..e2c239c
--- /dev/null
+++ b/docs/enrollment_diagram.template.md
@@ -0,0 +1,37 @@
+# nKode Enrollment
+```mermaid
+sequenceDiagram
+ participant User
+ participant Client
+ participant Server
+ Note over User,Client: Enrollment
+ Client->>User: Signup Form
+ Note left of User: email: {{ email }}
+ User->>Client: Submit Email
+ Client->>+Server: Signup Session: {{ email }}
+ Server->>Server: Create Signup Session
+ Note over User,Client: Set nKode
+ Server-->>-Client: signup_session_id, set_keypad, icons
+ Note left of Server: signup_session_id:
{{ signup_session_id }}
+ Note left of Server: set_keypad:
{{set_keypad}}
+ Note left of Server: Icons:
{{icon_matrix}}
+ Client->>Client: Order Icons by keypad
+ Client->>User: Display Keypad
+ Note left of Client: {{ ordered_keypad }}
+ Note left of User: User icons: {{ passcode_user_icons }}
+ User->>Client: Set Key Selection: {{ selected_keys_set }}
+ Client->>+Server: Set nKode:
{{ signup_session_id }}
{{ selected_keys_set }}
+ Server->>Server: Disperse Set Keypad
+ Note over User,Client: Confirm nKode
+ Server-->>-Client: signup_session_id, confirm_keypad, icons
+ Note left of Server: signup_session_id:
{{ signup_session_id }}
+ Note left of Server: confirm_keypad:
{{confirm_keypad}}
+ Client->>Client: Order Icons by keypad
+ Client->>User: Display Keypad
+ Note left of Client: {{ confirm_ordered_keypad }}
+ Note left of User: User icons: {{ passcode_user_icons }}
+ User->>Client: Key Selection: {{ confirm_key_selection }}
+ Client->>+Server: Confirm nKode:
{{ signup_session_id }}
{{ confirm_key_selection }}
+ Server->>Server: Create User
+ Server-->-Client: Success
+```
\ No newline at end of file
diff --git a/docs/render_enrollment_md.py b/docs/render_enrollment_md.py
new file mode 100644
index 0000000..e5e7221
--- /dev/null
+++ b/docs/render_enrollment_md.py
@@ -0,0 +1,107 @@
+# Render markdown template for nKode enrollment
+from pathlib import Path
+
+import numpy as np
+from jinja2 import Environment, FileSystemLoader, select_autoescape
+from secrets import choice
+from string import ascii_lowercase
+from src.models import NKodePolicy, KeypadSize
+from src.nkode_api import NKodeAPI
+from src.utils import select_keys_with_passcode_values
+
+
+def render_markdown_template(template_path, output_path, context):
+ """
+ Render a Jinja2 markdown template with the given context and save to output_path.
+
+ Args:
+ template_path (Path): Path to the template file
+ output_path (Path): Path where the rendered file will be saved
+ context (dict): Template variables
+ """
+ template_dir = template_path.parent
+ template_file = template_path.name
+
+ env = Environment(
+ loader=FileSystemLoader(template_dir),
+ autoescape=select_autoescape(['html', 'xml']),
+ trim_blocks=True,
+ lstrip_blocks=True
+ )
+
+ template = env.get_template(template_file)
+ rendered = template.render(**context)
+
+ with open(output_path, 'w') as f:
+ f.write(rendered)
+
+ print(f"Template rendered to {output_path}")
+
+
+def display_icons(icons_array: np.ndarray, kp: KeypadSize) -> str:
+ icons = "["
+ for row in icons_array.reshape(-1, kp.numb_of_keys):
+ icons += ",".join(row)
+ icons += "
"
+ icons = icons[:-5]
+ icons += "]"
+ return icons
+
+def display_icons_keypad(icons_array: np.ndarray, kp: KeypadSize) -> str:
+ icons = ""
+ for idx, row in enumerate(icons_array.reshape(-1, kp.numb_of_keys)):
+ icons += f"Key {idx}: "
+ icons += str(row)
+ icons += "
"
+ return icons
+
+if __name__ == "__main__":
+ api = NKodeAPI()
+ user_icons = np.array([
+ "😀", "😂", "🥳", "😍", "🤓",
+ "😎", "🥺", "😡", "😱", "🤯",
+ "🥰", "😴", "🤔", "🙃", "😇",
+ "🤖", "👽", "👾", "🐱", "🐶",
+ "🦁", "🐻", "🐸", "🐙", "🦄",
+ "🌟", "⚡", "🔥", "🍕", "🎉"
+ ])
+ policy = NKodePolicy(
+ max_nkode_len=10,
+ min_nkode_len=4,
+ distinct_positions=0,
+ distinct_properties=4,
+ )
+ keypad_size = KeypadSize(
+ numb_of_keys=5,
+ props_per_key=6
+ )
+ customer_id = api.create_new_customer(keypad_size, policy)
+ signup_session_id, set_signup_keypad = api.generate_signup_keypad(customer_id)
+ ordered_set_icons = user_icons[set_signup_keypad]
+ username = "test_username" + "".join([choice(ascii_lowercase) for _ in range(6)])
+ passcode_len = 4
+ passcode_property_indices = np.random.choice(set_signup_keypad.reshape(-1), size=passcode_len,
+ replace=False).tolist()
+ selected_keys_set = select_keys_with_passcode_values(passcode_property_indices, set_signup_keypad,
+ keypad_size.numb_of_keys)
+ confirm_keypad = api.set_nkode(username, customer_id, selected_keys_set, signup_session_id)
+ selected_keys_confirm = select_keys_with_passcode_values(passcode_property_indices, confirm_keypad,
+ keypad_size.numb_of_keys)
+ ordered_confirm_icons = user_icons[confirm_keypad]
+ print(f"Selected Keys\n{selected_keys_confirm}")
+ success = api.confirm_nkode(username, customer_id, selected_keys_confirm, signup_session_id)
+ context = {
+ "email": "user@example.com",
+ "signup_session_id": signup_session_id,
+ "set_keypad": display_icons_keypad(set_signup_keypad.reshape(-1, keypad_size.numb_of_keys), keypad_size),
+ "icon_matrix": display_icons(user_icons, keypad_size),
+ "ordered_keypad": display_icons_keypad(ordered_set_icons, keypad_size),
+ "passcode_user_icons": str(user_icons[passcode_property_indices]),
+ "selected_keys_set": str(selected_keys_set),
+ "confirm_keypad": display_icons_keypad(confirm_keypad.reshape(-1, keypad_size.numb_of_keys), keypad_size),
+ "confirm_ordered_keypad": display_icons_keypad(ordered_confirm_icons.reshape(-1, keypad_size.numb_of_keys), keypad_size),
+ "confirm_key_selection": selected_keys_confirm
+ }
+
+ # Render the template
+ render_markdown_template(Path("./enrollment_diagram.template.md"), Path("./enrollment_diagram.md"), context)
\ No newline at end of file
diff --git a/notebooks/Enrollment_Login_Renewal.ipynb b/notebooks/Enrollment_Login_Renewal.ipynb
index af5515d..eed046a 100644
--- a/notebooks/Enrollment_Login_Renewal.ipynb
+++ b/notebooks/Enrollment_Login_Renewal.ipynb
@@ -8,6 +8,7 @@
"sys.path.append(os.path.abspath('..')) # Adds the parent directory to path\n",
"from src.nkode_api import NKodeAPI\n",
"from src.models import NKodePolicy, KeypadSize\n",
+ "from src.utils import select_keys_with_passcode_values\n",
"from secrets import choice\n",
"from string import ascii_lowercase\n",
"import numpy as np\n",
@@ -20,11 +21,6 @@
" return \"test_username\" + \"\".join([choice(ascii_lowercase) for _ in range(6)])\n",
"\n",
"\n",
- "def select_keys_with_passcode_values(user_passcode_idxs: list[int], keypad: np.ndarray, props_per_key: int) -> list[int]:\n",
- " indices = [np.where(keypad == prop)[0][0] for prop in user_passcode_idxs]\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",
" interface_keypad = keypad.reshape(-1, props_per_key)\n",
" for idx, key_vals in enumerate(interface_keypad):\n",
@@ -33,12 +29,12 @@
"metadata": {
"collapsed": false,
"ExecuteTime": {
- "end_time": "2025-03-20T15:13:44.080558Z",
- "start_time": "2025-03-20T15:13:44.076372Z"
+ "end_time": "2025-03-24T09:48:10.442598Z",
+ "start_time": "2025-03-24T09:48:10.410209Z"
}
},
"outputs": [],
- "execution_count": 41
+ "execution_count": 1
},
{
"cell_type": "code",
@@ -56,12 +52,12 @@
"metadata": {
"collapsed": false,
"ExecuteTime": {
- "end_time": "2025-03-20T15:13:44.090939Z",
- "start_time": "2025-03-20T15:13:44.088281Z"
+ "end_time": "2025-03-24T09:48:10.450851Z",
+ "start_time": "2025-03-24T09:48:10.448737Z"
}
},
"outputs": [],
- "execution_count": 42
+ "execution_count": 2
},
{
"metadata": {},
@@ -115,8 +111,8 @@
"metadata": {
"collapsed": false,
"ExecuteTime": {
- "end_time": "2025-03-20T15:13:44.107060Z",
- "start_time": "2025-03-20T15:13:44.100773Z"
+ "end_time": "2025-03-24T09:48:10.468165Z",
+ "start_time": "2025-03-24T09:48:10.456820Z"
}
},
"outputs": [
@@ -124,30 +120,30 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "Customer Position Key: [22504 45127 46010 30773 46509 63084]\n",
+ "Customer Position Key: [ 4136 64524 15410 9988 20496 18918]\n",
"Customer Properties Key:\n",
- "[38076 5253 43656 24035 57980 18197]\n",
- "[56754 21362 27799 42374 57145 46164]\n",
- "[56031 10476 13741 23847 57450 42577]\n",
- "[63205 55476 58864 29925 9463 58182]\n",
- "[61997 24583 9269 19956 55576 32892]\n",
+ "[46103 19687 10938 59248 5143 27050]\n",
+ "[26684 7431 59668 28699 6929 18710]\n",
+ "[12853 35476 62914 24111 36473 25394]\n",
+ "[63988 14898 1879 44350 53666 23249]\n",
+ "[23805 45848 21514 8782 7583 36157]\n",
"Position to Properties Map:\n",
- "22504: [38076 56754 56031 63205 61997]\n",
- "45127: [ 5253 21362 10476 55476 24583]\n",
- "46010: [43656 27799 13741 58864 9269]\n",
- "30773: [24035 42374 23847 29925 19956]\n",
- "46509: [57980 57145 57450 9463 55576]\n",
- "63084: [18197 46164 42577 58182 32892]\n"
+ "4136: [46103 26684 12853 63988 23805]\n",
+ "64524: [19687 7431 35476 14898 45848]\n",
+ "15410: [10938 59668 62914 1879 21514]\n",
+ "9988: [59248 28699 24111 44350 8782]\n",
+ "20496: [ 5143 6929 36473 53666 7583]\n",
+ "18918: [27050 18710 25394 23249 36157]\n"
]
}
],
- "execution_count": 43
+ "execution_count": 3
},
{
"metadata": {
"ExecuteTime": {
- "end_time": "2025-03-20T15:13:44.127687Z",
- "start_time": "2025-03-20T15:13:44.125028Z"
+ "end_time": "2025-03-24T09:48:10.593687Z",
+ "start_time": "2025-03-24T09:48:10.591235Z"
}
},
"cell_type": "code",
@@ -164,16 +160,16 @@
"output_type": "stream",
"text": [
"Position Value to Icons Map:\n",
- "22504: ['😀' '🥺' '🤔' '🐱' '🦄']\n",
- "45127: ['😂' '😡' '🙃' '🐶' '🌟']\n",
- "46010: ['🥳' '😱' '😇' '🦁' '⚡']\n",
- "30773: ['😍' '🤯' '🤖' '🐻' '🔥']\n",
- "46509: ['🤓' '🥰' '👽' '🐸' '🍕']\n",
- "63084: ['😎' '😴' '👾' '🐙' '🎉']\n"
+ "4136: ['😀' '🥺' '🤔' '🐱' '🦄']\n",
+ "64524: ['😂' '😡' '🙃' '🐶' '🌟']\n",
+ "15410: ['🥳' '😱' '😇' '🦁' '⚡']\n",
+ "9988: ['😍' '🤯' '🤖' '🐻' '🔥']\n",
+ "20496: ['🤓' '🥰' '👽' '🐸' '🍕']\n",
+ "18918: ['😎' '😴' '👾' '🐙' '🎉']\n"
]
}
],
- "execution_count": 44
+ "execution_count": 4
},
{
"metadata": {},
@@ -197,8 +193,8 @@
{
"metadata": {
"ExecuteTime": {
- "end_time": "2025-03-20T15:13:44.156638Z",
- "start_time": "2025-03-20T15:13:44.150222Z"
+ "end_time": "2025-03-24T09:48:10.653252Z",
+ "start_time": "2025-03-24T09:48:10.646267Z"
}
},
"cell_type": "code",
@@ -226,11 +222,11 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "Key 0: ['🦄' '🦁' '🐻' '🤓' '👾']\n",
- "Key 1: ['🥺' '⚡' '🔥' '🍕' '🎉']\n",
- "Key 2: ['🐱' '😱' '🤖' '👽' '🐙']\n",
- "Key 3: ['😀' '🥳' '😍' '🐸' '😴']\n",
- "Key 4: ['🤔' '😇' '🤯' '🥰' '😎']\n"
+ "Key 0: ['😂' '🥳' '🐻' '🍕' '😎']\n",
+ "Key 1: ['🐶' '⚡' '🤖' '🥰' '🎉']\n",
+ "Key 2: ['🌟' '😇' '😍' '🤓' '🐙']\n",
+ "Key 3: ['😡' '😱' '🔥' '👽' '😴']\n",
+ "Key 4: ['🙃' '🦁' '🤯' '🐸' '👾']\n"
]
},
{
@@ -247,11 +243,11 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "Key 0: [24 20 21 4 17]\n",
- "Key 1: [ 6 26 27 28 29]\n",
- "Key 2: [18 8 15 16 23]\n",
- "Key 3: [ 0 2 3 22 11]\n",
- "Key 4: [12 14 9 10 5]\n"
+ "Key 0: [ 1 2 21 28 5]\n",
+ "Key 1: [19 26 15 10 29]\n",
+ "Key 2: [25 14 3 4 23]\n",
+ "Key 3: [ 7 8 27 16 11]\n",
+ "Key 4: [13 20 9 22 17]\n"
]
},
{
@@ -268,15 +264,15 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "Key 0: [61997 58864 29925 57980 42577]\n",
- "Key 1: [56754 9269 19956 55576 32892]\n",
- "Key 2: [63205 27799 23847 57450 58182]\n",
- "Key 3: [38076 43656 24035 9463 46164]\n",
- "Key 4: [56031 13741 42374 57145 18197]\n"
+ "Key 0: [19687 10938 44350 7583 27050]\n",
+ "Key 1: [14898 21514 24111 6929 36157]\n",
+ "Key 2: [45848 62914 59248 5143 23249]\n",
+ "Key 3: [ 7431 59668 8782 36473 18710]\n",
+ "Key 4: [35476 1879 28699 53666 25394]\n"
]
}
],
- "execution_count": 45
+ "execution_count": 5
},
{
"metadata": {},
@@ -289,8 +285,8 @@
{
"metadata": {
"ExecuteTime": {
- "end_time": "2025-03-20T15:13:44.190448Z",
- "start_time": "2025-03-20T15:13:44.187214Z"
+ "end_time": "2025-03-24T09:48:10.726327Z",
+ "start_time": "2025-03-24T09:48:10.723046Z"
}
},
"cell_type": "code",
@@ -309,14 +305,14 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "User Passcode Indices: [4, 9, 5, 18]\n",
- "User Passcode Icons: ['🤓' '🤯' '😎' '🐱']\n",
- "User Passcode Server-side properties: [57980 42374 18197 63205]\n",
- "Selected Keys: [0, 4, 4, 2]\n"
+ "User Passcode Indices: [8, 15, 17, 7]\n",
+ "User Passcode Icons: ['😱' '🤖' '👾' '😡']\n",
+ "User Passcode Server-side properties: [59668 24111 25394 7431]\n",
+ "Selected Keys: [3, 1, 4, 3]\n"
]
}
],
- "execution_count": 46
+ "execution_count": 6
},
{
"metadata": {},
@@ -329,8 +325,8 @@
{
"metadata": {
"ExecuteTime": {
- "end_time": "2025-03-20T15:13:44.516570Z",
- "start_time": "2025-03-20T15:13:44.208909Z"
+ "end_time": "2025-03-24T09:48:11.002815Z",
+ "start_time": "2025-03-24T09:48:10.759840Z"
}
},
"cell_type": "code",
@@ -347,17 +343,17 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "Key 0: [18 20 27 10 11]\n",
- "Key 1: [24 14 15 22 29]\n",
- "Key 2: [12 2 21 28 23]\n",
- "Key 3: [ 0 26 9 16 17]\n",
- "Key 4: [6 8 3 4 5]\n",
+ "Key 0: [ 1 26 9 4 11]\n",
+ "Key 1: [19 8 3 28 17]\n",
+ "Key 2: [ 7 20 21 10 23]\n",
+ "Key 3: [13 14 15 16 5]\n",
+ "Key 4: [25 2 27 22 29]\n",
"Selected Keys\n",
- "[4, 3, 4, 0]\n"
+ "[1, 3, 1, 2]\n"
]
}
],
- "execution_count": 47
+ "execution_count": 7
},
{
"metadata": {},
@@ -367,8 +363,8 @@
{
"metadata": {
"ExecuteTime": {
- "end_time": "2025-03-20T15:13:44.527802Z",
- "start_time": "2025-03-20T15:13:44.524844Z"
+ "end_time": "2025-03-24T09:48:11.011978Z",
+ "start_time": "2025-03-24T09:48:11.009413Z"
}
},
"cell_type": "code",
@@ -387,22 +383,22 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "Set Key 0: ['🦄' '🦁' '🐻' '🤓' '👾']\n",
- "Confirm Key 0: ['🥺' '😱' '😍' '🤓' '😎']\n",
- "Overlapping icon 🤓\n",
- "Set Key 1: ['🤔' '😇' '🤯' '🥰' '😎']\n",
- "Confirm Key 1: ['😀' '⚡' '🤯' '👽' '👾']\n",
- "Overlapping icon 🤯\n",
- "Set Key 2: ['🤔' '😇' '🤯' '🥰' '😎']\n",
- "Confirm Key 2: ['🥺' '😱' '😍' '🤓' '😎']\n",
- "Overlapping icon 😎\n",
- "Set Key 3: ['🐱' '😱' '🤖' '👽' '🐙']\n",
- "Confirm Key 3: ['🐱' '🦁' '🔥' '🥰' '😴']\n",
- "Overlapping icon 🐱\n"
+ "Set Key 0: ['😡' '😱' '🔥' '👽' '😴']\n",
+ "Confirm Key 0: ['🐶' '😱' '😍' '🍕' '👾']\n",
+ "Overlapping icon 😱\n",
+ "Set Key 1: ['🐶' '⚡' '🤖' '🥰' '🎉']\n",
+ "Confirm Key 1: ['🙃' '😇' '🤖' '👽' '😎']\n",
+ "Overlapping icon 🤖\n",
+ "Set Key 2: ['🙃' '🦁' '🤯' '🐸' '👾']\n",
+ "Confirm Key 2: ['🐶' '😱' '😍' '🍕' '👾']\n",
+ "Overlapping icon 👾\n",
+ "Set Key 3: ['😡' '😱' '🔥' '👽' '😴']\n",
+ "Confirm Key 3: ['😡' '🦁' '🐻' '🥰' '🐙']\n",
+ "Overlapping icon 😡\n"
]
}
],
- "execution_count": 48
+ "execution_count": 8
},
{
"metadata": {},
@@ -422,8 +418,8 @@
{
"metadata": {
"ExecuteTime": {
- "end_time": "2025-03-20T15:13:44.546871Z",
- "start_time": "2025-03-20T15:13:44.540903Z"
+ "end_time": "2025-03-24T09:48:11.030598Z",
+ "start_time": "2025-03-24T09:48:11.025452Z"
}
},
"cell_type": "code",
@@ -433,13 +429,13 @@
"user_prop_key_keypad = user_cipher.property_key.reshape(-1, keypad_size.props_per_key)"
],
"outputs": [],
- "execution_count": 49
+ "execution_count": 9
},
{
"metadata": {
"ExecuteTime": {
- "end_time": "2025-03-20T15:13:44.565168Z",
- "start_time": "2025-03-20T15:13:44.562664Z"
+ "end_time": "2025-03-24T09:48:11.049702Z",
+ "start_time": "2025-03-24T09:48:11.047621Z"
}
},
"cell_type": "code",
@@ -450,21 +446,21 @@
"output_type": "stream",
"text": [
"Property Key:\n",
- "[[21364 17750 43270 40570 2897 64106]\n",
- " [64901 60553 23487 56910 22974 27412]\n",
- " [49276 36687 58910 60854 56432 64908]\n",
- " [17816 7963 33663 13564 43318 39697]\n",
- " [ 6300 40793 34908 48633 47026 16580]]\n"
+ "[[12284 15976 959 23676 56686 51545]\n",
+ " [ 8349 41940 14857 24411 28369 47234]\n",
+ " [42434 47287 23836 29864 11461 30858]\n",
+ " [39973 19733 43467 29927 8960 22628]\n",
+ " [26608 3550 57761 58209 11329 828]]\n"
]
}
],
- "execution_count": 50
+ "execution_count": 10
},
{
"metadata": {
"ExecuteTime": {
- "end_time": "2025-03-20T15:13:44.583641Z",
- "start_time": "2025-03-20T15:13:44.581757Z"
+ "end_time": "2025-03-24T09:48:11.080213Z",
+ "start_time": "2025-03-24T09:48:11.077878Z"
}
},
"cell_type": "code",
@@ -474,17 +470,17 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "Passcode Key: [65482 44549 30799 45221 44404 5844 32654 14244 48015 17243]\n"
+ "Passcode Key: [43421 54264 31716 41010 25784 51749 8406 27083 36329 63965]\n"
]
}
],
- "execution_count": 51
+ "execution_count": 11
},
{
"metadata": {
"ExecuteTime": {
- "end_time": "2025-03-20T15:13:44.624946Z",
- "start_time": "2025-03-20T15:13:44.622774Z"
+ "end_time": "2025-03-24T09:48:11.120295Z",
+ "start_time": "2025-03-24T09:48:11.118074Z"
}
},
"cell_type": "code",
@@ -494,17 +490,17 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "Mask Key: [36463 57168 30740 46459 21013 40282 33046 14986 26644 13]\n"
+ "Mask Key: [27744 6339 46141 38859 23071 28613 2855 48530 24494 59329]\n"
]
}
],
- "execution_count": 52
+ "execution_count": 12
},
{
"metadata": {
"ExecuteTime": {
- "end_time": "2025-03-20T15:13:44.653291Z",
- "start_time": "2025-03-20T15:13:44.651215Z"
+ "end_time": "2025-03-24T09:48:11.158895Z",
+ "start_time": "2025-03-24T09:48:11.156729Z"
}
},
"cell_type": "code",
@@ -514,17 +510,17 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "Combined Position Key: [32765 21433 32527 38517 27021 45380]\n"
+ "Combined Position Key: [42763 65304 30825 5938 4970 58530]\n"
]
}
],
- "execution_count": 53
+ "execution_count": 13
},
{
"metadata": {
"ExecuteTime": {
- "end_time": "2025-03-20T15:13:44.682695Z",
- "start_time": "2025-03-20T15:13:44.680482Z"
+ "end_time": "2025-03-24T09:48:11.183517Z",
+ "start_time": "2025-03-24T09:48:11.181587Z"
}
},
"cell_type": "code",
@@ -534,17 +530,17 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "User Position Key = combined_pos_key XOR customer_pos_key: [10261 58366 52405 60992 56352 18216]\n"
+ "User Position Key = combined_pos_key XOR customer_pos_key: [46883 788 17499 12342 17274 44356]\n"
]
}
],
- "execution_count": 54
+ "execution_count": 14
},
{
"metadata": {
"ExecuteTime": {
- "end_time": "2025-03-20T15:13:44.713223Z",
- "start_time": "2025-03-20T15:13:44.710535Z"
+ "end_time": "2025-03-24T09:48:11.207260Z",
+ "start_time": "2025-03-24T09:48:11.204729Z"
}
},
"cell_type": "code",
@@ -560,16 +556,16 @@
"output_type": "stream",
"text": [
"Combined Position to Properties Map:\n",
- "32765: [21364 64901 49276 17816 6300]\n",
- "21433: [17750 60553 36687 7963 40793]\n",
- "32527: [43270 23487 58910 33663 34908]\n",
- "38517: [40570 56910 60854 13564 48633]\n",
- "27021: [ 2897 22974 56432 43318 47026]\n",
- "45380: [64106 27412 64908 39697 16580]\n"
+ "42763: [12284 8349 42434 39973 26608]\n",
+ "65304: [15976 41940 47287 19733 3550]\n",
+ "30825: [ 959 14857 23836 43467 57761]\n",
+ "5938: [23676 24411 29864 29927 58209]\n",
+ "4970: [56686 28369 11461 8960 11329]\n",
+ "58530: [51545 47234 30858 22628 828]\n"
]
}
],
- "execution_count": 55
+ "execution_count": 15
},
{
"metadata": {},
@@ -586,8 +582,8 @@
{
"metadata": {
"ExecuteTime": {
- "end_time": "2025-03-20T15:13:44.732450Z",
- "start_time": "2025-03-20T15:13:44.729920Z"
+ "end_time": "2025-03-24T09:48:11.235048Z",
+ "start_time": "2025-03-24T09:48:11.232871Z"
}
},
"cell_type": "code",
@@ -599,7 +595,7 @@
"encoded_mask = user_cipher.encode_base64_str(mask)"
],
"outputs": [],
- "execution_count": 56
+ "execution_count": 16
},
{
"metadata": {},
@@ -616,8 +612,8 @@
{
"metadata": {
"ExecuteTime": {
- "end_time": "2025-03-20T15:13:45.055535Z",
- "start_time": "2025-03-20T15:13:44.751147Z"
+ "end_time": "2025-03-24T09:48:11.484858Z",
+ "start_time": "2025-03-24T09:48:11.252168Z"
}
},
"cell_type": "code",
@@ -631,7 +627,7 @@
"passcode_hash = bcrypt.hashpw(passcode_prehash, bcrypt.gensalt(rounds=12)).decode(\"utf-8\")"
],
"outputs": [],
- "execution_count": 57
+ "execution_count": 17
},
{
"metadata": {},
@@ -645,8 +641,8 @@
{
"metadata": {
"ExecuteTime": {
- "end_time": "2025-03-20T15:13:45.367717Z",
- "start_time": "2025-03-20T15:13:45.061644Z"
+ "end_time": "2025-03-24T09:48:11.722985Z",
+ "start_time": "2025-03-24T09:48:11.488809Z"
}
},
"cell_type": "code",
@@ -664,20 +660,20 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "Key 0: [24 13 20 21 4 17]\n",
- "Key 1: [ 6 1 26 27 28 29]\n",
- "Key 2: [18 7 8 15 16 23]\n",
- "Key 3: [ 0 19 2 3 22 11]\n",
- "Key 4: [12 25 14 9 10 5]\n",
- "User Passcode: [4, 9, 5, 18]\n",
+ "Key 0: [18 1 2 21 28 5]\n",
+ "Key 1: [12 19 26 15 10 29]\n",
+ "Key 2: [ 0 25 14 3 4 23]\n",
+ "Key 3: [ 6 7 8 27 16 11]\n",
+ "Key 4: [24 13 20 9 22 17]\n",
+ "User Passcode: [8, 15, 17, 7]\n",
"\n",
"Selected Keys:\n",
- " [0, 4, 4, 2]\n",
+ " [3, 1, 4, 3]\n",
"\n"
]
}
],
- "execution_count": 58
+ "execution_count": 18
},
{
"metadata": {},
@@ -704,8 +700,8 @@
{
"metadata": {
"ExecuteTime": {
- "end_time": "2025-03-20T15:13:45.379898Z",
- "start_time": "2025-03-20T15:13:45.377353Z"
+ "end_time": "2025-03-24T09:48:11.731909Z",
+ "start_time": "2025-03-24T09:48:11.729517Z"
}
},
"cell_type": "code",
@@ -718,7 +714,7 @@
"user_position_key = customer.cipher.position_key ^ user.cipher.combined_position_key"
],
"outputs": [],
- "execution_count": 59
+ "execution_count": 19
},
{
"metadata": {},
@@ -732,8 +728,8 @@
{
"metadata": {
"ExecuteTime": {
- "end_time": "2025-03-20T15:13:45.391901Z",
- "start_time": "2025-03-20T15:13:45.389499Z"
+ "end_time": "2025-03-24T09:48:11.750757Z",
+ "start_time": "2025-03-24T09:48:11.748661Z"
}
},
"cell_type": "code",
@@ -743,7 +739,7 @@
"assert passcode_property_indices == presumed_property_indices\n"
],
"outputs": [],
- "execution_count": 60
+ "execution_count": 20
},
{
"metadata": {},
@@ -753,8 +749,8 @@
{
"metadata": {
"ExecuteTime": {
- "end_time": "2025-03-20T15:13:45.711702Z",
- "start_time": "2025-03-20T15:13:45.407474Z"
+ "end_time": "2025-03-24T09:48:11.995883Z",
+ "start_time": "2025-03-24T09:48:11.760909Z"
}
},
"cell_type": "code",
@@ -763,7 +759,7 @@
"assert valid_nkode"
],
"outputs": [],
- "execution_count": 61
+ "execution_count": 21
},
{
"metadata": {},
@@ -779,8 +775,8 @@
{
"metadata": {
"ExecuteTime": {
- "end_time": "2025-03-20T15:13:46.331470Z",
- "start_time": "2025-03-20T15:13:45.715778Z"
+ "end_time": "2025-03-24T09:48:12.479529Z",
+ "start_time": "2025-03-24T09:48:12.009222Z"
}
},
"cell_type": "code",
@@ -806,15 +802,15 @@
"output_type": "stream",
"text": [
"Old User Cipher and Mask\n",
- "mask: xetVN/8taK1lhtrDjt4w0M4pprQ=, code: $2b$12$6JzDrPs.dAb0iOIvm8afKuwf.Z8qKtg89Nnhx..tlBOD5y1MYMR4y\n",
+ "mask: nheBuPsWD2zInvscNhsJO6Wy0kU=, code: $2b$12$bsV3i1BsLH6nHCZOPVHns.b1ARmpuJETxFPZohcPG2OKO9Mr3B1du\n",
"\n",
"New User Cipher and Mask\n",
- "mask: WsKTIcZVngijEKlMfoF2UG5Rz9I=, code: $2b$12$jvQ..z4tPFII5dLXP0D2LOPrypDSB7yoRH6E0SZPO/yIIcZVtgCTS\n",
+ "mask: ionSnD9+/0DS5ul8+wMyi3PNCRA=, code: $2b$12$MZejDYT1GDoyE0w1TdFGCedyBD4BY2n6VjLQW73TwJPLyjiimdpA2\n",
"\n"
]
}
],
- "execution_count": 62
+ "execution_count": 22
},
{
"metadata": {},
@@ -827,8 +823,8 @@
{
"metadata": {
"ExecuteTime": {
- "end_time": "2025-03-20T15:13:46.344092Z",
- "start_time": "2025-03-20T15:13:46.339802Z"
+ "end_time": "2025-03-24T09:48:12.490144Z",
+ "start_time": "2025-03-24T09:48:12.486157Z"
}
},
"cell_type": "code",
@@ -841,7 +837,7 @@
"new_pos = customer.cipher.position_key"
],
"outputs": [],
- "execution_count": 63
+ "execution_count": 23
},
{
"metadata": {},
@@ -861,8 +857,8 @@
{
"metadata": {
"ExecuteTime": {
- "end_time": "2025-03-20T15:13:46.361420Z",
- "start_time": "2025-03-20T15:13:46.359046Z"
+ "end_time": "2025-03-24T09:48:12.503462Z",
+ "start_time": "2025-03-24T09:48:12.501409Z"
}
},
"cell_type": "code",
@@ -875,7 +871,7 @@
" user.cipher.property_key = user.cipher.property_key ^ props_xor"
],
"outputs": [],
- "execution_count": 64
+ "execution_count": 24
},
{
"metadata": {},
@@ -888,8 +884,8 @@
{
"metadata": {
"ExecuteTime": {
- "end_time": "2025-03-20T15:13:46.679562Z",
- "start_time": "2025-03-20T15:13:46.371777Z"
+ "end_time": "2025-03-24T09:48:12.759002Z",
+ "start_time": "2025-03-24T09:48:12.522251Z"
}
},
"cell_type": "code",
@@ -904,7 +900,7 @@
" user.renew = False"
],
"outputs": [],
- "execution_count": 65
+ "execution_count": 25
}
],
"metadata": {
diff --git a/src/customer.py b/src/customer.py
index 903eb64..7763d02 100644
--- a/src/customer.py
+++ b/src/customer.py
@@ -1,8 +1,5 @@
from dataclasses import dataclass
from uuid import UUID, uuid4
-
-import numpy as np
-
from src.customer_cipher import CustomerCipher
from src.models import NKodePolicy
from src.user import User
diff --git a/src/utils.py b/src/utils.py
index 40b1593..cd70ca9 100644
--- a/src/utils.py
+++ b/src/utils.py
@@ -28,3 +28,7 @@ def keypad_md_table(keypad_list: np.ndarray, keypad_size: KeypadSize) -> str:
table += "|".join([str(prop) for prop in keypad[key]])
table += "|"
return table
+
+def select_keys_with_passcode_values(user_passcode_idxs: list[int], keypad: np.ndarray, props_per_key: int) -> list[int]:
+ indices = [np.where(keypad == prop)[0][0] for prop in user_passcode_idxs]
+ return [int(index // props_per_key) for index in indices]