From c99d4b78950760d0f1dcb2c4e3b2f293d782bc3d Mon Sep 17 00:00:00 2001 From: Roland Osborne Date: Mon, 19 Dec 2022 10:53:56 -0800 Subject: [PATCH] switched rsa implementation in mobile app --- app/mobile/ios/Podfile.lock | 8 ++- app/mobile/package.json | 1 - app/mobile/src/access/create/Create.jsx | 2 +- app/mobile/src/context/useCardContext.hook.js | 28 +++++----- .../src/context/useChannelContext.hook.js | 56 +++++++++---------- .../context/useConversationContext.hook.js | 9 ++- .../conversation/useConversation.hook.js | 1 - .../profileBody/useProfileBody.hook.js | 3 +- app/mobile/yarn.lock | 5 -- package.json | 5 -- yarn.lock | 8 --- 11 files changed, 59 insertions(+), 67 deletions(-) delete mode 100644 package.json delete mode 100644 yarn.lock diff --git a/app/mobile/ios/Podfile.lock b/app/mobile/ios/Podfile.lock index d3377e0c..081ecba8 100644 --- a/app/mobile/ios/Podfile.lock +++ b/app/mobile/ios/Podfile.lock @@ -9,6 +9,8 @@ PODS: - ReactCommon - EXConstants (13.2.4): - ExpoModulesCore + - EXErrorRecovery (3.2.0): + - ExpoModulesCore - EXFileSystem (14.1.0): - ExpoModulesCore - EXFont (10.2.0): @@ -474,6 +476,7 @@ DEPENDENCIES: - EXApplication (from `../node_modules/expo-application/ios`) - EXAV (from `../node_modules/expo-av/ios`) - EXConstants (from `../node_modules/expo-constants/ios`) + - EXErrorRecovery (from `../node_modules/expo-error-recovery/ios`) - EXFileSystem (from `../node_modules/expo-file-system/ios`) - EXFont (from `../node_modules/expo-font/ios`) - Expo (from `../node_modules/expo`) @@ -552,6 +555,8 @@ EXTERNAL SOURCES: :path: "../node_modules/expo-av/ios" EXConstants: :path: "../node_modules/expo-constants/ios" + EXErrorRecovery: + :path: "../node_modules/expo-error-recovery/ios" EXFileSystem: :path: "../node_modules/expo-file-system/ios" EXFont: @@ -659,6 +664,7 @@ SPEC CHECKSUMS: EXApplication: e418d737a036e788510f2c4ad6c10a7d54d18586 EXAV: 596506c9bee54ad52f2f3b625cdaeb9d9f2dd6b7 EXConstants: 7c44785d41d8e959d527d23d29444277a4d1ee73 + EXErrorRecovery: 74d71ee59f6814315457b09d68e86aa95cc7d05d EXFileSystem: 927e0a8885aa9c49e50fc38eaba2c2389f2f1019 EXFont: a5d80bd9b3452b2d5abbce2487da89b0150e6487 Expo: fcdb32274e2ca9c7638d3b21b30fb665c6869219 @@ -674,7 +680,7 @@ SPEC CHECKSUMS: FirebaseInstallations: 99d24bac0243cf8b0e96cf5426340d211f0bcc80 FirebaseMessaging: 4487bbff9b9b927ba1dd3ea40d1ceb58e4ee3cb5 fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 - glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b + glog: 3d02b25ca00c2d456734d0bcff864cbc62f6ae1a GoogleDataTransport: 1c8145da7117bd68bbbed00cf304edb6a24de00f GoogleUtilities: 1d20a6ad97ef46f67bbdec158ce00563a671ebb7 nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431 diff --git a/app/mobile/package.json b/app/mobile/package.json index 60676810..759cdd8b 100644 --- a/app/mobile/package.json +++ b/app/mobile/package.json @@ -24,7 +24,6 @@ "expo-keep-awake": "~10.2.0", "expo-splash-screen": "~0.16.2", "expo-status-bar": "~1.4.0", - "jsencrypt": "^3.3.1", "moment": "^2.29.4", "react": "18.0.0", "react-dom": "18.0.0", diff --git a/app/mobile/src/access/create/Create.jsx b/app/mobile/src/access/create/Create.jsx index ed6f4076..89044814 100644 --- a/app/mobile/src/access/create/Create.jsx +++ b/app/mobile/src/access/create/Create.jsx @@ -74,7 +74,7 @@ export function Create() { )} { !state.tokenRequired && state.server === 'databag.coredb.org' && ( - The default public server is to test out the system. Use a private server othersise. + The default public server is to test out the system. Use a private server othersize. )} diff --git a/app/mobile/src/context/useCardContext.hook.js b/app/mobile/src/context/useCardContext.hook.js index 2a0a7afa..236a5356 100644 --- a/app/mobile/src/context/useCardContext.hook.js +++ b/app/mobile/src/context/useCardContext.hook.js @@ -33,8 +33,8 @@ import { removeContactChannelTopic } from 'api/removeContactChannelTopic'; import { getContactChannelNotifications } from 'api/getContactChannelNotifications'; import { setContactChannelNotifications } from 'api/setContactChannelNotifications'; +import { RSA } from 'react-native-rsa-native'; import CryptoJS from 'crypto-js'; -import { JSEncrypt } from 'jsencrypt' export function useCardContext() { const [state, setState] = useState({ @@ -56,19 +56,21 @@ export function useCardContext() { setState((s) => ({ ...s, ...value })) } - const unsealKey = (seals, sealKey) => { - let unsealedKey; - if (seals?.length) { - seals.forEach(seal => { - if (seal.publicKey === sealKey.public) { - let crypto = new JSEncrypt(); - crypto.setPrivateKey(sealKey.private); - unsealedKey = crypto.decrypt(seal.sealedKey); + const unsealKey = async (seals, sealKey) => { + let seal; + if (seals?.length) { + seals.forEach(s => { + if (s.publicKey === sealKey.public) { + seal = s; } }); } - return unsealedKey; - } + if (seal) { + const key = '-----BEGIN RSA PRIVATE KEY-----\n' + sealKey.private + '\n-----END RSA PRIVATE KEY-----' + return await RSA.decrypt(seal.sealedKey, key); + } + return null; + }; const getCardEntry = (cardId) => { const card = cards.current.get(cardId); @@ -633,7 +635,7 @@ export function useCardContext() { const card = cards.current.get(cardId); const channel = card.channels.get(channelId); const { subjectEncrypted, subjectIv, seals } = JSON.parse(channel.detail.data); - const unsealedKey = unsealKey(seals, sealKey); + const unsealedKey = await unsealKey(seals, sealKey); if (unsealedKey) { const iv = CryptoJS.enc.Hex.parse(subjectIv); const key = CryptoJS.enc.Hex.parse(unsealedKey); @@ -660,7 +662,7 @@ export function useCardContext() { const channel = card.channels.get(channelId); const { seals } = JSON.parse(channel.detail.data); const { messageEncrypted, messageIv } = JSON.parse(channel.summary.lastTopic.data); - const unsealedKey = unsealKey(seals, sealKey); + const unsealedKey = await unsealKey(seals, sealKey); if (unsealedKey) { const iv = CryptoJS.enc.Hex.parse(messageIv); const key = CryptoJS.enc.Hex.parse(unsealedKey); diff --git a/app/mobile/src/context/useChannelContext.hook.js b/app/mobile/src/context/useChannelContext.hook.js index b7127921..1e0d3ae1 100644 --- a/app/mobile/src/context/useChannelContext.hook.js +++ b/app/mobile/src/context/useChannelContext.hook.js @@ -18,8 +18,8 @@ import { clearChannelCard } from 'api/clearChannelCard'; import { addFlag } from 'api/addFlag'; import { setChannelNotifications } from 'api/setChannelNotifications'; import { getChannelNotifications } from 'api/getChannelNotifications'; -import { JSEncrypt } from 'jsencrypt' import CryptoJS from "crypto-js"; +import { RSA } from 'react-native-rsa-native'; export function useChannelContext() { const [state, setState] = useState({ @@ -38,18 +38,20 @@ export function useChannelContext() { setState((s) => ({ ...s, ...value })) } - const unsealKey = (seals, sealKey) => { - let unsealedKey; + const unsealKey = async (seals, sealKey) => { + let seal; if (seals?.length) { - seals.forEach(seal => { - if (seal.publicKey === sealKey.public) { - let crypto = new JSEncrypt(); - crypto.setPrivateKey(sealKey.private); - unsealedKey = crypto.decrypt(seal.sealedKey); + seals.forEach(s => { + if (s.publicKey === sealKey.public) { + seal = s; } }); } - return unsealedKey + if (seal) { + const key = '-----BEGIN RSA PRIVATE KEY-----\n' + sealKey.private + '\n-----END RSA PRIVATE KEY-----' + return await RSA.decrypt(seal.sealedKey, key); + } + return null; }; const setChannel = (channelId, channel) => { @@ -313,19 +315,15 @@ export function useChannelContext() { const channel = channels.current.get(channelId); let { seals, subjectEncrypted, subjectIv } = JSON.parse(channel.detail.data); - seals.forEach(seal => { - if (seal.publicKey === sealKey.public) { - let crypto = new JSEncrypt(); - crypto.setPrivateKey(sealKey.private); - const unsealedKey = crypto.decrypt(seal.sealedKey); - const key = CryptoJS.enc.Hex.parse(unsealedKey); - - const iv = CryptoJS.lib.WordArray.random(128 / 8); - const encrypted = CryptoJS.AES.encrypt(JSON.stringify({ subject }), key, { iv: iv }); - subjectEncrypted = encrypted.ciphertext.toString(CryptoJS.enc.Base64) - subjectIv = iv.toString(); - } - }); + const unsealedKey = await unsealKey(seals, sealKey); + if (!unsealedKey) { + throw new Error("cannot reseal subject"); + } + const key = CryptoJS.enc.Hex.parse(unsealedKey); + const iv = CryptoJS.lib.WordArray.random(128 / 8); + const encrypted = CryptoJS.AES.encrypt(JSON.stringify({ subject }), key, { iv: iv }); + subjectEncrypted = encrypted.ciphertext.toString(CryptoJS.enc.Base64) + subjectIv = iv.toString(); const data = { subjectEncrypted, subjectIv, seals }; return await setChannelSubject(server, appToken, channelId, 'sealed', data); }, @@ -348,12 +346,12 @@ export function useChannelContext() { const keyHex = key.toString(); let seals = []; - let crypto = new JSEncrypt(); - keys.forEach(publicKey => { - crypto.setPublicKey(publicKey); - const sealedKey = crypto.encrypt(keyHex); + for (let i = 0; i < keys.length; i++) { + const publicKey = keys[i]; + const key = '-----BEGIN PUBLIC KEY-----\n' + publicKey + '\n-----END PUBLIC KEY-----' + const sealedKey = await RSA.encrypt(keyHex, key); seals.push({ publicKey, sealedKey }); - }); + }; const data = { subjectEncrypted, subjectIv, seals }; return await addChannel(server, appToken, 'sealed', data, cards); @@ -391,7 +389,7 @@ export function useChannelContext() { const { guid } = session.current; const channel = channels.current.get(channelId); const { subjectEncrypted, subjectIv, seals } = JSON.parse(channel.detail.data); - const unsealedKey = unsealKey(seals, sealKey); + const unsealedKey = await unsealKey(seals, sealKey); if (unsealedKey) { const iv = CryptoJS.enc.Hex.parse(subjectIv); const key = CryptoJS.enc.Hex.parse(unsealedKey); @@ -416,7 +414,7 @@ export function useChannelContext() { const channel = channels.current.get(channelId); const { seals } = JSON.parse(channel.detail.data); const { messageEncrypted, messageIv } = JSON.parse(channel.summary.lastTopic.data); - const unsealedKey = unsealKey(seals, sealKey); + const unsealedKey = await unsealKey(seals, sealKey); if (unsealedKey) { const iv = CryptoJS.enc.Hex.parse(messageIv); const key = CryptoJS.enc.Hex.parse(unsealedKey); diff --git a/app/mobile/src/context/useConversationContext.hook.js b/app/mobile/src/context/useConversationContext.hook.js index 7a9c2c0d..fab9283f 100644 --- a/app/mobile/src/context/useConversationContext.hook.js +++ b/app/mobile/src/context/useConversationContext.hook.js @@ -6,7 +6,6 @@ import { ChannelContext } from 'context/ChannelContext'; import { ProfileContext } from 'context/ProfileContext'; import moment from 'moment'; import CryptoJS from 'crypto-js'; -import { JSEncrypt } from 'jsencrypt' export function useConversationContext() { const [state, setState] = useState({ @@ -168,6 +167,14 @@ export function useConversationContext() { return await channel.actions.setSyncRevision(channelId, revision); } + useEffect(() => { + if (conversationId.current) { + const { cardId, channelId } = conversationId.current; + const channelItem = getChannel(cardId, channelId); + setChannel(channelItem); + } + }, [card, channel]); + const sync = async () => { const curView = setView.current; if (!syncing.current) { diff --git a/app/mobile/src/session/conversation/useConversation.hook.js b/app/mobile/src/session/conversation/useConversation.hook.js index 4b10d14e..856b33a5 100644 --- a/app/mobile/src/session/conversation/useConversation.hook.js +++ b/app/mobile/src/session/conversation/useConversation.hook.js @@ -2,7 +2,6 @@ import { useRef, useState, useEffect, useContext } from 'react'; import { ConversationContext } from 'context/ConversationContext'; import { AccountContext } from 'context/AccountContext'; import CryptoJS from 'crypto-js'; -import { JSEncrypt } from 'jsencrypt' import { RSA } from 'react-native-rsa-native'; export function useConversation() { diff --git a/app/mobile/src/session/profile/profileBody/useProfileBody.hook.js b/app/mobile/src/session/profile/profileBody/useProfileBody.hook.js index da9206d9..8a37aa73 100644 --- a/app/mobile/src/session/profile/profileBody/useProfileBody.hook.js +++ b/app/mobile/src/session/profile/profileBody/useProfileBody.hook.js @@ -5,7 +5,6 @@ import { ProfileContext } from 'context/ProfileContext'; import { AccountContext } from 'context/AccountContext'; import { AppContext } from 'context/AppContext'; import config from 'constants/Config'; -import { JSEncrypt } from 'jsencrypt' import CryptoJS from "crypto-js"; import { RSA } from 'react-native-rsa-native'; @@ -122,8 +121,8 @@ export function useProfileBody() { }); // generate rsa key for sealing channel, delay for activity indicator - await new Promise(r => setTimeout(r, 1000)); const keys = await RSA.generateKeys(2048); + console.log("NEW KEYS", keys); // encrypt private key const iv = CryptoJS.lib.WordArray.random(128 / 8); diff --git a/app/mobile/yarn.lock b/app/mobile/yarn.lock index c40d2d24..48689a8a 100644 --- a/app/mobile/yarn.lock +++ b/app/mobile/yarn.lock @@ -4344,11 +4344,6 @@ jscodeshift@^0.13.1: temp "^0.8.4" write-file-atomic "^2.3.0" -jsencrypt@^3.3.1: - version "3.3.1" - resolved "https://registry.npmjs.org/jsencrypt/-/jsencrypt-3.3.1.tgz" - integrity sha512-dVvV54GdFuJgmEKn+oBiaifDMen4p6o6j/lJh0OVMcouME8sST0bJ7bldIgKBQk4za0zyGn0/pm4vOznR25mLw== - jsesc@^2.5.1: version "2.5.2" resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" diff --git a/package.json b/package.json deleted file mode 100644 index abb39cb9..00000000 --- a/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "dependencies": { - "react-native-sqlite-storage": "^6.0.1" - } -} diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index 4b117135..00000000 --- a/yarn.lock +++ /dev/null @@ -1,8 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -react-native-sqlite-storage@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/react-native-sqlite-storage/-/react-native-sqlite-storage-6.0.1.tgz#ce6a6b852f07abbea68658d5363818c8bef45dfb" - integrity sha512-1tDFjrint6X6qSYKf3gDyz+XB+X79jfiL6xTugKHPRtF0WvqMtVgdLuNqZunIXjNEvNtNVEbXaeZ6MsguFu00A==