libdave: Discord Audio & Video End-to-End Encryption

repository·main·Indexed 43 days ago

https://github.com/discord/libdave

JS and C++ implementations of Discord's DAVE protocol used to secure media streams in native clients. Includes the @discordapp/libdave package for out-of-band verification of call members and MLS epoch authenticators, as well as C++ libraries for encrypting and decrypting audio and video frames using key ratcheting and MLS (Messaging Layer Security) sessions.

Tokens
9.3K
Snippets
39
Records
46
Agent score
55%

What's inside libdave

  1. Overview of @discordapp/libdave

    main

    The @discordapp/libdave package is a JavaScript implementation of the DAVE protocol. It is used by Discord clients to perform out-of-band verifications of:

    1. DAVE protocol call members
    2. MLS epoch authenticators
  2. Overview of the DAVE protocol implementation

    main

    The libdave repository provides the JS and C++ implementations of Discord's Audio & Video End-to-End Encryption (DAVE) protocol. These libraries are used by Discord's native clients to enable secure audio and video communication.

    For a detailed technical specification of the protocol itself, refer to the DAVE protocol whitepaper.

  3. Use the TypeScript DAVE Session Manager

    main

    The DaveSessionManager class is designed to handle Voice Gateway events related to DAVE (Discord Audio Video Encryption). It manages the lifecycle of DAVE sessions, including event handling and the generation of key ratchets.

    To use it, follow these steps:

    1. Initialization: Instantiate a new DaveSessionManager object for every unique combination of selfUserId and groupId.
    2. Event Handling: When you receive an opcode from the Voice Gateway, call the appropriate method on your DaveSessionManager instance to process the event.
    3. Key Ratchet Updates: When signaled that a new key ratchet is available for a specific user, you must update your associated encryptor and decryptor with the new keys provided by the manager.

    Note: This sample is an implementation guide. You will need to provide the actual networking and media processing logic where indicated by TODO comments in the source code.

  4. Compile libdave C++ as a static or shared library

    main

    Use make to compile the library. It is recommended to run make cclean before starting a new build to ensure a clean state.

    # For a static library
    make cclean
    make
    
    # For a shared library
    make cclean
    make shared
  5. libdave C++ dependencies and testing tools

    main

    The following dependencies and tools are used by libdave:

    Core Dependencies

    • mlspp: Must be configured with -DMLS_CXX_NAMESPACE="mlspp" and -DDISABLE_GREASE=ON.
    • SSL Backends: OpenSSL (1.1 or 3.0) or BoringSSL.

    Testing Frameworks

    • googletest
    • AFLplusplus
  6. Manage Key Ratcheting and Passthrough Mode

    main

    The Encryptor allows controlling the security state and encryption bypass:

    • Key Ratcheting: Use SetKeyRatchet(std::unique_ptr<IKeyRatchet> keyRatchet) to provide a mechanism for rotating encryption keys. Use HasKeyRatchet() to check if a ratchet is currently active.
    • Passthrough Mode: Use SetPassthroughMode(bool passthroughMode) to enable or disable encryption entirely. When enabled, data is passed through without encryption. Use IsPassthroughMode() to check the current state.
    // Enable key ratcheting
    encryptor.SetKeyRatchet(std::move(my_ratchet_ptr));
    
    // Enable passthrough (no encryption)
    encryptor.SetPassthroughMode(true);
  7. Handle Protocol Version changes

    main

    The Encryptor can notify you when the underlying protocol version changes. Use SetProtocolVersionChangedCallback to register a std::function<void()> that will be triggered upon a version change. You can query the current version at any time using GetProtocolVersion().

    encryptor.SetProtocolVersionChangedCallback([]() {
        // Handle protocol version change
    });
    
    ProtocolVersion current = encryptor.GetProtocolVersion();
  8. Retrieve a Key Ratchet for a user

    main

    To perform pairwise operations or manage keys for a specific member of the group, use GetKeyRatchet(userId). This returns a std::unique_ptr<IKeyRatchet> which manages the key evolution for that specific user identity.

    std::unique_ptr<IKeyRatchet> ratchet = session->GetKeyRatchet("target_user_id");
    if (ratchet) {
        // Use the ratchet for pairwise encryption/decryption
    }