Skip to content

nacl.exceptions.CryptoError: Decryption failed. Ciphertext failed verification #2033

@TheoBoyer

Description

@TheoBoyer

Summary

I'm using a bot based on pycord during long conversations on discord. Sometimes (it occur very rarely tho) a nacl.exceptions.CryptoError is raised, and i have no way to handle it other than monkey patch

Reproduction Steps

Well it occur so rarely, it's hard to reproduce...
It happens often after the bot is being listening for a long time.

Minimal Reproducible Code

import discord
from discord.ext import commands
...

class STTSink(discord.sinks.WaveSink):
    def __init__(self, discussion: Discussion, get_name: Callable, **kwargs):
        self.discussion = discussion
        self.get_name = get_name
        super().__init__(**kwargs)

    def write(self, data, user):
        user = self.get_name(user)
        self.discussion.audio_sample(user, data)

class STTManager:
    def __init__(self, vc: discord.VoiceClient, guild: discord.Guild):
        self.guild = guild
        self.vc = vc
        self.transcription = Discussion()
        self.sink = STTSink(discussion=self.transcription, get_name=self.get_name)

    async def on_finish(self, sink: discord.sinks, channel: discord.TextChannel, *args):  # Our voice client already passes these in.
        if sink.vc.recording:  # If we're not recording, we're stopping the decoder.
            await sink.vc.stop_recording()
        await sink.vc.disconnect()  # Disconnect from the voice channel.
        print("Disconnected from voice channel.")
        #await channel.send(f"Merci pour l'invitation !")

    def start(self):
        self.vc.start_recording(
            self.sink,
            self.on_finish,
            self.vc.channel
        )
        self.transcription.start()

    def stop(self):
        print("Stopping recording...")
        if self.vc.recording:
            self.vc.stop_recording()
        else:
            self.vc.decoder.stop()
        print("Stopped recording.")
        self.transcription.stop()

TOKEN = open("token.txt", "r").read().strip()
intents = discord.Intents.default()
# Privileged message content intent
intents.message_content = True
# Guild members
intents.members = True

print("loading bot...")
bot = commands.Bot(intents=intents, command_prefix="/")
connections = {}

@bot.event
async def on_ready():
    print("Bot is ready")

@bot.command()
async def start(ctx: discord.ext.commands.Context):
    voice = ctx.author.voice
    # Check if user is in a voice channel
    if not voice:
        # Reply to the user with a message
        return await ctx.reply("Tu n'es pas dans un channel vocal !")
    
    vc = await voice.channel.connect()
    manager = STTManager(vc, ctx.guild)
    connections.update({ctx.guild.id: manager})
    try:
        manager.start()
    except TranscriptionNotAvailableError:
        manager.stop()
        await vc.disconnect()
        return await ctx.reply("Transcription not available")
    await ctx.reply(f"Starting transcription")

@bot.command()
async def stop(ctx):
    if ctx.guild.id in connections:  # Check if the guild is in the cache.
        manager = connections[ctx.guild.id]
        manager.stop()
        del connections[ctx.guild.id]  # Remove the guild from the cache.
    else:
        await ctx.reply("Je ne suis pas en train d'enregistrer ici")  # Respond with this if we aren't recording.

if __name__ == "__main__":
    bot.run(TOKEN)

Expected Results

That it doesn't crash

Actual Results

Exception in thread Thread-4:
Traceback (most recent call last):
File "/usr/lib/python3.9/threading.py", line 954, in _bootstrap_inner
self.run()
File "/usr/lib/python3.9/threading.py", line 892, in run
self._target(*self._args, **self._kwargs)
File "/home/ubuntu/.local/lib/python3.9/site-packages/discord/voice_client.py", line 814, in recv_audio
self.unpack_audio(data)
File "/home/ubuntu/.local/lib/python3.9/site-packages/discord/voice_client.py", line 696, in unpack_audio
data = RawData(data, self)
File "/home/ubuntu/.local/lib/python3.9/site-packages/discord/sinks/core.py", line 112, in init
self.decrypted_data = getattr(self.client, f"decrypt{self.client.mode}")(
File "/home/ubuntu/.local/lib/python3.9/site-packages/discord/voice_client.py", line 611, in _decrypt_xsalsa20_poly1305_lite
return self.strip_header_ext(box.decrypt(bytes(data), bytes(nonce)))
File "/home/ubuntu/.local/lib/python3.9/site-packages/nacl/secret.py", line 149, in decrypt
plaintext = nacl.bindings.crypto_secretbox_open(
File "/home/ubuntu/.local/lib/python3.9/site-packages/nacl/bindings/crypto_secretbox.py", line 79, in crypto_secretbox_open
ensure(
File "/home/ubuntu/.local/lib/python3.9/site-packages/nacl/exceptions.py", line 88, in ensure
raise raising(*args)
nacl.exceptions.CryptoError: Decryption failed. Ciphertext failed verification

Intents

intents = discord.Intents.default() # Privileged message content intent intents.message_content = True # Guild members intents.members = True

System Information

  • Python v3.9.5-final
  • py-cord v2.4.1-final
  • aiohttp v3.8.4
  • system info: Linux 5.11.0-37-generic # 41-Ubuntu SMP

Checklist

  • I have searched the open issues for duplicates.
  • I have shown the entire traceback, if possible.
  • I have removed my token from display, if visible.

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    on holdunconfirmed bugA bug report that needs triagingvoiceRelated to the voice chat feature

    Type

    No fields configured for Bug.

    Projects

    Status
    In Progress

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions