-
Notifications
You must be signed in to change notification settings - Fork 132
feature(e2ee): add data channel encryption #708
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 55 commits
Commits
Show all changes
57 commits
Select commit
Hold shift + click to select a range
8fbd62f
chore: Upgrade libwebrtc to m137.
cloudwebrtc ffd5ba9
fix compile issue for linux.
cloudwebrtc 1815e23
fix.
cloudwebrtc ed6063d
Add g++ for aarch64 to Ubuntu dependencies
cloudwebrtc 687edc5
fix build for linux arm64.
cloudwebrtc f12118e
Remove goma usage and switch to autoninja
cloudwebrtc d6c8d68
fix android build.
cloudwebrtc 770f172
fix build on linux arm64 for gcc.
cloudwebrtc 996a202
Update Windows OS version in workflow configuration
cloudwebrtc 2b90351
Add GCC 14 installation steps for Ubuntu
cloudwebrtc 79872ad
Update webrtc-builds.yml
cloudwebrtc b698d1a
Change Windows OS to latest and add SDK installation
cloudwebrtc 03921f3
Update webrtc-builds.yml
cloudwebrtc 3d304de
Update webrtc-builds.yml
cloudwebrtc 016bdef
Update webrtc-builds.yml
cloudwebrtc 5edf00e
Update webrtc-builds.yml
cloudwebrtc 48f6587
Update build_linux.sh
cloudwebrtc 10848d6
Update webrtc-builds.yml
cloudwebrtc 756d71a
Update webrtc-builds.yml
cloudwebrtc 2e92f57
Update build_windows.cmd
cloudwebrtc 41531ed
cargo fmt.
cloudwebrtc 8ee57fa
Merge branch 'main' into lukas/dc-e2ee
lukasIO c7695c4
Update build_windows.cmd
cloudwebrtc 2f17c07
Merge branch 'duan/upgrade-libwebrtc-to-m137' into lukas/dc-e2ee
lukasIO 9069b80
Add new encryption room options field and forward to e2ee_manager
lukasIO d29e7f8
libwebrtc ffi
lukasIO 4249366
Merge branch 'main' into lukas/dc-e2ee
lukasIO ee519e4
fix ffi
lukasIO 3c00272
add data packet cryptor to webrtc crate
lukasIO bf20551
add data frame cryptor handling on rtc session
lukasIO 34284cb
data packet type encryption handling
lukasIO 8800bf7
cleanup
lukasIO 9407cb6
ffi encryption option
lukasIO dcea938
add way to retrieve latest key index
lukasIO a09b685
fix key provider last index
lukasIO ad2f7af
Merge branch 'main' into lukas/dc-e2ee
lukasIO 2c2c533
Allow passing test room options
ladvoc e4fdfa6
add dc e2ee test
lukasIO ae48346
use shared key
lukasIO 7ee92bf
Implement encryption test receiver side
ladvoc 1b5a14e
rename test
lukasIO 08e5ff5
Add encrypted text stream example
lukasIO e9e46a4
revert merge artifacts
lukasIO b875864
whitespace
lukasIO 802e24d
whitespace
lukasIO ce09de0
format
lukasIO ef627dc
cleanup
lukasIO d082698
address comments
lukasIO 7a93560
simplify conversion and recursive data handling
lukasIO 22f9d42
cleanup
lukasIO 4f29df1
more explicit conversion
lukasIO a6e9236
Update test case
lukasIO 3b382bf
wip expose encryption_type
lukasIO fbdfe81
track participant's encryption status based on publications and incom…
lukasIO 451eca9
use is_encrypted getter on participants
lukasIO 54fb7c9
update deprecation notice
lukasIO a7bc6e4
Merge branch 'main' into lukas/dc-e2ee
lukasIO File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| [package] | ||
| name = "encrypted_text_stream" | ||
| version = "0.1.0" | ||
| edition = "2021" | ||
|
|
||
| [dependencies] | ||
| tokio = { version = "1", features = ["full"] } | ||
| futures-util = { version = "0.3", default-features = false, features = ["sink"] } | ||
| livekit = { path = "../../livekit", features = ["native-tls"] } | ||
| livekit-api = { path = "../../livekit-api" } | ||
| log = "0.4.26" | ||
| env_logger = "0.11.7" | ||
|
|
||
| [workspace] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,172 @@ | ||
| use futures_util::TryStreamExt; | ||
| use livekit::{ | ||
| e2ee::{ | ||
| key_provider::{KeyProvider, KeyProviderOptions}, | ||
| E2eeOptions, EncryptionType, | ||
| }, | ||
| prelude::*, | ||
| SimulateScenario, StreamReader, StreamTextOptions, TextStreamReader, | ||
| }; | ||
| use livekit_api::access_token; | ||
| use std::{env, error::Error, io::Write}; | ||
| use tokio::{ | ||
| io::{self, AsyncBufReadExt, BufReader}, | ||
| sync::mpsc::UnboundedReceiver, | ||
| }; | ||
|
|
||
| #[tokio::main] | ||
| async fn main() -> Result<(), Box<dyn Error>> { | ||
| env_logger::init(); | ||
|
|
||
| let url = env::var("LIVEKIT_URL").unwrap_or_else(|_| "ws://localhost:7880".to_string()); | ||
| let api_key = env::var("LIVEKIT_API_KEY").unwrap_or_else(|_| "devkey".to_string()); | ||
| let api_secret = env::var("LIVEKIT_API_SECRET").unwrap_or_else(|_| "secret".to_string()); | ||
| let room_name = env::var("LIVEKIT_ROOM").unwrap_or_else(|_| "dev".to_string()); | ||
| let identity = env::var("LIVEKIT_IDENTITY").unwrap_or_else(|_| "rust-participant".to_string()); | ||
|
|
||
| // Prompt for encryption password | ||
| print!("Enter encryption password: "); | ||
| std::io::stdout().flush()?; | ||
| let mut password = String::new(); | ||
| std::io::stdin().read_line(&mut password)?; | ||
| let password = password.trim().to_string(); | ||
|
|
||
| // Create access token | ||
| let token = access_token::AccessToken::with_api_key(&api_key, &api_secret) | ||
| .with_identity(&identity) | ||
| .with_name(&format!("{} (Encrypted)", identity)) | ||
| .with_grants(access_token::VideoGrants { | ||
| room_join: true, | ||
| room: room_name.clone(), | ||
| ..Default::default() | ||
| }) | ||
| .to_jwt()?; | ||
|
|
||
| // Set up E2EE key provider | ||
| let key_provider = | ||
| KeyProvider::with_shared_key(KeyProviderOptions::default(), password.as_bytes().to_vec()); | ||
|
|
||
| // Configure room options with encryption | ||
| let mut room_options = RoomOptions::default(); | ||
| room_options.encryption = | ||
| Some(E2eeOptions { key_provider, encryption_type: livekit::e2ee::EncryptionType::Gcm }); | ||
|
|
||
| // Connect to room | ||
| let (room, rx) = Room::connect(&url, &token, room_options).await?; | ||
| println!("Connected to encrypted room: {} - {}", room.name(), room.sid().await); | ||
|
|
||
| // Enable E2EE | ||
| room.e2ee_manager().set_enabled(true); | ||
| println!("End-to-end encryption enabled!"); | ||
|
|
||
| // Run the interactive chat | ||
| run_interactive_chat(room, rx).await | ||
| } | ||
|
|
||
| async fn run_interactive_chat( | ||
| room: Room, | ||
| mut rx: UnboundedReceiver<RoomEvent>, | ||
| ) -> Result<(), Box<dyn Error>> { | ||
| println!("\n=== Encrypted Text Chat ==="); | ||
| println!("Type messages to send (press Enter). Type 'quit' to exit."); | ||
| println!("Incoming messages will be displayed below:\n"); | ||
|
|
||
| let stdin = io::stdin(); | ||
| let mut stdin_reader = BufReader::new(stdin); | ||
|
|
||
| loop { | ||
| tokio::select! { | ||
| // Handle user input | ||
| input_result = read_user_input(&mut stdin_reader) => { | ||
| match input_result { | ||
| Ok(Some(input)) => { | ||
| if input == "quit" { | ||
| println!("Goodbye!"); | ||
| break; | ||
| } | ||
|
|
||
| // Send the message | ||
| let options = StreamTextOptions { | ||
| topic: "lk.chat".to_string(), | ||
| ..Default::default() | ||
| }; | ||
|
|
||
| match room.local_participant().send_text(&input, options).await { | ||
| Ok(_) => { | ||
| println!("✓ Sent (encrypted): {}", input); | ||
| } | ||
| Err(e) => { | ||
| println!("✗ Failed to send: {}", e); | ||
| } | ||
| } | ||
| } | ||
| Ok(None) => { | ||
| // Empty input, continue | ||
| continue; | ||
| } | ||
| Err(e) => { | ||
| eprintln!("Error reading input: {}", e); | ||
| break; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Handle incoming room events | ||
| event = rx.recv() => { | ||
| match event { | ||
| Some(RoomEvent::TextStreamOpened { reader, topic, participant_identity }) => { | ||
| if topic == "lk.chat" { | ||
| if let Some(mut reader) = reader.take() { | ||
| match reader.read_all().await { | ||
| Ok(message) => { | ||
| println!("📨 {} (decrypted): {}", participant_identity, message); | ||
| } | ||
| Err(e) => { | ||
| println!("✗ Failed to read message from {}: {}", participant_identity, e); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| Some(RoomEvent::ParticipantConnected( participant )) => { | ||
| println!("👋 {} joined the room", participant.identity()); | ||
| } | ||
| Some(RoomEvent::ParticipantDisconnected ( participant )) => { | ||
| println!("👋 {} left the room", participant.identity()); | ||
| } | ||
| Some(RoomEvent::Disconnected { reason }) => { | ||
| println!("Disconnected from room: {:?}", reason); | ||
| break; | ||
| } | ||
| Some(_) => { | ||
| // Ignore other events | ||
| } | ||
| None => { | ||
| println!("Room event stream ended"); | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| Ok(()) | ||
| } | ||
|
|
||
| async fn read_user_input( | ||
| stdin_reader: &mut BufReader<io::Stdin>, | ||
| ) -> Result<Option<String>, Box<dyn Error>> { | ||
| let mut input = String::new(); | ||
| let bytes_read = stdin_reader.read_line(&mut input).await?; | ||
|
|
||
| if bytes_read == 0 { | ||
| return Ok(None); // EOF | ||
| } | ||
|
|
||
| let input = input.trim().to_string(); | ||
| if input.is_empty() { | ||
| return Ok(None); | ||
| } | ||
|
|
||
| Ok(Some(input)) | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice example!