88 lines
2.9 KiB
Markdown
88 lines
2.9 KiB
Markdown
# Rosetta Encryption Specification
|
||
|
||
All encryption must be **cross-platform compatible** with the Android and Desktop versions.
|
||
|
||
## Message Encryption: XChaCha20-Poly1305
|
||
|
||
```
|
||
Encrypt:
|
||
1. Generate random 32-byte key + 24-byte nonce
|
||
2. HChaCha20(key, nonce[0:16]) → 32-byte subkey
|
||
3. ChaCha20 nonce = [0,0,0,0] + nonce[16:24]
|
||
4. Generate Poly1305 key from first 64 bytes of keystream
|
||
5. ChaCha20 encrypt plaintext (counter starts at 1)
|
||
6. Compute Poly1305 tag over ciphertext (padded to 16-byte boundaries)
|
||
7. Output: ciphertext + 16-byte tag (hex encoded)
|
||
|
||
Decrypt:
|
||
1. Extract 16-byte tag from end of ciphertext
|
||
2. Verify Poly1305 tag (reject if invalid)
|
||
3. Decrypt with ChaCha20
|
||
```
|
||
|
||
## Key Exchange: ECDH (secp256k1)
|
||
|
||
```
|
||
Encrypt key for recipient:
|
||
1. Generate random ephemeral private key (32 bytes)
|
||
2. Compute ephemeral public key = G × ephemeralPrivateKey (secp256k1)
|
||
3. Compute shared secret = recipientPublicKey × ephemeralPrivateKey
|
||
4. Use x-coordinate (32 bytes) as AES key
|
||
5. Generate random IV (16 bytes)
|
||
6. AES-256-CBC encrypt (key + nonce) with shared secret
|
||
7. Output: Base64(IV : ciphertext : ephemeralPrivateKey)
|
||
|
||
Decrypt key:
|
||
1. Parse ephemeralPrivateKey from Base64
|
||
2. Compute ephemeralPublicKey = G × ephemeralPrivateKey
|
||
3. Compute shared secret = ephemeralPublicKey × myPrivateKey
|
||
4. AES-256-CBC decrypt with shared secret + IV
|
||
5. Extract 32-byte key + 24-byte nonce
|
||
```
|
||
|
||
## Key Generation (from Seed Phrase)
|
||
|
||
```
|
||
1. BIP39 mnemonicToSeed(phrase, "") → PBKDF2-SHA512, 2048 iterations, salt="mnemonic" → 64 bytes
|
||
2. Convert bytes to hex string (128 characters)
|
||
3. SHA256(hexSeed) → 32-byte private key
|
||
4. secp256k1: publicKey = G × privateKey (compressed, 33 bytes)
|
||
```
|
||
|
||
## Password-Based Encryption (Account Storage)
|
||
|
||
```
|
||
1. zlib deflate compress the data
|
||
2. PBKDF2-HMAC-SHA256: password, salt="rosetta", 1000 iterations → 32-byte key
|
||
3. Generate random IV (16 bytes)
|
||
4. AES-256-CBC encrypt compressed data
|
||
5. Output: Base64(IV) : Base64(ciphertext)
|
||
6. For data > 10MB: split into 10MB chunks, prefix with "CHNK:"
|
||
```
|
||
|
||
## Attachment Encryption
|
||
|
||
```
|
||
1. Compress with zlib deflate
|
||
2. Convert plainKeyAndNonce bytes to UTF-8 string (JS Buffer compatibility)
|
||
3. PBKDF2-HMAC-SHA256: keyAndNonce string, salt="rosetta", 1000 iterations
|
||
4. Generate random IV (16 bytes)
|
||
5. AES-256-CBC encrypt
|
||
6. Output: Base64(IV) : Base64(ciphertext)
|
||
```
|
||
|
||
## Biometric Auth (iOS Keychain)
|
||
|
||
```
|
||
- Store password in iOS Keychain with biometric access control
|
||
- Use kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
|
||
- SecAccessControlCreateFlags: .biometryCurrentSet
|
||
- Encrypt with Secure Enclave where available
|
||
```
|
||
|
||
## iOS Crypto Libraries
|
||
- **CryptoKit** — for SHA256, HMAC, AES-GCM
|
||
- **Security.framework** — for Keychain, SecKey, Secure Enclave
|
||
- **secp256k1.swift** (via SPM) or **libsecp256k1** — for elliptic curve operations
|
||
- **Custom XChaCha20-Poly1305** — implement or use a Swift wrapper around libsodium
|