2014-04-14 67 views
0

我正在使用AES加密和OpenSSL加密/解密程序。我在兩個本地目錄之間建立了一個FUSE文件系統,其中一個是鏡像目錄,另一個是我的linux虛擬機上的掛載點。我正在修改fuse_operations結構中的讀取,寫入和創建函數,以便在從安裝點目錄打開並讀取加密文件時,應該在應用程序窗口中顯示明文。使用AES加密OpenSSL解密輸出中的字符無效libcrypto EVP API和FUSE文件系統

我有一個名爲do_crypt函數,接受作爲輸入的文本文件,其中,所述解密/加密的文本應該去一個輸出文件,用於解密,加密,或通過一個int,並通過短語用來完成操作。在IS代碼如下:

#define BLOCKSIZE 1024 
#define FAILURE 0 
#define SUCCESS 1 

extern int do_crypt(FILE* in, FILE* out, int action, char* key_str){ 
/* Local Vars */ 

/* Buffers */ 
unsigned char inbuf[BLOCKSIZE]; 
int inlen; 
/* Allow enough space in output buffer for additional cipher block */ 
unsigned char outbuf[BLOCKSIZE + EVP_MAX_BLOCK_LENGTH]; 
int outlen; 
int writelen; 

/* OpenSSL libcrypto vars */ 
EVP_CIPHER_CTX ctx; 
unsigned char key[32]; 
unsigned char iv[32]; 
int nrounds = 5; 

/* tmp vars */ 
int i; 

/* Setup Encryption Key and Cipher Engine if in cipher mode */ 
if(action >= 0){ 
if(!key_str){ 
    /* Error */ 
    fprintf(stderr, "Key_str must not be NULL\n"); 
    return 0; 
} 
/* Build Key from String */ 
i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), NULL, 
      (unsigned char*)key_str, strlen(key_str), nrounds, key, iv); 
if (i != 32) { 
    /* Error */ 
    fprintf(stderr, "Key size is %d bits - should be 256 bits\n", i*8); 
    return 0; 
} 
/* Init Engine */ 
EVP_CIPHER_CTX_init(&ctx); 
EVP_CipherInit_ex(&ctx, EVP_aes_256_cbc(), NULL, key, iv, action); 
}  

/* Loop through Input File*/ 
for(;;){ 
/* Read Block */ 
inlen = fread(inbuf, sizeof(*inbuf), BLOCKSIZE, in); 
if(inlen <= 0){ 
    /* EOF -> Break Loop */ 
    break; 
} 

/* If in cipher mode, perform cipher transform on block */ 
if(action >= 0){ 
    if(!EVP_CipherUpdate(&ctx, outbuf, &outlen, inbuf, inlen)) 
    { 
     /* Error */ 
     EVP_CIPHER_CTX_cleanup(&ctx); 
     return 0; 
    } 
} 
/* If in pass-through mode. copy block as is */ 
else{ 
    memcpy(outbuf, inbuf, inlen); 
    outlen = inlen; 
} 

/* Write Block */ 
writelen = fwrite(outbuf, sizeof(*outbuf), outlen, out); 
if(writelen != outlen){ 
    /* Error */ 
    perror("fwrite error"); 
    EVP_CIPHER_CTX_cleanup(&ctx); 
    return 0; 
} 
} 

/* If in cipher mode, handle necessary padding */ 
if(action >= 0){ 
/* Handle remaining cipher block + padding */ 
if(!EVP_CipherFinal_ex(&ctx, outbuf, &outlen)) 
    { 
    /* Error */ 
    EVP_CIPHER_CTX_cleanup(&ctx); 
    return 0; 
    } 
/* Write remainign cipher block + padding*/ 
fwrite(outbuf, sizeof(*inbuf), outlen, out); 
EVP_CIPHER_CTX_cleanup(&ctx); 
} 

/* Success */ 
return 1; 
} 

功能正常工作,而無需使用保險絲系統。一切都被正確加密/解密,但是當我使用讀功能來解密熔絲文件系統中的文件時,我在輸出中得到了一些無效字符。我試過3個文本編輯器來查看這些文件:sublime像任何其他文件一樣讀取輸出,沒有問題; geany不會打開該文件,因爲它表示無法識別編碼並且有無效字符; gedit顯示解密的輸出,但也有一些無效的字符表示爲'/ 00/00/00'。我不知道這些角色是什麼。我做了一些研究,我相信它們是空字符,但我不知道當我使用熔絲函數並運行解密時它們顯示出來的原因,但是當它們不使用它時,它們不顯示在輸出中。

我試過2個不同版本的閱讀功能:一種方式使用內存中的緩衝區來保存內容。

static int xmp_read(const char *path, char *buf, size_t size, off_t offset, 
     struct fuse_file_info *fi) 
{ 
    (void) fi; 
    int res; 

char fpath[PATH_MAX]; 
xmp_fullpath(fpath, path);//changes path to mirror directory 

FILE *f; 


FILE *tmpFile; 
tmpFile = tmpfile(); 
f = fopen(fpath, "r"); 

do_crypt(f, tmpFile, DECRYPT, XMP_DATA->key_phrase);//function that decrypts/encrypts 

rewind(tmpFile); 
res = pread(fileno(tmpFile), buf, size, offset);//read the encrypted/decrypted output to the application buffer 

fclose(f); 
fclose(tmpFile); 
return res; 
} 

另一種方式做加密/解密之前創建一個臨時文件:

int res; 
char fpath[PATH_MAX]; 
xmp_fullpath(fpath, path); 
FILE *memstream; 
char *membuf; 
size_t memlen; 
//off_t eob; 
memstream = open_memstream(&membuf, &memlen);//create a dynamically allocated buffer in memory 

FILE *f = fopen(fpath, "rb"); 

do_crypt(f, memstream, DECRYPT, XMP_DATA->key_phrase); 

fflush(memstream); 
fseek(memstream, offset, SEEK_SET); 

res = fread(buf, 1, memlen, memstream); 

return res; 

我的問題是:

1)爲什麼我會收到無效字符 '/ 00/00',這在嘗試解密文件時,在我的輸出中顯示爲空字符?

2)爲什麼我能夠使用一個文本編輯器查看文件,而不能查看其他文件?

再次加密和通過在熔絲系統中完美工作,我可以用所有三個文本編輯器打開它們。當我不使用保險絲時,do_crypt完美工作。但是當我嘗試在熔絲讀取功能中解密時,我得到了正確的解密文本,但我也得到了這些無效字符。當我使用'cat'終端命令時,輸出不包含無效字符。

以下是完整的代碼回購的鏈接。 https://github.com/latitude98/CU-CS3753-PA4

+0

這可能是['sizeof()'](http://stackoverflow.com/questions/15177420/what-does-sizeofarray-return)多數民衆贊成在罪魁禍首。請注意,它取決於編輯器/查看器對ASCII字符'00'等不可打印字符的作用。 –

+0

我的意思是「如」而不是像 - 當我累了,給我一點酒,我變成一個加拿大女孩:P –

+0

哈哈我知道你的意思! – rowe7280

回答

0

一個常見的錯誤操作的方式一樣在VFS級加密/解密數據的突變(例如經由保險絲)失敗調用底層GETATTR()系統調用之前發生變異在熔絲getattr函數(即解密)文件。在你的情況下,如果getattr()系統調用傳遞加密文件而不是未加密文件,它將返回錯誤的文件大小(加密和解密文件具有不同的文件大小)。很多程序依賴此文件大小是正確的,以便知道要讀取多少文件,所以如果getattr()返回加密文件的大小而不是未加密文件的大小,則可能會看到錯誤像你描述的那樣。

某些程序(例如複雜文本編輯器)在讀取文件時依賴於瞭解文件大小,因此需要使用getattr()才能正常工作。像'貓'這樣的實用程序傾向於使用更基本的「一次讀取一個字節,直到看到EOF」方法,因此不太依賴於正確的文件大小。這可以解釋爲什麼某些程序工作正常(尋找EOF的程序),但其他程序不會(嘗試讀取字節的程序)。

有幾個VFS /保險絲功能,除了明顯的(即讀取),需要你打電話解密。如上所述,getattr可能是最關鍵的一個。你可能也想看截斷和打開。根據您實施文件系統的方式,這些可能還需要一些解密知識。

相關問題