import SignalExpoModule from './SignalExpoModule'; import { IdentityKeyPair, PreKeyRecord, SignedPreKeyRecord, KyberPreKeyRecord, PreKeyBundle, ProtocolAddress, CiphertextMessage, DecryptedMessage, } from './SignalExpo.types'; // Re-export types export { IdentityKeyPair, PreKeyRecord, SignedPreKeyRecord, KyberPreKeyRecord, PreKeyBundle, ProtocolAddress, CiphertextMessage, DecryptedMessage, }; /** * Generate a new identity key pair for the Signal Protocol. * This should be called once when setting up a new user/device. */ export function generateIdentityKeyPair(): IdentityKeyPair { return SignalExpoModule.generateIdentityKeyPair(); } /** * Generate a registration ID for the Signal Protocol. * This is a 14-bit value used to identify the local installation. */ export function generateRegistrationId(): number { return SignalExpoModule.generateRegistrationId(); } /** * Generate a batch of pre-keys for the X3DH key agreement. * Pre-keys should be uploaded to your server for other users to fetch. * * @param start - Starting ID for the pre-keys * @param count - Number of pre-keys to generate */ export function generatePreKeys(start: number, count: number): PreKeyRecord[] { return SignalExpoModule.generatePreKeys(start, count); } /** * Generate a signed pre-key for the X3DH key agreement. * The signed pre-key is signed with the identity key for verification. * * @param identityKeyPair - The identity key pair to sign with * @param signedPreKeyId - ID for the signed pre-key */ export function generateSignedPreKey( identityKeyPair: IdentityKeyPair, signedPreKeyId: number ): SignedPreKeyRecord { // Pass only privateKey to avoid Record type conversion issues with sync functions return SignalExpoModule.generateSignedPreKey(identityKeyPair.privateKey, signedPreKeyId); } /** * Generate Kyber (post-quantum) pre-keys for PQXDH key agreement. * These provide quantum-resistant key exchange when establishing sessions. * * @param start - Starting ID for the Kyber pre-keys * @param count - Number of Kyber pre-keys to generate * @param identityKeyPair - The identity key pair to sign with */ export function generateKyberPreKeys( start: number, count: number, identityKeyPair: IdentityKeyPair ): KyberPreKeyRecord[] { // Pass only privateKey to avoid Record type conversion issues with sync functions return SignalExpoModule.generateKyberPreKeys(start, count, identityKeyPair.privateKey); } /** * Clear all in-memory stores for user switching. * Call this before initialize() when switching users. */ export async function clear(): Promise { return SignalExpoModule.clear(); } /** * Initialize the Signal protocol with keys. * Must be called before using encrypt/decrypt. * * @param identityKeyPair - The identity key pair * @param registrationId - The registration ID * @param preKeys - Array of pre-keys * @param signedPreKey - The signed pre-key */ export async function initialize( identityKeyPair: IdentityKeyPair, registrationId: number, preKeys: PreKeyRecord[], signedPreKey: SignedPreKeyRecord ): Promise { // Extract values from objects to avoid Record type conversion issues const preKeyIds = preKeys.map(pk => pk.id); const preKeyPrivateKeys = preKeys.map(pk => pk.privateKey); return SignalExpoModule.initialize( identityKeyPair.privateKey, identityKeyPair.publicKey, registrationId, preKeyIds, preKeyPrivateKeys, signedPreKey.id, signedPreKey.privateKey, signedPreKey.signature, signedPreKey.timestamp ); } /** * Store Kyber pre-keys in the native module. * Called during initializeFromStore to restore Kyber keys needed for decryption. * * @param kyberPreKeys - Array of Kyber pre-keys with serialized records */ export async function storeKyberPreKeys( kyberPreKeys: KyberPreKeyRecord[] ): Promise { const kyberPreKeyIds = kyberPreKeys.map(kp => kp.id); const kyberPreKeySerializedRecords = kyberPreKeys.map(kp => kp.serialized); return SignalExpoModule.storeKyberPreKeys( kyberPreKeyIds, kyberPreKeySerializedRecords ); } /** * Initialize a session from a pre-key bundle fetched from the server. * This establishes the initial encrypted session with a recipient. * * @param address - The recipient's address * @param bundle - The recipient's pre-key bundle */ export async function createSession( address: ProtocolAddress, bundle: PreKeyBundle ): Promise { // Kyber keys are required if (!bundle.kyberPreKeyId || !bundle.kyberPreKey || !bundle.kyberPreKeySignature) { throw new Error('Kyber pre-keys are required'); } // Combine INT params into array (to stay under 10 param limit) // IMPORTANT: Only ints in array - Uint8Array/Data does NOT convert properly inside arrays const intParams = [ address.deviceId, bundle.registrationId, bundle.deviceId, bundle.preKeyId, bundle.signedPreKeyId, bundle.kyberPreKeyId ]; return SignalExpoModule.createSession( address.name, intParams, bundle.preKeyPublic, bundle.signedPreKeyPublic, bundle.signedPreKeySignature, bundle.identityKey, bundle.kyberPreKey, bundle.kyberPreKeySignature ); } /** * Check if a session exists with the given address. * * @param address - The address to check */ export async function hasSession(address: ProtocolAddress): Promise { return SignalExpoModule.hasSession(address.name, address.deviceId); } /** * Delete a session with the given address. * * @param address - The address whose session to delete */ export async function deleteSession(address: ProtocolAddress): Promise { return SignalExpoModule.deleteSession(address.name, address.deviceId); } /** * Export a session for persistence. * Returns the serialized session bytes, or null if no session exists. * * @param address - The address whose session to export */ export async function exportSession(address: ProtocolAddress): Promise { return SignalExpoModule.exportSession(address.name, address.deviceId); } /** * Import a session from serialized bytes. * Used to restore sessions after switching users. * * @param address - The address for the session * @param serializedSession - The serialized session bytes */ export async function importSession( address: ProtocolAddress, serializedSession: Uint8Array ): Promise { return SignalExpoModule.importSession(address.name, address.deviceId, serializedSession); } /** * List all session addresses currently in memory. * * @returns Array of protocol addresses */ export async function listSessions(): Promise { const addresses: [string, number][] = await SignalExpoModule.listSessions(); return addresses.map(([name, deviceId]) => ({ name, deviceId })); } /** * Encrypt a message for the given recipient. * * @param address - The recipient's address * @param plaintext - The message to encrypt */ export async function encrypt( address: ProtocolAddress, plaintext: Uint8Array ): Promise { return SignalExpoModule.encrypt(address.name, address.deviceId, plaintext); } /** * Decrypt a message from the given sender. * * @param address - The sender's address * @param ciphertext - The encrypted message */ export async function decrypt( address: ProtocolAddress, ciphertext: CiphertextMessage ): Promise { return SignalExpoModule.decrypt(address.name, address.deviceId, ciphertext.type, ciphertext.body); } /** * Get the local identity public key. * This can be shared with others for verification. */ export async function getIdentityPublicKey(): Promise { return SignalExpoModule.getIdentityPublicKey(); } /** * Get the local registration ID. */ export async function getLocalRegistrationId(): Promise { return SignalExpoModule.getLocalRegistrationId(); }