Skip to content

Migrate to GunDB SEA: Replace custom crypto with built-in P2P authentication #1

@bryanchriswhite

Description

@bryanchriswhite

Summary

Replace the custom certificate/key management system with GunDB SEA (Security, Encryption, Authorization) for cryptographic identity. Keep Google OAuth for user authentication and Calendar integration, with the server acting as a trusted bridge linking Google identity to SEA keypairs.

Motivation

  • Simplify codebase: Remove ~400 lines of custom crypto code
  • Use battle-tested crypto: SEA uses native Web Crypto API (ECDSA, PBKDF2, AES)
  • Built-in verification: Peers automatically verify signatures - no custom certificate checking
  • Public-read, user-only-write: SEA's gun.user() provides this pattern natively
  • Future-proof: Clear path to fully decentralized auth later

Architecture

┌─────────────┐     ┌─────────────────────────┐     ┌─────────────┐
│   Browser   │────▶│   Express Server        │────▶│   Google    │
│             │     │                         │     │   OAuth     │
│  1. OAuth   │     │  1. Verify Google auth  │     └─────────────┘
│  2. Get seed│◀────│  2. Generate signed seed│
│  3. Derive  │     │  3. Calendar API proxy  │
│     SEA keys│     │                         │
│  4. gun.user│     └───────────┬─────────────┘
│     .auth() │                 │
└──────┬──────┘                 │
       │                        │
       ▼                        ▼
┌─────────────────────────────────────────────┐
│              GunDB P2P Network              │
│                                             │
│  - Topics stored in user space (~pubkey)    │
│  - All writes cryptographically signed      │
│  - Peers verify signatures automatically    │
│  - Public discovery graph for topic listing │
└─────────────────────────────────────────────┘

How It Works

Server-Side Seed Generation

The server generates a deterministic seed using HMAC:

// New endpoint: /auth/sea-seed
const seed = HMAC(SEA_SECRET, googleUserId);
res.json({ seed });
  • Same Google user always gets the same seed → same SEA keypair
  • Server secret required for seed generation (trusted bridge)
  • Enables future key rotation by versioning seeds

Client-Side SEA Authentication

// After Google OAuth callback
const { seed } = await fetch('/auth/sea-seed').then(r => r.json());

// Derive SEA keypair deterministically (using @gooddollar/gun-pk-auth)
const seaPair = genDeterministicSEAPair(seed);

// Authenticate to GunDB
const user = gun.user();
user.auth(seaPair, callback);

// user.is.pub is now the user's verified identity

Topic Storage Pattern

// Create topic in user's protected space (only author can write)
user.get('topics').get(topicId).put(topicData);

// Link to public discovery graph
gun.get('public-topics').get(topicId).put({
  author: user.is.pub,
  title: topicData.title
});

// Others read via author's public key (automatically verified by SEA)
gun.user(authorPubKey).get('topics').get(topicId).on((data) => {
  // Data is cryptographically verified
});

Implementation Checklist

Phase 1: Add SEA Seed Endpoint

  • Create /auth/sea-seed endpoint in server/routes/auth.js
  • Use HMAC with server secret to generate deterministic seed
  • Add SEA_SECRET to .env.example

Phase 2: Client SEA Integration

  • Add gun/sea.js script to client/index.html
  • Add @gooddollar/gun-pk-auth for deterministic key derivation
  • Create client/js/sea-auth.js with SEA authentication helpers
  • Update client/js/app.js:
    • Replace generateAndRegisterKeys() with SEA auth flow
    • Update checkAuth() to use SEA session
    • Remove crypto.js imports

Phase 3: Update Topic Storage Pattern

  • Change topic writes to use user.get('topics') (protected)
  • Add public discovery graph gun.get('public-topics')
  • Update topic reads to verify via author's public key
  • Update interest tracking to use SEA-signed data

Phase 4: Remove Legacy Code

  • Delete client/js/crypto.js
  • Delete server/services/keyManagement.js
  • Delete server/services/certificateService.js
  • Remove /auth/register-key endpoint
  • Remove node-forge dependency from package.json
  • Clean up GunDB storage (certificates, publicKeys namespaces)

Phase 5: Update Documentation

  • Update README with new auth flow
  • Update .env.example with SEA_SECRET

Files to Modify

File Action
server/routes/auth.js Add /auth/sea-seed, remove /auth/register-key
server/index.js Remove certificate/key service imports
client/index.html Add sea.js script
client/js/app.js Replace crypto flow with SEA auth
client/js/crypto.js DELETE
server/services/keyManagement.js DELETE
server/services/certificateService.js DELETE
package.json Add @gooddollar/gun-pk-auth, remove node-forge
.env.example Add SEA_SECRET

Dependencies

Add:

  • @gooddollar/gun-pk-auth - Deterministic SEA keypair generation from seeds

Remove:

  • node-forge - No longer needed for server-side crypto

Security Considerations

  1. SEA_SECRET must be kept secure - Compromise allows impersonation of any user
  2. Seed is sensitive - Transmitted over HTTPS only, never stored client-side
  3. Google account compromise = GunDB identity compromise - Same trust model as current system
  4. Key rotation - Possible by versioning seeds (e.g., HMAC(secret, ${userId}:v2))

Future Decentralization Path

The server's role is minimal and can be removed later:

Current (Phase 1) Future Options
Server generates seed from Google ID Client derives seed from Google ID directly
DID/Verifiable Credentials
Web3 wallet signatures as seed

The SEA-based topic storage pattern remains unchanged regardless of how the seed is generated.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions