最近在做一个基于https的项目,因为业务数据需要安全保障,于是需要一定的加解密工作,数据的安全也是现代互联网发展的保障。
下面几种加解密机制:

  1. DES、3DES加密

DES全称为Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1977年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),并授权在非密级政府通信中使用,随后该算法在国际上广泛流传开来。需要注意的是,在某些文献中,作为算法的DES称为数据加密算法(Data Encryption Algorithm,DEA),已与作为标准的DES区分开来。
DES对称加密,是一种比较传统的加密方式,其加密运算、解密运算使用的是同样的密钥,信息的发送者和信息的接收者在进行信息的传输与处理时,必须共同持有该密码(称为对称密码),是一种对称加密算法。
DES 的常见变体是三重 DES,使用 168 位的密钥对资料进行三次加密的一种机制;它通常(但非始终)提供极其强大的安全性。如果三个 56 位的子元素都相同,则三重 DES 向后兼容 DES。

DES加密过程:

#include <openssl/des.h>
#include <openssl/rand.h>
/*
注意:传进传出的参数皆为16进制字符数据

使用DES算法对数据加密
desKey	密钥,支持单倍、双倍、三倍
data	源数据 长度必须为8的倍数
mode 	加密模式 ECB CBC CFB
iv	仅 CBC CFB两种模式才有此值,长度为8字节
返回值:
>=0 加密数据的长度
<0 错误码
*/
int DesEncryptData(const std::string &desKeyHexStr, const std::string &dataHexStr, int mode, const std::string &iv, std::string &encDataHexStr)
{
	
	BYTE desKey[MAX_SIZE_L] = {0};
	std::string data ;
	std::string encData;
	int keyLen = 0, x = 0;
	long dataLen = 0;
	DES_key_schedule ks1, ks2, ks3;
	unsigned char tmpData[8], ke1[8], ke2[8], ke3[8], ivec[8];
	unsigned char input[MAX_SIZE_L], output[MAX_SIZE_L];

	keyLen = desKeyHexStr.length()/2;
	dataLen = dataHexStr.length()/2;

	if (keyLen == 0 || dataLen == 0)
		return -1;//errCodeOffsetOfCommon_CodeParameter;

	memset(input, 0, MAX_SIZE_L);
	memset(output, 0, MAX_SIZE_L);
	memset(desKey, 0, MAX_SIZE_L);
	
	hexToBytes(dataHexStr,input);
	hexToBytes(desKeyHexStr,desKey);

	switch (keyLen)
	{
	case 8:
		memset(ke1, 0, 8);  
		memcpy(ke1, desKey, 8);
		DES_set_key_unchecked((const_DES_cblock*)ke1, &ks1);  

		switch (mode)
		{
		case CBC:
			memcpy(ivec, iv.c_str(), 8);
			DES_cbc_encrypt(input, output, dataLen, &ks1, (DES_cblock *)ivec, DES_ENCRYPT);
			break;
		case CFB:
			memcpy(ivec, iv.c_str(), 8);
			DES_cfb_encrypt(input, output, 8, dataLen, &ks1, (DES_cblock *)ivec, DES_ENCRYPT);
			break;
		case ECB:
		default:
			for (x=0;x<dataLen;x+=8)
			{
				memcpy(tmpData, input+x, 8); 
				DES_ecb_encrypt((const_DES_cblock*)tmpData, (DES_cblock *)(output+x), &ks1, DES_ENCRYPT);
			}
			break;
		}
		break;

	case 16:
	case 24:
		memset(ke1, 0, 8);  
		memset(ke2, 0, 8);  
		memset(ke3, 0, 8); 

		if (keyLen == 16)
		{
			memcpy(ke1, desKey, 8);
			memcpy(ke2, desKey+8, 8);
			memcpy(ke3, desKey, 8);
		}else
		{
			memcpy(ke1, desKey, 8);
			memcpy(ke2, desKey+8, 8);
			memcpy(ke3, desKey+16, 8);
		}

		DES_set_key_unchecked((const_DES_cblock*)ke1, &ks1);  
		DES_set_key_unchecked((const_DES_cblock*)ke2, &ks2);  
		DES_set_key_unchecked((const_DES_cblock*)ke3, &ks3);  

		switch (mode)
		{
		case CBC:
			memcpy(ivec, iv.c_str(), 8);
			DES_ede3_cbc_encrypt(input, output, dataLen, &ks1, &ks2, &ks3, (DES_cblock *)ivec, DES_ENCRYPT);
			break;
		case CFB:
			memcpy(ivec, iv.c_str(), 8);
			DES_ede3_cfb_encrypt(input, output, 8, dataLen, &ks1, &ks2, &ks3, (DES_cblock *)ivec, DES_ENCRYPT);
		case ECB:
		default:
			for (x=0;x<dataLen;x+=8)
			{
				memcpy(tmpData, input+x, 8); 
				DES_ecb3_encrypt((const_DES_cblock*)tmpData, (DES_cblock *)(output+x), &ks1, &ks2, &ks3, DES_ENCRYPT);
			}
			break;
		}
		break;

	default:
		dataLen = -1;//errCodeOffsetOfCommon_CodeParameter;
		break;
	}

	if (dataLen > 0)
	{
		encDataHexStr = bytesToHexString(output,dataLen);
	}

	return encDataHexStr.length();
}

