Improve nsec password field requirements (fixes #1) and add more detailed descriptions.

This commit is contained in:
Danny Morabito 2024-11-28 22:47:19 +01:00
parent 0021db1c58
commit 8b4dba62e1
Signed by: dannym
GPG key ID: 7CC8056A5A04557E

View file

@ -38,7 +38,7 @@
} }
function loginWithNsec() { function loginWithNsec() {
if (password.length < 8) return alert('Password must be at least 8 characters long'); if (password.length < 32) return alert('Password must be at least 32 characters long');
let nsecBytes = decodeKey(nsec); let nsecBytes = decodeKey(nsec);
if (nsecBytes.type !== 'nsec') return alert('Invalid nsec'); if (nsecBytes.type !== 'nsec') return alert('Invalid nsec');
let encrypted = encryptNsec(nsecBytes.data, password); let encrypted = encryptNsec(nsecBytes.data, password);
@ -75,22 +75,97 @@
</script> </script>
{#if isLoggingIn} {#if isLoggingIn}
<div class="login-warning">
<h3>🚨 Critical Security Warning 🚨</h3>
<p>Your nsec is the master key to your ENTIRE Nostr identity. If someone gets it:</p>
<ul class="warning-list">
<li>They can read ALL your letters - past and future</li>
<li>They can post ANYTHING pretending to be you</li>
<li>They can take over your account PERMANENTLY</li>
<li>There is NO WAY to undo this - not even we can help you</li>
<li>Your account would be LOST FOREVER</li>
</ul>
<p class="warning-action">Only enter your nsec on devices you completely trust!</p>
<p class="warning-final">If you're not 100% sure about this, STOP and use a signing extension instead (or use
bunkers, coming soon).</p>
</div>
{#if ncryptsec || nsec} {#if ncryptsec || nsec}
Enter your password: <br /> <h3>Password Required</h3>
If this is a new account make sure to remember the password in order to login later, if this is an existing account, <p>
put in the same password you used to create the account. <br /> First time here? Create a strong password that is AT LEAST 32 characters long.<br>
<input bind:value={password} type="password" placeholder="Password" /> A good approach is to use 4-5 random words with numbers and symbols between them.<br>
<button onclick={cancelLoginWithNsec}>Cancel</button> Example: correct-horse9battery!staple$running<br /><br />
{#if ncryptsec} <a
<button onclick={loginWithExistingNcryptSec}>Login</button> href="https://xkcd.com/936/"
{:else} target="_blank"
<button onclick={loginWithNsec}>Login</button> rel="noopener"
{/if} class="button"
>
(See this XKCD comic for why this works)
</a>
</p>
<p class="warning-action">
Your password is used to encrypt your nsec. Write it down somewhere safe, it cannot be recovered.
</p>
<input
bind:value={password}
type="password"
placeholder="Minimum 32 characters"
class="password-input"
/>
<div class="password-strength">
Length: {password?.length || 0}/32 characters
</div>
<div class="button-group">
<button onclick={cancelLoginWithNsec}>Go Back</button>
<button
onclick={ncryptsec ? loginWithExistingNcryptSec : loginWithNsec}
disabled={password?.length < 32}
>
Sign In
</button>
</div>
{:else} {:else}
If you already have a nostr account, please enter your nsec below. If you don't have an nsec please use a nostr <p>
client to create one, such as <a href="https://primal.net">Primal</a>.<br /> Already have a Nostr account? Enter your nsec below.<br>
<input bind:value={nsecField} type="password" placeholder="nsec1..." /><br /> Need an account? Create one using any of these popular clients:
<button onclick={nsecOk}>Ok</button> </p>
<ul class="client-list">
<li>
<a href="https://primal.net" target="_blank" rel="noopener">
Primal
<span class="client-desc">Feature-rich web and mobile nostr client with great UI</span>
</a>
</li>
<li>
<a href="https://damus.io" target="_blank" rel="noopener">
Damus
<span class="client-desc">Popular iOS nostr client</span>
</a>
</li>
<li>
<a href="https://amethyst.social" target="_blank" rel="noopener">
Amethyst
<span class="client-desc">Feature-packed Android nostr client</span>
</a>
</li>
<li>
<a href="https://iris.to" target="_blank" rel="noopener">
Iris
<span class="client-desc">Minimalist web nostr client</span>
</a>
</li>
</ul>
<input
bind:value={nsecField}
type="password"
placeholder="nsec1..."
class="nsec-input"
/>
<button onclick={nsecOk}>Continue</button>
{/if} {/if}
{:else} {:else}
<button onclick={login}>Login with Nostr Extension</button> <button onclick={login}>Login with Nostr Extension</button>
@ -102,4 +177,144 @@
display: block; display: block;
align-self: center; align-self: center;
} }
.login-warning {
display: flex;
flex-direction: column;
gap: var(--spacing-sm);
margin-block: var(--spacing-md);
background: var(--glass-bg);
padding: var(--spacing-md);
}
.client-list {
list-style: none;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: var(--spacing-sm);
margin: var(--spacing-md) 0;
li {
background: var(--glass-bg);
border: 1px solid var(--glass-border);
border-radius: 8px;
padding: var(--spacing-sm);
transition: all 0.3s ease;
position: relative;
isolation: isolate;
&::before {
content: '';
position: absolute;
inset: -2px;
background: linear-gradient(45deg, var(--accent), transparent);
border-radius: 10px;
z-index: -1;
opacity: 0;
transition: opacity 0.3s ease;
}
&:hover {
transform: translateY(-2px);
box-shadow: 0 0 15px var(--glass-glow);
&::before {
opacity: 1;
}
}
a {
color: var(--text-primary);
text-decoration: none;
display: block;
font-weight: 500;
.client-desc {
display: block;
color: var(--text-secondary);
font-size: 0.8em;
margin-top: var(--spacing-xs);
opacity: 0.7;
}
&:hover {
text-decoration: underline;
}
}
}
}
.warning-list {
display: flex;
flex-direction: column;
gap: var(--spacing-sm);
margin: var(--spacing-md) 0;
li {
backdrop-filter: blur(var(--blur-strength));
background: var(--glass-bg-dark);
border: 1px solid var(--glass-border);
border-radius: 8px;
padding: var(--spacing-sm);
color: var(--text-primary);
display: flex;
align-items: center;
gap: var(--spacing-sm);
box-shadow: var(--depth-shadow);
transition: transform 0.3s ease;
&::before {
content: "⚠️";
font-size: 1.2em;
}
&:hover {
transform: translateX(var(--spacing-xs));
background: var(--glass-bg-darker);
}
}
}
.warning-action {
backdrop-filter: blur(var(--blur-strength));
background: var(--chip-error);
border: 1px solid var(--glass-border);
border-radius: 8px;
padding: var(--spacing-md);
margin: var(--spacing-md) 0;
text-align: center;
font-weight: 600;
color: var(--text-primary);
box-shadow: var(--depth-shadow),
0 0 15px var(--glass-glow);
&:hover {
background: color-mix(in srgb, var(--chip-error) 80%, black);
}
}
.warning-final {
position: relative;
text-align: center;
padding: var(--spacing-md) 0;
margin-top: var(--spacing-md);
font-weight: 600;
color: var(--text-primary);
&::before {
content: '';
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
width: 80%;
height: 2px;
background: linear-gradient(
90deg,
transparent,
var(--chip-error),
transparent
);
}
}
</style> </style>