Add Validate nkode

This commit is contained in:
2025-03-25 14:50:48 -05:00
parent 4f4f0bcea7
commit ee49b6cd53
4 changed files with 365 additions and 90 deletions

View File

@@ -0,0 +1,152 @@
# Encipher and Decipher nKode
### Customer Policy
- max nkode length: 10
- number of keys: 6
- properties per key: 9
- total number of properties: 54
### Customer Cipher
- property key: [50817 32783 33745 35836 30092 4212 15938 64571 58354 41241 3649 38852
37860 47294 10501 43278 9946 60484 34443 38446 57997 32874 49251 58321
15849 40891 43566 53732 31357 5248 22060 15762 23773 10428 22850 7975
11108 23454 32723 40871 6994 35130 41638 13889 6569 20765 56191 37770
4448 37031 30452 43080 24525 44717]
- position key: [25392 13634 17753 25555 61290 50870 49934 53104 9796]
---
### User Cipher
- property key: [35724 37130 47630 20125 52673 62248 61979 44917 17470 11483 20317 56084
34699 49571 32249 15009 43246 57623 21032 62384 61961 34049 1963 5370
1121 47700 26633 59166 16526 38173 56846 41594 54438 8714 46049 25028
38681 2017 39749 42164 38277 19216 23760 35115 23020 18954 26604 50262
21588 62239 30226 58722 12644 39141]
- passcode key: [51522 14440 21036 1484 4829 51359 61560 41543 23848 29080]
- combined position key: [14972 5803 54986 46940 19674 32943 38431 42194 29083]
- mask key: [15948 8251 52095 4511 25902 21701 15340 4458 15137 44295]
#### Combined Postion Key
```mermaid
block-beta
columns 2
user_pos["user position key:\n[22860 9193 37779 54415 41904 17945 21777 27554 22495]"]
customer_pos["customer position key:\n[25392 13634 17753 25555 61290 50870 49934 53104 9796]"]
space:2
xor(("XOR")):2
user_pos --> xor
customer_pos --> xor
space:2
comb_pos["combined position key\n[14972 5803 54986 46940 19674 32943 38431 42194 29083]"]:2
xor --> comb_pos
```
### User Keypad
- keypad:
- user passcode indices: [22, 6, 38, 21]
### nKode Cipher
#### Passcode Hash
```mermaid
block-beta
columns 2
cprop["customer_property_key\n[50817 32783 33745 35836 30092 4212 15938 64571 58354 41241 3649 38852
37860 47294 10501 43278 9946 60484 34443 38446 57997 32874 49251 58321
15849 40891 43566 53732 31357 5248 22060 15762 23773 10428 22850 7975
11108 23454 32723 40871 6994 35130 41638 13889 6569 20765 56191 37770
4448 37031 30452 43080 24525 44717]"]
uprop["user_property_key\n[35724 37130 47630 20125 52673 62248 61979 44917 17470 11483 20317 56084
34699 49571 32249 15009 43246 57623 21032 62384 61961 34049 1963 5370
1121 47700 26633 59166 16526 38173 56846 41594 54438 8714 46049 25028
38681 2017 39749 42164 38277 19216 23760 35115 23020 18954 26604 50262
21588 62239 30226 58722 12644 39141]"]
space:2
xor1(("XOR")):2
cprop --> xor1
uprop --> xor1
space:2
prop["combined_property_key\n[19725 4357 14815 50529 47181 58204 52313 21326 42956 36290 16668 19664
5231 31005 21756 37807 36404 3411 54435 26014 4228 1387 51144 63275
14728 9711 49703 14074 15091 33181 34850 40936 34939 2742 60067 32483
48253 23679 58518 15123 36567 49706 65142 49002 16453 6935 48275 22492
17716 25528 230 19754 28329 13896]"]
xor1 --> prop
pass["user_passcode_indices\n[22, 6, 38, 21]"]
space:2
sel(("select\properties")):2
pass --> sel
prop --> sel
space:2
passcode["user passcode properties:\n[51144 52313 58518 1387]"]:2
sel --> passcode
space:2
pad["zero pad to\nmax nkode length: 10"]:2
passcode -->pad
space:2
paddedpasscode["padded passcode:\n[51144 52313 58518 1387 0 0 0 0 0 0]"]
pad --> paddedpasscode
passkey["passcode key:\n[51522 14440 21036 1484 4829 51359 61560 41543 23848 29080]"]
space:2
xor2(("XOR")):2
passkey --> xor2
paddedpasscode --> xor2
space:2
cipheredpass["ciphered passcode:\n[ 3722 62513 46778 167 4829 51359 61560 41543 23848 29080]"]:2
xor2 --> cipheredpass
space:2
hash(("hash")):2
cipheredpass --> hash
space:2
cipheredhashed["hashed ciphered passcode:\n$2b$12$AQRZP88momhTaKGYaPzdiuBybg7V49SiZ8y9PQMoT0plZrEsbYO.K"]:2
hash --> cipheredhashed
```
#### Mask Encipher
```mermaid
block-beta
columns 3
passcode_idx["passcode indices:\n[22, 6, 38, 21]"]
comb_pos["combined position key:\n[14972 5803 54986 46940 19674 32943 38431 42194 29083]"]
cust_pos["customer position key:\n[25392 13634 17753 25555 61290 50870 49934 53104 9796]"]
space:3
propidx(["Get Position Idx:\nmap each to element mod props_per_key"])
passcode_idx-->propidx
space:1
xor1(("XOR"))
comb_pos --> xor1
cust_pos --> xor1
space:3
passcode_position_idx["passcode poition indices:\n[4, 6, 2, 3]"]
propidx --> passcode_position_idx
space:5
pad1(("Pad with\nrandom indices"))
passcode_position_idx --> pad1
space:5
posidx["Padded Passcode Position Indices:\n[4, 6, 2, 3, 7, 1, 8, 0, 5, 4]"]
pad1 --> posidx
space:1
user_pos["user position key:\n[22860 9193 37779 54415 41904 17945 21777 27554 22495]"]
xor1 --> user_pos
space:4
sel(("select positions"))
user_pos --> sel
posidx --> sel
space:5
passcode_pos["passcode positions:\n[41904 21777 37779 54415 27554 9193 22495 22860 17945 41904]"]
sel --> passcode_pos
mask_key["mask key\n[15948 8251 52095 4511 25902 21701 15340 4458 15137 44295]"]
space:4
xor2(("XOR"))
mask_key --> xor2
passcode_pos --> xor2
space:5
mask["enciphered mask:\n [40444 29994 22764 50448 3724 30508 27699 18470 32056 3767]"]
xor2 --> mask
```

