feat(crypto): sender-key per-conversation multi-device E2EE
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
import { getCryptoBackend } from './backend.js';
|
||||
import { decryptFrom, encryptFor, type EncryptedEnvelope } from './box.js';
|
||||
|
||||
// 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<EncryptedEnvelope> {
|
||||
return encryptFor(convKey, recipientPublicKey, senderPrivateKey);
|
||||
}
|
||||
|
||||
export async function unwrapConvKey(
|
||||
encryptedKey: Uint8Array,
|
||||
nonce: Uint8Array,
|
||||
senderPublicKey: Uint8Array,
|
||||
recipientPrivateKey: Uint8Array,
|
||||
): Promise<Uint8Array> {
|
||||
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);
|
||||
}
|
||||
Reference in New Issue
Block a user