【Linux】C语言实现对文件的加密算法

news/2024/7/24 1:59:45 标签: linux, c语言, 算法

异或加密

解密方式是进行第二次加密后自动解密

#define BUF_SIZE (16384)    //16k
/**************************************************************
功能描述: 加密实现
输入参数: 
---------------------------------------------------------------
修改作者: 
修改日期: 
修改说明:新增
***************************************************************/
void log_encrypt(char *data, int dataLen, const char *key)
{
    int n = 0;
    //对data的每一个字符和key进行按位异或
    for(n = 0; n < dataLen; n++)
    {
        *data = *data ^ 0x09;
        data++;
    }
}

/**************************************************************
功能描述: log文件加密
输入参数: 
---------------------------------------------------------------
修改作者: 
修改日期: 
修改说明:新增
***************************************************************/
unsigned int log_encryptFile(char *srcFileName)
{
    char *key = "google";
    int  srcFd = -1;
    int  dstFd = -1;
    char *tmpBuf = NULL;
    int  tmpLen = 0;
    int  writLen = 0;

    log_printf("start: CountFile build date: %s, [%s, %d]\n", __DATE__, __FUNCTION__, __LINE__);

    if (!srcFileName)
    {
        log_printf("srcFileName err![%s, %d]\n", __FUNCTION__, __LINE__);
        return EXIT_FAILURE;
    }

    srcFd = open(srcFileName, O_RDWR);
    log_printf("srcFileName:[%s] fd:[%d]\n", srcFileName, srcFd);
    if (srcFd < 0)
    {
        log_printf("open src file failed! [err:%d:%s]\n", errno, strerror(errno));
        return EXIT_FAILURE;
    }

    log_printf("file size:[%d]\n", lseek(srcFd, 0, SEEK_END));
    lseek(srcFd, 0, SEEK_SET);

    tmpBuf = (char *)malloc(BUF_SIZE);
    if (!tmpBuf)
    {
        log_printf("malloc buf failed! [err:%d:%s]\n", errno, strerror(errno));
        close(srcFd);
        return EXIT_FAILURE;
    }

    while((tmpLen = read(srcFd, tmpBuf, BUF_SIZE)) > 0)
    {
        //加密数据
        log_encrypt(tmpBuf, tmpLen, key);
        //指针会到此包开始处
        lseek(srcFd, -tmpLen, SEEK_CUR);
        //写文件
        writLen = write(srcFd, tmpBuf, tmpLen);
        if (writLen < 0)
        {
            log_printf("write err,Error: %s\n", strerror(errno));
        }
    }

    close(srcFd);
    free(tmpBuf);

    log_printf("end: ok: [%s, %d]\n", __FUNCTION__, __LINE__);

    return EXIT_SUCCESS;
}

AES加密

AES的算法时间复杂度最低,256K时间如下:
在这里插入图片描述
在这里插入图片描述

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

#define BLOCK_SIZE 16
#define KEY_BIT 256
#define IV_SIZE BLOCK_SIZE
#define KEY_SIZE (KEY_BIT/8)
#define JIEMI_SWITCH		1	//解密开关
// Generate IV
unsigned char iv[IV_SIZE] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};

