简体   繁体   English

加密/解密文件libgcrypt

[英]Encrypting/Decrypting Files libgcrypt

I've struggled to understand how to correctly use libgcrypt and have done my best to punch out some code. 我一直在努力了解如何正确使用libgcrypt,并竭尽所能编写一些代码。 Nevertheless, I'm attempting to encrypt (AES 256) and decrypt a file utilizing the aforementioned library. 不过,我正在尝试使用上述库对文件进行加密(AES 256)和解密。 The user will type the file name as a command-line argument. 用户将输入文件名作为命令行参数。 The encrypted file will be saved as a second file (output.txt). 加密的文件将另存为第二个文件(output.txt)。 Then, I want to decrypt the file to ensure that my result was correct. 然后,我想解密文件以确保结果正确。 Each time I run the program, the key that I generate has some foreign characters and the output file generated is blank. 每次运行该程序时,生成的密钥都有一些外来字符,并且生成的输出文件为空白。 Am I using the derive function correctly? 我是否正确使用了派生函数? And am I just decrypting the file incorrectly? 而且我是不正确地解密文件吗? I apologize in advance for my terrible code. 我为我的糟糕代码事先表示歉意。

#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);
}

You are assuming that the key consists of printable characters. 您假设键由可打印字符组成。 It does not, it consists of bytes ( char in C/C++) that may have any value (0..255 or, in your case, if unsigned, -128 to 127). 它没有,它由字节(在C / C ++中为char )组成,可以具有任何值(0..255,或者,如果是无符号,则为-128至127)。 If you print them to standard output then the standard output will decode these bytes using the currently configured character encoding and show the result. 如果将它们打印到标准输出,则标准输出将使用当前配置的字符编码对这些字节进行解码,并显示结果。 So that basically shows any kind of garbage. 这样基本上可以显示出任何形式的垃圾。 So this is no problem; 所以这没问题; print out the key in hexadecimals to get an idea of the key value. 以十六进制打印密钥以了解密钥值。

As for the error, you are opening your files in text mode instead of binary mode. 对于错误,您正在以文本模式而不是二进制模式打开文件。 Ciphertext, just like the key, contains of random bytes. 密文和密钥一样,包含随机字节。 You should open your ciphertext files in binary mode. 您应该以二进制模式打开密文文件。 Alternatively you can convert the ciphertext bytes to hexadecimals or base 64. 或者,您可以将密文字节转换为十六进制或基数64。

From the fopen manual pages: fopen手册页:

In order to open a file as a binary file, a "b" character has to be included in the mode string. 为了将文件打开为二进制文件,必须在模式字符串中包含“ b”字符​​。 This additional "b" character can either be appended at the end of the string (thus making the following compound modes: "rb", "wb", "ab", "r+b", "w+b", "a+b") or be inserted between the letter and the "+" sign for the mixed modes ("rb+", "wb+", "ab+"). 可以在字符串的末尾附加这个附加的“ b”字符​​(从而进行以下复合模式:“ rb”,“ wb”,“ ab”,“ r + b”,“ w + b”,“ a + b”)或插入字母和“ +”号之间的混合模式(“ rb +”,“ wb +”,“ ab +”)。

Try and learn about encoding such as hexadecimals and base 64 as well as character encoding such as ASCII and UTF-8. 尝试学习有关十六进制和64位基数的编码以及ASCII和UTF-8等字符编码的信息。 You need that if you want to perform any kind of encryption/decryption. 如果您想执行任何类型的加密/解密,则需要此选项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM