加密/解密文件libgcrypt

时间:2015-09-07 20:33:17

标签: c encryption cryptography

我一直在努力了解如何正确使用libgcrypt并尽力打出一些代码。然而,我正在尝试使用上述库加密(AES 256)并解密文件。用户将文件名键入为命令行参数。加密文件将保存为第二个文件(output.txt)。然后,我想解密文件以确保我的结果是正确的。每次运行程序时,我生成的密钥都有一些外来字符,生成的输出文件是空白的。我正确使用了派生函数吗?我只是错误地解密文件?我提前为我可怕的代码道歉。

#include <stdio.h>
#include <gcrypt.h>
#include <time.h>
#include <sys/stat.h>
//#define GCRY_CIPHER_AES256
//#define GCRY_KDF_PBKDF2
void intitializeLibrary();

int main(int argc, char **argv)
{
if(argc ==2){
    char *filename = argv[1];
    printf("The file you've requested to be encrypted is %s \n", filename);
    FILE *ifp, *ifpout;
    char *mode ="r";

    ifp = fopen(filename, mode);
    ifpout = fopen("output.txt", "w");
    if (ifp == NULL || ifpout == NULL){
        fprintf(stderr, "Can't open file! \n");
        exit(1);
    } else{
        intitializeLibrary();
        struct stat st;
        stat(filename, &st);
        int size = st.st_size;

        char *encBuffer = malloc(32);       
        char str[100];
        char keybuffer[32];
        char* salt = "CNT5410";
        char* iv = "assignment222222";
        printf("Enter password: ");
        gcry_cipher_hd_t handle;
        gets(str);

        gpg_error_t err;
        err = gcry_kdf_derive(str, 100, GCRY_KDF_PBKDF2, GCRY_CIPHER_AES256, salt, 7, 3, 32, keybuffer); 
        if(err){
            printf("Error in PBKDF2 \n");
            exit(1);
        }

        puts(keybuffer);

        err = gcry_cipher_open(&handle, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_ECB, 0);
        if(err){
            printf("Error in cipheropen\n");
            exit(1);
        }

        err = gcry_cipher_setkey(handle, keybuffer, 32);
        if(err){
            printf("Error in cipheropen\n");
            exit(1);
        }

        err = gcry_cipher_setiv(handle, iv, 16);
        int bytes;
        while(!feof(ifp)){
            bytes = fread(encBuffer, 1, size, ifp);
            if(!bytes){
                break;
            }
            while(bytes < 32){
                encBuffer[bytes++] = 0x0;
                gcry_cipher_encrypt(handle, encBuffer, size, NULL,0);
                bytes = fwrite(encBuffer, size, 16, ifpout);
            }
        }

        gcry_cipher_close(handle);
        fclose(ifp);
        fclose(ifpout);

        struct stat st2;
        stat(filename, &st2);
        int size2 = st2.st_size;

        err = gcry_cipher_open(&handle, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_ECB, 0);
        if(err){
            printf("Error in cipheropen\n");
            exit(1);
        }

        err = gcry_cipher_setkey(handle, keybuffer, 32);
        if(err){
            printf("Error in cipheropen\n");
            exit(1);
        }

        err = gcry_cipher_setiv(handle, iv, 16);
    ifp = fopen("output.txt", mode);
    ifpout = fopen(filename, "w");
        while(!feof(ifp)){
            bytes = fread(encBuffer, 1, size2, ifp);
            if(!bytes){
                break;
            }
            while(bytes < 32){
                encBuffer[bytes++] = 0x0;
                gcry_cipher_encrypt(handle, encBuffer, size2, NULL,0);
                bytes = fwrite(encBuffer, 1, size2, ifpout);
            }
        }

        free(encBuffer);
        encBuffer = NULL;


    } 
}else{
    puts("Please enter one file to encrypt");
}
return 0;
}

void intitializeLibrary(){

    /* Version check should be the very first call because it
            makes sure that important subsystems are intialized. */
            if (!gcry_check_version (GCRYPT_VERSION)){
            fputs ("libgcrypt version mismatch\n", stderr);
            exit (2);
            }

              /* Disable secure memory.  */
              gcry_control (GCRYCTL_DISABLE_SECMEM, 0);

              /* ... If required, other initialization goes here.  */

              /* Tell Libgcrypt that initialization has completed. */
              gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);

              /* Disable secure memory.  */
              gcry_control (GCRYCTL_DISABLE_SECMEM, 0);

              /* ... If required, other initialization goes here.  */

              /* Tell Libgcrypt that initialization has completed. */
              gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
}

1 个答案:

答案 0 :(得分:1)

您假设密钥由可打印字符组成。它没有,它由字节(C / C ++中的char)组成,可以有任何值(0..255,或者,在你的情况下,如果是无符号,-128到127)。如果将它们打印到标准输出,则标准输出将使用当前配置的字符编码对这些字节进行解码并显示结果。所以这基本上显示了任何一种垃圾。所以这没问题;以十六进制打印出密钥,以了解密钥值。

对于错误,您将以文本模式而不是二进制模式打开文件。密文就像密钥一样,包含随机字节。您应该以二进制模式打开密文文件。或者,您可以将密文字节转换为十六进制或基数为64。

来自fopen手册页:

  

为了将文件作为二进制文件打开,模式字符串中必须包含“b”字符。这个附加的“b”字符可以附加在字符串的末尾(从而产生以下复合模式:“rb”,“wb”,“ab”,“r + b”,“w + b”,“a + b“)或插入字母和混合模式的”+“符号之间(”rb +“,”wb +“,”ab +“)。

尝试并了解十六进制和base 64等编码以及ASCII和UTF-8等字符编码。如果要执行任何类型的加密/解密,则需要这样做。