C语言实现无规律数据加密、解密(使用文件加密、解密做演示)

10 篇文章 1 订阅
1 篇文章 0 订阅

  在网络传输重要信息或存储重要文件信息时,大部分会对数据加密,保证数据的安全性。互联网上流行的可逆加密方式对数据的安全性没有保证,便自己写了一套安全性极高加密、解密方法。

  方法的实现方式及特点

    1.采用指定单个字节加密转换(转换形式为ascll码表中0-128的形式,由1个字节拆分为三个字节,下面说明拆分方式);

    2.采用数组中随机数据减指定加密字节(比如当前数据ascll码为121,当前数组中的数据为222,结果为222-121=101,当然这个只是参考实例);

    3.采用随机指定数组方式(如果需要用到无规律加密方式,可以通过随机指定数组方式进行加密);

    4.指定很大的数据加密格式(比如使用1-2048字节中任意长度为一次的加密比例,大量数据分为多次加密);

    5.多次加密数据时,第一次加密数据生成数据头与加密信息,之后只生成加密信息(数据头包含使用的加密数组(比如数组1、数组2、等…,)和加密字节长度,解析数据时将会根据数据头获取到这些信息);

    6.加密字节为跳序形式(比如指定加密1,3,5字节或者指定为别的字节调序形式,只需简单改些代码就能实现);

    指定一个字节加密后拆分为三个字节表示为

    ①第一个字节为随机数组中的随机数据(比如数组有8个数据,第一个字节范围0-7作为标记,用来解密使用);
    ②第二个字节为加密后的数据拆分的一部分(小于128用来对上ascll码表);
    ③第三个字节为采用的拆分格式(解密使用)。


  下面贴上加密使用的数组

//数组中的任意数据都可以修改为1-255之间,末尾数据为0防止数组越界
unsigned char Data1[] ={255,210,208,179,168,199,202,189,0};
unsigned char Data2[] ={166,207,205,196,191,190,163,180,0};
unsigned char Data3[] ={155,197,186,172,228,226,219,239,0};
unsigned char Data4[] ={188,229,192,254,252,212,230,217,0};
unsigned char Data5[] ={229,206,212,224,253,211,181,207,0};
目前代码中使用的是这5个数组,需要更大的随机性可以通过简单修改代码,写入更多的数组,数组中的数据在1-255(不建议写0,字符串中0为结尾)。

  数据头定义格式


  数据头1-3字节为“LKY”用来校验加密后的数据,如果数据中不存在,将不处理数据;
  数据头4-128字节为校验信息段,如果校验不正确,将不处理数据;
  数据头129-133字节为使用的指定数组进行加密(目前最大可以指定5个数组,同时使用5个数组进行对指定直接加密处理,修改代码可以增加更多的数组);
  数据头134-256字节为补数据;
  数据头257-260字节为指定的加密长度(加密长度为1-2048);
  数据头261-512字节为补数据;
  数据头的总长度为512个字节。

  下面贴上.h文件(其中包括任意格式文件的加密、解密函数)

#include <vector>

struct FileData
{
	CString Filename;
	LPVOID _this;
	bool bCover;
};