View File

@@ -51,7 +51,6 @@ if __name__ == "__main__":
selected_keys_confirm = select_keys_with_passcode_values(passcode_property_indices, confirm_keypad, selected_keys_confirm = select_keys_with_passcode_values(passcode_property_indices, confirm_keypad,
keypad_size.numb_of_keys) keypad_size.numb_of_keys)
ordered_confirm_icons = emojis[confirm_keypad] ordered_confirm_icons = emojis[confirm_keypad]
print(f"Selected Keys\n{selected_keys_confirm}")
success = api.confirm_nkode(customer_id, selected_keys_confirm, signup_session_id) success = api.confirm_nkode(customer_id, selected_keys_confirm, signup_session_id)
context = { context = {
"email": "user@example.com", "email": "user@example.com",

View File

@@ -0,0 +1,79 @@
import base64
import hashlib
from pathlib import Path
import bcrypt
import numpy as np
from secrets import choice
from string import ascii_lowercase
from docs.scripts.utils import render_markdown_template, emojis
from src.models import NKodePolicy, KeypadSize
from src.nkode_api import NKodeAPI
from src.utils import select_keys_with_passcode_values
if __name__ == "__main__":
api = NKodeAPI()
policy = NKodePolicy(
max_nkode_len=10,
min_nkode_len=4,
distinct_positions=0,
distinct_properties=4,
)
keypad_size = KeypadSize(
numb_of_keys=6,
props_per_key=9
)
customer_id = api.create_new_customer(keypad_size, policy)
customer = api.get_customer(customer_id)
username = "test_username" + "".join([choice(ascii_lowercase) for _ in range(6)])
signup_session_id, set_signup_keypad = api.generate_signup_keypad(customer_id, username)
ordered_set_icons = emojis[set_signup_keypad]
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(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 = emojis[confirm_keypad]
success = api.confirm_nkode(customer_id, selected_keys_confirm, signup_session_id)
user = api.customers[customer_id].users[username]
combined_prop_key = user.cipher.property_key ^ customer.cipher.property_key
user_passcode = combined_prop_key[passcode_property_indices]
pad_len = customer.nkode_policy.max_nkode_len - passcode_len
padded_passcode = np.concatenate((user_passcode, np.zeros(pad_len, dtype=user_passcode.dtype)))
ciphered_passcode = padded_passcode ^ user.cipher.pass_key
passcode_prehash = base64.b64encode(hashlib.sha256(ciphered_passcode.tobytes()).digest())
passcode_hash = bcrypt.hashpw(passcode_prehash, bcrypt.gensalt(rounds=12)).decode("utf-8")
padded_passcode_position_indices = customer.cipher.get_passcode_position_indices_padded(
list(passcode_property_indices), customer.nkode_policy.max_nkode_len)
user_position_key = user.cipher.combined_position_key ^ customer.cipher.position_key
ordered_user_position_key = user_position_key[padded_passcode_position_indices]
mask = ordered_user_position_key ^ user.cipher.mask_key
encoded_mask = user.cipher.encode_base64_str(mask)
context = {
"max_nkode_len": policy.max_nkode_len,
"numb_of_keys": keypad_size.numb_of_keys,
"props_per_key": keypad_size.props_per_key,
"customer_property_key": customer.cipher.property_key,
"customer_position_key": customer.cipher.position_key,
"user_property_key": user.cipher.property_key,
"pass_key": user.cipher.pass_key,
"combined_position_key": user.cipher.combined_position_key,
"user_position_key": user_position_key,
"mask_key": user.cipher.mask_key,
"user_passcode_idxs": passcode_property_indices,
"combined_property_key": combined_prop_key,
"user_passcode_props": user_passcode,
"padded_passcode": padded_passcode,
"ciphered_passcode": ciphered_passcode,
"code": passcode_hash,
"passcode_position_idxs": padded_passcode_position_indices[:passcode_len],
"pad_user_passcode_idxs": padded_passcode_position_indices,
"ordered_user_position_key":ordered_user_position_key,
"mask": mask,
}
render_markdown_template(Path("../templates/encipher_decipher_nkode.template.md"), Path("../encipher_decipher_nkode.md"), context)

View File

@@ -1,46 +1,46 @@
# Encipher and Decipher nKode # Encipher and Decipher nKode
### Customer Policy ## Customer Policy
- max nkode length: {{ max_nkode_len }} - max nkode length: {{ max_nkode_len }}
- number of keys: {{ numb_of_keys }} - number of keys: {{ numb_of_keys }}
- properties per key: {{ props_per_key }} - properties per key: {{ props_per_key }}
- total number of properties: {{ numb_of_keys * props_per_key }} - total number of properties: {{ numb_of_keys * props_per_key }}
### Customer Cipher ## Customer Cipher
- property key: {{ customer_property_key }} - property key: {{ customer_property_key }}
- position key: {{ customer_position_key }} - position key: {{ customer_position_key }}
--- ---
### User Cipher ## User Cipher
- property key: {{ user_property_key }} - property key: {{ user_property_key }}
- passcode key: {{ pass_key }} - passcode key: {{ pass_key }}
- combined position key: {{ combined_position_key }} - combined position key: {{ combined_position_key }}
- mask key: {{ mask_key }} - mask key: {{ mask_key }}
#### Combined Postion Key ### Combined Postion Key
```mermaid ```mermaid
block-beta block-beta
columns 2 columns 2
user_pos["user postion key:\n{{user_postion_key}}"] user_pos["user position key:\n{{user_position_key}}"]
customer_pos["customer postion key:\n{{customer_position_key}}"] customer_pos["customer position key:\n{{customer_position_key}}"]
space:2 space:2
xor(("XOR")):2 xor(("XOR")):2
user_pos --> xor user_pos --> xor
customer_pos --> xor customer_pos --> xor
space:2 space:2
comb_pos["combined postion key\n{{combined_postion_key}}"]:2 comb_pos["combined position key\n{{combined_position_key}}"]:2
xor --> comb_pos xor --> comb_pos
``` ```
### User Keypad ## User Keypad
- keypad: {{ user_keypad}} - keypad: {{ user_keypad}}
- user passcode indicies: {{ user_passcode_idxs}} - user passcode indices: {{ user_passcode_idxs}}
### nKode Cipher ## nKode Cipher
#### Passcode Hash ### Passcode Hash
```mermaid ```mermaid
block-beta block-beta
columns 2 columns 2
@@ -51,15 +51,15 @@ columns 2
cprop --> xor1 cprop --> xor1
uprop --> xor1 uprop --> xor1
space:2 space:2
prop["combined_properity_key\n{{combined_property_key}}"] prop["combined_property_key\n{{combined_property_key}}"]
xor1 --> prop xor1 --> prop
pass["user_passcode_indicies\n{{user_passcode_idxs}}"] pass["user_passcode_indices\n{{user_passcode_idxs}}"]
space:2 space:2
sel(("select\nproperites")):2 sel(("select\nproperties")):2
pass --> sel pass --> sel
prop --> sel prop --> sel
space:2 space:2
passcode["passcode vals:\n{{passcode_vals}}"]:2 passcode["user passcode properties:\n{{user_passcode_props}}"]:2
sel --> passcode sel --> passcode
space:2 space:2
pad["zero pad to\nmax nkode length: {{max_nkode_len}}"]:2 pad["zero pad to\nmax nkode length: {{max_nkode_len}}"]:2
@@ -83,39 +83,43 @@ columns 2
hash --> cipheredhashed hash --> cipheredhashed
``` ```
#### Mask Encipher ### Mask Encipher
```mermaid ```mermaid
block-beta block-beta
columns 3 columns 3
passcode_idx["passcode indicies:\n{{user_passcode_idxs}}"] passcode_idx["passcode indices:\n{{user_passcode_idxs}}"]
comb_pos["combined position key"] comb_pos["combined position key:\n{{combined_position_key}}"]
cust_pos["customer position key"] cust_pos["customer position key:\n{{customer_position_key}}"]
space:3 space:3
pad1(("Pad with\nrandom indices")) propidx(["Get Position Idx:\nmap each to element mod props_per_key"])
passcode_idx-->propidx
space:1 space:1
xor1(("XOR")) xor1(("XOR"))
comb_pos --> xor1 comb_pos --> xor1
cust_pos --> xor1 cust_pos --> xor1
passcode_idx --> pad1
space:3 space:3
padded_passcode_idx["padded passcode indices:\n{{pad_user_passcode_idxs}}"] passcode_position_idx["passcode poition indices:\n{{passcode_position_idxs}}"]
pad1 --> padded_passcode_idx propidx --> passcode_position_idx
space:5 space:5
propidx(["Get Postion Idx:\nmap each to\nelement mod props_per_key"]) pad1(("Pad with\nrandom indices"))
padded_passcode_idx --> propidx passcode_position_idx --> pad1
space:5 space:5
posidx["Passcode Position Indices:\n{{passcode_pos_idx}}"] posidx["Padded Passcode Position Indices:\n{{pad_user_passcode_idxs}}"]
propidx --> posidx pad1 --> posidx
space:1 space:1
user_pos["user position key"] user_pos["user position key:\n{{user_position_key}}"]
xor1 --> user_pos xor1 --> user_pos
space:4 space:4
sel(("select\npositions")) sel(("select positions"))
user_pos --> sel user_pos --> sel
posidx --> sel posidx --> sel
space:5 space:5
passcode_pos["passcode positions:\n{{ordered_user_position_key}}"] passcode_pos["ordered user passcode positions:\n{{ordered_user_position_key}}"]
sel --> passcode_pos sel --> passcode_pos
mask_key["mask key\n{{mask_key}}"] mask_key["mask key\n{{mask_key}}"]
space:4 space:4
@@ -126,3 +130,44 @@ block-beta
mask["enciphered mask:\n {{mask}}"] mask["enciphered mask:\n {{mask}}"]
xor2 --> mask xor2 --> mask
``` ```
### Validate nKode
```mermaid
block-beta
columns 4
selected_keys["selected keys:\n{{selected_keys}}"]
login_keypad["login keypad:\n{{login_keypad}}"]
mask["enciphered mask:\n {{mask}}"]
mask_key["mask key:\n{{mask_key}}"]
space:6
user_position_key["user position key:\n{{user_position_key}}"]
passcode_pos["ordered user passcode positions:\n{{ordered_user_position_key}}"]
space:4
space:2
get_passcode_idxs(("recover passcode\nposition indices"))
space:7
passcode_pos_idxs["padded passcode position indices:\n{{pad_user_passcode_idxs}}"]
space:5
get_presumed_idxs(("recover passcode\nproperty indices"))
space:7
passcode_prop_idxs["presumed passcode property indices:\n{{user_passcode_idxs}}"]
space:7
sel(("select\nproperties"))
space:1
prop["combined_property_key\n{{combined_property_key}}"]
space:5
passcode_prop["presumed passcode properties:\n{{user_passcode_props}}"]
space:1
cipheredhashed["hashed ciphered passcode:\n{{code}}"]
space:6
comp(("compare"))
```