sorrydave
Production-quality Python library for the DAVE (Discord Audio/Video End-to-End Encryption) protocol. It implements the protocol as a pure data-transformation and state-management layer on top of rfc9420 (PyMLS), with no I/O or networking: you pass in bytes (Voice Gateway opcodes, encoded media frames) and get back bytes (opcode payloads, encrypted/decrypted frames).
Features
- MLS integration: Key packages, external sender handling, proposals, commit/welcome (opcodes 25–30), exporter-based sender keys
- Sender key ratchet: Per-sender, per-epoch keys via MLS-Exporter + HKDF; cache for out-of-order decryption
- Frame transform: Codec-aware encrypt/decrypt (OPUS, VP9, VP8, H264, H265, AV1), ULEB128, truncated AES128-GCM, DAVE footer (
0xFAFA) - Identity: Pairwise fingerprint (scrypt) and displayable codes (45-digit / 30-digit)
Install
pip install -e .
Requires Python 3.9+, rfc9420, cryptography, and pycryptodome.
Minimal lifecycle
- Create a session:
DaveSession(local_user_id=123456789, channel_id=voice_channel_id). The MLS group ID is the channel snowflake as 8 big-endian bytes; Discord will silently drop commits that use any other group ID. - On select_protocol_ack (or prepare_epoch with
epoch=1), callsession.prepare_epoch(1)and send the returned bytes as opcode 26 (Key Package). - On opcode 25 (External Sender Package), call
session.handle_external_sender_package(package_bytes). - On opcode 27 (Proposals), call
session.handle_proposals(proposal_bytes); if it returns bytes, send them as opcode 28. - On opcode 29 (Announce Commit), call
session.handle_commit(transition_id, commit_bytes). - On opcode 30 (Welcome), call
session.handle_welcome(transition_id, welcome_bytes). - On opcode 22 (Execute Transition), parse with
parse_execute_transition(payload)to gettransition_id, then callsession.execute_transition(transition_id). - Use
session.get_encryptor().encrypt(frame, codec="OPUS")andsession.get_decryptor(sender_id).decrypt(protocol_frame)for media.
Error recovery: On InvalidCommitError, send build_invalid_commit_welcome(transition_id) as opcode 31 to the voice gateway, then call session.prepare_epoch(1) and send the returned key package as opcode 26.
API overview
DaveSession:handle_external_sender_package,prepare_epoch,handle_proposals,handle_commit,handle_welcome,execute_transition,leave_group,get_encryptor,get_decryptorFrameEncryptor.encrypt(encoded_frame, codec)/FrameDecryptor.decrypt(protocol_frame)generate_fingerprint(local_id, local_pub, remote_id, remote_pub)→ 45-digit stringdisplayable_code(data, total_digits, group_size)for epoch authenticator (e.g. 30 digits, group 5)
Scope
- In scope: MLS state, ratchet, OPUS/VP9/VP8/H264/H265/AV1 codec handling, frame encrypt/decrypt, identity fingerprint, opcode 22 parse and opcode 31 build for transition and error recovery.
- Out of scope: Voice Gateway WebSocket I/O, SFU silence packets, WebRTC depacketizer patches.
License
MIT.
Release files for sorrydave 0.10.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| sorrydave-0.10.3.tar.gz | 92.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| sorrydave-0.10.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 141.9 kB
Release files / sorrydave-0.10.3.tar.gz
| Download URL | sorrydave-0.10.3.tar.gz |
|---|---|
| Size | 92.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
95301f83c6067c79b884aeb5ca60785bf8f3f0007b5e15c0fd1f2fd681b95cc6
|
|
BLAKE2b-256 checksum How to use checksums |
1d3cddd11d11d59af77ac0dcb404f4ab8be9c27b2991e346c0d0a8f17f89fa16
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.5
|
Release files / sorrydave-0.10.3-py3-none-any.whl
| Download URL | sorrydave-0.10.3-py3-none-any.whl |
|---|---|
| Size | 49.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7e4cc41f3b702de5c97582cfe96cedbba79b308f90c9c1a273a93f5e22209db4
|
|
BLAKE2b-256 checksum How to use checksums |
1c4f5f752ccc9c45d966a1eeff9784765a9795286e4dd634ef08d1b8249cd1eb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.5
|