mirror of
https://github.com/jjbrunton/Sauci.git
synced 2026-11-01 18:19:43 +00:00
Improve E2EE robustness and Android permissions
- Add IV validation and key sanitization for encryption - Add stale key repair for media decryption failures - Block READ_MEDIA_IMAGES/VIDEO permissions (use photo picker) - Prevent double-tap crashes in media picker - Clear media cache on logout - Persist versionCode/buildNumber in app.json - Bump Android targetSdk to 35
This commit is contained in:
1 parent
198cd80dfd
commit
348ef221db
13 files changed
+777
-106
No files matched your search
@@ -49,7 +49,13 @@ export async function decryptMediaFile(
|
||||
);
|
||||
const encryptedData = base64ToArrayBuffer(encryptedBase64);
|
||||
|
||||
// 3. Unwrap AES key
|
||||
// 3. Validate and decode IV (must be exactly 12 bytes for AES-GCM)
|
||||
const iv = base64ToUint8Array(encryptionIv);
|
||||
if (iv.length !== 12) {
|
||||
throw new Error(`Invalid IV length: expected 12 bytes, got ${iv.length}`);
|
||||
}
|
||||
|
||||
// 4. Unwrap AES key
|
||||
const wrappedKeyBase64 = isRecipient
|
||||
? keysMetadata.recipient_wrapped_key
|
||||
: keysMetadata.sender_wrapped_key;
|
||||
@@ -61,11 +67,10 @@ export async function decryptMediaFile(
|
||||
const rawAesKey = await unwrapAESKey(wrappedKeyBase64, privateKeyJwk);
|
||||
const aesKey = await importAESKey(rawAesKey);
|
||||
|
||||
// 4. Decrypt file
|
||||
const iv = base64ToUint8Array(encryptionIv);
|
||||
// 5. Decrypt file
|
||||
const decryptedData = await decryptAES(encryptedData, aesKey, iv);
|
||||
|
||||
// 5. Write decrypted file
|
||||
// 6. Write decrypted file
|
||||
const ext = mediaType === 'video' ? 'mp4' : 'jpg';
|
||||
const decryptedUri = `${FileSystem.cacheDirectory}${Date.now()}_decrypted.${ext}`;
|
||||
|
||||
|
||||
@@ -35,18 +35,23 @@ export async function decryptTextMessage(
|
||||
throw new Error('No wrapped key available for decryption');
|
||||
}
|
||||
|
||||
// 2. Unwrap AES key using RSA private key
|
||||
// 2. Validate and decode IV (must be exactly 12 bytes for AES-GCM)
|
||||
const iv = base64ToUint8Array(encryptionIv);
|
||||
if (iv.length !== 12) {
|
||||
throw new Error(`Invalid IV length: expected 12 bytes, got ${iv.length}`);
|
||||
}
|
||||
|
||||
// 3. Unwrap AES key using RSA private key
|
||||
const rawAesKey = await unwrapAESKey(wrappedKeyBase64, privateKeyJwk);
|
||||
|
||||
// 3. Import AES key
|
||||
// 4. Import AES key
|
||||
const aesKey = await importAESKey(rawAesKey);
|
||||
|
||||
// 4. Decrypt content
|
||||
const iv = base64ToUint8Array(encryptionIv);
|
||||
// 5. Decrypt content
|
||||
const ciphertext = base64ToArrayBuffer(encryptedContent);
|
||||
|
||||
const plaintext = await decryptAES(ciphertext, aesKey, iv);
|
||||
|
||||
// 5. Decode to string
|
||||
// 6. Decode to string
|
||||
return new TextDecoder().decode(plaintext);
|
||||
}
|
||||
Reference in new issue
Block a user