服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C/C++ Crypto密码库调用的实现方法

C/C++ Crypto密码库调用的实现方法

2021-11-19 15:44极客熊猫GeekPanda C/C++

Crypto 库是C/C++的加密算法库,这个加密库很流行,基本上涵盖了市面上的各类加密解密算法,感兴趣的可以参考一下

Crypto 库是C/C++的加密算法库,这个加密库很流行,基本上涵盖了市面上的各类加密解密算法,以下代码是我在学习是总结的,放到这里用于后期需要时能够快速解决问题。

项目地址:https://www.cryptopp.com/

Sha256加密算法

Sha系列加密算法包括很多,基本上有以下几种格式的加密方式,位数越大加密强度越大,此算法属于单向加密算法与MD5类似但安全性高于MD5。

  • SHA-1:生成摘要的性能比MD5略低
  • SHA-256:可以生成长度256bit的信息摘要
  • SHA-224:可以生成长度224bit的信息摘要
  • SHA-384:可以生成长度384bit的信息摘要
  • SHA-512:可以生成长度512bit的信息摘要
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <iostream>
#include <Windows.h>
#include <string>
#include <sha.h>
#include <md5.h>
#include <crc.h>
#include <files.h>
#include <hex.h>
 
#pragma comment(lib, "cryptlib.lib")
using namespace std;
using namespace CryptoPP;
 
// 计算文件的 SHA256 值
string CalSHA256_ByFile(char *pszFileName)
{
 string value;
 SHA256 sha256;
 FileSource(pszFileName, true, new HashFilter(sha256, new HexEncoder(new StringSink(value))));
 return value;
}
 
// 计算数据的 SHA256 值
string CalSHA256_ByMem(PBYTE pData, DWORD dwDataSize)
{
 string value;
 SHA256 sha256;
 StringSource(pData, dwDataSize, true, new HashFilter(sha256, new HexEncoder(new StringSink(value))));
 return value;
}
 
int main(int argc, char * argv[])
{
 string src = "hello lyshark";
 string dst;
 
 // 单独计算MD5值的使用
 MD5 md5;
 StringSource(src, true, new HashFilter(md5, new HexEncoder(new StringSink(dst))));
 cout << "计算字符串MD5: " << dst << endl;
 
 // 单独计算CRC32值
 CRC32 crc32;
 StringSource(src, true, new HashFilter(crc32, new HexEncoder(new StringSink(dst))));
 cout << "计算字符串CRC32: " << dst << endl;
 
 // 计算一个数组
 BYTE pArrayData[] = { 10, 20, 30, 40, 50 };
 DWORD dwArraySize = sizeof(pArrayData);
 
 dst.clear();
 StringSource(pArrayData, dwArraySize, true, new HashFilter(md5, new HexEncoder(new StringSink(dst))));
 cout << "计算数组的MD5: " << dst << endl;
 
 // 直接对文件计算Sha256散列值
 string sha = CalSHA256_ByFile("c://BuidIAT.exe");
 cout << "文件散列值: " << sha << endl;
 
 // 读入文件到内存后计算
 HANDLE hFile = CreateFile(L"c://BuidIAT.exe", GENERIC_READ, FILE_SHARE_READ, NULL,
  OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL);
 DWORD dwFileSize = GetFileSize(hFile, NULL);
 BYTE *pData = new BYTE[dwFileSize];
 ReadFile(hFile, pData, dwFileSize, NULL, NULL);
 
 string sha2 = CalSHA256_ByMem(pData, dwFileSize);
 cout << "内存中文件散列值: " << sha2.c_str() << endl;
 system("pause");
 return 0;
}

AES 加密与解密

AES是对称加密,AES可使用16,24或32字节密钥(分别对应128,192和256位)。 Crypto++ 库缺省的密钥长度是16字节,也就是 AES:: DEFAULT_KEYLENGTH。

对于 ECB 和 CBC 模式,处理的数据必须是块大小的倍数。或者,你可以用 StreamTransformationFilter 围绕这个模式对象,并把它作为一个过滤器对象。StreamTransformationFilter 能够缓存数据到块中并根据需要填充。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include<cryptlib.h>
#include<osrng.h>
#include<iostream>
#include<files.h>
#include<aes.h>
#include<modes.h>
#include<hex.h>
 
#pragma comment(lib, "cryptlib.lib")
using namespace std;
using namespace CryptoPP;
 
int main(int argc, char * argv[])
{
 
 cout << "Key 长度: " << AES::DEFAULT_KEYLENGTH << endl;
 cout << "最小长度: " << AES::MIN_KEYLENGTH << endl;
 cout << "最大长度: " << AES::MAX_KEYLENGTH << endl;
 cout << "Block Size: " << AES::BLOCKSIZE << endl;
 
 AutoSeededRandomPool rand;
 
 // 产生一个随机数的密钥
 SecByteBlock Key(0x00, AES::DEFAULT_KEYLENGTH);
 rand.GenerateBlock(Key, Key.size());
 
 // 产生一个随机的初始向量
 SecByteBlock ival(AES::BLOCKSIZE);
 rand.GenerateBlock(ival, ival.size());
 
 byte plainText[] = "hello lyshark";
 size_t Textlen = std::strlen((char*)plainText) + 1;
 cout << "待加密字符串长度: " << Textlen << endl;
 
 // 加密字符串
 CFB_Mode<AES>::Encryption cfbEncryption(Key, Key.size(), ival);
 cfbEncryption.ProcessData(plainText, plainText, Textlen);
 
 cout << "显示加密后的十六进制数: ";
 StringSource strSource1(plainText, Textlen, true, new HexEncoder(new FileSink(cout)));
 
 // 解密字符串 并将数据输出到Cout流上
 CFB_Mode<AES>::Decryption cfbDecryption(Key, Key.size(), ival);
 cfbDecryption.ProcessData(plainText, plainText, Textlen);
 cout << endl << "显示解密后的十六进制数: ";
 StringSource strSource2(plainText, Textlen, true, new HexEncoder(new FileSink(cout)));
 cout << endl;
 
 system("pause");
 return 0;
}

以下代码使用CBC模式加密与解密指定字符串。如果需要针对字符串进行加解密则需要使用以下代码实现.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include<cryptlib.h>
#include<osrng.h>
#include<iostream>
#include<files.h>
#include<aes.h>
#include<modes.h>
#include<hex.h>
 
#pragma comment(lib, "cryptlib.lib")
using namespace std;
using namespace CryptoPP;
 
int main(int argc, char * argv[])
{
 // 开辟空间并将空间赋予初始值0
 byte key[CryptoPP::AES::DEFAULT_KEYLENGTH], iv[CryptoPP::AES::BLOCKSIZE];
 memset(key, 0x00, CryptoPP::AES::DEFAULT_KEYLENGTH);
 memset(iv, 0x00, CryptoPP::AES::BLOCKSIZE);
 
 // 指定需要加密的字符串与
 std::string plaintext = "hello lyshark this is palintext";
 std::string ciphertext;
 std::string decryptedtext;
 
 // 输出加密前字符串长度
 std::cout << "加密前字符串长度: " << plaintext.size() << " bytes" << std::endl;
 std::cout << plaintext;
 std::cout << std::endl << std::endl;
 
 // 创建并开始加密字符串
 CryptoPP::AES::Encryption aesEncryption(key, CryptoPP::AES::DEFAULT_KEYLENGTH);
 CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption, iv);
 
 CryptoPP::StreamTransformationFilter stfEncryptor(cbcEncryption, new CryptoPP::StringSink(ciphertext));
 stfEncryptor.Put(reinterpret_cast<const unsigned char*>(plaintext.c_str()), plaintext.length());
 stfEncryptor.MessageEnd();
 
 // 输出密文长度
 std::cout << "加密密文长度: " << ciphertext.size() << " bytes" << std::endl;
 for (int i = 0; i < ciphertext.size(); i++)
 {
  std::cout << "0x" << std::hex << (0xFF & static_cast<byte>(ciphertext[i])) << " ";
 }
 std::cout << std::endl << std::endl;
 
 // 解密被加密的字符串
 CryptoPP::AES::Decryption aesDecryption(key, CryptoPP::AES::DEFAULT_KEYLENGTH);
 CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv);
 
 CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink(decryptedtext));
 stfDecryptor.Put(reinterpret_cast<const unsigned char*>(ciphertext.c_str()), ciphertext.size());
 stfDecryptor.MessageEnd();
 
 // 输出解密后的字符串长度
 std::cout << "解密后的字符串: " << std::endl;
 std::cout << decryptedtext;
 std::cout << std::endl << std::endl;
 
 system("pause");
 return 0;
}

下面的示例使用CFB模式实现快速对字符串进行加解密,该模式的数据的长度并不需要是AES的块大小的倍数.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include<cryptlib.h>
#include<osrng.h>
#include<iostream>
#include<files.h>
#include<aes.h>
#include<modes.h>
#include<hex.h>
 
#pragma comment(lib, "cryptlib.lib")
using namespace std;
using namespace CryptoPP;
 
int main(int argc, char * argv[])
{
 AutoSeededRandomPool rand;
 
 // 生成随机Key
 SecByteBlock key(0x00, AES::DEFAULT_KEYLENGTH);
 rand.GenerateBlock(key, key.size());
 
 // 生成随机IV值
 byte iv[AES::BLOCKSIZE];
 rand.GenerateBlock(iv, AES::BLOCKSIZE);
 
 // 需要加密的字符串
 char plainText[] = "hello lyshark";
 int messageLen = (int)strlen(plainText) + 1;
 
 
 // 执行快速加密
 CFB_Mode<AES>::Encryption cfbEncryption(key, key.size(), iv);
 cfbEncryption.ProcessData((byte*)plainText, (byte*)plainText, messageLen);
 cout << "加密后的数据: " << plainText << endl;
 
 // 执行快速解密
 CFB_Mode<AES>::Decryption cfbDecryption(key, key.size(), iv);
 cfbDecryption.ProcessData((byte*)plainText, (byte*)plainText, messageLen);
 cout << "解密后的数据: " << plainText << endl;
 
 system("pause");
 return 0;
}

AES2 加密:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include<cryptlib.h>
#include<iostream>
#include <Windows.h>
 
#pragma comment(lib, "cryptlib.lib")
using namespace std;
using namespace CryptoPP;
 
// AES加密
BOOL AesEncrypt(BYTE *pPassword, DWORD dwPasswordLength, BYTE *pData, DWORD &dwDataLength, DWORD dwBufferLength)
{
 BOOL bRet = TRUE;
 HCRYPTPROV hCryptProv = NULL;
 HCRYPTHASH hCryptHash = NULL;
 HCRYPTKEY hCryptKey = NULL;
 do
 {
  // 获取CSP句柄
  bRet = CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT);
  if (FALSE == bRet)
   break;
 
  // 创建HASH对象
  bRet = CryptCreateHash(hCryptProv, CALG_MD5, NULL, 0, &hCryptHash);
  if (FALSE == bRet)
   break;
 
  // 对密钥进行HASH计算
  bRet = CryptHashData(hCryptHash, pPassword, dwPasswordLength, 0);
  if (FALSE == bRet)
   break;
 
  // 使用HASH来生成密钥
  bRet = CryptDeriveKey(hCryptProv, CALG_AES_128, hCryptHash, CRYPT_EXPORTABLE, &hCryptKey);
  if (FALSE == bRet)
   break;
 
  // 加密数据
  bRet = CryptEncrypt(hCryptKey, NULL, TRUE, 0, pData, &dwDataLength, dwBufferLength);
  if (FALSE == bRet)
   break;
 } while (FALSE);
 
 // 关闭释放
 if (hCryptKey)
  CryptDestroyKey(hCryptKey);
 if (hCryptHash)
  CryptDestroyHash(hCryptHash);
 if (hCryptProv)
  CryptReleaseContext(hCryptProv, 0);
 return bRet;
}
 
// AES解密
BOOL AesDecrypt(BYTE *pPassword, DWORD dwPasswordLength, BYTE *pData, DWORD &dwDataLength, DWORD dwBufferLength)
{
 BOOL bRet = TRUE;
 HCRYPTPROV hCryptProv = NULL;
 HCRYPTHASH hCryptHash = NULL;
 HCRYPTKEY hCryptKey = NULL;
 
 do
 {
  // 获取CSP句柄
  bRet = ::CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT);
  if (FALSE == bRet)
   break;
 
  // 创建HASH对象
  bRet = CryptCreateHash(hCryptProv, CALG_MD5, NULL, 0, &hCryptHash);
  if (FALSE == bRet)
   break;
 
  // 对密钥进行HASH计算
  bRet = CryptHashData(hCryptHash, pPassword, dwPasswordLength, 0);
  if (FALSE == bRet)
   break;
 
  // 使用HASH来生成密钥
  bRet = CryptDeriveKey(hCryptProv, CALG_AES_128, hCryptHash, CRYPT_EXPORTABLE, &hCryptKey);
  if (FALSE == bRet)
   break;
 
  // 解密数据
  bRet = CryptDecrypt(hCryptKey, NULL, TRUE, 0, pData, &dwDataLength);
  if (FALSE == bRet)
   break;
 } while (FALSE);
 
 // 关闭释放
 if (hCryptKey)
  CryptDestroyKey(hCryptKey);
 if (hCryptHash)
  CryptDestroyHash(hCryptHash);
 if (hCryptProv)
  CryptReleaseContext(hCryptProv, 0);
 return bRet;
}
 
int main(int argc, char * argv[])
{
 BYTE pData[MAX_PATH] = { 0 };
 DWORD dwDataLength = 0, dwBufferLength = MAX_PATH;
 
 lstrcpy((char *)pData, "hello lyshark");
 dwDataLength = 1 + lstrlen((char *)pData);
 
 // 原始十六进制数据
 printf("AES 原始数据 [%d]: ", dwDataLength);
 for (int i = 0; i < dwDataLength; i++)
 {
  printf("%02x ", pData[i]);
 }
 printf("\n\n");
 
 // AES 加密
 AesEncrypt((BYTE *)"AAAVCDERFGTYHUJI", 16, pData, dwDataLength, dwBufferLength);
 printf("AES 加密后 [%d]: ", dwDataLength);
 for (int i = 0; i < dwDataLength; i++)
 {
  printf("%02x ", pData[i]);
 }
 printf("\n\n");
 
 // AES 解密
 AesDecrypt((BYTE *)"AAAVCDERFGTYHUJI", 16, pData, dwDataLength, dwBufferLength);
 printf("AES 解密后 [%d]: ", dwDataLength);
 for (int i = 0; i < dwDataLength; i++)
 {
  printf("%02x ", pData[i]);
 }
 system("pause");
 return 0;
}

Base64加解密:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include<cryptlib.h>
#include<osrng.h>
#include<iostream>
#include <Windows.h>
#include<files.h>
#include<base64.h>
#include<modes.h>
#include<hex.h>
 
#pragma comment(lib, "cryptlib.lib")
using namespace std;
using namespace CryptoPP;
 
 
void DisplayHex(BYTE *pData, DWORD dwSize)
{
 for (int i = 0; i < dwSize; i++)
 {
  if ((0 != i) && (0 == i % 16))
   printf("\n");
  else if ((0 != i) && (0 == i % 8))
   printf(" ");
  printf("%02X ", pData[i]);
 }
 printf("\n");
}
 
int main(int argc, char * argv[])
{
 unsigned char plainText[] = "hello lyshark";
 
 // 对字符串编码
 string encoded;
 Base64Encoder encoder;
 encoder.Put(plainText, sizeof(plainText));
 encoder.MessageEnd();
 
 word64 size = encoder.MaxRetrievable();
 if (size)
 {
  encoded.resize(size);
  encoder.Get((byte *)&encoded[0], encoded.size());
 }
 cout << "编码后的数据: " << encoded << endl;
 
 // 对字符串解码
 string decoded;
 Base64Decoder decoder;
 decoder.Put((byte *)encoded.data(), encoded.size());
 decoder.MessageEnd();
 
 size = decoder.MaxRetrievable();
 if (size && size <= SIZE_MAX)
 {
  decoded.resize(size);
  decoder.Get((byte *)&decoded[0], decoded.size());
 }
 cout << "对字符串解码: " << decoded;
 
 // 输出解码字符串的十六进制格式
 char szOriginalData[] = "hello lyshark";
 
 cout << "字符串十六进制格式: ";
 DisplayHex((BYTE *)szOriginalData, (1 + lstrlen(szOriginalData)));
 
 system("pause");
 return 0;
}

Hash加密算法

使用hash算法计算特定文件的Hash值.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#include<cryptlib.h>
#include<iostream>
#include <Windows.h>
 
#pragma comment(lib, "cryptlib.lib")
using namespace std;
using namespace CryptoPP;
 
BOOL GetFileData(char *pszFilePath, BYTE **ppFileData, DWORD *pdwFileDataLength)
{
 BOOL bRet = TRUE;
 BYTE *pFileData = NULL;
 DWORD dwFileDataLength = 0;
 HANDLE hFile = NULL;
 DWORD dwTemp = 0;
 
 do
 {
  hFile = CreateFile(pszFilePath, GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ |
   FILE_SHARE_WRITE, NULL, OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE, NULL);
  if (INVALID_HANDLE_VALUE == hFile)
  {
   bRet = FALSE;
   break;
  }
 
  dwFileDataLength = ::GetFileSize(hFile, NULL);
  pFileData = new BYTE[dwFileDataLength];
  if (NULL == pFileData)
  {
   bRet = FALSE;
   break;
  }
  RtlZeroMemory(pFileData, dwFileDataLength);
  ReadFile(hFile, pFileData, dwFileDataLength, &dwTemp, NULL);
 
  // 返回
  *ppFileData = pFileData;
  *pdwFileDataLength = dwFileDataLength;
 } while (FALSE);
 
 if (hFile)
  CloseHandle(hFile);
 return bRet;
}
 
 
BOOL CalculateHash(BYTE *pData, DWORD dwDataLength, ALG_ID algHashType,
 BYTE **ppHashData, DWORD *pdwHashDataLength)
{
 HCRYPTPROV hCryptProv = NULL;
 HCRYPTHASH hCryptHash = NULL;
 BYTE *pHashData = NULL;
 DWORD dwHashDataLength = 0;
 DWORD dwTemp = 0;
 BOOL bRet = FALSE;
 
 do
 {
  // 获得指定CSP的密钥容器的句柄
  bRet = CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT);
  if (FALSE == bRet)
   break;
 
  // 创建一个HASH对象, 指定HASH算法
  bRet = CryptCreateHash(hCryptProv, algHashType, NULL, NULL, &hCryptHash);
  if (FALSE == bRet)
   break;
 
  // 计算HASH数据
  bRet = ::CryptHashData(hCryptHash, pData, dwDataLength, 0);
  if (FALSE == bRet)
   break;
 
  // 获取HASH结果的大小
  dwTemp = sizeof(dwHashDataLength);
  bRet = ::CryptGetHashParam(hCryptHash, HP_HASHSIZE, (BYTE *)(&dwHashDataLength), &dwTemp, 0);
  if (FALSE == bRet)
   break;
 
  // 申请内存
  pHashData = new BYTE[dwHashDataLength];
  if (NULL == pHashData)
  {
   bRet = FALSE;
   break;
  }
  RtlZeroMemory(pHashData, dwHashDataLength);
 
  // 获取HASH结果数据
  bRet = CryptGetHashParam(hCryptHash, HP_HASHVAL, pHashData, &dwHashDataLength, 0);
  if (FALSE == bRet)
   break;
 
  // 返回数据
  *ppHashData = pHashData;
  *pdwHashDataLength = dwHashDataLength;
 
 } while (FALSE);
 
 // 释放关闭
 if (FALSE == bRet)
 {
  if (pHashData)
  {
   delete[]pHashData;
   pHashData = NULL;
  }
 }
 if (hCryptHash)
  CryptDestroyHash(hCryptHash);
 if (hCryptProv)
  CryptReleaseContext(hCryptProv, 0);
 return bRet;
}
 
int main(int argc, char * argv[])
{
 BYTE *pData = NULL;
 DWORD dwDataLength = 0;
 BYTE *pHashData = NULL;
 DWORD dwHashDataLength = 0;
 
 // 获取文件流数据
 GetFileData("c://BuidIAT.exe", &pData, &dwDataLength);
 
 // 计算 MD5
 CalculateHash(pData, dwDataLength, CALG_MD5, &pHashData, &dwHashDataLength);
 printf("MD5 Hash -> ");
 for (int i = 0; i < dwHashDataLength; i++)
  printf("%x", pHashData[i]);
 printf("\n\n", dwHashDataLength);
 if (pHashData)
 {
  delete[]pHashData;
  pHashData = NULL;
 }
 
 // 计算 SHA1
 CalculateHash(pData, dwDataLength, CALG_SHA1, &pHashData, &dwHashDataLength);
 printf("SHA1 -> ");
 for (int i = 0; i < dwHashDataLength; i++)
  printf("%x", pHashData[i]);
 printf("\n\n", dwHashDataLength);
 if (pHashData)
 {
  delete[]pHashData;
  pHashData = NULL;
 }
 
 // 计算 SHA256
 CalculateHash(pData, dwDataLength, CALG_SHA_256, &pHashData, &dwHashDataLength);
 printf("SHA256 -> ");
 for (int i = 0; i < dwHashDataLength; i++)
  printf("%x", pHashData[i]);
 printf("\n\n", dwHashDataLength);
 if (pHashData)
 {
  delete[]pHashData;
  pHashData = NULL;
 }
 system("pause");
 return 0;
}

RSA加密算法

RSA算法包括公钥与私钥两部,加密时会先使用RSA生成公钥与私钥,然后在进行加密.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#include<iostream>
#include <Windows.h>
 
using namespace std;
 
// 生成公钥和私钥
BOOL GenerateKey(BYTE **ppPublicKey, DWORD *pdwPublicKeyLength, BYTE **ppPrivateKey, DWORD *pdwPrivateKeyLength)
{
 BOOL bRet = TRUE;
 HCRYPTPROV hCryptProv = NULL;
 HCRYPTKEY hCryptKey = NULL;
 BYTE *pPublicKey = NULL;
 DWORD dwPublicKeyLength = 0;
 BYTE *pPrivateKey = NULL;
 DWORD dwPrivateKeyLength = 0;
 
 do
 {
  // 获取CSP句柄
  bRet = CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0);
  if (FALSE == bRet)
   break;
 
  // 生成公私密钥对
  bRet = CryptGenKey(hCryptProv, AT_KEYEXCHANGE, CRYPT_EXPORTABLE, &hCryptKey);
  if (FALSE == bRet)
   break;
 
  // 获取公钥密钥的长度和内容
  bRet = CryptExportKey(hCryptKey, NULL, PUBLICKEYBLOB, 0, NULL, &dwPublicKeyLength);
  if (FALSE == bRet)
   break;
 
  pPublicKey = new BYTE[dwPublicKeyLength];
  RtlZeroMemory(pPublicKey, dwPublicKeyLength);
  bRet = CryptExportKey(hCryptKey, NULL, PUBLICKEYBLOB, 0, pPublicKey, &dwPublicKeyLength);
  if (FALSE == bRet)
   break;
 
  // 获取私钥密钥的长度和内容
  bRet = CryptExportKey(hCryptKey, NULL, PRIVATEKEYBLOB, 0, NULL, &dwPrivateKeyLength);
  if (FALSE == bRet)
   break;
 
  pPrivateKey = new BYTE[dwPrivateKeyLength];
  RtlZeroMemory(pPrivateKey, dwPrivateKeyLength);
  bRet = CryptExportKey(hCryptKey, NULL, PRIVATEKEYBLOB, 0, pPrivateKey, &dwPrivateKeyLength);
  if (FALSE == bRet)
   break;
 
  // 返回数据
  *ppPublicKey = pPublicKey;
  *pdwPublicKeyLength = dwPublicKeyLength;
  *ppPrivateKey = pPrivateKey;
  *pdwPrivateKeyLength = dwPrivateKeyLength;
 
 } while (FALSE);
 
 // 释放关闭
 if (hCryptKey)
  CryptDestroyKey(hCryptKey);
 if (hCryptProv)
  CryptReleaseContext(hCryptProv, 0);
 return bRet;
}
 
// 公钥加密数据
BOOL RsaEncrypt(BYTE *pPublicKey, DWORD dwPublicKeyLength, BYTE *pData, DWORD &dwDataLength, DWORD dwBufferLength)
{
 BOOL bRet = TRUE;
 HCRYPTPROV hCryptProv = NULL;
 HCRYPTKEY hCryptKey = NULL;
 
 do
 {
  // 获取CSP句柄
  bRet = CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0);
  if (FALSE == bRet)
   break;
 
  // 导入公钥
  bRet = CryptImportKey(hCryptProv, pPublicKey, dwPublicKeyLength, NULL, 0, &hCryptKey);
  if (FALSE == bRet)
   break;
 
  // 加密数据
  bRet = CryptEncrypt(hCryptKey, NULL, TRUE, 0, pData, &dwDataLength, dwBufferLength);
  if (FALSE == bRet)
   break;
 } while (FALSE);
 
 // 释放并关闭
 if (hCryptKey)
  CryptDestroyKey(hCryptKey);
 if (hCryptProv)
  CryptReleaseContext(hCryptProv, 0);
 return bRet;
}
 
// 私钥解密数据
BOOL RsaDecrypt(BYTE *pPrivateKey, DWORD dwProvateKeyLength, BYTE *pData, DWORD &dwDataLength)
{
 BOOL bRet = TRUE;
 HCRYPTPROV hCryptProv = NULL;
 HCRYPTKEY hCryptKey = NULL;
 
 do
 {
  // 获取CSP句柄
  bRet = CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0);
  if (FALSE == bRet)
   break;
 
  // 导入私钥
  bRet = CryptImportKey(hCryptProv, pPrivateKey, dwProvateKeyLength, NULL, 0, &hCryptKey);
  if (FALSE == bRet)
   break;
 
  // 解密数据
  bRet = CryptDecrypt(hCryptKey, NULL, TRUE, 0, pData, &dwDataLength);
  if (FALSE == bRet)
   break;
 } while (FALSE);
 
 // 释放并关闭
 if (hCryptKey)
  CryptDestroyKey(hCryptKey);
 if (hCryptProv)
  CryptReleaseContext(hCryptProv, 0);
 return bRet;
}
 
