Add support for AEAD XChaCha20 Poly1305 encryption mode

This commit is contained in:
Mysty 2024-10-10 07:33:37 +10:00 committed by GitHub
parent 91f300a28a
commit ec9fd57254
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 28 additions and 4 deletions

View File

@ -29,7 +29,12 @@ from .snowflake import Snowflake
from .member import MemberWithUser
SupportedModes = Literal['xsalsa20_poly1305_lite', 'xsalsa20_poly1305_suffix', 'xsalsa20_poly1305']
SupportedModes = Literal[
'aead_xchacha20_poly1305_rtpsize',
'xsalsa20_poly1305_lite',
'xsalsa20_poly1305_suffix',
'xsalsa20_poly1305',
]
class _VoiceState(TypedDict):

View File

@ -230,12 +230,13 @@ class VoiceClient(VoiceProtocol):
self.timestamp: int = 0
self._player: Optional[AudioPlayer] = None
self.encoder: Encoder = MISSING
self._lite_nonce: int = 0
self._incr_nonce: int = 0
self._connection: VoiceConnectionState = self.create_connection_state()
warn_nacl: bool = not has_nacl
supported_modes: Tuple[SupportedModes, ...] = (
'aead_xchacha20_poly1305_rtpsize',
'xsalsa20_poly1305_lite',
'xsalsa20_poly1305_suffix',
'xsalsa20_poly1305',
@ -380,7 +381,21 @@ class VoiceClient(VoiceProtocol):
encrypt_packet = getattr(self, '_encrypt_' + self.mode)
return encrypt_packet(header, data)
def _encrypt_aead_xchacha20_poly1305_rtpsize(self, header: bytes, data) -> bytes:
# Esentially the same as _lite
# Uses an incrementing 32-bit integer which is appended to the payload
# The only other difference is we require AEAD with Additional Authenticated Data (the header)
box = nacl.secret.Aead(bytes(self.secret_key))
nonce = bytearray(24)
nonce[:4] = struct.pack('>I', self._incr_nonce)
self.checked_add('_incr_nonce', 1, 4294967295)
return header + box.encrypt(bytes(data), bytes(header), bytes(nonce)).ciphertext + nonce[:4]
def _encrypt_xsalsa20_poly1305(self, header: bytes, data) -> bytes:
# Deprecated. Removal: 18th Nov 2024. See:
# https://discord.com/developers/docs/topics/voice-connections#transport-encryption-modes
box = nacl.secret.SecretBox(bytes(self.secret_key))
nonce = bytearray(24)
nonce[:12] = header
@ -388,17 +403,21 @@ class VoiceClient(VoiceProtocol):
return header + box.encrypt(bytes(data), bytes(nonce)).ciphertext
def _encrypt_xsalsa20_poly1305_suffix(self, header: bytes, data) -> bytes:
# Deprecated. Removal: 18th Nov 2024. See:
# https://discord.com/developers/docs/topics/voice-connections#transport-encryption-modes
box = nacl.secret.SecretBox(bytes(self.secret_key))
nonce = nacl.utils.random(nacl.secret.SecretBox.NONCE_SIZE)
return header + box.encrypt(bytes(data), nonce).ciphertext + nonce
def _encrypt_xsalsa20_poly1305_lite(self, header: bytes, data) -> bytes:
# Deprecated. Removal: 18th Nov 2024. See:
# https://discord.com/developers/docs/topics/voice-connections#transport-encryption-modes
box = nacl.secret.SecretBox(bytes(self.secret_key))
nonce = bytearray(24)
nonce[:4] = struct.pack('>I', self._lite_nonce)
self.checked_add('_lite_nonce', 1, 4294967295)
nonce[:4] = struct.pack('>I', self._incr_nonce)
self.checked_add('_incr_nonce', 1, 4294967295)
return header + box.encrypt(bytes(data), bytes(nonce)).ciphertext + nonce[:4]