Privacy Tools Guide

Migrate from Google Authenticator to password manager TOTP by adding TOTP secrets during account setup instead of using Google’s proprietary format. Password managers like Bitwarden, 1Password, and KeePass generate TOTP codes directly from stored secrets, provide automatic backups, and work across devices. This is more convenient than Google Authenticator (no manual entry needed) and more secure (tied to encrypted password vault rather than unencrypted device) while maintaining the same industry-standard TOTP algorithm.

Understanding TOTP Mechanics

TOTP generates temporary codes based on a shared secret and the current time. The algorithm follows RFC 6238 and produces 6-digit codes that expire every 30 seconds.

The core TOTP formula:

TOTP = HMAC-SHA1(secret, floor(current_unix_time / 30))

When you set up 2FA, the service provides a Base32-encoded secret. During authentication, both your device and the server generate codes using this secret and the same time window. If the codes match, authentication succeeds.

Why Migrate to Your Password Manager

Password managers that support TOTP offer several advantages over standalone authenticator apps:

Unified Storage: Your 2FA secrets live alongside your passwords, meaning one secure vault protects all your credentials. This eliminates the need to manage separate apps and reduces the attack surface.

Encrypted Backups: Unlike Google Authenticator’s lack of export options, password managers provide encrypted backups of your entire vault, including TOTP secrets.

Cross-Device Sync: Access your 2FA codes across desktop and mobile without manual transfer.

Search and Organization: Quickly find any 2FA code using your password manager’s search functionality rather than scrolling through a list of service icons.

Migrating from Google Authenticator

The migration process requires exporting your secrets from Google Authenticator and importing them into your password manager. Google Authenticator stores codes in QR codes or as manual entry keys.

Step 1: Export Your Google Authenticator Secrets

Open Google Authenticator and tap the three-dot menu. Select “Transfer accounts” then “Export accounts.” The app generates QR codes containing your secrets. Scan these with another device or decode them using tools like zbarimg:

# Install zbar tools
brew install zbar

# Decode QR code (if saved as image)
zbarimg google_auth_export.png

Alternatively, manually note the secret keys displayed in Google Authenticator during setup. Each entry shows the service name and the Base32 secret.

Step 2: Import into Your Password Manager

Most password managers support TOTP import via QR scanning or manual entry. For Bitwarden, for example:

  1. Open Bitwarden Vault
  2. Navigate to Options → Import
  3. Select “Google Authenticator (CSV)” as import source
  4. Upload your exported CSV file

For 1Password, scan the QR codes directly using the mobile app’s camera.

Using TOTP Programmatically

Developers often need to generate TOTP codes for automation or testing. The otpauth library provides straightforward implementation:

from otpauth import OtpAuth

# Initialize with your Base32 secret
totp = OtpAuth(secret="JBSWY3DPEHPK3PXP")

# Generate current TOTP code
code = totp.to_uri()  # otpauth://totp/Example:secret?secret=...
print(f"Current code: {totp.generate()}")

For command-line TOTP generation, oathtool from the oath-toolkit package works well:

# Install oathtool
brew install oath-toolkit

# Generate TOTP from secret
oathtool --base32 --totp JBSWY3DPEHPK3PXP

This outputs a 6-digit code matching what your password manager displays.

Implementing TOTP in Your Applications

If you are building authentication systems, storing TOTP secrets requires careful handling:

import secrets
import base64

def generate_totp_secret():
    """Generate a secure random Base32 TOTP secret."""
    return base64.b32encode(secrets.token_bytes(20)).decode('utf-8')

def verify_totp(secret, token):
    """Verify a TOTP token against a stored secret."""
    from otpauth import OtpAuth
    totp = OtpAuth(secret=secret)
    return totp.verify(token, valid_window=1)

Store secrets in your database with encryption at rest. Never log or expose TOTP secrets in plaintext.

Security Considerations

While password managers with TOTP provide excellent convenience, consider these best practices:

Master Password Strength: Your master password protects all 2FA codes. Use a long, unique phrase with entropy exceeding 60 bits.

Enable Biometric Unlock: Most password managers support fingerprint or Face ID for quick access without compromising security.

Export Encrypted Backups: Regularly export an encrypted backup of your vault. Store this in a secure location separate from your primary device.

Use Hardware Security Keys for Critical Accounts: For high-value accounts (cryptocurrency, primary email), consider hardware keys like YubiKey over TOTP.

Troubleshooting Common Issues

Time Synchronization: TOTP requires accurate time on both device and server. If codes fail consistently, verify your system clock:

# Check time drift (macOS)
sudo sntp -s time.apple.com

Secret Key Format: Ensure you enter secrets in Base32 format. Some services display secrets in hexadecimal, requiring conversion.

Duplicate Entries: Some password managers create separate entries for passwords and TOTP. Verify your vault structure after import.

Advanced TOTP Implementation for Developers

For developers building applications that use TOTP for user authentication, understanding implementation details improves security.

Server-Side TOTP Verification

Implement strong TOTP verification that accounts for clock drift:

import hmac
import hashlib
import base64
import time
import struct

def verify_totp(secret, token, window=1):
    """
    Verify TOTP token with time window tolerance.

    window: Number of 30-second periods to accept
    (0 = current period only, 1 = current ± 1 period)
    """
    token = int(token)
    secret_bytes = base64.b32decode(secret)

    # Get current time counter
    time_counter = int(time.time()) // 30

    # Check token against multiple time windows
    for i in range(-window, window + 1):
        expected = hmac.new(
            secret_bytes,
            struct.pack('>Q', time_counter + i),
            hashlib.sha1
        ).digest()

        # Extract 31-bit integer from HMAC
        offset = expected[-1] & 0xf
        code = struct.unpack('>I', expected[offset:offset+4])[0] & 0x7fffffff
        code = code % 1000000

        if code == token:
            return True

    return False

This implementation handles:

Backup Codes for Account Recovery

When users store TOTP in a password manager, they must have recovery mechanisms if their vault is inaccessible:

import secrets

def generate_backup_codes(count=8):
    """Generate backup codes for TOTP recovery."""
    codes = []
    for _ in range(count):
        # 8 alphanumeric characters per code
        code = secrets.token_urlsafe(6)[:8].upper()
        codes.append(code)
    return codes

def hash_backup_code(code):
    """Hash backup code for storage (like passwords)."""
    import hashlib
    return hashlib.sha256(code.encode()).hexdigest()

Generate backup codes during TOTP setup. Users save them offline (printed, encrypted file) for emergency use.

Database Schema for TOTP Storage

Store TOTP secrets securely at the application level:

CREATE TABLE user_totp_credentials (
    id SERIAL PRIMARY KEY,
    user_id INTEGER NOT NULL UNIQUE REFERENCES users(id),
    secret VARCHAR(32) NOT NULL,
    backup_codes_hash TEXT[] NOT NULL,
    enabled_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    last_used_at TIMESTAMP,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Separate table for backup code tracking
CREATE TABLE backup_code_usage (
    id SERIAL PRIMARY KEY,
    user_id INTEGER NOT NULL REFERENCES users(id),
    code_hash VARCHAR(64) NOT NULL,
    used_at TIMESTAMP,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Never store backup codes in plaintext. Hash them using bcrypt or similar, similar to password storage.

TOTP Setup Flow Best Practices

  1. Generate secret on server, don’t trust client-generated secrets
  2. Display secret in Base32 and QR code for user to scan
  3. Require test token before enabling (user provides one generated token to verify)
  4. Display backup codes only once, clearly warn to save offline
  5. Enforce backup code save before enabling TOTP
def setup_totp_for_user(user_id):
    # Generate 32-byte secret (256 bits)
    secret = base64.b32encode(secrets.token_bytes(32)).decode('utf-8')

    # Generate backup codes
    backup_codes = generate_backup_codes(10)

    # Create QR code for easy scanning
    totp_uri = f"otpauth://totp/{user_id}?secret={secret}&issuer=YourApp"

    return {
        'secret': secret,
        'qr_code_uri': totp_uri,
        'backup_codes': backup_codes,  # Show ONCE, then hash for storage
        'backup_codes_hash': [hash_backup_code(c) for c in backup_codes]
    }

Migration from Authenticator Apps

When users migrate from Google Authenticator or Authy:

def export_totp_for_migration(user_id):
    """Generate portable TOTP export for user."""
    user_secrets = get_user_totp_secrets(user_id)

    export_data = {
        'version': 1,
        'date': datetime.now().isoformat(),
        'secrets': [
            {
                'account': secret.account_name,
                'secret': secret.base32_secret,
                'issuer': secret.issuer,
                'algorithm': 'SHA1'
            }
            for secret in user_secrets
        ]
    }

    # Encrypt for safety
    encrypted = encrypt_export(export_data)

    return encrypted

Comparison: Password Manager TOTP vs Dedicated Authenticators

Aspect Password Manager Google Authenticator Authy Hardware Key
Cost Free (with manager) Free Free $40-80
Backup/Sync Automatic (encrypted) No automatic backup Cloud sync (optional) Manual backup
Search Yes No (icon-based) Yes N/A
Recovery Codes Easy access Manual tracking Manual tracking Printed codes
Account Recovery Master password Difficult Account recovery Recovery codes only
Phishing Resistant No No No Yes (FIDO2)

Password managers excel at convenience and organization. Hardware keys (YubiKey with FIDO2 protocol) provide maximum security but lack TOTP generation. Dedicated authenticators offer a middle ground with cloud sync options.

Use Case Recommendations

Use password manager TOTP for:

Use hardware keys for:

Use dedicated authenticators for:

TOTP at Scale: Enterprise Implementation

Organizations deploying TOTP should implement:

class EnterpriseOTPPolicy:
    def __init__(self):
        self.min_setup_time = 72  # Hours to set up after enabling
        self.rate_limit = 5  # Failed attempts per minute
        self.backup_code_count = 10
        self.window_size = 1  # Accept ±1 time window
        self.algorithm = 'SHA1'

    def enforce_totp_setup(self, user):
        """Require TOTP for users with elevated privileges."""
        if user.is_admin or user.has_access_to_sensitive_systems:
            if not user.totp_enabled:
                user.totp_setup_deadline = datetime.now() + timedelta(days=3)
                user.totp_enforcement = True

Enforce TOTP for:

Built by theluckystrike — More at zovo.one