docs.sigit.io/emailflow.md
_ f9be77ec7c
All checks were successful
Release to Production / build_and_release (push) Successful in 19s
updates
2025-01-12 23:24:33 +00:00

3.9 KiB

Email Flow

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
  • 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:

  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

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.

SIGNUP FLOW

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 <br> Nostr Relay
    U->>W: Click SIGNUP and enter <br>email address
    Note over W: Ephemeral key generated <br> to communicate with DVM
    W->>D: Request Account
    Note right of W: Event uses PoW and<br> encrypts only EMAIL<br> to dvm@sigit.io pubkey
    D -x DB: Verify PoW and check<br> if email exists
    Note over D: If email already exists, <br>send user to LOGIN.<br> Otherwise#58;
    D->>DB: Create Temp Session
    Note over DB: SESSION entry#58;<br>#128274;session.pubkey="ephemeral pubkey"<br>session.email=lowcase($EMAIL)<br>session.email_code=INT (6 digits)<br>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<br> an encrypted (and detailed)<br> error message
    W->>U: Tell user to check email and<br>to open it in the <br> SAME BROWSER SESSION
    Note over W: Screen to accept the 6 digits <br> is already displayed<br>(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 <br>encrypts only CODE<br> to DVM pubkey
    D -x DB: Check email_code where <br>session pk=event pk
    D->>DB: If code matches,<br>create User Account
    Note over DB: USER entry#58;<br>#128274;user.id=uid()<br>user.email=session.email<br>user.pubkey=""<br>user.activated=false<br>user.created_at=now()<br>user.bkp=""<br>user.entropy=uid()
    D->>W: Provide user.entropy
    Note left of D: Payload encrypted to ephemeral <br>pubkey. Is either a UID or a <br> detailed error message.
    Note over W: Client verifies that <br> DVM response came from <br> DVM pubkey
    W->>U: Ask for secure password
    Note right of U: This password is what prevents<br>backend from decrypting the nsec
    Note right of U: User is warned that they CANNOT<br>RESET PASSWORD, should USE <br>PASSWORD MANAGER etc
    U->>W: Enter password (twice)

    Note over W: Nostr Keypair Generated <br> & Encrypted inside a <br> PRIVATE METHOD,<br>using password + entropy.<br> Password variable is not <br>stored, sent or printed <br> anywhere. Temporary <br>variables are destroyed.

    W->>D: Request account activation
    Note right of W: Event uses PoW and<br> encrypts both PUBKEY<br> and the already-<br>encrypted BACKUP<br> to the DVM pubkey
    D -x DB: Ensure event pubkey <br> in SESSION table
    D->>DB: Update Account
    Note over DB: user.activated=true <br>user.pubkey=$pubkey<br>user.bkp=$backup
    D->>W: Account activated
    Note left of D: Payload is an empty string or<br> an encrypted (and detailed)<br> error message
    W->>U: User is automatically logged in
    Note over W: Ephemeral key is destroyed<br>Default relay list applied