296 lines
17 KiB
HTML
296 lines
17 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
|
<meta name="apple-mobile-web-app-title" content="nKode Authentication Evolved">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>nKode</title>
|
|
<link rel="icon" type="image/png" href="assets/n.png"/>
|
|
<link rel="apple-touch-icon" href="assets/n.png">
|
|
|
|
<!-- Tailwind CSS CDN -->
|
|
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
</head>
|
|
<body>
|
|
<div class="bg-white">
|
|
<header class="absolute inset-x-0 top-0 z-50">
|
|
<nav class="fixed top-0 w-full z-50 flex items-center justify-between p-6 px-8 bg-white" aria-label="Global">
|
|
<div class="flex flex-1">
|
|
<a href="#" class="-m-1.5 p-1.5">
|
|
<img class="h-8 w-auto" src="assets/lightmodenkode.svg" alt="">
|
|
</a>
|
|
</div>
|
|
<div class="md:flex md:hidden">
|
|
<button id="open-menu" type="button" class="-m-2.5 inline-flex items-center justify-center rounded-md p-2.5 text-gray-400">
|
|
<span class="sr-only">Open main menu</span>
|
|
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
<div class="hidden md:flex items-center gap-x-12">
|
|
<div class="flex gap-x-6 text-lg font-semibold leading-6 text-black">
|
|
<a href="#create-an-nkode">Create an nKode</a>
|
|
<a href="#how-nkode-works">How nKode Works</a>
|
|
<a href="#faq">FAQ</a>
|
|
</div>
|
|
<div class="ml-auto">
|
|
<button class="bg-orange-500 text-white py-2 px-4 rounded-full hover:bg-orange-600 transition duration-200 text-sm sm:text-lg">
|
|
<a href="https://app.nkode.tech">Try nKode <span aria-hidden="true">→</span></a>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
<!-- Mobile menu, show/hide based on menu open state. -->
|
|
<div id="mobile-menu" class="md:hidden hidden" role="dialog" aria-modal="true">
|
|
<!-- Background backdrop, show/hide based on slide-over state. -->
|
|
<div class="fixed inset-0 z-50"></div>
|
|
<div class="fixed inset-y-0 right-0 z-50 w-full overflow-y-auto bg-white px-6 py-6 md:max-w-sm md:ring-1 md:ring-white/10">
|
|
<div class="flex items-center justify-between">
|
|
<a href="#" class="-m-1.5 p-1.5">
|
|
<span class="sr-only">Your Company</span>
|
|
<img class="h-8 w-auto" src="assets/lightmodenkode.svg" alt="">
|
|
</a>
|
|
<button id="close-menu" type="button" class="-m-2.5 rounded-md p-2.5 text-black">
|
|
<span class="sr-only">Close menu</span>
|
|
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
<div class="mt-6 flow-root">
|
|
<div class="-my-6 divide-y divide-white/25">
|
|
<div class="space-y-2 py-6">
|
|
<a href="#create-an-nkode" class="-mx-3 block rounded-lg px-3 py-2 text-base font-semibold leading-7 text-black hover:bg-gray-200 mobile-nav">Create an nKode</a>
|
|
<a href="#how-nkode-works" class="-mx-3 block rounded-lg px-3 py-2 text-base font-semibold leading-7 text-black hover:bg-gray-200 mobile-nav" >How nKode Works</a>
|
|
<a href="#faq" class="-mx-3 block rounded-lg px-3 py-2 text-base font-semibold leading-7 text-black hover:bg-gray-200 mobile-nav">FAQ</a>
|
|
</div>
|
|
|
|
<button class="bg-orange-500 text-white py-2 px-4 rounded-full hover:bg-orange-600 transition duration-200 text-sm sm:text-large">
|
|
<a href="https://app.nkode.tech">Try nKode <span aria-hidden="true">→</span></a>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
<main>
|
|
<div class="mx-auto lg:max-w-3xl sm:max-w-xl max-w-sm mb-8">
|
|
<div class="text-4xl tracking-tight text-black py-24">
|
|
<span class="text-orange-600 font-semibold">n</span>Kode is <span class="font-semibold">easier</span> to remember and more <span class="font-semibold">secure</span> than a password
|
|
<div class="text-center mt-8">
|
|
<button class="bg-orange-500 text-white py-2 px-4 rounded-full hover:bg-orange-600 transition duration-200 text-sm sm:text-lg">
|
|
<a href="https://app.nkode.tech">Try nKode <span aria-hidden="true">→</span></a>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<section id="create-an-nkode" class="scroll-mt-24">
|
|
<h3 class="text-4xl">How to create an nKode</h3>
|
|
<p class="text-2xl mt-4">1. Enter your email</p>
|
|
<img class="w-3/4 mx-auto mt-8" src="assets/signup.png">
|
|
<h4 class="text-2xl">2. Set your nKode</h4>
|
|
<p class="mt-8 text-xl">Select 4 icons that will be your nKode. Icons can not be repeated.</p>
|
|
<p class="text-xl">Example: pizza, ladybug, wine, baseball</p>
|
|
<div class="mt-8 flex flex-row">
|
|
<img class="w-16" src="assets/pizza.png">
|
|
<img class="w-16" src="assets/ladybug.png">
|
|
<img class="w-16" src="assets/wine.png">
|
|
<img class="w-16" src="assets/baseball.png">
|
|
</div>
|
|
<img class="w-3/4 mx-auto mt-8" src="assets/set_nkode.png">
|
|
|
|
<h4 class="text-2xl">3. Confirm your nKode</h4>
|
|
<p class="mt-8 text-xl">Confirm your nKode by reentering it.</p>
|
|
<img class="w-3/4 mx-auto mt-8" src="assets/confirm_nkode.png">
|
|
|
|
<h4 class="text-2xl">4. Login with nKode</h4>
|
|
<p class="mt-8 text-xl">Once you've confirmed, the login screen will open. Enter your nKode to login</p>
|
|
<img class="w-3/4 mx-auto mt-8" src="assets/login1.png">
|
|
|
|
</section>
|
|
<section id="how-nkode-works" class="scroll-mt-24">
|
|
<h3 class="text-4xl mt-8">How nKode Works</h3>
|
|
<h4 class="text-2xl mt-4">Keypad Settings</h4>
|
|
<p>
|
|
Your nKode keypad is configurable.
|
|
Under advanced settings, you can change the number of keys and the number of attributes (icon) per key.
|
|
From this point forward, we will use the term attribute instead of icon.
|
|
</p>
|
|
<img class="w-3/4 mx-auto mt-8" src="assets/advanced_settings.png">
|
|
<h4 class="text-2xl mt-4">Account Creation</h4>
|
|
<p>
|
|
The server is able to deduce your nKode from two entries.
|
|
Notice how, in the set and confirm keypads below, no attribute in the set keypad share a key with any other attribute in the confirm keypad.
|
|
This is called an attribute dispersion.
|
|
</p>
|
|
<div class="flex flex-row">
|
|
<img class="w-1/2 mx-auto mt-8" src="assets/set_nkode.png">
|
|
<img class="w-1/2 mx-auto mt-8" src="assets/confirm_nkode.png">
|
|
</div>
|
|
<h4 class="text-2xl mt-4">Attribute Dispersion</h4>
|
|
<p>
|
|
The login keypad looks different from the set and confirm keypads.
|
|
It has three more attributes per key.
|
|
A dispersion is possible if the number of attributes per key is less than or equal to the total number of keys.
|
|
Since the login keypad has more attributes per key than keys, we call this a dispersion-resistant keypad.
|
|
If a malicious actor steals your keypad, they can use your keypad to phish for your nKode.
|
|
If the login keypad was dispersable, an attack might go like this:
|
|
</p>
|
|
|
|
<ol class="list-decimal list-inside mt-2 space-y-2">
|
|
<li>You click a malicious link from your email or text saying you need to authorize USPS to send you a package (or whatever the latest scam is today).</li>
|
|
<li>You're redirected to a site with your nKode keypad requesting authorization with your nKode.</li>
|
|
<li>You enter your nKode, but you're informed you entered the wrong nKode.</li>
|
|
<li>The attacker disperses your keypad and requests you enter your nKode again.</li>
|
|
<li>You enter it again, and your nKode is stolen.</li>
|
|
</ol>
|
|
<p>
|
|
The greater the difference between the number of attributes per key and the number of keys, the greater the dispersion resistance, which comes with trade-offs.
|
|
If there are too few keys, it becomes easier to randomly enter keys and accidentally get into your account without actually knowing your nKode.
|
|
If you increase the number of keys without increasing the number of attributes per key, your keypad becomes more dispersable.
|
|
If you have too many attributes and keys, the keypad is too busy, which makes it challenging to find your attributes.
|
|
</p>
|
|
<h4 class="text-2xl mt-4">Server-Side Attributes</h4>
|
|
<p>
|
|
A traditional password is composed of ASCII and sometimes Unicode characters.
|
|
These are salted, hash, and stored in a database.
|
|
nKode is similar.
|
|
An unsigned 64-bit integer represents every attribute, though it can be a byte array of any size.
|
|
These server-side attributes can be rotated daily, weekly, or any other cadence desired.
|
|
Here's how it works:
|
|
</p>
|
|
<ol class="list-decimal list-inside mt-2 space-y-2">
|
|
<li>An administrator or cron job starts the server-side attribute renewal.</li>
|
|
<li>The server-side attributes are rotated, and an intermediate transformation is applied to the user's server-side keys</li>
|
|
<li>Has a successful login, and the user's keys, salt, and hash are all replaced.</li>
|
|
</ol>
|
|
|
|
<h4 class="text-2xl mt-4">Login</h4>
|
|
<p>
|
|
Every time you log in, your attributes are randomly shuffled.
|
|
Attributes don't move to arbitrary locations within the key; attributes are a part of a set.
|
|
You can identify the set by its position within the key.
|
|
In the example below, you can see some attributes haven't moved, some moved to other keys as a group, and some moved to different keys alone.
|
|
</p>
|
|
<div class="flex flex-row">
|
|
<img class="w-1/2 mx-auto mt-8" src="assets/login1.png">
|
|
<img class="w-1/2 mx-auto mt-8" src="assets/login2.png">
|
|
</div>
|
|
|
|
<div class="text-center mt-8">
|
|
<button class="bg-orange-500 text-white py-2 px-4 rounded-full hover:bg-orange-600 transition duration-200 text-sm sm:text-lg">
|
|
<a href="https://app.nkode.tech">Try nKode <span aria-hidden="true">→</span></a>
|
|
</button>
|
|
</div>
|
|
|
|
</section>
|
|
<section class="scroll-mt-24" id="faq">
|
|
|
|
<h3 class="text-4xl mt-8">FAQ</h3>
|
|
<h4 class="text-2xl mt-4">How does nKode defend against common attacks?</h4>
|
|
<p>
|
|
At the time of this writing, nKode is only a demo web application.
|
|
Ideally, all nKode authentication is done through a mobile application.
|
|
A mobile application can make nKode more secure by requiring passkeys and biometric authentication to get the nKode keypad.
|
|
This makes it very difficult to steal or use your nKode.
|
|
</p>
|
|
<h5 class="text-xl mt-4">1. MFA Prompt Bombing</h5>
|
|
<p>
|
|
Many MFA solutions try to make login as frictionless as possible.
|
|
This kind of frictionless system makes prompt bombing a viable attack.
|
|
Adding some friction to the login process, nKode mitigates prompt bombing, not so much that it's too time-consuming but not so little that a person could mindlessly accept an MFA request or accidentally fat-finger and accept an authentication request by mistake.
|
|
The easiest attack vector for a nKode MFA bomb is session hijacking.
|
|
Stealing nKode is more complex, making it an unlikely attack vector.
|
|
nKode can mitigate this by adding a button, "I did not make this MFA request."
|
|
The server can block fraudulent requests if the user presses this button.
|
|
Otherwise, the user enters their nKode.
|
|
Since a user has to look for their nKode, it prevents them from quickly typing in a passcode without thinking, giving them a chance to reconsider their decision. </p>
|
|
<h5 class="text-xl mt-4">2. Service Desk Social Engineering: Scattered Spider</h5>
|
|
<p>
|
|
An nKode keypad is made from any visual attribute.
|
|
To make this more concrete, take a look at <a class="text-orange-600 underline" href="https://www.flaticon.com/search?word=abstract">Flaticon</a>.
|
|
If every employee at the service desk has a randomly generated keypad from abstract visual attributes like those found on Flaticon, an employee would have difficulty explaining their nKode.
|
|
Moreover, this keypad can be further protected with a 2FA keycard so only the employee can render their keypad.
|
|
For an attacker to get a target's nKode, they'd have to be with the target, and the targeted employee would have to point to the attributes on their screen since they're difficult to describe in words.
|
|
The attacker must also steal the employee's 2FA keycard to render the login screen.
|
|
</p>
|
|
<h5 class="text-xl mt-4">3. Session Hijacking</h5>
|
|
<p>
|
|
To mitigate the damage from session hijacking, jwts or session tokens can be made read-only by default.
|
|
When a user makes a sensitive write transaction, such as updating personal information or sending money, they must enter an nKode.
|
|
</p>
|
|
<h5 class="text-xl mt-4">3. Sim Swaps</h5>
|
|
<p>
|
|
If a user's device is damaged, lost, or stolen, they'll need a way to establish authentication keys with the new device without using the old device.
|
|
|
|
We are building two types of nKode offerings:
|
|
</p>
|
|
|
|
<ol class="list-decimal list-inside mt-2 space-y-2">
|
|
<li>Sign in with nKode is a B2C service nKode SSO is a B2B service.</li>
|
|
<li>The solutions below will use the terms customers and mobile carriers, but these are interchangeable with employee and service desk.</li>
|
|
</ol>
|
|
<h6 class="mt-2 font-semibold">Temporary nKode Portal</h6>
|
|
<p>
|
|
The customer calls their mobile carrier to activate the sim for a new phone without the old device.
|
|
The customer provides information like their name, dob, and ssn and answers security questions.
|
|
The carrier will then activate a temporary web portal where the customer enters their nKode to authenticate the request.
|
|
When the portal is activated, the customer with the authenticated phone will receive a notification on their nKode app alerting them to the activated portal.
|
|
If the user has their device, they can close the portal by entering their nKode.
|
|
The portal should only be opened if the user can't use their device to activate the new sim.
|
|
If their phone is stolen, the thief can't stop this process if they don't know the user's nKode.
|
|
Customers who want higher security can specify a wait period before a replacement device is activated.
|
|
If the portal isn't closed before the end of this waiting period, the sim swap or new device enrollment can proceed.
|
|
</p>
|
|
<h6 class="mt-2 font-semibold">Authentication nKode Delegates</h6>
|
|
<p>
|
|
This solution is only suitable for Sign in with nKode.
|
|
After a user has installed the nKode app and created their account, they can delegate authentication to trusted friends and family who also have a Sign in with nKode for device recovery.
|
|
If a user delegates authentication recovery to a few trusted people and they've lost their device, the user can go to any of their trusted delegates to enroll a new device through their delegate's nKode app.
|
|
Users can configure account delegation such that any authentication can be completed with only one delegate or require more than one delegate to authenticate on the user's behalf.
|
|
Once a device has been enrolled, the carrier can rely on nKode to authenticate a sim swap.
|
|
</p>
|
|
|
|
<h5 class="text-xl mt-4">4. Redline Stealer</h5>
|
|
<p>
|
|
Ideally, all nKode authentication goes through the mobile app. If authentication is done on a laptop, an attacker can steal a user's nKode after watching several nKode entries depending on the number of keys and attributes per key. This number can vary as the number of attributes and keys change.
|
|
</p>
|
|
<h5 class="text-xl mt-4">5. Exploiting SSO SAML</h5>
|
|
<p>
|
|
If an attacker finds a way to steal a user's nKode, they still need the user's device. The user's device contains their passkeys and biometrics. Without it, the adversary won't be able to authenticate.
|
|
</p>
|
|
</section>
|
|
</div>
|
|
</main>
|
|
|
|
</div>
|
|
|
|
<!-- Add your JavaScript just before the closing body tag -->
|
|
<script>
|
|
// Get the elements from the DOM
|
|
const openMenuButton = document.getElementById('open-menu');
|
|
const closeMenuButton = document.getElementById('close-menu');
|
|
const mobileMenu = document.getElementById('mobile-menu');
|
|
const mobileNavLinks = document.getElementsByClassName('mobile-nav');
|
|
// Function to show the mobile menu
|
|
openMenuButton.addEventListener('click', () => {
|
|
mobileMenu.classList.remove('hidden');
|
|
});
|
|
|
|
// Function to hide the mobile menu
|
|
closeMenuButton.addEventListener('click', () => {
|
|
mobileMenu.classList.add('hidden');
|
|
});
|
|
|
|
Array.from(mobileNavLinks).forEach(link => {
|
|
link.addEventListener('click', () => {
|
|
mobileMenu.classList.add('hidden');
|
|
});
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|