//数据加密解密类
class DataOperation
{
public:
	DataOperation();
	virtual ~DataOperation();
/***************************** 加密部分 ***********************************************************************************************/
	//设置加密数据(传入1表示使用unsigned char Data1[] ={255,210,208,179,168,199,202,189,193,0}数组加密)传入类型1-5,
	//如果传入数据超过5次,不再记录
	bool SetEncryptionData(int nCount);
	//设备每一次加密的数据长度值为0-2048,默认使用2048
	bool SetEncryptionLen(int nLen);
	//加密数据函数
	//返回加密完成的函数
	//如果传入的数据超过设置每一次加密的数据长度,将会采用设置的数据长度
	//第一次调用会生成512字节数据头与加密后的数据一起返回(比如需要加密3048个字节数据,第一次调用函数返回数据头和2048加密后的数据,第二次调用返回剩下1000个字节加密后的数据)
	char *EncryptionData(char * SrcData,int & nDataLen);
	//加密文件
	//参数一文件完整路径加名称
	//参数二 true为覆盖文件 false为创建文件名加_Temp的新文件
	bool EncryptionFile(CString Filename,bool bCover);
/**************************************************************************************************************************************/

/***************************** 解密部分 ***********************************************************************************************/
	//解析数据头信息,返回每一次解密需要传入的数据长度(使用加密后的数据前512字节为数据头信息传入函数获取到加密数据以及加密的数据长度等)
	int DecryptionHead(char * SrcData);
	//解密数据(传入加密后的数据以及数据长度,不要带数据头信息)
	//比如解密3048字节长度数据,去掉数据512个字节数据(数据头信息),从513字节开始为需要解析的数据
	//nDataLen 为解析数据头返回的每次需要传入的数据长度
	char *DecryptionData(const char * SrcData,int & nDataLen);
	//解密文件
	bool DecryptionFile(CString Filename,bool bCover);
/**************************************************************************************************************************************/
private:
	//加密数据计算函数
	char *EncryptionData_(char * SrcData,int & nDataLen,char *HeadData = 0);
	//指定字节进行加密运算
	unsigned char *Encryption_Operation(std::vector<unsigned char *> VData,unsigned char SrcData[]);
	//获取指定的加密数组
	unsigned char * GetData_Operation(int nVal);
	//根据指定加密长度获取解密长度
	int GetDecryptionDataLen(int nDataLen);
	//指定字节进行解密运算
	unsigned char *Decryption_Operation(unsigned char * VData[],unsigned char SrcData[],int nVDataLen);
private:
	//保存需要使用的加密数据(只在加密数据时使用,解密时自动根据数据头信息获取加密数据)
	char m_EncryptionData[6];
	//保存需要使用的解密数据
	char m_DecryptionData[6];
	//
	int m_EncryptionDataLen;
	//
	int m_DecryptionDataLen;
	//
	bool m_bValidHead;
};

  下面贴上.cpp文件

#include "stdafx.h"
#include "Operation.h"


unsigned char Data1[] ={255,210,208,179,168,199,202,189,0};
unsigned char Data2[] ={166,207,205,196,191,190,163,180,0};
unsigned char Data3[] ={155,197,186,172,228,226,219,239,0};
unsigned char Data4[] ={188,229,192,254,252,212,230,217,0};
unsigned char Data5[] ={229,206,212,224,253,211,181,207,0};
//数组的长度
int DataLen = 8;
//获取数组
#define GetData(nVal)\
	Data##nVal;

DataOperation::DataOperation():m_EncryptionDataLen(2048),m_bValidHead(false),m_DecryptionDataLen(0)
{
	memset(m_EncryptionData,0,sizeof(m_EncryptionData));
	memset(m_DecryptionData,0,sizeof(m_DecryptionData));
	SetEncryptionData(2);
	SetEncryptionData(1);
}
	
DataOperation::~DataOperation()
{

}

//如果传入数据超过5次,不再记录
bool DataOperation::SetEncryptionData(int nCount)
{
	int nLen = strlen(m_EncryptionData);
	if (5 <= nLen)
		return false;
	m_EncryptionData[nLen] = nCount;
	return true;
}

//设备每一次加密的数据长度值为0-2048,默认使用2048
bool DataOperation::SetEncryptionLen(int nLen)
{
	if (0 >= nLen || 2048 < nLen)
		return false;
	m_EncryptionDataLen = nLen;
	return true;
}

//加密数据函数
char * DataOperation::EncryptionData(char * SrcData,int & nDataLen)
{
	if (0 == SrcData)
		return 0;
	if (!m_bValidHead)
	{
		//首先生出数据头,然后与数据合并
		char DataHead[513] = {0};
		int nInIdex = strlen("LKY");
		memcpy(DataHead,"LKY",nInIdex);
		//前128位校验数据头信息
		for (int i = 3;i < 128;i++)
		{
			DataHead[i] = ((DataHead[i - 1] + i)%128 + 1);
		}
		int ii = 0;
		//129-133为使用的加密数据
		for (int i = 128;i < 133;i++)
		{
			
			if (0 == m_EncryptionData[ii])
			{
				DataHead[i] = '0';
			}
			else
			{
				DataHead[i] = m_EncryptionData[ii];
			}
			++ii;
		}
		//134-256为补数据
		for (int i = 133;i < 256;i++)
		{
			DataHead[i] = ((DataHead[i - 1] + i)%128 + 1);
		}
		//257-261为加密长度
		char EncryptionDataLen[5] = {0};
		itoa(m_EncryptionDataLen,EncryptionDataLen,10);
		ii = 0;
		for (int i = 256;i < 260;i++)
		{
			if (0 == EncryptionDataLen[ii])
			{
				DataHead[i] = '99';
			}
			else
			{
				DataHead[i] = EncryptionDataLen[ii];
			}
			++ii;
		}
		//261-512为补数据
		for (int i = 260;i < 512;i++)
		{
			DataHead[i] = ((DataHead[i - 1] + i)%128 + 1);
		}
		m_bValidHead = true;
		return EncryptionData_(SrcData,nDataLen,DataHead);
	}
	return EncryptionData_(SrcData,nDataLen);
}


//加密数据计算函数
char *DataOperation::EncryptionData_(char * SrcData,int & nLen,char *HeadData)
{
	char pStrData[2048 + 513 + 26] = {0};
	int nIndex = 0;
	if (0 != HeadData)
	{
		memcpy(pStrData,HeadData,512);
		nIndex += 512;
	}
	int nOffset = 0,nLeft = 0;
	int nDataLen = (m_EncryptionDataLen <= nLen ? m_EncryptionDataLen : nLen);
	//获取加密数组
	std::vector<unsigned char *>VData;
	for(int ilen = 0;ilen < strlen(m_EncryptionData);ilen++)
	{
		int nVal = m_EncryptionData[ilen];
		unsigned char * DataArray = GetData_Operation(nVal);
		VData.push_back(DataArray);
	}
	int i = 0;
	//开始加密数据
	for (;i < nDataLen;(i = i * 2 + 1))
	{
		//拷贝没有加密的数据
		if (0 < i - nLeft)
		{
			memcpy(pStrData + nIndex,SrcData + nLeft,i - nLeft);
			nIndex += i - nLeft;
		}

		unsigned char StrTemp[4] = {0,SrcData[i],0,0};
		Encryption_Operation(VData,StrTemp);

		if(128 <= StrTemp[1])
		{
			StrTemp[1] = StrTemp[1] - 127;
			StrTemp[2] = 127;
		}
		else if (0 == StrTemp[1])
		{
			StrTemp[1] = '0';
			StrTemp[2] = '0';
		}
		else
		{
			StrTemp[1] = 128 - StrTemp[1];
			StrTemp[2] = '1';
		}

		//拷贝转换过的数据
		memcpy(pStrData + nIndex,StrTemp,strlen((char *)StrTemp));
		nIndex += strlen((char *)StrTemp);
		nLeft = i + 1;
	}

	if (nLeft < nDataLen && 0 != nIndex)
	{
		memcpy(pStrData + nIndex,SrcData + nLeft,nDataLen - nLeft);
		nIndex += nDataLen - nLeft;
	}
	else if (0 == nIndex)
	{
		nLen = nDataLen;
		return pStrData;
	}
	nLen = nIndex;
	return pStrData;
}

//指定字节进行加密运算
unsigned char *DataOperation::Encryption_Operation(std::vector<unsigned char *> VData,unsigned char SrcData[])
{
	
	static ULONG64 StrEncryptionVal = 0;
	//第一个字节标记加密数组的字节位置
	SrcData[0] = (StrEncryptionVal % DataLen + '0');
	for (auto it = VData.begin();it != VData.end();it++)
	{
		unsigned char * data = *it;
		SrcData[1] = (data[SrcData[0] - '0']) - SrcData[1];
	}
	++StrEncryptionVal;
	return SrcData;
}

//获取指定的加密数组
unsigned char * DataOperation::GetData_Operation(int nVal)
{
	switch (nVal)
	{
	case 1:
		{
			return GetData(1);
		}
		break;
	case 2:
		{
			return GetData(2);
		}
		break;
	case 3:
		{
			return GetData(3);
		}
		break;
	case 4:
		{
			return GetData(4);
		}
		break;
	case 5:
		{
			return GetData(5);
		}
		break;
	}
	return 0;
}

//解析数据头信息,返回每一次解密需要传入的数据长度(使用加密后的数据前512字节为数据头信息传入函数获取到加密数据以及加密的数据长度等)
int DataOperation::DecryptionHead(char * SrcData)
{
	if (0 == SrcData || 512 > strlen(SrcData))
		return 0;
	char pSrcData[513] = {0};
	memcpy(pSrcData,SrcData,512);
	if (pSrcData[0] != 'L' || pSrcData[1] != 'K' || pSrcData[2] != 'Y')
		return 0;
	//前128位校验数据头信息
	int i = 127;
	for (;i > 3;i--)
		pSrcData[i - 1] = ((pSrcData[i] + i)%128 - pSrcData[i - 1] - 1);
	if (pSrcData[i - 1] != 'Y')
		return 0;

	//129-134为使用的加密数据
	i = 128;
	int ii = 0;
	memset(m_DecryptionData,0,sizeof(m_DecryptionData));
	for (;i < 133;i++)
	{
		if ('0' == pSrcData[i])
		{
			continue;
		}
		else
		{
			m_DecryptionData[ii++] = pSrcData[i];
		}
	}

	//257-261为加密长度
	char EncryptionDataLen[5] = {0};
	ii = 0;
	i = 256;
	for (;i < 260;i++)
	{
		if (pSrcData[i] == '99')
		{
			continue;
		}
		else
		{
			EncryptionDataLen[ii++] = pSrcData[i];
		}
	}
	m_EncryptionDataLen = atoi(EncryptionDataLen);
	m_DecryptionDataLen = GetDecryptionDataLen(m_EncryptionDataLen);
	return m_DecryptionDataLen;
}

//根据指定加密长度获取解密长度
int DataOperation::GetDecryptionDataLen(int nDataLen)
{
	if (0 >= nDataLen)
		return 0;
	int nIndex = 0;
	for (int i = 0;i < nDataLen;(i = i * 2 + 1))
	{
		nIndex += 2;
	}
	return nDataLen + nIndex;
}

