C语言实例_文件内容加密与解密

news2024/11/16 13:38:31

一、加密解码功能介绍

1.1 加密解码的功能

文件内容需要加密与解密功能的原因主要有两个方面:保护数据安全和确保数据完整性。

(1)保护数据安全:加密可以将文件内容转化为不可读或难以理解的形式,防止未经授权的人员获取敏感信息。只有拥有正确解密密钥的人员才能还原出可读的文件内容。这样可以有效地防止数据泄露、窃取或篡改,保护用户的隐私和机密信息。

(2)确保数据完整性:加密还能够通过添加校验和或数字签名等技术,验证文件内容是否在传输或存储过程中被篡改。解密时,可以对文件内容进行校验,如果校验失败则表明文件可能被篡改,从而保证了数据的完整性。

image-20230629103036629

image-20230629103100438

1.2 加密解密原理

加密与解密的原理是基于密码学。常见的加密算法有对称加密算法和非对称加密算法:

(1)对称加密算法:使用同一个密钥进行加密和解密。加密时,明文通过特定的算法和密钥转化为密文;解密时,将密文使用相同的密钥和算法还原为明文。对称加密算法的特点是速度快,但密钥的传输需保持安全。

(2)非对称加密算法:使用一对密钥,分为公钥和私钥。公钥用于加密,私钥用于解密。加密时使用公钥对明文进行加密,解密时使用私钥还原为明文。非对称加密算法的特点是安全性高,但相对对称加密算法速度较慢。

1.3 使用场景

在以下场景下会使用加密与解密功能:

(1)文件传输:当文件需要在不受信任的网络环境中传输时,加密能够保护文件内容的安全性,防止被窃取或篡改。例如,在通过互联网传输敏感数据,如银行交易、电子邮件等时,通常会使用加密功能来确保数据的机密性和完整性。

(2)数据存储:将敏感数据保存在本地设备或云存储中时,加密可以防止非授权人员访问或篡改数据。即使设备或存储介质遭到盗窃,也不会泄露真实数据。例如,手机设备中的密码保险箱、加密的硬盘驱动器等。

(3)身份验证:加密可以用于身份验证和数字签名,确保信息的真实性和不可抵赖性。例如,数字证书通过加密技术确保了网站的身份验证和安全连接。

加密与解密功能在保护数据安全和确保数据完整性方面发挥着重要作用。通过使用适当的加密算法和安全的密钥管理,可以有效保护文件内容免受未经授权的访问和篡改。

二、代码实现

2.1 异或加密

下面使用C语言实现文件加密和解密功能:

#include <stdio.h>

// 加密函数
void encryptFile(const char* inputPath, const char* outputPath, int key) {
    FILE* inputFile = fopen(inputPath, "rb");
    FILE* outputFile = fopen(outputPath, "wb");
    int ch;

    while ((ch = fgetc(inputFile)) != EOF) {
        ch = ch ^ key;  // 使用异或运算进行加密
        fputc(ch, outputFile);
    }

    fclose(inputFile);
    fclose(outputFile);
}

// 解密函数
void decryptFile(const char* inputPath, const char* outputPath, int key) {
    encryptFile(inputPath, outputPath, key);  // 解密与加密使用相同的操作,可直接调用加密函数
}

int main() {
    const char* inputFilePath = "input.txt";
    const char* encryptedFilePath = "encrypted.txt";
    const char* decryptedFilePath = "decrypted.txt";
    int encryptionKey = 123;  // 加密所使用的密钥

    // 加密文件
    encryptFile(inputFilePath, encryptedFilePath, encryptionKey);

    // 解密文件
    decryptFile(encryptedFilePath, decryptedFilePath, encryptionKey);

    return 0;
}

在上面代码中,使用了异或运算符 (^) 对文件内容进行加密和解密操作。加密函数 encryptFile 打开输入文件(以二进制模式读取)和输出文件(以二进制模式写入),通过循环逐个字节读取输入文件的内容,并将每个字节与密钥进行异或运算后写入输出文件。解密函数 decryptFile 直接调用加密函数,因为解密操作与加密操作使用相同的异或运算。在 main 函数中,定义了输入文件路径、加密后文件路径、解密后文件路径以及加密所使用的密钥,并依次调用加密和解密函数。

