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). - 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.9.0
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.9.0.tar.gz | 81.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| sorrydave-0.9.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 125.9 kB
Release files / sorrydave-0.9.0.tar.gz
| Download URL | sorrydave-0.9.0.tar.gz |
|---|---|
| Size | 81.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d09d3f18cabe078f37480c2de534dd8c0436c16be300b514dbae61233e85dbf9
|
|
BLAKE2b-256 checksum How to use checksums |
20f8f74da61686a2632fcbb2953b809f6f2e00d6804a0647380fd6df47110eb4
|
| 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.9.0-py3-none-any.whl
| Download URL | sorrydave-0.9.0-py3-none-any.whl |
|---|---|
| Size | 44.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6404d3ab53503d3d7b02d363e2c741519326cf0cb2301b4f58b519d73446d700
|
|
BLAKE2b-256 checksum How to use checksums |
11092b34bb4b4ac6327cee288a85fd0bb6a1699463847a9851fc01bdda35cc06
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.5
|