//解密数据(传入加密后的数据以及数据长度,不要带数据头信息)
char *DataOperation::DecryptionData(const char * SrcData,int & nDataLen)
{
	if (0 == SrcData || 0 >= nDataLen)
		return 0;
	
	char Data[2048 + 100] = {0};
	int nIndex = 0;
	int nOffset = 0,nLeft = 0,nCurrent = 0;
	int nLen = (m_DecryptionDataLen <= nDataLen ? m_DecryptionDataLen : nDataLen);
	//获取解密
	int nDecryptionDataLen = strlen(m_DecryptionData);
	unsigned char *VData[10] = {0};
	int nVDataLen = 0;
	for(int iLen = nDecryptionDataLen;iLen > 0;iLen--)
	{
		int nVal = m_DecryptionData[iLen - 1];
		unsigned char * DataArray = GetData_Operation(nVal);
		VData[nVDataLen++] = DataArray;
	}
	int i = 0;
	//开始加密数据
	for (;i < nLen;(i = i * 2 + 1))
	{
		nCurrent = i + nOffset;
		if (nCurrent >= nDataLen)
		{
			break;
		}

		//拷贝没有加密的数据
		if (0 < nCurrent - nLeft)
		{
			memcpy(Data + nIndex,SrcData + nLeft,nCurrent - nLeft);
			nIndex += (nCurrent - nLeft);
		}

		unsigned char StrTemp[4] = {SrcData[nCurrent],SrcData[nCurrent + 1],SrcData[nCurrent + 2],0};

		if (127 == StrTemp[2])
		{
			StrTemp[1] = StrTemp[1] + 127;
			StrTemp[2] = 0;
		}
		else if ('1' == StrTemp[2])
		{
			StrTemp[1] = 128 - StrTemp[1];
			StrTemp[2] = 0;
		}
		else if ('0' == StrTemp[2])
		{
			StrTemp[1] = 0;
			StrTemp[2] = 0;
		}
		else
		{
			StrTemp[2] = 0;
		}

		Decryption_Operation(VData,StrTemp,nDecryptionDataLen);
		//拷贝转换过的数据
		memcpy(Data + nIndex,StrTemp + 1,1);
		nIndex += 1;
		nOffset += 2;
		nLeft = i + nOffset + 1;
	}
	if (nLeft < nLen && 0 != nIndex)
	{
		memcpy(Data + nIndex,SrcData + nLeft,nLen - nLeft);
		nIndex += nLen - nLeft;
	}
	else if (0 == nIndex)
	{
		return Data;
	}

	nDataLen = nIndex;
	return Data;
}

//指定字节进行解密运算
unsigned char *DataOperation::Decryption_Operation(unsigned char * VData[],unsigned char SrcData[],int nVDataLen)
{
	for (int i = 0;i < nVDataLen;i++)
	{
		unsigned char * data = VData[i];
		SrcData[1] = (data[SrcData[0] - '0']) - SrcData[1];
	}
	return SrcData;
}


//加密文件
bool DataOperation::EncryptionFile(CString Filename,bool bCover)
{
	//增加随机加密 默认使用2,1数组
	SetEncryptionData(5);
	SetEncryptionData(4);

	if (Filename.IsEmpty())
		return false;
	CFile file1,file2;
	if (!file1.Open(Filename,CFile::modeRead))

		return false;
	ULONG64 nFileLen = file1.GetLength();
	if (0 == nFileLen)
		return false;

	CString Filename2(Filename.Mid(0,Filename.ReverseFind(_T('.'))));
	Filename2.AppendFormat(_T("_Temp%s"),Filename.Mid(Filename.ReverseFind(_T('.')),
		Filename.GetLength() - Filename.ReverseFind(_T('.'))));

	if (!file2.Open(Filename2,CFile::modeCreate | CFile::modeWrite))
		return false;
	char StrData[4096] = {0};
	int nDataLen = 0;
	while (0 < nFileLen)
	{
		if (2048 <= nFileLen)
		{
			file1.Read(StrData,2048);
			nDataLen = 2048;
			char *WriteFile = EncryptionData(StrData,nDataLen);
			file2.Write(WriteFile,nDataLen);
			nFileLen -= 2048;
		}
		else
		{
			file1.Read(StrData,nFileLen);
			nDataLen = nFileLen;
			char *WriteFile = EncryptionData(StrData,nDataLen);
			file2.Write(WriteFile,nDataLen);
			nFileLen -= nFileLen;
			break;
		}
	}
	file1.Close();
	file2.Close();
	if (bCover)
	{
		USES_CONVERSION;
		//覆盖本地文件
		int nResult = remove(T2A(Filename));
		nResult = rename(T2A(Filename2),T2A(Filename));
	}
	return true;
}

