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:
parent
d3e8b23c86
commit
ee7eb461c4
12 changed files with 1777 additions and 21 deletions
42
src/lib/utils/crypto.ts
Normal file
42
src/lib/utils/crypto.ts
Normal 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)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue