Enigma EFS is a WPF MVVM application written in C# that simulates an Encrypted File System. The motivation behind this project was a better understanding of cryptography, different security protocols and encryption algorithms.
- Enigma EFS
NIST | National Institute of Standards and Technology |
SHA | Secure Hash Algorithm |
KDF | Key Derivation Function |
PBKDF2 | Password-Based KDF 2 |
MAC | Message Authentication Code |
HMAC | Keyed-hash Message Authentication Code |
PRNG | Pseudorandom Number Generator |
CSPRNG | Cryptographically Secure PRNG |
ECB | Electronic Codebook |
CBC | Cipher Block Chaining |
CFB | Cipher Feedback |
OFB | Output Feedback |
IV | Initialization Vector |
PKI | Public Key Infrastructure |
PKIX | Public Key Infrastructure X.509 |
FS | File System |
EFS | Encrypted FS |
2FA | Two-factor Authentication |
MFA | Multi-factor authentication |
RSA | Rivest-Shamir-Adleman algorithm |
AES | Advanced Encryption Standard |
3DES | Triple Data Encryption Standard |
While learning about the history of cryptography and cryptanalysis, I've learned more about the Enigma machine and Alan Turing. Naturally, I choose to name this project Enigma and encrypted files have an extension .at
.
To use the application, a user first needs to register. The user needs to provide a unique Username, Password and his X.509 Public Certificate. The user's Username, hashed Password value and his public RSA key extracted from the provided certificate will be stored in Enigma's database.
When registering, the user has an option to have his password created for him. The passwords are generated by CSPRNG and are guaranteed to have high entropy. The user can also choose to use a random passphrase generated by Enigma based on Diceware.
NOTE:
No two users can have the same certificate.
To access Enigmas EFS a user needs to log in first. Login process is realized through 2FA. At first, user only needs to provide his certificate (something only the user has). If the entered certificate exists in the Enigma's database, the user will be prompted to provide his Username and Password (something only the user knows). If the entered password matches the hash value stored for the current user in the database, the user's certificate will be subjected to different tests. When the given certificate matches the public key stored in the database, it is subjected to further verifications. At the end, if the login attempt is successful, the user is granted access to EFS.
Every user has a total of three opportunities to enter his password. After three failed attempts, a "nuclear switch" is turned on and user's data is deleted. The emphasis is placed on security of data above anything else. User is prepared to lose his data forever if that means that the attacker won't get his hands on files.
This functionality is implemented to add more security to user's files. In addition to deleting user files, user's account is locked, preventing him to log in to Enigmas EFS. Only an admin can unlock a user account. Unlocking process is followed with a mandatory user password change.
If a user wants to access his files and use other Enigma EFS options, he needs to import his private RSA key first. If the key's password is correct, the user is granted access to EFS. With successful key import, the program's MFA is completed successfully.
User can add files from FS to Enigma EFS by selecting a path to the original file, encryption and hashing algorithm. Files need to be added one at the time because batch import isn't supported. When adding a new file, the user can choose to either delete or keep the original file.
User can add a new folder to EFS by entering the folder's name. Folder is added at the current path.
User can export any file from his EFS to a selected location on FS.
User can add simple .txt
files to Enigma EFS by using a built-in application text editor.
Users can simply delete their files without any restrictions.
Every user can share their file with other users. For no other reason than simply wanting to put a limit, a user can share his files with up to three other users. When sharing a file with another user, the file's Key is encrypted using a shared user's public RSA key, after which it's stored inside the file's Security Descriptor header.
Unsharing a file is even simpler than sharing. When unsharing, the file is first parsed, after which the shared user's encrypted Key is simply deleted. The new, revised file, then overwrites the old file.
User can simply update an already existing encrypted file with a new file. The user can use a modified version of the old file or an entirely new file. However, the file's type must remain the same when updating an encrypted file. Once the data containing the actual file is updated, the file's read and altered time as well as the file signature is updated. File update also includes a change of the file's IV while the Key remains the same.
NOTE:
Filename will be changed since the file's IV is also changed.
User can update .txt
files stored on Enigma EFS by using the built-in application text editor. This update requires the file to be decrypted first before allowing the user to change context of the .txt
file.
User can view encrypted files that are stored on Enigma EFS. The file is first decrypted and stored on FS in temp directory. Method used for file reading checks for the existence of environment variables in the following order and uses the first path found:
- The path specified by the
TMP
environment variable. - The path specified by the
TEMP
environment variable. - The path specified by the
USERPROFILE
environment variable. - The Windows directory.
After writing a new temp file named "Enigma-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.extension (e.q. Enigma-382c74c3-721d-4f34-80e5-57657b6cbc27.pdf for a .pdf
file), the file is then opened using a default application on the system for the chosen file type.
NOTE:
- Every temporary file is deleted once the Enigma application is closed or if user logs out.
- If a temp file is in use when trying to delete it, deletion will fail and temp file will remain on FS. For this reason temp files are also deleted when the application is first started.
User can change his Enigma EFS password at any time.
- Click on the menu button.
- Click Change password.
- Type your current password into the “Current password” box.
- Type a new password into the “New password” box.
- Repeat a new password into the “Confirm password” box.
- Click Submit.
For testing purposes, there is a folder OPENSSL and a database Users.db provided in the repository with certificates and private keys. Unfortunately, encrypted private keys are not stored on git due too their large size. There are five users already registered:
Id | Username | Password |
---|---|---|
1 | marko#2393 | myRandomPass253 |
4 | igor#1893 | myRandomPass105 |
5 | janko#9459 | myRandomPass269 |
6 | luka#1374 | myRandomPass985 |
7 | aleksa#1184 | myRandomPass593 |
Also, here's the property query for my SQLite database:
CREATE TABLE "Users" (
"Id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
"Username" CHAR(30) NOT NULL UNIQUE,
"Salt" BLOB NOT NULL UNIQUE,
"PassHash" BLOB NOT NULL,
"PublicKey" BLOB NOT NULL UNIQUE,
"LastLogin" CHAR(33) NOT NULL,
"LoginAttempt" INTEGER NOT NULL,
"UsbKey" BOOLEAN NOT NULL,
"Locked" BOOLEAN NOT NULL,
"CertificateExpirationDate" CHAR(38) NOT NULL,
"Revoked" BOOLEAN NOT NULL,
"ForcePasswordChange" BOOLEAN NOT NULL
);
NOTE:
For more info about certificates stored in OPENSSL folder read users_cert_list.txt file.
Enigma EFS views each encrypted file as a set of file attributes. File elements such as its name, its security information, and even its data are file attributes. Each attribute is identified by an attribute type code stored as an enum
.
public enum AttributeType : uint
{
Unkown = 0,
STANDARD_INFORMATION = 0x10,
SECURITY_DESCRIPTOR = 0x50,
DATA = 0x80,
}
Files are encrypted using one of the available symmetric algorithms. After the user picks a symmetric algorithm, hash algorithm, key size and a block cipher mode of operation, the file is then encrypted. First, the file headers are generated, after which the original file is signed and encrypted (in that order).
NOTE:
Symmetric algorithm name, hash algorithm name and IV value are not encrypted because my research has led me to believe that their exposure won't weaken Enigma's security.
Encrypted files are decrypted using a stored encrypted Key, IV and an encryption algorithm name stored inside the file's Security Descriptor header. An encrypted Key is first decrypted using a user's private RSA key, after which it's used for file decryption. After file decryption, a file signature is checked to see if the file's integrity has been compromised.
NOTE:
Every time file is decrypted its read time is updated.
Every filename is encrypted using an AES-256 algorithm in OFB mode, with IV and Key stored in the file header. After encryption, filename is Base64 encoded.
Windows file naming restrictions
A filename cannot contain any of the following characters: <, >, ", /, \, |, ? or *.
Since the Base64 encoded name can contain a forbidden name symbol forward slash, '/' is replaced with '$'.
Attribute Type | Attribute Name | Description |
---|---|---|
0x10 | Standard Information | Information such as creation time, modified time and read time. |
0x50 | Security Descriptor | Information such as symmetric algorithm name, hash algorithm name, IV value, encrypted Key value, Owner Id and RSA Signature data. |
0x80 | Data | Encrypted file data. |
Offset | Size (bytes) |
Description |
---|---|---|
0x00 | Attribute Type (0x10) | |
0x04 | Total Length | |
0x08 | C Time - File Creation | |
0x10 | Owner Id | |
0x14 | A Time - File Altered | |
0x1c | A Time User Id | |
0x20 | R Time - File Read | |
0x28 | R time User Id |
Total size of this header is
$44$ bits.
Offset | Size (bytes) |
Description |
---|---|---|
0x000 | Attribute Type (0x50) | |
0x004 | Algorithm Name Signature Length | |
0x005 |
|
Algorithm Name Signature (e.q. AES-256-CBC) |
0x010 | Hash Algorithm Name Length | |
0x011 |
|
Hash Algorithm Name (e.q. SHA256) |
0x017 | IV length | |
0x018 |
|
IV |
0x028 | Owner Id | |
0x02c | Number of users that have access to the file (max. 4 users) |
|
0x030 | User Id | |
0x034 | Encrypted Key Length | |
0x038 |
|
Encrypted Key (e.q. |
0x138 | RSA Signature Length | |
0x13c |
|
RSA Signature |
Offset | Size (bytes) |
Description |
---|---|---|
0x00 | Attribute Type (0x80) | |
0x04 | up to |
Encrypted Data |
List of symmetric encryption algorithms that are implemented in Enigma EFS.
ALGORITHM NAME |
BLOCK CIPHER MODE OF OPERATION |
KEY SIZE (bits) |
BLOCK SIZE (bits) |
---|---|---|---|
AES | ECB, CBC, CFB, OFB |
|
|
Camellia | ECB, CBC, CFB, OFB |
|
|
3DES | ECB, CBC, CFB, OFB | ||
Twofish | ECB, CBC, CFB, OFB |
|
NOTE:
I don't recomment ECB mode because it's not semantically secure. The only time it could be safe to use is if its used for encryption of data smaller than 128 bits when using with AES, Camellia or Twofish, or 64 bits when using with 3DES.
RSA cryptosystem is the only asymmetric algorithm implemented. It's used to encrypt symmetric keys, and it's used for generating a digital signature of files.
Hashing algorithms that are implemented in Enigma EFS.
Algorithm | Variant | Output size (bits) |
---|---|---|
MD2 | x | |
MD4 | x | |
MD5 | x | |
SHA-1 | x | |
SHA-2 | SHA-224 SHA-256 SHA-384 SHA-512 |
|
RIPEMD | RIPEMD-128 RIPEMD-160 RIPEMD-256 |
|
NOTE:
MD5 and SHA1 MUST NOT be used for cryptographic hash functions. Keep in mind that RIPEMD-128 and RIPEMD-160 aren't considered secure because message digest of (at least)
$224$ bits must be used. RIPEMD-256 isn't recommended by NIST, so caution is advised when using it. Also, MD2 and MD4 are obsolete.
Username is provided by the user when registering. After having a discussion with my professor, I've come to the conclusion that a better approach to username creation would be to add random numbers to every username. This will make a brute force attack on a user's account more difficult, and it will also allow duplicate username usage. Probability of a collision when using the same username is
I've used a similar approach to creating usernames as Discord. Each username is assigned a four-digit number, prefixed with '#', which is added to the end of their username. E.q. if you choose a username myname, then your final username will look something like myname#5642.
Guidelines for choosing good passwords are typically designed to make passwords harder to discover by intelligent guessing. All the guidelines are NIST compliant.
Memorized secrets are at least 8 characters in length, not including spaces.
Passwords are only required to be changed if there is evidence of compromise.
New passwords are screened against a list of known compromised passwords.
New passwords can't contain the username.
Password hints and knowledge-based security questions are not implemented.
Maximum password length is set
$200$ characters (NIST minimum is$64$ ).Passwords can contain all printable ASCII characters, including a space character.
In Enigma EFS password strength is specified in terms of entropy (concept from information theory) which is measured in bits. For passwords generated by a process that randomly selects a string of symbols of length, L, from a set of N possible symbols, the number of possible passwords can be found by raising the number of symbols to the power L. Increasing either L or N will strengthen the generated password. The strength of a random password as measured by the Shannon's entropy is just the base-2 logarithm of the number of possible passwords, assuming each symbol in the password is produced independently. A random password's information entropy, H, is given by the formula:
Entropy per symbol for different symbol sets:
SYMBOL SET | SYMBOL COUNT |
ENTROPY PER SYMBOL |
---|---|---|
Arabic numbers (0-9)
|
|
|
Case-insensitive Latin alphabet(a–z or A–Z)
|
|
|
Case-insensitive alphanumeric(a–z or A–Z, 0–9)
|
|
|
Case-sensitive Latin alphabet(a–z, A–Z)
|
|
|
Case-sensitive alphanumeric(a–z, A–Z, 0–9)
|
|
|
All ASCII printable characters |
|
|
Diceware word list |
per word |
NOTE:
NIST recommends dropping the arbitrary password complexity requirements needing mixtures of upper case letters, symbols and numbers. Based on cracking real-world passwords conclude "notion of password entropy...does not provide a valid metric for measuring the security provided by password creation policie". However, I have implemented Shannon's entropy in Enigma EFS despite it not being a good predictor of how quickly attackers can crack passwords.
A passphrase is a sequence of randomly chosen words. It is similar to password in usage, but is generally longer. Enigma EFS offers random generated passphrases based on Diceware. While such a collection of words might appear to violate the "not from any dictionary" rule, the security is based entirely on the large number of possible ways to choose from the list of words and not from any secrecy about the words themselves. There are in total
A supplementary approach to frustrating brute-force attacks is to derive the key from the password/passphrase using a deliberately slow hash function. Enigma EFS uses NIST recommended key derivation function PBKDF2. One weakness of PBKDF2 is that while its number of iterations can be adjusted to make it take an arbitrarily large amount of computing time, it's not a memory-hard function. A function that is not only time-hard but also memory-hard like Balloon or Argon2 could add more security to the system.
When first creating an account, every user is prompted to encrypt his private RSA key using his password. Unlike a user account password, the RSA password doesn't need to have a high entropy. The only limitation is that it has to be at least 8 characters long. Every RSA key is encrypted using AES-256-OFB algorithm. Key and IV are derived from the user's password using a SHA-512 hashing algorithm.
After encryption, the encrypted RSA key is hidden in a haystack of CSPRNG random data, which is then stored on FS or on a user USB. Haystack size is always random, and its size is given by the formula:
The idea was to hide a block of useful data in a much larger block of random data, which will virtually indistinguishable from our hidden data. Given that description, a better name would perhaps be a needle in a stack of needles. Does this actually increase the security of the private key? I'm not really sure, there is a good chance this is a good example of security theater. What I do know is that the private RSA key should be secure as long as the user's password is strong and kept a secret. If a user's RSA key is stored on a USB, it should have an added security advantage compared to a key stored on FS duo to physical security.
Haystack contains, starting from a first bit of data, encrypted RSA key randomly chosen starting location in a haystack stored as an integer, size of the encrypted RSA key stored as an integer, user passwords salt stored in next
User certificate has to be issued by a proper root CA. Path to list of trusted CAs is stored in EnigmaEFS.config file. Since 2015, NIST recommends a minimum of
-
User can't store files larger than 2 GB.
-
Minimum RSA key size permitted is
$2,048$ bits long. -
Only a file owner can share/unshare, update or delete a file.
- RSA key usage
RSA keys are used both for encryption and file signing.
- Encryption using ECB mode
When updating an already encrypted file, only the IV value is changed while the KEY remains the same. This is potentially a problem when using an ECB mode which doesn't require IV. An attacker who is observing different versions of the encrypted file can perhaps deduce an opentext.
-
- 3DES encryption
Please be mindful when using 3DES encryption as it only provides
$112$ bit security, not$192$ bits ($168$ bits), due to meet-in-the-middle attack.
- Implement encryption of large files.
- Remove 2 GB file size restriction.
- Remove file type limitations.
-
Implement SHA-3 hashing (-224,-256,-384 and -512). - Implement trusted timestamping and TSA.
- Implement re-login process after 5 minutes of inactivity.
-
Implement forgot password functionality. - Implement password change.
- Fix RSA USB key loading bug.
- Add nonRepudiation bit as mandatory part of KeyUsage certificate extension.
Dirk Strauss - Cryptography in .NET
Michael Welschenbach - Cryptography in C and C++
Dirk Strauss - Application Security in .NET Succinctly
William Stallings - Cryptography and Network Security: Principles and Practice
John F. Dooley - History of Cryptography and Cryptanalysis: Codes, Ciphers, and Their Algorithms
Some of the projects that Enigma EFS uses, either directly or indirectly.