c++加解密算法总结

不可逆加密

概述

单向加密,主要是对明文的保密和摘要提取。算法包括MD5、SHA、HMAC等。

特点

  • 压缩性:任意长度的数据,单向加密后长度都是固定的;
  • 抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的结果都有很大区别;
  • 弱抗碰撞性:已知原数据和其单向加密结果,想找到一个具有相同结果的数据(即伪造数据)是非常困难的;
  • 强抗碰撞性:想找到两个不同的数据,使它们具有相同的单向加密结果,是非常困难的;
  • 简单高效:对数据进行单向加密处理速度是很快的;

应用

  • 数据加密,安全访问认证
  • 文件完整性验证,数字签名

安全性

单向加密的安全性主要取决于加密结果的长度,对于同一加密算法,安全性与加密结果的长度成正比。单向加密是存在被破解的可能的,主要有暴力破解、查字典法破解和社会工学破解等。

常用算法

MD5

概念

MD5 Message-Digest Algorithm,一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。

特点

  • 压缩性:无论数据长度是多少,计算出来的MD5值长度相同;
  • 容易计算性:由原数据容易计算出MD5值;
  • 抗修改性:即便修改一个字节,计算出来的MD5值也会巨大差异;
  • 抗碰撞性:知道数据和MD5值,很小概率找到相同MD5值相同的原数据;

代码示例

// MD5示例
#include <iostream>    
#include <string.h>
#include <stdio.h>
#include "openssl/md5.h"   
#include "openssl/evp.h"
#include "openssl/bio.h"
#include "openssl/buffer.h"

std::string base64Encode(const char * input, int length, bool with_new_line)
{
	BIO* bmem = NULL;
	BIO* b64 = NULL;
	BUF_MEM* bptr = NULL;
 
	b64 = BIO_new(BIO_f_base64());
 
	if(!with_new_line) {
		BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
	}
 
	bmem = BIO_new(BIO_s_mem());
	b64 = BIO_push(b64, bmem);
	BIO_write(b64, input, length);
	BIO_flush(b64);
	BIO_get_mem_ptr(b64, &bptr);
 
	char * buff = (char *)malloc(bptr->length + 1);
	memcpy(buff, bptr->data, bptr->length);
	buff[bptr->length] = 0;
 
	BIO_free_all(b64);
 
	return buff;
} 

void md5(const std::string &srcStr, std::string &encodedStr, std::string &encodedHexStr) 
{  
    // 调用md5哈希    
    unsigned char mdStr[33] = {0};  
    MD5((const unsigned char *)srcStr.c_str(), srcStr.length(), mdStr);  
  
    // 哈希后的字符串    
    encodedStr = std::string((const char *)mdStr);  
    // 哈希后的十六进制串 32字节    
    char buf[65] = {0};  
    char tmp[3] = {0};  
    for (int i = 0; i < 32; i++)  
    {  
        sprintf(tmp, "%02x", mdStr[i]);  
        strcat(buf, tmp);  
    }  
    buf[32] = '\0'; // 后面都是0,从32字节截断    
    encodedHexStr = std::string(buf);  
}  	

int main(int argc, char **argv)  
{  
    // 原始明文    
    std::string srcText = "test MD5";  
  
    std::string encryptText = "";  
    std::string encryptHexText = "";  
    std::string decryptText = "";  
  
    std::cout << "=== 原始明文 ===" << std::endl;  
    std::cout << srcText << std::endl;  

	std::cout << "=== md5哈希 ===" << std::endl;  
    md5(srcText, encryptText, encryptHexText);  
    std::cout << "摘要字符: " << base64Encode(encryptText.c_str(), encryptText.length(), false) << std::endl;  
    std::cout << "摘要串: " << encryptHexText << std::endl;  

	return 0;
}

执行结果:

=== 原始明文 ===
test MD5
=== md5哈希 ===
摘要字符: ISpMOJ207PrPYYF6cRz4kg==
摘要串: 212a4c389db4ecfacf61817a711cf892

SHA

概念

安全散列算法(英语:Secure Hash Algorithm,缩写为SHA)是一个密码散列函数家族,是FIPS所认证的安全散列算法。能计算出一个数字消息所对应到的,长度固定的字符串(又称消息摘要)的算法。且若输入的消息不同,它们对应到不同字符串的机率很高。

主要包括SHA1、SHA2,SHA2包括SHA-224、SHA-256、SHA-384、SHA-512。

安全性:SHA2>SHA1>MD5

代码示例

// SHA256示例
#include <iostream>    
#include <string.h>
#include <stdio.h>
#include "openssl/sha.h"   
#include "openssl/evp.h"
#include "openssl/bio.h"
#include "openssl/buffer.h"

std::string base64Encode(const char * input, int length, bool with_new_line)
{
	BIO* bmem = NULL;
	BIO* b64 = NULL;
	BUF_MEM* bptr = NULL;
 
	b64 = BIO_new(BIO_f_base64());
 
	if(!with_new_line) {
		BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
	}
 
	bmem = BIO_new(BIO_s_mem());
	b64 = BIO_push(b64, bmem);
	BIO_write(b64, input, length);
	BIO_flush(b64);
	BIO_get_mem_ptr(b64, &bptr);
 
	char * buff = (char *)malloc(bptr->length + 1);
	memcpy(buff, bptr->data, bptr->length);
	buff[bptr->length] = 0;
 
	BIO_free_all(b64);
 
	return buff;
} 

void sha256(const std::string &srcStr, std::string &encodedStr, std::string &encodedHexStr)  
{  
    // 调用sha256哈希    
    unsigned char mdStr[33] = {0};  
    SHA256((const unsigned char *)srcStr.c_str(), srcStr.length(), mdStr);  
  
    // 哈希后的字符串    
    encodedStr = std::string((const char *)mdStr);  
    // 哈希后的十六进制串 32字节    
    char buf[65] = {0};  
    char tmp[3] = {0};  
    for (int i = 0; i < 32; i++)  
    {  
        sprintf(tmp, "%02x", mdStr[i]);  
        strcat(buf, tmp);  
    }  
    buf[32] = '\0'; // 后面都是0,从32字节截断    
    encodedHexStr = std::string(buf);  
}  

int main(int argc, char **argv)  
{  
    // 原始明文    
    std::string srcText = "test SHA256";  
  
    std::string encryptText;  
    std::string encryptHexText;  
    std::string decryptText;  
  
    std::cout << "=== 原始明文 ===" << std::endl;  
    std::cout << srcText << std::endl;  

	std::cout << "=== sha256哈希 ===" << std::endl;  
    sha256(srcText, encryptText, encryptHexText);  
    std::cout << "摘要字符: " << base64Encode(encryptText.c_str(), encryptText.length(), false) << std::endl;  
    std::cout << "摘要串: " << encryptHexText << std::endl;  

	return 0;
}

执行结果:

=== 原始明文 ===
test SHA256
=== sha256哈希 ===
摘要字符: pCOIxncw2JM02mtU4CvifgrwHQuR6NnwRH/mQsys0wU=
摘要串: a42388c67730d89334da6b54e02be27e

HMAC(需要密钥)

概念

HMAC是密钥相关的哈希运算消息认证码(Hash-based Message Authentication Code)的缩写,它可以与任何迭代散列函数捆绑使用。

HMAC算法更像是一种加密算法,它引入了密钥,其安全性已经不完全依赖于所使用的Hash算法。

代码示例

// HAMC示例
#include <iostream>    
#include <string.h>
#include <stdio.h>
#include "openssl/hmac.h"
using namespace std;

int HmacEncode(const char * algo, 
		const char * key, unsigned int key_length, 
		const char * input, unsigned int input_length, 
		unsigned char * &output, unsigned int &output_length) {
	const EVP_MD * engine = NULL;
	if(strcasecmp("sha512", algo) == 0) {
		engine = EVP_sha512();
	}
	else if(strcasecmp("sha256", algo) == 0) {
		engine = EVP_sha256();
	}
	else if(strcasecmp("sha1", algo) == 0) {
		engine = EVP_sha1();
	}
	else if(strcasecmp("md5", algo) == 0) {
		engine = EVP_md5();
	}
	else if(strcasecmp("sha224", algo) == 0) {
		engine = EVP_sha224();
	}
	else if(strcasecmp("sha384", algo) == 0) {
		engine = EVP_sha384();
	}
	else if(strcasecmp("sha", algo) == 0) {
		engine = EVP_sha();
	}
	else if(strcasecmp("md2", algo) == 0) {
		engine = EVP_md2();
	}
	else {
		cout << "Algorithm " << algo << " is not supported by this program!" << endl;
		return -1;
	}
 
	output = (unsigned char*)malloc(EVP_MAX_MD_SIZE);
	
	HMAC_CTX ctx;
	HMAC_CTX_init(&ctx);
	HMAC_Init_ex(&ctx, key, strlen(key), engine, NULL);
	HMAC_Update(&ctx, (unsigned char*)input, strlen(input));	
 
	HMAC_Final(&ctx, output, &output_length);
	HMAC_CTX_cleanup(&ctx);	
 
	return 0;
}

int main(int argc, char **argv)  
{  
    if(argc < 2) {
		//参数指定hash算法,支持HmacEncode列举的那些
		cout << "Please specify a hash algorithm!" << endl;
		return -1;
	}
 
	char key[] = "dsfjgasdss;dsfzaasdsr;dsfjgasdsr";   //secret key
	std::string data = "8ba5a744-f48d-4ba2-b93f-e223deqe32343dd2332";//要加密传输的数据
 
	unsigned char * mac = NULL;
	unsigned int mac_length = 0;
	
	int ret = HmacEncode(argv[1], key, strlen(key), data.c_str(), data.length(), mac, mac_length);	
	
	if(0 == ret) {
		cout << "Algorithm HMAC encode succeeded!" << endl;
	}
	else {
		cout << "Algorithm HMAC encode failed!" << endl;
		return -1;
	}
 
	cout << "mac length: " << mac_length << endl;
	cout << "mac:";
	for(int i = 0; i < (int)mac_length; i++) {
		printf("%-03x", (unsigned int)mac[i]);
	}
	cout << endl;
	
	if(mac) {
		free(mac);
		cout << "mac is freed!" << endl;
	}

	return 0;
}

执行结果:

[root@localhost ~]# ./HMACTest sha1
Algorithm HMAC encode succeeded!
mac length: 20
mac:2e a7 ac fa 3b 24 18 3  bf 2b fb b6 a4 89 f6 b4 e3 16 6d cc 
mac is freed!
[root@localhost ~]# ./HMACTest md5
Algorithm HMAC encode succeeded!
mac length: 16
mac:6f 1b 72 7  95 3f ba fb f6 0  f2 66 c2 5e 2e b1 
mac is freed!
[root@localhost ~]# ./HMACTest sha256
Algorithm HMAC encode succeeded!
mac length: 32
mac:38 c3 1e 8f a  44 39 a8 ec 4f 2a 43 fd 59 62 ba bb 19 46 f4 59 20 89 39 24 1d 35 aa af 6b de 9  
mac is freed!
[root@localhost ~]# 

各种算法得到的摘要长度如下:

算法摘要长度(字节)
MD216
MD516
SHA20
SHA120
SHA22428
SHA25632
SHA38448
SHA51264

可逆加密

根据密钥的对称性,分为对称加密和非对称加密。

对称加密

概述

数据发信方将明文(原始数据)和加密密钥一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去。收信方收到密文后,若想解读原文,则需要使用加密用过的密钥及相同算法的逆算法对密文进行解密,才能使其恢复成可读明文。在对称加密算法中,使用的密钥只有一个,发收信双方都使用这个密钥对数据进行加密和解密,这就要求解密方事先必须知道加密密钥。

特点

密钥较小(一般小于256bit),密钥越大,加密越强,但加密解密越慢。

优势:算法公开、计算量小,加密速度快、加密效率高,适用于大量数据的加密;

劣势:同一套密钥,安全性较低;

应用

常用算法

DES

概念

一种块加密算法(Block cipher),其密钥默认长度为 56 位。块加密或者叫分组加密,这种加密方法是把明文分成几个固定大小的 block 块,然后分别对其进行加密。

DES 加密算法是对密钥进行保密,而公开算法,包括加密和解密算法。这样,只有掌握了和发送方相同密钥的人才能解读由 DES加密算法加密的密文数据。因此,破译 DES 加密算法实际上就是 搜索密钥的编码。对于 56 位长度的 密钥 来说,如果用 穷举法 来进行搜索的话,其运算次数为 2 56 2 ^{56} 256 次。

代码示例
// DES示例
#include <iostream>    
#include <string.h>
#include <stdio.h>
#include <vector>
#include "openssl/des.h"   
#include "openssl/evp.h"
#include "openssl/bio.h"
#include "openssl/buffer.h"
using namespace std;

std::string base64Encode(const char * input, int length, bool with_new_line)
{
	BIO* bmem = NULL;
	BIO* b64 = NULL;
	BUF_MEM* bptr = NULL;
 
	b64 = BIO_new(BIO_f_base64());
 
	if(!with_new_line) {
		BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
	}
 
	bmem = BIO_new(BIO_s_mem());
	b64 = BIO_push(b64, bmem);
	BIO_write(b64, input, length);
	BIO_flush(b64);
	BIO_get_mem_ptr(b64, &bptr);
 
	char * buff = (char *)malloc(bptr->length + 1);
	memcpy(buff, bptr->data, bptr->length);
	buff[bptr->length] = 0;
 
	BIO_free_all(b64);
 
	return buff;
} 

// 加密 ecb模式    
std::string des_encrypt(const std::string &clearText, const std::string &key)  
{  
    std::string cipherText; // 密文    
  
    DES_cblock keyEncrypt;  
    memset(keyEncrypt, 0, 8);  
  
    // 构造补齐后的密钥    
    if (key.length() <= 8)  
        memcpy(keyEncrypt, key.c_str(), key.length());  
    else  
        memcpy(keyEncrypt, key.c_str(), 8);  
  
    // 密钥置换    
    DES_key_schedule keySchedule;  
    DES_set_key_unchecked(&keyEncrypt, &keySchedule);  
  
    // 循环加密,每8字节一次    
    const_DES_cblock inputText;  
    DES_cblock outputText;  
    std::vector<unsigned char> vecCiphertext;  
    unsigned char tmp[8];  
  
    for (int i = 0; i < (int)clearText.length() / 8; i++)  
    {  
        memcpy(inputText, clearText.c_str() + i * 8, 8);  
        DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_ENCRYPT);  
        memcpy(tmp, outputText, 8);  
  
        for (int j = 0; j < 8; j++)  
            vecCiphertext.push_back(tmp[j]);  
    }  
  
    if (clearText.length() % 8 != 0)  
    {  
        int tmp1 = clearText.length() / 8 * 8;  
        int tmp2 = clearText.length() - tmp1;  
        memset(inputText, 0, 8);  
        memcpy(inputText, clearText.c_str() + tmp1, tmp2);  
        // 加密函数    
        DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_ENCRYPT);  
        memcpy(tmp, outputText, 8);  
  
        for (int j = 0; j < 8; j++)  
            vecCiphertext.push_back(tmp[j]);  
    }  
  
    cipherText.clear();  
    cipherText.assign(vecCiphertext.begin(), vecCiphertext.end());  
  
    return cipherText;  
}  
  
// 解密 ecb模式    
std::string des_decrypt(const std::string &cipherText, const std::string &key)  
{  
    std::string clearText; // 明文    
  
    DES_cblock keyEncrypt;  
    memset(keyEncrypt, 0, 8);  
  
    if (key.length() <= 8)  
        memcpy(keyEncrypt, key.c_str(), key.length());  
    else  
        memcpy(keyEncrypt, key.c_str(), 8);  
  
    DES_key_schedule keySchedule;  
    DES_set_key_unchecked(&keyEncrypt, &keySchedule);  
  
    const_DES_cblock inputText;  
    DES_cblock outputText;  
    std::vector<unsigned char> vecCleartext;  
    unsigned char tmp[8];  
  
    for (int i = 0; i < (int)cipherText.length() / 8; i++)  
    {  
        memcpy(inputText, cipherText.c_str() + i * 8, 8);  
        DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_DECRYPT);  
        memcpy(tmp, outputText, 8);  
  
        for (int j = 0; j < 8; j++)  
            vecCleartext.push_back(tmp[j]);  
    }  
  
    if (cipherText.length() % 8 != 0)  
    {  
        int tmp1 = cipherText.length() / 8 * 8;  
        int tmp2 = cipherText.length() - tmp1;  
        memset(inputText, 0, 8);  
        memcpy(inputText, cipherText.c_str() + tmp1, tmp2);  
        // 解密函数    
        DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_DECRYPT);  
        memcpy(tmp, outputText, 8);  
  
        for (int j = 0; j < 8; j++)  
            vecCleartext.push_back(tmp[j]);  
    }  
  
    clearText.clear();  
    clearText.assign(vecCleartext.begin(), vecCleartext.end());  
  
    return clearText;  
}  

int main(int argc, char **argv)  
{  
     // 原始明文    
    std::string srcText = "test DES";  
  
    std::string encryptText;  
    std::string encryptHexText;  
    std::string decryptText;  
  
    std::cout << "=== 原始明文 ===" << std::endl;  
    std::cout << srcText << std::endl;  

    std::cout << "=== des加解密 ===" << std::endl;  
    std::string desKey = "12345";  
    encryptText = des_encrypt(srcText, desKey);  
    std::cout << "加密字符: " << std::endl;  
    std::cout << base64Encode(encryptText.c_str(), encryptText.length(), false) << std::endl;  
    decryptText = des_decrypt(encryptText, desKey);  
    std::cout << "解密字符: " << std::endl;  
    std::cout << decryptText << std::endl;  

	return 0;
}

执行结果:

=== 原始明文 ===
test DES
=== des加解密 ===
加密字符: 
vmfC/L3cGBo=
解密字符: 
test DES

3DES

概念

3DES(即Triple DES)是DESAES过渡的加密算法,它使用3条56位的密钥对数据进行三次加密。是DES的一个更安全的变形。它以DES为基本模块,通过组合分组方法设计出分组加密算法。比起最初的DES3DES更为安全。密钥长度默认为168位,还可以选择128位。

代码示例
#include <iostream>    
#include <string.h>
#include <stdio.h>
#include <vector>
#include "openssl/des.h"   
#include "openssl/evp.h"
#include "openssl/bio.h"
#include "openssl/buffer.h"
using namespace std;

std::string base64Encode(const char * input, int length, bool with_new_line)
{
	BIO* bmem = NULL;
	BIO* b64 = NULL;
	BUF_MEM* bptr = NULL;
 
	b64 = BIO_new(BIO_f_base64());
 
	if(!with_new_line) {
		BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
	}
 
	bmem = BIO_new(BIO_s_mem());
	b64 = BIO_push(b64, bmem);
	BIO_write(b64, input, length);
	BIO_flush(b64);
	BIO_get_mem_ptr(b64, &bptr);
 
	char * buff = (char *)malloc(bptr->length + 1);
	memcpy(buff, bptr->data, bptr->length);
	buff[bptr->length] = 0;
 
	BIO_free_all(b64);
 
	return buff;
} 

int Des3DesEncrypt(const std::string& rand_key, const std::string& in, std::string& out)
{
	char out_array[10240];
	char in_array[10240];
	memset(out_array, 0, 10240);
	memset(in_array, 0, 10240);
 
	DES_key_schedule keyschedc1;
	DES_key_schedule keyschedc2;
	DES_key_schedule keyschedc3;
 
	if (rand_key.size() < 24)
	{
		return -1;
	}
 
	DES_set_key((DES_cblock *)rand_key.substr(0,8).c_str(), &keyschedc1);
	DES_set_key((DES_cblock *)rand_key.substr(8,8).c_str(), &keyschedc2);
	DES_set_key((DES_cblock *)rand_key.substr(16,8).c_str(), &keyschedc3);
 
	//数据不足8位的时候后面需要补齐 如果是取余为0,则补8个0
	int data_rest = in.size()%8;
	char ch = 8-data_rest;
 
	int len = (in.size()/8 + 1)*8;
 
	for (int i=0; i<(int)in.size(); ++i)in_array[i] = in.at(i);
	memset(in_array + in.size(), ch, 8 - data_rest);
 
	for (int i=0; i<len; i += 8)
	{
	    DES_ecb3_encrypt((DES_cblock *)(in_array + i),
	                    (DES_cblock *)(out_array + i),
	                    &keyschedc1, &keyschedc2,
	                    &keyschedc3, DES_ENCRYPT);
	}
 
	out.assign(out_array, len);
 
	return 0;
}

int main(int argc, char **argv)  
{  
     // 原始明文    
    std::string srcText = "test 3DES";  
  
    std::string encryptText;  
    std::string encryptHexText;  
    std::string decryptText;  
  
    std::cout << "=== 原始明文 ===" << std::endl;  
    std::cout << srcText << std::endl;  

    std::cout << "=== 3des加解密 ===" << std::endl;  
    std::string desKey = "wemnsanb1wemnaqnbqpamnaqnbvfdewsxcvbgyhujiuytrfdsedfvnmk";  
    Des3DesEncrypt(desKey, srcText, encryptText);  
    std::cout << "加密字符: " << std::endl;  
    std::cout << base64Encode(encryptText.c_str(), encryptText.length(), false) << std::endl;  
    //decryptText = des_decrypt(encryptText, desKey);  
    //std::cout << "解密字符: " << std::endl;  
    //std::cout << decryptText << std::endl;  

    return 0;
}

执行结果:

=== 原始明文 ===
test 3DES
=== 3des加解密 ===
加密字符: 
/XnXVk51IzF+TP1+Xi3Z7g==

AES

概念

AES 是块加密算法,也就是说,每次处理的数据是一块(16 字节、128位),当数据不是 16 字节的倍数时填充,这就是所谓的分组密码(区别于基于比特位的流密码),16 字节是分组长度。AES 共有 ECB、CBC 等多种模式。

代码示例
// AES示例

#include <iostream>    
#include <string.h>
#include <stdio.h>
#include <vector>
#include "openssl/aes.h"   
#include "openssl/evp.h"
#include "openssl/bio.h"
#include "openssl/buffer.h"
using namespace std;

std::string base64Encode(const char * input, int length, bool with_new_line)
{
	BIO* bmem = NULL;
	BIO* b64 = NULL;
	BUF_MEM* bptr = NULL;
 
	b64 = BIO_new(BIO_f_base64());
 
	if(!with_new_line) {
		BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
	}
 
	bmem = BIO_new(BIO_s_mem());
	b64 = BIO_push(b64, bmem);
	BIO_write(b64, input, length);
	BIO_flush(b64);
	BIO_get_mem_ptr(b64, &bptr);
 
	char * buff = (char *)malloc(bptr->length + 1);
	memcpy(buff, bptr->data, bptr->length);
	buff[bptr->length] = 0;
 
	BIO_free_all(b64);
 
	return buff;
} 

// 加密
void AesEncrypt(const unsigned char *in, unsigned char *out, int length, const unsigned char *key, unsigned char *ivec)
{
    AES_KEY encrypt_key;
    // 设置加密密钥
   if(AES_set_encrypt_key((const unsigned char*)key, 128, &encrypt_key) < 0)
    {
	cout << "AES_set_encrypt_key failed" << endl;
      return ;
    }

    AES_cbc_encrypt(in, out, length, &encrypt_key, ivec, AES_ENCRYPT);	
}

// 解密
void AesDecrypt(const unsigned char *in, unsigned char *out, int length, const unsigned char *key, unsigned char *ivec)
{
    AES_KEY decrypt_key;
    if (AES_set_decrypt_key((const unsigned char*)key, 128, &decrypt_key) < 0)
     {
	  cout << "AES_set_decrypt_key failed" << endl;
        return ;
     }    

    AES_cbc_encrypt(in, out, length, &decrypt_key, ivec, AES_DECRYPT);
}

int main(int argc, char **argv)  
{  
    unsigned char key[16] = "123456789012345";
    unsigned char ivec[16] = "123456789012345";
    unsigned char aes_in[20] = "123456act012345678";
    unsigned char aes_out[32];

    AesEncrypt(aes_in, aes_out, 20, key, ivec);  //加密
    cout << "Encrypt result:" <<base64Encode((char*)aes_out, 32, false) << endl;

    memset(aes_in, 0, 20);
    memcpy(ivec, "123456789012345", 16);
    AesDecrypt(aes_out, aes_in, 20, key, ivec);  //解密
    cout << "Decrypt result:" << aes_in << endl;

    return 0;
}

执行结果:

Encrypt result:zVrnKAdkWqHp4SAvj/8wfhuyVQImEemAqhO0feTzazE=
Decrypt result:123456act012345678

非对称加密

概述

非对称加密算法需要两个密钥来进行加密和解密,分别是公钥和私钥。公钥和私钥成对存在,如果用公钥对数据进行加密,那么只有使用对应的私钥才能解密。

特点

算法强度复杂、安全性依赖于算法与密钥。但是由于其算法复杂,使得加密解密速度没有对称加密解密的速度快。

应用

加解密和数字签名验证。

关于数字前面和数字证书,可参考:https://blog.csdn.net/qq_34827674/article/details/119081396

常用算法

RSA

概念

RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作RSA公开密钥密码体制。所谓的公开密钥密码体制就是使用不同的加密密钥与解密密钥,是一种“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制。

RSA的算法涉及三个参数,n、e1、e2。其中,n是两个大质数p、q的积,n的二进制表示时所占用的位数,就是所谓的密钥长度。e1和e2是一对相关的值,e1可以任意取。

加密盐

加密盐也是比较常听到的一个概念,盐就是一个随机字符串用来和我们的加密串拼接后进行加密。加盐主要是为了提供加密字符串的安全性。假如有一个加盐后的加密串,黑客通过一定手段这个加密串,他拿到的明文,并不是我们加密前的字符串,而是加密前的字符串和盐组合的字符串,这样相对来说又增加了字符串的安全性。

代码示例
// RSA代码示例

#include <iostream>    
#include <string.h>
#include <stdio.h>
#include <vector>
#include "openssl/rsa.h"    
#include "openssl/pem.h" 
#include "openssl/evp.h"
#include "openssl/bio.h"
#include "openssl/buffer.h"
using namespace std;

std::string base64Encode(const char * input, int length, bool with_new_line)
{
	BIO* bmem = NULL;
	BIO* b64 = NULL;
	BUF_MEM* bptr = NULL;
 
	b64 = BIO_new(BIO_f_base64());
 
	if(!with_new_line) {
		BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
	}
 
	bmem = BIO_new(BIO_s_mem());
	b64 = BIO_push(b64, bmem);
	BIO_write(b64, input, length);
	BIO_flush(b64);
	BIO_get_mem_ptr(b64, &bptr);
 
	char * buff = (char *)malloc(bptr->length + 1);
	memcpy(buff, bptr->data, bptr->length);
	buff[bptr->length] = 0;
 
	BIO_free_all(b64);
 
	return buff;
} 

#define KEY_LENGTH  2048               // 密钥长度  
#define PUB_KEY_FILE "pubkey.pem"    // 公钥路径  
#define PRI_KEY_FILE "prikey.pem"    // 私钥路径  
  
// 函数方法生成密钥对   
void generateRSAKey(std::string strKey[2])  
{  
    // 公私密钥对    
    size_t pri_len;  
    size_t pub_len;  
    char *pri_key = NULL;  
    char *pub_key = NULL;  
  
    // 生成密钥对    
    RSA *keypair = RSA_generate_key(KEY_LENGTH, RSA_3, NULL, NULL);  
  
    BIO *pri = BIO_new(BIO_s_mem());  
    BIO *pub = BIO_new(BIO_s_mem());  
  
    PEM_write_bio_RSAPrivateKey(pri, keypair, NULL, NULL, 0, NULL, NULL);  
    PEM_write_bio_RSAPublicKey(pub, keypair);  
  
    // 获取长度    
    pri_len = BIO_pending(pri);  
    pub_len = BIO_pending(pub);  
  
    // 密钥对读取到字符串    
    pri_key = (char *)malloc(pri_len + 1);  
    pub_key = (char *)malloc(pub_len + 1);  
  
    BIO_read(pri, pri_key, pri_len);  
    BIO_read(pub, pub_key, pub_len);  
  
    pri_key[pri_len] = '\0';  
    pub_key[pub_len] = '\0';  
  
    // 存储密钥对    
    strKey[0] = pub_key;  
    strKey[1] = pri_key;  
  
    // 存储到磁盘(这种方式存储的是begin rsa public key/ begin rsa private key开头的)  
    FILE *pubFile = fopen(PUB_KEY_FILE, "w");  
    if (pubFile == NULL)  
    {  
        //assert(false);  
        return;  
    }  
    fputs(pub_key, pubFile);  
    fclose(pubFile);  
  
    FILE *priFile = fopen(PRI_KEY_FILE, "w");  
    if (priFile == NULL)  
    {  
        //assert(false);  
        return;  
    }  
    fputs(pri_key, priFile);  
    fclose(priFile);  
  
    // 内存释放  
    RSA_free(keypair);  
    BIO_free_all(pub);  
    BIO_free_all(pri);  
  
    free(pri_key);  
    free(pub_key);  
}  
  
// 命令行方法生成公私钥对(begin public key/ begin private key)  
// 找到openssl命令行工具,运行以下  
// openssl genrsa -out prikey.pem 1024   
// openssl rsa -in privkey.pem - pubout -out pubkey.pem  
  
// 公钥加密    
std::string rsa_pub_encrypt(const std::string &clearText, const std::string &pubKey)  
{  
    std::string strRet;  
    RSA *rsa = NULL;  
    BIO *keybio = BIO_new_mem_buf((unsigned char *)pubKey.c_str(), -1);  
    // 此处有三种方法  
    // 1, 读取内存里生成的密钥对,再从内存生成rsa  
    // 2, 读取磁盘里生成的密钥对文本文件,在从内存生成rsa  
    // 3,直接从读取文件指针生成rsa  
   // RSA* pRSAPublicKey = RSA_new();  
    rsa = PEM_read_bio_RSAPublicKey(keybio, &rsa, NULL, NULL);  
  
    int len = RSA_size(rsa);  
    char *encryptedText = (char *)malloc(len + 1);  
    memset(encryptedText, 0, len + 1);  
  
    // 加密函数  
    int ret = RSA_public_encrypt(clearText.length(), (const unsigned char*)clearText.c_str(), (unsigned char*)encryptedText, rsa, RSA_PKCS1_PADDING);  
    if (ret >= 0)  
        strRet = std::string(encryptedText, ret);  
  
    // 释放内存  
    free(encryptedText);  
    BIO_free_all(keybio);  
    RSA_free(rsa);  
  
    return strRet;  
}  
  
// 私钥解密    
std::string rsa_pri_decrypt(const std::string &cipherText, const std::string &priKey)  
{  
    std::string strRet;  
    RSA *rsa = RSA_new();  
    BIO *keybio;  
    keybio = BIO_new_mem_buf((unsigned char *)priKey.c_str(), -1);  
  
    // 此处有三种方法  
    // 1, 读取内存里生成的密钥对,再从内存生成rsa  
    // 2, 读取磁盘里生成的密钥对文本文件,在从内存生成rsa  
    // 3,直接从读取文件指针生成rsa  
    rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa, NULL, NULL);  
  
    int len = RSA_size(rsa);  
    char *decryptedText = (char *)malloc(len + 1);  
    memset(decryptedText, 0, len + 1);  
  
    // 解密函数  
    int ret = RSA_private_decrypt(cipherText.length(), (const unsigned char*)cipherText.c_str(), (unsigned char*)decryptedText, rsa, RSA_PKCS1_PADDING);  
    if (ret >= 0)  
        strRet = std::string(decryptedText, ret);  
  
    // 释放内存  
    free(decryptedText);  
    BIO_free_all(keybio);  
    RSA_free(rsa);  
  
    return strRet;  
}  

int main(int argc, char **argv)  
{  
    // 原始明文    
    std::string srcText = "test RSA";  
  
    std::string encryptText;  
    std::string encryptHexText;  
    std::string decryptText;  
  
    std::cout << "=== 原始明文 ===" << std::endl;  
    std::cout << srcText << std::endl;  

    std::cout << "=== rsa加解密 ===" << std::endl;  
    std::string key[2];  
    generateRSAKey(key);  
    std::cout << "公钥: " << std::endl;  
    std::cout << key[0] << std::endl;  
    std::cout << "私钥: " << std::endl;  
    std::cout << key[1] << std::endl;  
    encryptText = rsa_pub_encrypt(srcText, key[0]);  
    std::cout << "加密字符: " << std::endl;  
    std::cout << base64Encode(encryptText.c_str(), encryptText.length(), false) << std::endl;  
    decryptText = rsa_pri_decrypt(encryptText, key[1]);  
    std::cout << "解密字符: " << std::endl;  
    std::cout << decryptText << std::endl;  

    return 0;
}

执行结果:

=== 原始明文 ===
test RSA
=== rsa加解密 ===
公钥: 
-----BEGIN RSA PUBLIC KEY-----
MIIBCAKCAQEAsWHxQu2SKLA/A2esf5xlDg3wapfisrBJjv2MaYU5D1MK/pkWDYCe
7U5IMKtaDKs3ScRdozId7P1NYlPkjCorwaGe1c48+BCwnEh4YHZfozQ88L7MWNUy
cIyzgu5TdI0iWJQn9zyYW5Tl8HIOY2wmHAfZcC1GqgGQANZUPHX7jZWvosuO1BVg
AIa6jVNRiAWG3U3LqN2pHOx7HZrghLYW+QQw8HXrJmmeX6hVdToapTcME7cVdHiQ
JgwTMdQbLziT6/qTBgdLI2ODpWQ2aYSkxOEuI1zgsezmjl22Q1vGwQLyW15NNmzw
MwEs3n8h90HjHdmb9CoLfCtYSAbX/w71EQIBAw==
-----END RSA PUBLIC KEY-----

私钥: 
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAsWHxQu2SKLA/A2esf5xlDg3wapfisrBJjv2MaYU5D1MK/pkW
DYCe7U5IMKtaDKs3ScRdozId7P1NYlPkjCorwaGe1c48+BCwnEh4YHZfozQ88L7M
WNUycIyzgu5TdI0iWJQn9zyYW5Tl8HIOY2wmHAfZcC1GqgGQANZUPHX7jZWvosuO
1BVgAIa6jVNRiAWG3U3LqN2pHOx7HZrghLYW+QQw8HXrJmmeX6hVdToapTcME7cV
dHiQJgwTMdQbLziT6/qTBgdLI2ODpWQ2aYSkxOEuI1zgsezmjl22Q1vGwQLyW15N
NmzwMwEs3n8h90HjHdmb9CoLfCtYSAbX/w71EQIBAwKCAQB2QUuB87bFytSs78hV
Eu4JXqBHD+x3IDEJ/l2briYKN1ypu2QJAGnziYV1x5Fdx3oxLZPCIWlIqN5BjUMI
HB0rwRSOiX36tcsS2vrq+ZUXeCigfzLl43b1syJXSYz4XhbluBqk0xA9De6gTAmX
nW69WpD1c4RxVmAAjuLS+VJeYq49prBFXw3AHjqfZgUYp0vcwGg4DdW1D6/vuhzW
fGaHbXOgBCxKt3vLmPB57VKrjUpH8p5u2BUIhqaOv4avLBCAXozr9IGSM43R6/wY
/H6fciToiY263vnoYpCRmnl7WN+9/wtf/Tz/DDq5MBl3tmMexBxsAD5HbRnjbZUL
qXVDAoGBANlUo38itg2NlVNahGYH48A+etYEAeG+OAerv5oIqU3b4tO/HjFExWil
FzERlssm4h+jQasL3LVi3OGYrDVxwrB4rcJAZg3X0KgGPwU60pigb7/t/Y5mwD5w
cnb0fxaEyfNYBrztU4yVYgSzDQydVejbtFP9I/Y+cJ9EyFI2vn2XAoGBANDxrgdJ
UL3SxA9DtePbJtTTsllQxwbPHOuKRBs6Ui9R/S/BUXdxkPwJK7usv1N9AP0EiXzC
V7s2ZTfDCJu2s8qyvv1jsnrwRYbkQzcJN041RjbYkP2y3jFBV2Z0dPoDM69mWP85
HYgfDNAVqe8mWmWT/x1VBbfSlxIuGiY20keXAoGBAJDjF6oXJAkJDjeRrZlal9V+
/I6tVpZ+0AUdKmawcN6SlzfUvsuDLkXDZMthDzIZ7BUXgRyykyOXPeu7HXj2gcr7
HoGARAk6ixqu1K4nNxBq9SqeqQmZ1X71oaSi/2RYhqI6ryieN7MOQVh3Xgho4/CS
eDf+F/l+9b+DMDbPKakPAoGBAItLyVow4H6MgrTXzpfnbziNIZDghK80vfJcLWd8
Nso2qMqA4PpLtf1bcn0d1OJTVf4DBlMsOnzO7iUssGfPIoch1KjtIadK2QSYLM9b
ejQjhCSQYKkh6XYrj5mi+KaszR+ZkKomE7AUszVjxp9u5u5iqhOOA8/hugwevBl5
4YUPAoGAaDgxWJb12UsZaYclsbeBxJ7gLCxLG3hnWBURuNmImbTuUL3eK3yhD6j6
3g9r0oT9mTkLB+f5r4ODDD7yDOWYZbp4JsyPAFp2gva4IP+twA391FRg0p60roKO
AZCQ4dCyvnL6V6CnqTFUVhS9H9I7NCZHjUL+eFTAiL+7eFFPuBs=
-----END RSA PRIVATE KEY-----

加密字符: 
XpcptvI+vqqk34oNyppgQ22faFmilhVk3THl3we+kPPvIsMuvL+n2jYZhpBRmgIe5v8dqm8wul8ZU03L3INNMrjEcdU2P0KQFb5dk0ONe9ySm/B6UsZSJuOzT/+FBlpGK63Q94cRWb4JNp3rzbm+IF+m1lS7GtmYthh0axnhdJasm85U9qmiDDT5YX/8VGbvtygMqtIsVq7ZBDCjor3lc8LZR5/d/oPQ5mXNaA6e9CUuc09mwoRNzWHvCBZJRYarOAIkm4XMFwEGDVWX6ca1gZJt/13vtYPrrKYt7i96Z8ANFwl8kipNczK8GGWskmF0auenZD1v/Rh+kof3YGBotg==
解密字符: 
test RSA

DSA

ECC

参考:

常用加密算法:https://blog.csdn.net/tianshan2010/article/details/106170662/

md5(base64):https://blog.csdn.net/w1820020635/article/details/88350680

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于springboot实现医院信息管理系统【源码+论文】

基于springboot实现医院信管系统演示开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xf…

2023年全国DAMA-CDGP数据治理专家认证线上班招生简章

DAMA认证为数据管理专业人士提供职业目标晋升规划&#xff0c;彰显了职业发展里程碑及发展阶梯定义&#xff0c;帮助数据管理从业人士获得企业数字化转型战略下的必备职业能力&#xff0c;促进开展工作实践应用及实际问题解决&#xff0c;形成企业所需的新数字经济下的核心职业…

Vue3——v-md-editor(markDown编辑器)使用教程

Vue3——v-md-editor安装使用教程 安装 # 使用 npm npm i kangc/v-md-editor -SEditorMarkdown.vue页面用来封装此编辑器组件 Test.vue作为接受EditorMarkdown.vue的父组件&#xff0c;当测试页使用 路由部分要放入test.vue main.js部分全局引入组件 import EditorMarkdown f…

操作系统权限维持(十一)之Linux系统-SSH Wrapper后门

系列文章 操作系统权限维持&#xff08;一&#xff09;之Windows系统-粘贴键后门 操作系统权限维持&#xff08;二&#xff09;之Windows系统-克隆账号维持后门 操作系统权限维持&#xff08;三&#xff09;之Windows系统-启动项维持后门 操作系统权限维持&#xff08;四&…

算法强化每日一题--字符串中找出连续最长的数字串

hi,大家好,今天为大家带来一道题目 OR59 字符串中找出连续最长的数字串 描述 读入一个字符串str&#xff0c;输出字符串str中的连续最长的数字串 输入描述&#xff1a; 个测试输入包含1个测试用例&#xff0c;一个字符串str&#xff0c;长度不超过255。 输出描述&#xff1a; 在…

北邮22信通:(8)实验1 题目五:大整数加减法(搬运官方代码)

