From e62ed6c1202195a71567a7cdee34201014d2e808 Mon Sep 17 00:00:00 2001 From: Diego Mello Date: Tue, 14 May 2024 15:37:22 -0300 Subject: [PATCH] Cleanup --- app/definitions/IMessage.ts | 4 + app/lib/encryption/encryption.ts | 42 ------ app/lib/encryption/room.ts | 52 ------- app/lib/encryption/utils.ts | 188 ++----------------------- app/lib/methods/handleMediaDownload.ts | 22 +-- app/lib/methods/sendFileMessage.ts | 6 - app/views/ShareView/index.tsx | 32 +---- 7 files changed, 24 insertions(+), 322 deletions(-) diff --git a/app/definitions/IMessage.ts b/app/definitions/IMessage.ts index 996ec0c4f..4f4806b75 100644 --- a/app/definitions/IMessage.ts +++ b/app/definitions/IMessage.ts @@ -142,6 +142,10 @@ export interface IMessage extends IMessageFromServer { tmsg?: string; blocks?: any; e2e?: E2EType; + content?: { + algorithm: 'rc.v1.aes-sha2'; + ciphertext: string; // Encrypted subset JSON of IMessage + }; tshow?: boolean; comment?: string; subscription?: { id: string }; diff --git a/app/lib/encryption/encryption.ts b/app/lib/encryption/encryption.ts index ba867c5eb..39054d099 100644 --- a/app/lib/encryption/encryption.ts +++ b/app/lib/encryption/encryption.ts @@ -44,8 +44,6 @@ class Encryption { decrypt: Function; encrypt: Function; encryptText: Function; - encryptFile: Function; - decryptFile: Function; encryptUpload: Function; importRoomKey: Function; }; @@ -522,46 +520,6 @@ class Encryption { // Decrypt multiple subscriptions decryptSubscriptions = (subscriptions: ISubscription[]) => Promise.all(subscriptions.map(s => this.decryptSubscription(s))); - - // Encrypt a file - encryptFile = async (rid: string, path: string, iv: ArrayBuffer) => { - try { - // If the client is not ready - if (!this.ready) { - // Wait for ready status - await this.establishing; - } - - const roomE2E = await this.getRoomInstance(rid); - - return roomE2E.encryptFile(path, iv); - } catch (e) { - console.error(e); - } - - // Send a non encrypted message - return null; - }; - - // decrypt a file - decryptFile = async (rid: string, path: string, iv: ArrayBuffer) => { - try { - // If the client is not ready - if (!this.ready) { - // Wait for ready status - await this.establishing; - } - - const roomE2E = await this.getRoomInstance(rid); - - return roomE2E.decryptFile(path, iv); - } catch (e) { - console.error(e); - } - - // Send a non encrypted message - return null; - }; } const encryption = new Encryption(); diff --git a/app/lib/encryption/room.ts b/app/lib/encryption/room.ts index d73fa5607..18080f14e 100644 --- a/app/lib/encryption/room.ts +++ b/app/lib/encryption/room.ts @@ -269,58 +269,6 @@ export default class EncryptionRoom { return message; }; - // Encrypt - encryptFile = async (p: string, iv: ArrayBuffer) => { - console.log('🚀 ~ EncryptionRoom ~ encryptFile= ~ p:', p); - if (!this.ready) { - console.log('🚀 ~ EncryptionRoom ~ encryptFile= ~ this.ready:', this.ready); - return null; - } - - try { - // const path = utf8ToBuffer(p); - const path = p; - console.log('🚀 ~ EncryptionRoom ~ encryptFile= ~ path:', path); - // const vector = await SimpleCrypto.utils.randomBytes(16); - const data = await SimpleCrypto.AES.encryptFile(path, this.roomKey as ArrayBuffer, iv); - console.log('🚀 ~ EncryptionRoom ~ encryptFile= ~ this.roomKey:', bufferToB64URI(this.roomKey)); - console.log('🚀 ~ EncryptionRoom ~ encryptFile= ~ data:', data); - - // return this.keyID + bufferToB64(joinVectorData(vector, data)); - return data; - } catch (e) { - // Do nothing - console.error(e); - } - - return null; - }; - - decryptFile = async (p: string, iv: ArrayBuffer) => { - console.log('🚀 ~ EncryptionRoom ~ decryptFile= ~ p:', p); - if (!this.ready) { - console.log('🚀 ~ EncryptionRoom ~ decryptFile= ~ this.ready:', this.ready); - return null; - } - - try { - // const path = utf8ToBuffer(p); - const path = p; - console.log('🚀 ~ EncryptionRoom ~ decryptFile= ~ path:', path); - // const vector = await SimpleCrypto.utils.randomBytes(16); - const data = await SimpleCrypto.AES.decryptFile(path, this.roomKey as ArrayBuffer, iv); - console.log('🚀 ~ EncryptionRoom ~ decryptFile= ~ data:', data); - - // return this.keyID + bufferToB64(joinVectorData(vector, data)); - return data; - } catch (e) { - // Do nothing - console.error(e); - } - - return null; - }; - // Decrypt text decryptText = async (msg: string | ArrayBuffer) => { if (!msg) { diff --git a/app/lib/encryption/utils.ts b/app/lib/encryption/utils.ts index 06a9a492e..260a402fa 100644 --- a/app/lib/encryption/utils.ts +++ b/app/lib/encryption/utils.ts @@ -1,7 +1,5 @@ import ByteBuffer from 'bytebuffer'; import SimpleCrypto from 'react-native-simple-crypto'; -import EJSON from 'ejson'; -import { atob } from 'js-base64'; import { random } from '../methods/helpers'; import { fromByteArray, toByteArray } from './helpers/base64-js'; @@ -41,7 +39,6 @@ export const bufferToB64URI = (buffer: ArrayBuffer): string => { return base64; }; export const b64URIToBuffer = (base64: string): ArrayBuffer => { - console.log('🚀 ~ b64URIToBuffer ~ base64:', base64); const bufferLength = base64.length * 0.75; const len = base64.length; let i; @@ -96,7 +93,15 @@ export const randomPassword = (): string => `${random(3)}-${random(3)}-${random( export const generateAESCTRKey = () => SimpleCrypto.utils.randomBytes(32); -export const exportAESCTR = key => { +interface IExportedKey { + kty: string; + alg: string; + k: string; + ext: boolean; + key_ops: string[]; +} + +export const exportAESCTR = (key: ArrayBuffer): IExportedKey => { // Web Crypto format of a Secret Key const exportedKey = { // Type of Secret Key @@ -111,181 +116,10 @@ export const exportAESCTR = key => { }; return exportedKey; - // return EJSON.stringify(exportedKey); }; -export const encryptAESCTR = (path: string, key: ArrayBuffer, vector: ArrayBuffer) => +export const encryptAESCTR = (path: string, key: string, vector: string): Promise => SimpleCrypto.AES.encryptFile(path, key, vector); -export const decryptAESCTR = (path: string, key: ArrayBuffer, vector: ArrayBuffer) => +export const decryptAESCTR = (path: string, key: string, vector: string): Promise => SimpleCrypto.AES.decryptFile(path, key, vector); - -// Base 64 encoding - -const BASE_64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; - -const BASE_64_VALS = Object.create(null); - -const getChar = (val: number) => BASE_64_CHARS.charAt(val); -const getVal = (ch: string) => (ch === '=' ? -1 : BASE_64_VALS[ch]); - -for (let i = 0; i < BASE_64_CHARS.length; i++) { - BASE_64_VALS[getChar(i)] = i; -} - -// XXX This is a weird place for this to live, but it's used both by -// this package and 'ejson', and we can't put it in 'ejson' without -// introducing a circular dependency. It should probably be in its own -// package or as a helper in a package that both 'base64' and 'ejson' -// use. -const newBinary = (len: number) => { - if (typeof Uint8Array === 'undefined' || typeof ArrayBuffer === 'undefined') { - const ret = Object.assign( - Array.from({ length: len }, () => 0), - { - $Uint8ArrayPolyfill: true - } - ); - return ret; - } - return new Uint8Array(new ArrayBuffer(len)); -}; - -const encode = (array: ArrayLike | string) => { - if (typeof array === 'string') { - const str = array; - const binary = newBinary(str.length); - for (let i = 0; i < str.length; i++) { - const ch = str.charCodeAt(i); - if (ch > 0xff) { - throw new Error('Not ascii. Base64.encode can only take ascii strings.'); - } - - binary[i] = ch; - } - array = binary; - } - - const answer: string[] = []; - let a: number | null = null; - let b: number | null = null; - let c: number | null = null; - let d: number | null = null; - - for (let i = 0; i < array.length; i++) { - switch (i % 3) { - case 0: - a = (array[i] >> 2) & 0x3f; - b = (array[i] & 0x03) << 4; - break; - case 1: - b = (b ?? 0) | ((array[i] >> 4) & 0xf); - c = (array[i] & 0xf) << 2; - break; - case 2: - c = (c ?? 0) | ((array[i] >> 6) & 0x03); - d = array[i] & 0x3f; - answer.push(getChar(a ?? 0)); - answer.push(getChar(b ?? 0)); - answer.push(getChar(c)); - answer.push(getChar(d)); - a = null; - b = null; - c = null; - d = null; - break; - } - } - - if (a !== null) { - answer.push(getChar(a)); - answer.push(getChar(b ?? 0)); - if (c === null) { - answer.push('='); - } else { - answer.push(getChar(c)); - } - - if (d === null) { - answer.push('='); - } - } - - return answer.join(''); -}; - -const decode = (str: string) => { - let len = Math.floor((str.length * 3) / 4); - if (str.charAt(str.length - 1) === '=') { - len--; - if (str.charAt(str.length - 2) === '=') { - len--; - } - } - - const arr = newBinary(len); - - let one: number | null = null; - let two: number | null = null; - let three: number | null = null; - - let j = 0; - - for (let i = 0; i < str.length; i++) { - const c = str.charAt(i); - const v = getVal(c); - switch (i % 4) { - case 0: - if (v < 0) { - throw new Error('invalid base64 string'); - } - - one = v << 2; - break; - case 1: - if (v < 0) { - throw new Error('invalid base64 string'); - } - - one = (one ?? 0) | (v >> 4); - arr[j++] = one; - two = (v & 0x0f) << 4; - break; - case 2: - if (v >= 0) { - two = (two ?? 0) | (v >> 2); - arr[j++] = two; - three = (v & 0x03) << 6; - } - - break; - case 3: - if (v >= 0) { - arr[j++] = (three ?? 0) | v; - } - - break; - } - } - - return arr; -}; - -export function base64Decode(string) { - string = atob(string); - const { length } = string; - const buf = new ArrayBuffer(length); - const bufView = new Uint8Array(buf); - for (let i = 0; i < string.length; i++) { - bufView[i] = string.charCodeAt(i); - } - return buf; -} - -// console.log( -// atob( -// 'eyJrZXkiOnsiYWxnIjoiQTI1NkNUUiIsImV4dCI6dHJ1ZSwiayI6Ink1MDhHNTNTZHpvVnVibVM1Z01leHpmLXBkeDVDd3hZZFQwNVNBcVdURU0iLCJrZXlfb3BzIjpbImVuY3J5cHQiLCJkZWNyeXB0Il0sImt0eSI6Im9jdCJ9LCJpdiI6IkRBQnY2YnRhRTg1ZEVyTTJMdGJXakE9PSJ9' -// ) -// ); - -export const Base64 = { encode, decode, newBinary }; diff --git a/app/lib/methods/handleMediaDownload.ts b/app/lib/methods/handleMediaDownload.ts index c59e5e36e..1e8784bb0 100644 --- a/app/lib/methods/handleMediaDownload.ts +++ b/app/lib/methods/handleMediaDownload.ts @@ -213,7 +213,6 @@ export function downloadMediaFile({ let downloadKey = ''; try { const path = getFilePath({ type, mimeType, urlToCache: downloadUrl, encrypted: !!encryption }); - console.log('🚀 ~ returnnewPromise ~ path:', path); if (!path) { return reject(); } @@ -221,25 +220,14 @@ export function downloadMediaFile({ downloadQueue[downloadKey] = FileSystem.createDownloadResumable(downloadUrl, path); const result = await downloadQueue[downloadKey].downloadAsync(); - console.log('🚀 ~ returnnewPromise ~ result:', result); + if (!result) { + return reject(); + } - // const decryptedFile = await Encryption.decryptFile(rid, result.uri.substring(7), encryption.key, encryption.iv); - // console.log('🚀 ~ downloadMediaFile ~ decryptedFile:', decryptedFile); - - console.log('🚀 ~ returnnewPromise ~ encryption:', encryption); - // const exportedKeyArrayBuffer = b64URIToBuffer(encryption.key.k); - // const vector = b64URIToBuffer(encryption.iv); - // const vector = b64ToBuffer(encryption.iv); - // const vector = Base64.decode(encryption.iv); - // const vector = Base64.decode(encryption.iv); - // const vector = b64ToBuffer(encryption.iv); - // console.log('🚀 ~ returnnewPromise ~ vector:', vector); - - const decryptedFile = await decryptAESCTR(result.uri.substring(7), encryption.key.k, encryption.iv); - console.log('🚀 ~ handleMediaDownload ~ decryptedFile:', decryptedFile); + const decryptedFile = await decryptAESCTR(result.uri, encryption.key.k, encryption.iv); if (decryptedFile) { - return resolve(`file://${decryptedFile}`); + return resolve(decryptedFile); } return reject(); } catch (e) { diff --git a/app/lib/methods/sendFileMessage.ts b/app/lib/methods/sendFileMessage.ts index b095d9a31..bc741d80a 100644 --- a/app/lib/methods/sendFileMessage.ts +++ b/app/lib/methods/sendFileMessage.ts @@ -139,7 +139,6 @@ export function sendFileMessage( 'X-Auth-Token': token, 'X-User-Id': id }; - console.log('🚀 ~ returnnewPromise ~ RocketChatSettings.customHeaders:', RocketChatSettings.customHeaders); try { const data = formData.map(item => { @@ -153,14 +152,9 @@ export function sendFileMessage( } return item; }); - console.log('🚀 ~ data ~ data:', data); const response = await RNFetchBlob.fetch('POST', uploadUrl, headers, data); - console.log(response); const json = response.json(); - console.log('🚀 ~ returnnewPromise ~ json:', json); - - console.log('🚀 ~ returnnewPromise ~ getContent:', getContent); let content; if (getContent) { content = await getContent(json.file._id, json.file.url); diff --git a/app/views/ShareView/index.tsx b/app/views/ShareView/index.tsx index 5eb188415..fc67ffdda 100644 --- a/app/views/ShareView/index.tsx +++ b/app/views/ShareView/index.tsx @@ -39,15 +39,7 @@ import { sendFileMessage, sendMessage } from '../../lib/methods'; import { hasPermission, isAndroid, canUploadFile, isReadOnly, isBlocked } from '../../lib/methods/helpers'; import { RoomContext } from '../RoomView/context'; import { Encryption } from '../../lib/encryption'; -import { - Base64, - b64URIToBuffer, - bufferToB64, - decryptAESCTR, - encryptAESCTR, - exportAESCTR, - generateAESCTRKey -} from '../../lib/encryption/utils'; +import { bufferToB64, encryptAESCTR, exportAESCTR, generateAESCTRKey } from '../../lib/encryption/utils'; interface IShareViewState { selected: IShareAttachment; @@ -264,36 +256,21 @@ class ShareView extends Component { try { // Send attachment if (attachments.length) { - console.log('🚀 ~ ShareView ~ send= ~ attachments:', attachments); await Promise.all( attachments.map(async ({ filename: name, mime: type, description, size, canUpload }) => { if (!canUpload) { - return Promise.resolve(); // Resolve immediately if upload is not allowed + return Promise.resolve(); } try { - const { path } = attachments[0]; // Consider if you need a specific attachment or iterate over each + const { path } = attachments[0]; const vector = await SimpleCrypto.utils.randomBytes(16); const key = await generateAESCTRKey(); - const exportedKey = await exportAESCTR(key); - // console.log('🚀 ~ ShareView ~ send= ~ exportedKey:', exportedKey, exportedKey.k); - - // const exportedKeyArrayBuffer = b64URIToBuffer(exportedKey.k); - // console.log('BASE64 BASE64 BASE64 key:', exportedKey, exportedKey.k); - // console.log('BASE64 BASE64 BASE64 vector:', bufferToB64(vector)); - // console.log('BASE64 BASE64 BASE64 vector:', bufferToB64(vector)); - const encryptedFile = await encryptAESCTR(path, exportedKey.k, bufferToB64(vector)); - // console.log('🚀 ~ ShareView ~ send= ~ encryptedFile:', encryptedFile); - - // const decryptedFile = await decryptAESCTR(encryptedFile, exportedKeyArrayBuffer, vector); - // console.log('🚀 ~ ShareView ~ send= ~ decryptedFile:', decryptedFile); const getContent = async (_id: string, fileUrl: string) => { - // console.log('🚀 ~ ShareView ~ getContent ~ _id:', _id, fileUrl); const attachments = []; - // console.log('🚀 ~ ShareView ~ getContent ~ attachment.encryption.exportedKey:', vector, exportedKey); const attachment = { title: name, @@ -314,7 +291,6 @@ class ShareView extends Component { const data = EJSON.stringify({ attachments }); - // console.log('🚀 ~ ShareView ~ getContent ~ attachments:', attachments, data); return { algorithm: 'rc.v1.aes-sha2', @@ -343,7 +319,7 @@ class ShareView extends Component { ); } catch (e) { console.error(e); - return Promise.reject(e); // Ensure that errors are propagated + return Promise.reject(e); } }) );