refactor render_markdown.py
This commit is contained in:
@@ -36,7 +36,7 @@ policy = NKodePolicy(
|
||||
|
||||
keypad_size = KeypadSize(
|
||||
numb_of_keys = {{ keypad_size.numb_of_keys }},
|
||||
attrs_per_key = {{ keypad_size.attrs_per_key }} # aka number of sets
|
||||
props_per_key = {{ keypad_size.props_per_key }} # aka number of sets
|
||||
)
|
||||
|
||||
customer_id = api.create_new_customer(keypad_size, policy)
|
||||
@@ -44,9 +44,9 @@ customer = api.customers[customer_id]
|
||||
```
|
||||
### Customer Attributes and Sets
|
||||
A customer has users and defines the attributes and set values for all its users.
|
||||
Since our customer has {{ keypad_size.numb_of_keys }} keys and {{ keypad_size.attrs_per_key }} attributes per key,
|
||||
this gives a customer interface of {{ keypad_size.numb_of_attrs }} distinct attributes and {{ keypad_size.attrs_per_key }} distinct attribute sets.
|
||||
Each attribute belongs to one of the {{ keypad_size.attrs_per_key }} sets. Each attribute and set value is a unique 2-byte integer in this example.
|
||||
Since our customer has {{ keypad_size.numb_of_keys }} keys and {{ keypad_size.props_per_key }} attributes per key,
|
||||
this gives a customer interface of {{ keypad_size.numb_of_props }} distinct attributes and {{ keypad_size.props_per_key }} distinct attribute sets.
|
||||
Each attribute belongs to one of the {{ keypad_size.props_per_key }} sets. Each attribute and set value is a unique 2-byte integer in this example.
|
||||
|
||||
```
|
||||
set_vals = customer.attributes.set_vals
|
||||
@@ -56,7 +56,7 @@ Customer Sets: {{ customer_set_vals }}
|
||||
|
||||
```
|
||||
attr_vals = customer.attributes.attr_vals
|
||||
keypad_view(attr_vals, keypad_size.attrs_per_key)
|
||||
keypad_view(attr_vals, keypad_size.props_per_key)
|
||||
|
||||
Customer Attributes:
|
||||
{% for attrs in customer_attr_view -%}
|
||||
@@ -85,15 +85,15 @@ Now that we have a customer, we can create users. To create a new user:
|
||||
The user's interface must be dispersable so the server can determine the user's nkode.
|
||||
The server randomly drops attribute sets until
|
||||
the number of attributes equals the number of keys, making the interface dispersable.
|
||||
In our case, the server randomly drops {{ keypad_size.attrs_per_key - keypad_size.numb_of_keys }} attribute {{ "sets" if keypad_size.attrs_per_key - keypad_size.numb_of_keys > 1 else "set" }}.
|
||||
to give us a {{ keypad_size.numb_of_keys }} X {{ keypad_size.numb_of_keys }} keypad with possible index values ranging from 0-{{ keypad_size.numb_of_attrs - 1 }}.
|
||||
In our case, the server randomly drops {{ keypad_size.props_per_key - keypad_size.numb_of_keys }} attribute {{ "sets" if keypad_size.props_per_key - keypad_size.numb_of_keys > 1 else "set" }}.
|
||||
to give us a {{ keypad_size.numb_of_keys }} X {{ keypad_size.numb_of_keys }} keypad with possible index values ranging from 0-{{ keypad_size.numb_of_props - 1 }}.
|
||||
Each value in the interface is the index value of a customer attribute.
|
||||
The user never learns what their "real" attribute is. They do not see the index value representing their nKode or
|
||||
the customer server-side value.
|
||||
|
||||
```
|
||||
session_id, signup_interface = api.generate_index_interface(customer_id)
|
||||
signup_interface_keypad = list_to_matrix(signup_interface, keypad_size.attrs_per_key)
|
||||
signup_interface_keypad = list_to_matrix(signup_interface, keypad_size.props_per_key)
|
||||
|
||||
Signup Keypad:
|
||||
{% for key in signup_keypad -%}
|
||||
@@ -110,7 +110,7 @@ If users want to change anything about their interface, they must also change th
|
||||
```
|
||||
username = {{ username }}
|
||||
user_passcode = {{ user_passcode }}
|
||||
selected_keys_set = select_keys_with_passcode_values(user_passcode, signup_interface, keypad_size.attrs_per_key)
|
||||
selected_keys_set = select_keys_with_passcode_values(user_passcode, signup_interface, keypad_size.props_per_key)
|
||||
|
||||
Selected Keys
|
||||
{{ selected_keys_set }}
|
||||
@@ -161,11 +161,11 @@ Steps 1-2 are straightforward. For a better idea of how they work, see pyNKode.
|
||||
|
||||
##### User Cipher Keys Data Structure
|
||||
```
|
||||
set_key = generate_random_nonrepeating_list(keypad_size.attrs_per_key, max_numb=2**(8*numb_of_bytes))
|
||||
set_key = generate_random_nonrepeating_list(keypad_size.props_per_key, max_numb=2**(8*numb_of_bytes))
|
||||
set_key = xor_lists(set_key, customer_attr.set_vals)
|
||||
|
||||
UserCipherKeys(
|
||||
prop_key=generate_random_nonrepeating_list(keypad_size.attrs_per_key * keypad_size.numb_of_keys, max_numb=2**(8*numb_of_bytes)),
|
||||
prop_key=generate_random_nonrepeating_list(keypad_size.props_per_key * keypad_size.numb_of_keys, max_numb=2**(8*numb_of_bytes)),
|
||||
pass_key=generate_random_nonrepeating_list(max_nkode_len, max_numb=2**(8*numb_of_bytes)),
|
||||
mask_key=generate_random_nonrepeating_list(max_nkode_len, max_numb=2**(8*numb_of_bytes)),
|
||||
set_key=set_key,
|
||||
@@ -176,13 +176,13 @@ UserCipherKeys(
|
||||
|
||||
##### User Cipher Keys Values
|
||||
```
|
||||
user_keys = UserCipherKeys(
|
||||
prop_key = {{ user_keys.prop_key }},
|
||||
pass_key = {{ user_keys.pass_key }},
|
||||
mask_key = {{ user_keys.mask_key }},
|
||||
set_key = {{ user_keys.set_key }},
|
||||
salt = {{ user_keys.salt }},
|
||||
max_nkode_len = {{ user_keys.max_nkode_len }}
|
||||
user_cipher = UserCipherKeys(
|
||||
prop_key = {{ user_cipher.prop_key }},
|
||||
pass_key = {{ user_cipher.pass_key }},
|
||||
mask_key = {{ user_cipher.mask_key }},
|
||||
set_key = {{ user_cipher.set_key }},
|
||||
salt = {{ user_cipher.salt }},
|
||||
max_nkode_len = {{ user_cipher.max_nkode_len }}
|
||||
)
|
||||
```
|
||||
|
||||
@@ -219,15 +219,15 @@ Passcode Attr Vals: {{ passcode_server_set }}
|
||||
```
|
||||
|
||||
```
|
||||
padded_passcode_server_set = user_keys.pad_user_mask(passcode_server_set, customer.nkode_policy.max_nkode_len)
|
||||
padded_passcode_server_set = user_cipher.pad_user_mask(passcode_server_set, customer.nkode_policy.max_nkode_len)
|
||||
|
||||
set_idx = [customer.attributes.get_set_index(set_val) for set_val in padded_passcode_server_set]
|
||||
mask_set_keys = [user_keys.set_key[idx] for idx in set_idx]
|
||||
mask_set_keys = [user_cipher.set_key[idx] for idx in set_idx]
|
||||
|
||||
ciphered_mask = xor_lists(mask_set_keys, padded_passcode_server_set)
|
||||
ciphered_mask = xor_lists(ciphered_mask, user_keys.mask_key)
|
||||
ciphered_mask = xor_lists(ciphered_mask, user_cipher.mask_key)
|
||||
|
||||
mask = user_keys.encode_base64_str(ciphered_mask)
|
||||
mask = user_cipher.encode_base64_str(ciphered_mask)
|
||||
Mask: {{ enciphered_nkode.mask }}
|
||||
```
|
||||
|
||||
@@ -238,17 +238,17 @@ Mask: {{ enciphered_nkode.mask }}
|
||||
- code = hash(ciphered_passcode, salt)
|
||||
|
||||
```
|
||||
ciphered_customer_attrs = xor_lists(customer.attributes.attr_vals, user_keys.prop_key)
|
||||
ciphered_customer_attrs = xor_lists(customer.attributes.attr_vals, user_cipher.prop_key)
|
||||
passcode_ciphered_attrs = [ciphered_customer_attrs[idx] for idx in passcode]
|
||||
pad_len = customer.nkode_policy.max_nkode_len - passcode_len
|
||||
|
||||
passcode_ciphered_attrs.extend([0 for _ in range(pad_len)])
|
||||
|
||||
ciphered_code = xor_lists(passcode_ciphered_attrs, user_keys.pass_key)
|
||||
ciphered_code = xor_lists(passcode_ciphered_attrs, user_cipher.pass_key)
|
||||
|
||||
passcode_bytes = int_array_to_bytes(ciphered_code)
|
||||
passcode_digest = base64.b64encode(hashlib.sha256(passcode_bytes).digest())
|
||||
hashed_data = bcrypt.hashpw(passcode_digest, user_keys.salt)
|
||||
hashed_data = bcrypt.hashpw(passcode_digest, user_cipher.salt)
|
||||
code = hashed_data.decode("utf-8")
|
||||
|
||||
Code: {{ enciphered_nkode.code }}
|
||||
@@ -264,7 +264,7 @@ To login, a user:
|
||||
The client requests the user's login interface.
|
||||
```
|
||||
login_interface = api.get_login_interface(username, customer_id)
|
||||
keypad_view(login_interface, keypad_size.attrs_per_key)
|
||||
keypad_view(login_interface, keypad_size.props_per_key)
|
||||
```
|
||||
The server returns a randomly shuffled interface. Learn more about how the [User Interface Shuffle](nkode_concepts.md/#user-interface-shuffle) works
|
||||
```
|
||||
@@ -301,11 +301,11 @@ Recover nKode set values:
|
||||
|
||||
```
|
||||
user = customer.users[username]
|
||||
user_keys = user.user_keys
|
||||
user_cipher = user.user_cipher
|
||||
user_mask = user.enciphered_passcode.mask
|
||||
decoded_mask = user_keys.decode_base64_str(user_mask)
|
||||
deciphered_mask = xor_lists(decoded_mask, user_keys.mask_key)
|
||||
set_key_rand_component = xor_lists(set_vals, user_keys.set_key)
|
||||
decoded_mask = user_cipher.decode_base64_str(user_mask)
|
||||
deciphered_mask = xor_lists(decoded_mask, user_cipher.mask_key)
|
||||
set_key_rand_component = xor_lists(set_vals, user_cipher.set_key)
|
||||
passcode_sets = []
|
||||
for set_cipher in deciphered_mask[:passcode_len]:
|
||||
set_idx = set_key_rand_component.index(set_cipher)
|
||||
@@ -331,7 +331,7 @@ Recall User Passcode: {{ user_passcode }}
|
||||
```
|
||||
### Compare Enciphered Passcodes
|
||||
```
|
||||
enciphered_nkode = user_keys.encipher_salt_hash_code(presumed_selected_attributes_idx, customer.attributes)
|
||||
enciphered_nkode = user_cipher.encipher_salt_hash_code(presumed_selected_attributes_idx, customer.attributes)
|
||||
```
|
||||
If `enciphered_nkode == user.enciphered_passcode.code`, the user's key selection is valid, and the login is successful.
|
||||
|
||||
@@ -388,8 +388,8 @@ attrs_xor = xor_lists(new_attrs, old_attrs)
|
||||
sets_xor = xor_lists(new_sets, old_sets)
|
||||
for user in customer.users.values():
|
||||
user.renew = True
|
||||
user.user_keys.set_key = xor_lists(user.user_keys.set_key, sets_xor)
|
||||
user.user_keys.prop_key = xor_lists(user.user_keys.prop_key, attrs_xor)
|
||||
user.user_cipher.set_key = xor_lists(user.user_cipher.set_key, sets_xor)
|
||||
user.user_cipher.prop_key = xor_lists(user.user_cipher.prop_key, attrs_xor)
|
||||
```
|
||||
##### User prop Key
|
||||
The user's prop key was a randomly generated list of length `numb_of_keys * attr_per_key`.
|
||||
@@ -412,11 +412,11 @@ remains the same.
|
||||
Once the user has a successful login, they get a new salt and cipher keys, and their `enciphered_passcode` is recomputed
|
||||
with the new values.
|
||||
```
|
||||
user.user_keys = UserCipherKeys.new(
|
||||
user.user_cipher = UserCipherKeys.new(
|
||||
customer.attributes.keypad_size,
|
||||
customer.attributes.set_vals,
|
||||
user.user_keys.max_nkode_len
|
||||
user.user_cipher.max_nkode_len
|
||||
)
|
||||
user.enciphered_passcode = user.user_keys.encipher_nkode(presumed_selected_attributes_idx, customer.attributes)
|
||||
user.enciphered_passcode = user.user_cipher.encipher_nkode(presumed_selected_attributes_idx, customer.attributes)
|
||||
user.renew = False
|
||||
```
|
||||
|
||||
@@ -15,8 +15,9 @@ def random_username() -> str:
|
||||
return "test_username" + "".join([choice(ascii_lowercase) for _ in range(6)])
|
||||
|
||||
|
||||
def select_keys_with_passcode_values(user_passcode: list[int], interface: list[int], attrs_per_key: int) -> list[int]:
|
||||
return [interface.index(attr) // attrs_per_key for attr in user_passcode]
|
||||
def select_keys_with_passcode_values(user_passcode: list[int], keypad: np.ndarray, attrs_per_key: int) -> list[int]:
|
||||
indices = [np.where(keypad == attr)[0][0] for attr in user_passcode]
|
||||
return [int(index // attrs_per_key) for index in indices]
|
||||
|
||||
|
||||
def visualize_keypad(keypad_list: np.ndarray, props_per_key: int):
|
||||
@@ -39,7 +40,7 @@ def render_nkode_authentication(data: dict):
|
||||
output = template.render(data)
|
||||
|
||||
# Print or save the output
|
||||
output_file = "/Users/donov/Desktop/NKode_documentation/nkode/docs/nkode_authentication.md"
|
||||
output_file = os.path.expanduser("~/Desktop/nkode_authentication.md")
|
||||
with open(output_file, 'w') as fp:
|
||||
fp.write(output)
|
||||
print("File written successfully")
|
||||
@@ -71,18 +72,17 @@ if __name__ == "__main__":
|
||||
set_attribute_dict = dict(zip(set_vals, attr_set_view))
|
||||
|
||||
session_id, signup_interface = api.generate_signup_keypad(customer_id)
|
||||
#signup_keypad = list_to_matrix(signup_keypad, keypad_size.numb_of_keys)
|
||||
signup_keypad = signup_interface.reshape(-1, keypad_size.props_per_key)
|
||||
signup_keypad = signup_interface.reshape(-1, keypad_size.numb_of_keys)
|
||||
|
||||
username = random_username()
|
||||
passcode_len = 4
|
||||
user_passcode = signup_interface[:passcode_len]
|
||||
user_passcode = signup_interface[:passcode_len].tolist()
|
||||
selected_keys_set = select_keys_with_passcode_values(user_passcode, signup_interface, keypad_size.numb_of_keys)
|
||||
server_side_attr = [customer.cipher.prop_key[idx] for idx in user_passcode]
|
||||
|
||||
confirm_interface = api.set_nkode(username, customer_id, selected_keys_set, session_id)
|
||||
|
||||
confirm_keypad = list_to_matrix(confirm_interface, keypad_size.numb_of_keys)
|
||||
confirm_keypad = confirm_interface.reshape(-1, keypad_size.numb_of_keys)
|
||||
|
||||
selected_keys_confirm = select_keys_with_passcode_values(user_passcode, confirm_interface, keypad_size.numb_of_keys)
|
||||
|
||||
@@ -121,7 +121,7 @@ if __name__ == "__main__":
|
||||
USER LOGIN
|
||||
"""
|
||||
login_interface = api.get_login_keypad(username, customer_id)
|
||||
login_keypad = list_to_matrix(login_interface, keypad_size.props_per_key)
|
||||
login_keypad = login_interface.reshape(-1, keypad_size.props_per_key)
|
||||
selected_keys_login = select_keys_with_passcode_values(user_passcode, login_interface, keypad_size.props_per_key)
|
||||
success = api.login(customer_id, username, selected_keys_login)
|
||||
assert success
|
||||
@@ -141,7 +141,7 @@ if __name__ == "__main__":
|
||||
login_passcode_sets = []
|
||||
for set_cipher in deciphered_mask[:passcode_len]:
|
||||
set_idx = np.where(set_key_rand_component == set_cipher)[0][0]
|
||||
login_passcode_sets.append(set_vals[set_idx])
|
||||
login_passcode_sets.append(int(set_vals[set_idx]))
|
||||
|
||||
"""
|
||||
GET PRESUMED ATTRIBUTES
|
||||
@@ -200,7 +200,7 @@ if __name__ == "__main__":
|
||||
'server_side_attr': server_side_attr,
|
||||
'confirm_keypad': confirm_keypad,
|
||||
'selected_keys_confirm': selected_keys_confirm,
|
||||
'cipher': user_keys,
|
||||
'user_cipher': user_keys,
|
||||
'passcode_server_attr': passcode_server_attr,
|
||||
'passcode_server_set': passcode_server_set,
|
||||
'enciphered_nkode': enciphered_nkode,
|
||||
|
||||
Reference in New Issue
Block a user