尝试使用C和opensll-lib加密目录中的文件时出现分段错误

时间:2017-01-17 13:05:10

标签: c encryption

我尝试在C中创建一个程序,使用openssl-lib加密目录中的所有文件。我用ntfw()读取目录并将文件名传递给处理函数handleCryptProcess()。功能执行波纹管程序。

  1. 创建一个临时文件来保存密文。
  2. 加密明文并将结果输出到cyphertext文件中。
  3. 删除纯文本文件。
  4. 将密文文件重命名为原始文件。
  5. 我使用RSA公钥来加密文件。

    我的问题是,当我的文件夹包含多个文件时,我会收到细分错误。这与处理程序功能有关。我想,上述一个或多个程序无法有效处理内存。

    当我的文件夹包含 ONLY ONE 文件时,该程序成功

    Bellow是我的处理函数:

    #include "crypt.h"
    
    /**
     * - First we generate the filepath of our output file with getCyphertextFilePath().
     * - The we check (cryptFlag) and determine if we want to encrypt or decrypt the file.
     * - encryptRSAFile() tries to encrypt the file under (fpath).
     *   decryptRSAFile() tries to decrypt the file under (fpath).
     * - We delete the original file using unlink().
     * - Lastly, rename the new file back to original filename with rename().
     */
    int handleCryptProcess(const char *fpath, const en_de_crypt_flag cryptFlag) {
        int status;
        char *new_fpath = NULL; /* Hold the file path of our output file */
    
        status = getOutputFilePath(fpath, &new_fpath);
        if (status == -1) {
            return -1; /* Could not get the output filepath. */
        }
    
        if (cryptFlag == ENCRYPT) { /* We want to encrypt our file. */
            status = encryptRSAFile(fpath, new_fpath);
        } else { /* We want to decrypt our file. */
            status = decryptRSAFile(fpath, new_fpath);
        }   
        if (status == -1) {
            return -1; /* Failed to encrypt/decrypt fpath. */
        }
    
        status = unlink(fpath); /* Delete the original file. */
        if (status == -1) {
            return -1; /* Failed to delete original fpath. */
        }
        status = rename(new_fpath, fpath); /* Rename our file. */
        if (status == -1) {
            return -1; /* Failed to rename back to original fpath. */
        }
        return 0; /* File encrypted/decrypted successfully. */
    }
    

    这是我用来创建密文的那个:

    #include "crypt.h"
    
    /**
     * We use RSA asymmetric cryptography to create our cyphertext.
     * The public key was passed to (rsaPubKey) when we initialized it
     * in main() with publicRSATextKeyToStruct().
     * (fpath) is the file we want to encrypt.
     * (cyphertext_fpath) is our cyphertext.
     */
    int encryptRSAFile(const char *fpath, const char *cyphertext_fpath) {
        FILE *fin, *fout;
    
        /**
         * Open the plaintext file we want to encrypt.
         */
        fin = fopen(fpath, "rb");
        if (fin == NULL) {
            return -1;
        }
    
        /**
         * Create a cyphertext file for writing to.
         */
        fout = fopen(cyphertext_fpath, "wb");
        if (fout == NULL) {
            return -1;
        }
    
        /**
         * The EVP_PKEY_new() function allocates an empty EVP_PKEY
         * structure which is used by OpenSSL to store private keys. 
         */
        EVP_PKEY *pkey = EVP_PKEY_new();
    
        EVP_CIPHER_CTX ctx; /* Cipher contex ctx. */
        unsigned char buffer[RSA_KEY_SIZE]; /* Buffer that holds out plaintext. */
        unsigned char buffer_out[RSA_KEY_SIZE + EVP_MAX_IV_LENGTH]; /* Buffer that holds the cyphertext. */
        size_t len;
        int len_out;
    
        /**
         * ek is an array of buffers where the public key encrypted secret key will be written, 
         * each buffer must contain enough room for the corresponding encrypted key.
         * That is ek[i] must have room for EVP_PKEY_size(pubk[i]) bytes
         */
        unsigned char *ek = NULL;
        int eklen;
        uint32_t eklen_n;
        unsigned char iv[EVP_MAX_IV_LENGTH]; /* Buffer where the generated IV is written to */
    
    
        if (!EVP_PKEY_assign_RSA(pkey, rsaPubKey)) {
            return -1;
        }
    
        EVP_CIPHER_CTX_init(&ctx); /* Initialize a new context. */
        ek = malloc(EVP_PKEY_size(pkey));
    
        /**
         * EVP_SealInit() initializes a cipher context (ctx) for encryption 
         * with cipher type using a random secret key and (iv).
         * Cipher type we use is AES 256.
         * The secret key is encrypted using our public key (pkey).
         */
        if (!EVP_SealInit(&ctx, EVP_aes_256_cbc(), &ek, &eklen, iv, &pkey, 1)) {
            return 2;
        }
    
        eklen_n = htonl(eklen);
        if (fwrite(&eklen_n, sizeof eklen_n, 1, fout) != 1) {
            return 3;
        }
        if (fwrite(ek, eklen, 1, fout) != 1) {
            return 4;
        }
        if (fwrite(iv, EVP_CIPHER_iv_length(EVP_aes_256_cbc()), 1, fout) != 1) {
            return 5;
        }
    
        while ((len = fread(buffer, 1, sizeof buffer, fin)) > 0) {
            if (!EVP_SealUpdate(&ctx, buffer_out, &len_out, buffer, len)) {
                return 6;
            }
    
            if (fwrite(buffer_out, len_out, 1, fout) != 1) {
                return 7;
            }
        }
    
        if (ferror(fin)) {
            return 8;
        }
    
        if (!EVP_SealFinal(&ctx, buffer_out, &len_out)) {
            return 9;
        }
    
        if (fwrite(buffer_out, len_out, 1, fout) != 1) {
            return 10;
        }
    
        EVP_PKEY_free(pkey);
        free(ek);
        fclose(fin);
        fclose(fout);
        return 0;
    }
    

    这是否与return值有关?也许是我如何检查错误状态。但是我无法理解,openssl文档在这方面并不是很支持。

    更新

    为了更清楚地了解发生了什么,我发布了一个例子。

    假设我们有两个文件。

    • File1.ext
    • File2.ext

    程序开始,读取File1对其进行加密并转到File2。

    在File2上,我的代码在加密程序的以下情况下中断:

    fwrite(ek, eklen, 1, fout) != 1
    

    然后,我得到了一个分段错误。这并不总是发生在第二个文件中。如果可能发生在第三个之后,但永远不会发生。

    如果我有三个文件,我可能会加密第一个文件,第二个文件会破坏程序,第三个文件会破坏程序。

0 个答案:

没有答案