@toled/signal-expo
v0.5.14
Published
Signal Protocol encryption for Expo - wraps official libsignal library
Maintainers
Readme
@toled/signal-expo
Signal Protocol encryption for Expo/React Native - wraps the official libsignal library.
Features
- End-to-end encryption using the Signal Protocol
- Key generation (identity keys, pre-keys, signed pre-keys)
- Session establishment via X3DH key agreement
- Message encryption/decryption with Double Ratchet
- Built on official Signal libraries (Swift + Kotlin bindings)
Requirements
- Expo SDK 50+ or React Native 0.73+
- iOS 13.0+
- Android API 24+ (Android 7.0)
- Development build required (not compatible with Expo Go)
Installation
npm install @toled/signal-expo expo-secure-storeAdd the plugin to your app.json or app.config.js:
{
"expo": {
"plugins": ["@toled/signal-expo"]
}
}Then generate native projects and run:
# Generate native iOS/Android projects
npx expo prebuild --clean
# Run on iOS
npx expo run:ios
# Run on Android
npx expo run:androidUsing EAS Build
eas build --profile development --platform allUsage
import {
generateIdentityKeyPair,
generateRegistrationId,
generatePreKeys,
generateSignedPreKey,
initialize,
createSession,
encrypt,
decrypt,
} from '@toled/signal-expo';
// 1. Generate identity (do this once per device)
const identityKeyPair = generateIdentityKeyPair();
const registrationId = generateRegistrationId();
const preKeys = generatePreKeys(1, 100);
const signedPreKey = generateSignedPreKey(identityKeyPair, 1);
// 2. Initialize the protocol (required before encrypt/decrypt)
await initialize(identityKeyPair, registrationId, preKeys, signedPreKey);
// 3. Upload to your server (public keys only):
// - identityKeyPair.publicKey
// - registrationId
// - preKeys.map(k => ({ id: k.id, publicKey: k.publicKey }))
// - { id: signedPreKey.id, publicKey: signedPreKey.publicKey, signature: signedPreKey.signature }
// 4. Create session with recipient (using their pre-key bundle from server)
const recipientAddress = { name: 'user123', deviceId: 1 };
await createSession(recipientAddress, recipientPreKeyBundle);
// 5. Encrypt message
const plaintext = new TextEncoder().encode('Hello!');
const ciphertext = await encrypt(recipientAddress, plaintext);
// 6. Decrypt received message
const decrypted = await decrypt(senderAddress, receivedCiphertext);
const message = new TextDecoder().decode(decrypted.plaintext);API
Key Generation
| Function | Description |
|----------|-------------|
| generateIdentityKeyPair() | Creates a new identity key pair |
| generateRegistrationId() | Creates a 14-bit registration ID |
| generatePreKeys(start, count) | Generates pre-keys for X3DH |
| generateSignedPreKey(identityKeyPair, id) | Generates a signed pre-key |
Initialization
| Function | Description |
|----------|-------------|
| initialize(identityKeyPair, registrationId, preKeys, signedPreKey) | Initialize the protocol stores (required before encrypt/decrypt) |
Session Management
| Function | Description |
|----------|-------------|
| createSession(address, bundle) | Establishes session from pre-key bundle |
| hasSession(address) | Checks if session exists |
| deleteSession(address) | Removes a session |
Encryption/Decryption
| Function | Description |
|----------|-------------|
| encrypt(address, plaintext) | Encrypts a message |
| decrypt(address, ciphertext) | Decrypts a message |
Types
interface IdentityKeyPair {
publicKey: Uint8Array; // 33 bytes
privateKey: Uint8Array; // 32 bytes
}
interface ProtocolAddress {
name: string; // User identifier
deviceId: number; // Device ID
}
interface PreKeyBundle {
registrationId: number;
deviceId: number;
preKeyId: number | null;
preKeyPublic: Uint8Array | null;
signedPreKeyId: number;
signedPreKeyPublic: Uint8Array;
signedPreKeySignature: Uint8Array;
identityKey: Uint8Array;
}License
AGPL-3.0 (same as libsignal)
Credits
This library wraps the official Signal Protocol implementation from libsignal.
