【c语言随笔 3】GCC编译环境下实现DES加密和RSA加密

该代码实现了一个C语言的加密解密工具,支持DES和RSA算法。程序可以对文件、文件夹和字符串进行加密解密。DES部分实现了文件、文件夹和字符串的加密解密,而RSA部分仅用于密钥加密或小数据加密。代码包含主函数、操作函数和加密解密函数,使用批处理文件简化编译流程。注意,RSA不适合加密大文件,因为效率较低且不安全。代码存在一些限制,如文件名和字符串长度、文件夹命名等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 声明: 核心DES和RSA代码有所借鉴,忘了借鉴谁的了,写本代码主要用于学习
  • 实现功能: DES与RSA的文件、文件夹和字符串的加密解密;
  • 本代码存在的问题(由于懒,尚未处理):
  1. RSA公钥密钥未实现存储,不具备现实应用意义
  2. 文件与文件夹的命名以及字符串不可过长,最长大约500字节
  3. 文件与文件夹的命名不可含有中文
  4. DES效率不达标,正常效率时1MB几毫秒完成,本代码1MB大约2s左右
  5. 代码有一千多行纯自己手写,可读性有待提升
  6. 2023/04/13追加:RSA一般用于密钥加密或小数据量加密,要求每次信息传输的参数随机才能保证安全性,具体参考“共模攻击”;故RSA加密大文件不具备现实意义,无法保证安全性。

架构

架构

架构

根目录下(主函数):

  1. 主函数在 cipher.c 中, 主要实现和用户之间的交互以及加密解密功能调用;
  2. cipher.h 内包含常用的头文件,加密解密中需要与用户间进行传递的变量内容;
  3. cmake.bat 主要是因为编译命令太长,故写批处理文件方便执行gcc编译,当然这是在windows os下执行的,linux os下为shell文件(*.sh),请自行分析编写;

op目录下(操作函数):

  1. binop.c 处理二进制与其他数据类型(主要是int 与 char)的相互转换,其中二进制数据是以整型数组存储的;e.g. int bin[4] = {0, 1, 1, 0}; // 表示 6
  2. ioop.c 处理io操作,如字符串的处理,文件的读写,文件夹的遍历与对应配置文件的生成等;
  3. ioop.h, binop.h 向外暴露的调用接口

cipher目录下(加密解密):

  1. des.c 实现DES的加密解密
  2. rsa.c 实现RSA的加密解密
  3. des.h, rsa.h 向外暴露的调用接口

代码实现

1. 根目录下

  • cmake.bat
@echo off && setlocal enableDelayedExpansion
echo Begin Compilation...
gcc -o main cipher.c cipher.h .\op\binop.c .\op\binop.h .\op\ioop.c .\op\ioop.h .\cipher\des.c .\cipher\des.h .\cipher\rsa.c .\cipher\rsa.h
echo Compilation complete!

  • cipher.h
// 条件编译
#ifndef _CIPHER_H_
	#define _CIPHER_H_ // 如果没有cipher.h,那就引入头文件cipher.h

	#include <stdio.h>
	#include <stdlib.h>
	#include <string.h>
	#include <direct.h>
	#include <math.h>
	#include <io.h>

	#define MAX_READ 32768 // 设置文件一次性读取最大字节数
	#define NUM_MAX 100    // 设置随机数随机范围上限
	
	int K[16][48];     // 用来存放k1, k2 ... k16
	int encipher;      // 加密为1, 解密为0
	int way;           // DES: 0, RSA: 1
	int op;            // 操作选择
	int n, e, d;       // 保存私钥 公钥

#endif

  • cipher.c
#include <time.h>
#include ".\cipher.h"
#include ".\op\ioop.h"
#include ".\cipher\des.h"
#include ".\cipher\rsa.h"

// 主函数
int main(int argc, char const *argv[])
{	
	/***************************Get Private Key***************************/
	char k[9] = {'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'};
	printf("----------            DES         ------------\n");
	printf("Please enter your 8Bytes private key >> ");
	gets(k);
	printf("\n");
	while (k[7] == '\0' || k[8] != '\0'){
		for (int i = 0; i < 9; ++i)
		{
			k[i] = '\0';
		}
		printf("Input Error! Please enter correct key >> ");
		gets(k);
		printf("\n");
	}
	
	// get k1 ... k16
	getK(k);
	
	/***************************RSA-Get e, d, n***************************/
	// 私钥 公钥
	KeyGener();

	/***************************run process***************************/
	char choice;
	char source[500];
	char des[500];

	while(1){
		int dis;
		int start;
		int end;

		/***************************Init***************************/
		for (int i = 0; i < 500; ++i)
		{	
			choice = '\0';
			source[i] = '\0';
			des[i] = '\0';
		}
		/***************************User choice***************************/
		printf("DES: 1, RSA: 0, Please to choose >> ");
		scanf("%c", &choice);
 		printf("\n");

		while (choice != '1' && choice != '0')
		{
			printf("Invalid Input! Please enter 0 or 1! >> ");
			scanf("%c", &choice);
			printf("\n");
		}
		getchar();
		if (choice == '1')
			way = 1;
		else if(choice == '0')
			way = 0;
		else
			break;
		/***************************User choice***************************/
		printf("A:Encipher, B:Decipher, Q: Quit, Please to choose >> ");
		scanf("%c", &choice);
 		printf("\n");

		while (choice != 'A' && choice != 'B' && choice != 'a' && choice != 'b' && choice != 'Q' && choice != 'q')
		{
			printf("Invalid Input! Please enter A or B or Q! >> ");
			scanf("%c", &choice);
			printf("\n");
		}
		getchar();
		if (choice == 'A' || choice == 'a')
			encipher = 1;
		else if(choice == 'B' || choice == 'b')
			encipher = 0;
		else
			break;
		/***************************User choice File or Dir***************************/
		printf("Operate Object -- File: 0 , Dir: 1, String: 2, Please to choose >> ");
		scanf("%c", &choice);
 		printf("\n");

		while (choice != '2' && choice != '1' && choice != '0')
		{
			printf("Invalid Input! Please enter 2 or 1 or 0! >> ");
			scanf("%c", &choice);
			printf("\n");
		}
		getchar();
		if (choice == '0')
			op = 0;
		else if(choice == '1')
			op = 1;
		else if(choice == '2')
			op = 2;
		else
			break;		
		/***************************Run next Process***************************/
		if(op == 0){
			printf("Enter your input file name(with path) >> ");
			gets(source);
			printf("\n");
			printf("Enter your output file name(with path) >> ");
			gets(des);
			printf("\n");

			start = time(0);
			RunFileProcess(source, des);
			end = time(0);
			dis = end - start;
			printf("Run Time:%ds \n\n", dis);
		}else if(op == 1){
			if (encipher == 1)
				printf("Enter your input dir name(with path) >> ");
			else{
				printf("!!!Note!!!Your \"CIPHER FILE\" must save in same path with \".secxml FILE\"!\n");
				printf("Enter your input CIPHER FILE name(with path) >> ");
			}
			gets(source);
			printf("\n");

			if (encipher == 1)
				printf("Enter your output file name(with path) >> ");
			else
				printf("Enter your output dir name(with path) >> ");
			gets(des);
			printf("\n");

			start = time(0);
			RunDirProcess(source, des);
			end = time(0);
			dis = end - start;
			printf("Run Time:%ds \n\n", dis);
		}else{
			printf("Enter your input string >> ");
			gets(source);
			printf("\n");
			printf("There is your output string >> ");
			
			start = time(0);
			RunStr(source);
			end = time(0);
			dis = end - start;
			printf("Run Time:%ds \n\n", dis);
		}
	}
	printf("Enter to Good-Bye!\n");
	getchar();
	return 0;
}

