# Encipher, Decipher and Renew nKode ## Tenant Policy - max nkode length: 10 - number of keys: 6 - properties per key: 9 - total number of properties: 54 --- ## Deterministic CSPRNG - AES-CTR DRBG - ChaCha20 ## User Cipher Keys Derive keys in memory from PRNG above: - property key: [ 6890 54130 42240 40467 46502 31074 10598 63689 27697 54461 21116 31999 10698 14870 50779 48637 29314 33075 52993 42014 2837 1935 34274 63380 36021 26329 20788 39848 7335 2619 61516 61122 39878 32506 19151 6611 2803 10730 53682 39987 11998 42378 6081 8624 34336 15222 35632 33233 4072 53750 54671 63845 2770 43728] - passcode key: [10632 49355 48031 9925 15082 24190 5137 14304 24524 16141] - user position key: [45632 9012 27470 28203 15901 7554 16974 54240 53827] - mask key: [ 8177 54825 26281 51895 8940 16695 19756 63041 7376 54396] --- ## User Keypad - keypad example:
- user passcode indices: [48 12 7 36] --- ## nKode Cipher ### Passcode Hash ```mermaid block-beta columns 2 prop["user_property_key\n[ 6890 54130 42240 40467 46502 31074 10598 63689 27697 54461 21116 31999 10698 14870 50779 48637 29314 33075 52993 42014 2837 1935 34274 63380 36021 26329 20788 39848 7335 2619 61516 61122 39878 32506 19151 6611 2803 10730 53682 39987 11998 42378 6081 8624 34336 15222 35632 33233 4072 53750 54671 63845 2770 43728]"] pass["user_passcode_indices\n[48 12 7 36]"] space:2 sel(("select\nproperties")):2 pass --> sel prop --> sel space:2 passcode["user passcode properties:\n[ 4072 10698 63689 2803]"]:2 sel --> passcode space:2 pad["zero pad to\nmax nkode length: 10"]:2 passcode -->pad space:2 paddedpasscode["padded passcode:\n[ 4072 10698 63689 2803 0 0 0 0 0 0]"] pad --> paddedpasscode passkey["passcode key:\n[10632 49355 48031 9925 15082 24190 5137 14304 24524 16141]"] space:2 xor2(("XOR")):2 passkey --> xor2 paddedpasscode --> xor2 space:2 cipheredpass["ciphered passcode:\n[ 9824 59649 17238 11318 15082 24190 5137 14304 24524 16141]"]:2 xor2 --> cipheredpass space:2 hash(("hash")):2 cipheredpass --> hash space:2 cipheredhashed["hashed ciphered passcode:\n$2b$12$XcXlcNKMyXQziv.kQWKngO88KUcm.xrn4YRZOOhGgIyMmpMw7NPJa"]:2 hash --> cipheredhashed ``` ### Mask Encipher ```mermaid block-beta columns 2 passcode_idx["passcode indices:\n[48 12 7 36]"] space:3 propidx(["Get Position Idx:\nmap each to element mod props_per_key"]) passcode_idx-->propidx space:3 passcode_position_idx["passcode poition indices:\n[3, 3, 7, 0]"] propidx --> passcode_position_idx space:3 pad1(("Pad with\nrandom indices")) passcode_position_idx --> pad1 space:3 posidx["Padded Passcode Position Indices:\n[3, 3, 7, 0, 0, 0, 5, 8, 8, 8]"] pad1 --> posidx user_pos["user position key:\n[45632 9012 27470 28203 15901 7554 16974 54240 53827]"] space:2 sel(("select positions")) user_pos --> sel posidx --> sel space:3 passcode_pos["ordered user passcode positions:\n[28203 28203 54240 45632 45632 45632 7554 53827 53827 53827]"] sel --> passcode_pos mask_key["mask key\n[ 8177 54825 26281 51895 8940 16695 19756 63041 7376 54396]"] space:2 xor2(("XOR")) mask_key --> xor2 passcode_pos --> xor2 space:3 mask["enciphered mask:\n cdq4ArVJePcB2PN3D2LrwyLN6mE="] xor2 --> mask ``` ### Validate nKode ```mermaid block-beta columns 3 selected_keys["keys selected by user during login:\n[1, 3, 1, 4]"] login_keypad["login keypad:\nKey 0: [ 9 28 2 39 49 32 42 34 44] Key 1: [ 0 1 20 48 40 50 51 7 35] Key 2: [18 19 47 21 13 14 24 25 8] Key 3: [27 10 11 12 4 5 6 16 17] Key 4: [36 37 38 3 22 23 33 43 53] Key 5: [45 46 29 30 31 41 15 52 26] "] space:4 selectkeys(("filter keys")) mask["enciphered mask:\n cdq4ArVJePcB2PN3D2LrwyLN6mE="] mask_key["mask key:\n[ 8177 54825 26281 51895 8940 16695 19756 63041 7376 54396]"] space:2 xor1(("XOR")) mask --> xor1 mask_key --> xor1 selected_keys --> selectkeys login_keypad --> selectkeys space:3 ordered_keys["ordered keys:\n[[ 0 1 20 48 40 50 51 7 35] [27 10 11 12 4 5 6 16 17] [ 0 1 20 48 40 50 51 7 35] [36 37 38 3 22 23 33 43 53]]"] user_position_key["user position key:\n[45632 9012 27470 28203 15901 7554 16974 54240 53827]"] passcode_pos["ordered user passcode positions:\n[28203 28203 54240 45632 45632 45632 7554 53827 53827 53827]"] selectkeys --> ordered_keys xor1 --> passcode_pos space:8 get_passcode_idxs(("recover passcode\nposition indices")) user_position_key --> get_passcode_idxs passcode_pos --> get_passcode_idxs space:8 passcode_pos_idxs["padded passcode position indices:\n[3, 3, 7, 0, 0, 0, 5, 8, 8, 8]"] get_passcode_idxs --> passcode_pos_idxs space:3 get_presumed_idxs(("recover passcode\nproperty indices")) ordered_keys --> get_presumed_idxs passcode_pos_idxs --> get_presumed_idxs space:5 passcode_prop_idxs["presumed passcode property indices:\n[48 12 7 36]"] prop["user_property_key\n[ 6890 54130 42240 40467 46502 31074 10598 63689 27697 54461 21116 31999 10698 14870 50779 48637 29314 33075 52993 42014 2837 1935 34274 63380 36021 26329 20788 39848 7335 2619 61516 61122 39878 32506 19151 6611 2803 10730 53682 39987 11998 42378 6081 8624 34336 15222 35632 33233 4072 53750 54671 63845 2770 43728]"] cipheredhashed["hashed ciphered passcode:\n$2b$12$XcXlcNKMyXQziv.kQWKngO88KUcm.xrn4YRZOOhGgIyMmpMw7NPJa"] get_presumed_idxs --> passcode_prop_idxs space:3 sel(("select\nproperties")) passcode_prop_idxs --> sel prop --> sel space:5 passcode_prop["presumed passcode properties:\n[ 4072 10698 63689 2803]"] sel --> passcode_prop space:5 cipher(("encipher")) passcode_prop --> cipher space:5 cipheredpass["ciphered passcode:\n[ 9824 59649 17238 11318 15082 24190 5137 14304 24524 16141]"] cipher --> cipheredpass space:7 comp{"compare"} cipheredpass --> comp cipheredhashed --> comp space:5 suc(("success")) comp --"Equal"--> suc ``` ## Renew A renewal happens every login ### Nonce Renew With ChaCha20, we can renew the keys and hash every login with a new nonce ### Secret Renew The secret is renewed less frequently. It's stored securely using a service like AWS Secrets Manager.