# @toled/signal-expo

Signal Protocol encryption for Expo/React Native - wraps the official [libsignal](https://github.com/signalapp/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

```bash
npm install @toled/signal-expo expo-secure-store
```

Add the plugin to your `app.json` or `app.config.js`:

```json
{
  "expo": {
    "plugins": ["@toled/signal-expo"]
  }
}
```

Then generate native projects and run:

```bash
# Generate native iOS/Android projects
npx expo prebuild --clean

# Run on iOS
npx expo run:ios

# Run on Android
npx expo run:android
```

### Using EAS Build

```bash
eas build --profile development --platform all
```

## Usage

```typescript
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

```typescript
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](https://signal.org/docs/) implementation from [libsignal](https://github.com/signalapp/libsignal).
