Skip to content

Commit 4c89c56

Browse files
Add support for new enccryption methods (#1803)
* fix: actually raise error on encryption fail * feat: add support for new voice encryption reqs pynacl intentionally doesnt support them, so adding cryptography dep * ci: correct from checks. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 8bc94e7 commit 4c89c56

File tree

3 files changed

+71
-6
lines changed

3 files changed

+71
-6
lines changed

interactions/api/voice/encryption.py

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import struct
2+
import secrets
23

3-
__all__ = ("Encryption",)
4+
__all__ = ("Decryption", "Encryption")
45

56
from abc import ABC, abstractmethod
67

@@ -11,21 +12,33 @@
1112
except ImportError:
1213
nacl_imported = False
1314

15+
try:
16+
from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305, AESGCM
17+
18+
cryptography_imported = True
19+
except ImportError:
20+
cryptography_imported = False
21+
1422

1523
class Crypt(ABC):
1624
SUPPORTED = (
25+
# todo: need deprecating
1726
"xsalsa20_poly1305_lite",
1827
"xsalsa20_poly1305_suffix",
1928
"xsalsa20_poly1305",
29+
"aead_xchacha20_poly1305_rtpsize",
30+
"aead_aes256_gcm_rtpsize",
2031
)
2132

2233
def __init__(self, secret_key) -> None:
23-
if not nacl_imported:
34+
if not nacl_imported or not cryptography_imported:
2435
raise RuntimeError("Please install interactions[voice] to use voice components.")
2536
self.box: secret.SecretBox = secret.SecretBox(bytes(secret_key))
26-
2737
self._xsalsa20_poly1305_lite_nonce: int = 0
2838

39+
self.xchacha20 = ChaCha20Poly1305(bytes(secret_key))
40+
self.aes_gcm = AESGCM(bytes(secret_key))
41+
2942
@abstractmethod
3043
def xsalsa20_poly1305_lite(self, header: bytes, data) -> bytes:
3144
raise NotImplementedError
@@ -38,6 +51,14 @@ def xsalsa20_poly1305_suffix(self, header: bytes, data) -> bytes:
3851
def xsalsa20_poly1305(self, header: bytes, data) -> bytes:
3952
raise NotImplementedError
4053

54+
@abstractmethod
55+
def aead_xchacha20_poly1305_rtpsize(self, header: bytes, data) -> bytes:
56+
raise NotImplementedError
57+
58+
@abstractmethod
59+
def aead_aes256_gcm_rtpsize(self, header: bytes, data) -> bytes:
60+
raise NotImplementedError
61+
4162

4263
class Encryption(Crypt):
4364
def encrypt(self, mode: str, header: bytes, data) -> bytes:
@@ -48,6 +69,10 @@ def encrypt(self, mode: str, header: bytes, data) -> bytes:
4869
return self.xsalsa20_poly1305_suffix(header, data)
4970
case "xsalsa20_poly1305":
5071
return self.xsalsa20_poly1305(header, data)
72+
case "aead_xchacha20_poly1305_rtpsize":
73+
return self.aead_xchacha20_poly1305_rtpsize(header, data)
74+
case "aead_aes256_gcm_rtpsize":
75+
return self.aead_aes256_gcm_rtpsize(header, data)
5176
case _:
5277
raise RuntimeError(f"Unsupported encryption type requested: {mode}")
5378

@@ -71,6 +96,22 @@ def xsalsa20_poly1305(self, header: bytes, data) -> bytes:
7196

7297
return header + self.box.encrypt(bytes(data), bytes(nonce)).ciphertext
7398

99+
def aead_xchacha20_poly1305_rtpsize(self, header: bytes, data) -> bytes:
100+
nonce_suffix = secrets.token_bytes(4)
101+
nonce = bytearray(24)
102+
nonce[:4] = nonce_suffix
103+
ciphertext = self.xchacha20.encrypt(bytes(nonce), bytes(data), header)
104+
105+
return header + ciphertext + nonce_suffix
106+
107+
def aead_aes256_gcm_rtpsize(self, header: bytes, data) -> bytes:
108+
nonce_suffix = secrets.token_bytes(4)
109+
nonce = bytearray(12)
110+
nonce[:4] = nonce_suffix
111+
ciphertext = self.aes_gcm.encrypt(bytes(nonce), bytes(data), header)
112+
113+
return header + ciphertext + nonce_suffix
114+
74115

75116
class Decryption(Crypt):
76117
def decrypt(self, mode: str, header: bytes, data) -> bytes:
@@ -81,6 +122,10 @@ def decrypt(self, mode: str, header: bytes, data) -> bytes:
81122
return self.xsalsa20_poly1305_suffix(header, data)
82123
case "xsalsa20_poly1305":
83124
return self.xsalsa20_poly1305(header, data)
125+
case "aead_xchacha20_poly1305_rtpsize":
126+
return self.aead_xchacha20_poly1305_rtpsize(header, data)
127+
case "aead_aes256_gcm_rtpsize":
128+
return self.aead_aes256_gcm_rtpsize(header, data)
84129
case _:
85130
raise RuntimeError(f"Unsupported decryption type requested: {mode}")
86131

@@ -98,11 +143,25 @@ def xsalsa20_poly1305_lite(self, header: bytes, data) -> bytes:
98143

99144
def xsalsa20_poly1305_suffix(self, header: bytes, data) -> bytes:
100145
nonce = data[-24:]
101-
102146
return self.box.decrypt(bytes(data[:-24]), bytes(nonce))
103147

104148
def xsalsa20_poly1305(self, header: bytes, data) -> bytes:
105149
nonce = bytearray(24)
106150
nonce[:12] = header
107-
108151
return self.box.decrypt(bytes(data), bytes(nonce))
152+
153+
def aead_xchacha20_poly1305_rtpsize(self, header: bytes, data) -> bytes:
154+
nonce_suffix = data[-4:]
155+
ciphertext = data[:-4]
156+
nonce = bytearray(24)
157+
nonce[:4] = nonce_suffix
158+
159+
return self.xchacha20.decrypt(bytes(nonce), bytes(ciphertext), header)
160+
161+
def aead_aes256_gcm_rtpsize(self, header: bytes, data) -> bytes:
162+
nonce_suffix = data[-4:]
163+
ciphertext = data[:-4]
164+
nonce = bytearray(12)
165+
nonce[:4] = nonce_suffix
166+
167+
return self.aes_gcm.decrypt(bytes(nonce), bytes(ciphertext), header)

interactions/api/voice/voice_gateway.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,12 @@ async def dispatch_opcode(self, data, op) -> None:
197197
self.logger.info(f"Voice connection established; using {data['mode']}")
198198
self.selected_mode = data["mode"]
199199
self.secret = data["secret_key"]
200-
self.encryptor = Encryption(self.secret)
200+
try:
201+
self.encryptor = Encryption(self.secret)
202+
self.logger.debug(f"Encryption initialized successfully for mode {data['mode']}")
203+
except Exception as e:
204+
self.logger.error(f"Failed to initialize encryption: {e}", exc_info=True)
205+
raise
201206
self.ready.set()
202207
if self.cond:
203208
with self.cond:

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pre-commit = { version = "*", optional = true }
3636

3737
[tool.poetry.group.voice.dependencies]
3838
PyNaCl = "^1.5.0,<1.6"
39+
cryptography = "46.0.3"
3940

4041
[tool.poetry.group.speedup.dependencies]
4142
aiodns = "*"

0 commit comments

Comments
 (0)