diff --git a/emailflow.md b/emailflow.md
index 52689f0..bec0129 100644
--- a/emailflow.md
+++ b/emailflow.md
@@ -3,21 +3,28 @@
In creating an email flow that maintains PRIVACY and SECURITY whilst also being convenient to use, the following principles were observed:
- Keypair must be generated client-side
-- Keypair must be protected by a password
-- There must be protection from keyloggers
+- Keypair must be protected by a long and complex password
- It must be possible to change the password
- It must remain possible to work offline
- Network traffic must not contain identifying metadata
-All of the above is achieved using a high level flow as follows:
+All of the above is achieved using a high level signup flow as follows:
-1. Generate temporary key pair for secure server communication
-2. Validate email using a 6 digit code
-3. Provide some server side entropy to client
-4. Combine entropy + complex user password to encrypt the final keypair
-5. Store the encrypted keypair on the server
+1. User provides email and complex password
+2. These are used to encrypt a locally generated keypair into a backup
+3. Email address, Public Key and encrypted backup are sent to the server
+4. Account is validated
-The password is only used to encrypt the key and is never stored or sent anywhere. Hence, the server cannot decrypt the backup. All key signing / encryption operations happen on client side using [private class properties](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_properties).
+The password is only used to encrypt/decrypt the local backup and is never stored or sent anywhere.
+
+When perforing a login, the flow is:
+
+1. Generate a temporary key pair for secure server communication
+2. Validate the email
+3. Provide the encrypted keypair for the user to unlock
+
+
+All key signing / encryption operations happen on client side using [private class properties](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_properties).
## SIGNUP FLOW
@@ -27,47 +34,44 @@ sequenceDiagram
autoNumber
actor U as SIGit User
participant W as SIGit Website
- participant D as DVM
- Participant DB as DataBase
- Note over W,D: All comms over
Nostr Relay
- U->>W: Click SIGNUP and enter
email address
- Note over W: Ephemeral key generated
to communicate with DVM
- W->>D: Request Account
- Note right of W: Event uses PoW and
encrypts only EMAIL
to dvm@sigit.io pubkey
- D -x DB: Verify PoW and check
if email exists
- Note over D: If email already exists,
send user to LOGIN.
Otherwise#58;
- D->>DB: Create Temp Session
- Note over DB: SESSION entry#58;
#128274;session.pubkey="ephemeral pubkey"
session.email=lowcase($EMAIL)
session.email_code=INT (6 digits)
session.created_at=now()
+ participant D as Server
+ Participant DB
+ Note over W,D: All comms encrypted with throwaway
(ephemeral) client keys and a
.well-known server key
+ U->>W: Click SIGNUP
+ U->>W: Provide Email and Complex Password
+ Note over W: Validate Email
Ensure Complex Password
+
+ Note right of U: User is warned that they CANNOT
RESET PASSWORD, should USE
PASSWORD MANAGER etc
+
+
+ Note over W: Nostr Keypair Generated
& Encrypted inside a
PRIVATE method,
with COMPLEX password.
Password variable is not
stored, sent or printed
anywhere.
Any sensitive variables
are immediately destroyed.
+ W->>D: Request account activation
+ Note right of W: Event uses PoW and
encrypts PUBKEY, EMAIL,
and the encrypted BACKUP
to the dvm@sigit.io pubkey
using the ephemeral key
+ Note over D: Verify PoW,
event.created_at,
event.id
+ D -x DB: Check if email exists
+ Note over D: If email already exists, and
user.last_seen <> null then
send user to LOGIN.
If email exists and last_seen
is null, then DELETE the
current entry.
Otherwise#58;
+ D->>DB: Create DB entries
+ Note over DB: USER insert#58;
#128274;user.id=uid()
user.pubkey=lowcase($PUBKEY)
user.email=lowcase($EMAIL)
user.last_seen=null
user.created_at=now()
user.bkp=$BACKUP
+ Note over DB: SESSION insert#58;
#128274;session.pubkey="ephemeral pubkey"
session.email_code=INT (6 digits)
session.user_id=user.id
session.created_at=now()
D->>U: Send session.email_code via email
D->>W: Account created
- Note left of D: Payload is an empty string or
an encrypted (and detailed)
error message
+ Note left of D: Payload is the user.id and/or
an encrypted (and detailed)
error message
+ Note over W: Verify DVM pubkey,
event.created_at,
event.id
W->>U: Tell user to check email and
to open it in the
SAME BROWSER SESSION
Note over W: Screen to accept the 6 digits
is already displayed
(mobile optimised if relevant)
U->>W: User opens link or enters the code
W->>D: Verify Account
- Note right of W: Event uses PoW and
encrypts only CODE
to DVM pubkey
+ Note right of W: Event uses PoW and
encrypts both user_id
and email_code
to DVM pubkey
D -x DB: Check email_code where
session pk=event pk
- D->>DB: If code matches,
create User Account
- Note over DB: USER entry#58;
#128274;user.id=uid()
user.email=session.email
user.pubkey=""
user.activated=false
user.created_at=now()
user.bkp=""
user.entropy=uid()
- D->>W: Provide user.entropy
- Note left of D: Payload encrypted to ephemeral
pubkey. Is either a UID or a
detailed error message.
- Note over W: Client verifies that
DVM response came from
DVM pubkey
- W->>U: Ask for secure password
- Note right of U: This password is what prevents
backend from decrypting the nsec
- Note right of U: User is warned that they CANNOT
RESET PASSWORD, should USE
PASSWORD MANAGER etc
- U->>W: Enter password (twice)
+ D->>DB: If email_code matches,
update USER table where
session.user_id=user.id
- Note over W: Nostr Keypair Generated
& Encrypted inside a
PRIVATE METHOD,
using password + entropy.
Password variable is not
stored, sent or printed
anywhere. Temporary
variables are destroyed.
- W->>D: Request account activation
- Note right of W: Event uses PoW and
encrypts both PUBKEY
and the already-
encrypted BACKUP
to the DVM pubkey
- D -x DB: Ensure event pubkey
in SESSION table
- D->>DB: Update Account
- Note over DB: user.activated=true
user.pubkey=$pubkey
user.bkp=$backup
+ Note over DB: USER update#58;
user.last_seen=now()
D->>W: Account activated
Note left of D: Payload is an empty string or
an encrypted (and detailed)
error message
+ Note over W: Verify DVM pubkey,
event.created_at,
event.id
W->>U: User is automatically logged in
- Note over W: Ephemeral key is destroyed
Default relay list applied
+ Note over W: Ephemeral key is destroyed
Default relay list is broadcast
using the user pubkey
```