Crypto++入门学习笔记(DES、AES、RSA、SHA-256)详解编程语言

最先附上 下载地址 

 

背景(只是个人感想,技术上不对后面的内容构成知识性障碍,可以skip):

最近,基于某些原因和需要,笔者需要去了解一下Crypto++库,然后对一些数据进行一些加密解密的操作。

笔者之前没接触过任何加密解密方面的知识(当然,把每个字符的ASCII值加1之流对明文进行加密的“趣事”还是干过的,当时还很乐在其中。),甚至一开始连Crypto++的名字都没有听过,被BS了之后,就开始了Crypto++的入门探索过程。

最初,大概知道了要了解两大类算法中的几个算法——对称加密算法:DES、AES(后来因为人品好的缘故也了解了下非对称加密算法RSA,后文会详述何谓“人品好”);散列算法(需要通过Hash运算):SHA-256。

起初,笔者以为这样的知名算法在网上应该有很多现成的例子。笔者比较懒,对于自己不熟悉的东西,总希望找捷径,直接找别人现(在已经写)成可(编译运)行的代码然后施展ctrl + C,ctrl + V算法(咳,什么算法,是大法!!!)。

However,发觉网上的例子不是稀缺,就是只有代码没有解释。笔者觉得很难忍受这样的“莫名其妙”(奇怪的是笔者容忍了windows了,尽管它不开源),遂决定从零开始……

 

 

 

……写在代码前……

      如果之前像笔者一样没相关经验——完全没接触过加密解密——,请务必阅读下文。
 

一些前期工作——编译cryptlib并使其可用:

      本文不涉及这部分内容,因为已经有相对完善的资料:
        IT虾米网

 

总结了一点预备知识:

关于几个算法的介绍,网上各大百科都有,笔者不再详细Ctrl+C/V了。不过在写代码之前,即使复制修改人家代码之前,也有必要了解一下几个算法(除了名称之外)的使用流程(不是算法具体的实现,汗!)。

 

对称加密:(AES、DES)

相对于与非对称加密而言,加密、解密用的密匙相同。就像日常生活中的钥匙,开门和锁门都是同一把。

详见:IT虾米网

 

非对称加密:(RSA)

相对于上述的对称加密而言,加密、解密用的密匙不同,有公匙和私匙之分。

详见:IT虾米网 

散列算法:(SHA系列,我们熟悉的MD5等)

用途:验证信息有没有被修改。

原理:对长度大的信息进行提炼(通过一个Hash函数),提炼过后的信息长度小很多,得到的是一个固定长度的值(Hash值)。对于两个信息量很大的文件通过比较这两个值,就知道这两个文件是否完全一致(另外一个文件有没有被修改)。从而避免了把两个文件中的信息进行逐字逐句的比对,减少时间开销。

形象地描述:鬼泣3里面维吉尔跟但丁除了发型之外都很像。怎么区分两个双生子?比较他们的DNA就好比是比较信息量很大的文件,然而直接看发型就好比是看Hash值。一眼就看出来了。

 

注:以上是笔者对几个概念的,非常不严格的,非常主观的,概括的描述,想要详细了解,可以:

IT虾米网

几个算法的介绍,选择,比较。

 

 

 

……Code speaking……

 

平台:WindowsXP

IDE以及工具:Visual Studio 2008 + Visual Assist

库版本:Crypto++ 5.6.0

 

 

库的文档(包括类和函数的接口列表):
IT虾米网

 

 

对称加密算法:

DES:

一开始笔者并没有找到关于DES运用的很好的例程,或者说,笔者的搜索功力薄弱,未能找到非常完整的例程吧。

IT虾米网

笔者以下的代码主要是参考上面URL的论坛回帖,但是作了些修改:

 

 1#include <iostream> 
2#include <des.h> 
3 
4#pragma comment( lib, "cryptlib.lib" ) 
5 
6using namespace std; 
7using namespace CryptoPP; 
8 
9int main( void ) 
10{ 
11    //主要是打印一些基本信息,方便调试: 
12    cout << "DES Parameters: " << endl; 
13    cout << "Algorithm name : " << DES::StaticAlgorithmName() << endl;  
14     
15    unsigned char key[ DES::DEFAULT_KEYLENGTH ]; 
16    unsigned char input[ DES::BLOCKSIZE ] = "12345"; 
17    unsigned char output[ DES::BLOCKSIZE ]; 
18    unsigned char txt[ DES::BLOCKSIZE ]; 
19 
20    cout << "input is: " << input << endl; 
21 
22    //可以理解成首先构造一个加密器 
23    DESEncryption encryption_DES; 
24 
25    //回忆一下之前的背景,对称加密算法需要一个密匙。加密和解密都会用到。 
26    //因此,设置密匙。 
27    encryption_DES.SetKey( key, DES::KEYLENGTH ); 
28    //进行加密 
29    encryption_DES.ProcessBlock( input, output ); 
30 
31    //显示结果 
32    //for和for之后的cout可有可无,主要为了运行的时候看加密结果 
33    //把字符串的长度写成一个常量其实并不被推荐。 
34    //不过笔者事先知道字符串长,为了方便调试,就直接写下。 
35    //这里主要是把output也就是加密后的内容,以十六进制的整数形式输出。 
36    for( int i = 0; i < 5; i++ ) 
37    { 
38        cout << hex << (int)output[ i ] << ends; 
39    } 
40    cout << endl; 
41 
42    //构造一个加密器 
43    DESDecryption decryption_DES;     
44 
45    //由于对称加密算法的加密和解密都是同一个密匙, 
46    //因此解密的时候设置的密匙也是刚才在加密时设置好的key 
47    decryption_DES.SetKey( key, DES::KEYLENGTH ); 
48    //进行解密,把结果写到txt中 
49    //decryption_DES.ProcessAndXorBlock( output, xorBlock, txt ); 
50    decryption_DES.ProcessBlock( output, txt ); 
51 
52    //以上,加密,解密还原过程已经结束了。以下是为了验证: 
53    //加密前的明文和解密后的译文是否相等。 
54    if ( memcmp( input, txt, 5 ) != 0 ) 
55    { 
56        cerr << "DES Encryption/decryption failed./n"; 
57        abort(); 
58    } 
59    cout << "DES Encryption/decryption succeeded./n"; 
60     
61    return 0; 
62} 
63

 

 回想一下以上代码的编写过程,就可以发现,进行DES加密,流程大概是:
       数据准备;
       构造加密器;
       设置加密密匙;
       加密数据;
       显示(非必要);
       设置解密密匙(跟加密密匙是同一个key);
       解密数据;
       验证与显示(非必要);
       由此可见,主要函数的调用流程就是这样。但是文档没有详细讲,笔者当时打开下载回来的源文件时,就傻了眼。
猜想:
       AES和以后的算法,是不是都是按照这些基本的套路呢?

       AES:    

       在实际运用的时候,从代码上看,AES跟DES非常相像。但是值得注意一点的是,AES取代了DES成为21世纪的加密标准。是因为以其密匙长度和高安全性获得了先天优势。虽然界面上看上去没多大区别,但是破解难度远远大于DES。详细情况,在之前的URL有提及过。
     
       很幸运,笔者很快就找到了AES的使用例程,而且很详细:
      IT虾米网

 

#include <iostream> 
#include <aes.h> 
#pragma comment( lib, "cryptlib.lib" ) 
using namespace std;  
using namespace CryptoPP; 
int main() 
{ 
//AES中使用的固定参数是以类AES中定义的enum数据类型出现的,而不是成员函数或变量 
//因此需要用::符号来索引 
cout << "AES Parameters: " << endl; 
cout << "Algorithm name : " << AES::StaticAlgorithmName() << endl;  
//Crypto++库中一般用字节数来表示长度,而不是常用的字节数 
cout << "Block size : " << AES::BLOCKSIZE * 8 << endl; 
cout << "Min key length : " << AES::MIN_KEYLENGTH * 8 << endl; 
cout << "Max key length : " << AES::MAX_KEYLENGTH * 8 << endl; 
//AES中只包含一些固定的数据,而加密解密的功能由AESEncryption和AESDecryption来完成 
//加密过程 
AESEncryption aesEncryptor; //加密器  
 
unsigned char aesKey[AES::DEFAULT_KEYLENGTH]; //密钥 
unsigned char inBlock[AES::BLOCKSIZE] = "123456789"; //要加密的数据块 
unsigned char outBlock[AES::BLOCKSIZE]; //加密后的密文块 
unsigned char xorBlock[AES::BLOCKSIZE]; //必须设定为全零 
 
memset( xorBlock, 0, AES::BLOCKSIZE ); //置零 
 
aesEncryptor.SetKey( aesKey, AES::DEFAULT_KEYLENGTH ); //设定加密密钥 
aesEncryptor.ProcessAndXorBlock( inBlock, xorBlock, outBlock ); //加密 
//以16进制显示加密后的数据 
for( int i=0; i<16; i++ ) { 
cout << hex << (int)outBlock[i] << " "; 
} 
cout << endl; 
//解密 
AESDecryption aesDecryptor; 
unsigned char plainText[AES::BLOCKSIZE]; 
aesDecryptor.SetKey( aesKey, AES::DEFAULT_KEYLENGTH ); 
//细心的朋友注意到这里的函数不是之前在DES中出现过的:ProcessBlock, 
//而是多了一个Xor。其实,ProcessAndXorBlock也有DES版本。用法跟AES版本差不多。 
//笔者分别在两份代码中列出这两个函数,有兴趣的朋友可以自己研究一下有何差异。 
aesDecryptor.ProcessAndXorBlock( outBlock, xorBlock, plainText ); 
for( int i=0; i<16; i++ )  
{  
cout << plainText[i];  
} 
cout << endl; 
return 0; 
}

其实来到这里,都可以发现,加密解密的套路也差不多,至于之后笔者在误打误撞中找到的RSA,也只不过是在设置密匙的时候多了私匙和公匙的区别而已。笔者总觉得,有完整的例程对照学习,是一件很幸福的事情。

 

非对称加密算法:

RSA:

小背景:
       其实,笔者在一开始并没有接到“了解RSA”的要求。不过由于笔者很粗心,在看AES的时候只记得A和S两个字母,Google的时候就误打误撞Google了一个RSA。其实RSA方面的资料还是挺多的,因此它事实上是笔者第一个编译运行成功的Crypto++库中算法的应用实例。
       
         IT虾米网
       以下代码主要是按照上述URL中提供的代码写成的,作为笔者的第一份有效学习资料,笔者认为作为调用者的我们,不用清楚算法实现的细节。只需要明白几个主要函数的功用和调用的次序即可。
       由以下代码可以看出,其实RSA也离不开:数据准备、设置密匙(注意,有公匙和私匙)、加密解密这样的套路。至于如何产生密匙,有兴趣的朋友可以到Crypto++的主页上下载源文件研究。作为入门和了解阶段,笔者觉得:只需要用起来即可。

  

1//version at Crypto++ 5.60 
2#include "randpool.h" 
3#include "rsa.h" 
4#include "hex.h" 
5#include "files.h" 
6#include <iostream> 
7 
8using namespace std; 
9using namespace CryptoPP; 
10 
11#pragma comment(lib, "cryptlib.lib") 
12 
13 
14//------------------------ 
15 
16// 函数声明 
17 
18//------------------------ 
19 
20void GenerateRSAKey( unsigned int keyLength, const char *privFilename, const char *pubFilename, const char *seed  ); 
21string RSAEncryptString( const char *pubFilename, const char *seed, const char *message ); 
22string RSADecryptString( const char *privFilename, const char *ciphertext ); 
23RandomPool & GlobalRNG(); 
24 
25//------------------------ 
26// 主程序 
27//------------------------ 
28 
29void main( void ) 
30 
31{ 
32    char priKey[ 128 ] = { 0 }; 
33    char pubKey[ 128 ] = { 0 }; 
34    char seed[ 1024 ]  = { 0 }; 
35 
36    // 生成 RSA 密钥对 
37    strcpy( priKey, "pri" );  // 生成的私钥文件 
38    strcpy( pubKey, "pub" );  // 生成的公钥文件 
39    strcpy( seed, "seed" ); 
40    GenerateRSAKey( 1024, priKey, pubKey, seed ); 
41 
42    // RSA 加解密 
43    char message[ 1024 ] = { 0 }; 
44    cout<< "Origin Text:/t" << "Hello World!" << endl << endl; 
45    strcpy( message, "Hello World!" ); 
46    string encryptedText = RSAEncryptString( pubKey, seed, message );  // RSA 公匙加密 
47    cout<<"Encrypted Text:/t"<< encryptedText << endl << endl; 
48    string decryptedText = RSADecryptString( priKey, encryptedText.c_str() );  // RSA 私匙解密 
49} 
50 
51 
52 
53//------------------------ 
54 
55// 生成RSA密钥对 
56 
57//------------------------ 
58 
59void GenerateRSAKey(unsigned int keyLength, const char *privFilename, const char *pubFilename, const char *seed) 
60{ 
61    RandomPool randPool; 
62    randPool.Put((byte *)seed, strlen(seed)); 
63 
64    RSAES_OAEP_SHA_Decryptor priv(randPool, keyLength); 
65    HexEncoder privFile(new FileSink(privFilename)); 
66 
67    priv.DEREncode(privFile); 
68    privFile.MessageEnd(); 
69 
70    RSAES_OAEP_SHA_Encryptor pub(priv); 
71    HexEncoder pubFile(new FileSink(pubFilename)); 
72    pub.DEREncode(pubFile); 
73 
74    pubFile.MessageEnd(); 
75 
76    return77} 
78 
79 
80 
81//------------------------ 
82 
83// RSA加密 
84 
85//------------------------ 
86 
87string RSAEncryptString( const char *pubFilename, const char *seed, const char *message ) 
88{ 
89    FileSource pubFile( pubFilename, true, new HexDecoder ); 
90    RSAES_OAEP_SHA_Encryptor pub( pubFile ); 
91 
92    RandomPool randPool; 
93    randPool.Put( (byte *)seed, strlen(seed) ); 
94 
95    string result; 
96    StringSource( message, true, new PK_EncryptorFilter(randPool, pub, new HexEncoder(new StringSink(result))) ); 
97     
98    return result; 
99} 
100 
101 
102 
103//------------------------ 
104// RSA解密 
105//------------------------ 
106 
107string RSADecryptString( const char *privFilename, const char *ciphertext ) 
108{ 
109    FileSource privFile( privFilename, true, new HexDecoder ); 
110    RSAES_OAEP_SHA_Decryptor priv(privFile); 
111 
112    string result; 
113    StringSource( ciphertext, true, new HexDecoder(new PK_DecryptorFilter(GlobalRNG(), priv, new StringSink(result))) ); 
114 
115    return result; 
116} 
117 
118 
119 
120//------------------------ 
121 
122// 定义全局的随机数池 
123 
124//------------------------ 
125 
126RandomPool & GlobalRNG() 
127{ 
128    static RandomPool randomPool; 
129    return randomPool; 
130} 
131 
132

 

散列算法:

SHA-256                                                                                                                                                                                                                                                                      

       SHA-256主要是用来求一大段信息的Hash值,跟之前三个用于加密、解密的算法有所不同。用到SHA的场合,多半是为了校验文件。
       
         笔者的参考资料:IT虾米网
       请注意,笔者在实现的时候,稍微修改了一下两个子函数的实现,以满足笔者的需求。因此会与上述URL中的代码有差异。

 

 1//http://hi.baidu.com/magic475/blog/item/19b37a8c1fa15a14b21bbaeb.html 
2#include <iostream> 
3#include <string.h> 
4 
5#include "sha.h" 
6#include "secblock.h" 
7#include "modes.h" 
8#include "hex.h" 
9 
10#pragma comment( lib, "cryptlib.lib") 
11 
12using namespace std; 
13using namespace CryptoPP; 
14 
15void CalculateDigest(string &Digest, const string &Message); 
16bool VerifyDigest(const string &Digest, const string &Message); 
17 
18int main( void ) 
19{ 
20    //main函数中注释掉的,关于strMessage2的代码,其实是笔者模拟了一下 
21    //通过求Hash值来对“大”量数据进行校验的这个功能的运用。 
22    //注释之后并不影响这段代码表达的思想和流程。 
23    string strMessage( "Hello world" ); 
24    string strDigest; 
25    //string strMessage2( "hello world" ); //只是第一个字母不同 
26    //string strDigest2; 
27 
28    CalculateDigest( strDigest, strMessage );  //计算Hash值并打印一些debug信息 
29    cout << "the size of Digest is: " << strDigest.size() << endl; 
30    cout << "Digest is: " << strDigest << endl; 
31 
32    //CalculateDigest( strDigest2, strMessage2 ); 
33    //why put this function here will affect the Verify function? 
34    //作者在写代码的过程中遇到的上述问题。 
35    //如果把这行代码的注释取消,那么之后的运行结果就不是预料中的一样: 
36    //即使strDigest也无法对应strMessage,笔者不知道为什么,希望高手指出,谢谢! 
37 
38    bool bIsSuccess = false; 
39    bIsSuccess = VerifyDigest( strDigest, strMessage );  
40    //通过校验,看看strDigest是否对应原来的message 
41    if( bIsSuccess ) 
42    { 
43        cout << "sussessive verify" << endl; 
44        cout << "origin string is: " << strMessage << endl << endl; 
45    } 
46    else 
47    { 
48        cout << "fail!" << endl; 
49    } 
50 
51    //通过strDigest2与strMessage进行校验,要是相等, 
52    //就证明strDigest2是对应的strMessage2跟strMessage1相等。 
53    //否则,像这个程序中的例子一样,两个message是不相等的 
54    /*CalculateDigest( strDigest2, strMessage2 ); 
55    bIsSuccess = VerifyDigest( strDigest2, strMessage ); 
56    if( !bIsSuccess ) 
57    { 
58        cout << "success! the tiny modification is discovered~" << endl; 
59        cout << "the origin message is: /n" << strMessage << endl; 
60        cout << "after modify is: /n" << strMessage2 << endl; 
61    }*/ 
62    return 0; 
63} 
64 
65 
66//基于某些原因,以下两个子函数的实现跟原来参考代码中的实现有所区别, 
67//详细原因,笔者在CalculateDigest函数的注释中写明 
68void CalculateDigest(string &Digest, const string &Message) 
69{ 
70    SHA256 sha256; 
71    int DigestSize = sha256.DigestSize(); 
72    char* byDigest; 
73    char* strDigest; 
74 
75    byDigest = new char[ DigestSize ]; 
76    strDigest = new char[ DigestSize * 2 + 1 ]; 
77 
78    sha256.CalculateDigest((byte*)byDigest, (const byte *)Message.c_str(), Message.size()); 
79    memset(strDigest, 0, sizeof(strDigest)); 
80    //uCharToHex(strDigest, byDigest, DigestSize); 
81    //参考的代码中有以上这么一行,但是貌似不是什么库函数。 
82    //原作者大概是想把Hash值转换成16进制数保存到一个string buffer中, 
83    //然后在主程序中输出,方便debug的时候对照查看。 
84    //但是这并不影响计算Hash值的行为。 
85    //因此笔者注释掉了这行代码,并且修改了一下这个函数和后面的VerifyDigest函数, 
86    //略去原作者这部分的意图,继续我们的程序执行。 
87 
88    Digest = byDigest; 
89 
90    delete []byDigest; 
91    byDigest = NULL; 
92    delete []strDigest; 
93    strDigest = NULL; 
94 
95    return; 
96} 
97 
98bool VerifyDigest(const string &Digest, const string &Message) 
99{ 
100    bool Result; 
101    SHA256 sha256; 
102    char* byDigest; 
103 
104    byDigest = new char[ sha256.DigestSize() ]; 
105    strcpy( byDigest, Digest.c_str() ); 
106 
107    //HexTouChar(byDigest, Digest.c_str(), Digest.size()); 
108    //为何注释掉,请参看CalculateDigest函数的注释 
109    Result = sha256.VerifyDigest( (byte*)byDigest, (const byte *)Message.c_str(), Message.size() ); 
110 
111    delete []byDigest; 
112    byDigest = NULL; 
113    return Result; 
114} 
115 
116

 


如果下载了库不知道怎么编译的:可以看看
 

crypto++的安装
首先到IT虾米网上下载最新版本的源代码,如果是windows版的,会得到一个vc的项目,直接用vc打开就可以编译了。这里建议大家使用最新版的c++编译器,因为诸如vc6的编译器是不支持c++的标准的,很多符合c++标准的代码不能编译通过。编译的时间比较长,完成后会生成cryptlib.lib这个库文件。可以将crypto++源文件的目录命名为cryptopp,拷贝到编译器的include目录(例如:c:/vs.net/vc7/include),将cryptlib.lib文件拷贝到编译器的lib目录。这样我们只需要说明链接cryptlib.lib即可。例如在vc7中在项目->属性->链接器->命令行->附加选项中添加“cryptlib.lib”。

hello world
现在写一个hello world程序看看能不能编译通过。

#include <iostream>
using namespace std;

#include <cryptopp/aes.h>
using namespace cryptopp;

int main()
{
       cout << “hello crypto++” << endl;
       cout << “aes block size is ” << aes::blocksize << endl;

 return 0;
}

编译运行,一切ok,哈哈:d,可以用了。

 
 
 
前面AES的demo好像不能用  再发一个
 
 
 
 

Crypto++是个免费的C++加解密类库,由于资格太老、持续更新,最新版本到了CryptoPP 5.6,对天缘而言,第一眼看到CryptoPP就感觉头大,根目录下放置大量单源文件、编译文件、项目文件,再加上多平台和多编译器支持,文件几乎又多了一倍,而且还是都混到一起,直接就让人望而却步。毕竟Crypto是个功能完整,且经过大量用户使用考验的开源库。所以,皱眉学习汇总一下,遂成此文。

官方网址:IT虾米网

本文测试环境:Windows7 SP1+VC6,测试工程名为Test。用VC打开CryptoPP工程文件,会发现有四个子工程:

  • cryptdll – 生成cryptopp.dll动态库
  • dlltest – 用来测试cryptopp.dll,依赖cryptdll工程
  • cryptlib – 生成cryptlib.lib静态库
  • cryptest – 用来测试cryptopp,依赖cryptlib工程

所以,我们有两种使用CryptoPP方法,一种是静态链接,还有一种是动态链接,使用对应的工程编译即可,区别就不说了,我们下文以静态链接为例,介绍几种常用加解密算法使用。

一、编译cryptlib

首先需要编译cryptlib,最后得到cryptlib.lib文件。

  1. 先在测试工程Test下创建目录cryptopp/lib和cryptopp/include,并把Project Settings-C/C++-Processor下Include目录增加“cryptopp/include”。
  2. 把cryptlib.lib拷贝到Test/cryptopp/lib下。
  3. 把cryptoPP根目录下所有的*.h文件都拷贝到Test/cryptopp/include下。当然实际上用不了那么多,后续用到哪个include哪个。

下文开始测试使用CryptoPP,实际使用中,如果功能上逻辑上需要修改,可以参考上文测试工程中的示例程序,以及官方文档。下文编译如果报告XX重复定义等错误,请检查LIB库工程和本测试工程的:Project Setting-C/C++-Code Generation User run-time library是否统一。

二、测试cryptlib

1、测试MD5

#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 
#include "md5.h" 
using namespace CryptoPP; 
#pragma comment(lib, "cryptopp//lib//cryptlib.lib")  
using namespace std; 
void main() { 
byte message[]="HelloWorld!";        
byte mres[16];//MD5 128 bits=16bytes 
Weak::MD5 md5;  
md5.Update(message,11);//strlen=11 
md5.Final(mres);        
for(int i=0;i<16;i++) 
printf("%02X",mres[i]); 
printf("/n"); 
}

2、测试AES

//For AES encrypt 
#include "default.h"  
#include "cryptlib.h" 
#include "filters.h" 
#include "bench.h" 
#include "osrng.h" 
#include "hex.h" 
#include "modes.h" 
#include "files.h" 
using namespace CryptoPP; 
#pragma comment(lib, "cryptopp//lib//cryptlib.lib")  
using namespace std; 
void main() { 
unsigned char key[]	= {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,	0x01,0x02, 0x03,0x04,0x05,0x06,0x07,0x08};//AES::DEFAULT_KEYLENGTH 
unsigned char iv[]	= {0x01,0x02,0x03,0x03,0x03,0x03,0x03,0x03,	0x03,0x03, 0x01,0x02,0x03,0x03,0x03,0x03}; 
int keysize = 16; 
string	message = "Hello World!"; 
string	strEncTxt; 
string	strDecTxt; 
//CBC - PADDING 
//AES-CBC Encrypt(ONE_AND_ZEROS_PADDING) 
CBC_Mode<AES>::Encryption  Encryptor1(key,keysize,iv);  
StringSource(	message, 
true, 
new StreamTransformationFilter(	Encryptor1, 
new StringSink( strEncTxt ), 
BlockPaddingSchemeDef::BlockPaddingScheme::ONE_AND_ZEROS_PADDING, 
true) 
); 
//AES-CBC Decrypt 
CBC_Mode<AES>::Decryption Decryptor1(key,keysize,iv);  
StringSource(	strEncTxt,  
true, 
new StreamTransformationFilter( Decryptor1, 
new StringSink( strDecTxt ), 
BlockPaddingSchemeDef::BlockPaddingScheme::ONE_AND_ZEROS_PADDING, 
true) 
); 
//CTR - NO_PADDING 
//AES-CTR Encrypt 
CTR_Mode<AES>::Encryption  Encryptor2(key,keysize,iv);  
StringSource(	message,  
true, 
new StreamTransformationFilter( Encryptor2, 
new StringSink( strEncTxt ), 
BlockPaddingSchemeDef::BlockPaddingScheme::NO_PADDING, 
true) 
);  
//AES-CTR Decrypt 
CTR_Mode<AES>::Decryption Decryptor2(key,keysize,iv);  
StringSource(	strEncTxt,  
true, 
new StreamTransformationFilter( Decryptor2, 
new StringSink( strDecTxt ), 
BlockPaddingSchemeDef::BlockPaddingScheme::NO_PADDING, 
true) 
);   
}

上文是使用StringSource方式加密字符串,还可以使用FileSource方式直接对文件进行加解密操作。示例如下:

SecByteBlock HexDecodeString(const char *hex) { 
StringSource ss(hex, true, new HexDecoder); 
SecByteBlock result((size_t)ss.MaxRetrievable()); 
ss.Get(result, result.size()); 
return result; 
} 
void AES_CTR_Encrypt(const char *hexKey, const char *hexIV, const char *infile, const char *outfile) { 
SecByteBlock key = HexDecodeString(hexKey); 
SecByteBlock iv = HexDecodeString(hexIV); 
CTR_Mode<AES>::Encryption aes(key, key.size(), iv); 
FileSource(infile, true, new StreamTransformationFilter(aes, new FileSink(outfile))); 
}

直接调用AES_CTR_Encrypt函数即可,CBC函数需对应修改。

四、使用提示

1、StringSource类定义filters.h

	//! zero terminated string as source 
StringSource(const char *string, bool pumpAll, BufferedTransformation *attachment = NULL) 
: SourceTemplate<StringStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string)));} 
//! binary byte array as source 
StringSource(const byte *string, size_t length, bool pumpAll, BufferedTransformation *attachment = NULL) 
: SourceTemplate<StringStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string, length)));} 
//! std::string as source 
StringSource(const std::string &string, bool pumpAll, BufferedTransformation *attachment = NULL) 
: SourceTemplate<StringStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string)));}

2、RSA有关的加解密、签名函数

更多请参考工程cryptest工程下test.cpp文件内函数

void GenerateRSAKey(unsigned int keyLength, const char *privFilename, const char *pubFilename, const char *seed); 
string RSAEncryptString(const char *pubFilename, const char *seed, const char *message); 
string RSADecryptString(const char *privFilename, const char *ciphertext); 
void RSASignFile(const char *privFilename, const char *messageFilename, const char *signatureFilename); 
bool RSAVerifyFile(const char *pubFilename, const char *messageFilename, const char *signatureFilename);

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/18510.html

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论