//密钥key:4a776d4e5ba6a68aec14abc9d7df9714
//加密原数据:hello,world!
//转换成16进制字符的80pad:68656c6c6f2c776f726c642180000000
//80pad转换成16进制字符串data:3638363536633663366632633737366637323663363432313830303030303030
//将data和key传参进去,
std::string enData;
int len = DesEncryptData(key,data,ECB,"",enData);
//得到3Des加密后的结果是enData:547f98962becbd93897b96aa44971c384853b21511529e2dceb58a11940ca037

解密过程:

/*
使用DES算法对数据解密
desKey	密钥,支持单倍、双倍、三倍
data	源数据 长度必须为8的倍数
mode 	加密模式 ECB CBC CFB
iv	仅CBC CFB两种模式才有此值
*/
int DesDecryptData(const std::string &desKeyHexStr, const std::string &dataHexStr, int mode, const std::string &iv, std::string &plainDataHexStr)
{
	BYTE desKey[MAX_SIZE_L];
	//std::string desKey;// = hexStringToString(desKeyHexStr);
	std::string data;// = hexStringToString(dataHexStr);
	int keyLen = 0, x = 0;
	long dataLen = 0;
	DES_key_schedule ks1, ks2, ks3;
	unsigned char tmpData[8], ke1[8], ke2[8], ke3[8], ivec[8];  
	unsigned char input[MAX_SIZE_L], output[MAX_SIZE_L];

	keyLen = desKeyHexStr.length()/2;
	dataLen = dataHexStr.length()/2;

	if (keyLen == 0 || dataLen == 0)
		return -1;//errCodeOffsetOfCommon_CodeParameter;

	memset(desKey,0,MAX_SIZE_L);
	memset(input, 0, MAX_SIZE_L);
	memset(output, 0, MAX_SIZE_L);
	//memcpy(input, data.c_str(), dataLen);
	hexToBytes(dataHexStr,input);
	hexToBytes(desKeyHexStr,desKey);

	switch (keyLen)
	{
	case 8:
		memset(ke1, 0, 8);  
		memcpy(ke1, desKey, 8);
		DES_set_key_unchecked((const_DES_cblock*)ke1, &ks1);  

		switch (mode)
		{
		case CBC:
			memcpy(ivec, iv.c_str(), 8);
			DES_cbc_encrypt(input, output, dataLen, &ks1, (DES_cblock *)ivec, DES_DECRYPT);
			break;
		case CFB:
			memcpy(ivec, iv.c_str(), 8);
			DES_cfb_encrypt(input, output, 8, dataLen, &ks1, (DES_cblock *)ivec, DES_DECRYPT);
			break;
		case ECB:
		default:
			for (x=0;x<dataLen;x+=8)
			{
				memcpy(tmpData, input+x, 8); 
				DES_ecb_encrypt((const_DES_cblock*)tmpData, (DES_cblock *)(output+x), &ks1, DES_DECRYPT);
			}
			break;
		}
		break;

	case 16:
	case 24:
		memset(ke1, 0, 8);  
		memset(ke2, 0, 8);  
		memset(ke3, 0, 8); 

		if (keyLen == 16)
		{
			memcpy(ke1, desKey, 8);
			memcpy(ke2, desKey+8, 8);
			memcpy(ke3, desKey, 8);
		}else
		{
			memcpy(ke1, desKey, 8);
			memcpy(ke2, desKey+8, 8);
			memcpy(ke3, desKey+16, 8);
		}

		DES_set_key_unchecked((const_DES_cblock*)ke1, &ks1);  
		DES_set_key_unchecked((const_DES_cblock*)ke2, &ks2);  
		DES_set_key_unchecked((const_DES_cblock*)ke3, &ks3);  

		switch (mode)
		{
		case CBC:
			memcpy(ivec, iv.c_str(), 8);
			DES_ede3_cbc_encrypt(input, output, dataLen, &ks1, &ks2, &ks3, (DES_cblock *)ivec, DES_DECRYPT);
			break;
		case CFB:
			memcpy(ivec, iv.c_str(), 8);
			DES_ede3_cfb_encrypt(input, output, 8, dataLen, &ks1, &ks2, &ks3, (DES_cblock *)ivec, DES_DECRYPT);
		case ECB:
		default:
			for (x=0;x<dataLen;x+=8)
			{
				memcpy(tmpData, input+x, 8); 
				DES_ecb3_encrypt((const_DES_cblock*)tmpData, (DES_cblock *)(output+x), &ks1, &ks2, &ks3, DES_DECRYPT);
			}
			break;
		}
		break;

	default:
		dataLen = -1;//errCodeOffsetOfCommon_CodeParameter;
		break;
	}

	if (dataLen > 0)
	{
		/*std::string result((char *)output, dataLen);
		plainDataHexStr = encodeHexString(result);*/
		plainDataHexStr = bytesToHexString(output,dataLen);
	}
	return plainDataHexStr.length();
}

