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:
Assignment: Link
Setting Up FUSE environment
sudo apt-get install fuse libfuse-dev
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.
memfs
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等
Makefile
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
將memfs
掛載到 /tmp/memfs
./memfs -f -d /tmp/memfs
-f
: 表示讓process在foreground運作。主要目的是在terminal中看到程式的输出,類似於 dmesg
(查看kernel 內的訊息)。
-d
: Debug模式,可以用來查看更詳細的運作訊息,包含每個指令實際執行到的function、nodeid、pid、error message等等
結束後,在另一個terminal 中輸入:
cd /tmp/memfs
即可開始對file system進行各種操作。
創建新directory
mkdir testdir
可以發現,mkdir
實際上會先去LOOKUP /testdir
,得到 error: NO such file or directory,
接下來會真正執行MKDIR
產生 testdir
這個目錄
建立新檔案
touch testfile
在Foreground中會出現:
可以發現創立檔案的流程:
LOOKUP /testfile
得到 error: NO such file or directoryCREATE /testfile
在nodeid 為 1(root directory)下創建testfileSETATTR
對testfile設定一些屬性(如:atimes
,mtimes
),RELEASE
關閉testfile,得到success。
寫入檔案
echo "Hello" > testfile
在Foreground中會出現:
可以發現共寫入6個bytes,"Hello\n"
共6bytes。
讀取檔案
cat testfile
列出directory內容
ls -l
delete file
rm testfile
delete directory
rmdir testdir
- Integrating AES-256 Encryption
- Encrypted with a different key
- Ensure all file operations (read, write, etc.) handle encrypted data correctly
- Testing and Validation
AES-256 Encryption如何運作?
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 different key. Design the system so that the encryption key must be supplied to open a file.
寫入時加密: 可以在mount 上資料夾之前,先設幾個斷點,到時候方便檢查是否確實加密
- 讓
memfs
mount 上/tmp/memfs
:
gdb --args ./memfs -f -d /tmp/memfs
gdb
寫入斷點:
break memfs.c:545 // before ending memfs_write()
break memfs.c:456 // before ending memfs_read()
gdb
執行程式:
run
在另一邊的terminal 打入:
echo "123456789123456789" > testfile
可以看到自動生成的AES key
(32-bits)及IV
(16-bits),
停在中斷點後,在 gdb
中打入指令,查看memory中的加密資料內容:
x/32bx encrypted_data
可以看到這串資料使用了AES-256加密演算法,且加密資料 encrypted_data
的內容與原始寫入資料: 123456789123456789\n
沒有任何關係
讀取時解密: 若要查看解密資料是否正確
- 先打:
cat testfile
- 停在中斷點後,在
gdb
打入指令,查看memory中的解密資料內容:
x/32bx decrypted_data
這次可以看到,解密的資料為正確資料,因為根據ASCII-Table:
1
為0x31
2
為0x32
- ...
9
為0x39
\n
為0x0a
可以得到結論,寫入的資料經過AES-256加密過後,在未解密的情況下讀取,確實會是一串和原始資料不相關的資料,證實有正確實現加密檔案的動作,
而解密過後的資料decrypted_data
資料為: 123456789123456789\n
,確實為寫入資料,因此驗證AES-256在寫入時有正確加密,不夠的位元也有做padding,而在讀取資料時才做解密的動作,且解密資料為寫入資料正確無誤。
測試多個檔案生成不同的key
touch testfile_2
touch testfile_3
Testing and Validation
測試: 若給予錯誤的AES key,是否能解密資料
更改memfs_read()
為:
// 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
執行結果:
可以看到,使用錯誤的AES key讀取已經加密的資料,無法讀取
卸载file system
fusermount -u /tmp/memfs