Skip to content

Tsatsch/base-auth

Repository files navigation

Base Auth - Decentralized 2FA Authenticator

Secure two-factor authentication with IPFS and Base blockchain

Store encrypted 2FA secrets on IPFS with immutable blockchain references

πŸš€ Why Base Auth?

Signature-Based Encryption for Maximum Security: Unlike traditional crypto solutions that tie encryption directly to wallet addresses, Base Auth uses cryptographic signatures as the encryption key. When you store TOTP secrets, the system requires you to sign a message with your wallet - this signature becomes the encryption key for your 2FA data. This means your sensitive authentication codes are encrypted using the unique signature you generate, not your wallet address or private key, providing enhanced security and privacy.

Frontend Independence: Your TOTP codes remain accessible even when the frontend application is down, as your encrypted data is stored on decentralized IPFS with blockchain references, ensuring you can always retrieve your 2FA secrets using your wallet signature.

Familiar Experience, Enhanced Security: Works exactly like Google Authenticator or Authy, but with the added benefits of:

  • Zero Server Storage: Your secrets never touch our servers
  • Decentralized Storage: Data stored on IPFS, not centralized databases
  • Blockchain Immutability: Only encrypted references stored on-chain
  • Encryption: AES-256-GCM with signature-derived keys
  • Seamless Migration: Import from existing authenticators without starting over

Overview

Base Auth is a decentralized authenticator mini-app that combines IPFS storage with Base blockchain security. Your 2FA secrets are encrypted with AES-256-GCM using signature-derived keys, stored on IPFS, and referenced via immutable Content Identifiers (CIDs) on the blockchain. Only you can decrypt your secrets using your wallet signature.

Features

  • Signature-Based Authentication: Uses wallet signatures, not wallets address or private keys
  • Base Name Resolution: Displays your Base name when available
  • Encryption Functions: AES-256-GCM with PBKDF2 key derivation from signatures
  • IPFS Storage: Encrypted secrets stored on decentralized IPFS network
  • Blockchain References: Only immutable IPFS CIDs stored on-chain
  • Mobile-Friendly: Originally build for mobile usage for Base Mini Apps
  • Real-Time TOTP: 6-digit codes that refresh every 30 seconds
  • Maximum Privacy: No raw secrets on blockchain, all encryption client-side
  • Import/Export: Migrate from Google Authenticator and other apps
  • QR Code Support: Scan and generate QR codes for easy setup

Frontend Independence: Accessing TOTP Codes When Frontend is Down

Base Auth ensures your TOTP codes remain accessible and secure even when the frontend application is unavailable through a decentralized architecture that eliminates single points of failure. Your encrypted 2FA secrets are stored on IPFS (InterPlanetary File System) with immutable blockchain references, making them accessible through multiple pathways without depending on any centralized server or frontend application.

How It Works When Frontend is Down:

  1. Blockchain-Based Access: Your wallet address serves as the key to retrieve your IPFS Content Identifier (CID) directly from the Base blockchain smart contract. The smart contract stores only the IPFS CID - no sensitive data is ever stored on-chain.

  2. IPFS Decentralized Storage: Your encrypted TOTP secrets are stored on IPFS, a distributed file system that operates independently of any single server. IPFS ensures data availability through multiple nodes across the network.

  3. Signature-Based Decryption: Your wallet signature (not your private key) is used to derive the encryption key for your TOTP secrets. This means you can decrypt your data using any compatible wallet that can sign the same message.

  4. Manual Recovery Process: If the frontend is unavailable, you can still access your TOTP codes by:

    • Connecting your wallet to any Base-compatible interface
    • Calling the smart contract's getUserCID() function to retrieve your IPFS CID
    • Fetching your encrypted bundle directly from IPFS using the CID
    • Signing the vault access message with your wallet to derive the decryption key
    • Decrypting your TOTP secrets using the signature-derived key
    • Generating TOTP codes using standard TOTP algorithms

This architecture ensures that your TOTP codes remain accessible through the decentralized IPFS network and blockchain infrastructure, providing true ownership and control over your 2FA data regardless of frontend availability.

Complete Data Flow & Architecture

What's Stored Where

Smart Contract Storage (TwoFactorAuthenticator.sol):

struct UserData {
    string ipfsCID;        // IPFS Content Identifier pointing to encrypted bundle
    uint256 timestamp;     // Last update timestamp
    bool exists;           // Track if user has data
}
  • Only IPFS CIDs: No raw secrets, just immutable references
  • User-specific mapping: mapping(address => UserData) private userData
  • Events: UserDataUpdated, UserDataRemoved for transparency

IPFS Bundle Structure:

interface UserTOTPBundle {
  userAddress: string;
  lastUpdated: number;
  version: number;
  accounts: TOTPAccount[];
}

