【翠字营原创】基于 cryptlib.lib 开发的几种加密解密算法经典例子 涉及: MD5 AES AES-CBC 希望对大家学习有帮助!

这几天初步研究了一下加密解密算法, 查了不少的资料, 发现中文网上的资料不是很好, 很多说的云里雾里, 对于初步了解学习密码算法的同志很是头痛,不知道是大家都很懂还是有多保留哦

下面把自己完成的测试通过的代码和大家晒一下, 希望对大家有益!

注:不才了解不足, 有什么不足的请大家拍砖, 共同进步!

#include

#include

using namespace std;

 

#include "aes.h"

#include "md5.h"

#include "modes.h"

#include "filters.h"

using namespace CryptoPP;

 

 

int main(int argc, char* argv[])

{

  

//======================== MD5算法====================

   std::cout<<"======= MD5算法======="<<std::endl;

   std::string strInput = "";

   std::cout<<"Pls input message info"<<std::endl;

   std::cin>>strInput;

 

   //MD5算法的输入内容可以是任意长度的字符串

   int len = strInput.length();

   byte *message = new byte[len+1];

   message[len]=0;

   memcpy(message,strInput.c_str(),len+1);

   std::cout<<"message: "<<message<<endl;

 

   //MD5生成的信息摘要固定长度位(个字节)

   byte digest[16];

   MD5 md5;

   md5.CalculateDigest(digest, message, len); //等价于下面两行代码之和

   //注意,此处len必须是message的字符长度,否则生成的哈希值会一次一变

   //md5.Update(message, len);

   //md5.Final(digest);

 

   std::cout<<"Algorithm name :"<<md5.AlgorithmName()<<std::endl;

   std::cout<<"md5 digest";

   for(int i=0; i<16; i++)

   {

      printf("%02x", digest[i]);

   }

   cout<<endl;

 

//======================== 普通AES加密解密====================

   //AES可以使用byte192bytebyte的密钥

   //只能加密位的数据块,加密后的数据块长度也是位

   std::cout<<"====== 普通AES加密解密======"<<std::endl;

   cout << "Algorithm name: " << AES::StaticAlgorithmName() << endl;     

   cout << "Block size: " <<AES::BLOCKSIZE<<"字节"<< AES::BLOCKSIZE * 8 <<""<<endl;

   cout << "default key length: " <<AES::DEFAULT_KEYLENGTH<<"字节"<< AES::DEFAULT_KEYLENGTH * 8 <<""<<endl;

   cout << "Min key length: " <<AES::MIN_KEYLENGTH<<"字节"<< AES::MIN_KEYLENGTH * 8 <<""<<endl;

   cout << "Max key length: " <<AES::MAX_KEYLENGTH<<"字节"<< AES::MAX_KEYLENGTH * 8 <<""<<endl;

  

   //AES中只包含一些固定的数据,而加密解密的功能由AESEncryptionAESDecryption来完成

   //加密过程

   unsigned char aesKey[AES::DEFAULT_KEYLENGTH] = "123456789012345";    //密钥

 

   //inBloc数组中设置准备测试的数据块信息

   unsigned char inBlock[AES::BLOCKSIZE+1] = "abcdefghijklmnop";

   //unsigned char inBlock[AES::BLOCKSIZE+1];    //要加密的数据块

   unsigned char outBlock[AES::BLOCKSIZE];   //加密后的密文块

 

   //对于普通AES加密解密不需要指定异或数组序列,也可以指定置为的异或数组

   //unsigned char xorBlock[AES::BLOCKSIZE]; //必须设定为全零

   //memset( xorBlock, 0, AES::BLOCKSIZE );  /置零

 

   /*

   //准备把MD5值进行AES加密解密

   memcpy(inBlock,digest,AES::BLOCKSIZE);

   inBlock[AES::BLOCKSIZE]= 0;*/

 

   cout<<"加密前的明文:";

   cout<<"inBlock: "<<inBlock<<endl;

 

   //加密

   AESEncryption aesEncryptor; //加密器

   aesEncryptor.SetKey( aesKey, AES::DEFAULT_KEYLENGTH );  //设定加密密钥

   aesEncryptor.ProcessAndXorBlock( inBlock, NULL, outBlock ); 

 

   //以进制显示加密后的数据

   cout<<"加密后的密文:";

   for( int i=0; i<16; i++ )

   {

      cout << hex << (int)outBlock[i] << " ";

   }

   cout << endl;

 

 

 

   //解密

   unsigned char plainText[AES::BLOCKSIZE];

   AESDecryption aesDecryptor;

  

   //如果修改密钥,解码不正确

   //aesKey[0]= 'x';

   aesDecryptor.SetKey( aesKey, AES::DEFAULT_KEYLENGTH );

   aesDecryptor.ProcessAndXorBlock( outBlock, NULL, plainText );

  

   cout<<"解密后的明文:";

   for( int i=0; i<16; i++ )

   {     

      cout << plainText[i];   

   }

   cout << endl; 

 

//======================== AES-CBC模式加密解密====================

/*

由于加密解密算法,密钥长度和数据块长度都是固定的,但是在实际应用中明文的长度是不确定的,而且会远大于

加密解密算法中数据块的固定长度,所以这个时候就需要使用一定的模式来处理这些情况。就出现了现在的几种

加密解密模式,比如:ECBCBCCFB等。这些模式提供分块,缓存,补充字节,加密解密等功能,提供开发效率。

 

1ECB(Electronic Code Book:电码本)

ECB是最简单的模式,同样的明文分组总是加密成相同的密文分组。这对于发送

单一的块数据来说是非常好的,如密钥。但对执行一个加密的信息流来说不是很好,因为如果相同的明文多次发送以

后,同样的密文也会被多次发送。

ECB最大的弱点是对每一个块用相同的方式进行加密。如果我们的密钥或者数据不断发生变化,ECB是完全安全的。

但是如果类似的块经过同样的密钥加密发出以后,攻击者可能获得一些我们并不想让别人知道的信息。

 

2CBC(Cipher Block Chaining:密码分组链接)

CBC模式改变了加密方式,同样的明文分组不一定加密或解密同样的密文块,因此解决了ECB存在的主要问题。

CBC使用前一分组的信息加密当前分组。因此和ECB模式大不相同。这个方法依然存在问题,那就是相同的信息

仍然加密成相同的密文,因为所有的分组是同时变成密文分组的。为了解决这个问题,引入一个

Initialization Vector(初始化向量),也就是前不久有人问到的IV问题。IV仅仅是一个初始化加密程序的随机数。

它无需秘密保存,但队每一个信息来说它都是不同的,通过这个方式,即使有两条相同的信息,只要他们有不同的IV

,那么他们加密后的密文也是不同的。从这个意义上来说,初始化向量无疑就和口令加密过程中使用的盐值是一样的。

CBC很适合文本传输,但它每一次都需要传送一个完整的数据块,一般选个字符。

 

3CFB(Cipher FeedBack:密码反馈)

CFB的工作方式与CBC类似,但它可以执行更小的数据块,典型的有位,这非常适合加密像聊天对话这样的信息,

因为每次可以发送单一的字节数据块。和CBC一样,CFB也需要一个IV,且相同及钥发送的每条信息的IV都必须

是唯一的。

 

4OFB(Output FeedBack:输出反馈) OFB除了在传输中能给数据提供更好的保护,防止数据丢失外,其他和CFB类似。

密文中一位出错,也只造成明文中的一位出错,其他的方式会造成整个块丢失。和CBC以及CFB一样,OFB也需要一个IV

 

*/

 

   std::cout<<"====== AES-CBC加密解密======"<<std::endl;

   cout << "Encryption Algorithm name: " << CBC_Mode_ExternalCipher::Encryption::StaticAlgorithmName()<< endl;

   cout << "Decryption Algorithm name: " << CBC_Mode_ExternalCipher::Decryption::StaticAlgorithmName()<< endl;

  

   //设置aes 密钥

   byte key[AES::DEFAULT_KEYLENGTH] = "1234567890";

   //设置初始向量组, 可以默认随机,但是一旦指定,加密和解密必须使用相同的初始向量组

   byte iv[AES::BLOCKSIZE] = "sky";

   //memset( iv, 0, AES::BLOCKSIZE);

 

   std::string plaintext = "You're probably using a *.* wildcard. 7-Zip doesn't use /

the operating system's wildcard mask parser, and consequently treats *.* as any /

file that has an extension. To process all files you must use the * wildcard /

instead or omit the wildcard altogether.";

 

   std::cout << "加密前的明文(" <<dec<< plaintext.size() << " bytes): " << std::endl;

   std::cout << plaintext;

   std::cout << std::endl << std::endl;

 

   //加密

   std::string strCiphertext = "";

   AES::Encryption aesEncryption;

   aesEncryption.SetKey(key, AES::DEFAULT_KEYLENGTH);

 

  

   CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption, iv);

   //等同于下面两句构建基于AES 算法的CBC模式

   //CBC_Mode::Encryption cbcEncryption;

   //cbcEncryption.SetKeyWithIV(key, AES::DEFAULT_KEYLENGTH, iv);

 

   StreamTransformationFilter stfEncryptor(cbcEncryption, new StringSink(strCiphertext));

   stfEncryptor.Put((byte*)(plaintext.c_str()),plaintext.length());

   stfEncryptor.MessageEnd();

 

   std::cout << "加密后的密文(" << strCiphertext.size() << " bytes)" << std::endl;

   int iCipherTextSize = strCiphertext.size();

   for( int i = 0; i<iCipherTextSize; i++)

   {

      std::cout <<hex << (0xFF & static_cast<byte>(strCiphertext[i])) << " ";

   }

   std::cout << std::endl << std::endl;

 

   //解密

   std::string strDecryptedText = "";

   AESDecryption aesDecryption;

   aesDecryption.SetKey(key, AES::DEFAULT_KEYLENGTH);

   CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv);

   StreamTransformationFilter stfDecryptor(cbcDecryption, new StringSink(strDecryptedText));

  stfDecryptor.Put((byte*)(strCiphertext.c_str() ),strCiphertext.length());

   stfDecryptor.MessageEnd();

 

   std::cout << "解密后的明文("<<dec<<strDecryptedText.size()<<" bytes)"<<endl;

   cout<<strDecryptedText.c_str()<<endl;

 

   return 0;

}

===============

输出结果:

======= MD5算法=======
P
ls input message info:
sadasagfafafasfaf
message: sadasagfafafasfaf
Algorithm name ::MD5
md5 digest:17bb7a8c4eee8c030e5a54c7984fdfe4


====== 普通AES加密解密 ======
Algorithm name: AES
Block size: 16字节 128位
default key length: 16字节 128位
Min key length: 16字节 128位
Max key length: 32字节 256位
加密前的明文:inBlock: abcdefghijklmnop
加密后的密文:1c 58 c5 f0 61 b4 84 da 8e 7b 56 e4 e3 83 df c6
解密后的明文:abcdefghijklmnop

====== AES-CBC加密解密 ======
Encryption Algorithm name: CBC
Decryption Algorithm name: CBC
加密前的明文 (253 bytes):
You're probably using a *.* wildcard. 7-Zip doesn't use the operating system's w
ildcard mask parser, and consequently treats *.* as any file that has an extensi
on. To process all files you must use the * wildcard instead or omit the wildcar
d altogether.

 

加密后的密文 (256 bytes):
6d 6 4d 8e 42 56 18 5f eb 8c 46 c7 15 68 40 fe 9b fb 88 b9 90 78 ab 1a a7 bc 95
59 e9 2f 73 ee 31 dc 5f be f3 27 af 1a e4 4f 50 19 dc 59 37 c7 a4 3c 4b 79 47 b5
 9b a7 ad e3 85 28 1a 8b 9c aa 37 ea 26 1 6d ef f1 f 80 8e 2a d3 b2 46 68 97 cf
b a5 ae a6 a 78 30 ad d3 ea 4c 8a ac 20 84 88 4 c9 df 61 6a 13 5a b6 e0 58 6 78
d1 ff ed 8d 8c fa d5 c3 e6 21 34 52 38 f2 b1 ee a6 a 1 15 1 81 e8 63 db fe 3b cb
 25 f5 76 6e a8 a9 f3 c7 9 78 de 19 24 19 f7 bb b6 b3 74 e 96 22 db d9 e3 1b d7
50 ff e0 63 29 2b 80 57 f7 bf 91 e7 1a fd be 2b 18 65 83 53 8 e2 fe 68 6e 54 e8
cd d8 c6 4f 53 87 a8 80 fd 5a cd ff e5 78 7d 4a ce 8 ca fa a9 75 de 13 96 3e 61
59 3e 4d 23 8a 17 8c 25 73 a5 67 b9 ef 96 ee c9 69 d8 b4 f4 a9 4 7f 6e fa 53 a9
18 d1 c1 34 75 7e b9 65 1a 4b 4

解密后的明文(253 bytes):
You're probably using a *.* wildcard. 7-Zip doesn't use the operating system's w
ildcard mask parser, and consequently treats *.* as any file that has an extensi
on. To process all files you must use the * wildcard instead or omit the wildcar
d altogether.

你可能感兴趣的:(C++)