refactor dispersion_tutorial.ipynb

This commit is contained in:
2025-03-20 11:15:48 -05:00
parent fdcf31948f
commit 7b1ba996ae
3 changed files with 263 additions and 229 deletions

View File

@@ -1,36 +1,71 @@
{ {
"cells": [ "cells": [
{
"cell_type": "markdown",
"source": [
"## Dispersion"
],
"metadata": {
"collapsed": false
}
},
{ {
"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",
"\n", "\n",
"def random_property_rotation(\n",
" user_keypad: np.ndarray,\n",
" prop_rotation: list[int]\n",
") -> np.ndarray:\n",
" transposed = user_keypad.T\n",
" if len(prop_rotation) != len(transposed):\n",
" raise ValueError(\"prop_rotation must be the same length as the number of properties\")\n",
" for idx, prop_set in enumerate(transposed):\n",
" rotation = prop_rotation[idx]\n",
" rotation = rotation % len(prop_set) if len(prop_set) > 0 else 0\n",
" transposed[idx] = np.roll(prop_set, rotation)\n",
" return transposed.T\n",
"\n",
"def keypad_md_table(keypad_list: np.ndarray, keypad_size: KeypadSize) -> str:\n", "def keypad_md_table(keypad_list: np.ndarray, keypad_size: KeypadSize) -> str:\n",
" assert (keypad_size.total_props == len(keypad_list))\n", " assert (keypad_size.total_props == len(keypad_list))\n",
" keypad = keypad_list.reshape(-1, keypad_size.props_per_key)\n", " keypad = keypad_list.reshape(-1, keypad_size.props_per_key)\n",
" table = \"|key|\" + \"\".join([f\"set{idx}|\" for idx in range(keypad_size.props_per_key)])\n", " table = \"||\" + \"\".join([f\"position {idx}|\" for idx in range(keypad_size.props_per_key)])\n",
" table += \"\\n|\" + \"\".join(\"-|\" for _ in range(keypad_size.props_per_key + 1))\n", " table += \"\\n|\" + \"\".join(\"-|\" for _ in range(keypad_size.props_per_key + 1))\n",
"\n", "\n",
" for key in range(keypad_size.numb_of_keys):\n", " for key in range(keypad_size.numb_of_keys):\n",
" table += f\"\\n|key{key+1}|\"\n", " table += f\"\\n|key {key}|\"\n",
" table += \"|\".join([str(prop) for prop in keypad[key]])\n", " table += \"|\".join([str(prop) for prop in keypad[key]])\n",
" table += \"|\"\n", " table += \"|\"\n",
" return table\n", " return table"
],
"metadata": {
"collapsed": false,
"ExecuteTime": {
"end_time": "2025-03-20T16:15:24.214098Z",
"start_time": "2025-03-20T16:15:24.207220Z"
}
},
"outputs": [],
"execution_count": 80
},
{
"metadata": {},
"cell_type": "markdown",
"source": [
"## Keypad Dispersion\n",
"\n", "\n",
"Keypad dispersion refers to an operation that redistributes the properties assigned to each key on a keypad, ensuring that no property shares a key with a property that was previously adjacent to it.\n",
"Keypads are only dispersable if `numb_of_keys <= properites_per_key`\n",
"\n", "\n",
"A keypad dispersion is completed in two steps:\n",
"1. Create a property rotation array; a randomly permuted subset of indices, selected without replacement from a range equal to the number of keys on a keypad, with its length truncated to match the number of properties assigned per key.\n",
"2. Rotate each position, similar to a ring or combination lock, by a distance equal to its corresponding value in the property rotation array."
]
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-03-20T16:15:24.225459Z",
"start_time": "2025-03-20T16:15:24.220286Z"
}
},
"cell_type": "code",
"source": [
"keypad_size = KeypadSize(numb_of_keys=5, props_per_key=4)\n", "keypad_size = KeypadSize(numb_of_keys=5, props_per_key=4)\n",
"props = [1, 10, 11, 100]\n", "props = [1, 10, 11, 100]\n",
"keypad = []\n", "keypad = []\n",
@@ -38,90 +73,98 @@
" keypad.extend([key_numb * prop for prop in props])\n", " keypad.extend([key_numb * prop for prop in props])\n",
"\n", "\n",
"demo_interface = UserKeypad(keypad_size=keypad_size, keypad=np.array(keypad))\n", "demo_interface = UserKeypad(keypad_size=keypad_size, keypad=np.array(keypad))\n",
"\n", "display(Markdown(f\"\"\"\n",
"## Example Keypad\n",
"{keypad_size.numb_of_keys} X {keypad_size.props_per_key} keypad ({keypad_size.numb_of_keys} keys, {keypad_size.props_per_key} properties per key).\n",
"\"\"\"))\n",
"display(Markdown(keypad_md_table(demo_interface.keypad, keypad_size)))\n" "display(Markdown(keypad_md_table(demo_interface.keypad, keypad_size)))\n"
], ],
"metadata": {
"collapsed": false,
"ExecuteTime": {
"end_time": "2025-03-14T14:34:55.702615Z",
"start_time": "2025-03-14T14:34:55.694963Z"
}
},
"outputs": [ "outputs": [
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"<IPython.core.display.Markdown object>" "<IPython.core.display.Markdown object>"
], ],
"text/markdown": "|key|set0|set1|set2|set3|\n|-|-|-|-|-|\n|key1|1|10|11|100|\n|key2|2|20|22|200|\n|key3|3|30|33|300|\n|key4|4|40|44|400|\n|key5|5|50|55|500|" "text/markdown": "\n## Example Keypad\n5 X 4 keypad (5 keys, 4 properties per key).\n"
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"<IPython.core.display.Markdown object>"
],
"text/markdown": "||position 0|position 1|position 2|position 3|\n|-|-|-|-|-|\n|key 0|1|10|11|100|\n|key 1|2|20|22|200|\n|key 2|3|30|33|300|\n|key 3|4|40|44|400|\n|key 4|5|50|55|500|"
}, },
"metadata": {}, "metadata": {},
"output_type": "display_data" "output_type": "display_data"
} }
], ],
"execution_count": 4 "execution_count": 81
}, },
{ {
"cell_type": "code", "metadata": {},
"source": [ "cell_type": "markdown",
"demo_interface_matrix = demo_interface.keypad.reshape(-1, demo_interface.keypad_size.props_per_key)\n", "source": "### Create Property Rotation Array"
"shuffled_keys = np.random.permutation(demo_interface_matrix)\n",
"shuffled_keys_list = shuffled_keys.reshape(-1)\n",
"display(Markdown(keypad_md_table(shuffled_keys_list, keypad_size)))"
],
"metadata": {
"collapsed": false,
"ExecuteTime": {
"end_time": "2025-03-14T14:34:55.718161Z",
"start_time": "2025-03-14T14:34:55.714512Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
"<IPython.core.display.Markdown object>"
],
"text/markdown": "|key|set0|set1|set2|set3|\n|-|-|-|-|-|\n|key1|1|10|11|100|\n|key2|4|40|44|400|\n|key3|3|30|33|300|\n|key4|2|20|22|200|\n|key5|5|50|55|500|"
},
"metadata": {},
"output_type": "display_data"
}
],
"execution_count": 5
}, },
{ {
"cell_type": "code", "cell_type": "code",
"source": [ "source": [
"prop_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 = random_property_rotation(\n", "print(f\"Property Rotation: {prop_rotation}\")\n"
" shuffled_keys,\n",
" prop_rotation\n",
")\n",
"\n",
"display(Markdown(keypad_md_table(dispersed_interface.reshape(-1), keypad_size)))\n"
], ],
"metadata": { "metadata": {
"collapsed": false, "collapsed": false,
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-14T14:34:55.731332Z", "end_time": "2025-03-20T16:15:24.240606Z",
"start_time": "2025-03-14T14:34:55.728135Z" "start_time": "2025-03-20T16:15:24.237773Z"
} }
}, },
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Property Rotation: [4 3 2 0]\n"
]
}
],
"execution_count": 82
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### Apply the Rotation"
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-03-20T16:15:24.256086Z",
"start_time": "2025-03-20T16:15:24.253226Z"
}
},
"cell_type": "code",
"source": [
"dispersed_interface = random_property_rotation(\n",
" demo_interface.keypad.reshape(-1, keypad_size.props_per_key),\n",
" prop_rotation\n",
")\n",
"display(Markdown(keypad_md_table(dispersed_interface.reshape(-1), keypad_size)))"
],
"outputs": [ "outputs": [
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"<IPython.core.display.Markdown object>" "<IPython.core.display.Markdown object>"
], ],
"text/markdown": "|key|set0|set1|set2|set3|\n|-|-|-|-|-|\n|key1|5|30|44|100|\n|key2|1|20|33|400|\n|key3|4|50|22|300|\n|key4|3|10|55|200|\n|key5|2|40|11|500|" "text/markdown": "||position 0|position 1|position 2|position 3|\n|-|-|-|-|-|\n|key 0|2|30|44|100|\n|key 1|3|40|55|200|\n|key 2|4|50|11|300|\n|key 3|5|10|22|400|\n|key 4|1|20|33|500|"
}, },
"metadata": {}, "metadata": {},
"output_type": "display_data" "output_type": "display_data"
} }
], ],
"execution_count": 6 "execution_count": 83
} }
], ],
"metadata": { "metadata": {

View File

@@ -30,12 +30,12 @@
"metadata": { "metadata": {
"collapsed": false, "collapsed": false,
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-20T12:00:21.292663Z", "end_time": "2025-03-20T15:13:44.080558Z",
"start_time": "2025-03-20T12:00:21.253426Z" "start_time": "2025-03-20T15:13:44.076372Z"
} }
}, },
"outputs": [], "outputs": [],
"execution_count": 2 "execution_count": 41
}, },
{ {
"cell_type": "code", "cell_type": "code",
@@ -53,12 +53,12 @@
"metadata": { "metadata": {
"collapsed": false, "collapsed": false,
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-20T12:00:21.298357Z", "end_time": "2025-03-20T15:13:44.090939Z",
"start_time": "2025-03-20T12:00:21.296258Z" "start_time": "2025-03-20T15:13:44.088281Z"
} }
}, },
"outputs": [], "outputs": [],
"execution_count": 3 "execution_count": 42
}, },
{ {
"metadata": {}, "metadata": {},
@@ -112,8 +112,8 @@
"metadata": { "metadata": {
"collapsed": false, "collapsed": false,
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-20T12:00:21.317747Z", "end_time": "2025-03-20T15:13:44.107060Z",
"start_time": "2025-03-20T12:00:21.306163Z" "start_time": "2025-03-20T15:13:44.100773Z"
} }
}, },
"outputs": [ "outputs": [
@@ -121,30 +121,30 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Customer Position Key: [37938 42486 36680 47679 5944 46439]\n", "Customer Position Key: [22504 45127 46010 30773 46509 63084]\n",
"Customer Properties Key:\n", "Customer Properties Key:\n",
"[14469 12272 54942 53713 60529 64319]\n", "[38076 5253 43656 24035 57980 18197]\n",
"[49129 65121 60219 33860 48996 57925]\n", "[56754 21362 27799 42374 57145 46164]\n",
"[61464 3328 59612 33957 62738 42039]\n", "[56031 10476 13741 23847 57450 42577]\n",
"[ 3074 46306 41956 4712 59250 7730]\n", "[63205 55476 58864 29925 9463 58182]\n",
"[23724 39640 530 27472 33903 26824]\n", "[61997 24583 9269 19956 55576 32892]\n",
"Position to Properties Map:\n", "Position to Properties Map:\n",
"37938: [14469 49129 61464 3074 23724]\n", "22504: [38076 56754 56031 63205 61997]\n",
"42486: [12272 65121 3328 46306 39640]\n", "45127: [ 5253 21362 10476 55476 24583]\n",
"36680: [54942 60219 59612 41956 530]\n", "46010: [43656 27799 13741 58864 9269]\n",
"47679: [53713 33860 33957 4712 27472]\n", "30773: [24035 42374 23847 29925 19956]\n",
"5944: [60529 48996 62738 59250 33903]\n", "46509: [57980 57145 57450 9463 55576]\n",
"46439: [64319 57925 42039 7730 26824]\n" "63084: [18197 46164 42577 58182 32892]\n"
] ]
} }
], ],
"execution_count": 4 "execution_count": 43
}, },
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-20T12:00:21.325478Z", "end_time": "2025-03-20T15:13:44.127687Z",
"start_time": "2025-03-20T12:00:21.322970Z" "start_time": "2025-03-20T15:13:44.125028Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -161,16 +161,16 @@
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Position Value to Icons Map:\n", "Position Value to Icons Map:\n",
"37938: ['😀' '🥺' '🤔' '🐱' '🦄']\n", "22504: ['😀' '🥺' '🤔' '🐱' '🦄']\n",
"42486: ['😂' '😡' '🙃' '🐶' '🌟']\n", "45127: ['😂' '😡' '🙃' '🐶' '🌟']\n",
"36680: ['🥳' '😱' '😇' '🦁' '⚡']\n", "46010: ['🥳' '😱' '😇' '🦁' '⚡']\n",
"47679: ['😍' '🤯' '🤖' '🐻' '🔥']\n", "30773: ['😍' '🤯' '🤖' '🐻' '🔥']\n",
"5944: ['🤓' '🥰' '👽' '🐸' '🍕']\n", "46509: ['🤓' '🥰' '👽' '🐸' '🍕']\n",
"46439: ['😎' '😴' '👾' '🐙' '🎉']\n" "63084: ['😎' '😴' '👾' '🐙' '🎉']\n"
] ]
} }
], ],
"execution_count": 5 "execution_count": 44
}, },
{ {
"metadata": {}, "metadata": {},
@@ -194,8 +194,8 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-20T12:00:21.349267Z", "end_time": "2025-03-20T15:13:44.156638Z",
"start_time": "2025-03-20T12:00:21.342655Z" "start_time": "2025-03-20T15:13:44.150222Z"
} }
}, },
"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: [18 19 8 3 28]\n", "Key 0: [24 20 21 4 17]\n",
"Key 1: [24 7 26 9 22]\n", "Key 1: [ 6 26 27 28 29]\n",
"Key 2: [ 0 13 14 27 16]\n", "Key 2: [18 8 15 16 23]\n",
"Key 3: [ 6 1 2 21 10]\n", "Key 3: [ 0 2 3 22 11]\n",
"Key 4: [12 25 20 15 4]\n" "Key 4: [12 14 9 10 5]\n"
] ]
}, },
{ {
@@ -265,15 +265,15 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Key 0: [ 3074 46306 60219 53713 33903]\n", "Key 0: [61997 58864 29925 57980 42577]\n",
"Key 1: [23724 65121 530 33860 59250]\n", "Key 1: [56754 9269 19956 55576 32892]\n",
"Key 2: [14469 3328 59612 27472 62738]\n", "Key 2: [63205 27799 23847 57450 58182]\n",
"Key 3: [49129 12272 54942 4712 48996]\n", "Key 3: [38076 43656 24035 9463 46164]\n",
"Key 4: [61464 39640 41956 33957 60529]\n" "Key 4: [56031 13741 42374 57145 18197]\n"
] ]
} }
], ],
"execution_count": 6 "execution_count": 45
}, },
{ {
"metadata": {}, "metadata": {},
@@ -286,8 +286,8 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-20T12:00:21.372390Z", "end_time": "2025-03-20T15:13:44.190448Z",
"start_time": "2025-03-20T12:00:21.369564Z" "start_time": "2025-03-20T15:13:44.187214Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -306,14 +306,14 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"User Passcode Indices: [19, 28, 22, 18]\n", "User Passcode Indices: [4, 9, 5, 18]\n",
"User Passcode Icons: ['🐶' '🍕' '🐸' '🐱']\n", "User Passcode Icons: ['🤓' '🤯' '😎' '🐱']\n",
"User Passcode Server-side properties: [46306 33903 59250 3074]\n", "User Passcode Server-side properties: [57980 42374 18197 63205]\n",
"Selected Keys: [0, 0, 1, 0]\n" "Selected Keys: [0, 4, 4, 2]\n"
] ]
} }
], ],
"execution_count": 7 "execution_count": 46
}, },
{ {
"metadata": {}, "metadata": {},
@@ -326,8 +326,8 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-20T12:00:21.631111Z", "end_time": "2025-03-20T15:13:44.516570Z",
"start_time": "2025-03-20T12:00:21.391841Z" "start_time": "2025-03-20T15:13:44.208909Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -344,17 +344,17 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Key 0: [0 7 2 3 4]\n", "Key 0: [18 20 27 10 11]\n",
"Key 1: [ 6 25 26 27 28]\n", "Key 1: [24 14 15 22 29]\n",
"Key 2: [24 19 20 21 16]\n", "Key 2: [12 2 21 28 23]\n",
"Key 3: [12 13 8 9 10]\n", "Key 3: [ 0 26 9 16 17]\n",
"Key 4: [18 1 14 15 22]\n", "Key 4: [6 8 3 4 5]\n",
"Selected Keys\n", "Selected Keys\n",
"[2, 1, 4, 4]\n" "[4, 3, 4, 0]\n"
] ]
} }
], ],
"execution_count": 8 "execution_count": 47
}, },
{ {
"metadata": {}, "metadata": {},
@@ -364,8 +364,8 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-20T12:08:59.799827Z", "end_time": "2025-03-20T15:13:44.527802Z",
"start_time": "2025-03-20T12:08:59.796887Z" "start_time": "2025-03-20T15:13:44.524844Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -384,22 +384,22 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Set Key 0: ['🐱' '🐶' '😱' '😍' '🍕']\n", "Set Key 0: ['🦄' '🦁' '🐻' '🤓' '👾']\n",
"Confirm Key 0: ['🦄' '🐶' '🦁' '🐻' '👽']\n", "Confirm Key 0: ['🥺' '😱' '😍' '🤓' '😎']\n",
"Overlapping icon 🐶\n", "Overlapping icon 🤓\n",
"Set Key 1: ['🐱' '🐶' '😱' '😍' '🍕']\n", "Set Key 1: ['🤔' '😇' '🤯' '🥰' '😎']\n",
"Confirm Key 1: ['🥺' '🌟' '' '🔥' '🍕']\n", "Confirm Key 1: ['😀' '' '🤯' '👽' '👾']\n",
"Overlapping icon 🍕\n", "Overlapping icon 🤯\n",
"Set Key 2: ['🦄' '😡' '' '🤯' '🐸']\n", "Set Key 2: ['🤔' '😇' '🤯' '🥰' '😎']\n",
"Confirm Key 2: ['🐱' '😂' '😇' '🤖' '🐸']\n", "Confirm Key 2: ['🥺' '😱' '😍' '🤓' '😎']\n",
"Overlapping icon 🐸\n", "Overlapping icon 😎\n",
"Set Key 3: ['🐱' '🐶' '😱' '😍' '🍕']\n", "Set Key 3: ['🐱' '😱' '🤖' '👽' '🐙']\n",
"Confirm Key 3: ['🐱' '😂' '😇' '🤖' '🐸']\n", "Confirm Key 3: ['🐱' '🦁' '🔥' '🥰' '😴']\n",
"Overlapping icon 🐱\n" "Overlapping icon 🐱\n"
] ]
} }
], ],
"execution_count": 15 "execution_count": 48
}, },
{ {
"metadata": {}, "metadata": {},
@@ -419,8 +419,8 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-20T12:00:21.680780Z", "end_time": "2025-03-20T15:13:44.546871Z",
"start_time": "2025-03-20T10:38:44.954840Z" "start_time": "2025-03-20T15:13:44.540903Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -430,13 +430,13 @@
"user_prop_key_keypad = user_cipher.property_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": 83 "execution_count": 49
}, },
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-20T12:00:21.683788Z", "end_time": "2025-03-20T15:13:44.565168Z",
"start_time": "2025-03-20T10:38:44.966571Z" "start_time": "2025-03-20T15:13:44.562664Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -447,21 +447,21 @@
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Property Key:\n", "Property Key:\n",
"[[53739 14349 64971 50952 51008 37461]\n", "[[21364 17750 43270 40570 2897 64106]\n",
" [45744 17444 29958 27397 60694 8069]\n", " [64901 60553 23487 56910 22974 27412]\n",
" [43064 47943 49025 5623 3145 4890]\n", " [49276 36687 58910 60854 56432 64908]\n",
" [ 1128 11012 53093 14232 26108 5391]\n", " [17816 7963 33663 13564 43318 39697]\n",
" [59341 47378 48497 6840 34437 29587]]\n" " [ 6300 40793 34908 48633 47026 16580]]\n"
] ]
} }
], ],
"execution_count": 84 "execution_count": 50
}, },
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-20T12:00:21.684015Z", "end_time": "2025-03-20T15:13:44.583641Z",
"start_time": "2025-03-20T10:38:44.983449Z" "start_time": "2025-03-20T15:13:44.581757Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -471,17 +471,17 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Passcode Key: [16245 48001 4534 55258 54613 15211 33171 56565 33961 50654]\n" "Passcode Key: [65482 44549 30799 45221 44404 5844 32654 14244 48015 17243]\n"
] ]
} }
], ],
"execution_count": 85 "execution_count": 51
}, },
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-20T12:00:21.689867Z", "end_time": "2025-03-20T15:13:44.624946Z",
"start_time": "2025-03-20T10:38:45.005712Z" "start_time": "2025-03-20T15:13:44.622774Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -491,17 +491,17 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Mask Key: [52084 24514 63626 6657 19669 39430 35626 25229 14824 63798]\n" "Mask Key: [36463 57168 30740 46459 21013 40282 33046 14986 26644 13]\n"
] ]
} }
], ],
"execution_count": 86 "execution_count": 52
}, },
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-20T12:00:21.690242Z", "end_time": "2025-03-20T15:13:44.653291Z",
"start_time": "2025-03-20T10:38:45.024649Z" "start_time": "2025-03-20T15:13:44.651215Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -511,17 +511,17 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Combined Position Key: [10235 12456 898 54650 50445 20719]\n" "Combined Position Key: [32765 21433 32527 38517 27021 45380]\n"
] ]
} }
], ],
"execution_count": 87 "execution_count": 53
}, },
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-20T12:00:21.694701Z", "end_time": "2025-03-20T15:13:44.682695Z",
"start_time": "2025-03-20T10:38:45.038985Z" "start_time": "2025-03-20T15:13:44.680482Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -531,17 +531,17 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"User Position Key = combined_pos_key XOR customer_pos_key: [ 3444 19636 47437 1440 7882 36903]\n" "User Position Key = combined_pos_key XOR customer_pos_key: [10261 58366 52405 60992 56352 18216]\n"
] ]
} }
], ],
"execution_count": 88 "execution_count": 54
}, },
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-20T12:00:21.696066Z", "end_time": "2025-03-20T15:13:44.713223Z",
"start_time": "2025-03-20T10:38:45.056942Z" "start_time": "2025-03-20T15:13:44.710535Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -557,16 +557,16 @@
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Combined Position to Properties Map:\n", "Combined Position to Properties Map:\n",
"10235: [53739 45744 43064 1128 59341]\n", "32765: [21364 64901 49276 17816 6300]\n",
"12456: [14349 17444 47943 11012 47378]\n", "21433: [17750 60553 36687 7963 40793]\n",
"898: [64971 29958 49025 53093 48497]\n", "32527: [43270 23487 58910 33663 34908]\n",
"54650: [50952 27397 5623 14232 6840]\n", "38517: [40570 56910 60854 13564 48633]\n",
"50445: [51008 60694 3145 26108 34437]\n", "27021: [ 2897 22974 56432 43318 47026]\n",
"20719: [37461 8069 4890 5391 29587]\n" "45380: [64106 27412 64908 39697 16580]\n"
] ]
} }
], ],
"execution_count": 89 "execution_count": 55
}, },
{ {
"metadata": {}, "metadata": {},
@@ -583,8 +583,8 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-20T12:00:21.696415Z", "end_time": "2025-03-20T15:13:44.732450Z",
"start_time": "2025-03-20T10:38:45.068009Z" "start_time": "2025-03-20T15:13:44.729920Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -596,7 +596,7 @@
"encoded_mask = user_cipher.encode_base64_str(mask)" "encoded_mask = user_cipher.encode_base64_str(mask)"
], ],
"outputs": [], "outputs": [],
"execution_count": 90 "execution_count": 56
}, },
{ {
"metadata": {}, "metadata": {},
@@ -613,8 +613,8 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-20T12:00:21.696640Z", "end_time": "2025-03-20T15:13:45.055535Z",
"start_time": "2025-03-20T10:38:45.087096Z" "start_time": "2025-03-20T15:13:44.751147Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -628,7 +628,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": 91 "execution_count": 57
}, },
{ {
"metadata": {}, "metadata": {},
@@ -642,8 +642,8 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-20T12:00:21.696764Z", "end_time": "2025-03-20T15:13:45.367717Z",
"start_time": "2025-03-20T10:38:45.326214Z" "start_time": "2025-03-20T15:13:45.061644Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -661,20 +661,20 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Key 0: [18 25 14 15 4 29]\n", "Key 0: [24 13 20 21 4 17]\n",
"Key 1: [ 6 13 20 27 28 5]\n", "Key 1: [ 6 1 26 27 28 29]\n",
"Key 2: [24 19 26 9 16 23]\n", "Key 2: [18 7 8 15 16 23]\n",
"Key 3: [ 0 1 8 3 10 11]\n", "Key 3: [ 0 19 2 3 22 11]\n",
"Key 4: [12 7 2 21 22 17]\n", "Key 4: [12 25 14 9 10 5]\n",
"User Passcode: [28, 13, 9, 10]\n", "User Passcode: [4, 9, 5, 18]\n",
"\n", "\n",
"Selected Keys:\n", "Selected Keys:\n",
" [1, 1, 2, 3]\n", " [0, 4, 4, 2]\n",
"\n" "\n"
] ]
} }
], ],
"execution_count": 92 "execution_count": 58
}, },
{ {
"metadata": {}, "metadata": {},
@@ -701,8 +701,8 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-20T12:00:21.696874Z", "end_time": "2025-03-20T15:13:45.379898Z",
"start_time": "2025-03-20T10:38:45.567396Z" "start_time": "2025-03-20T15:13:45.377353Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -712,10 +712,10 @@
"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",
"ordered_user_position_key = mask ^ user.cipher.mask_key\n", "ordered_user_position_key = mask ^ user.cipher.mask_key\n",
"user_position_key = customer.cipher.position_key ^ user.cipher.combined_position_key\n" "user_position_key = customer.cipher.position_key ^ user.cipher.combined_position_key"
], ],
"outputs": [], "outputs": [],
"execution_count": 93 "execution_count": 59
}, },
{ {
"metadata": {}, "metadata": {},
@@ -727,15 +727,20 @@
] ]
}, },
{ {
"metadata": {}, "metadata": {
"ExecuteTime": {
"end_time": "2025-03-20T15:13:45.391901Z",
"start_time": "2025-03-20T15:13:45.389499Z"
}
},
"cell_type": "code", "cell_type": "code",
"outputs": [],
"execution_count": null,
"source": [ "source": [
"passcode_position_indices = [int(np.where(user_position_key == pos)[0][0]) for pos in ordered_user_position_key[:passcode_len]]\n", "passcode_position_indices = [int(np.where(user_position_key == pos)[0][0]) for pos in ordered_user_position_key[:passcode_len]]\n",
"presumed_property_indices = customer.users[username].user_keypad.get_prop_idxs_by_keynumb_setidx(selected_keys_login, passcode_position_indices)\n", "presumed_property_indices = customer.users[username].user_keypad.get_prop_idxs_by_keynumb_setidx(selected_keys_login, passcode_position_indices)\n",
"assert passcode_property_indices == presumed_property_indices\n" "assert passcode_property_indices == presumed_property_indices\n"
] ],
"outputs": [],
"execution_count": 60
}, },
{ {
"metadata": {}, "metadata": {},
@@ -745,8 +750,8 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-20T12:00:21.697134Z", "end_time": "2025-03-20T15:13:45.711702Z",
"start_time": "2025-03-20T10:38:45.576610Z" "start_time": "2025-03-20T15:13:45.407474Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -755,7 +760,7 @@
"assert valid_nkode" "assert valid_nkode"
], ],
"outputs": [], "outputs": [],
"execution_count": 94 "execution_count": 61
}, },
{ {
"metadata": {}, "metadata": {},
@@ -771,8 +776,8 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-20T12:00:21.697273Z", "end_time": "2025-03-20T15:13:46.331470Z",
"start_time": "2025-03-20T10:38:45.816688Z" "start_time": "2025-03-20T15:13:45.715778Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -798,15 +803,15 @@
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Old User Cipher and Mask\n", "Old User Cipher and Mask\n",
"mask: y8aMd+5qYcPVLETTcs2aHqx2hhk=, code: $2b$12$wMi7WGmlch8kWMYJ2v.FHOne1.YSQPqKU/itpBuycwSFyasryF/2u\n", "mask: xetVN/8taK1lhtrDjt4w0M4pprQ=, code: $2b$12$6JzDrPs.dAb0iOIvm8afKuwf.Z8qKtg89Nnhx..tlBOD5y1MYMR4y\n",
"\n", "\n",
"New User Cipher and Mask\n", "New User Cipher and Mask\n",
"mask: aln5Su79utoVmqQXNCjYiUdwVYw=, code: $2b$12$gQf3UVa3cWMBy0CO0sBLyuJzdXGzg3qpNFMTD6MvycuR6N3gLFdgC\n", "mask: WsKTIcZVngijEKlMfoF2UG5Rz9I=, code: $2b$12$jvQ..z4tPFII5dLXP0D2LOPrypDSB7yoRH6E0SZPO/yIIcZVtgCTS\n",
"\n" "\n"
] ]
} }
], ],
"execution_count": 95 "execution_count": 62
}, },
{ {
"metadata": {}, "metadata": {},
@@ -819,8 +824,8 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-20T12:00:21.697386Z", "end_time": "2025-03-20T15:13:46.344092Z",
"start_time": "2025-03-20T10:38:46.293584Z" "start_time": "2025-03-20T15:13:46.339802Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -833,7 +838,7 @@
"new_pos = customer.cipher.position_key" "new_pos = customer.cipher.position_key"
], ],
"outputs": [], "outputs": [],
"execution_count": 96 "execution_count": 63
}, },
{ {
"metadata": {}, "metadata": {},
@@ -853,8 +858,8 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-20T12:00:21.697503Z", "end_time": "2025-03-20T15:13:46.361420Z",
"start_time": "2025-03-20T10:38:46.310019Z" "start_time": "2025-03-20T15:13:46.359046Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -867,7 +872,7 @@
" user.cipher.property_key = user.cipher.property_key ^ props_xor" " user.cipher.property_key = user.cipher.property_key ^ props_xor"
], ],
"outputs": [], "outputs": [],
"execution_count": 97 "execution_count": 64
}, },
{ {
"metadata": {}, "metadata": {},
@@ -880,8 +885,8 @@
{ {
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2025-03-20T12:00:21.697608Z", "end_time": "2025-03-20T15:13:46.679562Z",
"start_time": "2025-03-20T10:38:46.318482Z" "start_time": "2025-03-20T15:13:46.371777Z"
} }
}, },
"cell_type": "code", "cell_type": "code",
@@ -896,7 +901,7 @@
" user.renew = False" " user.renew = False"
], ],
"outputs": [], "outputs": [],
"execution_count": 98 "execution_count": 65
} }
], ],
"metadata": { "metadata": {

View File

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