2016-04-30 71 views
0

我在使用openssl獲取兩個程序來加密和解密郵件時遇到了一些麻煩。這兩個程序編譯並運行正常,但解密似乎只解密我的plaintext.txt文件的前7個字符。使文件加密後OpenSSL加密/解密只解密前7個字符?

和解密從這樣從命令行調用...

./enc -i plaintext.txt -o cipher.txt -p密碼

./dec I- cipher.txt -o decrypt.txt -p密碼

plaintext.txt輸入... 這事保密

decrypt.txt輸出... 這是}?W,

這裏是enc.c(加密)

#include <stdio.h> 
#include <errno.h> 
#include <string.h> 
#include <stdlib.h> 
#include <openssl/bio.h> 
#include <openssl/evp.h> 

/* AES-GCM test data from NIST public test vectors */ 

static const unsigned char gcm_iv[] = { 
    0x99, 0xaa, 0x3e, 0x68, 0xed, 0x81, 0x73, 0xa0, 0xee, 0xd0, 0x66, 0x84 
}; 

unsigned char * aes_gcm_encrypt(unsigned char *pt, long size, unsigned char *myCipher, unsigned char *out) 
{ 
    EVP_CIPHER_CTX *ctx; 
    int outlen, tmplen; 
    unsigned char outbuf[1024]; 
    // printf("AES GCM Encrypt:\n"); 
// printf("Plaintext:\n"); 
    // BIO_dump_fp(stdout, pt, size); 
    ctx = EVP_CIPHER_CTX_new(); 
    /* Set cipher type and mode */ 
    EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); 
    /* Set IV length if default 96 bits is not appropriate */ 
    // EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, sizeof(out), NULL); 
    /* Initialise key and IV */ 
    EVP_EncryptInit_ex(ctx, NULL, NULL, out, gcm_iv); 
    /* Encrypt plaintext */ 
    EVP_EncryptUpdate(ctx, outbuf, &outlen, pt, sizeof(pt)); 
    /* Output encrypted block */ 
    // printf("Ciphertext:\n"); 
    // BIO_dump_fp(stdout, outbuf, size); 
    /* Finalise: note get no output for GCM */ 
    EVP_EncryptFinal_ex(ctx, outbuf, &outlen); 


    EVP_CIPHER_CTX_free(ctx); 
    return myCipher = outbuf; 
} 


    extern int errno; 

int main(int argc, char **argv) 
{ 

    int ITERATION = 10000; 
    FILE * fp; 
    int errnum; 
    long size; 
    unsigned char *pass; 
    int len; 
    pass = argv[6]; 


    fp = fopen(argv[2], "a+"); 
    if (fp == NULL) 
    { 
     errnum = errno; 
     fprintf(stderr, "Value of errno: %d\n", errno); 
     perror("error printed by perror"); 
     fprintf(stderr, "Error opening the file: %s\n", strerror(errnum)); 
    } 

    fseek(fp, 0, SEEK_END); 
    size = ftell(fp); 
    fseek(fp, 0, SEEK_SET); 

    unsigned char * buff; 
    buff = (unsigned char*) malloc(sizeof(unsigned char)*size + 1); 
    memset(buff, '\0', sizeof(unsigned char)*size + 1); 
    fread(buff, 1, size, fp); 

    int SHA1_LEN = 30; 
    unsigned char* out = (unsigned char*)calloc(SHA1_LEN, sizeof(unsigned char)); 
    //int SALT_LEN = 5; 
    //RAND_bytes(salt, SALT_LEN); 

    pass = argv[6]; 
    printf("Test print of pass: %s\n", pass); 
    PKCS5_PBKDF2_HMAC_SHA1(pass, strlen(pass), NULL, 0, ITERATION, SHA1_LEN, out); 

    printf("PASSWORD ENCRYPT: "); 
    printf("%s\n", out); 

    unsigned char *myCipher; 

    myCipher = aes_gcm_encrypt(buff, size, myCipher, out); 

    //printf("%s\n", myCipher); 
    fclose(fp); 

    fp = fopen(argv[4], "w+"); 
    if (fp == NULL) 
    { 
     errnum = errno; 
     fprintf(stderr, "Value of errno: %d\n", errno); 
     perror("error printed by perror"); 
     fprintf(stderr, "Error opening the file: %s\n", strerror(errnum)); 
    } 

    fputs(myCipher, fp); 

    printf("CIPHER TEXT: %s\n", myCipher); 

    printf("\n"); 
    fclose(fp); 


    return 0; 
} 

這裏是dec.c(解密)

#include <stdio.h> 
#include <errno.h> 
#include <string.h> 
#include <stdlib.h> 
#include <openssl/bio.h> 
#include <openssl/evp.h> 


static const unsigned char gcm_iv[] = { 
    0x99, 0xaa, 0x3e, 0x68, 0xed, 0x81, 0x73, 0xa0, 0xee, 0xd0, 0x66, 0x84 
}; 

unsigned char * aes_gcm_decrypt(unsigned char *pt, long size, unsigned char *myPlainText, unsigned char *out) 
{ 
    EVP_CIPHER_CTX *ctx; 
    int outlen, tmplen, rv; 
    unsigned char outbuf[1024]; 
    //printf("AES GCM Derypt:\n"); 
    //printf("Ciphertext:\n"); 
    //BIO_dump_fp(stdout, pt, size); 
    ctx = EVP_CIPHER_CTX_new(); 
    /* Select cipher */ 
    EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); 
    /* Set IV length, omit for 96 bits */ 
    // EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, sizeof(gcm_iv), NULL); 
    /* Specify key and IV */ 
    EVP_DecryptInit_ex(ctx, NULL, NULL, out, gcm_iv); 

    /* Decrypt plaintext */ 
    EVP_DecryptUpdate(ctx, outbuf, &outlen, pt, sizeof(pt)); 
    /* Output decrypted block */ 
    // printf("Plaintext:\n"); 
    //BIO_dump_fp(stdout, outbuf, size); 

    rv = EVP_DecryptFinal_ex(ctx, outbuf, &outlen); 
    EVP_CIPHER_CTX_free(ctx); 
    return myPlainText = outbuf; 

} 

    extern int errno; 

int main(int argc, char **argv) 
{ 

    int ITERATION = 10000; 
    FILE * fp; 
    int errnum; 
    long size; 
    unsigned char *pass; 
    int len; 
    pass = argv[6]; 


    fp = fopen(argv[2], "a+"); 
    if (fp == NULL) 
    { 
     errnum = errno; 
     fprintf(stderr, "Value of errno: %d\n", errno); 
     perror("error printed by perror"); 
     fprintf(stderr, "Error opening the file: %s\n", strerror(errnum)); 
    } 

    fseek(fp, 0, SEEK_END); 
    size = ftell(fp); 
    fseek(fp, 0, SEEK_SET); 

    unsigned char * buff; 
    buff = (unsigned char*) malloc(sizeof(unsigned char)*size + 1); 
    memset(buff, '\0', sizeof(unsigned char)*size + 1); 
    fread(buff, 1, size, fp); 

    int SHA1_LEN = 30; 
    unsigned char* out = (unsigned char*)calloc(SHA1_LEN, sizeof(unsigned char)); 

    pass = argv[6]; 
    printf("Test print of pass: %s\n", pass); 
    PKCS5_PBKDF2_HMAC_SHA1(pass, strlen(pass), NULL, 0, ITERATION, SHA1_LEN, out); 

    printf("PASSWORD ENCRYPT: "); 
    printf("%s\n", out); 

    unsigned char *myPlainText; 

    myPlainText = aes_gcm_decrypt(buff, size, myPlainText, out); 
    fclose(fp); 

    fp = fopen(argv[4], "w+"); 
    if (fp == NULL) 
    { 
     errnum = errno; 
     fprintf(stderr, "Value of errno: %d\n", errno); 
     perror("error printed by perror"); 
     fprintf(stderr, "Error opening the file: %s\n", strerror(errnum)); 
    } 

    fputs(myPlainText, fp); 

    printf("PLAINTEXT: %s\n", myPlainText); 
    printf("\n"); 
    fclose(fp); 


    return 0; 
} 

回答

1

沒有SSL的詳細瞭解我的猜測是,這些調用

EVP_EncryptUpdate(ctx, outbuf, &outlen, pt, sizeof(pt));

EVP_DecryptUpdate(ctx, outbuf, &outlen, pt, sizeof(pt));

應該具有pt指向的大小而不是指針的大小。

EVP_EncryptUpdate(ctx, outbuf, &outlen, pt, ptlen);

EVP_DecryptUpdate(ctx, outbuf, &outlen, pt, ptlen);

其中ptlen是緩衝角點大小。

看着openssl manual證實了我的猜測:

EVP_EncryptUpdate()從緩衝區加密INL字節寫入加密版本出來。可以多次調用該函數來加密連續的數據塊。寫入的數據量取決於加密數據的塊對齊方式:因此寫入的數據量可能是從零字節到(inl + cipher_block_size - 1)的任何值,因此out應該包含足夠的空間。寫入的實際字節數放在outl中。

EVP_DecryptInit_ex(),EVP_DecryptUpdate()和EVP_DecryptFinal_ex()是相應的解密操作。如果啓用了填充並且最終塊格式不正確,則EVP_DecryptFinal()將返回錯誤代碼。參數和限制與加密操作相同,只是如果啓用了填充,傳遞給EVP_DecryptUpdate()的解密數據緩衝區應該有足夠的空間用於(inl + cipher_block_size)字節,除非密碼塊大小爲1,在這種情況下,inl字節是sufficien

+0

哦,男人,謝謝你! strlen(pt)馬上修復它。 – user3622460