简述
Crypto ++ Library是一个免费的C ++类加密方案库。该库包含以下算法:
算法 |
名称 |
认证的加密方案 |
GCM,CCM,EAX |
高速流密码 |
ChaCha (8/12/20), Panama, Sosemanuk, Salsa20 (8/12/20), XSalsa20 |
AES |
AES (Rijndael), RC6, MARS, Twofish, Serpent, CAST-256 |
其他分组密码 |
ARIA,IDEA,Blowfish,Triple-DES(DES-EDE2和DES-EDE3), Camellia,SEED,Kalyna(128/256/512),RC5,SIMON(64/128),SPECK(64/128),SM4,Threefish(256/512/1024),Skipjack,SHACAL-2,TEA,XTEA |
分组密码模式的操作 |
ECB, CBC, CBC ciphertext stealing (CTS), CFB, OFB, counter mode (CTR) |
消息认证码 |
BLAKE2b and BLAKE2s, CMAC, CBC-MAC, DMAC, GMAC (GCM), HMAC, Poly1305, SipHash, Two-Track-MAC, VMAC |
散列函数 |
BLAKE2b and BLAKE2s, Keccack (F1600), SHA-1, SHA-2, SHA-3, Poly1305, SipHash, Tiger, RIPEMD (128, 256, 160, 320), SM3, WHIRLPOOL |
公钥密码学 |
RSA, DSA, Determinsitic DSA (RFC 6979), ElGamal, Nyberg-Rueppel (NR), Rabin-Williams (RW), EC-based German Digital Signature (ECGDSA), LUC, LUCELG, DLIES (variants of DHAES), ESIGN |
公钥系统的填充方案 |
PKCS#1 v2.0, OAEP, PSS, PSSR, IEEE P1363 EMSA2 and EMSA5 |
重要协议计划 |
Diffie-Hellman (DH), Unified Diffie-Hellman (DH2), Menezes-Qu-Vanstone (MQV), Hashed MQV (HMQV), Fully Hashed MQV (FHMQV), LUCDIF, XTR-DH |
椭圆曲线密码学 |
ECDSA, Determinsitic ECDSA (RFC 6979), ECGDSA, ECNR, ECIES, ECDH, ECMQV |
为保持向后兼容性和历史价值而保留不安全或过时的算法 |
MD2, MD4, MD5, Panama Hash, DES, ARC4, SEAL 3.0, WAKE-OFB, DESX (DES-XEX3), RC2, SAFER, 3-WAY, GOST, SHARK, CAST-128, Square |
截至到我撰写本文的日期2018/03/05为止,该算法库的最新版本是crypto++6.10。
官网链接:https://www.cryptopp.com/
编译
解压文件夹后,在windows下使用vs打开其中的.sln文件,可以在解决方案中看到四个项目工程,分别为cryptest、cryptlib、cryptopp、dlltest。
将编译模式设置为release,然后版本分别选择x86和x64,然后执行如下操作:
清理解决方案 -> 重新生成解决方案。
编译完成后,在子目录下生成Win32和x64两个文件夹,分别对应32位和64位版本的链接库。文件夹下有一个名为output的文件夹其中包含了crypttest.exe,cryptlib.lib,cryptlib.pdb三个文件。
crypttest.exe用于测试编译结果,我在使用该程序测试时发现示例输入文件有打不开而导致测试中断的情况,但是并不影响最终使用,这个文件删掉也可以。
cryptlib.lib是自己写的项目要链接的外部依赖库。
cryptlib.pdb用于收集调试信息。
在项目中使用
以debug模式的配置为例,在vs中新建一个空项目,然后作如下配置:
C/C++->常规->附加包含目录:C:\cryptopp610
C/C++->代码生成->运行库:MTD
连接器->常规->附加库目录:C:\cryptopp610\x64\Output\Debug
release模式的配置如上把,只不过把MTD换成MT,然后附加库目录改为Win32\Output\Release
然后在编写代码时,在文件开头加载外部依赖库,使用指令:
#pragma comment(lib, "cryptlib.lib" )
示例代码:
#include <aes.h>
#include <Hex.h> // StreamTransformationFilter
#include <modes.h> // CFB_Mode
#include <iostream> // std:cerr
#include <sstream> // std::stringstream
#include <string>
using namespace std;
using namespace CryptoPP;
#pragma comment(lib, "cryptlib.lib" )
std::string ECB_AESEncryptStr(std::string sKey, const char *plainText)
{
std::string outstr;
//填key
SecByteBlock key(AES::MAX_KEYLENGTH);
memset(key, 0x30, key.size());
sKey.size() <= AES::MAX_KEYLENGTH ? memcpy(key, sKey.c_str(), sKey.size()) : memcpy(key, sKey.c_str(), AES::MAX_KEYLENGTH);
AES::Encryption aesEncryption((byte *)key, AES::MAX_KEYLENGTH);
ECB_Mode_ExternalCipher::Encryption ecbEncryption(aesEncryption);
StreamTransformationFilter ecbEncryptor(ecbEncryption, new HexEncoder(new StringSink(outstr)));
ecbEncryptor.Put((byte *)plainText, strlen(plainText));
ecbEncryptor.MessageEnd();
return outstr;
}
std::string ECB_AESDecryptStr(std::string sKey, const char *cipherText)
{
std::string outstr;
//填key
SecByteBlock key(AES::MAX_KEYLENGTH);
memset(key, 0x30, key.size());
sKey.size() <= AES::MAX_KEYLENGTH ? memcpy(key, sKey.c_str(), sKey.size()) : memcpy(key, sKey.c_str(), AES::MAX_KEYLENGTH);
ECB_Mode<AES >::Decryption ecbDecryption((byte *)key, AES::MAX_KEYLENGTH);
HexDecoder decryptor(new StreamTransformationFilter(ecbDecryption, new StringSink(outstr)));
decryptor.Put((byte *)cipherText, strlen(cipherText));
decryptor.MessageEnd();
return outstr;
}
std::string CBC_AESEncryptStr(std::string sKey, std::string sIV, const char *plainText)
{
std::string outstr;
//填key
SecByteBlock key(AES::MAX_KEYLENGTH);
memset(key, 0x30, key.size());
sKey.size() <= AES::MAX_KEYLENGTH ? memcpy(key, sKey.c_str(), sKey.size()) : memcpy(key, sKey.c_str(), AES::MAX_KEYLENGTH);
//填iv
byte iv[AES::BLOCKSIZE];
memset(iv, 0x30, AES::BLOCKSIZE);
sIV.size() <= AES::BLOCKSIZE ? memcpy(iv, sIV.c_str(), sIV.size()) : memcpy(iv, sIV.c_str(), AES::BLOCKSIZE);
AES::Encryption aesEncryption((byte *)key, AES::MAX_KEYLENGTH);
CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption, iv);
StreamTransformationFilter cbcEncryptor(cbcEncryption, new HexEncoder(new StringSink(outstr)));
cbcEncryptor.Put((byte *)plainText, strlen(plainText));
cbcEncryptor.MessageEnd();
return outstr;
}
std::string CBC_AESDecryptStr(std::string sKey, std::string sIV, const char *cipherText)
{
std::string outstr;
//填key
SecByteBlock key(AES::MAX_KEYLENGTH);
memset(key, 0x30, key.size());
sKey.size() <= AES::MAX_KEYLENGTH ? memcpy(key, sKey.c_str(), sKey.size()) : memcpy(key, sKey.c_str(), AES::MAX_KEYLENGTH);
//填iv
byte iv[AES::BLOCKSIZE];
memset(iv, 0x30, AES::BLOCKSIZE);
sIV.size() <= AES::BLOCKSIZE ? memcpy(iv, sIV.c_str(), sIV.size()) : memcpy(iv, sIV.c_str(), AES::BLOCKSIZE);
CBC_Mode<AES >::Decryption cbcDecryption((byte *)key, AES::MAX_KEYLENGTH, iv);
HexDecoder decryptor(new StreamTransformationFilter(cbcDecryption, new StringSink(outstr)));
decryptor.Put((byte *)cipherText, strlen(cipherText));
decryptor.MessageEnd();
return outstr;
}
std::string CBC_CTS_AESEncryptStr(std::string sKey, std::string sIV, const char *plainText)
{
std::string outstr;
//填key
SecByteBlock key(AES::MAX_KEYLENGTH);
memset(key, 0x30, key.size());
sKey.size() <= AES::MAX_KEYLENGTH ? memcpy(key, sKey.c_str(), sKey.size()) : memcpy(key, sKey.c_str(), AES::MAX_KEYLENGTH);
//填iv
byte iv[AES::BLOCKSIZE];
memset(iv, 0x30, AES::BLOCKSIZE);
sIV.size() <= AES::BLOCKSIZE ? memcpy(iv, sIV.c_str(), sIV.size()) : memcpy(iv, sIV.c_str(), AES::BLOCKSIZE);
AES::Encryption aesEncryption((byte *)key, AES::MAX_KEYLENGTH);
CBC_CTS_Mode_ExternalCipher::Encryption cbcctsEncryption(aesEncryption, iv);
StreamTransformationFilter cbcctsEncryptor(cbcctsEncryption, new HexEncoder(new StringSink(outstr)));
cbcctsEncryptor.Put((byte *)plainText, strlen(plainText));
cbcctsEncryptor.MessageEnd();
return outstr;
}
std::string CBC_CTS_AESDecryptStr(std::string sKey, std::string sIV, const char *cipherText)
{
std::string outstr;
//填key
SecByteBlock key(AES::MAX_KEYLENGTH);
memset(key, 0x30, key.size());
sKey.size() <= AES::MAX_KEYLENGTH ? memcpy(key, sKey.c_str(), sKey.size()) : memcpy(key, sKey.c_str(), AES::MAX_KEYLENGTH);
//填iv
byte iv[AES::BLOCKSIZE];
memset(iv, 0x30, AES::BLOCKSIZE);
sIV.size() <= AES::BLOCKSIZE ? memcpy(iv, sIV.c_str(), sIV.size()) : memcpy(iv, sIV.c_str(), AES::BLOCKSIZE);
CBC_CTS_Mode<AES >::Decryption cbcctsDecryption((byte *)key, AES::MAX_KEYLENGTH, iv);
HexDecoder decryptor(new StreamTransformationFilter(cbcctsDecryption, new StringSink(outstr)));
decryptor.Put((byte *)cipherText, strlen(cipherText));
decryptor.MessageEnd();
return outstr;
}
std::string CFB_AESEncryptStr(std::string sKey, std::string sIV, const char *plainText)
{
std::string outstr;
//填key
SecByteBlock key(AES::MAX_KEYLENGTH);
memset(key, 0x30, key.size());
sKey.size() <= AES::MAX_KEYLENGTH ? memcpy(key, sKey.c_str(), sKey.size()) : memcpy(key, sKey.c_str(), AES::MAX_KEYLENGTH);
//填iv
byte iv[AES::BLOCKSIZE];
memset(iv, 0x30, AES::BLOCKSIZE);
sIV.size() <= AES::BLOCKSIZE ? memcpy(iv, sIV.c_str(), sIV.size()) : memcpy(iv, sIV.c_str(), AES::BLOCKSIZE);
AES::Encryption aesEncryption((byte *)key, AES::MAX_KEYLENGTH);
CFB_Mode_ExternalCipher::Encryption cfbEncryption(aesEncryption, iv);
StreamTransformationFilter cfbEncryptor(cfbEncryption, new HexEncoder(new StringSink(outstr)));
cfbEncryptor.Put((byte *)plainText, strlen(plainText));
cfbEncryptor.MessageEnd();
return outstr;
}
std::string CFB_AESDecryptStr(std::string sKey, std::string sIV, const char *cipherText)
{
std::string outstr;
//填key
SecByteBlock key(AES::MAX_KEYLENGTH);
memset(key, 0x30, key.size());
sKey.size() <= AES::MAX_KEYLENGTH ? memcpy(key, sKey.c_str(), sKey.size()) : memcpy(key, sKey.c_str(), AES::MAX_KEYLENGTH);
//填iv
byte iv[AES::BLOCKSIZE];
memset(iv, 0x30, AES::BLOCKSIZE);
sIV.size() <= AES::BLOCKSIZE ? memcpy(iv, sIV.c_str(), sIV.size()) : memcpy(iv, sIV.c_str(), AES::BLOCKSIZE);
CFB_Mode<AES >::Decryption cfbDecryption((byte *)key, AES::MAX_KEYLENGTH, iv);
HexDecoder decryptor(new StreamTransformationFilter(cfbDecryption, new StringSink(outstr)));
decryptor.Put((byte *)cipherText, strlen(cipherText));
decryptor.MessageEnd();
return outstr;
}
std::string OFB_AESEncryptStr(std::string sKey, std::string sIV, const char *plainText)
{
std::string outstr;
//填key
SecByteBlock key(AES::MAX_KEYLENGTH);
memset(key, 0x30, key.size());
sKey.size() <= AES::MAX_KEYLENGTH ? memcpy(key, sKey.c_str(), sKey.size()) : memcpy(key, sKey.c_str(), AES::MAX_KEYLENGTH);
//填iv
byte iv[AES::BLOCKSIZE];
memset(iv, 0x30, AES::BLOCKSIZE);
sIV.size() <= AES::BLOCKSIZE ? memcpy(iv, sIV.c_str(), sIV.size()) : memcpy(iv, sIV.c_str(), AES::BLOCKSIZE);
AES::Encryption aesEncryption((byte *)key, AES::MAX_KEYLENGTH);
OFB_Mode_ExternalCipher::Encryption ofbEncryption(aesEncryption, iv);
StreamTransformationFilter ofbEncryptor(ofbEncryption, new HexEncoder(new StringSink(outstr)));
ofbEncryptor.Put((byte *)plainText, strlen(plainText));
ofbEncryptor.MessageEnd();
return outstr;
}
std::string OFB_AESDecryptStr(std::string sKey, std::string sIV, const char *cipherText)
{
std::string outstr;
//填key
SecByteBlock key(AES::MAX_KEYLENGTH);
memset(key, 0x30, key.size());
sKey.size() <= AES::MAX_KEYLENGTH ? memcpy(key, sKey.c_str(), sKey.size()) : memcpy(key, sKey.c_str(), AES::MAX_KEYLENGTH);
//填iv
byte iv[AES::BLOCKSIZE];
memset(iv, 0x30, AES::BLOCKSIZE);
sIV.size() <= AES::BLOCKSIZE ? memcpy(iv, sIV.c_str(), sIV.size()) : memcpy(iv, sIV.c_str(), AES::BLOCKSIZE);
OFB_Mode<AES >::Decryption ofbDecryption((byte *)key, AES::MAX_KEYLENGTH, iv);
HexDecoder decryptor(new StreamTransformationFilter(ofbDecryption, new StringSink(outstr)));
decryptor.Put((byte *)cipherText, strlen(cipherText));
decryptor.MessageEnd();
return outstr;
}
std::string CTR_AESEncryptStr(std::string sKey, std::string sIV, const char *plainText)
{
std::string outstr;
//填key
SecByteBlock key(AES::MAX_KEYLENGTH);
memset(key, 0x30, key.size());
sKey.size() <= AES::MAX_KEYLENGTH ? memcpy(key, sKey.c_str(), sKey.size()) : memcpy(key, sKey.c_str(), AES::MAX_KEYLENGTH);
//填iv
byte iv[AES::BLOCKSIZE];
memset(iv, 0x30, AES::BLOCKSIZE);
sIV.size() <= AES::BLOCKSIZE ? memcpy(iv, sIV.c_str(), sIV.size()) : memcpy(iv, sIV.c_str(), AES::BLOCKSIZE);
AES::Encryption aesEncryption((byte *)key, AES::MAX_KEYLENGTH);
CTR_Mode_ExternalCipher::Encryption ctrEncryption(aesEncryption, iv);
StreamTransformationFilter ctrEncryptor(ctrEncryption, new HexEncoder(new StringSink(outstr)));
ctrEncryptor.Put((byte *)plainText, strlen(plainText));
ctrEncryptor.MessageEnd();
return outstr;
}
std::string CTR_AESDecryptStr(std::string sKey, std::string sIV, const char *cipherText)
{
std::string outstr;
//填key
SecByteBlock key(AES::MAX_KEYLENGTH);
memset(key, 0x30, key.size());
sKey.size() <= AES::MAX_KEYLENGTH ? memcpy(key, sKey.c_str(), sKey.size()) : memcpy(key, sKey.c_str(), AES::MAX_KEYLENGTH);
//填iv
byte iv[AES::BLOCKSIZE];
memset(iv, 0x30, AES::BLOCKSIZE);
sIV.size() <= AES::BLOCKSIZE ? memcpy(iv, sIV.c_str(), sIV.size()) : memcpy(iv, sIV.c_str(), AES::BLOCKSIZE);
CTR_Mode<AES >::Decryption ctrDecryption((byte *)key, AES::MAX_KEYLENGTH, iv);
HexDecoder decryptor(new StreamTransformationFilter(ctrDecryption, new StringSink(outstr)));
decryptor.Put((byte *)cipherText, strlen(cipherText));
decryptor.MessageEnd();
return outstr;
}
int main()
{
string plainText = "This Program shows how to use ECB, CBC, CBC_CTS, CFB, OFB and CTR mode of AES in Crypto++.";
string aesKey = "0123456789ABCDEF0123456789ABCDEF";//256bits, also can be 128 bits or 192bits
string aesIV = "ABCDEF0123456789";//128 bits
string ECB_EncryptedText, ECB_DecryptedText,
CBC_EncryptedText, CBC_DecryptedText,
CBC_CTS_EncryptedText, CBC_CTS_DecryptedText,
CFB_EncryptedText, CFB_DecryptedText,
OFB_EncryptedText, OFB_DecryptedText,
CTR_EncryptedText, CTR_DecryptedText;
//ECB
ECB_EncryptedText = ECB_AESEncryptStr(aesKey, plainText.c_str());//ECB加密
ECB_DecryptedText = ECB_AESDecryptStr(aesKey, ECB_EncryptedText.c_str());//ECB解密
//CBC
CBC_EncryptedText = CBC_AESEncryptStr(aesKey, aesIV, plainText.c_str());//CBC加密
CBC_DecryptedText = CBC_AESDecryptStr(aesKey, aesIV, CBC_EncryptedText.c_str());//CBC解密
//CBC_CTS
CBC_CTS_EncryptedText = CBC_CTS_AESEncryptStr(aesKey, aesIV, plainText.c_str());//CBC_CTS加密
CBC_CTS_DecryptedText = CBC_CTS_AESDecryptStr(aesKey, aesIV, CBC_CTS_EncryptedText.c_str());//CBC_CTS解密
//CFB
CFB_EncryptedText = CFB_AESEncryptStr(aesKey, aesIV, plainText.c_str());//CFB加密
CFB_DecryptedText = CFB_AESDecryptStr(aesKey, aesIV, CFB_EncryptedText.c_str());//CFB解密
//OFB
OFB_EncryptedText = OFB_AESEncryptStr(aesKey, aesIV, plainText.c_str());//OFB加密
OFB_DecryptedText = OFB_AESDecryptStr(aesKey, aesIV, OFB_EncryptedText.c_str());//OFB解密
//CTR
CTR_EncryptedText = CTR_AESEncryptStr(aesKey, aesIV, plainText.c_str());//CTR加密
CTR_DecryptedText = CTR_AESDecryptStr(aesKey, aesIV, CTR_EncryptedText.c_str());//CTR解密
cout << "Crypto++ AES-256 加密测试" << endl;
cout << "分别使用ECB,CBC, CBC_CTR,CFB,OFB和CTR模式" << endl;
cout << "加密用密钥:" << aesKey << endl;
cout << "密钥长度:" << AES::MAX_KEYLENGTH * 8 << "bits" << endl;
cout << "IV:" << aesIV << endl;
cout << endl;
cout << "ECB测试" << endl;
cout << "原文:" << plainText << endl;
cout << "密文:" << ECB_EncryptedText << endl;
cout << "恢复明文:" << ECB_DecryptedText << endl << endl;
cout << "CBC测试" << endl;
cout << "原文:" << plainText << endl;
cout << "密文:" << CBC_EncryptedText << endl;
cout << "恢复明文:" << CBC_DecryptedText << endl << endl;
cout << "CBC_CTS测试" << endl;
cout << "原文:" << plainText << endl;
cout << "密文:" << CBC_CTS_EncryptedText << endl;
cout << "恢复明文:" << CBC_CTS_DecryptedText << endl << endl;
cout << "CFB测试" << endl;
cout << "原文:" << plainText << endl;
cout << "密文:" << CFB_EncryptedText << endl;
cout << "恢复明文:" << CFB_DecryptedText << endl << endl;
cout << "OFB测试" << endl;
cout << "原文:" << plainText << endl;
cout << "密文:" << OFB_EncryptedText << endl;
cout << "恢复明文:" << OFB_DecryptedText << endl << endl;
cout << "CTR测试" << endl;
cout << "原文:" << plainText << endl;
cout << "密文:" << CTR_EncryptedText << endl;
cout << "恢复明文:" << CTR_DecryptedText << endl << endl;
getchar();
return 0;
}
运行结果: