Closed
Description
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