2. op目录下

  • binop.h
#ifndef _BINOP_H_
	#define _BINOP_H_
	
	void getBinary(char[], int[]); // 从8位串转二进制数
	void getChars(int[], char[]); // 二进制数转8位串
	void int2chars(int, char[]); // 一个整型转4维字符数组
	int bin2int(int[]); // 二进制比特数组转整型
	void chars2ints(char[], int[]); // 32个char转成8个整型数

#endif

  • binop.c
#include "..\cipher.h"

void getBinary(char[], int[]); // 从8位串转二进制数
void getChars(int[], char[]); // 二进制数转8位串
void int2chars(int, char[]); // 一个整型转4维字符数组
int bin2int(int[]); // 二进制比特数组转整型
void chars2ints(char[], int[]); // 32个char转成8个整型数

// 从8位串转二进制数
void getBinary(char input[], int binary[]){
	int i, j, t;
	int c = 1; // 进位位
	int positive = 1; // 判断是否是负数(负数的补码要加 1 并取反)
	int a[8] = { 0,0,0,0,0,0,0,0 };
	int m;

	for (i = 0; i < 8; i++)
	{
		// 8bits 01 Data to 8 int data
		for(j = 0; j < 8; j++){
			a[j] = 0;
		}
		m = input[i];
		
		// calculate 1 Byte to: a1*2^(n-1)+...+an*2^0
		// get a1 -> an
		for (j = 0; m != 0; j++)
		{
			a[j] = m % 2;
			if (a[j] < 0 && positive == 1)
			{
				positive = 0; // 是负数
			}
			m = m / 2;
		}

		// save as: an -> a1
		for (j = 0; j < 8; j++){
			// 负数的补码 取反
			if (positive == 0)
			{
				if (a[7 - j] == -1)
					a[7 - j] = 0;
				else
					a[7 - j] = 1;
			}

			binary[(i * 8) + j] = a[7 - j];
		}
		
		// 负数的补码取反后+1转原码
		if(positive == 0){
			for(t = 7; t >= 0 ; t--){
				// 0 的话 +c, 进位位置 0
				if (binary[(i * 8) + t] == 0)
				{
					binary[(i * 8) + t] = 0 + c;	
					c = 0;
				}
				// 1 的话 +c, 进位位讨论
				else{
					if (c == 1)
						binary[(i * 8) + t] = 0;
				}
			}
		}

		//恢复初始值
		c = 1;
		positive = 1;
	}
}

// 二进制数转8位串
void getChars(int input[], char chars[]){
	int i, j, t; // loop

	for (i = 0; i < 8; i++)
	{	
		chars[i] = 128 * input[(8*i) + 0] + 64 * input[(8*i) + 1] + 
		32 * input[(8*i) + 2] + 16 * input[(8*i) + 3] + 
		8 * input[(8*i) + 4] + 4 * input[(8*i) + 5] + 
		2 * input[(8*i) + 6]  + input[(8*i) + 7];
	}
}

// 一个整型转4维字符数组
void int2chars(int num, char schar[]){
    int bi[32]; // 存储比特值
    int k[31] = 
    {
    0x40000000,0x20000000,0x10000000, 
    0x8000000,0x4000000,0x2000000, 
    0x1000000,0x800000,0x400000,
    0x200000,0x100000,0x80000,
    0x40000,0x20000,0x10000,
    0x8000,0x4000,0x2000,
    0x1000,0x800,0x400,
    0x200,0x100,0x80,
    0x40,0x20,0x10,
    0x8,0x4,0x2,0x1
    }; // 除基取余法
    int r, cf = 1; //r用于计算 cf进位标志位

    int cint; // 其他中间变量
    int i;
    
    // 判断正负
    if(num >= 0) {
        bi[0] = 0; 
        r = num;
    }
    else {
        bi[0] = 1;  // 负数最高位为1
        r = -1*num; // 先取原码
    }
    
    // 取原码
    for (i = 1; i < 32; ++i) {
        bi[i] = r/k[i - 1];
        r -= k[i - 1]*bi[i];
    }
    
    // 负数原码转补码
    if (bi[0]) {
        // 按位取反
        for (i = 1; i < 32; ++i) {
            if (bi[i] == 0) bi[i] = 1;
            else bi[i] = 0;
        }
        
        // 反码加一
        for (i = 31; i > 0; --i) {
            if (cf) {
                if (bi[i]) bi[i] = 0;
                else {
                    bi[i] = 1;
                    cf = 0;
                }
            }
        }
    }

    for (i = 0; i < 4; ++i)
    {	
    	cint = 128*bi[i*8+0] + 64*bi[i*8+1] + 32*bi[i*8+2] + 16*bi[i*8+3] + 
    	8*bi[i*8+4] + 4*bi[i*8+5] + 2*bi[i*8+6] + 1*bi[i*8+7];
    	schar[i] = (char)cint;
    }
} 

// 二进制比特数组转整型
int bin2int(int bi[]){
	int num = 0, cf = 0;
	int k[31] = 
    {
    0x40000000,0x20000000,0x10000000, 
    0x8000000,0x4000000,0x2000000, 
    0x1000000,0x800000,0x400000,
    0x200000,0x100000,0x80000,
    0x40000,0x20000,0x10000,
    0x8000,0x4000,0x2000,
    0x1000,0x800,0x400,
    0x200,0x100,0x80,
    0x40,0x20,0x10,
    0x8,0x4,0x2,0x1
    }; // 除基取余法

    int i;

	// 负数原码转补码
    if (bi[0]) {
        // 按位取反
        for (i = 1; i < 32; ++i) {
            if (bi[i] == 0) bi[i] = 1;
            else bi[i] = 0;
        }
        
        // 反码加一
        for (i = 31; i > 0; --i) {
            if (cf) {
                if (bi[i]) bi[i] = 0;
                else {
                    bi[i] = 1;
                    cf = 0;
                }
            }
        }
    }

    for (i = 1; i < 32; ++i)
    {
    	num += k[i-1]*bi[i];
    }

    if (bi[0])
    {
    	num *= -1;
    }

    return num;
}

