# Objective This assignment aims to deepen understanding of file system operations and encryption mechanisms by building a simple in-memory file system using the FUSE (Filesystem in Userspace) framework, followed by integrating AES-256 encryption to ensure data security. **Resources:** 1. [Less Simple, Yet Stupid Filesystem (Using FUSE)](https://github.com/MaaSTaaR/LSYSFS) 2. [In Storage Filesystem (ISFS) Using FUSE](https://github.com/yttty/isfs) Assignment: [Link](https://github.com/gary7102/Encrypted-FS-on-FUSE/blob/main/Assignment%202.docx) # Part 1 **Setting Up FUSE environment** ``` sudo apt-get install fuse libfuse-dev ``` ![image](https://hackmd.io/_uploads/ryLRzhBm1e.png) ![image](https://hackmd.io/_uploads/SknVNnrQJe.png) # Part 2 Building a Basic In-Memory File System with FUSE: Using the FUSE framework, create a simple in-memory file system. This file system should support basic operations such as: * Create, read, and write files. * Open and close files. * Create and remove directories. * List directory contents. <font size = 4>**memfs**</font> ``` memfs/ ├── Makefile ├── main.c # 主程式,包含Initlize 和 FUSE 的入口點 ├── node.c # 節點操作(如Create, LookUP)相關操作 ├── node.h # header file of node.c ├── encryption.c # 與資料加密和解密相關操作 ├── encryption.h # header file of encryption.c` ├── operations.c # FUSE 各種函數的實現(如: read, write, mkdir) ├── operations.h # headre file of operations.c └── memfs.h # global header file,定義核心結構、global vaviable,root等 ``` <font size = 4>**Makefile**</font> ``` CC = gcc CFLAGS = `pkg-config fuse3 --cflags` -Wall -g LDFLAGS = `pkg-config fuse3 --libs` -lssl -lcrypto SOURCES = main.c node.c encryption.c operations.c OBJECTS = $(SOURCES:.c=.o) HEADERS = memfs.h node.h encryption.h operations.h all: memfs memfs: $(OBJECTS) $(CC) $(CFLAGS) -o memfs $(OBJECTS) $(LDFLAGS) %.o: %.c $(HEADERS) $(CC) $(CFLAGS) -c $< -o $@ clean: rm -f memfs $(OBJECTS) ``` **Makefile 說明:** 執行 `make` 時,會先找到 `all`,`all` 依賴於 `memfs`,所以去執行`memfs` ,`memfs` 依賴於 `$(OBJECTS)`,所以實際上會先去檢查所有的`.o`檔是否存在, * 如果`.o` file 不在,就先把對應的`.c`檔編譯成`.o` file * 如果`.o` file 存在,就直接執行 `memfs` 的生成 `pkg-config fuse3 --cflags` 及`pkg-config fuse3 --libs` 表示 provide the compiler the proper arguments to include “fuse3” library. `-Wall` 表示啟用所有常用的編譯器警告 編譯成功後會出現一個可執行檔 `memfs` ![image](https://hackmd.io/_uploads/SJMST3ZV1g.png) <font size = 4>**將`memfs` 掛載到 `/tmp/memfs`**</font> ``` ./memfs -f -d /tmp/memfs ``` `-f` : 表示讓process在foreground運作。主要目的是在terminal中看到程式的输出,類似於 `dmesg` (查看kernel 內的訊息)。 `-d` : Debug模式,可以用來查看更詳細的運作訊息,包含每個指令實際執行到的function、nodeid、pid、error message等等 結束後,在另一個terminal 中輸入: ``` cd /tmp/memfs ``` 即可開始對file system進行各種操作。 --- <font size = 4>**創建新directory**</font> ``` mkdir testdir ``` 在Foreground中會出現: ![image](https://hackmd.io/_uploads/SyQfXgvmkl.png) 可以發現,`mkdir` 實際上會先去`LOOKUP /testdir`,得到 error: NO such file or directory, 接下來會真正執行`MKDIR` 產生 `testdir` 這個目錄 --- <font size = 4>**建立新檔案**</font> ``` touch testfile ``` 在Foreground中會出現: ![image](https://hackmd.io/_uploads/ryX2ilDmye.png) 可以發現創立檔案的流程: * `LOOKUP /testfile` 得到 error: NO such file or directory * `CREATE /testfile` 在nodeid 為 1(root directory)下創建testfile * `SETATTR` 對testfile設定一些屬性(如: `atimes`, `mtimes`), * `RELEASE` 關閉testfile,得到success。 --- <font size = 4>**寫入檔案**</font> ``` echo "Hello" > testfile ``` 在Foreground中會出現: ![image](https://hackmd.io/_uploads/r1Wu3xwXyg.png) 可以發現共寫入6個bytes,`"Hello\n"` 共6bytes。 --- <font size = 4>**讀取檔案**</font> ``` cat testfile ``` ![image](https://hackmd.io/_uploads/B1FxbZwmyl.png) 在Foreground中會出現: ![image](https://hackmd.io/_uploads/ryqyg-PQ1l.png) --- <font size = 4>**列出directory內容**</font> ``` ls -l ``` ![image](https://hackmd.io/_uploads/BkndbbvXke.png) 在Foreground中會出現: ![image](https://hackmd.io/_uploads/Syaw-bvQye.png) --- <font size = 4>**delete file**</font> ``` rm testfile ``` 在Foreground中會出現: ![image](https://hackmd.io/_uploads/rk7cM-wXyg.png) --- <font size = 4>**delete directory**</font> ``` rmdir testdir ``` 在Foreground中會出現: ![image](https://hackmd.io/_uploads/rk1HMZD7kg.png) 若 directory不存在會出現: ![image](https://hackmd.io/_uploads/HyOoPttXJe.png) # Part 3, 4, 5 * Integrating AES-256 Encryption * Encrypted with a different key * Ensure all file operations (read, write, etc.) handle encrypted data correctly * Testing and Validation <font size = 4>**AES-256 Encryption如何運作?**</font> * `EVP_CIPHER_CTX_new()` : returns a pointer to a newly created EVP_CIPHER_CTX for success and NULL for failure. * `EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv)` * `EVP_EncryptUpdate(ctx, *ciphertext, &len, plaintext, plaintext_len)` * `EVP_EncryptFinal_ex(...)` * `EVP_CIPHER_CTX_free(ctx)` Implement a mechanism for managing encryption keys, ensuring that each file can be encrypted with a <font color = orange>**different key**</font>. Design the system so that the encryption key must be supplied to open a file. <font size = 4>**寫入時加密:**</font> 可以在mount 上資料夾之前,先設幾個斷點,到時候方便檢查是否確實加密 * 讓 `memfs` mount 上 `/tmp/memfs`: ``` gdb --args ./memfs -f -d /tmp/memfs ``` * `gdb` 寫入斷點: ``` break memfs.c:545 // before ending memfs_write() break operations.c:220 break memfs.c:456 // before ending memfs_read() break operations.c:296 ``` * `gdb` 執行程式: ``` run ``` **在另一邊的terminal 打入:** ``` echo "123456789123456789" > testfile ``` 可以看到自動生成的`AES key`(32-bits)及`IV`(16-bits), ![image](https://hackmd.io/_uploads/BkX5bd37kl.png) 停在中斷點後,在 `gdb`中打入指令,查看memory中的加密資料內容: ``` x/32bx encrypted_data ``` ![image](https://hackmd.io/_uploads/Hk6GsF2Qkl.png) 和我們直接印出資料內容: ![image](https://hackmd.io/_uploads/H17ZitnXke.png) 得到一樣的內容 可以看到這串資料使用了AES-256加密演算法,且加密資料 `encrypted_data` 的內容與原始寫入資料: `123456789123456789\n` 沒有任何關係 <font size = 4>**讀取時解密:**</font> 若要查看解密資料是否正確 * 先打: ``` cat testfile ``` * 停在中斷點後,在 `gdb` 打入指令,查看memory中的解密資料內容: ``` x/32bx decrypted_data ``` ![image](https://hackmd.io/_uploads/B1fzZkiXkl.png) 這次可以看到,解密的資料為正確資料,因為根據ASCII-Table: * `1` 為 `0x31` * `2` 為 `0x32` * ... * `9` 為 `0x39` * `\n` 為 `0x0a` 可以得到結論,寫入的資料經過AES-256加密過後,在未解密的情況下讀取,確實會是一串和原始資料不相關的資料,證實有正確實現加密檔案的動作, 而解密過後的資料`decrypted_data` 資料為: `123456789123456789\n`,確實為寫入資料,因此驗證AES-256在寫入時有正確加密,不夠的位元也有做padding,而在讀取資料時才做解密的動作,且解密資料為寫入資料正確無誤。 <font size = 4>**測試多個檔案生成不同的key**</font> ``` touch testfile_2 ``` ![image](https://hackmd.io/_uploads/H1qrIOnmye.png) ``` touch testfile_3 ``` ![image](https://hackmd.io/_uploads/HkpULdhQkl.png) # Part 6 <font size = 4>**Testing and Validation**</font> 測試: 若給予錯誤的AES key,是否能解密資料 更改`memfs_read()` 為: ```c // Use wrong key to decrypted data int memfs_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { // ... // 定義錯誤的 AES 金鑰(與正確金鑰不同) unsigned char wrong_key[AES_KEY_SIZE] = "wrongkey12345678901234567890abcd"; // 使用錯誤的金鑰進行解密 int decrypted_size = decrypt_data((unsigned char *)node->data, node->size, wrong_key, node->aes_iv, &decrypted_data); // ... ``` 這個`memfs_read()`內預設了錯誤的AES key,在讀取時會使用到錯誤的key, 並且`return -EIO`,所以在command line 會看到 Input/output error <font size = 4>**執行結果:**</font> ![image](https://hackmd.io/_uploads/rk_NOY27kl.png) ![image](https://hackmd.io/_uploads/ByuIOt37kx.png) 可以看到,使用錯誤的AES key讀取已經加密的資料,無法讀取 <font size = 4>**卸载file system**</font> ``` fusermount -u /tmp/memfs ``` # Problems