refactor render_markdown.py
This commit is contained in:
@@ -36,7 +36,7 @@ policy = NKodePolicy(
|
|||||||
|
|
||||||
keypad_size = KeypadSize(
|
keypad_size = KeypadSize(
|
||||||
numb_of_keys = {{ keypad_size.numb_of_keys }},
|
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)
|
customer_id = api.create_new_customer(keypad_size, policy)
|
||||||
@@ -44,9 +44,9 @@ customer = api.customers[customer_id]
|
|||||||
```
|
```
|
||||||
### Customer Attributes and Sets
|
### Customer Attributes and Sets
|
||||||
A customer has users and defines the attributes and set values for all its users.
|
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,
|
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_attrs }} distinct attributes and {{ keypad_size.attrs_per_key }} distinct attribute sets.
|
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.attrs_per_key }} sets. Each attribute and set value is a unique 2-byte integer in this example.
|
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
|
set_vals = customer.attributes.set_vals
|
||||||
@@ -56,7 +56,7 @@ Customer Sets: {{ customer_set_vals }}
|
|||||||
|
|
||||||
```
|
```
|
||||||
attr_vals = customer.attributes.attr_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:
|
Customer Attributes:
|
||||||
{% for attrs in customer_attr_view -%}
|
{% 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 user's interface must be dispersable so the server can determine the user's nkode.
|
||||||
The server randomly drops attribute sets until
|
The server randomly drops attribute sets until
|
||||||
the number of attributes equals the number of keys, making the interface dispersable.
|
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" }}.
|
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_attrs - 1 }}.
|
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.
|
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 user never learns what their "real" attribute is. They do not see the index value representing their nKode or
|
||||||
the customer server-side value.
|
the customer server-side value.
|
||||||
|
|
||||||
```
|
```
|
||||||
session_id, signup_interface = api.generate_index_interface(customer_id)
|
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:
|
Signup Keypad:
|
||||||
{% for key in 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 }}
|
username = {{ username }}
|
||||||
user_passcode = {{ user_passcode }}
|
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
|
||||||
{{ selected_keys_set }}
|
{{ 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
|
##### 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)
|
set_key = xor_lists(set_key, customer_attr.set_vals)
|
||||||
|
|
||||||
UserCipherKeys(
|
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)),
|
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)),
|
mask_key=generate_random_nonrepeating_list(max_nkode_len, max_numb=2**(8*numb_of_bytes)),
|
||||||
set_key=set_key,
|
set_key=set_key,
|
||||||
@@ -176,13 +176,13 @@ UserCipherKeys(
|
|||||||
|
|
||||||
##### User Cipher Keys Values
|
##### User Cipher Keys Values
|
||||||
```
|
```
|
||||||
user_keys = UserCipherKeys(
|
user_cipher = UserCipherKeys(
|
||||||
prop_key = {{ user_keys.prop_key }},
|
prop_key = {{ user_cipher.prop_key }},
|
||||||
pass_key = {{ user_keys.pass_key }},
|
pass_key = {{ user_cipher.pass_key }},
|
||||||
mask_key = {{ user_keys.mask_key }},
|
mask_key = {{ user_cipher.mask_key }},
|
||||||
set_key = {{ user_keys.set_key }},
|
set_key = {{ user_cipher.set_key }},
|
||||||
salt = {{ user_keys.salt }},
|
salt = {{ user_cipher.salt }},
|
||||||
max_nkode_len = {{ user_keys.max_nkode_len }}
|
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]
|
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(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 }}
|
Mask: {{ enciphered_nkode.mask }}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -238,17 +238,17 @@ Mask: {{ enciphered_nkode.mask }}
|
|||||||
- code = hash(ciphered_passcode, salt)
|
- 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]
|
passcode_ciphered_attrs = [ciphered_customer_attrs[idx] for idx in passcode]
|
||||||
pad_len = customer.nkode_policy.max_nkode_len - passcode_len
|
pad_len = customer.nkode_policy.max_nkode_len - passcode_len
|
||||||
|
|
||||||
passcode_ciphered_attrs.extend([0 for _ in range(pad_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_bytes = int_array_to_bytes(ciphered_code)
|
||||||
passcode_digest = base64.b64encode(hashlib.sha256(passcode_bytes).digest())
|
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 = hashed_data.decode("utf-8")
|
||||||
|
|
||||||
Code: {{ enciphered_nkode.code }}
|
Code: {{ enciphered_nkode.code }}
|
||||||
@@ -264,7 +264,7 @@ To login, a user:
|
|||||||
The client requests the user's login interface.
|
The client requests the user's login interface.
|
||||||
```
|
```
|
||||||
login_interface = api.get_login_interface(username, customer_id)
|
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
|
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 = customer.users[username]
|
||||||
user_keys = user.user_keys
|
user_cipher = user.user_cipher
|
||||||
user_mask = user.enciphered_passcode.mask
|
user_mask = user.enciphered_passcode.mask
|
||||||
decoded_mask = user_keys.decode_base64_str(user_mask)
|
decoded_mask = user_cipher.decode_base64_str(user_mask)
|
||||||
deciphered_mask = xor_lists(decoded_mask, user_keys.mask_key)
|
deciphered_mask = xor_lists(decoded_mask, user_cipher.mask_key)
|
||||||
set_key_rand_component = xor_lists(set_vals, user_keys.set_key)
|
set_key_rand_component = xor_lists(set_vals, user_cipher.set_key)
|
||||||
passcode_sets = []
|
passcode_sets = []
|
||||||
for set_cipher in deciphered_mask[:passcode_len]:
|
for set_cipher in deciphered_mask[:passcode_len]:
|
||||||
set_idx = set_key_rand_component.index(set_cipher)
|
set_idx = set_key_rand_component.index(set_cipher)
|
||||||
@@ -331,7 +331,7 @@ Recall User Passcode: {{ user_passcode }}
|
|||||||
```
|
```
|
||||||
### Compare Enciphered Passcodes
|
### 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.
|
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)
|
sets_xor = xor_lists(new_sets, old_sets)
|
||||||
for user in customer.users.values():
|
for user in customer.users.values():
|
||||||
user.renew = True
|
user.renew = True
|
||||||
user.user_keys.set_key = xor_lists(user.user_keys.set_key, sets_xor)
|
user.user_cipher.set_key = xor_lists(user.user_cipher.set_key, sets_xor)
|
||||||
user.user_keys.prop_key = xor_lists(user.user_keys.prop_key, attrs_xor)
|
user.user_cipher.prop_key = xor_lists(user.user_cipher.prop_key, attrs_xor)
|
||||||
```
|
```
|
||||||
##### User prop Key
|
##### User prop Key
|
||||||
The user's prop key was a randomly generated list of length `numb_of_keys * attr_per_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
|
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.
|
with the new values.
|
||||||
```
|
```
|
||||||
user.user_keys = UserCipherKeys.new(
|
user.user_cipher = UserCipherKeys.new(
|
||||||
customer.attributes.keypad_size,
|
customer.attributes.keypad_size,
|
||||||
customer.attributes.set_vals,
|
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
|
user.renew = False
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -15,8 +15,9 @@ def random_username() -> str:
|
|||||||
return "test_username" + "".join([choice(ascii_lowercase) for _ in range(6)])
|
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]:
|
def select_keys_with_passcode_values(user_passcode: list[int], keypad: np.ndarray, attrs_per_key: int) -> list[int]:
|
||||||
return [interface.index(attr) // attrs_per_key for attr in user_passcode]
|
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):
|
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)
|
output = template.render(data)
|
||||||
|
|
||||||
# Print or save the output
|
# 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:
|
with open(output_file, 'w') as fp:
|
||||||
fp.write(output)
|
fp.write(output)
|
||||||
print("File written successfully")
|
print("File written successfully")
|
||||||
@@ -71,18 +72,17 @@ if __name__ == "__main__":
|
|||||||
set_attribute_dict = dict(zip(set_vals, attr_set_view))
|
set_attribute_dict = dict(zip(set_vals, attr_set_view))
|
||||||
|
|
||||||
session_id, signup_interface = api.generate_signup_keypad(customer_id)
|
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.numb_of_keys)
|
||||||
signup_keypad = signup_interface.reshape(-1, keypad_size.props_per_key)
|
|
||||||
|
|
||||||
username = random_username()
|
username = random_username()
|
||||||
passcode_len = 4
|
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)
|
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]
|
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_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)
|
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
|
USER LOGIN
|
||||||
"""
|
"""
|
||||||
login_interface = api.get_login_keypad(username, customer_id)
|
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)
|
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)
|
success = api.login(customer_id, username, selected_keys_login)
|
||||||
assert success
|
assert success
|
||||||
@@ -141,7 +141,7 @@ if __name__ == "__main__":
|
|||||||
login_passcode_sets = []
|
login_passcode_sets = []
|
||||||
for set_cipher in deciphered_mask[:passcode_len]:
|
for set_cipher in deciphered_mask[:passcode_len]:
|
||||||
set_idx = np.where(set_key_rand_component == set_cipher)[0][0]
|
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
|
GET PRESUMED ATTRIBUTES
|
||||||
@@ -200,7 +200,7 @@ if __name__ == "__main__":
|
|||||||
'server_side_attr': server_side_attr,
|
'server_side_attr': server_side_attr,
|
||||||
'confirm_keypad': confirm_keypad,
|
'confirm_keypad': confirm_keypad,
|
||||||
'selected_keys_confirm': selected_keys_confirm,
|
'selected_keys_confirm': selected_keys_confirm,
|
||||||
'cipher': user_keys,
|
'user_cipher': user_keys,
|
||||||
'passcode_server_attr': passcode_server_attr,
|
'passcode_server_attr': passcode_server_attr,
|
||||||
'passcode_server_set': passcode_server_set,
|
'passcode_server_set': passcode_server_set,
|
||||||
'enciphered_nkode': enciphered_nkode,
|
'enciphered_nkode': enciphered_nkode,
|
||||||
|
|||||||
Reference in New Issue
Block a user