int main(int argc, char * argv[])
{
 BYTE *pPublicKey = NULL;
 DWORD dwPublicKeyLength = 0;
 BYTE *pPrivateKey = NULL;
 DWORD dwPrivateKeyLength = 0;
 BYTE *pData = NULL;
 DWORD dwDataLength = 0;
 DWORD dwBufferLength = 4096;
 
 pData = new BYTE[dwBufferLength];
 
 RtlZeroMemory(pData, dwBufferLength);
 lstrcpy((char *)pData, "hello lyshark");
 dwDataLength = 1 + lstrlen((char *)pData);
 
 // 输出加密前原始数据
 printf("加密前原始数据: ");
 for (int i = 0; i < dwDataLength; i++)
  printf("%x", pData[i]);
 printf("\n\n");
 
 // 生成公钥和私钥
 GenerateKey(&pPublicKey, &dwPublicKeyLength, &pPrivateKey, &dwPrivateKeyLength);
 printf("公钥: ");
 for (int i = 0; i < dwPublicKeyLength; i++)
  printf("%.2x", pPublicKey[i]);
 printf("\n\n");
 
 printf("私钥: ");
 for (int i = 0; i < dwPrivateKeyLength; i++)
  printf("%.2x", pPrivateKey[i]);
 printf("\n\n");
 
 // 使用公钥加密
 RsaEncrypt(pPublicKey, dwPublicKeyLength, pData, dwDataLength, dwBufferLength);
 printf("公钥加密: ");
 for (int i = 0; i < dwDataLength; i++)
  printf("%x", pData[i]);
 printf("\n\n");
 
 // 使用私钥解密
 RsaDecrypt(pPrivateKey, dwPrivateKeyLength, pData, dwDataLength);
 printf("私钥解密: ");
 for (int i = 0; i < dwDataLength; i++)
  printf("%x", pData[i]);
 printf("\n\n");
 
 delete[]pData;
 delete[]pPrivateKey;
 delete[]pPublicKey;
 
 system("pause");
 return 0;
}

Crypt库实现RSA加密

RSA加密一般使用公钥加密私钥解密,先生成公钥与私钥,然后使用这两份密钥对字符串等数据进行操作.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include<cryptlib.h>
#include<osrng.h>
#include<iostream>
#include<files.h>
#include <Windows.h>
#include <rsa.h>
#include <hex.h>
#include<modes.h>
 
#pragma comment(lib, "cryptlib.lib")
using namespace std;
using namespace CryptoPP;
 
// 定义全局随机数池
RandomPool & GlobalRNG();
RandomPool & GlobalRNG()
{
 static RandomPool randomPool;
 return randomPool;
}
 
// 生成RSA密钥对
BOOL GenerateRSAKey(DWORD dwRSAKeyLength, char *pszPrivateKeyFileName, char *pszPublicKeyFileName, BYTE *pSeed, DWORD dwSeedLength)
{
 RandomPool randPool;
 randPool.Put(pSeed, dwSeedLength);
 
 // 生成RSA私钥
 RSAES_OAEP_SHA_Decryptor priv(randPool, dwRSAKeyLength);
 HexEncoder privFile(new FileSink(pszPrivateKeyFileName)); // 打开文件实行序列化操作
 
 priv.DEREncode(privFile);
 privFile.MessageEnd();
 
 // 生成RSA公钥
 RSAES_OAEP_SHA_Encryptor pub(priv);
 HexEncoder pubFile(new FileSink(pszPublicKeyFileName));  // 打开文件实行序列化操作
 
 pub.DEREncode(pubFile);          // 写密码对象pub到文件对象pubFile里
 pubFile.MessageEnd();
 return TRUE;
}
 
/* 此处的加密算法是通过文件中的公钥与私钥进行加密的*/
// RSA加密字符串
string RSA_Encrypt_ByFile(char *pszOriginaString, char *pszPublicKeyFileName, BYTE *pSeed, DWORD dwSeedLength)
{
 RandomPool randPool;
 randPool.Put(pSeed, dwSeedLength);
 
 FileSource pubFile(pszPublicKeyFileName, TRUE, new HexDecoder);
 RSAES_OAEP_SHA_Encryptor pub(pubFile);
 
 // 加密
 string strEncryptString;
 StringSource(pszOriginaString, TRUE, new PK_EncryptorFilter(randPool, pub, new HexEncoder(new StringSink(strEncryptString))));
 return strEncryptString;
}
// RSA解密字符串
string RSA_Decrypt_ByFile(char *pszEncryptString, char *pszPrivateKeyFileName)
{
 FileSource privFile(pszPrivateKeyFileName, TRUE, new HexDecoder);
 RSAES_OAEP_SHA_Decryptor priv(privFile);
 
 string strDecryptString;
 StringSource(pszEncryptString, TRUE, new HexDecoder(new PK_DecryptorFilter(GlobalRNG(), priv, new StringSink(strDecryptString))));
 return strDecryptString;
}
 
