最近在做一個基於https的項目,因爲業務數據需要安全保障,於是需要一定的加解密工作,數據的安全也是現代互聯網發展的保障。
下面幾種加解密機制:
- 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!
- 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供享社
鏈接:https://www.jianshu.com/p/68c664b663f4
來源:簡書
加鹽算法:其實就是在需要加密的數據後面增加一串隨機數進行加密即可。爲什麼要加鹽呢,其實就是爲了高安全性。加鹽必須隨機纔有用。https://blog.csdn.net/M_Kerry/article/details/82725622#3salt_30
#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