北邮22信通一枚~ 跟随课程进度每周更新数据结构与算法的代码和文章 持续关注作者 解锁更多邮苑信通专属代码~ 上一篇文章&#xff1a; 北邮22信通&#xff1a;&#xff08;7&#xff09;实验1 题目四&#xff1a;一元多项式&#xff08;节省内存版&#xff09;_青山如…

【人人都能读标准】17. 底层算法:ECMAScript的错误处理机制

本文为《人人都能读标准》—— ECMAScript篇的第17篇。我在这个仓库中系统地介绍了标准的阅读规则以及使用方式&#xff0c;并深入剖析了标准对JavaScript核心原理的描述。 我们在11.程序完整执行过程说过&#xff0c;一个程序的运行会经历三个阶段&#xff1a;初始化Realm环境…

MyBatis-面试题

文章目录1.什么是MyBatis?2.#{}和${}的区别是什么&#xff1f;3.MyBatis的一级、二级缓存4.MyBatis的优缺点5.当实体类中的属性名和表中的字段名不一样 &#xff0c;怎么办 &#xff1f;6.模糊查询like语句该怎么写?7.Mybatis是如何进行分页的&#xff1f;分页插件的原理是什…

渗透测试之冰蝎实战

渗透测试之冰蝎实战1.基本使用2.命令执行&虚拟终端3.文件管理4.反弹shell5.内网资产扫描6.内网穿透7.数据库管理“冰蝎”是一款动态二进制加密网站管理客户端 下载地址 1.基本使用 运行冰蝎&#xff0c;打开传输协议&#xff1a; 生成一个php远程马&#xff1a; 点击生成…

【测试基础】之07 linux基础

Linux操作系统Linux操作系统介绍操作系统&#xff1a;管理计算机硬件与软件 资源的计算机程序&#xff0c;同时也是计算机系统的内核与基石。简单地说&#xff0c;操作系统就是出于用户与计算机系统硬件之间用于传递信息的系统程序软件。例如&#xff1a;操作系统会在接收到用户…

金三银四,你准备好面试了吗? (附30w字软件测试面试题总结)

不知不觉&#xff0c;已是3月下旬。最近有很多小伙伴都在跟我谈论春招面试的问题&#xff0c;其实对于面试&#xff0c;我也没有太多的经验&#xff0c;只能默默地把之前整理的软件测试面试题分享给Ta。今天就来大致的梳理一下软件测试的面试体系&#xff08;每一部分最后都有相…

Vue3学习笔记(5.0)

Vue.js循环语句 v-for指令需要以site in sites形式的特殊语法&#xff0c;sites是源数据数组并且site是数组元素迭代的别名。 v-for可以绑定数据到数组来渲染一个列表&#xff1a; <!--* Author: RealRoad1083425287qq.com* Date: 2023-03-26 16:26:51* LastEditors: Mei…

图解redis的client的实现

目录 1.引言 2.客户端属性 2.1套接字描述符 2.2 name 2.3 客户端标志 2.4输入缓冲区 2.5命令与命令参数 2.6命令实现的函数 2.7输出缓冲区 2.8身份验证 2.9 时间 3.客户端的创建的关闭 3.1普通客户端的创建 3.2普通客户端的关闭 3.AOF的伪客户端 1.引言 Redis服务…

(数字图像处理MATLAB+Python)第二章数字图像处理基础-第三、四节:数字图像的生成和数值描述

文章目录一&#xff1a;数字图像的生成与表示&#xff08;1&#xff09;图像信号的数字化&#xff08;2&#xff09;数字图像类型二&#xff1a;数字图像的数值描述&#xff08;1&#xff09;常用坐标系&#xff08;2&#xff09;数字图像的数据结构&#xff08;3&#xff09;常…

Typora使用

Typora Typora 是一款支持实时预览的 Markdown 文本编辑器。 1. 基础操作 1.1标题 # 一级标题## 二级标题### 三级标题#### 四级标题##### 五级标题###### 六级标题1.2 引用 > 引用内容1 > 引用内容2 >> 引用内容31.3 斜体 *斜体* _斜体_1.4 加粗…

mysql整理

文章目录概述SQLDDLDMLDQL单表查询多表查询DQL的执行顺序DCL管理用户控制权限函数约束事务存储引擎索引概述语法性能分析索引的使用SQL的优化insert优化主键优化Order by优化其它优化存储对象视图存储过程基本操作变量IF条件判断参数循环条件处理程序存储函数触发器锁全局锁表级…

Mysql-缓冲池 buffer pool

缓冲池 buffer pool innodb中的数据是以【页】的形式存储在磁盘上的表空间内&#xff0c;但是【磁盘的速度】和【内存】相比简直不值一提&#xff0c;而【内存的速度】和【cpu的速度】同样不可同日而语&#xff0c;对于数据库而言&#xff0c;I/O成本永远是不可忽略的一项成本…

基于Elman神经网络预测计费系统的输出(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 简单循环网络&#xff08;simple recurrent networks&#xff0c;简称SRN&#xff09;又称为Elman network&#xff0c;是由Jeff…

什么是AI文章生成器-AI文章生成器批量生成文章

AI文章生成器有哪些 目前市面上存在一些可以生成文章的 AI 文章生成器&#xff0c;以下是其中几种常见的&#xff1a; OpenAI GPT-3&#xff1a; OpenAI GPT-3 是目前最先进、最著名的 AI 文章生成器之一&#xff0c;它可以生成各种类型的文章&#xff0c;例如新闻报道、科学报…

我的Macbook pro使用体验

刚拿到Mac那一刻&#xff0c;第一眼很惊艳&#xff0c;不经眼前一亮&#xff0c;心想&#xff1a;这是一件艺术品&#xff0c;太好看了吧 而后再体验全新的Macos 系统&#xff0c;身为多年的win用户说实话一时间还是难以接受 1.从未见过的访达&#xff0c;不习惯的右键 2. …
最新文章