/* 通过在内存中的密钥对进行加密与解密 */
// RSA加密字符串
string RSA_Encrypt_ByMem(char *pszOriginaString, char *pszMemPublicKey, BYTE *pSeed, DWORD dwSeedLength)
{
 RandomPool randPool;
 randPool.Put(pSeed, dwSeedLength);
 
 StringSource pubStr(pszMemPublicKey, TRUE, new HexDecoder);
 RSAES_OAEP_SHA_Encryptor pub(pubStr);
 
 // 加密
 string strEncryptString;
 StringSource(pszOriginaString, TRUE, new PK_EncryptorFilter(randPool, pub, new HexEncoder(new StringSink(strEncryptString))));
 return strEncryptString;
}
// RSA解密字符串
string RSA_Decrypt_ByMem(char *pszEncryptString, char *pszMemPrivateKey)
{
 StringSource privStr(pszMemPrivateKey, TRUE, new HexDecoder);
 RSAES_OAEP_SHA_Decryptor priv(privStr);
 
 string strDecryptString;
 StringSource(pszEncryptString, TRUE, new HexDecoder(new PK_DecryptorFilter(GlobalRNG(), priv, new StringSink(strDecryptString))));
 return strDecryptString;
}
 
int main(int argc, char * argv[])
{
 // 指定公钥与私钥所在文件目录
 char szPrivateFile[] = "c://private.key";
 char szPublicFile[] = "c://public.key";
 
 // 指定一串随机数种子
 char szSeed[] = "ABCDESGHETYSQDGH";
 
 // 以下就是待加密的字符串
 char szOriginalString[] = "hello lyshark";
 
 /* 此处是从文件中读取出公钥与私钥对特定字符串进行加密与解密 */
 // 生成RSA公私密钥对
 GenerateRSAKey(1024, szPrivateFile, szPublicFile, (BYTE *)szSeed, lstrlen(szSeed));
 
 // RSA公钥加密字符串
 string strEncryptString = RSA_Encrypt_ByFile(szOriginalString, szPublicFile, (BYTE *)szSeed, lstrlen(szSeed));
 
 // RSA私钥解密字符串
 string strDecryptString = RSA_Decrypt_ByFile((char *)strEncryptString.c_str(), szPrivateFile);
 
 // 显示
 printf("原文字符串:\t[%d]%s\n", lstrlen(szOriginalString), szOriginalString);
 printf("密文字符串:\t[%d]%s\n", strEncryptString.length(), strEncryptString.c_str());
 printf("明文字符串:\t[%d]%s\n", strDecryptString.length(), strDecryptString.c_str());
 printf("\n\n");
 
 // --------------------------------------------------------------------------------------------------------------
 /* 此处是在内存中对指定字符串进行解密*/
 char g_szPubKey[] = "填充公钥";
 char g_szPrivKey[] = "填充私钥";
 
 // RSA公钥加密字符串
 string strEncryptString_Mem = RSA_Encrypt_ByMem(szOriginalString, g_szPubKey, (BYTE *)szSeed, ::lstrlen(szSeed));
 // RSA私钥解密字符串
 string strDecryptString_Mem = RSA_Decrypt_ByMem((char *)strEncryptString_Mem.c_str(), g_szPrivKey);
 // 显示
 printf("原文字符串:\n[%d]%s\n", ::lstrlen(szOriginalString), szOriginalString);
 printf("密文字符串:\n[%d]%s\n", strEncryptString_Mem.length(), strEncryptString_Mem.c_str());
 printf("明文字符串:\n[%d]%s\n", strDecryptString_Mem.length(), strDecryptString_Mem.c_str());
 system("pause");
 return 0;

到此这篇关于C/C++ Crypto密码库调用的实现方法的文章就介绍到这了,更多相关C++ Crypto密码库内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/qq_29186859/article/details/118345549

延伸 · 阅读

精彩推荐