kd_totp

Time-based One-Time Password (TOTP) 2FA implementation per RFC 6238 and RFC 4226.

Features

  • RFC 6238 (TOTP) and RFC 4226 (HOTP) compliant
  • Two-step enrollment: setup → confirm → enable
  • Replay attack prevention with counter tracking
  • Configurable clock drift tolerance
  • QR code URI generation (Google Authenticator compatible)
  • Timing-safe code comparison
  • PostgreSQL and SQLite support

Installation

dependencies:
  kd_totp: ^1.0.0

Usage

Low-Level Algorithm

import 'package:kd_totp/kd_totp.dart';

// Generate a secret
final secret = TotpAlgorithm.generateSecret();

// Generate a TOTP code
final code = TotpAlgorithm.totp(secret);

// Verify a code
final result = TotpAlgorithm.verify(secret, code);
if (result != null) {
  print('Valid! Delta: $result');
}

// Generate a QR code URI
final uri = TotpAlgorithm.generateUri(
  secret: secret,
  accountName: 'user@example.com',
  issuer: 'MyApp',
);

Service Layer

final totpService = TotpService(
  repository: SqliteTotpRepository(db),
  config: TotpConfig(
    timeStep: 30,
    digits: 6,
    window: 1,
  ),
);

Enrollment Flow

// Step 1: Generate secret and create pending entry
final secret = totpService.generateSecret();
final uri = totpService.generateUri(
  secret: secret,
  accountName: 'user@example.com',
  issuer: 'MyApp',
);
// Display URI as QR code to user

await totpService.setupTotp(
  accountId: accountId,
  secret: secret,
);

// Step 2: User scans QR code and enters confirmation code
await totpService.enableTotp(
  accountId: accountId,
  confirmationCode: '123456',
);

Login Verification

// Verify and consume code (prevents replay attacks)
await totpService.verifyAndConsume(
  accountId: accountId,
  code: '654321',
);

Configuration

OptionDefaultDescription
timeStep30TOTP time step in seconds
digits6Number of digits in the code
window1Clock drift tolerance