interface TOTPAccount {
  id: string;
  accountName: string;
  encryptedSecret: string;  // AES-256-GCM encrypted
  algorithm: string;
  period: number;
  digits: number;
  timestamp: number;
  iv: string;              // Initialization vector
  salt: string;            // PBKDF2 salt
  logoCID?: string;        // Optional logo stored separately
}

Encryption Process

1. Adding a 2FA Account:

User Input β†’ Wallet Signature β†’ Key Derivation β†’ Encryption β†’ IPFS β†’ Blockchain
     ↓              ↓               ↓             ↓         ↓        ↓
Account Name β†’ Sign Message β†’ PBKDF2 + Salt β†’ AES-256-GCM β†’ Bundle β†’ CID

2. Key Derivation (lib/crypto.ts):

// 1. User signs a message with their wallet
const signature = await wallet.signMessage("Base Auth Vault Access");

// 2. Signature is hashed with SHA-256
const signatureHash = await crypto.subtle.digest('SHA-256', signatureBytes);

// 3. PBKDF2 key derivation with random salt
const key = await crypto.subtle.deriveKey({
  name: 'PBKDF2',
  salt: randomSalt,           // 16-byte random salt
  iterations: 100000,          // 100k iterations
  hash: 'SHA-256',
}, keyMaterial, { name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt']);

3. Encryption Process:

// Each secret is encrypted individually
const { encrypted, iv, salt } = await encryptSecretGCM(secret, signature);

// Bundle structure for IPFS
const encryptedBundle: EncryptedBundle = {
  encryptedData: encrypted,    // AES-256-GCM encrypted JSON
  iv: iv,                      // 12-byte random IV
  salt: salt,                  // 16-byte random salt
  version: 2
};

IPFS Storage & Retrieval

Upload Process:

  1. Encrypt Bundle: All user accounts encrypted as single bundle
  2. Create JSON: Bundle serialized to JSON
  3. Upload to IPFS: Via Pinata Cloud with JWT authentication
  4. Receive CID: Content Identifier (e.g., QmXxXxXx...)
  5. Store CID on-chain: Only the CID stored in smart contract

Retrieval Process:

  1. Read CID: Get IPFS CID from smart contract
  2. Fetch from IPFS: Download encrypted bundle using CID
  3. Decrypt: Use wallet signature + stored salt to derive key
  4. Parse Bundle: Extract individual TOTP accounts
  5. Generate Codes: Create 6-digit TOTP codes

Security & Decentralization

Security Features:

  • Signature-Based Keys: No private key exposure, uses wallet signing
  • Client-Side Encryption: All encryption/decryption in browser
  • Authenticated Encryption: AES-256-GCM prevents tampering
  • Unique Salts: Each encryption uses random salt
  • No Server Storage: Zero server-side sensitive data

Decentralization:

  • IPFS Storage: Decentralized file system, not centralized databases
  • Blockchain References: Immutable CIDs on Base blockchain
  • No Single Point of Failure: IPFS + blockchain redundancy
  • User Control: Only user can decrypt with their signature

Import & Export - Your TOTP Codes Migration From Other Services

Migrating from Google Authenticator

Step 1: Export from Google Authenticator

  1. Open Google Authenticator app
  2. Tap the three dots menu β†’ "Transfer accounts"
  3. Select "Export accounts" β†’ "Next"
  4. Choose accounts to export β†’ "Next"
  5. Scan the QR code with Base Auth

Step 2: Import to Base Auth

  1. Open Base Auth and connect your wallet
  2. Tap "Import from Google Authenticator"
  3. Scan the migration QR code
  4. Select which accounts to import
  5. Tap "Import" - accounts are encrypted and stored

Exporting to Other Apps

Step 1: Export from Base Auth

  1. In Base Auth, tap "Export Accounts"
  2. Review security warning and tap "I Understand"
  3. Scan each QR code with your target app

Step 2: Import to Target App

  1. Open your target authenticator app
  2. Look for "Import" or "Add Account" option
  3. Scan the QR codes from Base Auth
  4. Accounts are now available in your target app

Migration Security

What's Protected:

  • Encrypted Transfer: QR codes contain encrypted data, not plain secrets
  • Temporary Display: QR codes only shown during export process
  • No Server Storage: Migration data never touches our servers
  • User Control: You choose which accounts to migrate

Supported Formats:

  • Google Authenticator migration format
  • Standard otpauth:// URIs
  • Base32 secret strings
  • Batch migration (multiple accounts)

Development

# Run linter
npm run lint

# Build for production
npm run build

# Start production server
npm start

Resources

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Submit a pull request

License

MIT License - see LICENSE file for details


Built with πŸ’™ on Base

Base β€’ Mini-Apps β€’ OnchainKit

About

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •