test and validate signup with dispersable keypad and login with non-dispersable keypad
This commit is contained in:
16
nkode_api.py
16
nkode_api.py
@@ -28,18 +28,21 @@ class NKodeAPI(BaseModel):
|
||||
def generate_index_interface(self, customer_id: UUID) -> tuple[UUID, list[int]]:
|
||||
assert (customer_id in self.customers.keys())
|
||||
customer = self.customers[customer_id]
|
||||
set_interface = UserInterface.new(customer.attributes.keypad_size)
|
||||
login_interface = UserInterface.new(customer.attributes.keypad_size)
|
||||
set_interface = login_interface.sign_up_interface()
|
||||
new_session = UserSignupSession(
|
||||
session_id=uuid4(),
|
||||
login_interface=login_interface,
|
||||
set_interface=set_interface.interface,
|
||||
customer_id=customer_id,
|
||||
keypad_size=customer.attributes.keypad_size,
|
||||
keypad_size=set_interface.keypad_size,
|
||||
)
|
||||
self.signup_sessions[new_session.session_id] = new_session
|
||||
return new_session.session_id, new_session.set_interface
|
||||
|
||||
def set_nkode(
|
||||
self, username: str,
|
||||
self,
|
||||
username: str,
|
||||
customer_id: UUID,
|
||||
key_selection: list[int],
|
||||
session_id: UUID
|
||||
@@ -71,10 +74,7 @@ class NKodeAPI(BaseModel):
|
||||
username=username,
|
||||
enciphered_passcode=enciphered_passcode,
|
||||
user_keys=new_user_keys,
|
||||
user_interface=UserInterface(
|
||||
interface=self.signup_sessions[session_id].confirm_interface,
|
||||
keypad_size=customer.attributes.keypad_size
|
||||
),
|
||||
user_interface=self.signup_sessions[session_id].login_interface,
|
||||
)
|
||||
self.customers[customer_id].add_new_user(new_user)
|
||||
del self.signup_sessions[session_id]
|
||||
@@ -88,7 +88,7 @@ class NKodeAPI(BaseModel):
|
||||
customer = self.customers[customer_id]
|
||||
assert (username in customer.users.keys())
|
||||
user = customer.users[username]
|
||||
user.user_interface.shuffle_interface()
|
||||
user.user_interface.partial_interface_shuffle()
|
||||
return user.user_interface.interface
|
||||
|
||||
def login(self, customer_id: UUID, username: str, key_selection: list[int]) -> bool:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"execution_count": 62,
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from nkode_api import NKodeAPI\n",
|
||||
@@ -14,14 +14,14 @@
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-07-19T19:42:26.168590Z",
|
||||
"start_time": "2024-07-19T19:42:26.080917Z"
|
||||
"end_time": "2024-07-22T16:43:14.323435Z",
|
||||
"start_time": "2024-07-22T16:43:14.225885Z"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"execution_count": 63,
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def random_username() -> str:\n",
|
||||
@@ -40,14 +40,14 @@
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-07-19T19:42:26.169484Z",
|
||||
"start_time": "2024-07-19T19:42:26.084626Z"
|
||||
"end_time": "2024-07-22T16:43:14.323797Z",
|
||||
"start_time": "2024-07-22T16:43:14.229848Z"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"execution_count": 64,
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"api = NKodeAPI()"
|
||||
@@ -55,8 +55,8 @@
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-07-19T19:42:26.169561Z",
|
||||
"start_time": "2024-07-19T19:42:26.087253Z"
|
||||
"end_time": "2024-07-22T16:43:14.323871Z",
|
||||
"start_time": "2024-07-22T16:43:14.232313Z"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -79,7 +79,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"execution_count": 65,
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"policy = NKodePolicy(\n",
|
||||
@@ -89,8 +89,8 @@
|
||||
" distinct_attributes=4\n",
|
||||
")\n",
|
||||
"keypad_size = KeypadSize(\n",
|
||||
" numb_of_keys = 10,\n",
|
||||
" attrs_per_key = 7 # aka number of sets\n",
|
||||
" numb_of_keys = 5,\n",
|
||||
" attrs_per_key = 4 # aka number of sets\n",
|
||||
")\n",
|
||||
"customer_id = api.create_new_customer(keypad_size, policy)\n",
|
||||
"customer = api.customers[customer_id]"
|
||||
@@ -98,8 +98,8 @@
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-07-19T19:42:26.266945Z",
|
||||
"start_time": "2024-07-19T19:42:26.091559Z"
|
||||
"end_time": "2024-07-22T16:43:14.414667Z",
|
||||
"start_time": "2024-07-22T16:43:14.238210Z"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -126,14 +126,14 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"execution_count": 66,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Customer Sets: [36939, 30293, 19380, 1964, 37282, 10031, 35065]\n",
|
||||
"Customer Attributes: [3505, 54543, 45347, 44748, 53903, 52815, 60524, 9975, 48764, 34550, 64903, 32542, 23911, 35423, 63534, 65510, 21500, 37871, 19901, 6884, 255, 17031, 63424, 28925, 34144, 42192, 31390, 40124, 17254, 48729, 39518, 57631, 43182, 61064, 4422, 53465, 55843, 37538, 60243, 21929, 51240, 24244, 27507, 57663, 45226, 31543, 58101, 37770, 62668, 49947, 64348, 20373, 64786, 14379, 13970, 11323, 3662, 62709, 37802, 27817, 60687, 22963, 42846, 3620, 9784, 48482, 13855, 60342, 34564, 45989]\n"
|
||||
"Customer Sets: [6259, 41347, 52298, 30406]\n",
|
||||
"Customer Attributes: [65233, 63177, 42010, 46768, 5724, 12484, 7294, 20676, 9411, 8047, 18067, 6808, 51196, 46992, 15995, 34735, 37237, 57815, 17974, 10378]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -146,8 +146,8 @@
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-07-19T19:42:43.930527Z",
|
||||
"start_time": "2024-07-19T19:42:43.924673Z"
|
||||
"end_time": "2024-07-22T16:43:14.431062Z",
|
||||
"start_time": "2024-07-22T16:43:14.413572Z"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -162,20 +162,17 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 17,
|
||||
"execution_count": 67,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Set to Attribute Map:\n",
|
||||
"36939: [3505, 9975, 63534, 17031, 17254, 53465, 27507, 49947, 3662, 3620]\n",
|
||||
"30293: [54543, 48764, 65510, 63424, 48729, 55843, 57663, 64348, 62709, 9784]\n",
|
||||
"19380: [45347, 34550, 21500, 28925, 39518, 37538, 45226, 20373, 37802, 48482]\n",
|
||||
"1964: [44748, 64903, 37871, 34144, 57631, 60243, 31543, 64786, 27817, 13855]\n",
|
||||
"37282: [53903, 32542, 19901, 42192, 43182, 21929, 58101, 14379, 60687, 60342]\n",
|
||||
"10031: [52815, 23911, 6884, 31390, 61064, 51240, 37770, 13970, 22963, 34564]\n",
|
||||
"35065: [60524, 35423, 255, 40124, 4422, 24244, 62668, 11323, 42846, 45989]\n"
|
||||
"6259: [65233, 5724, 9411, 51196, 37237]\n",
|
||||
"41347: [63177, 12484, 8047, 46992, 57815]\n",
|
||||
"52298: [42010, 7294, 18067, 15995, 17974]\n",
|
||||
"30406: [46768, 20676, 6808, 34735, 10378]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -190,8 +187,8 @@
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-07-19T19:42:46.177582Z",
|
||||
"start_time": "2024-07-19T19:42:46.173094Z"
|
||||
"end_time": "2024-07-22T16:43:14.431341Z",
|
||||
"start_time": "2024-07-22T16:43:14.417167Z"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -206,7 +203,7 @@
|
||||
"\n",
|
||||
"#### Generate Index Interface\n",
|
||||
"- random interface is generated. Run the cell below over and over to see it change. Notice that values never move out of their columns jus their rows.\n",
|
||||
"- each value in the interface is the index value of an attribute in the customer interface\n",
|
||||
"- each value in the interface is the index value of a customer attribute\n",
|
||||
"- the user never learns what their \"real\" attribute is. All they do is specify an index in the customer interface\n"
|
||||
],
|
||||
"metadata": {
|
||||
@@ -215,16 +212,26 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 18,
|
||||
"outputs": [],
|
||||
"execution_count": 68,
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": "[[4, 1, 10, 3],\n [8, 5, 2, 15],\n [0, 13, 14, 11],\n [16, 9, 6, 7],\n [12, 17, 18, 19]]"
|
||||
},
|
||||
"execution_count": 68,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"session_id, signup_interface = api.generate_index_interface(customer_id)"
|
||||
"session_id, signup_interface = api.generate_index_interface(customer_id)\n",
|
||||
"list_to_matrix(signup_interface, keypad_size.attrs_per_key)"
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-07-19T19:42:47.644598Z",
|
||||
"start_time": "2024-07-19T19:42:47.640134Z"
|
||||
"end_time": "2024-07-22T16:43:14.431562Z",
|
||||
"start_time": "2024-07-22T16:43:14.420566Z"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -232,7 +239,7 @@
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"#### Set NKode\n",
|
||||
"The user identifies attributes in the interface they want in their nkode. Each attribute in the gui has an index value. Below the user has selected 12, 2, 52, 28. Graphiclly represent with anything. The only requirment is that the graphical must be associated with the same number everytime the user goes to login. If the user wants to change anything about their interface, they must also change their nkode."
|
||||
"The user identifies attributes in the interface they want in their nkode. Each attribute in the gui has an index value. Below the user has selected 16, 9, 6, 19. Graphiclly represent with anything. The only requirment is that the graphical must be associated with the same number everytime the user goes to login. If the user wants to change anything about their interface, they must also change their nkode."
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
@@ -240,64 +247,54 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 19,
|
||||
"execution_count": 69,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Keypad View\n",
|
||||
"Key 0: [63, 1, 16, 59, 32, 19, 34]\n",
|
||||
"Key 1: [49, 57, 65, 66, 4, 47, 48]\n",
|
||||
"Key 2: [28, 50, 58, 10, 11, 5, 27]\n",
|
||||
"Key 3: [21, 43, 51, 52, 25, 68, 41]\n",
|
||||
"Key 4: [7, 64, 2, 38, 60, 54, 62]\n",
|
||||
"Key 5: [56, 29, 23, 31, 67, 61, 20]\n",
|
||||
"Key 6: [42, 15, 9, 24, 53, 26, 13]\n",
|
||||
"Key 7: [14, 36, 30, 45, 46, 33, 69]\n",
|
||||
"Key 8: [0, 22, 44, 17, 39, 40, 55]\n",
|
||||
"Key 9: [35, 8, 37, 3, 18, 12, 6]\n",
|
||||
"Key 0: [4, 1, 10, 3]\n",
|
||||
"Key 1: [8, 5, 2, 15]\n",
|
||||
"Key 2: [0, 13, 14, 11]\n",
|
||||
"Key 3: [16, 9, 6, 7]\n",
|
||||
"Key 4: [12, 17, 18, 19]\n",
|
||||
"Selected Keys\n",
|
||||
"[9, 4, 3, 2]\n"
|
||||
"[3, 3, 3, 4]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"keypad_view(signup_interface, keypad_size.attrs_per_key)\n",
|
||||
"username = random_username()\n",
|
||||
"user_passcode = [12, 2, 52, 28]\n",
|
||||
"user_passcode = [16, 9, 6, 19]\n",
|
||||
"selected_keys_set = select_keys_with_passcode_values(user_passcode, signup_interface, keypad_size.attrs_per_key)\n",
|
||||
"print(f\"Selected Keys\\n{selected_keys_set}\")"
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-07-19T19:42:48.948115Z",
|
||||
"start_time": "2024-07-19T19:42:48.942682Z"
|
||||
"end_time": "2024-07-22T16:43:14.431673Z",
|
||||
"start_time": "2024-07-22T16:43:14.424684Z"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 20,
|
||||
"execution_count": 70,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Keypad View\n",
|
||||
"Key 0: [49, 22, 23, 59, 11, 12, 62]\n",
|
||||
"Key 1: [42, 64, 44, 52, 46, 5, 6]\n",
|
||||
"Key 2: [56, 8, 2, 66, 32, 33, 27]\n",
|
||||
"Key 3: [0, 50, 37, 24, 25, 19, 69]\n",
|
||||
"Key 4: [7, 36, 58, 31, 4, 68, 34]\n",
|
||||
"Key 5: [35, 1, 30, 17, 53, 47, 41]\n",
|
||||
"Key 6: [28, 43, 16, 38, 67, 26, 48]\n",
|
||||
"Key 7: [14, 57, 51, 3, 39, 61, 13]\n",
|
||||
"Key 8: [63, 15, 65, 10, 60, 40, 20]\n",
|
||||
"Key 9: [21, 29, 9, 45, 18, 54, 55]\n",
|
||||
"Key 0: [12, 9, 14, 15]\n",
|
||||
"Key 1: [0, 17, 2, 3]\n",
|
||||
"Key 2: [8, 13, 10, 7]\n",
|
||||
"Key 3: [4, 5, 6, 19]\n",
|
||||
"Key 4: [16, 1, 18, 11]\n",
|
||||
"Selected Keys\n",
|
||||
"[0, 2, 1, 6]\n"
|
||||
"[4, 0, 3, 3]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -310,8 +307,8 @@
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-07-19T19:42:49.532737Z",
|
||||
"start_time": "2024-07-19T19:42:49.528687Z"
|
||||
"end_time": "2024-07-22T16:43:14.431769Z",
|
||||
"start_time": "2024-07-22T16:43:14.427713Z"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -329,7 +326,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 21,
|
||||
"execution_count": 71,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
@@ -337,16 +334,11 @@
|
||||
"text": [
|
||||
"Set Interface\n",
|
||||
"Keypad View\n",
|
||||
"Key 0: [63, 1, 16, 59, 32, 19, 34]\n",
|
||||
"Key 1: [49, 57, 65, 66, 4, 47, 48]\n",
|
||||
"Key 2: [28, 50, 58, 10, 11, 5, 27]\n",
|
||||
"Key 3: [21, 43, 51, 52, 25, 68, 41]\n",
|
||||
"Key 4: [7, 64, 2, 38, 60, 54, 62]\n",
|
||||
"Key 5: [56, 29, 23, 31, 67, 61, 20]\n",
|
||||
"Key 6: [42, 15, 9, 24, 53, 26, 13]\n",
|
||||
"Key 7: [14, 36, 30, 45, 46, 33, 69]\n",
|
||||
"Key 8: [0, 22, 44, 17, 39, 40, 55]\n",
|
||||
"Key 9: [35, 8, 37, 3, 18, 12, 6]\n"
|
||||
"Key 0: [4, 1, 10, 3]\n",
|
||||
"Key 1: [8, 5, 2, 15]\n",
|
||||
"Key 2: [0, 13, 14, 11]\n",
|
||||
"Key 3: [16, 9, 6, 7]\n",
|
||||
"Key 4: [12, 17, 18, 19]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -357,14 +349,14 @@
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-07-19T19:42:50.432534Z",
|
||||
"start_time": "2024-07-19T19:42:50.427816Z"
|
||||
"end_time": "2024-07-22T16:43:14.447860Z",
|
||||
"start_time": "2024-07-22T16:43:14.430888Z"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 22,
|
||||
"execution_count": 72,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
@@ -372,16 +364,11 @@
|
||||
"text": [
|
||||
"Confirm Interface\n",
|
||||
"Keypad View\n",
|
||||
"Key 0: [49, 22, 23, 59, 11, 12, 62]\n",
|
||||
"Key 1: [42, 64, 44, 52, 46, 5, 6]\n",
|
||||
"Key 2: [56, 8, 2, 66, 32, 33, 27]\n",
|
||||
"Key 3: [0, 50, 37, 24, 25, 19, 69]\n",
|
||||
"Key 4: [7, 36, 58, 31, 4, 68, 34]\n",
|
||||
"Key 5: [35, 1, 30, 17, 53, 47, 41]\n",
|
||||
"Key 6: [28, 43, 16, 38, 67, 26, 48]\n",
|
||||
"Key 7: [14, 57, 51, 3, 39, 61, 13]\n",
|
||||
"Key 8: [63, 15, 65, 10, 60, 40, 20]\n",
|
||||
"Key 9: [21, 29, 9, 45, 18, 54, 55]\n"
|
||||
"Key 0: [12, 9, 14, 15]\n",
|
||||
"Key 1: [0, 17, 2, 3]\n",
|
||||
"Key 2: [8, 13, 10, 7]\n",
|
||||
"Key 3: [4, 5, 6, 19]\n",
|
||||
"Key 4: [16, 1, 18, 11]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -392,14 +379,14 @@
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-07-19T19:42:50.897855Z",
|
||||
"start_time": "2024-07-19T19:42:50.894734Z"
|
||||
"end_time": "2024-07-22T16:43:14.448110Z",
|
||||
"start_time": "2024-07-22T16:43:14.433535Z"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 23,
|
||||
"execution_count": 73,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
@@ -420,8 +407,8 @@
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-07-19T19:42:51.884002Z",
|
||||
"start_time": "2024-07-19T19:42:51.198018Z"
|
||||
"end_time": "2024-07-22T16:43:15.081248Z",
|
||||
"start_time": "2024-07-22T16:43:14.437249Z"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -438,14 +425,14 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 23,
|
||||
"execution_count": 73,
|
||||
"outputs": [],
|
||||
"source": [],
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-07-19T19:42:53.411190Z",
|
||||
"start_time": "2024-07-19T19:42:53.406912Z"
|
||||
"end_time": "2024-07-22T16:43:15.083482Z",
|
||||
"start_time": "2024-07-22T16:43:15.078924Z"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -471,7 +458,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 24,
|
||||
"execution_count": 74,
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
@@ -513,19 +500,19 @@
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-07-19T19:42:55.684088Z",
|
||||
"start_time": "2024-07-19T19:42:55.680817Z"
|
||||
"end_time": "2024-07-22T16:43:15.097910Z",
|
||||
"start_time": "2024-07-22T16:43:15.084617Z"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 25,
|
||||
"execution_count": 75,
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": "<IPython.core.display.Markdown object>",
|
||||
"text/markdown": "|key|set0|set1|set2|set3|\n|-|-|-|-|-|\n|key1|5|50|55|500|\n|key2|3|30|33|300|\n|key3|2|20|22|200|\n|key4|4|40|44|400|\n|key5|1|10|11|100|"
|
||||
"text/markdown": "|key|set0|set1|set2|set3|\n|-|-|-|-|-|\n|key1|4|40|44|400|\n|key2|2|20|22|200|\n|key3|1|10|11|100|\n|key4|5|50|55|500|\n|key5|3|30|33|300|"
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
@@ -540,19 +527,19 @@
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-07-19T19:42:56.543819Z",
|
||||
"start_time": "2024-07-19T19:42:56.537207Z"
|
||||
"end_time": "2024-07-22T16:43:15.098089Z",
|
||||
"start_time": "2024-07-22T16:43:15.088214Z"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 26,
|
||||
"execution_count": 76,
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": "<IPython.core.display.Markdown object>",
|
||||
"text/markdown": "|key|set0|set1|set2|set3|\n|-|-|-|-|-|\n|key1|3|40|11|200|\n|key2|2|10|55|400|\n|key3|4|50|33|100|\n|key4|1|30|22|500|\n|key5|5|20|44|300|"
|
||||
"text/markdown": "|key|set0|set1|set2|set3|\n|-|-|-|-|-|\n|key1|2|10|44|500|\n|key2|1|50|22|300|\n|key3|5|30|11|400|\n|key4|3|40|55|200|\n|key5|4|20|33|100|"
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
@@ -570,8 +557,65 @@
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-07-19T19:42:56.940543Z",
|
||||
"start_time": "2024-07-19T19:42:56.935742Z"
|
||||
"end_time": "2024-07-22T16:43:15.098218Z",
|
||||
"start_time": "2024-07-22T16:43:15.091198Z"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [],
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 80,
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": "'$2b$12$M2kUbtPVmpphEHJIw/AKc.v96GcyR9WqPzNcbQqSHJWjiZJ6NwqMm'"
|
||||
},
|
||||
"execution_count": 80,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"user_hash = list(api.customers[customer_id].users.values())[0].enciphered_passcode.code\n",
|
||||
"user_hash\n"
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-07-22T16:46:22.182625Z",
|
||||
"start_time": "2024-07-22T16:46:22.178757Z"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 84,
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": "[27172,\n 59678,\n 42816,\n 42517,\n 14869,\n 3862,\n 33437,\n 50365,\n 1299,\n 423,\n 16708,\n 23065,\n 1118,\n 54789,\n 22038,\n 22603,\n 36630,\n 18246,\n 48084,\n 32460]"
|
||||
},
|
||||
"execution_count": 84,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"list(api.customers[customer_id].users.values())[0].user_keys.alpha_key\n",
|
||||
"\n"
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-07-22T16:48:52.733419Z",
|
||||
"start_time": "2024-07-22T16:48:52.728228Z"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -581,10 +625,7 @@
|
||||
"outputs": [],
|
||||
"source": [],
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"ExecuteTime": {
|
||||
"start_time": "2024-07-19T19:42:26.284802Z"
|
||||
}
|
||||
"collapsed": false
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
@@ -12,6 +12,9 @@ class Customer(BaseModel):
|
||||
attributes: CustomerAttributes
|
||||
users: dict[str, User]
|
||||
|
||||
# TODO: validate policy and keypad size don't conflict
|
||||
|
||||
|
||||
def add_new_user(self, user: User):
|
||||
self.users[user.username] = user
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from pydantic import BaseModel
|
||||
from pydantic import BaseModel, model_validator
|
||||
|
||||
from src.models import KeypadSize
|
||||
from src.utils import generate_random_nonrepeating_list
|
||||
@@ -9,6 +9,13 @@ class CustomerAttributes(BaseModel):
|
||||
set_vals: list[int]
|
||||
keypad_size: KeypadSize
|
||||
|
||||
@model_validator(mode='after')
|
||||
def check_keys_vs_attrs(self):
|
||||
if self.keypad_size.is_dispersable:
|
||||
raise ValueError("number of keys must be less than the number of "
|
||||
"attributes per key to be dispersion resistant")
|
||||
return self
|
||||
|
||||
@staticmethod
|
||||
def new(keypad_size: KeypadSize):
|
||||
assert (keypad_size.numb_of_keys <= 256)
|
||||
|
||||
@@ -16,7 +16,7 @@ class NKodePolicy(BaseModel):
|
||||
min_nkode_len: int = 4
|
||||
distinct_sets: int = 0
|
||||
distinct_attributes: int = 4
|
||||
# TODO: bytes_per_attr
|
||||
byte_len: int = 2 # Todo: this should change the total number of bytes an attribute or set value can be
|
||||
|
||||
|
||||
class KeypadSize(BaseModel):
|
||||
@@ -26,3 +26,7 @@ class KeypadSize(BaseModel):
|
||||
@property
|
||||
def numb_of_attrs(self) -> int:
|
||||
return self.attrs_per_key * self.numb_of_keys
|
||||
|
||||
@property
|
||||
def is_dispersable(self) -> bool:
|
||||
return self.attrs_per_key <= self.numb_of_keys
|
||||
|
||||
@@ -16,28 +16,55 @@ class UserInterface(BaseModel):
|
||||
interface=list(range(keypad_size.numb_of_attrs)),
|
||||
keypad_size=keypad_size
|
||||
)
|
||||
interface.disperse_interface()
|
||||
for _ in range(10):
|
||||
interface.shuffle_interface()
|
||||
interface.random_interface_shuffle()
|
||||
return interface
|
||||
|
||||
def sign_up_interface(self):
|
||||
assert (not self.keypad_size.is_dispersable)
|
||||
self.random_interface_shuffle()
|
||||
interface_matrix = self.interface_keypad_matrix()
|
||||
attr_set_view = matrix_transpose(interface_matrix)
|
||||
attr_set_view = secure_fisher_yates_shuffle(attr_set_view)
|
||||
attr_set_view = attr_set_view[:self.keypad_size.numb_of_keys]
|
||||
interface_matrix = matrix_transpose(attr_set_view)
|
||||
return UserInterface(
|
||||
interface=matrix_to_list(interface_matrix),
|
||||
keypad_size=KeypadSize(
|
||||
numb_of_keys=self.keypad_size.numb_of_keys,
|
||||
attrs_per_key=self.keypad_size.numb_of_keys
|
||||
)
|
||||
)
|
||||
|
||||
def interface_keypad_matrix(self) -> list[list[int]]:
|
||||
return list_to_matrix(self.interface, self.keypad_size.attrs_per_key)
|
||||
|
||||
def random_interface_shuffle(self):
|
||||
keypad_view = self.interface_keypad_matrix()
|
||||
keypad_view = secure_fisher_yates_shuffle(keypad_view)
|
||||
set_view = matrix_transpose(keypad_view)
|
||||
set_view = [secure_fisher_yates_shuffle(attr_set) for attr_set in set_view]
|
||||
keypad_view = matrix_transpose(set_view)
|
||||
self.interface = matrix_to_list(keypad_view)
|
||||
|
||||
def disperse_interface(self):
|
||||
assert (self.keypad_size.is_dispersable)
|
||||
user_interface_matrix = list_to_matrix(self.interface, self.keypad_size.attrs_per_key)
|
||||
shuffled_keys = secure_fisher_yates_shuffle(user_interface_matrix)
|
||||
|
||||
attr_rotation = secure_fisher_yates_shuffle(list(range(self.keypad_size.numb_of_keys)))[:self.keypad_size.attrs_per_key]
|
||||
attr_rotation = secure_fisher_yates_shuffle(list(range(self.keypad_size.numb_of_keys)))[
|
||||
:self.keypad_size.attrs_per_key]
|
||||
dispersed_interface = self.random_attribute_rotation(
|
||||
shuffled_keys,
|
||||
attr_rotation,
|
||||
)
|
||||
self.interface = matrix_to_list(dispersed_interface)
|
||||
|
||||
def shuffle_interface(self):
|
||||
def partial_interface_shuffle(self):
|
||||
numb_of_selected_sets = self.keypad_size.attrs_per_key // 2
|
||||
# randomly shuffle half the sets. if attrs_per_key is odd, randomly add one 50% of the time
|
||||
numb_of_selected_sets += choice([0, 1]) if (self.keypad_size.attrs_per_key & 1) == 1 else 0
|
||||
selected_sets = secure_fisher_yates_shuffle(list(range(self.keypad_size.attrs_per_key)))[:numb_of_selected_sets]
|
||||
user_interface_matrix = list_to_matrix(self.interface, self.keypad_size.attrs_per_key)
|
||||
user_interface_matrix = self.interface_keypad_matrix()
|
||||
shuffled_keys = secure_fisher_yates_shuffle(user_interface_matrix)
|
||||
interface_by_sets = []
|
||||
for idx, attrs in enumerate(matrix_transpose(shuffled_keys)):
|
||||
@@ -60,7 +87,7 @@ class UserInterface(BaseModel):
|
||||
return matrix_transpose(transposed_user_interface)
|
||||
|
||||
def attribute_adjacency_graph(self) -> dict[int, set[int]]:
|
||||
user_interface_keypad = list_to_matrix(self.interface, self.keypad_size.attrs_per_key)
|
||||
user_interface_keypad = self.interface_keypad_matrix()
|
||||
graph = {}
|
||||
for key in user_interface_keypad:
|
||||
for attr in key:
|
||||
@@ -71,5 +98,5 @@ class UserInterface(BaseModel):
|
||||
|
||||
def get_key_attr_idxs(self, key_numb: int) -> list[int]:
|
||||
assert (0 <= key_numb < self.keypad_size.numb_of_keys)
|
||||
keypad_attr_idx = list_to_matrix(self.interface, self.keypad_size.attrs_per_key)
|
||||
keypad_attr_idx = self.interface_keypad_matrix()
|
||||
return keypad_attr_idx[key_numb]
|
||||
|
||||
@@ -9,6 +9,8 @@ from src.models import KeypadSize
|
||||
class UserSignupSession(BaseModel):
|
||||
session_id: UUID
|
||||
customer_id: UUID
|
||||
login_interface: UserInterface
|
||||
|
||||
keypad_size: KeypadSize
|
||||
set_interface: list[int] | None = None
|
||||
confirm_interface: list[int] | None = None
|
||||
|
||||
@@ -8,17 +8,17 @@ def nkode_api() -> NKodeAPI:
|
||||
return NKodeAPI()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("keypad_size,user_passcode", [
|
||||
(KeypadSize(numb_of_keys=10, attrs_per_key=7), [3, 10, 27, 68]),
|
||||
(KeypadSize(numb_of_keys=10, attrs_per_key=7), [3, 10, 27, 68, 32]),
|
||||
@pytest.mark.parametrize("keypad_size,passocode_len", [
|
||||
(KeypadSize(numb_of_keys=10, attrs_per_key=11), 4),
|
||||
(KeypadSize(numb_of_keys=10, attrs_per_key=12), 5),
|
||||
])
|
||||
def test_create_new_user_and_renew_keys(nkode_api, keypad_size, user_passcode):
|
||||
def test_create_new_user_and_renew_keys(nkode_api, keypad_size, passocode_len):
|
||||
username = "test_username"
|
||||
nkode_policy = NKodePolicy() # default policy
|
||||
customer_id = nkode_api.create_new_customer(keypad_size, nkode_policy)
|
||||
session_id, set_interface = nkode_api.generate_index_interface(customer_id)
|
||||
|
||||
key_selection = lambda interface: [interface.index(attr) // keypad_size.attrs_per_key for attr in user_passcode]
|
||||
user_passcode = set_interface[:passocode_len]
|
||||
key_selection = lambda interface: [interface.index(attr) // keypad_size.numb_of_keys for attr in user_passcode]
|
||||
set_key_selection = key_selection(set_interface)
|
||||
|
||||
confirm_interface = nkode_api.set_nkode(username, customer_id, set_key_selection, session_id)
|
||||
@@ -31,6 +31,7 @@ def test_create_new_user_and_renew_keys(nkode_api, keypad_size, user_passcode):
|
||||
)
|
||||
assert successful_confirm
|
||||
|
||||
key_selection = lambda interface: [interface.index(attr) // keypad_size.attrs_per_key for attr in user_passcode]
|
||||
login_interface = nkode_api.get_login_index_interface(username, customer_id)
|
||||
login_key_selection = key_selection(login_interface)
|
||||
successful_login = nkode_api.login(customer_id, username, login_key_selection)
|
||||
|
||||
@@ -5,11 +5,11 @@ from src.models import KeypadSize
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"keypad_size",
|
||||
[KeypadSize(numb_of_keys=10, attrs_per_key=7)]
|
||||
[KeypadSize(numb_of_keys=10, attrs_per_key=11)]
|
||||
)
|
||||
def test_attr_set_idx(keypad_size):
|
||||
user_interface = UserInterface.new(keypad_size)
|
||||
for attr_idx in range(70):
|
||||
for attr_idx in range(keypad_size.numb_of_attrs):
|
||||
user_interface_idx = user_interface.interface[attr_idx]
|
||||
|
||||
assert (attr_idx % keypad_size.attrs_per_key == user_interface_idx % keypad_size.attrs_per_key)
|
||||
|
||||
@@ -22,9 +22,9 @@ def test_encode_decode_base64(passcode_len):
|
||||
@pytest.mark.parametrize(
|
||||
"keypad_size,max_nkode_len",
|
||||
[
|
||||
(KeypadSize(numb_of_keys=10, attrs_per_key=7), 10),
|
||||
(KeypadSize(numb_of_keys=9, attrs_per_key=7), 10),
|
||||
(KeypadSize(numb_of_keys=8, attrs_per_key=7), 12),
|
||||
(KeypadSize(numb_of_keys=10, attrs_per_key=11), 10),
|
||||
(KeypadSize(numb_of_keys=9, attrs_per_key=11), 10),
|
||||
(KeypadSize(numb_of_keys=8, attrs_per_key=11), 12),
|
||||
])
|
||||
def test_decode_mask(keypad_size, max_nkode_len):
|
||||
customer = CustomerAttributes.new(keypad_size)
|
||||
|
||||
@@ -26,7 +26,7 @@ def test_shuffle_attrs(user_interface):
|
||||
- the order in which the attributes move from key to key is random (i.e. the distance traveled is uniform)
|
||||
"""
|
||||
pre_shuffle_interface = user_interface.interface
|
||||
user_interface.shuffle_interface()
|
||||
user_interface.partial_interface_shuffle()
|
||||
post_shuffle_interface = user_interface.interface
|
||||
for i in range(1000):
|
||||
assert (not all(
|
||||
|
||||
Reference in New Issue
Block a user