//解密文件
bool DataOperation::DecryptionFile(CString Filename,bool bCover)
{
	if (Filename.IsEmpty())
		return false;
	CFile file1,file2;
	if (!file1.Open(Filename,CFile::modeRead))
		return false;
	ULONG64 nFileLen = file1.GetLength();
	if (512 >= nFileLen)
		return false;

	CString Filename2(Filename.Mid(0,Filename.ReverseFind(_T('.'))));
	Filename2.AppendFormat(_T("_Temp%s"),Filename.Mid(Filename.ReverseFind(_T('.')),
		Filename.GetLength() - Filename.ReverseFind(_T('.'))));

	if (!file2.Open(Filename2,CFile::modeCreate | CFile::modeWrite))
		return false;
	char StrData[2048 + 100] = {0};
	int nDataLen = 0;
	file1.Read(StrData,512);
	//解密数据头
	int nDecryptionLen = DecryptionHead(StrData);
	if (0 >= nDecryptionLen)
		return false;
	nFileLen -= 512;


	while (0 < nFileLen)
	{
		
		if (nDecryptionLen <= nFileLen)
		{
			
			nDataLen = nDecryptionLen;
			file1.Read(StrData,nDataLen);
			char *WriteFile = DecryptionData(StrData,nDataLen);
			memset(StrData,0,strlen(StrData));
			memcpy(StrData,WriteFile,nDataLen);
			file2.Write(StrData,nDataLen);
			nFileLen -= nDecryptionLen;
		}
		else
		{
			nDataLen = nFileLen;
			file1.Read(StrData,nFileLen);
			char *WriteFile = DecryptionData(StrData,nDataLen);
			memset(StrData,0,strlen(StrData));
			memcpy(StrData,WriteFile,nDataLen);
			file2.Write(StrData,nDataLen);
			nFileLen -= nFileLen;
			break;
		}
	}
	file1.Close();
	file2.Close();
	if (bCover)
	{
		USES_CONVERSION;
		//覆盖本地文件
		int nResult = remove(T2A(Filename));
		nResult = rename(T2A(Filename2),T2A(Filename));
	}

	return true;
}

  下面说下具体函数用法

//设置加密数据(传入1表示使用unsigned char Data1[] ={255,210,208,179,168,199,202,189,193,0}数组加密)传入类型1-5,
//如果传入数据超过5次,不再记录
//这个函数需要在加密函数使用之前调用,默认采用2、1数组加密
bool SetEncryptionData(int nCount);


//设置每一次加密的数据长度值为0-2048,默认使用2048
bool SetEncryptionLen(int nLen);


//加密数据函数
//返回加密完成的函数
//如果传入的数据超过设置每一次加密的数据长度,将会采用设置的数据长度
//第一次调用会生成512字节数据头与加密后的数据一起返回(比如需要加密3048个字节数据,第一次调用函数返回数据头和2048加密后的数据,第二次调用返回剩下1000个字节加密后的数据)
char *EncryptionData(char * SrcData,int & nDataLen);


//加密文件
//参数一文件完整路径加名称
//参数二 true为覆盖文件 false为创建文件名加_Temp的新文件
bool EncryptionFile(CString Filename,bool bCover);


//解析数据头信息,返回每一次解密需要传入的数据长度(使用加密后的数据前512字节为数据头信息传入函数获取到加密数据以及加密的数据长度等)
int DecryptionHead(char * SrcData);


//解密数据(传入加密后的数据以及数据长度,不要带数据头信息)
//比如解密3048字节长度数据,去掉数据512个字节数据(数据头信息),从513字节开始为需要解析的数据
//nDataLen 为解析数据头返回的每次需要传入的数据长度
char *DecryptionData(const char * SrcData,int & nDataLen);


//解密文件
//参数一文件完整路径加名称
//参数二 true为覆盖文件 false为创建文件名加_Temp的新文件
bool DecryptionFile(CString Filename,bool bCover);

  函数使用方式参考加密文件和解密文件函数,工程下载地址:https://download.csdn.net/download/a29562268/10448713。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坤昱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值