// 32个char转成8个整型数
void chars2ints(char schar[], int sint[]){
	char charght[8];
	int bi[64];
	int hbi[32];
	int i, j;

	// 32个char分4组
	for (i = 0; i < 4; ++i)
	{
		// 8个char -> 2个int
		for (j = 0; j < 8; ++j)
		{
			charght[j] = schar[i*8+j];
		} 
		getBinary(charght, bi);
		for (j = 0; j < 2; ++j)
		{
			for (int k = 0; k < 32; ++k)
			{
				hbi[k] = bi[j*32+k];
			}
			sint[i*2+j] = bin2int(hbi);
		}
	}
}

  • ioop.h
#ifndef _IOOP_H_
	#define _IOOP_H_

	void RunFileProcess(char[], char[]); // 文件操作
	void RunDirProcess(char[], char[]); // 文件夹操作
	void RunStr(char[]); // 字符串操作

#endif

  • ioop.c
#include "..\cipher.h"
#include "..\op\binop.h"
#include "..\cipher\rsa.h"
#include "..\cipher\des.h"

void printCipher(char[]); // 把8个原密文打印成16个字符串密文
void rebackCipher(char[], char[]); // 16个字符串密文变换回去8个原密文
void dirxml(char[], char[], int*); // 生成文件夹xml结构,要求dirPath(存放文件夹)要大,xmlSave要大(存储xml文本串),p指向xmlSave的top
void dirEncipher(char[], FILE*, int); // 文件夹加密
void dirDecipher(char[], FILE*, int); // 文件夹 解密
void dirCipher(char[], char[], char[]); // 文件夹加密/解密
void getCipherXml(char[], char[]); // 生成配置文件 并加密
void getDecipherXml(char[], char[]); // 获得文本串

/*三个接口*/
void RunFileProcess(char[], char[]); // 文件操作
void RunDirProcess(char[], char[]); // 文件夹操作
void RunStr(char[]); // 字符串操作

// 把8个原密文打印成16个字符串密文
void printCipher(char str[]){
	int data;
	int cbin[64];
	int i;
	getBinary(str, cbin);

	for (i = 0; i < 16; i++)
	{	
		data = cbin[i*4+0]*8 + cbin[i*4+1]*4 + cbin[i*4+2]*2 + cbin[i*4+3];
		if (data < 10)
			printf("%c", data+48);
		else if (data == 10)
			printf("A");
		else if (data == 11)
			printf("B");
		else if (data == 12)
			printf("C");
		else if (data == 13)
			printf("D");
		else if (data == 14)
			printf("E");
		else if (data == 15)
			printf("F");
	}
}

// 16个字符串密文变换回去8个原密文
void rebackCipher(char str[], char cback[]){
	int data;
	int mbin[64];
	int i, j;
	int b[4] = {0, 0, 0, 0};

	for(i = 0; i < 16; ++i){
		if (str[i] >= '0' && str[i] <= '9')
			data = str[i] - '0';
		else if (str[i] >= 'A' && str[i] <= 'F')
			data = str[i] - 'A' + 10;
		else if (str[i] >= 'a' && str[i] <= 'f')
			data = str[i] - 'a' + 10;

		// 按四位(半个字节)存储
		for (j = 0; j < 4; ++j)
		{
			b[j] = 0;
		}

		// 正向存储
		for (j = 3; data != 0; j--)
		{
			b[j] = data % 2;
			data = data / 2;
		}

		// 每个10进制数4位二进制数存入mbin中
		for (j = 0; j < 4; j++)
			mbin[j + (i * 4)] = b[j];
	}

	getChars(mbin, cback);
}

// 生成文件夹xml结构,要求dirPath(存放文件夹)要大,xmlSave要大(存储xml文本串),p指向xmlSave的top
void dirxml(char dirPath[], char xmlSave[], int *p){
    //文件存储信息结构体 
    struct _finddata_t fileinfo;
    //保存文件句柄 
    long fHandle;
    // 标志值
    int i, j;
    int file = 0;
    // 存储值
    char path[500];   // 存放本级路径
    char savNum[500]; // 存放十进制数转换的字符串

    char nextdir[500];
    int size = sizeof(fileinfo.name);

    // 初始化
	for(i = 0; i < 500; i++){
        path[i] = '\0';
        savNum[i] = '\0';
	}

	// 构建目录头标签
    strcat(xmlSave, "<dirm>");
    (*p) += 6;

    // 获得本级路径
    for (i = 0; dirPath[i] != '\0'; ++i)
    {	
    	path[i] = dirPath[i];
        xmlSave[(*p)++] = dirPath[i];
    }

    // 尾标签
    strcat(xmlSave, "</dirm>");
    (*p) += 7;

    path[i] = '/';
    dirPath[i] = '/';   // 生成命令语
    dirPath[i+1] = '*';
    dirPath[i+2] = '\0';

    // 遍历文件夹
    if( (fHandle = _findfirst(dirPath, &fileinfo )) != -1L ){
        do{	
        	// 如果文件大小为0,有是文件夹的可能
            if (fileinfo.size == 0)
            {
            	// 有后缀 则不是文件夹
            	for (j = 0; fileinfo.name[j] != '\0'; ++j)
            	{
            		if (fileinfo.name[j] == '.')
            		{
            			file = 1;
            			break;
            		}
            	}

            	// 否则是文件夹
            	if (file == 0)
            	{	
            		memset(nextdir, '\0', 500);
            		size = sizeof(fileinfo.name);
            		for (j = 0; j < i + size + 1; ++j)
            		{
            			if (j <= i)
            				nextdir[j] = path[j];
            			else
            				nextdir[j] = fileinfo.name[j-i-1];
            		}
            		dirxml(nextdir, xmlSave, p);
            	}else{
            		// 不是文件夹 以文件构造标签
                    sprintf(savNum, "%d", fileinfo.size); // 文件大小 数字转字符串

                    strcat(xmlSave, "<file>");
                    (*p) += 6;
                    for (j = 0; path[j] != '\0'; ++j)
                        xmlSave[(*p)++] = path[j];
                    for (j = 0; fileinfo.name[j] != '\0'; ++j)
                        xmlSave[(*p)++] = fileinfo.name[j];
                    xmlSave[(*p)++] = ':';
                    for (j = 0; savNum[j] != '\0'; ++j){
                        xmlSave[(*p)++] = savNum[j];
                        savNum[j] = '\0';
                    }
                    strcat(xmlSave, "</file>");
                    (*p) += 7;
                }
            }else{
            	// 有文件大小必不是文件夹 构建文件标签
                sprintf(savNum, "%d", fileinfo.size); // 文件大小 数字转字符串

                strcat(xmlSave, "<file>");
                (*p) += 6;
                for (j = 0; path[j] != '\0'; ++j)
                    xmlSave[(*p)++] = path[j];
                for (j = 0; fileinfo.name[j] != '\0'; ++j)
                    xmlSave[(*p)++] = fileinfo.name[j];
                xmlSave[(*p)++] = ':';
                for (j = 0; savNum[j] != '\0'; ++j){
                    xmlSave[(*p)++] = savNum[j];
                    savNum[j] = '\0';
                }
                strcat(xmlSave, "</file>");
                (*p) += 7;
            }

            // 恢复file标志位 
            file = 0;
        }while( _findnext(fHandle,&fileinfo)==0);
    }else{
    	printf("No such Dir!\n");
    	return;
    }

    //关闭文件 
    _findclose( fHandle );
}

// 文件夹加密
void dirEncipher(char source[], FILE *fi, int size){
	char rchar[8];
	int r = size%8;
	
	char ncchar[MAX_READ];
	int ncint[MAX_READ];

	int nn = size/MAX_READ;
	int nr = size%MAX_READ;

	char cchar[nr];
	int cint[nr];

	int i;

	FILE *fo;
	/***************************File Open***************************/	
	fo = fopen(source, "rb");
	// judge file exists
	if(fo == NULL){
    	printf("+fail to open the file! \n");
    	return;
    }
    /***************************File Operation - Data Input***************************/
	// core operation
	// 8Bytes a block
	printf("+Encoding...");
	if(way == 1){
		for(i = 0; i < size/8; ++i){
			fread(&rchar, 8, 1, fo);
			DES(rchar);
			fwrite(&rchar, 8, 1, fi);
		}
		// last block < 8Bytes
		// do not encipher
		if (r!= 0)
		{
			fread(&rchar, r, 1, fo);
			fwrite(&rchar, r, 1, fi);
		}
	}else{
		printf("\nnn: %d, nr: %d\n", nn, nr);
		for(i = 0; i < nn; i++){
			fread(&ncchar, MAX_READ, 1, fo);
			enRSA(ncchar, ncint, MAX_READ);
			fwrite(&ncint, MAX_READ*4, 1, fi);
		}

		if(nr != 0){
			fread(&cchar, nr, 1, fo);
			enRSA(cchar, cint, nr);
			fwrite(&cint, nr*4, 1, fi);
		}
	}
	printf("DONE!\n");
	
	/***************************File Close***************************/
	// clear file pointer;
	fclose(fo);
}

// 文件夹 解密
void dirDecipher(char outfile[], FILE *fo, int size){
	char rchar[8];
	int r = size%8;
	
	int i, nn, nr;
	char ncchar[MAX_READ/4];
	int ncint[MAX_READ/4];
	char *cchar;
	int *cint;

	FILE *fi;
	/***************************File Open***************************/	
	fi = fopen(outfile, "wb");
    /***************************File Operation - Data Input***************************/
	// core operation
	// 8Bytes a block
	printf("+Decoding...");
	if(way == 1){
		for(i = 0; i < size/8; ++i){
			fread(&rchar, 8, 1, fo);
			DES(rchar);
			fwrite(&rchar, 8, 1, fi);
		}
		// last block < 8Bytes
		// do not encipher
		if (r!= 0)
		{
			fread(&rchar, r, 1, fo);
			fwrite(&rchar, r, 1, fi);
		}
	}else{
		size = size*4;
		nn = size/MAX_READ;
		nr = size%MAX_READ;

		cchar = (char*)malloc(sizeof(char)*nr/4);
		cint = (int*)malloc(sizeof(int)*nr/4);

		printf("\nnn: %d, nr: %d\n", nn, nr);
		for(i = 0; i < nn; i++){
			fread(&ncint, MAX_READ, 1, fo);
			deRSA(ncint, ncchar, MAX_READ/4);
			fwrite(&ncchar, MAX_READ/4, 1, fi);
		}

		if(nr != 0){
			fread(&cint, nr, 1, fo);
			deRSA(cint, cchar, nr/4);
			fwrite(&cchar, nr/4, 1, fi);
		}
	}
	printf("DONE!\n");

	/***************************File Close***************************/
	// clear file pointer;
	fclose(fi);	
}

// 文件夹加密/解密
void dirCipher(char m[], char des[], char depath[]){
	// 串指针
	int sd = 0;
	int sf = 0;
	int ed = 0;
	int ef = 0;

	// 读取标记
	int d = 0;
	int f = 0;
	int h = 0;

	// 存储指针与存储数组
	int l = 0;
	int j = 0;
	char t[500];
	char s[100];

	// 文件大小
	int size;

	// 路径拼接
	char path[1000];

	// 其他中间变量
	int i, k;

	// 子串
	char sdir[6] = "<dirm>";
	char sfile[6] = "<file>";
	char edir[7] = "</dirm>";
	char efile[7] = "</file>";

	// 加密输出文件
	FILE *fi;
	// 读取文件
	FILE *fo;

	if (encipher == 1) // 生成目的文件
		fi = fopen(des, "wb");
	if (encipher == 0)
	{
		fo = fopen(des, "rb");
		if(fo == NULL){
    		printf("+fail to open the file! \n");
    		return;
    	}
	}

	// 模式串匹配
	for(i = 0; m[i] != '\0'; ++i) {
	   // 文件夹
	   if (d == 0) {
	       if (m[i] == sdir[sd]) {
	           sd++;
	           if (sd == 6) {
	               sd = 0;
	               d = 1;
	           }
	       }
	   }else {
	       if (m[i] == edir[ed]) {
	           ed++;
	           if (ed == 7) {
	               j -= 7;
	               
	               printf("+dir: ");
	               for (k = 0; k <= j; ++k) 
	               printf("%c", t[k]);
	           	   for (k = j + 1; t[k] != '\0'; ++k) 
	               t[k] = '\0';
	               printf("\n");

	               if (encipher == 0)
	               {
	               	   memset(path, '\0', sizeof(path));
		               strcat(path, depath);
		               strcat(path, "/");
		               strcat(path, t);

		               mkdir(path);
		               for (k = 0; path[k] != '\0'; ++k) 
		               path[k] = '\0';
	               }

	               j = 0;
	               d = 0;
	               f = 0;
	               ed = 0;
	           }else t[j++] = m[i];
	       }else t[j++] = m[i];
	   } 
	   // 文件
	   if (f == 0) {
	       if (m[i] == sfile[sf]) {
	           sf++;
	           if (sf == 6) {
	               sf = 0;
	               f = 1;
	           }
	       }
	   }else {
	       if (m[i] == efile[ef]) {
	           ef++;
	           if (ef == 7) { 
	               j -= 7;
	               
	               printf("+file: ");
	               for (k = 0; k <= j; ++k)
	               printf("%c", t[k]);
	           	   for (k = j + 1; t[k] != '\0'; ++k) 
	               t[k] = '\0';
	               for (k = l; s[k] != '\0' ; ++k) 
	               s[k] = '\0';
	               size = atoi(s);
	               printf(" size: %d",size);
	               printf("\n");

	               if (encipher == 1 && size != 0)
	               		dirEncipher(t, fi, size);
	               	else if (encipher == 0 && size != 0)
	               	{
	               	   memset(path, '\0', sizeof(path));
		               strcat(path, depath);
		               strcat(path, "/");
		               strcat(path, t);

		               // 解密路径
	               	   dirDecipher(path, fo, size);
	               	}
	               
	               j = 0;
	               l = 0;
	               f = 0;
	               d = 0;
	               h = 0;
	               ef = 0;
	           }else t[j++] = m[i];
	       }else {
	           if (m[i] == ':') {
	               h = 1;
	               continue;
	           }
	           if (h == 1)                                
	            s[l++] = m[i];
	           else t[j++] = m[i]; 
	       }
	   }       
	}

	if (encipher == 1) // 生成目的文件
		fclose(fi);
	else
		fclose(fo);
}

// 生成配置文件 并加密
void getCipherXml(char xml[], char des[]){
    // 目标文件路径
    char path[1000];
    char gener[1000];
    
    int i;

    FILE *fo;


    memset(path, '\0', sizeof(path)); 
    memset(gener, '\0', sizeof(gener)); 

    strcat(path, des);
    strcat(path, ".xml");
    strcat(gener, des);
    strcat(gener, ".secxml");

    // 文件操作
    // init file pointer
    fo = fopen(path, "w");

    // 写入文件
    for (i = 0; i < strlen(xml); i++)
        fputc(xml[i], fo);

    // 关闭
    fclose(fo);

    // 加密配置文件
    RunFileProcess(path, gener);
    // 删除中间xml文件
    remove(path);
} 

// 获得文本串
void getDecipherXml(char cipher[], char source[]){
	// 存储源文件.xml的路径
	char despath[1000]; // 获得.secxml的路径
	char xmlpath[1000];

	char ch;
    int index = 0; // cipher的指针

    FILE *fo;

	// 初始化
	memset(despath, '\0', sizeof(despath));
	memset(xmlpath, '\0', sizeof(xmlpath));

	// 获得文件路径
	strcat(despath, source);
	strcat(despath, ".secxml");
	strcat(xmlpath, source);
	strcat(xmlpath, ".xml");

	// 解密.secxml文件
	RunFileProcess(despath, xmlpath);

	// 读取.xml文件
	fo = fopen(xmlpath, "r");
	// judge file exists
	if(fo == NULL){
    	printf("+fail to open the xml file! \n");
    	return;
    }

    // 循环读入
    while((ch=fgetc(fo)) != EOF)
    	cipher[index++] = ch;

    // 关闭指针
    fclose(fo);
}

// 文件操作
void RunFileProcess(char source[], char des[]){
	/***************************Variables***************************/
	// file output and file input
	FILE *fo;
	FILE *fi;

	// rchar -- save a block of data stream
	// size -- file size
	// r -- remainder of size/8
	char rchar[8];
	int size;
	int r;

	int read_size;
	int read_r;
	int n;

	char *cm_content;
	char *cc_content;
	int *ic_content;
	char *cm_r;
	char *cc_r;
	int *ic_r;
	int index, i, k, read;

	/***************************File Open***************************/
	// init file pointer
	fo = fopen(source, "rb");
	// judge file exists
	if(fo == NULL){
    	printf("+fail to open the file! \n");
    	return;
    }
	fi = fopen(des, "wb");
    // file exits
	printf("+The file is open! \n");

	/***************************File Size***************************/
	// get size of file (Bytes)
	fseek(fo, 0, SEEK_END); // point to end of file 
	
	size = ftell(fo);
	r = size%8;	
	printf("+file size: %dBytes\n", size);
	printf("+remainder Bytes: %dBytes\n", r);
	
	fseek(fo, 0, SEEK_SET); // point to start of file

	/***************************File Operation - Data Input***************************/
	// core operation
	// 8Bytes a block
	printf("size-r: %d\n", size-r);
	if (size-r < MAX_READ)
	{
		read_size = size - r;
		read_r = 0;
	}else{
		read_size = MAX_READ;
		read_r = size%MAX_READ - r;
	}
	n = size/read_size;

	printf("+Encoding...");
	if(way == 1){
		cm_content = (char*)malloc(sizeof(char)*read_size);
		cc_content = (char*)malloc(sizeof(char)*read_size);
		cm_r = (char*)malloc(sizeof(char)*read_r);
		cc_r = (char*)malloc(sizeof(char)*read_r);
		index = 0;

		for(k = 0; k < n; ++k){
			fread(cm_content, read_size, 1, fo);
			for(i = 0; i < read_size; ++i){
				rchar[i%8] = cm_content[i];
				if(i%8 == 7){
					DES(rchar);
					for(int j = 0; j < 8; ++j)
						cc_content[index++] = rchar[j];
				}
			}
			fwrite(cc_content, read_size, 1, fi);
			index = 0;
		}

		if(read_r != 0){
			fread(cm_r, read_r, 1, fo);
			for(i = 0; i < read_r; ++i){
				rchar[i%8] = cm_r[i];
				if(i%8 == 7){
					DES(rchar);
					for(int j = 0; j < 8; ++j)
						cc_r[index++] = rchar[j];
				}
			}
			fwrite(cc_r, read_r, 1, fi);
			index = 0;
		}

		printf("DONE!\n\n");
		// last block < 8Bytes
		// do not encipher
		if (r!= 0)
		{
			fread(&rchar, r, 1, fo);
			fwrite(&rchar, r, 1, fi);
		}
	}else{
		if(encipher == 1){
			cm_content = (char*)malloc(sizeof(char)*MAX_READ);
			ic_content = (int*)malloc(sizeof(int)*MAX_READ);

			read = size%MAX_READ;
			cm_r = (char*)malloc(sizeof(char)*read);
			ic_r = (int*)malloc(sizeof(int)*read);

			for(k = 0; k < n; ++k){
				fread(cm_content, MAX_READ, 1, fo);
				enRSA(cm_content, ic_content, MAX_READ);
				fwrite(ic_content, MAX_READ*4, 1, fi);
			}

			if(read != 0){
				fread(cm_r, read, 1, fo);
				enRSA(cm_r, ic_r, read);
				fwrite(ic_r, read*4, 1, fi);
			}

			printf("DONE!\n\n");
		}else{
			cm_content = (char*)malloc(sizeof(char)*MAX_READ/4);
			ic_content = (int*)malloc(sizeof(int)*MAX_READ/4);

			read = size%MAX_READ;
			cm_r = (char*)malloc(sizeof(char)*read/4);
			ic_r = (int*)malloc(sizeof(int)*read/4);

			for(k = 0; k < n; ++k){
				fread(ic_content, MAX_READ, 1, fo);
				deRSA(ic_content, cm_content, MAX_READ/4);
				fwrite(cm_content, MAX_READ/4, 1, fi);
			}

			if(read != 0){
				fread(ic_r, read, 1, fo);
				deRSA(ic_r, cm_r, read/4);
				fwrite(cm_r, read/4, 1, fi);
			}

			printf("DONE!\n\n");
		}
	}
	
	/***************************File Close***************************/
	// clear file pointer;
	fclose(fo);
	fclose(fi);
}

// 文件夹操作
void RunDirProcess(char source[], char des[]){
	// 存放xml文本
	char xmlSave[1000];
	int point = 0;
	int *p;
	p = &point;

	// 初始化
	memset(xmlSave, '\0', sizeof(xmlSave));

	// 生成文本文件存储
	if (encipher == 1){
		// 获得文本串
		dirxml(source, xmlSave, p);
		// 生成加密的xml文件
		getCipherXml(xmlSave, des); 
	}
	else{
		mkdir(des);
		getDecipherXml(xmlSave, source);
	}

	// 加密/解密
	if (encipher == 1)
		dirCipher(xmlSave, des, "");
	else
		dirCipher(xmlSave, source, des);

	printf("\n");
}

// 字符串操作
void RunStr(char source[]){
	char tmp[8];
	char uchar[4];	
	char tmpp[16];
	char strchar[32];
	int strint[8];
	int index = 0;
	int i, j, k;

	if(encipher == 1){
		// 加密情况下
		for(i = 0; source[i] != '\0' || i%8 != 0; ++i){
			if (i >= 500)
				tmp[i%8] = '\0';
			else
				tmp[i%8] = source[i];

			if (i%8 == 7){
				if(way ==  1){
					DES(tmp);
					printCipher(tmp);
				}else{
					enRSA(tmp, strint, 8);
					printf("\n");
					for (j = 0; j < 8; ++j)
					{
						int2chars(strint[j], uchar);
						for (k = 0; k < 4; ++k)
							strchar[j*4+k] = uchar[k];
					}
					for(j = 0; j < 32; j++){
						tmp[j%8] = strchar[j];
						if(j%8 == 7) {
							printCipher(tmp);
						}
					}
				}
			}
		}
	}else{
		// 解密情况下
		for(i = 0; source[i] != '\0'; ++i){
			tmpp[i%16] = source[i];

			if (i%16 == 15){
				rebackCipher(tmpp, tmp);

				if(way == 1){
					 DES(tmp);
					 for (j = 0; j < 8; ++j)
					{
						if (tmp[j] != '\0')
							printf("%c", tmp[j]);
					}
				}
				else{
					for (j = 0; j < 8; ++j){
						strchar[8*index+j] = tmp[j];
					}

					index++;
					if(index == 4){
						index = 0;
						chars2ints(strchar, strint);
						deRSA(strint, tmp, 8);
						for (j = 0; j < 8; ++j)
						{
							if (tmp[j] != '\0')
								printf("%c", tmp[j]);
						}
					}
				}

			}					
		}
	}

	printf("\n\n");
}

3. cipher目录下

  • des.h
#ifndef _DES_H_
	#define _DES_H_

	void getK(char[]); // 获得16个子密钥 进入程序
	void DES(char[]); // DES 加密 解密

#endif

  • des.c
#include "..\cipher.h"
#include "..\op\binop.h"

int IP[64] = { //初始换位表
		58, 50, 42, 34, 26, 18, 10, 2,
		60, 52, 44, 36, 28, 20, 12, 4,
		62, 54, 46, 38, 30, 22, 14, 6,
		64, 56, 48, 40, 32, 24, 16, 8,
		57, 49, 41, 33, 25, 17, 9, 1,
		59, 51, 43, 35, 27, 19, 11, 3,
		61, 53, 45, 37, 29, 21, 13, 5,
		63, 55, 47, 39, 31, 23, 15, 7
	};
 
int E[48] = { //扩展换位表
	32, 1, 2, 3, 4, 5,
	4, 5, 6, 7, 8, 9,
	8, 9, 10, 11, 12, 13,
	12, 13, 14, 15, 16, 17,
	16, 17, 18, 19, 20, 21,
	20, 21, 22, 23, 24, 25,
	24, 25, 26, 27, 28, 29,
	28, 29, 30, 31, 32, 1 };

int PC1[56] = { //PC1换位表(64—>56)
	57, 49, 41, 33, 25, 17, 9,
	1, 58, 50, 42, 34, 26, 18,
	10, 2, 59, 51, 43, 35, 27,
	19, 11, 3, 60, 52, 44, 36,
	63, 55, 47, 39, 31, 23, 15,
	7, 62, 54, 46, 38, 30, 22,
	14, 6, 61, 53, 45, 37, 29,
	21, 13, 5, 28, 20, 12, 4 };

int move[16] = { //循环移位表
	1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1 };

int PC2[48] = { //PC2换位表(56—>48)
	14, 17, 11, 24, 1, 5,
	3, 28, 15, 6, 21, 10,
	23, 19, 12, 4, 26, 8,
	16, 7, 27, 20, 13, 2,
	41, 52, 31, 37, 47, 55,
	30, 40, 51, 45, 33, 48,
	44, 49, 39, 56, 34, 53,
	46, 42, 50, 36, 29, 32 };

int S1[4][16] = { //S换位表
	14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
	0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
	4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
	15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
};
int S2[4][16] = {
	15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
	3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
	0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
	13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
};
int S3[4][16] = {
	10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
	13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
	13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
	1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
};
int S4[4][16] = {
	7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
	13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
	10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
	3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
};
int S5[4][16] = {
	2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
	14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
	4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
	11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
};
int S6[4][16] = {
	12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
	10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
	9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
	4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
};
int S7[4][16] = {
	4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
	13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
	1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
	6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
};
int S8[4][16] = {
	13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
	1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
	7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
	2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
};

int P[32] = { //P换位表
	16,7,20,21,29,12,28,17,1,15,23,26,5,18,31,10,
	2,8,24,14,32,27,3,9,19,13,30,6,22,11,4,25
};

void get16key(int[]); // 获得16个子密钥 处理程序

/*接口*/
void getK(char[]); // 获得16个子密钥 进入程序
void DES(char[]); // DES 加密 解密

// 获得16个子密钥 处理程序
void get16key(int keyPC1[]){
	int i;
	int j;
	int t;
	// 中间量 参与中间运算
	int n; // 参与一位、两位运算
	int m; // 参与两位移位
	// 存放左右合并后的经过PC2转换
	int keyAB[56];
	// 存放左右28bits
	int A[28];
	int B[28];

	// keyPC1对半分,存放
	for (i = 0; i < 28; ++i)
	{
		A[i] = keyPC1[i];
		B[i] = keyPC1[i + 28];
	}

	// 循环16次的左移和PC2转换
	for (t = 0; t < 16; t++)
		{
			 //按照循环移位表将Ai和Bi分别左移move[t]位
			if (move[t] == 1)
			{	
				// 取出A[0]
				n = A[0]; 
				// 循环左移一位
				for (i = 0; i < 27; i++)
					A[i] = A[i + 1];
				A[27] = n;

				// 取出B[0]
				n = B[0];
				// 循环左移一位
				for (i = 0; i < 27; i++)
					B[i] = B[i + 1];
				B[27] = n;
			}
			else
			{	
				// 取出A[0]、A[1]
				n = A[0];
				m = A[1];
				// 循环左移两位
				for (i = 0; i < 26; i++)
					A[i] = A[i + 2];
				A[26] = n;
				A[27] = m;
				
				// 取出B[0]、B[1]
				n = B[0];
				m = B[1];
				// 循环左移两位
				for (i = 0; i < 26; i++)
					B[i] = B[i + 2];
				B[26] = n;
				B[27] = m;
			}

			//将A和B合并成56位,进行密钥生成
			for (i = 0; i < 28; i++)
			{
				keyAB[i] = A[i];
				keyAB[i + 28] = B[i];
			}

			//通过PC2换位表变成48位密钥
			for (i = 0; i < 48; i++) 
				K[t][i] = keyAB[PC2[i] - 1];
		}
}

// 获得16个子密钥 进入程序
void getK(char InputKey[]){
	// 8字节转64bits存储
	int key[64];
	int keyPC1[56]; // 经过PC1后转成56bits
	int i;

	// 前期准备
	//将密钥转化成64位二进制数放到一维数组key中
	getBinary(InputKey, key);

	//通过PC1换位表变成56位密钥放在keyPC1中
	for (i = 0; i < 56; i++) 
			keyPC1[i] = key[PC1[i] - 1];

	// 获得密钥k1 -> k16
	get16key(keyPC1);
}

// DES 加密 解密
void DES(char M[]){
	// 存放64bits明文/密文
	int text[64];
	int text_ip[64]; // 存放ip变换后的密文/明文
	// 存放左右32位
	int L[32];
	int R[32];
	int Ri[32]; // 用于交换左右
	int Li[32];
	// 轮函数的输出存放
	int Rf[32];
	// 主体的输出
	int text_end[64];
	int text_out[64];

	int m;  // 工具变量
	// 膨胀函数后的输出
	int RE[48];
	// 与子密钥异或后的输出
	int RK[48];
	// S盒(收缩函数)的输出
	int r[8];  // 获得行号
	int c[8];  // 获得列号
	int RS[8];
	// P置换前的32位
	int RP[32];

	int t, i, j;
	int b[4] = {0, 0, 0, 0};

	// 前期准备
	getBinary(M, text);

	// IP 变换
	for (i = 0; i < 64; ++i)
	{
		text_ip[i] = text[IP[i] - 1];
	}

	// 拆分成左右
	for (i = 0; i < 32; ++i)
	{
		L[i] = text_ip[i];
		R[i] = text_ip[32 + i];
	}

	// 主体部分
	for (t = 0; t < 16; ++t)
	{	
		// 进入轮函数,获得 f (32位)
		if(encipher == 1){
			// RoundFunc(Rf, R, t);
			//将右半部分通过扩展换位表E从32位扩展成48位
			for (i = 0; i < 48; i++)
				RE[i] = R[E[i] - 1];

			//RE与K异或运算
			for (i = 0; i < 48; i++) 
				RK[i] = RE[i] ^ K[t][i];

			//将R和K异或运算的结果通过S位移表
			for (i = 0; i < 8; i++)
			{	
				// 六位(6*8=48) --> 两位行号:00, 01, 10, 11 (0 -> 3); 四位列号: 0000 -> 1111 (0 -> 15);
				// 二进制转十进制
				r[i] = RK[(i * 6) + 0] * 2 + RK[(i * 6) + 5];
				c[i] = RK[(i * 6) + 1] * 8 + RK[(i * 6) + 2] * 4 + RK[(i * 6) + 3] * 2 + RK[(i * 6) + 4];
			}

			// 按照行号列号,从每个S盒内获得值
			RS[0] = S1[r[0]][c[0]];
			RS[1] = S2[r[1]][c[1]];
			RS[2] = S3[r[2]][c[2]];
			RS[3] = S4[r[3]][c[3]];
			RS[4] = S5[r[4]][c[4]];
			RS[5] = S6[r[5]][c[5]];
			RS[6] = S7[r[6]][c[6]];
			RS[7] = S8[r[7]][c[7]];
			
			//把十进制结果转成32位二进制(一个十进制数4bit存储)储存在数组RP中
			for (i = 0; i < 8; i++) 
			{
				// 按四位(半个字节)存储
				for (j = 0; j < 4; ++j)
				{
					b[j] = 0;
				}
				m = RS[i];

				// 正向存储
				for (j = 3; m != 0; j--)
				{
					b[j] = m % 2;
					m = m / 2;
				}

				// 每个10进制数4位二进制数存入BP中
				for (j = 0; j < 4; j++)
					RP[j + (i * 4)] = b[j];
			}

			//将二进制结果再经过一个P盒换位
			for (i = 0; i < 32; i++)
				Rf[i] = RP[P[i] - 1];
		}
		else if(encipher == 0){
			// RoundFunc(Rf, R, 15 - t);
						//将右半部分通过扩展换位表E从32位扩展成48位
			for (i = 0; i < 48; i++)
				RE[i] = R[E[i] - 1];

			//RE与K异或运算
			for (i = 0; i < 48; i++) 
				RK[i] = RE[i] ^ K[15 - t][i];

			//将R和K异或运算的结果通过S位移表
			for (i = 0; i < 8; i++)
			{	
				// 六位(6*8=48) --> 两位行号:00, 01, 10, 11 (0 -> 3); 四位列号: 0000 -> 1111 (0 -> 15);
				// 二进制转十进制
				r[i] = RK[(i * 6) + 0] * 2 + RK[(i * 6) + 5];
				c[i] = RK[(i * 6) + 1] * 8 + RK[(i * 6) + 2] * 4 + RK[(i * 6) + 3] * 2 + RK[(i * 6) + 4];
			}

			// 按照行号列号,从每个S盒内获得值
			RS[0] = S1[r[0]][c[0]];
			RS[1] = S2[r[1]][c[1]];
			RS[2] = S3[r[2]][c[2]];
			RS[3] = S4[r[3]][c[3]];
			RS[4] = S5[r[4]][c[4]];
			RS[5] = S6[r[5]][c[5]];
			RS[6] = S7[r[6]][c[6]];
			RS[7] = S8[r[7]][c[7]];
			
			//把十进制结果转成32位二进制(一个十进制数4bit存储)储存在数组RP中
			for (i = 0; i < 8; i++) 
			{
				// 按四位(半个字节)存储
				for (j = 0; j < 4; ++j)
				{
					b[j] = 0;
				}
				m = RS[i];

				// 正向存储
				for (j = 3; m != 0; j--)
				{
					b[j] = m % 2;
					m = m / 2;
				}

				// 每个10进制数4位二进制数存入BP中
				for (j = 0; j < 4; j++)
					RP[j + (i * 4)] = b[j];
			}

			//将二进制结果再经过一个P盒换位
			for (i = 0; i < 32; i++)
				Rf[i] = RP[P[i] - 1];
		}
		else{
			printf("Variable \"encipher\" error! Invalid encipher!\n");
			getchar();
			exit(1);
		}

		//与前一次的左部异或运算,得到本次迭代的右部
		for (i = 0; i < 32; i++) 
			Ri[i] = L[i] ^ Rf[i];
		
		// 左换成右 右换成上一次的右经过 L ^ f(R, Ki)的结果
		for (i = 0; i < 32; i++)
		{
			L[i] = R[i];
			R[i] = Ri[i];
		}
	}

	// 最后一次左右交换
	for (i = 0; i < 32; i++)
		Li[i] = R[i];
	for (i = 0; i < 32; i++)
		R[i] = L[i];
	for (i = 0; i < 32; i++)
		L[i] = Li[i];

	//把左右两部分合起来存到text_end中
	for (i = 0; i < 32; i++)
		text_end[i] = L[i];
	for (i = 32; i < 64; i++)
		text_end[i] = R[i - 32];

	//进行初始换位的逆过程
	for (i = 0; i < 64; i++) 
		text_out[IP[i] - 1] = text_end[i];

	// 64位二进制数转化为8位字符串
	getChars(text_out, M);
}

  • rsa.h
