feat(chat): Implement end-to-end encrypted swarm messaging system
- Add Swarm Chat documentation with architecture, API endpoints, and security considerations - Create database schema for chat conversations, messages, and typing indicators - Implement chat API endpoints for sending, receiving, and managing messages - Add client-side encryption utilities using RSA-OAEP with SHA-256 - Create chat page UI for viewing conversations and messages - Add chat type definitions for TypeScript support - Update database schema with new chat tables and relationships - Update sidebar navigation to include chat link - Enable true end-to-end encrypted messaging across swarm nodes without ActivityPub limitations
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Swarm Chat Cryptography
|
||||
*
|
||||
* End-to-end encryption for chat messages using public key cryptography.
|
||||
*/
|
||||
|
||||
import crypto from 'crypto';
|
||||
|
||||
/**
|
||||
* Encrypt a message using the recipient's public key
|
||||
*/
|
||||
export function encryptMessage(message: string, recipientPublicKey: string): string {
|
||||
try {
|
||||
// Use RSA-OAEP for encryption
|
||||
const encrypted = crypto.publicEncrypt(
|
||||
{
|
||||
key: recipientPublicKey,
|
||||
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
|
||||
oaepHash: 'sha256',
|
||||
},
|
||||
Buffer.from(message, 'utf8')
|
||||
);
|
||||
|
||||
return encrypted.toString('base64');
|
||||
} catch (error) {
|
||||
console.error('Failed to encrypt message:', error);
|
||||
throw new Error('Encryption failed');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt a message using the recipient's private key
|
||||
*/
|
||||
export function decryptMessage(encryptedMessage: string, privateKey: string): string {
|
||||
try {
|
||||
const decrypted = crypto.privateDecrypt(
|
||||
{
|
||||
key: privateKey,
|
||||
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
|
||||
oaepHash: 'sha256',
|
||||
},
|
||||
Buffer.from(encryptedMessage, 'base64')
|
||||
);
|
||||
|
||||
return decrypted.toString('utf8');
|
||||
} catch (error) {
|
||||
console.error('Failed to decrypt message:', error);
|
||||
throw new Error('Decryption failed');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign a message payload for authenticity verification
|
||||
*/
|
||||
export function signPayload(payload: string, privateKey: string): string {
|
||||
try {
|
||||
const sign = crypto.createSign('SHA256');
|
||||
sign.update(payload);
|
||||
sign.end();
|
||||
|
||||
const signature = sign.sign(privateKey, 'base64');
|
||||
return signature;
|
||||
} catch (error) {
|
||||
console.error('Failed to sign payload:', error);
|
||||
throw new Error('Signing failed');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify a signed payload
|
||||
*/
|
||||
export function verifySignature(payload: string, signature: string, publicKey: string): boolean {
|
||||
try {
|
||||
const verify = crypto.createVerify('SHA256');
|
||||
verify.update(payload);
|
||||
verify.end();
|
||||
|
||||
return verify.verify(publicKey, signature, 'base64');
|
||||
} catch (error) {
|
||||
console.error('Failed to verify signature:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Swarm Chat Types
|
||||
*
|
||||
* Type definitions for the swarm chat system.
|
||||
*/
|
||||
|
||||
export interface SwarmChatMessage {
|
||||
id: string;
|
||||
conversationId: string;
|
||||
senderHandle: string;
|
||||
senderDisplayName?: string;
|
||||
senderAvatarUrl?: string;
|
||||
senderNodeDomain?: string;
|
||||
encryptedContent: string;
|
||||
deliveredAt?: string;
|
||||
readAt?: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface SwarmChatConversation {
|
||||
id: string;
|
||||
type: 'direct' | 'group';
|
||||
participant1Id: string;
|
||||
participant2Handle: string;
|
||||
lastMessageAt?: string;
|
||||
lastMessagePreview?: string;
|
||||
unreadCount?: number;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Payload for sending a chat message to a remote node
|
||||
*/
|
||||
export interface SwarmChatMessagePayload {
|
||||
messageId: string;
|
||||
senderHandle: string;
|
||||
senderDisplayName?: string;
|
||||
senderAvatarUrl?: string;
|
||||
senderNodeDomain: string;
|
||||
recipientHandle: string;
|
||||
encryptedContent: string;
|
||||
timestamp: string;
|
||||
signature?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Payload for typing indicator
|
||||
*/
|
||||
export interface SwarmChatTypingPayload {
|
||||
senderHandle: string;
|
||||
senderNodeDomain: string;
|
||||
recipientHandle: string;
|
||||
isTyping: boolean;
|
||||
timestamp: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Payload for read receipt
|
||||
*/
|
||||
export interface SwarmChatReadReceiptPayload {
|
||||
messageId: string;
|
||||
readerHandle: string;
|
||||
readerNodeDomain: string;
|
||||
timestamp: string;
|
||||
}
|
||||
Reference in New Issue
Block a user