From 67e958cab6d43d0746d19993fd1e6996658a8eb2 Mon Sep 17 00:00:00 2001 From: davidliu Date: Tue, 17 Dec 2024 02:38:27 +0900 Subject: [PATCH 1/4] feat: e2ee implementation --- ci/yarn.lock | 6 +- example/index.tsx | 4 +- example/ios/Podfile.lock | 10 +- example/package.json | 2 +- example/src/App.tsx | 2 +- example/src/PreJoinPage.tsx | 84 +++++++++++++-- example/src/RoomPage.tsx | 14 ++- example/yarn.lock | 10 +- package.json | 7 +- src/e2ee/RNE2EEManager.ts | 199 ++++++++++++++++++++++++++++++++++++ src/e2ee/RNKeyProvider.ts | 113 ++++++++++++++++++++ src/hooks.ts | 1 + src/hooks/useE2EEManager.ts | 49 +++++++++ src/index.tsx | 4 + tsconfig.json | 1 + yarn.lock | 62 ++++++----- 16 files changed, 515 insertions(+), 53 deletions(-) create mode 100644 src/e2ee/RNE2EEManager.ts create mode 100644 src/e2ee/RNKeyProvider.ts create mode 100644 src/hooks/useE2EEManager.ts diff --git a/ci/yarn.lock b/ci/yarn.lock index 9cb7e88..165f583 100644 --- a/ci/yarn.lock +++ b/ci/yarn.lock @@ -2159,15 +2159,15 @@ __metadata: linkType: hard "@livekit/react-native-webrtc@npm:^125.0.5": - version: 125.0.5 - resolution: "@livekit/react-native-webrtc@npm:125.0.5" + version: 125.0.6 + resolution: "@livekit/react-native-webrtc@npm:125.0.6" dependencies: base64-js: 1.5.1 debug: 4.3.4 event-target-shim: 6.0.2 peerDependencies: react-native: ">=0.60.0" - checksum: 3c492575156b5d243b03fdb6ed05881c9daaaddad05083f0bfa6d604cc0962f434a46d5fdbd592333caebcdab6d10d8bc3657aa227b6d726c6c853aa49e793be + checksum: 7c715568b4899bae718b39bd9bf1d72a346afdab008f6fd47b903f6bf96eabf9a7457d0de6835e4e76750754c7fc6f4a460fa4176733d8ba189e7cd2dc1f5e36 languageName: node linkType: hard diff --git a/example/index.tsx b/example/index.tsx index 41fc785..231dc30 100644 --- a/example/index.tsx +++ b/example/index.tsx @@ -1,8 +1,8 @@ import { AppRegistry } from 'react-native'; import App from './src/App'; import { name as appName } from './app.json'; -import { registerGlobals } from '@livekit/react-native'; -import { LogLevel, setLogLevel } from 'livekit-client'; +import { registerGlobals, setLogLevel } from '@livekit/react-native'; +import { LogLevel } from 'livekit-client'; import { setupErrorLogHandler } from './src/utils/ErrorLogHandler'; import { setupCallService } from './src/callservice/CallService'; diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index c022de3..0b3b9b8 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -12,7 +12,7 @@ PODS: - React-Core - livekit-react-native-webrtc (125.0.5): - React-Core - - WebRTC-SDK (~> 125.6422.05) + - WebRTC-SDK (~> 125.6422.06) - RCT-Folly (2024.01.01.00): - boost - DoubleConversion @@ -1201,7 +1201,7 @@ PODS: - ReactCommon/turbomodule/core - Yoga - SocketRocket (0.7.0) - - WebRTC-SDK (125.6422.05) + - WebRTC-SDK (125.6422.06) - Yoga (0.0.0) DEPENDENCIES: @@ -1407,7 +1407,7 @@ SPEC CHECKSUMS: glog: fdfdfe5479092de0c4bdbebedd9056951f092c4f hermes-engine: 01d3e052018c2a13937aca1860fbedbccd4a41b7 livekit-react-native: b93bfc9038869dcbd5cee53b419c956c28e44949 - livekit-react-native-webrtc: 081ba1baabf80183f35ac840fc3a787e99b45e45 + livekit-react-native-webrtc: 87b33c90c01d78b2d8016981ea0f20ecceac18fd RCT-Folly: 02617c592a293bd6d418e0a88ff4ee1f88329b47 RCTDeprecation: b03c35057846b685b3ccadc9bfe43e349989cdb2 RCTRequired: 194626909cfa8d39ca6663138c417bc6c431648c @@ -1461,9 +1461,9 @@ SPEC CHECKSUMS: RNCAsyncStorage: 0c357f3156fcb16c8589ede67cc036330b6698ca RNScreens: b32a9ff15bea7fcdbe5dff6477bc503f792b1208 SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d - WebRTC-SDK: 1990a1a595bd0b59c17485ce13ff17f575732c12 + WebRTC-SDK: 79942c006ea64f6fb48d7da8a4786dfc820bc1db Yoga: ae3c32c514802d30f687a04a6a35b348506d411f -PODFILE CHECKSUM: 6fcbd8445e8602c6a7ab17fb1523c62772c821da +PODFILE CHECKSUM: b5aad0c7d12b2ea501eb822f98f00ca01d154bd9 COCOAPODS: 1.13.0 diff --git a/example/package.json b/example/package.json index aefde84..e9e3e80 100644 --- a/example/package.json +++ b/example/package.json @@ -10,7 +10,7 @@ "postinstall": "patch-package" }, "dependencies": { - "@livekit/react-native-webrtc": "^125.0.5", + "@livekit/react-native-webrtc": "^125.0.6", "@react-native-async-storage/async-storage": "^1.17.10", "@react-navigation/native": "^6.0.8", "@react-navigation/native-stack": "^6.5.0", diff --git a/example/src/App.tsx b/example/src/App.tsx index 93dab60..a1e4702 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -23,5 +23,5 @@ export default function App() { export type RootStackParamList = { PreJoinPage: undefined; - RoomPage: { url: string; token: string }; + RoomPage: { url: string; token: string; e2ee: boolean; e2eeKey: string }; }; diff --git a/example/src/PreJoinPage.tsx b/example/src/PreJoinPage.tsx index 443b3ee..52758a5 100644 --- a/example/src/PreJoinPage.tsx +++ b/example/src/PreJoinPage.tsx @@ -2,23 +2,37 @@ import * as React from 'react'; import { useState, useEffect } from 'react'; import type { NativeStackScreenProps } from '@react-navigation/native-stack'; -import { StyleSheet, View, TextInput, Text, Button } from 'react-native'; +import { + StyleSheet, + View, + TextInput, + Text, + Button, + Switch, +} from 'react-native'; import type { RootStackParamList } from './App'; import { useTheme } from '@react-navigation/native'; import AsyncStorage from '@react-native-async-storage/async-storage'; -const DEFAULT_URL = 'wss://www.example.com'; -const DEFAULT_TOKEN = ''; +const DEFAULT_URL = 'ws://192.168.11.3:7880'; +const DEFAULT_TOKEN = + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzU3ODc4OTYsImlzcyI6IkFQSVRMV3JLOHRid3I0NyIsIm5iZiI6MTczMzE5NTg5Niwic3ViIjoicGhvbmUiLCJ2aWRlbyI6eyJyb29tIjoibXlyb29tIiwicm9vbUpvaW4iOnRydWV9fQ.2ucoFK_t1rX8cnUVdx_7nS-TOGv_2Io6uNEw11kPs3M'; +const DEFAULT_E2EE = false; +const DEFAULT_E2EE_KEY = ''; const URL_KEY = 'url'; const TOKEN_KEY = 'token'; +const E2EE_KEY = 'e2eeEnabled'; +const E2EE_SHARED_KEY_KEY = 'e2eeSharedKey'; export const PreJoinPage = ({ navigation, }: NativeStackScreenProps) => { const [url, setUrl] = useState(DEFAULT_URL); const [token, setToken] = useState(DEFAULT_TOKEN); - + const [e2eeEnabled, setE2EE] = useState(DEFAULT_E2EE); + const [e2eeKey, setE2EEKey] = useState(DEFAULT_E2EE_KEY); + const toggleE2EE = () => setE2EE((previousState) => !previousState); useEffect(() => { AsyncStorage.getItem(URL_KEY).then((value) => { if (value) { @@ -31,14 +45,44 @@ export const PreJoinPage = ({ setToken(value); } }); + AsyncStorage.getItem(E2EE_KEY).then((value) => { + if (value) { + setE2EE(value === 'true'); + } + }); + AsyncStorage.getItem(E2EE_SHARED_KEY_KEY).then((value) => { + if (value) { + setE2EEKey(value); + } + }); }, []); const { colors } = useTheme(); - let saveValues = (saveUrl: string, saveToken: string) => { + let e2eeKeyInputTitle = E2EE Key; + let e2eeKeyInput = ( + + ); + let saveValues = ( + saveUrl: string, + saveToken: string, + saveE2EE: boolean, + saveE2EEKey: string + ) => { AsyncStorage.setItem(URL_KEY, saveUrl); AsyncStorage.setItem(TOKEN_KEY, saveToken); + AsyncStorage.setItem(E2EE_KEY, saveE2EE.toString()); + AsyncStorage.setItem(E2EE_SHARED_KEY_KEY, saveE2EEKey); }; + return ( URL @@ -63,10 +107,25 @@ export const PreJoinPage = ({ value={token} /> + Enable E2EE + + + + + {e2eeEnabled ? e2eeKeyInputTitle : null} + {e2eeEnabled ? e2eeKeyInput : null} + + +