ILLEST Developers

Encryption, as a bot meets it

ILLEST is end-to-end encrypted. The server stores ciphertext and holds no keys, so it cannot read anything for a bot either. A bot is a member of each conversation the way a person is: with a device, a key of its own, and a place in the conversation's encrypted group. The library does all of it. What follows is what it means for the code you write.

The bot is a device

The token is enough to enrol, not to run. The first run makes the bot's keys and keeps them under ~/.illest/bots/<name>/:

FileWhat it is
device.jsonthe device key, which signs the server's challenge on every sign-in
identity.jsonthe account's identity key, which vouches for the device to everybody in a conversation

Keep that folder with the bot, and back it up the way you would a password. Losing it is losing the device and every group key only it held: the history it had read is gone, and members see the bot's security key change. A second machine running the same token is a second device.

Joining is two steps

  1. The invite link adds the bot to the server. on_guild_join fires.
  2. The clients of people in the server let the bot's device into each channel's encrypted group, usually within seconds while the bot is online. on_group_join(channel) fires for each.

Until a channel has let it in, the bot cannot read or send there. A bot that has never run holds no device, so nothing can let it in at all.

What it can read

  • From when it joined. channel.history(), fetch_message() and channel.pins() return the messages this bot holds, from when it was let into the channel's group. There is nothing older to fetch: the server cannot read it either.
  • While it was stopped. On start it brings every group it holds up to date before handling anything, and hands what was sent meanwhile to on_missed_message, with message.late set, never to on_message.

Who sent it

Every message is signed by the sender's device. message.author_verified is True when the sender's own device vouched for the account; when False, author is only the server's word, so authorise nothing on it.

Python
import illest
from illest.ext import commands

bot = commands.Bot(command_prefix="!", intents=illest.Intents.default())


@bot.command()
async def wipe(ctx: commands.Context):
    if not ctx.author_verified:
        await ctx.reply("I cannot tell it is you. Try again from your own device.")
        return
    await ctx.channel.purge(limit=50)

The library pins each account's key the first time it sees it. If an account later shows another, message.author_key_changed is True and on_key_change(user_id) fires once. Check with the person another way, then call client.accept_key_change(user_id).

What the server does see

The server routes messages, so it knows which account sent something to which conversation, and when, and how large it was. It does not know what was said, which command was used or with what, which button was pressed, or what a form held: those travel sealed inside the conversation.

Ephemeral is a rendering rule

Every ILLEST app shows an ephemeral answer to its one reader only, but the bytes reach every device in the conversation. Inside an encrypted group nothing stronger exists. Forms and autocomplete travel the same way. Put nothing in one that the other members must not be able to read.

What a bot cannot do

A bot cannot join a voice call: calls are encrypted from each person's device, and a bot has no microphone. It sees who is in a voice channel (on_voice_state_update) and can move or disconnect members with the moderate scope.