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.2
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.2.tar.gz | 87.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| sorrydave-0.10.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 137.0 kB
Release files / sorrydave-0.10.2.tar.gz
| Download URL | sorrydave-0.10.2.tar.gz |
|---|---|
| Size | 87.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d8da49c6248a3ea7c88933eff66208af9f33811552fd4c210a1a0d401659d001
|
|
BLAKE2b-256 checksum How to use checksums |
7ca25cb5a60f5f3a1d4aa4eaba28f415f4b8352681cbe391f1f67467763057b3
|
| 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.2-py3-none-any.whl
| Download URL | sorrydave-0.10.2-py3-none-any.whl |
|---|---|
| Size | 49.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c4de88ea7b376ee77f6bf298e19bb4c4dc4f1b3adcce1af36a457b39447ab28f
|
|
BLAKE2b-256 checksum How to use checksums |
958a3760b4ac8155e75d1d5e1315e57c67a8c80c7cecc86d2ea4d729b5fdab9d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.5
|