Dev:UnrealDB

This page describes the "UnrealDB" database design to developers. It is not really meant for end-users (admins).

Header
This describes the header that is present at the beginning of the database file.

raw v0
This is used for backwards compatibility with databases written using the old functions in UnrealIRCd 5.0.0 through 5.0.9 that only support unencrypted operations. This means there is NO header (zero bytes).

plaintext v1
After this 40 bytes the same format is used as the previous read_int32/read_int64/etc functions did from UnrealIRCd 5.0.0-5.0.9.
 * 32 bytes: the string "UnrealIRCd-DB-v1" followed by zeroes (0x00)
 * 8 bytes: creation/update time of the database

So, if you ever need to convert plaintext v1 back to raw v0, then just chop off the first 40 bytes.

crypto v1

 * 2 bytes: algorithm (0x1 at the moment)
 * 2 bytes: key length in bytes (32 at the moment)
 * 2 bytes: time cost for Argon2id, that is: number of rounds
 * 2 bytes: memory cost for Argon2id, in powers of two, eg 15 means 2^15=32MB
 * 2 bytes: parallel cost for Argon2id, that is number of threads
 * 2 bytes: salt length in bytes (16 at the moment)
 * variable size: salt as a string (of size saltlen as indicated earlier)
 * variable size: key as a string (of size keylen as indicated earlier)
 * 24 bytes: XChaCha20 Poly1305 header from libsodium
 * (Now encrypted) the 2 byte string length followed by the string "UnrealIRCd-DB-Crypted-Now", use unrealdb_read_str

Encryption
UnrealDB supports encryption. It uses XChaCha20 provided by libsodium. ChaCha20 is one of the two available ciphers in TLSv1.3 (the other one being AES). The XChaCha20 version uses a large nonce, allowing it to be safely used for writing lots of data.

Key derivation
A cipher such as ChaCha20 requires a key. In UnrealIRCd we use Argon2id as a key derivation function to convert a password to a suitable key. The exact parameters of the Argon2id call are stored in each database file, such as the time/memory/parallel cost and some other parameters. By default UnrealIRCd uses quite strong Argon2id parameters, namely 4 for time, 32M for memory and 2 for parallelism. Hashing therefore takes about 100ms on GHz machines, so this means only about 10 hashes per second can be checked per 2 CPU cores.

In the configuration file you don't directly enter a key in a set:: item. Instead you refer to a secret block. In the secret block the password is stored or it tells how to retrieve the password (eg keyboard input or in future versions an URL).

As mentioned, only 10 hashes can be generated per second per 2 CPU cores, which is rather slow (and simply too slow for channeldb). Therefore, to speed things up, UnrealIRCd will cache the Argon2id result and converge to using the same parameters for the same secret block. This includes using the same salt. The main reason for the salt to exist is to prevent the case where (lots of) machines use the same known parameters/hashes, since that would allow precompution attacks. Reusing a salt on the same machine is no problem as using one per machine makes precompution still not costworthy.