diff --git a/notebooks/nkode_tutorial.ipynb b/notebooks/nkode_tutorial.ipynb index 64d4fdc..f53c722 100644 --- a/notebooks/nkode_tutorial.ipynb +++ b/notebooks/nkode_tutorial.ipynb @@ -30,12 +30,12 @@ "metadata": { "collapsed": false, "ExecuteTime": { - "end_time": "2025-03-20T08:32:08.092320Z", - "start_time": "2025-03-20T08:32:08.087658Z" + "end_time": "2025-03-20T10:38:44.577863Z", + "start_time": "2025-03-20T10:38:44.572040Z" } }, "outputs": [], - "execution_count": 27 + "execution_count": 75 }, { "cell_type": "code", @@ -53,12 +53,12 @@ "metadata": { "collapsed": false, "ExecuteTime": { - "end_time": "2025-03-20T08:32:08.113043Z", - "start_time": "2025-03-20T08:32:08.110624Z" + "end_time": "2025-03-20T10:38:44.585583Z", + "start_time": "2025-03-20T10:38:44.582961Z" } }, "outputs": [], - "execution_count": 28 + "execution_count": 76 }, { "metadata": {}, @@ -112,8 +112,8 @@ "metadata": { "collapsed": false, "ExecuteTime": { - "end_time": "2025-03-20T08:32:08.198233Z", - "start_time": "2025-03-20T08:32:08.193182Z" + "end_time": "2025-03-20T10:38:44.601079Z", + "start_time": "2025-03-20T10:38:44.595017Z" } }, "outputs": [ @@ -121,30 +121,30 @@ "name": "stdout", "output_type": "stream", "text": [ - "Customer Position Key: [21284 3999 4057 48308 14680 46323]\n", + "Customer Position Key: [10895 31772 47823 53466 56263 49352]\n", "Customer Properties Key:\n", - "[45633 21215 48438 45863 52540 14191]\n", - "[11907 4042 56372 63103 45179 58318]\n", - "[28909 48497 31171 15125 2886 9246]\n", - "[15651 10936 5595 16546 8096 13333]\n", - "[41923 43364 15227 43001 11056 62605]\n", + "[32913 31208 39571 1116 2737 19900]\n", + "[ 4026 23392 64571 25864 56877 34756]\n", + "[56837 8582 51951 34890 37611 61978]\n", + "[55074 11623 3931 21342 53702 21700]\n", + "[26922 1472 49420 42668 7254 41918]\n", "Position to Properties Map:\n", - "21284: [45633 11907 28909 15651 41923]\n", - "3999: [21215 4042 48497 10936 43364]\n", - "4057: [48438 56372 31171 5595 15227]\n", - "48308: [45863 63103 15125 16546 43001]\n", - "14680: [52540 45179 2886 8096 11056]\n", - "46323: [14191 58318 9246 13333 62605]\n" + "10895: [32913 4026 56837 55074 26922]\n", + "31772: [31208 23392 8582 11623 1472]\n", + "47823: [39571 64571 51951 3931 49420]\n", + "53466: [ 1116 25864 34890 21342 42668]\n", + "56263: [ 2737 56877 37611 53702 7254]\n", + "49352: [19900 34756 61978 21700 41918]\n" ] } ], - "execution_count": 29 + "execution_count": 77 }, { "metadata": { "ExecuteTime": { - "end_time": "2025-03-20T08:32:08.226660Z", - "start_time": "2025-03-20T08:32:08.224216Z" + "end_time": "2025-03-20T10:38:44.612692Z", + "start_time": "2025-03-20T10:38:44.610267Z" } }, "cell_type": "code", @@ -161,16 +161,16 @@ "output_type": "stream", "text": [ "Position Value to Icons Map:\n", - "21284: ['😀' '🥺' '🤔' '🐱' '🦄']\n", - "3999: ['😂' '😡' '🙃' '🐶' '🌟']\n", - "4057: ['🥳' '😱' '😇' '🦁' '⚡']\n", - "48308: ['😍' '🤯' '🤖' '🐻' '🔥']\n", - "14680: ['🤓' '🥰' '👽' '🐸' '🍕']\n", - "46323: ['😎' '😴' '👾' '🐙' '🎉']\n" + "10895: ['😀' '🥺' '🤔' '🐱' '🦄']\n", + "31772: ['😂' '😡' '🙃' '🐶' '🌟']\n", + "47823: ['🥳' '😱' '😇' '🦁' '⚡']\n", + "53466: ['😍' '🤯' '🤖' '🐻' '🔥']\n", + "56263: ['🤓' '🥰' '👽' '🐸' '🍕']\n", + "49352: ['😎' '😴' '👾' '🐙' '🎉']\n" ] } ], - "execution_count": 30 + "execution_count": 78 }, { "metadata": {}, @@ -194,8 +194,8 @@ { "metadata": { "ExecuteTime": { - "end_time": "2025-03-20T08:32:08.256237Z", - "start_time": "2025-03-20T08:32:08.250147Z" + "end_time": "2025-03-20T10:38:44.636348Z", + "start_time": "2025-03-20T10:38:44.630660Z" } }, "cell_type": "code", @@ -223,11 +223,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" ] }, { @@ -244,11 +244,11 @@ "name": "stdout", "output_type": "stream", "text": [ - "Key 0: [24 1 14 16 11]\n", - "Key 1: [18 25 8 22 5]\n", - "Key 2: [12 13 20 10 23]\n", - "Key 3: [ 0 7 26 28 17]\n", - "Key 4: [ 6 19 2 4 29]\n" + "Key 0: [18 25 15 4 29]\n", + "Key 1: [ 6 13 27 28 5]\n", + "Key 2: [24 19 9 16 23]\n", + "Key 3: [ 0 1 3 10 11]\n", + "Key 4: [12 7 21 22 17]\n" ] }, { @@ -265,15 +265,15 @@ "name": "stdout", "output_type": "stream", "text": [ - "Key 0: [41923 21215 31171 2886 58318]\n", - "Key 1: [15651 43364 56372 8096 14191]\n", - "Key 2: [28909 48497 5595 45179 13333]\n", - "Key 3: [45633 4042 15227 11056 9246]\n", - "Key 4: [11907 10936 48438 52540 62605]\n" + "Key 0: [55074 1472 34890 2737 41918]\n", + "Key 1: [ 4026 8582 42668 7254 19900]\n", + "Key 2: [26922 11623 25864 37611 21700]\n", + "Key 3: [32913 31208 1116 56877 34756]\n", + "Key 4: [56837 23392 21342 53702 61978]\n" ] } ], - "execution_count": 31 + "execution_count": 79 }, { "metadata": {}, @@ -286,8 +286,8 @@ { "metadata": { "ExecuteTime": { - "end_time": "2025-03-20T08:32:08.280568Z", - "start_time": "2025-03-20T08:32:08.277339Z" + "end_time": "2025-03-20T10:38:44.674025Z", + "start_time": "2025-03-20T10:38:44.671302Z" } }, "cell_type": "code", @@ -306,20 +306,20 @@ "name": "stdout", "output_type": "stream", "text": [ - "User Passcode Indices: [19, 7, 10, 6]\n", - "User Passcode Icons: ['🐶' '😡' '🥰' '🥺']\n", - "User Passcode Server-side properties: [10936 4042 45179 11907]\n", - "Selected Keys: [4, 3, 2, 4]\n" + "User Passcode Indices: [28, 13, 9, 10]\n", + "User Passcode Icons: ['🍕' '🙃' '🤯' '🥰']\n", + "User Passcode Server-side properties: [ 7254 8582 25864 56877]\n", + "Selected Keys: [1, 1, 2, 3]\n" ] } ], - "execution_count": 32 + "execution_count": 80 }, { "metadata": { "ExecuteTime": { - "end_time": "2025-03-20T08:32:08.316148Z", - "start_time": "2025-03-20T08:32:08.313495Z" + "end_time": "2025-03-20T10:38:44.700525Z", + "start_time": "2025-03-20T10:38:44.697597Z" } }, "cell_type": "code", @@ -334,23 +334,23 @@ "name": "stdout", "output_type": "stream", "text": [ - "Key 0: [18 7 20 4 11]\n", - "Key 1: [12 1 26 22 29]\n", - "Key 2: [ 0 19 14 10 5]\n", - "Key 3: [24 25 2 28 23]\n", - "Key 4: [ 6 13 8 16 17]\n", + "Key 0: [ 6 7 3 4 23]\n", + "Key 1: [24 1 15 28 17]\n", + "Key 2: [12 25 27 16 11]\n", + "Key 3: [ 0 13 9 22 29]\n", + "Key 4: [18 19 21 10 5]\n", "Selected Keys\n", - "[2, 0, 2, 4]\n" + "[1, 3, 3, 4]\n" ] } ], - "execution_count": 33 + "execution_count": 81 }, { "metadata": { "ExecuteTime": { - "end_time": "2025-03-20T08:32:08.575664Z", - "start_time": "2025-03-20T08:32:08.337518Z" + "end_time": "2025-03-20T10:38:44.947744Z", + "start_time": "2025-03-20T10:38:44.709897Z" } }, "cell_type": "code", @@ -360,7 +360,7 @@ "assert success" ], "outputs": [], - "execution_count": 34 + "execution_count": 82 }, { "metadata": {}, @@ -380,8 +380,8 @@ { "metadata": { "ExecuteTime": { - "end_time": "2025-03-20T08:32:08.588049Z", - "start_time": "2025-03-20T08:32:08.583087Z" + "end_time": "2025-03-20T10:38:44.959614Z", + "start_time": "2025-03-20T10:38:44.954840Z" } }, "cell_type": "code", @@ -391,13 +391,13 @@ "user_prop_key_keypad = user_cipher.property_key.reshape(-1, keypad_size.props_per_key)" ], "outputs": [], - "execution_count": 35 + "execution_count": 83 }, { "metadata": { "ExecuteTime": { - "end_time": "2025-03-20T08:32:08.596984Z", - "start_time": "2025-03-20T08:32:08.595221Z" + "end_time": "2025-03-20T10:38:44.968863Z", + "start_time": "2025-03-20T10:38:44.966571Z" } }, "cell_type": "code", @@ -408,21 +408,21 @@ "output_type": "stream", "text": [ "Property Key:\n", - "[[43643 58945 45655 10493 17462 5635]\n", - " [42071 15680 60860 39600 15784 4102]\n", - " [60857 21300 14877 25869 12858 50934]\n", - " [55451 44486 22660 41758 36853 37697]\n", - " [24236 53340 57175 52425 5167 2017]]\n" + "[[53739 14349 64971 50952 51008 37461]\n", + " [45744 17444 29958 27397 60694 8069]\n", + " [43064 47943 49025 5623 3145 4890]\n", + " [ 1128 11012 53093 14232 26108 5391]\n", + " [59341 47378 48497 6840 34437 29587]]\n" ] } ], - "execution_count": 36 + "execution_count": 84 }, { "metadata": { "ExecuteTime": { - "end_time": "2025-03-20T08:32:08.615012Z", - "start_time": "2025-03-20T08:32:08.613119Z" + "end_time": "2025-03-20T10:38:44.985451Z", + "start_time": "2025-03-20T10:38:44.983449Z" } }, "cell_type": "code", @@ -432,17 +432,17 @@ "name": "stdout", "output_type": "stream", "text": [ - "Passcode Key: [31049 4633 40678 55986 14115 22499 3470 53359 20871 60539]\n" + "Passcode Key: [16245 48001 4534 55258 54613 15211 33171 56565 33961 50654]\n" ] } ], - "execution_count": 37 + "execution_count": 85 }, { "metadata": { "ExecuteTime": { - "end_time": "2025-03-20T08:32:08.639696Z", - "start_time": "2025-03-20T08:32:08.637469Z" + "end_time": "2025-03-20T10:38:45.007753Z", + "start_time": "2025-03-20T10:38:45.005712Z" } }, "cell_type": "code", @@ -452,17 +452,17 @@ "name": "stdout", "output_type": "stream", "text": [ - "Mask Key: [55361 38182 36656 63013 26815 17961 23911 65497 28524 60226]\n" + "Mask Key: [52084 24514 63626 6657 19669 39430 35626 25229 14824 63798]\n" ] } ], - "execution_count": 38 + "execution_count": 86 }, { "metadata": { "ExecuteTime": { - "end_time": "2025-03-20T08:32:08.658960Z", - "start_time": "2025-03-20T08:32:08.657009Z" + "end_time": "2025-03-20T10:38:45.026885Z", + "start_time": "2025-03-20T10:38:45.024649Z" } }, "cell_type": "code", @@ -472,17 +472,17 @@ "name": "stdout", "output_type": "stream", "text": [ - "Combined Position Key: [33934 3750 42586 25190 7504 35546]\n" + "Combined Position Key: [10235 12456 898 54650 50445 20719]\n" ] } ], - "execution_count": 39 + "execution_count": 87 }, { "metadata": { "ExecuteTime": { - "end_time": "2025-03-20T08:32:08.678360Z", - "start_time": "2025-03-20T08:32:08.676228Z" + "end_time": "2025-03-20T10:38:45.041101Z", + "start_time": "2025-03-20T10:38:45.038985Z" } }, "cell_type": "code", @@ -492,17 +492,17 @@ "name": "stdout", "output_type": "stream", "text": [ - "User Position Key = combined_pos_key XOR customer_pos_key: [55210 313 43395 57042 9224 15913]\n" + "User Position Key = combined_pos_key XOR customer_pos_key: [ 3444 19636 47437 1440 7882 36903]\n" ] } ], - "execution_count": 40 + "execution_count": 88 }, { "metadata": { "ExecuteTime": { - "end_time": "2025-03-20T08:32:08.698976Z", - "start_time": "2025-03-20T08:32:08.696420Z" + "end_time": "2025-03-20T10:38:45.059433Z", + "start_time": "2025-03-20T10:38:45.056942Z" } }, "cell_type": "code", @@ -518,16 +518,16 @@ "output_type": "stream", "text": [ "Combined Position to Properties Map:\n", - "33934: [43643 42071 60857 55451 24236]\n", - "3750: [58945 15680 21300 44486 53340]\n", - "42586: [45655 60860 14877 22660 57175]\n", - "25190: [10493 39600 25869 41758 52425]\n", - "7504: [17462 15784 12858 36853 5167]\n", - "35546: [ 5635 4102 50934 37697 2017]\n" + "10235: [53739 45744 43064 1128 59341]\n", + "12456: [14349 17444 47943 11012 47378]\n", + "898: [64971 29958 49025 53093 48497]\n", + "54650: [50952 27397 5623 14232 6840]\n", + "50445: [51008 60694 3145 26108 34437]\n", + "20719: [37461 8069 4890 5391 29587]\n" ] } ], - "execution_count": 41 + "execution_count": 89 }, { "metadata": {}, @@ -544,8 +544,8 @@ { "metadata": { "ExecuteTime": { - "end_time": "2025-03-20T08:32:08.762578Z", - "start_time": "2025-03-20T08:32:08.760236Z" + "end_time": "2025-03-20T10:38:45.070036Z", + "start_time": "2025-03-20T10:38:45.068009Z" } }, "cell_type": "code", @@ -557,25 +557,25 @@ "encoded_mask = user_cipher.encode_base64_str(mask)" ], "outputs": [], - "execution_count": 42 + "execution_count": 90 }, { "metadata": {}, "cell_type": "markdown", "source": [ "#### Encipher Passcode\n", - "UserCipherKeys.encipher_salt_hash_code:\n", - "\n", - "- ciphered_customer_prop = alpha_key ^ customer_prop\n", - "- ciphered_passcode_i = pass_key_i ^ ciphered_customer_prop_i\n", - "- code = hash(ciphered_passcode, salt)" + "1. Compute `combined_property_key`\n", + "2. Recover `user_passcode = ordered_combined_proptery_key`; order by passcode_property_indices\n", + "3. Zero pad `user_pascode`\n", + "4. Encipher `user_passcode` with `user.cipher.pass_key`\n", + "5. Hash `ciphered_passcode`" ] }, { "metadata": { "ExecuteTime": { - "end_time": "2025-03-20T08:32:09.024060Z", - "start_time": "2025-03-20T08:32:08.789902Z" + "end_time": "2025-03-20T10:38:45.320480Z", + "start_time": "2025-03-20T10:38:45.087096Z" } }, "cell_type": "code", @@ -583,48 +583,13 @@ "combined_prop_key = customer.cipher.property_key ^ user_cipher.property_key\n", "user_passcode = combined_prop_key[passcode_property_indices]\n", "pad_len = customer.nkode_policy.max_nkode_len - passcode_len\n", - "user_passcode_padded = np.concatenate((user_passcode, np.zeros(pad_len, dtype=user_passcode.dtype)))\n", - "ciphered_passcode = user_passcode_padded ^ user_cipher.pass_key\n", + "padded_passcode = np.concatenate((user_passcode, np.zeros(pad_len, dtype=user_passcode.dtype)))\n", + "ciphered_passcode = padded_passcode ^ user_cipher.pass_key\n", "passcode_prehash = base64.b64encode(hashlib.sha256(ciphered_passcode.tobytes()).digest())\n", "passcode_hash = bcrypt.hashpw(passcode_prehash, bcrypt.gensalt(rounds=12)).decode(\"utf-8\")" ], "outputs": [], - "execution_count": 43 - }, - { - "metadata": {}, - "cell_type": "markdown", - "source": [ - "### Enciphered nKode\n", - "An encipher passcode has two parts:\n", - "1. Code: the enciphered and hashed passcode\n", - "2. Mask: the mask is used to recover the passcode sets. The mask and the users key select are used to recover the property values of the user's passcode\n", - "The method UserCipherKeys.encipher_nkode secures a users nKode in the database. This method is called in api.confirm_nkode\n", - "```\n", - "class EncipheredNKode(BaseModel):\n", - " code: str\n", - " mask: str\n", - "```\n" - ] - }, - { - "metadata": { - "ExecuteTime": { - "end_time": "2025-03-20T08:32:09.032955Z", - "start_time": "2025-03-20T08:32:09.030937Z" - } - }, - "cell_type": "code", - "source": [ - "from src.models import EncipheredNKode\n", - "\n", - "enciphered_nkode = EncipheredNKode(\n", - " mask=encoded_mask,\n", - " code=passcode_hash,\n", - ")" - ], - "outputs": [], - "execution_count": 44 + "execution_count": 91 }, { "metadata": {}, @@ -632,14 +597,14 @@ "source": [ "### User Login\n", "1. Get login keypad\n", - "2. Login\n" + "2. Select keys with passcode icons (in our case, passcode property indices)\n" ] }, { "metadata": { "ExecuteTime": { - "end_time": "2025-03-20T08:32:09.273099Z", - "start_time": "2025-03-20T08:32:09.040255Z" + "end_time": "2025-03-20T10:38:45.559945Z", + "start_time": "2025-03-20T10:38:45.326214Z" } }, "cell_type": "code", @@ -657,29 +622,29 @@ "name": "stdout", "output_type": "stream", "text": [ - "Key 0: [24 1 14 27 16 11]\n", - "Key 1: [18 25 8 3 22 5]\n", - "Key 2: [12 13 20 21 10 23]\n", - "Key 3: [ 0 7 26 9 28 17]\n", - "Key 4: [ 6 19 2 15 4 29]\n", - "User Passcode: [19, 7, 10, 6]\n", + "Key 0: [18 25 14 15 4 29]\n", + "Key 1: [ 6 13 20 27 28 5]\n", + "Key 2: [24 19 26 9 16 23]\n", + "Key 3: [ 0 1 8 3 10 11]\n", + "Key 4: [12 7 2 21 22 17]\n", + "User Passcode: [28, 13, 9, 10]\n", "\n", "Selected Keys:\n", - " [4, 3, 2, 4]\n", + " [1, 1, 2, 3]\n", "\n" ] } ], - "execution_count": 45 + "execution_count": 92 }, { "metadata": {}, "cell_type": "markdown", "source": [ "## Validate Login Key Entry\n", - "- decipher user mask and recover nkode set values\n", - "- get presumed properties from key selection and set values\n", - "- encipher, salt and hash presumed properties values and compare it to the users hashed code" + "- decipher user mask and recover nkode position values\n", + "- get presumed properties from key selection and position values\n", + "- compare with hash" ] }, { @@ -687,22 +652,18 @@ "cell_type": "markdown", "source": [ "### Decipher Mask\n", - "Recall:\n", - "- combined_set_key = user_set_key ^ customer_set_key\n", - "- mask = mask_key ^ ordered_user_set_key\n", - "\n", - "Recover nKode set values: \n", + "Recover nKode position values:\n", "- decode mask from base64 to int\n", - "- ordered_user_set_key = mask ^ mask_key\n", - "- ordered_combined_set_key = ordered_customer_set_key ^ ordered_user_set_key\n", + "- ordered_user_position_key = mask ^ mask_key\n", + "- user_position_key = user.cipher.co\n", "- deduce the set indices" ] }, { "metadata": { "ExecuteTime": { - "end_time": "2025-03-20T08:32:09.282728Z", - "start_time": "2025-03-20T08:32:09.279895Z" + "end_time": "2025-03-20T10:38:45.570140Z", + "start_time": "2025-03-20T10:38:45.567396Z" } }, "cell_type": "code", @@ -711,34 +672,51 @@ "selected_keys_login = select_keys_with_passcode_values(passcode_property_indices, login_keypad, keypad_size.props_per_key)\n", "user = api.customers[customer_id].users[username]\n", "mask = user.cipher.decode_base64_str(user.enciphered_passcode.mask)\n", - "deciphered_mask = mask ^ user.cipher.mask_key\n", - "set_key = customer.cipher.position_key ^ user.cipher.combined_position_key\n", - "passcode_set_index = [int(np.where(set_key == set_cipher)[0][0]) for set_cipher in deciphered_mask[:passcode_len]]\n", - "presumed_selected_properties_idx = customer.users[username].user_keypad.get_prop_idxs_by_keynumb_setidx(selected_keys_login, passcode_set_index)\n", - "assert passcode_property_indices == presumed_selected_properties_idx\n" + "ordered_user_position_key = mask ^ user.cipher.mask_key\n", + "user_position_key = customer.cipher.position_key ^ user.cipher.combined_position_key\n" ], "outputs": [], - "execution_count": 46 + "execution_count": 93 }, { "metadata": {}, "cell_type": "markdown", - "source": "### Compare Enciphered Passcodes" + "source": [ + "#### Get Presumed Properties\n", + "- Get the passcode position indices (within the keys)\n", + "- Get the presumed property indices from the key and position within the key" + ] + }, + { + "metadata": {}, + "cell_type": "code", + "outputs": [], + "execution_count": null, + "source": [ + "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", + "assert passcode_property_indices == presumed_property_indices\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "### Compare Enciphered Passcodes\n" }, { "metadata": { "ExecuteTime": { - "end_time": "2025-03-20T08:32:09.526068Z", - "start_time": "2025-03-20T08:32:09.295445Z" + "end_time": "2025-03-20T10:38:45.809575Z", + "start_time": "2025-03-20T10:38:45.576610Z" } }, "cell_type": "code", "source": [ - "valid_nkode = user.cipher.compare_nkode(presumed_selected_properties_idx, customer.cipher, user.enciphered_passcode.code)\n", - "assert valid_nkode\n" + "valid_nkode = user.cipher.compare_nkode(presumed_property_indices, customer.cipher, user.enciphered_passcode.code)\n", + "assert valid_nkode" ], "outputs": [], - "execution_count": 47 + "execution_count": 94 }, { "metadata": {}, @@ -754,8 +732,8 @@ { "metadata": { "ExecuteTime": { - "end_time": "2025-03-20T08:32:09.996256Z", - "start_time": "2025-03-20T08:32:09.529950Z" + "end_time": "2025-03-20T10:38:46.286081Z", + "start_time": "2025-03-20T10:38:45.816688Z" } }, "cell_type": "code", @@ -765,110 +743,121 @@ " code = api.customers[customer_id].users[username].enciphered_passcode.code\n", " print(f\"mask: {mask}, code: {code}\\n\")\n", "\n", - "print_user_enciphered_code() \n", - "api.renew_keys(customer_id)\n", + "print(\"Old User Cipher and Mask\")\n", "print_user_enciphered_code()\n", - "\n", + "api.renew_keys(customer_id) # Steps 1 and 2\n", "login_keypad = api.get_login_keypad(username, customer_id)\n", "selected_keys_login = select_keys_with_passcode_values(passcode_property_indices, login_keypad, keypad_size.props_per_key)\n", - "success = api.login(customer_id, username, selected_keys_login)\n", - "assert success\n", - "print_user_enciphered_code()" + "success = api.login(customer_id, username, selected_keys_login) # Step 3\n", + "print(\"New User Cipher and Mask\")\n", + "print_user_enciphered_code()\n", + "assert success" ], "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "mask: cz9m1OunYlEK42X0jRrGAzKvheg=, code: $2b$12$Z.N7qwUTMgSVJFQC9hKgjeQ8owBpZMm5Aa14RQdiJH7C8l61QJENS\n", + "Old User Cipher and Mask\n", + "mask: y8aMd+5qYcPVLETTcs2aHqx2hhk=, code: $2b$12$wMi7WGmlch8kWMYJ2v.FHOne1.YSQPqKU/itpBuycwSFyasryF/2u\n", "\n", - "mask: cz9m1OunYlEK42X0jRrGAzKvheg=, code: $2b$12$Z.N7qwUTMgSVJFQC9hKgjeQ8owBpZMm5Aa14RQdiJH7C8l61QJENS\n", - "\n", - "mask: e+RtDYeB1G1RfuTOjCna6K9xLUU=, code: $2b$12$DHdD52jbBdVoXYArhWCm7eABlnch.tNhO/1Eipygj8fpoUFuPzyEC\n", + "New User Cipher and Mask\n", + "mask: aln5Su79utoVmqQXNCjYiUdwVYw=, code: $2b$12$gQf3UVa3cWMBy0CO0sBLyuJzdXGzg3qpNFMTD6MvycuR6N3gLFdgC\n", "\n" ] } ], - "execution_count": 48 + "execution_count": 95 }, { "metadata": {}, "cell_type": "markdown", "source": [ - "#### Renew Customer Keys\n", - "- Get old properties and sets\n", - "- Replace properties and sets" + "### Renew Customer Keys\n", + "The customer cipher keys are replaced." ] }, { "metadata": { "ExecuteTime": { - "end_time": "2025-03-20T08:32:10.012897Z", - "start_time": "2025-03-20T08:32:10.009292Z" + "end_time": "2025-03-20T10:38:46.296985Z", + "start_time": "2025-03-20T10:38:46.293584Z" } }, "cell_type": "code", "source": [ "old_props = customer.cipher.property_key.copy()\n", - "old_sets = customer.cipher.position_key.copy()\n", - "customer.cipher.renew()\n", + "old_pos = customer.cipher.position_key.copy()\n", + "customer.cipher.property_key = np.random.choice(2 ** 16, size=keypad_size.total_props, replace=False)\n", + "customer.cipher.position_key = np.random.choice(2 ** 16, size=keypad_size.props_per_key, replace=False)\n", "new_props = customer.cipher.property_key\n", - "new_sets = customer.cipher.position_key" + "new_pos = customer.cipher.position_key" ], "outputs": [], - "execution_count": 49 + "execution_count": 96 }, { "metadata": {}, "cell_type": "markdown", "source": [ "### Renew User\n", - "\n" + "User property and position keys go through an intermediate phase.\n", + "#### user.cipher.combined_position_key\n", + "- user_combined_position_key = user_combined_position_key XOR pos_xor\n", + "- user_combined_position_key = (user_position_key XOR old_customer_position_key) XOR (old_customer_position_key XOR new_customer_position_key)\n", + "- user_combined_position_key = user_position_key XOR new_customer_position_key\n", + "#### user.cipher.combined_position_key\n", + "- user_property_key = user_property_key XOR props_xor\n", + "- user_property_key = user_property_key XOR old_customer_property_key XOR new_customer_property_key\n" ] }, { "metadata": { "ExecuteTime": { - "end_time": "2025-03-20T08:32:10.019285Z", - "start_time": "2025-03-20T08:32:10.017224Z" + "end_time": "2025-03-20T10:38:46.312031Z", + "start_time": "2025-03-20T10:38:46.310019Z" } }, "cell_type": "code", "source": [ - "props_xor = np.bitwise_xor(new_props, old_props)\n", - "sets_xor = np.bitwise_xor(new_sets, old_sets)\n", + "props_xor = new_props ^ old_props\n", + "pos_xor = new_pos ^ old_pos\n", "for user in customer.users.values():\n", " user.renew = True\n", - " user.cipher.combined_position_key = np.bitwise_xor(user.cipher.combined_position_key, sets_xor)\n", - " user.cipher.property_key = np.bitwise_xor(user.cipher.property_key, props_xor)" + " user.cipher.combined_position_key = user.cipher.combined_position_key ^ pos_xor\n", + " user.cipher.property_key = user.cipher.property_key ^ props_xor" ], "outputs": [], - "execution_count": 50 + "execution_count": 97 }, { "metadata": {}, "cell_type": "markdown", - "source": "### Refresh User Keys" + "source": [ + "### Refresh User Keys\n", + "After a user's first successful login, the renew flag is checked. If it's true, the user's cipher is replaced with a new cipher." + ] }, { "metadata": { "ExecuteTime": { - "end_time": "2025-03-20T08:32:10.260051Z", - "start_time": "2025-03-20T08:32:10.026503Z" + "end_time": "2025-03-20T10:38:46.553807Z", + "start_time": "2025-03-20T10:38:46.318482Z" } }, "cell_type": "code", "source": [ - "user.cipher = UserCipher.create(\n", - " customer.cipher.keypad_size,\n", - " customer.cipher.position_key,\n", - " user.cipher.max_nkode_len\n", - ")\n", - "user.enciphered_passcode = user.cipher.encipher_nkode(presumed_selected_properties_idx, customer.cipher)\n", - "user.renew = False" + "if user.renew:\n", + " user.cipher = UserCipher.create(\n", + " customer.cipher.keypad_size,\n", + " customer.cipher.position_key,\n", + " user.cipher.max_nkode_len\n", + " )\n", + " user.enciphered_passcode = user.cipher.encipher_nkode(presumed_property_indices, customer.cipher)\n", + " user.renew = False" ], "outputs": [], - "execution_count": 51 + "execution_count": 98 } ], "metadata": {