Skip to content

AleksaMCode/Enigma

Repository files navigation

Enigma EFS

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.

Table of contents

Acronyms

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

Name origin

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.

Usage

Register

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.

Login

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.

Login attempt limit

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.

Nuclear switch

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.

Private key import

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.

File import

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.

Add folder

User can add a new folder to EFS by entering the folder's name. Folder is added at the current path.

File export

User can export any file from his EFS to a selected location on FS.

Create and import a new .txt file

User can add simple .txt files to Enigma EFS by using a built-in application text editor.

Remove file

Users can simply delete their files without any restrictions.

File sharing

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.

File unsharing

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.

File updating

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.

.txt file updating

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.

File reading

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:

  1. The path specified by the TMP environment variable.
  2. The path specified by the TEMP environment variable.
  3. The path specified by the USERPROFILE environment variable.
  4. 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.

Changing the Current Password

User can change his Enigma EFS password at any time.

  1. Click on the menu button.
  2. Click Change password.
  3. Type your current password into the “Current password” box.
  4. Type a new password into the “New password” box.
  5. Repeat a new password into the “Confirm password” box.
  6. Click Submit.

Database

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.

Encrypted 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,
} 

File encryption

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.

File decryption

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.

File naming

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 '$'.

Enigma EFS Encrypted File Attribute Types

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.

Layout of the Standard Information

Offset Size
(bytes)
Description
0x00 $4$ Attribute Type (0x10)
0x04 $4$ Total Length
0x08 $8$ C Time - File Creation
0x10 $4$ Owner Id
0x14 $8$ A Time - File Altered
0x1c $4$ A Time User Id
0x20 $8$ R Time - File Read
0x28 $4$ R time User Id

Total size of this header is $44$ bits.

Layout of the Security Descriptor

Offset Size
(bytes)
Description
0x000 $4$ Attribute Type (0x50)
0x004 $1$ Algorithm Name Signature Length
0x005 $11$ - $13$ Algorithm Name Signature (e.q. AES-256-CBC)
0x010 $1$ Hash Algorithm Name Length
0x011 $3$ - $10$ Hash Algorithm Name (e.q. SHA256)
0x017 $1$ IV length
0x018 $8$ or $16$ IV
0x028 $4$ Owner Id
0x02c $4$

Number of users that have access to the file (max. 4 users)
e.q. only a file owner has access to the file

0x030 $4$ User Id
0x034 $4$ Encrypted Key Length
0x038 $256$, $384$ or $512$ Encrypted Key
(e.q. $256$ when user has $2,048$ bits RSA key)
0x138 $4$ RSA Signature Length
0x13c $256$, $384$ or $512$ RSA Signature

Layout of the Data

Offset Size
(bytes)
Description
0x00 $4$ Attribute Type (0x80)
0x04 up to $2$ GB Encrypted Data

Algorithms

Symmetric algorithms

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 $128$, $192$, and $256$ $128$
Camellia ECB, CBC, CFB, OFB $128$, $192$, and $256$ $128$
3DES ECB, CBC, CFB, OFB $192$ $64$
Twofish ECB, CBC, CFB, OFB $128$, $192$, and $256$ $128$

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.

Asymmetric algorithm

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

Hashing algorithms that are implemented in Enigma EFS.

Algorithm Variant Output size
(bits)
MD2 x $128$
MD4 x $128$
MD5 x $128$
SHA-1 x $160$
SHA-2 SHA-224
SHA-256
SHA-384
SHA-512
$224$
$256$
$384$
$512$
RIPEMD RIPEMD-128
RIPEMD-160
RIPEMD-256
$128$
$160$
$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

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 $0.0001$. If the collision does happen, the user should try to register again with the same username (probability of two consecutive collisions is $0.00000001$).

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.

Passwords and keys

Password guidelines

Guidelines for choosing good passwords are typically designed to make passwords harder to discover by intelligent guessing. All the guidelines are NIST compliant.

  1. Memorized secrets are at least 8 characters in length, not including spaces.

  2. Passwords are only required to be changed if there is evidence of compromise.

  3. New passwords are screened against a list of known compromised passwords.

  4. New passwords can't contain the username.

  5. Password hints and knowledge-based security questions are not implemented.

  6. Maximum password length is set $200$ characters (NIST minimum is $64$).

  7. Passwords can contain all printable ASCII characters, including a space character.

Password Entropy

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:

$H = \log_2{N^L}$.

Entropy per symbol for different symbol sets:

SYMBOL SET SYMBOL
COUNT
ENTROPY PER
SYMBOL
Arabic numbers (0-9) $10$ $3.322$ bits
Case-insensitive Latin alphabet
(a–z or A–Z)
$26$ $4.700$ bits
Case-insensitive alphanumeric
(a–z or A–Z, 0–9)
$36$ $5.170$ bits
Case-sensitive Latin alphabet
(a–z, A–Z)
$2$ $5.700$ bits
Case-sensitive alphanumeric
(a–z, A–Z, 0–9)
$65$ $5.954$ bits
All ASCII printable characters $95$ $6.570$ bits
Diceware word list $7,776$ $12.925$ bits
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.

Passphrase

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 $7,776$ words in the list (EFF wordlist) and anywhere between $6$ and $10$ words are chosen randomly which gives us a combination domain of $[7776^6,7776^{10}]$, that provides anywhere from $78$ to $128$ bits of entropy. Number $7,776$ ($6^5=7,776$) was chosen to allow words to be selected by throwing dice five times. Every dice throw is simulated by CSPRNG. As an additional security random delimiter with random length, that varies between $3$ and $5$ charters (ASCII chars between 0x20 and 0x41), is used.

Password protection and storage

Key stretching

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.

RSA key encryption and hiding

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.

Needle in a Haystack Steganography

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:

$haystack\textunderscore size = (size(encrypted\textunderscore RSA\textunderscore key) + CSPRNG - random([1024,4096])) \cdot 100,000$

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 structure

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 $16$ bytes of data, user password digest stored in next $32$ bytes of data and the encrypted RSA key stored at the appropriate location.

Certificate policies

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 $2,048$-bit keys for RSA. Consequently, Enigma EFS accepts only certificate that use, at least, $2,048$ bit long RSA key. $2,048$-bit keys are sufficient until 2030. This policy is perhaps not warranted, because I doubt any respectable CA will create a certificate with $1,024$ bit long key. Also, KeyUsage certificate extension has to have leastwise digitalSignature and keyEncipherment bits set.

Limitations and restrictions

  • 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.

Potential problems and known security and other bugs

  • 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.

To-Do List

  • 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.

References

Books

Links

Github projects

Some of the projects that Enigma EFS uses, either directly or indirectly.