#ifndef _RSA_H_
	#define _RSA_H_

	void KeyGener(); // RSA私钥 公钥 生成
	void enRSA(char[], int[], int); // RSA加密
	void deRSA(int[], char[], int); // RSA解密

#endif

  • rsa.c
#include "..\cipher.h"

int primo(int); // 检查是否为素数
int rand_int(int); // 生成不超过Max的随机数
int pow_int_mod(int, int, int); // 加密 解密 快速模幂指数算法
void cria_num_primos(int*, int*); // 生成大素数
int escolha_e(int); // 生成e 用于发送公钥
int calculo_d(int, int); // 生成d 用于保存私钥 求逆元

/*接口*/
void KeyGener(); // RSA私钥 公钥 生成
void enRSA(char[], int[], int); // RSA加密
void deRSA(int[], char[], int); // RSA解密

// 检查是否为素数
int primo(int p) {
    int k = 2;
    while ((p % k) != 0) 
    	k++;
    if (k == p) //numero primo
    	return 1;
    else        //numero nao primo
    	return 0;
}

// 生成不超过Max的随机数
int rand_int(int max) {
    return(1 + (rand() % max));
}

// 加密 解密 快速模幂指数算法
int pow_int_mod(int num, int expo, int mod) {
    int i = 0, f = 0;
    int result = 0;
    
    if(expo % 2 == 0) {
        result = 1;
        f = (num * num) % mod; // 偶数除二
        for(i = 1; i <= expo/2; i++) {
            result = (f*result) % mod;
        }
    }else{
        result = num; // 奇数减一
        f = (num * num) % mod; // 偶数除二
        for(i = 1; i <= expo/2; i++) {
            result = (f*result) % mod;
        }    
    }
    
    return result;
}

// RSA加密
void enRSA(char mtext[], int ctext[], int l) {        
    int i;
    
    for(i = 0; i < l; i++) {
        ctext[i] = pow_int_mod(mtext[i], e, n);
    }
}

// RSA解密
void deRSA(int ctext[], char dtext[], int l) {
    int i, c_int;
    
    for(i = 0; i < l; i++) {
        c_int = pow_int_mod(ctext[i], d, n);
        dtext[i] = (char) c_int;
    }
}

// 生成大素数
void cria_num_primos(int *p, int *q){
    do{
        *p = 10 + rand_int(NUM_MAX);
    }while(primo(*p) == 0);
    
    do{
        *q = 10 + rand_int(NUM_MAX);
    }while((primo(*q) == 0) &&(*p != *q));
}

// 生成e 用于发送公钥
int escolha_e(int fi_n) {
    int e;
    e = rand_int(fi_n);
    while ((e < fi_n)) { 
        if ((fi_n % e) != 0 && (primo(e))) 
            return e;
        else 
            e = rand_int(fi_n);
    }
}

// 生成d 用于保存私钥 求逆元
int calculo_d(int fi_n, int e) {
    int d;
    d = 2;
    while ((d < fi_n) && (((e*d) % fi_n) != 1)) 
    	d++;
    return d;
}

// RSA私钥 公钥 生成
void KeyGener() {
    int p, q, fi_n;
    
    cria_num_primos(&p, &q); // 得到两个大素数
    printf("----------            RSA         ------------\n");
    printf("numero primos %d %d\n", p, q);
    
    n = p * q; // 得到公钥私钥公共部分 n
    printf("N: %d\t", n);
    
    fi_n = (p - 1) * (q - 1); // 得到用于生成e的上界
    e = escolha_e(fi_n); // 获得公钥e
    printf("e: %d\t", e);
    
    d = calculo_d(fi_n, e); //获得私钥d - e的逆元
    printf("d: %d\n", d);
    
    printf("Chaves\n");
    printf("Publica: { %d , %d }\n", e, n);
    printf("Privada: { %d , %d }\n", d, n);
    printf("---------------------------------------------\n");
}

执行方式(以文件夹加密解密为例)

  • 加密
    加密
  • 解密
    解密
  • 结果
    resultresult_1
  • 加密再解密后的所得的伪xml文件

cdemo.xml

结构讲解: <file or dir>file_path:file_size(Bytes)</file or /dir>

  • 结语

其它的操作类似,不再赘述。本次实验在效率与代码的可读性上还有较大的提升空间,本次实验的创新点在于巧妙地利用了xml文件的结构性来存储要加密的文件夹。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值