Updated on the 23rd of December 2020
This information is aimed at developers and anybody interested in the algorithms used by Kryptor. If you have no programming or cryptography experience, then you will probably find this page confusing.
The following repeats for every file that is encrypted:
Kryptor defaults to a 4096 byte buffer. However, when the file is greater than or equal to 1 MiB in size, a buffer of 128 KiB is used. When a file less than 4096 bytes in size is selected (e.g. a small text file), Kryptor uses the file's size as the buffer size.
The structure of an encrypted file looks like this:
ARGON2 MEMORY SIZE | ARGON2 ITERATIONS | SALT (16 bytes) | ENCRYPTED FILE DATA | *ENCRYPTED ORIGINAL FILE NAME | MAC (64 bytes)
*The original file name is only stored in the file if 'Anonymous Rename' is enabled in the settings.
Libsodium is used as the library for BLAKE2b, Argon2, and XChaCha20.
If 'Memory Encryption' is enabled in the settings, the password bytes, encryption key, and MAC key are encrypted in memory when they do not need to be accessed. However, there are periods of time during the encryption process when these arrays are not accessed but don't get encrypted for performance reasons.
Once an array containing sensitive data no longer needs to be used, Array.Clear() is called to zero out the elements of the array.
Kryptor defaults to a 4096 byte buffer. However, when the file is greater than or equal to 1 MiB in size, a buffer of 128 KiB is used. When a file less than 4096 bytes in size is selected (e.g. a small '.txt' file), Kryptor uses the file's size as the buffer size.
When this setting is enabled, sensitive byte arrays are encrypted in memory using ProtectedMemory (which uses the Data Protection API available on Windows) with the MemoryProtectionScope set to 'SameProcess'. These byte arrays are encrypted in place.
Note: There are periods of time when these arrays don't get encrypted for performance reasons.
When running the CLI version of Kryptor or the GUI version on Linux or macOS using Mono, Kryptor uses libsodium Sealed Boxes (Curve25519, XSalsa20-Poly1305) with a random key pair generated using PublicKeyBox.GenerateKeyPair().
Note: This method of memory encryption is not as secure as ProtectedMemory because the encryption keys are stored by Kryptor.
When enabled, random file/folder names are generated using Path.GetRandomFileName(), which is called twice to create longer random file names. The random extensions are removed using String.Replace(".", string.Empty).
Note: Path.GetRandomFileName() uses RNGCryptoServiceProvider internally.
If a folder is selected for file encryption, all of the subdirectories are anonymously renamed first, then the parent directory is anonymously renamed. For each renamed folder, the original folder name is stored in a '.txt' file within the folder. This file then gets encrypted like other files in the folder.
For each selected file, the original file name is appended to the end of the file after a new line (Environment.NewLine). Then a random name is generated (as outlined above) and used as the name for the encrypted file that's created.
Keyfiles are given a random name in the SaveFileDialog using Path.GetRandomFileName() and use the '.key' extension. Keyfiles are marked as read-only using File.SetAttributes() to prevent modification.
For passwords, a random byte is generated using libsodium and converted to a char. If the char is within any of the selected character sets (lowercase/uppercase/numbers/symbols), then it is added to the password. This process repeats until the specified password length is reached.
For passphrase generation, the EFF's long wordlist (for use with five dice) is used as the word source. However, custom wordlists can be used by either appending to the existing wordlist or replacing the 'wordlist.txt' file in the Kryptor folder.
libsodium is used to generate random line numbers. These lines are then read from the file, and the words are combined to form a passphrase. Each word is separated by a '-' character.
Passphrases require the lowercase and symbols character sets to be selected. If the user selects uppercase, the words are converted to title case using TextInfo.ToTitleCase(). If the user selects numbers, then the length of each word is appended after each word.
Kryptor uses libsodium Sealed Boxes (Curve25519, XSalsa20-Poly1305) for password sharing. Recipient key pairs are randomly generated using PublicKeyBox.GenerateKeyPair(), which generates two 256-bit keys. The recipient can verify the integrity of the message but can't verify the identity of the sender.