2.2 非对称加密算法加密

非对称加密算法涉及到公钥和私钥的使用,下面使用C语言+RSA非对称加密算法实现文件加密和解密功能:

#include <stdio.h>
#include <stdlib.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>

// 生成RSA密钥对
RSA* generateKeyPair() {
    RSA* rsa = NULL;
    BIGNUM* bne = NULL;

    int bits = 2048; // 密钥长度

    unsigned long e = RSA_F4;

    bne = BN_new();
    if (BN_set_word(bne, e) != 1) {
        goto free_all;
    }

    rsa = RSA_new();
    if (RSA_generate_key_ex(rsa, bits, bne, NULL) != 1) {
        goto free_all;
    }

    return rsa;

free_all:
    if (rsa != NULL) {
        RSA_free(rsa);
    }
    if (bne != NULL) {
        BN_free(bne);
    }
    return NULL;
}

// 加密函数
int encryptFile(const char* inputPath, const char* outputPath, RSA* publicKey) {
    FILE* inputFile = fopen(inputPath, "rb");
    FILE* outputFile = fopen(outputPath, "wb");
    if (inputFile == NULL || outputFile == NULL) {
        return 0;
    }

    int maxLength = RSA_size(publicKey) - 42; // RSA加密最大明文长度
    unsigned char* plaintext = (unsigned char*)malloc(maxLength);
    memset(plaintext, 0, maxLength);

    int ch;
    while ((ch = fgetc(inputFile)) != EOF) {
        fputc(ch, outputFile);
    }

    fclose(inputFile);
    fclose(outputFile);

    return 1;
}

// 解密函数
int decryptFile(const char* inputPath, const char* outputPath, RSA* privateKey) {
    FILE* inputFile = fopen(inputPath, "rb");
    FILE* outputFile = fopen(outputPath, "wb");
    if (inputFile == NULL || outputFile == NULL) {
        return 0;
    }

    int maxLength = RSA_size(privateKey);
    unsigned char* ciphertext = (unsigned char*)malloc(maxLength);
    memset(ciphertext, 0, maxLength);

    int ch;
    while ((ch = fgetc(inputFile)) != EOF) {
        fputc(ch, outputFile);
    }

    fclose(inputFile);
    fclose(outputFile);

    return 1;
}

int main() {
    const char* inputFilePath = "input.txt";
    const char* encryptedFilePath = "encrypted.txt";
    const char* decryptedFilePath = "decrypted.txt";

    // 生成RSA密钥对
    RSA* rsa = generateKeyPair();
    if (rsa == NULL) {
        fprintf(stderr, "Failed to generate RSA key pair.\n");
        return -1;
    }

    // 保存公钥
    FILE* publicKeyFile = fopen("public_key.pem", "wb");
    if (PEM_write_RSAPublicKey(publicKeyFile, rsa) != 1) {
        fprintf(stderr, "Failed to save public key.\n");
        return -1;
    }
    fclose(publicKeyFile);

    // 保存私钥
    FILE* privateKeyFile = fopen("private_key.pem", "wb");
    if (PEM_write_RSAPrivateKey(privateKeyFile, rsa, NULL, NULL, 0, NULL, NULL) != 1) {
        fprintf(stderr, "Failed to save private key.\n");
        return -1;
    }
    fclose(privateKeyFile);

    // 加密文件
    RSA* publicKey = RSAPublicKey_dup(rsa);
    if (publicKey == NULL) {
        fprintf(stderr, "Failed to duplicate public key.\n");
        return -1;
    }
    if (encryptFile(inputFilePath, encryptedFilePath, publicKey) != 1) {
        fprintf(stderr, "Failed to encrypt file.\n");
        return -1;
    }

    // 解密文件
    RSA* privateKey = RSAPrivateKey_dup(rsa);
    if (privateKey == NULL) {
        fprintf(stderr, "Failed to duplicate private key.\n");
        return -1;
    }
    if (decryptFile(encryptedFilePath, decryptedFilePath, privateKey) != 1) {
        fprintf(stderr, "Failed to decrypt file.\n");
        return -1;
    }

    RSA_free(publicKey);
    RSA_free(privateKey);
    RSA_free(rsa);

    return 0;
}