//解密传参data:547f98962becbd93897b96aa44971c384853b21511529e2dceb58a11940ca037
//key:4a776d4e5ba6a68aec14abc9d7df9714
std::string decData;
int len = DesDecryptData(key,data,ECB,"",decData);
//decData:3638363536633663366632633737366637323663363432313830303030303030
//得到80pad:68656c6c6f2c776f726c642180000000
//转换得到16进制字符串:68656c6c6f2c776f726c6421
//16进制转bytes:hello,world!
  1. SHA256 (salt)

SHA代表安全哈希算法。SHA-1和SHA-2是该算法不同的两个版本,它们的构造和签名的长度都有所不一样,但可以把SHA-2理解为SHA-1的继承者。

首先,人们一般把哈希值位数长度作为重要的区别,SHA-1是160位的哈希值,而SHA-2是组合值,有不同的位数,其中最受欢迎的是256位。

因为SHA-2有多种不同的位数,导致这个名词有一些混乱。但是无论是“SHA-2”,“SHA-256”或“SHA-256位”,其实都是指同一种加密算法。但是SHA-224”,“SHA-384”或“SHA-512”,表示SHA-2的二进制长度。还要另一种就是会把算法和二进制长度都写上,如“SHA-2
384”。

SSL行业选择SHA作为数字签名的散列算法,从2011到2015,一直以SHA-1位主导算法。但随着互联网技术的提升,SHA-1的缺点越来越突显。从去年起,SHA-2成为了新的标准,所以现在签发的SSL证书,必须使用该算法签名。
作者:ROW供享社

加盐算法:其实就是在需要加密的数据后面增加一串随机数进行加密即可。为什么要加盐呢,其实就是为了高安全性。加盐必须随机才有用。

#include "openssl/sha.h"  

std::string mingwen = "123456";
unsigned char mdStr[33] = {0};//hash后的值长度为32个字节,也就是256个bit
SHA256((const unsigned char *)mingwen.c_str(),mingwen.length(),mdStr);
std::string res = bytesToHexString(mdStr,32);//字节数组转16进制字符串
//长度64位的16进制字符串res:8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92