void file_encrypt(char* filename) {
    FILE* fp = fopen(filename, "rb");
    FILE* outfp = fopen("encrypted.tmp", "wb");
    if(fp == NULL) {
        printf("Can't open file.\n");
        return;
    }

    // Generate key
    unsigned char key[KEY_SIZE];
    SHA256((unsigned char*)"google", strlen("google"), key);

    EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
    if(EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv) != 1) {
        printf("Failed to initialize encryption.\n");
        return;
    }

    unsigned char data_block[BLOCK_SIZE];
    unsigned char encrypt_block[BLOCK_SIZE + EVP_MAX_BLOCK_LENGTH];
    int out_len;

    fseek(fp, 0, SEEK_END);
    long file_size = ftell(fp);
    fseek(fp, 0, SEEK_SET);

    unsigned char* buffer = (unsigned char*)malloc(file_size + EVP_MAX_BLOCK_LENGTH);
    fread(buffer, 1, file_size, fp);

    for(long i = 0; i < file_size; i += BLOCK_SIZE) {
        memcpy(data_block, buffer + i, BLOCK_SIZE);
        if(i + BLOCK_SIZE > file_size) {
            for(int j = file_size % BLOCK_SIZE; j < BLOCK_SIZE; ++j)
                data_block[j] = BLOCK_SIZE - (file_size % BLOCK_SIZE);
        }
        if(EVP_EncryptUpdate(ctx, encrypt_block, &out_len, data_block, BLOCK_SIZE) != 1) {
            printf("Failed to encrypt block.\n");
            return;
        }
        fwrite(encrypt_block, 1, out_len, outfp);
    }

    if(EVP_EncryptFinal_ex(ctx, encrypt_block, &out_len) != 1) {
        printf("Failed to finish encryption.\n");
        return;
    }
    fwrite(encrypt_block, 1, out_len, outfp);

    free(buffer);
    fclose(fp);
    fclose(outfp);
    rename("encrypted.tmp", filename);
    EVP_CIPHER_CTX_free(ctx);
}

void file_decrypt(char* filename) {
    FILE* fp = fopen(filename, "rb");
    FILE* outfp = fopen("decrypted.tmp", "wb");
    if(fp == NULL) {
        printf("Can't open file.\n");
        return;
    }

    // Generate key
    unsigned char key[KEY_SIZE];
    SHA256((unsigned char*)"google", strlen("google"), key);

    EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
    if(EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv) != 1) {
        printf("Failed to initialize decryption.\n");
        return;
    }

    unsigned char data_block[BLOCK_SIZE];
    unsigned char decrypt_block[BLOCK_SIZE + EVP_MAX_BLOCK_LENGTH];
    int out_len;

    fseek(fp, 0, SEEK_END);
    long file_size = ftell(fp);
    fseek(fp, 0, SEEK_SET);

    unsigned char* buffer = (unsigned char*)malloc(file_size + EVP_MAX_BLOCK_LENGTH);
    fread(buffer, 1, file_size, fp);

    for(long i = 0; i < file_size; i += BLOCK_SIZE) {
        memcpy(data_block, buffer + i, BLOCK_SIZE);
        if(EVP_DecryptUpdate(ctx, decrypt_block, &out_len, data_block, BLOCK_SIZE) != 1) {
            printf("Failed to decrypt block.\n");
            return;
        }
        fwrite(decrypt_block, 1, out_len, outfp);
    }

    if(EVP_DecryptFinal_ex(ctx, decrypt_block, &out_len) != 1) {
        printf("Failed to finish decryption.\n");
        return;
    }
    fwrite(decrypt_block, 1, out_len, outfp);

    free(buffer);
    fclose(fp);
    fclose(outfp);
    rename("decrypted.tmp", filename);
    EVP_CIPHER_CTX_free(ctx);
}

int main(int argc, char **argv) {
    if(argc != 2) {
        printf("Usage: %s <file>\n", argv[0]);
        return 1;
    }

    char *srcFileName = argv[1];
#if JIEMI_SWITCH
    file_encrypt(srcFileName);
    printf("加密成功\n");
#else
    file_decrypt(srcFileName);
    printf("解密成功\n");
#endif
    return 0;
}

简单加密

它只是对输入文件进行简单的异或加密操作,使用一个字符串作为密钥
时间复杂度较高,对257K的文件加密,要33s
在这里插入图片描述

/**************************************************************
修改作者:wangjj
修改日期:9/25/2023
修改说明:新增
***************************************************************/
unsigned int log_encryptFile(char *srcFileName)
{
    char *key = "hualaixiaofang";
    int keyLen = strlen(key);
    int ch;
    int i = 0;

    log_printf("encrytFile begin [%s,%d\n]", __FUNCTION__, __LINE__);

    if (!srcFileName || !key)
    {
        log_printf("param err! error:%s [%s,%d]\n", strerror(errno), __FUNCTION__, __LINE__);
        return EXIT_FAILURE;
    }	

    FILE *file = fopen(srcFileName, "rb+");
    if (file == NULL)
    {
        log_printf("open file failed!!, error:%s [%s,%d]\n", strerror(errno), __FUNCTION__, __LINE__);
        return EXIT_FAILURE;
    }

    while ((ch = fgetc(file)) != EOF)
    {
        // 对每个字符和key的对应字符进行加密操作
        ch = ch + key[i];
        
        // 将加密后的字符写回文件
        fseek(file, -1, SEEK_CUR);
        fputc(ch, file);
        
        // 更新key的位置
        i = (i + 1) % keyLen;
    }
    log_printf("encrytFile end [%s,%d\n]", __FUNCTION__, __LINE__);
    fclose(file);
}