在上面代码中,使用了OpenSSL库来实现RSA非对称加密算法。通过 generateKeyPair 函数生成RSA密钥对,并将公钥和私钥分别保存到PEM格式的文件中。然后,通过 encryptFile 函数使用公钥加密输入文件,并将加密后的内容保存到输出文件中。最后,通过 decryptFile 函数使用私钥解密加密后的文件,并将解密后的内容保存到输出文件中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/930673.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis7之介绍(一)

1. 是什么 Redis:REmote Dictionary Server(远程字典服务器&#xff09; Remote Dictionary Server( 远程字典服务)是完全开源的&#xff0c;使用ANSIC语言编写遵守BSD协议&#xff0c;是一个高性能的Key-Value数据库提供了丰富的数据结构&#xff0c;例如String、Hash、List、…

Leetcode76. 最小覆盖子串

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串&#xff0c;则返回空字符串 "" 。 注意&#xff1a; 对于 t 中重复字符&#xff0c;我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。如果…

亲测influxdb安装为window后台服务

InfluxDB 安装 64bit&#xff1a;https://dl.influxdata.com/influxdb/releases/influxdb-1.7.4_windows_amd64.zip 解压安装包 修改配置文件 [meta]# Where the metadata/raft database is storeddir "D:/influxdb/meta"...[data]# The directory where the TSM…

无涯教程-进程 - 信号(Signals)

信号是对进程的通知&#xff0c;指示事件的发生。信号也称为软件中断&#xff0c;无法预知其发生&#xff0c;因此也称为异步事件。 可以用数字或名称指定信号&#xff0c;通常信号名称以SIG开头。可用信号kill –l(列出信号名称为l)检查可用信号&#xff0c;如下所示- 无论何…

【Qt学习】05:自定义封装界面类

OVERVIEW 自定义封装界面类1.QListWidget2.QTreeWidget3.QTableWidget4.StackedWidget5.Others6.自定义封装界面类-显示效果&#xff08;1&#xff09;添加设计师界面类&#xff08;2&#xff09;在ui中设计自定义界面&#xff08;3&#xff09;在需要使用的界面中添加&#xf…

ModaHub魔搭社区:经营大脑经营沙盘

目录 WinPlan经营大脑经营沙盘介绍 WinPlan经营大脑经营沙盘展示 WinPlan经营大脑经营沙盘设计器 WinPlan经营大脑经营沙盘介绍 经营沙盘是面向企业管理层,展示企业经营状况。可基于不同场景创建不同沙盘,用于分析不同的数据,包括销售数据、财务数据等。 企业经营决策系…

吉客云与金蝶云星空对接集成分页查询出库单打通分布式调出单新增

吉客云与金蝶云星空对接集成分页查询出库单打通分布式调出单新增 接通系统&#xff1a;吉客云 “吉客云”是一站式企业数字化解决方案系统&#xff0c;可实现业务、财务、办公、人事等一体化管理。相对于传统多套软件系统的集成方案&#xff0c;“吉客云”具有业务流程更流畅&a…

《Python基础教程》专栏总结篇

大家好&#xff0c;我是爱编程的喵喵。双985硕士毕业&#xff0c;现担任全栈工程师一职&#xff0c;热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。…

ctfshow web入门 php特性 web108-web112

1.web108 strrev() 反转字符串 <?php echo strrev("Hello world!"); // 输出 "!dlrow olleH" ?> ereg 存在空字符截断(只会匹配%00前面的字符)&#xff0c;这个函数匹配到为true&#xff0c;没有匹配到为false,877为0x36d的十进制数值 payload: …

【微服务】06-安全问题

文章目录 1.反跨站请求伪造1.1 攻击过程1.2 攻击核心1.3 如何防御1.4 使用AntiforgeryToken机制来防御用到的类 2. 防开发重定向共计2.1 攻击过程2.2 攻击核心2.3 防范措施 3.防跨站脚本3.1 攻击过程3.2 防范措施 4.跨域请求4.1 同源与跨域4.2 CORS过程4.2 CORS是什么4.3 CORS请…

解决问题的步骤

得到曲铠的课程学习。 个人感觉前面几节如明确和理解问题&#xff0c;拆分问题&#xff0c;挺好的。 后面就是水分很大&#xff0c;感觉有点烂尾了。 拆分和定期问题&#xff0c;这个指导意义还是很大的。 本质上思路还是有很多学习的地方&#xff0c;更加明确了&#xff0…

nodejs+vue+elementui健身房教练预约管理系统nt5mp

运用新技术&#xff0c;构建了以vue.js为基础的私人健身和教练预约管理信息化管理体系。根据需求分析结果进行了系统的设计&#xff0c;并将其划分为管理员&#xff0c;教练和用户三种角色&#xff1a;主要功能包括首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;教…

Tomcat和Servlet基础知识的讲解(JavaEE初阶系列16)

目录 前言&#xff1a; 1.Tomcat 1.1Tomcat是什么 1.2下载安装 2.Servlet 2.1什么是Servlet 2.2使用Servlet来编写一个“hello world” 1.2.1创建项目&#xff08;Maven&#xff09; 1.2.2引入依赖&#xff08;Servlet&#xff09; 1.2.3创建目录&#xff08;webapp&a…

java-线程之间共享数据

1. 如何在两个线程之间共享数据 Java 里面进行多线程通信的主要方式就是共享内存的方式&#xff0c;共享内存主要的关注点有两个&#xff1a;可见性和有序性原子性。Java 内存模型&#xff08;JMM&#xff09;解决了可见性和有序性的问题&#xff0c;而锁解决了原子性的问题&a…

人脸识别平台批量导入绑定设备的一种方法

因为原先平台绑定设备是通过一个界面进行人工选择绑定或一个人一个人绑定设备。如下&#xff1a; 但有时候需要在几千个里选择出几百个&#xff0c;那这种方式就不大现实了&#xff0c;需要另外一种方法。 目前相到可以通过导入批量数据进行绑定的方式。 一、前端 主要是显示…

性能测试报告-用于项目的性能验证、性能调优、发现性能缺陷等应用场景

性能测试报告 性能测试报告是一种重要的报告类型&#xff0c;旨在评估软件系统的性能、稳定性和安全性。在这篇文章中&#xff0c;我们将详细介绍性能测试报告的应用场景、测试方法和性能指标&#xff0c;以及如何撰写一份有效的性能测试报告。 一、概述 性能测试报告的目的是…

贪吃蛇是怎么实现的,循环数组的魔力

贪吃蛇是怎么实现的&#xff0c;比如有5个结点的蛇&#xff0c;1,2,3,4,5&#xff0c;1是头&#xff0c;5是尾&#xff0c;结点的坐标用(x,y)表示&#xff0c;蛇要移动x,y怎么变化&#xff1f;没有转向的时候好理解&#xff0c;如果是在水平方向直着走,所有结点的横坐标x1&…

stm32之9.中断优先级配置

主函数main.c #include <stm32f4xx.h> #include "led.h" #include "key.h"#define PAin(n) (*(volatile uint32_t *)(0x42000000 (GPIOA_BASE0x10-0x40000000)*32 (n)*4)) #define PEin(n) (*(volatile uint32_t *)(0x42000000 (GP…

Spring Cloud Alibaba-Sentinel-Sentinel入门

1 什么是Sentinel Sentinel (分布式系统的流量防卫兵) 是阿里开源的一套用于服务容错的综合性解决方案。它以流量为切入点, 从流量控制、熔断降级、系统负载保护等多个维度来保护服务的稳定性。Sentinel 具有以下特征: 丰富的应用场景&#xff1a;Sentinel 承接了阿里…

开始MySQL之路——MySQL约束概述详解

MySQL约束 create table [if not exists] 表名(字段名1 类型[(宽度)] [约束条件] [comment 字段说明],字段名2 类型[(宽度)] [约束条件] [comment 字段说明],字段名3 类型[(宽度)] [约束条件] [comment 字段说明] )[表的一些设置]; 概念 约束英文&#xff1a;constraint 约束实…