import { getCryptoBackend } from './backend'; import { decryptFrom, encryptFor, type EncryptedEnvelope } from './box'; // Sender-Key (Signal-style) helpers — one symmetric XSalsa20-Poly1305 key per // conversation, wrapped with `crypto_box` for each recipient device's pubkey. // // Flow: // - generateConvKey() produces 32 random bytes // - wrapConvKeyForRecipient() encrypts the conv-key with sender's private key // and recipient's pubkey -> stored in `conversation_keys` table // - unwrapConvKey() reverses it on the receiving side // - encryptWithConvKey()/decryptWithConvKey() do the message-payload work export function generateConvKey(): Uint8Array { const backend = getCryptoBackend(); return backend.randomBytes(backend.secretboxKeyLength); } export async function wrapConvKeyForRecipient( convKey: Uint8Array, recipientPublicKey: Uint8Array, senderPrivateKey: Uint8Array, ): Promise { return encryptFor(convKey, recipientPublicKey, senderPrivateKey); } export async function unwrapConvKey( encryptedKey: Uint8Array, nonce: Uint8Array, senderPublicKey: Uint8Array, recipientPrivateKey: Uint8Array, ): Promise { return decryptFrom(encryptedKey, nonce, senderPublicKey, recipientPrivateKey); } export interface ConvCipher { ciphertext: Uint8Array; nonce: Uint8Array; } export function encryptWithConvKey( plaintext: Uint8Array, convKey: Uint8Array, ): ConvCipher { const backend = getCryptoBackend(); const nonce = backend.randomBytes(backend.secretboxNonceLength); const ciphertext = backend.secretbox(plaintext, nonce, convKey); return { ciphertext, nonce }; } export function decryptWithConvKey( ciphertext: Uint8Array, nonce: Uint8Array, convKey: Uint8Array, ): Uint8Array { const backend = getCryptoBackend(); return backend.secretboxOpen(ciphertext, nonce, convKey); }