Migrate Markdown-Notes: projects, meetings, reference, personal

This commit is contained in:
2026-01-26 22:05:01 +00:00
parent 9507ddf856
commit 49025b3586
93 changed files with 3422 additions and 11 deletions

View File

@@ -0,0 +1,184 @@
# nKode Tutorial
## nKode Keypad
- nKode keypad contains keys
- Each key has icons
- Each icon belongs to a set and has an index value associated with it
- The position within the key is the set value
- When attributes are shuffled, they'll always remain in the same position within the key
(note: the set value can be obuscated from the client but we find it helpful to quickly find the attribute)
## nKode Enrollment
- user sets then confirms their nKode
- Set and Confirm are dipersion of each other and allow the server to infer the users nKode
- the users login has additional icons added to each to key to make it dispersion resistant
- After the user as selected their nKode through the set and confirms,
the server can infer the users selection since each key selection will only have one icons in common.
- The users nKode is enciphered, salted and hashed.
## Dispersion
- Two keypads are dispersion of each other if:
Kp1: Keypad 1
Kp2: Keypad 2
for each key1 in Kp1:
for each key2 in Kp2:
iconsIntersection(key1, key2) <= 1
## Dispersion Algo
- Convert a Keypad view into a matrix view
- each row is key and each column is a set
- Fisher Yates the keys i.e. the rows in the matrix
- Fisher Yates an identity matrix equivalent to the number of keys
- The shuffled permutation is used to rotate the columns
## Dispersion Resistance
- Dispersion is only possible if {number of icons per key} <= {number keys in the keypad}
- If there are more icons per key than keys, it makes it difficult to phish for a users nkode
## Cipher Keys
#### attribute key
- randomly generated array of unsigned integars
- array of length {numb of keys} * {number of attributes per key}
- xored with ss-attr to give each user a unique
#### passcode key
- randomly generated array of unsigned integars
- array of length {max nKode length}
- xored with final user passcode
#### set key
- used to recover users nkode set values
- array of unsigned integars
- each elemenet in the array is a random number XOR'ed with the set value of the users nKode
- so `for set_key_i in user_set_key`
`set_key_i = user_passcode_set_i ^ random_set_key_i`
#### mask key
- used to recover users nkode set values
- array of random unsigned integars
#### server-side attributes (ss-attr) and sets (ss-set)
- Each icon has a server side attribute.
- The icon and the ss-attr are indexed to the same place in an array.
- The dispersion and shuffle operation are applied to the index array and the index array is applied to the icon and ss-attr
- ss-attrs are randomly generated permutation of unsigned ints (or byte arrays of any length for extra security)
### Encipher and Hash nKode Passcode
passcode = index values of the selected icons infered in set/comfirm
user_attrs = arr_xor(ss_attr, user_attr_key)
passcode_attr = [user_attrs[idx] for idx in passcode]
ciphered_passcode = arr_xor(passcode_attr, user_passcode_key)
// optional sha256 if ciphered_passcode is more than 72 bytes
passcode_digest = sha256(ciphered_passcode)
hashed_passcode = bcrypt(passcode_digest)
### Enicphering nKode Set
nKode mask is used to recover the users nKode
1. set_key_i = (set_rand_numb_i ^ set_val_i)
2. mask_key_i = mask_rand_numb_i
passcode = index values of the selected icons infered in set/comfirm
// recall ss_set array is an order list
set_idx = get_set_value(passcode)
user_set_keys = [set_key[idx] for idx in set_idx]
user_set_vals = [ss_sets[idx] for idx in set_idx]
mask = arr_xor(user_set_val, user_set_keys, mask_key)
- mask_i = mask_key_i ^ padded_passcode_server_set_i ^ set_key_i
- mask_i = mask_rand_num_i ^ set_val_i ^ set_rand_numb_i ^ set_val_i
- mask_i = mask_rand_num_i ^ set_rand_numb_i # set_val_i is cancelled out
#### nKode Validation
// set_val_i = mask_i ^ set_key_i ^ mask_key_i
// selected_keys the keys the user selects
recovered_set_vals = arr_xor(mask, set_key, mask_key)
user_keypad = get_user_keypad(username)
presumed_password = get_pressumed_passcode(user_key, selected_keys, recovered_set_val)
if is_valid_passcode(presumed_password, hashed_passcode)
return LOGIN_SUCCESS
else
return LOGIN_FAIL
## nKode Login Shuffle
- After a successful login, the users keypad is shuffled in a two step process:
1. the keys are randomly shuffled
2. half the sets are randomly shuffled
- We've found this works best for xyz reason and we're also working on simulations to find a probablity curve for number of overserveration before an adversery can crack an nkode
## nKode Login
- When a user request their nkode keypad, the server sends a list of svgs in the order they should be displayed
- The Gen2 demo implementation works a bit different it sends the svgs indexed in order from 0-total_numb_of_attr along with an index array for how the svgs should be ordered
- this is a legacy from the gen 1 keypad but it helps to make the implemntation more concrete so we'll use this legacy
- The frontend organized the svgs into keys and displays them.
- The user selects keys for their nkode and their key selection is sent back to the server for validation
## Preventing User Enumeration
- This isn't applied in the demo application
- We can prevent a threat actor from enumerating users.
- if a valid email is entered into the login for a user that dne, we can create a ghost keypad and have it behave as if it were a real user.
- if there are too many "failed nkode attempts" we lock the non-existing user out.
- We can prevent timing attacks by either mocking the real control flow or setting a 1 or 2 sec response delay from the time the login request was recieved thereby completely elimiating timing attacks
## Renew
Renew changes user ciphers, user salt, ss_attr, and ss_set.
This is import in the event of a partial database hack or leak.
An admin or cron job can run the renew with any frequency (daily, weekly, monthly)
Users are aware of this process.
Nothing changes for them.
### Three Step Renew
Renew has three phases
1. Server-Side Attribute Renewal: ss_attr and ss_set values are replaced with new values
2. Intermdiate User Renewal: every user goes through an intermediate phase before full Renewal
3. Full User Renewal: The user's first successful login completes the renewal. User has gets new salt, and cipher
#### Server-Side Attribute Renewal
old_ss_attr, old_ss_set = get_ss_vals()
renew_ss_vals() // new randomly generated values
new_ss_attr, new_ss_set = get_ss_vals()
xor_ss_attr = arr_xor(old_ss_attr, new_ss_attr)
xor_ss_set = arr_xor(old_ss_set, new_ss_set)
#### Intermdiate User Renewal
all_users = get_all_users()
for user in all_users:
user.renew = True // This flags the server to complete phase 3, full user renewal
user.set_key = xor_lists(user.set_key, xor_ss_set) // recall user.set_key = rand_num ^ old_ss_set. this operation cancels out old_ss_set and replaces it with new_ss_set
user.attribute_key = xor_lists(user.attribute_key, xor_ss_attr) // recall user.attribute_key ^ old_ss_attr are the user's nkode ss attributes so when we
#### Full User Renewal
After a successful login user keys are reset as if the user was signing up for the first time