feat: Implement comprehensive Nostr identity and social features

## Core Identity Management
- Add secure key generation and import functionality
- Implement AES-GCM encryption with PBKDF2 key derivation
- Create password-protected identity storage
- Add browser-compatible crypto utilities (no Buffer dependency)

## User Interface
- Build identity management dialog with tabs for setup and profile
- Add navbar integration with user dropdown and mobile support
- Create password unlock dialog for encrypted identities
- Integrate vue-sonner for toast notifications

## Nostr Protocol Integration
- Implement event creation (notes, reactions, profiles, contacts)
- Add reply thread detection and engagement metrics
- Create social interaction composables for publishing
- Support multi-relay publishing with failure handling
- Add profile fetching and caching system

## Security Features
- Web Crypto API with 100k PBKDF2 iterations
- Secure random salt and IV generation
- Automatic password prompts for encrypted storage
- Legacy support for unencrypted identities

## Technical Improvements
- Replace all Buffer usage with browser-native APIs
- Add comprehensive error handling and validation
- Implement reactive state management with Vue composables
- Create reusable crypto utility functions

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
padreug 2025-07-02 16:25:20 +02:00
parent d3e8b23c86
commit ee7eb461c4
12 changed files with 1777 additions and 21 deletions

42
src/lib/utils/crypto.ts Normal file
View file

@ -0,0 +1,42 @@
/**
* Crypto utility functions for browser environments
*/
/**
* Convert hex string to Uint8Array
*/
export function hexToBytes(hex: string): Uint8Array {
if (hex.length % 2 !== 0) {
throw new Error('Hex string must have even length')
}
const bytes = hex.match(/.{2}/g)?.map(byte => parseInt(byte, 16))
if (!bytes) {
throw new Error('Invalid hex string')
}
return new Uint8Array(bytes)
}
/**
* Convert Uint8Array to hex string
*/
export function bytesToHex(bytes: Uint8Array): string {
return Array.from(bytes)
.map(b => b.toString(16).padStart(2, '0'))
.join('')
}
/**
* Convert string to Uint8Array
*/
export function stringToBytes(str: string): Uint8Array {
return new TextEncoder().encode(str)
}
/**
* Convert Uint8Array to string
*/
export function bytesToString(bytes: Uint8Array): string {
return new TextDecoder().decode(bytes)
}