Skip to content

How It Works

ByteAuth uses public-key cryptography to authenticate users without passwords. This page explains the complete authentication flow and the cryptographic principles behind it.

ByteAuth uses ECDSA (Elliptic Curve Digital Signature Algorithm) with the secp256k1 curve — the same cryptographic standard that secures Bitcoin transactions worth billions of dollars.

Private Key : A 256-bit random number known only to the user. Stored securely on their device, protected by biometric authentication.

Public Key : Derived mathematically from the private key. Shared with your application to verify signatures. Cannot be used to derive the private key.

Digital Signature : Proof that the holder of a private key authorized a specific message. Created by signing a challenge with the private key.

Challenge : A unique, time-limited string that must be signed to prove identity. Prevents replay attacks.

  1. Client Requests QR Code

    Your frontend requests a new authentication session from your backend. The server generates:

    • A unique session ID
    • A cryptographic challenge (random string)
    • A timestamp
    // Response from your server
    {
    "session_id": "sess_abc123",
    "challenge": "Sign this to login to example.com at 1699876543",
    "expires_at": 1699876573
    }
  2. QR Code Displayed

    The QR code encodes a URL containing:

    • Your webhook URL
    • The session ID
    • The challenge
    • Timestamp

    The QR refreshes every 30 seconds with a new challenge, but the session ID remains constant until page reload.

  3. User Scans with ByteVault

    The ByteVault app:

    • Decodes the QR data
    • Displays your domain name for verification
    • Prompts for biometric authentication (Face ID/Touch ID)
  4. ByteVault Signs Challenge

    After biometric confirmation, ByteVault:

    • Derives the domain-specific private key
    • Signs the challenge using ECDSA/SHA256
    • Sends the signature to your webhook endpoint
    // POST to your webhook
    {
    "public_key": "04a1b2c3...",
    "signature": "3045022100...",
    "challenge": "Sign this to login to example.com at 1699876543",
    "timestamp": 1699876545
    }
  5. Server Verifies Signature

    Your server:

    • Retrieves the challenge from the session
    • Verifies the signature using the public key
    • Confirms the timestamp is within the valid window
    • Creates or retrieves the user record
    • Marks the session as authenticated
  6. Client Polls for Status

    Your frontend polls an endpoint every 5 seconds:

    GET /api/check?session_id=sess_abc123
    // Response when authenticated
    { "status": "authenticated", "user_id": 123 }
  7. User Authenticated

    Upon receiving the authenticated status, redirect the user to their dashboard.

ByteVault generates a unique key pair for each domain you integrate with. This is accomplished through deterministic key derivation:

Master Seed + Domain Name → Domain-Specific Private Key → Public Key
  1. Privacy - Different public keys per service prevent cross-site tracking
  2. Security - Compromising one key doesn’t affect others
  3. Recovery - All keys can be regenerated from the master seed
AttackHow It’s Prevented
PhishingPrivate keys never leave the device. Fake sites can’t steal credentials.
Credential StuffingNo passwords to reuse. Each site gets a unique public key.
Man-in-the-MiddleSignatures are domain-bound. Intercepted signatures can’t be replayed.
Replay AttacksChallenges expire in 30 seconds and can only be used once.
Database BreachesPublic keys are public. Stealing them doesn’t grant access.

ByteVault requires biometric authentication (Face ID, Touch ID, or device passcode) before signing any challenge. This ensures:

  1. Device possession - The attacker must have the physical device
  2. User presence - The legitimate user must actively approve
  3. Liveness - Built-in liveness detection prevents photo/video attacks

The challenge string includes:

Action: login|register
Domain: yourdomain.com
Timestamp: Unix epoch seconds
Nonce: Random 32-character string

Example:

Sign this to login to example.com at 1699876543:a1b2c3d4e5f6...

To verify a signature, use your framework’s ECDSA library:

import { ec as EC } from 'elliptic';
import crypto from 'crypto';
const secp256k1 = new EC('secp256k1');
function verifySignature(publicKey, signature, message) {
const hash = crypto.createHash('sha256').update(message).digest();
const key = secp256k1.keyFromPublic(publicKey, 'hex');
return key.verify(hash, signature);
}
ComponentTiming
QR Code RefreshEvery 30 seconds
Challenge Validity30 seconds
Client PollingEvery 5 seconds
Session LifetimeUntil page reload