最先附上 下載地址
背景(只是個人感想,技術上不對后面的內容構成知識性障礙,可以skip):
最近,基於某些原因和需要,筆者需要去了解一下Crypto++庫,然后對一些數據進行一些加密解密的操作。
筆者之前沒接觸過任何加密解密方面的知識(當然,把每個字符的ASCII值加1之流對明文進行加密的“趣事”還是干過的,當時還很樂在其中。),甚至一開始連Crypto++的名字都沒有聽過,被BS了之后,就開始了Crypto++的入門探索過程。
最初,大概知道了要了解兩大類算法中的幾個算法——對稱加密算法:DES、AES(后來因為人品好的緣故也了解了下非對稱加密算法RSA,后文會詳述何謂“人品好”);散列算法(需要通過Hash運算):SHA-256。
起初,筆者以為這樣的知名算法在網上應該有很多現成的例子。筆者比較懶,對於自己不熟悉的東西,總希望找捷徑,直接找別人現(在已經寫)成可(編譯運)行的代碼然后施展ctrl + C,ctrl + V算法(咳,什么算法,是大法!!!)。
However,發覺網上的例子不是稀缺,就是只有代碼沒有解釋。筆者覺得很難忍受這樣的“莫名其妙”(奇怪的是筆者容忍了windows了,盡管它不開源),遂決定從零開始……
……寫在代碼前……
如果之前像筆者一樣沒相關經驗——完全沒接觸過加密解密——,請務必閱讀下文。
一些前期工作——編譯cryptlib並使其可用:
本文不涉及這部分內容,因為已經有相對完善的資料:
http://www.cnblogs.com/cxun/archive/2008/07/30/743541.html
總結了一點預備知識:
關於幾個算法的介紹,網上各大百科都有,筆者不再詳細Ctrl+C/V了。不過在寫代碼之前,即使復制修改人家代碼之前,也有必要了解一下幾個算法(除了名稱之外)的使用流程(不是算法具體的實現,汗!)。
對稱加密:(AES、DES)
相對於與非對稱加密而言,加密、解密用的密匙相同。就像日常生活中的鑰匙,開門和鎖門都是同一把。
詳見:http://baike.baidu.com/view/119320.htm
非對稱加密:(RSA)
相對於上述的對稱加密而言,加密、解密用的密匙不同,有公匙和私匙之分。
詳見:http://baike.baidu.com/view/554866.htm
散列算法:(SHA系列,我們熟悉的MD5等)
用途:驗證信息有沒有被修改。
原理:對長度大的信息進行提煉(通過一個Hash函數),提煉過后的信息長度小很多,得到的是一個固定長度的值(Hash值)。對於兩個信息量很大的文件通過比較這兩個值,就知道這兩個文件是否完全一致(另外一個文件有沒有被修改)。從而避免了把兩個文件中的信息進行逐字逐句的比對,減少時間開銷。
形象地描述:鬼泣3里面維吉爾跟但丁除了發型之外都很像。怎么區分兩個雙生子?比較他們的DNA就好比是比較信息量很大的文件,然而直接看發型就好比是看Hash值。一眼就看出來了。
注:以上是筆者對幾個概念的,非常不嚴格的,非常主觀的,概括的描述,想要詳細了解,可以:
http://wenku.baidu.com/view/4fb8e0791711cc7931b716aa.html
幾個算法的介紹,選擇,比較。
……Code speaking……
平台:WindowsXP
IDE以及工具:Visual Studio 2008 + Visual Assist
庫版本:Crypto++ 5.6.0
庫的文檔(包括類和函數的接口列表):
http://www.cryptopp.com/docs/ref/index.html
對稱加密算法:
DES:
一開始筆者並沒有找到關於DES運用的很好的例程,或者說,筆者的搜索功力薄弱,未能找到非常完整的例程吧。
http://bbs.pediy.com/showthread.php?p=745389
筆者以下的代碼主要是參考上面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的使用例程,而且很詳細:
http://dev.firnow.com/course/3_program/c++/cppsl/2008827/138033.html
#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++庫中算法的應用實例。
http://www.cnblogs.com/cxun/archive/2008/07/30/743541.html
以下代碼主要是按照上述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 return ; 77} 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的場合,多半是為了校驗文件。
筆者的參考資料:http://hi.baidu.com/magic475/blog/item/19b37a8c1fa15a14b21bbaeb.html
請注意,筆者在實現的時候,稍微修改了一下兩個子函數的實現,以滿足筆者的需求。因此會與上述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++的安裝
首先到www.cryptopp.com上下載最新版本的源代碼,如果是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> int main() return 0; |
Crypto++是個免費的C++加解密類庫,由於資格太老、持續更新,最新版本到了CryptoPP 5.6,對天緣而言,第一眼看到CryptoPP就感覺頭大,根目錄下放置大量單源文件、編譯文件、項目文件,再加上多平台和多編譯器支持,文件幾乎又多了一倍,而且還是都混到一起,直接就讓人望而卻步。畢竟Crypto是個功能完整,且經過大量用戶使用考驗的開源庫。所以,皺眉學習匯總一下,遂成此文。
本文測試環境:Windows7 SP1+VC6,測試工程名為Test。用VC打開CryptoPP工程文件,會發現有四個子工程:
- cryptdll - 生成cryptopp.dll動態庫
- dlltest - 用來測試cryptopp.dll,依賴cryptdll工程
- cryptlib - 生成cryptlib.lib靜態庫
- cryptest - 用來測試cryptopp,依賴cryptlib工程
所以,我們有兩種使用CryptoPP方法,一種是靜態鏈接,還有一種是動態鏈接,使用對應的工程編譯即可,區別就不說了,我們下文以靜態鏈接為例,介紹幾種常用加解密算法使用。
一、編譯cryptlib
首先需要編譯cryptlib,最后得到cryptlib.lib文件。
- 先在測試工程Test下創建目錄cryptopp\lib和cryptopp\include,並把Project Settings-C/C++-Processor下Include目錄增加“cryptopp\include”。
- 把cryptlib.lib拷貝到Test\cryptopp\lib下。
- 把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);