编译方式

gcc -o decrypt_program_jiemi AES_encrypt.c -lcrypto

mbedtls加密


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mbedtls/aes.h"

#define KEY_SIZE 32 // 256位密钥
#define BLOCK_SIZE 16 // 128位分组

int log_encryptFile(const char* input_file) {
    
    // 打开输入文件
    FILE* input = fopen(input_file, "rb");
    if (input == NULL) {
        printf("无法打开输入文件\n");
        return -1;
    }
    const unsigned char key[KEY_SIZE] = "wjj";
    // 计算输入文件大小
    fseek(input, 0, SEEK_END);
    long input_size = ftell(input);
    fseek(input, 0, SEEK_SET);

    // 创建输出缓冲区
    unsigned char* output = (unsigned char*)malloc(input_size);
    if (output == NULL) {
        printf("内存分配失败\n");
        fclose(input);
        return -1;
    }

    // 初始化加密上下文
    mbedtls_aes_context ctx;
    mbedtls_aes_init(&ctx);
    mbedtls_aes_setkey_enc(&ctx, key, KEY_SIZE * 8);

    // 加密文件内容
    unsigned char input_block[BLOCK_SIZE];
    unsigned char output_block[BLOCK_SIZE];
    size_t offset = 0;
    size_t read_bytes;
    while ((read_bytes = fread(input_block, 1, BLOCK_SIZE, input)) > 0) {
        mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, input_block, output_block);
        memcpy(output + offset, output_block, read_bytes);
        offset += read_bytes;
    }

    // 关闭文件和释放资源
    fclose(input);
    mbedtls_aes_free(&ctx);

    // 打开输入文件,以写入方式覆盖原内容
    input = fopen(input_file, "wb");
    if (input == NULL) {
        printf("无法打开输入文件\n");
        free(output);
        return -1;
    }

    // 将加密后的内容写入输入文件
    fwrite(output, 1, input_size, input);

    // 关闭文件和释放资源
    fclose(input);
    free(output);

    printf("文件加密完成\n");

    return 0;
}

int log_decryptFile(const char* input_file) {
    // 打开输入文件
    FILE* input = fopen(input_file, "rb");
    if (input == NULL) {
        printf("无法打开输入文件\n");
        return -1;
    }
    const unsigned char key[KEY_SIZE] = "wjj";
    // 计算输入文件大小
    fseek(input, 0, SEEK_END);
    long input_size = ftell(input);
    fseek(input, 0, SEEK_SET);

    // 创建输出缓冲区
    unsigned char* output = (unsigned char*)malloc(input_size);
    if (output == NULL) {
        printf("内存分配失败\n");
        fclose(input);
        return -1;
    }

    // 初始化解密上下文
    mbedtls_aes_context ctx;
    mbedtls_aes_init(&ctx);
    mbedtls_aes_setkey_dec(&ctx, key, KEY_SIZE * 8);

    // 解密文件内容
    unsigned char input_block[BLOCK_SIZE];
    unsigned char output_block[BLOCK_SIZE];
    size_t offset = 0;
    size_t read_bytes;
    while ((read_bytes = fread(input_block, 1, BLOCK_SIZE, input)) > 0) {
        mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_DECRYPT, input_block, output_block);
        memcpy(output + offset, output_block, read_bytes);
        offset += read_bytes;
    }

    // 关闭文件和释放资源
    fclose(input);
    mbedtls_aes_free(&ctx);

    // 打开输入文件,以写入方式覆盖原内容
    input = fopen(input_file, "wb");
    if (input == NULL) {
        printf("无法打开输入文件\n");
        free(output);
        return -1;
    }

    // 将解密后的内容写入输入文件
    fwrite(output, 1, input_size, input);

    // 关闭文件和释放资源
    fclose(input);
    free(output);

    printf("文件解密完成\n");

    return 0;
}
// 编译方式:gcc -o decrypt-jiami AES_encrypt.c -lmbedtls -lmbedcrypto -lmbedx509
int main(int argc, char **argv) {
    if(argc != 2) {
        printf("Usage: %s <file>\n", argv[0]);
        return 1;
    }

    char *srcFileName = argv[1];

    if (log_encryptFile(srcFileName) != 0) {
        printf("加密文件失败\n");
        return -1;
    }
    printf("文件加密完成\n");
 

#if 0
    if (log_decryptFile(srcFileName) != 0) {
        printf("解密文件失败\n");
        return -1;
    }

   printf("解密成功\n");
#endif 
    return 0;
}

编译方式

gcc -o decrypt-jiami AES_encrypt.c -lmbedtls -lmbedcrypto -lmbedx509

http://www.niftyadmin.cn/n/5053401.html

相关文章

java - 包装类

目录 前言 一 什么是包装类? 1.获取包装类的两种方式(了解)(已经淘汰) 2.两种方式获取对象的区别(掌握) 3.自动装箱&&自动装箱 4.Integer常用方法 总结 前言 大家好,今天给大家讲解一下包装类 一 什么是包装类? 在Java中&#xff0c;每个基本数据类型都有对应…

MYSQL操作命令大全

mysql命令大全 命令说明示例mysql -h ip -P port -u user -p password远程连接mysqlmysql -h192.168.0.201 -P3306 -uroot -p123mysql -u user -p password本地连接mysqlmysql -uroot -p123select * from information_schema.TABLES where TABLE_SCHEMA(select database()) 查…

AI 大模型

随着人工智能技术的迅猛发展&#xff0c;AI 大模型逐渐成为推动人工智能领域提升的关键因素&#xff0c;大模型已成为了引领技术浪潮研究和应用方向。大模型即大规模预训练模型&#xff0c;通常是指那些在大规模数据上进行了预训练的具有庞大规模和复杂结构的人工智能模型&…

睿趣科技:新手抖音开店卖什么产品好

抖音已经成为了一款年轻人热爱的社交媒体应用&#xff0c;同时也成为了一种全新的电商平台。对于新手来说&#xff0c;抖音开店卖什么产品是一个备受关注的问题。在这篇文章中&#xff0c;我们将探讨一些适合新手的产品选择&#xff0c;帮助他们在抖音上开店获得成功。 流行时尚…

API 接口参数签名的几种方案

API 接口参数签名的几种方案 在涉及跨系统接口调用时&#xff0c;我们容易碰到以下安全问题&#xff1a; 请求身份被伪造。请求参数被篡改。请求被抓包&#xff0c;然后重放攻击。 本篇将根据假设的需求场景&#xff0c;循序渐进讲明白跨系统接口调用时必做的几个步骤&#…

竞赛 基于视觉的身份证识别系统

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于机器视觉的身份证识别系统 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f9ff; 更多资料, 项目分享&#xff1a; https://gitee.com/dancheng-sen…

代码随想录 第8章 二叉树

1、理论知识 &#xff08;1&#xff09;、满二叉树 如果一棵二叉树只有度为0的节点和度为2的节点&#xff0c;并且度为0的节点在同一层上&#xff0c;则这棵二叉树为满二叉树。 &#xff08;2&#xff09;、完全二叉树 除了底层节点可能没有填满&#xff0c;其余每层的节点…

vuejs - - - - - 递归组件的实现

递归组件的实现 1. 需求描述&#xff1a;2. 效果图&#xff1a;3. 代码3.1 封装组件代码3.2 父组件使用 1. 需求描述&#xff1a; 点击添加行&#xff0c;增加一级目录结构当类型为object or array时&#xff0c;点击右侧➕&#xff0c;增加子集点击右侧&#x1f6ae;&#x…