Skip to content

feat: create password input component for edit protection #65

Closed
@nullcoder

Description

@nullcoder

Description

Create a secure password input component for edit protection using PBKDF2 as specified.

Requirements

  • Password input for 8-64 character passwords
  • Support alphanumeric and special characters
  • Masked input by default with show/hide toggle
  • Validation for length requirements (8-64 chars)
  • Validation messages for errors
  • Character counter showing X/64
  • Confirm password field for initial setup
  • Password strength indicator
  • Accessible labels and error announcements
  • Must implement PBKDF2-SHA256 with 100,000 iterations
  • Generate random 16-byte salt for each gist

Acceptance Criteria

  • Password input accepts alphanumeric and special characters
  • Enforces 8-64 character length requirement
  • Show/hide toggle works for both fields
  • Real-time validation shows clear error messages
  • Character counter updates as user types
  • Password strength indicator shows weak/medium/strong
  • Confirm field validates match with primary field
  • Generates proper PBKDF2 hash for storage
  • Returns both hash and salt to parent component
  • Accessible with screen readers
  • Secure input field (type="password")

UI Structure

Set Edit Password (Optional)
┌─────────────────────────────────────┐
│ Password: ●●●●●●●● [👁️]     8/64    │
└─────────────────────────────────────┘
💪 Strength: Medium
⚠️ Password must be at least 8 characters

┌─────────────────────────────────────┐
│ Confirm: ●●●●●●●● [👁️]      8/64    │
└─────────────────────────────────────┘
✓ Passwords match

Technical Implementation

interface PasswordInputProps {
  value: string;
  onChange: (value: string) => void;
  onValidHash?: (hash: string, salt: string) => void;
  mode: 'create' | 'verify';
  existingHash?: string; // For verify mode
  existingSalt?: string; // For verify mode
}

// PBKDF2 implementation
async function hashPassword(password: string, salt: Uint8Array): Promise<string> {
  const encoder = new TextEncoder();
  const keyMaterial = await crypto.subtle.importKey(
    'raw',
    encoder.encode(password),
    'PBKDF2',
    false,
    ['deriveBits']
  );
  
  const hashBuffer = await crypto.subtle.deriveBits(
    {
      name: 'PBKDF2',
      salt: salt,
      iterations: 100000,
      hash: 'SHA-256'
    },
    keyMaterial,
    256 // 32 bytes
  );
  
  return btoa(String.fromCharCode(...new Uint8Array(hashBuffer)));
}

Validation Rules

  • Minimum 8 characters (security)
  • Maximum 64 characters (usability)
  • Allow letters, numbers, special characters
  • Clear error messages:
    • "Password must be at least 8 characters"
    • "Password must be no more than 64 characters"
    • "Passwords do not match"

Password Strength Rules

  • Weak: < 12 characters or only one character type
  • Medium: 12+ characters with 2+ character types
  • Strong: 16+ characters with 3+ character types (letters, numbers, special)

Security Considerations

  • Never log or store plain text password
  • Use constant-time comparison for verification
  • Clear password from memory after hashing
  • Implement rate limiting on verify attempts
  • Consider clipboard clearing after paste
  • Use secure input field attributes

Related

  • Part of Phase 4 UI Components
  • Used in create/edit gist forms
  • Must follow PBKDF2 spec from SPEC.md
  • Critical for edit protection feature

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureNew feature implementationpriority: mediumNormal priorityuiUser interface and components

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions