免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
Crypto 入門學(xué)習(xí)筆記(DES、AES、RSA、SHA

背景(只是個人感想,技術(shù)上不對后面的內(nèi)容構(gòu)成知識性障礙,可以skip):

最近,基于某些原因和需要,筆者需要去了解一下Crypto++庫,然后對一些數(shù)據(jù)進行一些加密解密的操作。

筆者之前沒接觸過任何加密解密方面的知識(當然,把每個字符的ASCII值加1之流對明文進行加密的“趣事”還是干過的,當時還很樂在其中。),甚至一開始連Crypto++的名字都沒有聽過,被BS了之后,就開始了Crypto++的入門探索過程。

最初,大概知道了要了解兩大類算法中的幾個算法——對稱加密算法:DES、AES(后來因為人品好的緣故也了解了下非對稱加密算法RSA,后文會詳述何謂“人品好”);散列算法(需要通過Hash運算):SHA-256。

起初,筆者以為這樣的知名算法在網(wǎng)上應(yīng)該有很多現(xiàn)成的例子。筆者比較懶,對于自己不熟悉的東西,總希望找捷徑,直接找別人現(xiàn)(在已經(jīng)寫)成可(編譯運)行的代碼然后施展ctrl + C,ctrl + V算法(咳,什么算法,是大法!?。。?。

However,發(fā)覺網(wǎng)上的例子不是稀缺,就是只有代碼沒有解釋。筆者覺得很難忍受這樣的“莫名其妙”(奇怪的是筆者容忍了windows了,盡管它不開源),遂決定從零開始……

 

 

 

……寫在代碼前……


      如果之前像筆者一樣沒相關(guān)經(jīng)驗——完全沒接觸過加密解密——,請務(wù)必閱讀下文。
 

一些前期工作——編譯cryptlib并使其可用:

      本文不涉及這部分內(nèi)容,因為已經(jīng)有相對完善的資料:
        http://www.cnblogs.com/cxun/archive/2008/07/30/743541.html

 

總結(jié)了一點預(yù)備知識:

關(guān)于幾個算法的介紹,網(wǎng)上各大百科都有,筆者不再詳細Ctrl+C/V了。不過在寫代碼之前,即使復(fù)制修改人家代碼之前,也有必要了解一下幾個算法(除了名稱之外)的使用流程(不是算法具體的實現(xiàn),汗?。?/p>

 

對稱加密:(AES、DES)

相對于與非對稱加密而言,加密、解密用的密匙相同。就像日常生活中的鑰匙,開門和鎖門都是同一把。

詳見:http://baike.baidu.com/view/119320.htm

 

非對稱加密:(RSA)

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

詳見:http://baike.baidu.com/view/554866.htm 


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

用途:驗證信息有沒有被修改。

原理:對長度大的信息進行提煉(通過一個Hash函數(shù)),提煉過后的信息長度小很多,得到的是一個固定長度的值(Hash值)。對于兩個信息量很大的文件通過比較這兩個值,就知道這兩個文件是否完全一致(另外一個文件有沒有被修改)。從而避免了把兩個文件中的信息進行逐字逐句的比對,減少時間開銷。

形象地描述:鬼泣3里面維吉爾跟但丁除了發(fā)型之外都很像。怎么區(qū)分兩個雙生子?比較他們的DNA就好比是比較信息量很大的文件,然而直接看發(fā)型就好比是看Hash值。一眼就看出來了。

 

注:以上是筆者對幾個概念的,非常不嚴格的,非常主觀的,概括的描述,想要詳細了解,可以:

http://wenku.baidu.com/view/4fb8e0791711cc7931b716aa.html

幾個算法的介紹,選擇,比較。

 

 

 

……Code speaking……

 

平臺:WindowsXP

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

庫版本:Crypto++ 5.6.0

 

 

庫的文檔(包括類和函數(shù)的接口列表):
http://www.cryptopp.com/docs/ref/index.html

 

 

對稱加密算法:

DES:

一開始筆者并沒有找到關(guān)于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

 6
using namespace std;
 7
using namespace CryptoPP;
 8

 9
int main( void )
10
{
11
    
//主要是打印一些基本信息,方便調(diào)試:
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
    
//可以理解成首先構(gòu)造一個加密器
23
    DESEncryption encryption_DES;
24

25
    
//回憶一下之前的背景,對稱加密算法需要一個密匙。加密和解密都會用到。
26
    
//因此,設(shè)置密匙。
27
    encryption_DES.SetKey( key, DES::KEYLENGTH );
28
    
//進行加密
29
    encryption_DES.ProcessBlock( input, output );
30

31
    
//顯示結(jié)果
32
    
//for和for之后的cout可有可無,主要為了運行的時候看加密結(jié)果
33
    
//把字符串的長度寫成一個常量其實并不被推薦。
34
    
//不過筆者事先知道字符串長,為了方便調(diào)試,就直接寫下。
35
    
//這里主要是把output也就是加密后的內(nèi)容,以十六進制的整數(shù)形式輸出。
36
    forint i = 0; i < 5; i++ )
37
    
{
38
        cout 
<< hex << (int)output[ i ] << ends;
39
    }

40
    cout 
<< endl;
41

42
    
//構(gòu)造一個加密器
43
    DESDecryption decryption_DES;    
44

45
    
//由于對稱加密算法的加密和解密都是同一個密匙,
46
    
//因此解密的時候設(shè)置的密匙也是剛才在加密時設(shè)置好的key
47
    decryption_DES.SetKey( key, DES::KEYLENGTH );
48
    
//進行解密,把結(jié)果寫到txt中
49
    
//decryption_DES.ProcessAndXorBlock( output, xorBlock, txt );
50
    decryption_DES.ProcessBlock( output, txt );
51

52
    
//以上,加密,解密還原過程已經(jīng)結(jié)束了。以下是為了驗證:
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

 回想一下以上代碼的編寫過程,就可以發(fā)現(xiàn),進行DES加密,流程大概是:
       數(shù)據(jù)準備;
       構(gòu)造加密器;
       設(shè)置加密密匙;
       加密數(shù)據(jù);
       顯示(非必要);
       設(shè)置解密密匙(跟加密密匙是同一個key);
       解密數(shù)據(jù);
       驗證與顯示(非必要);
       由此可見,主要函數(shù)的調(diào)用流程就是這樣。但是文檔沒有詳細講,筆者當時打開下載回來的源文件時,就傻了眼。
猜想:
       AES和以后的算法,是不是都是按照這些基本的套路呢?


       AES:   

       在實際運用的時候,從代碼上看,AES跟DES非常相像。但是值得注意一點的是,AES取代了DES成為21世紀的加密標準。是因為以其密匙長度和高安全性獲得了先天優(yōu)勢。雖然界面上看上去沒多大區(qū)別,但是破解難度遠遠大于DES。詳細情況,在之前的URL有提及過。
     
       很幸運,筆者很快就找到了AES的使用例程,而且很詳細:
      http://dev.firnow.com/course/3_program/c++/cppsl/2008827/138033.html

 1
#include <iostream>
 2
#include 
<aes.h>
 3

 4
#pragma comment( lib, 
"cryptlib.lib" )
 5

 6
using namespace std; 
 7
using namespace CryptoPP;
 8

 9
int main()
10
{
11

12
    
//AES中使用的固定參數(shù)是以類AES中定義的enum數(shù)據(jù)類型出現(xiàn)的,而不是成員函數(shù)或變量
13
    
//因此需要用::符號來索引
14
    cout << "AES Parameters: " << endl;
15
    cout 
<< "Algorithm name : " << AES::StaticAlgorithmName() << endl;      
16

17
    
//Crypto++庫中一般用字節(jié)數(shù)來表示長度,而不是常用的字節(jié)數(shù)
18
    cout << "Block size     : " << AES::BLOCKSIZE * 8 << endl;
19
    cout 
<< "Min key length : " << AES::MIN_KEYLENGTH * 8 << endl;
20
    cout 
<< "Max key length : " << AES::MAX_KEYLENGTH * 8 << endl;
21

22
    
//AES中只包含一些固定的數(shù)據(jù),而加密解密的功能由AESEncryption和AESDecryption來完成
23
    
//加密過程
24
    AESEncryption aesEncryptor; //加密器 
25

26
    unsigned 
char aesKey[AES::DEFAULT_KEYLENGTH];  //密鑰
27
    unsigned char inBlock[AES::BLOCKSIZE] = "123456789";    //要加密的數(shù)據(jù)塊
28
    unsigned char outBlock[AES::BLOCKSIZE]; //加密后的密文塊
29
    unsigned char xorBlock[AES::BLOCKSIZE]; //必須設(shè)定為全零
30

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

33
    aesEncryptor.SetKey( aesKey, AES::DEFAULT_KEYLENGTH );  
//設(shè)定加密密鑰
34
    aesEncryptor.ProcessAndXorBlock( inBlock, xorBlock, outBlock );  //加密
35

36
    
//以16進制顯示加密后的數(shù)據(jù)
37
    forint i=0; i<16; i++ ) {
38
        cout 
<< hex << (int)outBlock[i] << " ";
39
    }

40
    cout 
<< endl;
41

42
    
//解密
43
    AESDecryption aesDecryptor;
44
    unsigned 
char plainText[AES::BLOCKSIZE];
45

46
    aesDecryptor.SetKey( aesKey, AES::DEFAULT_KEYLENGTH );
47
    
//細心的朋友注意到這里的函數(shù)不是之前在DES中出現(xiàn)過的:ProcessBlock,
48
    
//而是多了一個Xor。其實,ProcessAndXorBlock也有DES版本。用法跟AES版本差不多。
49
    
//筆者分別在兩份代碼中列出這兩個函數(shù),有興趣的朋友可以自己研究一下有何差異。
50
    aesDecryptor.ProcessAndXorBlock( outBlock, xorBlock, plainText );
51

52

53
    
forint i=0; i<16; i++ ) 
54
    
{      
55
        cout 
<< plainText[i];   
56
    }

57
    cout 
<< endl;
58

59
    
return 0;
60
}

61

62


其實來到這里,都可以發(fā)現(xiàn),加密解密的套路也差不多,至于之后筆者在誤打誤撞中找到的RSA,也只不過是在設(shè)置密匙的時候多了私匙和公匙的區(qū)別而已。筆者總覺得,有完整的例程對照學(xué)習(xí),是一件很幸福的事情。

 

非對稱加密算法:

RSA:

小背景:
       其實,筆者在一開始并沒有接到“了解RSA”的要求。不過由于筆者很粗心,在看AES的時候只記得A和S兩個字母,Google的時候就誤打誤撞Google了一個RSA。其實RSA方面的資料還是挺多的,因此它事實上是筆者第一個編譯運行成功的Crypto++庫中算法的應(yīng)用實例。
       
         http://www.cnblogs.com/cxun/archive/2008/07/30/743541.html
       以下代碼主要是按照上述URL中提供的代碼寫成的,作為筆者的第一份有效學(xué)習(xí)資料,筆者認為作為調(diào)用者的我們,不用清楚算法實現(xiàn)的細節(jié)。只需要明白幾個主要函數(shù)的功用和調(diào)用的次序即可。
       由以下代碼可以看出,其實RSA也離不開:數(shù)據(jù)準備、設(shè)置密匙(注意,有公匙和私匙)、加密解密這樣的套路。至于如何產(chǎn)生密匙,有興趣的朋友可以到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

  8
using namespace std;
  9
using namespace CryptoPP;
 10

 11
#pragma comment(lib, 
"cryptlib.lib")
 12

 13

 14
//------------------------
 15

 16
// 函數(shù)聲明
 17

 18
//------------------------
 19

 20
void GenerateRSAKey( unsigned int keyLength, const char *privFilename, const char *pubFilename, const char *seed  );
 21
string RSAEncryptString( const char *pubFilename, const char *seed, const char *message );
 22
string RSADecryptString( const char *privFilename, const char *ciphertext );
 23
RandomPool 
& GlobalRNG();
 24

 25
//------------------------
 26
// 主程序
 27
//------------------------
 28

 29
void 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

 59
void 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

 87
string RSAEncryptString( const char *pubFilename, const char *seed, const char *message )
 88
{
 89
    FileSource pubFile( pubFilename, 
truenew 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, 
truenew PK_EncryptorFilter(randPool, pub, new HexEncoder(new StringSink(result))) );
 97
    
 98
    
return result;
 99
}

100

101

102

103
//------------------------
104
// RSA解密
105
//------------------------
106

107
string RSADecryptString( const char *privFilename, const char *ciphertext )
108
{
109
    FileSource privFile( privFilename, 
truenew HexDecoder );
110
    RSAES_OAEP_SHA_Decryptor priv(privFile);
111

112
    
string result;
113
    StringSource( ciphertext, 
truenew HexDecoder(new PK_DecryptorFilter(GlobalRNG(), priv, new StringSink(result))) );
114

115
    
return result;
116
}

117

118

119

120
//------------------------
121

122
// 定義全局的隨機數(shù)池
123

124
//------------------------
125

126
RandomPool 
& 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
       請注意,筆者在實現(xiàn)的時候,稍微修改了一下兩個子函數(shù)的實現(xiàn),以滿足筆者的需求。因此會與上述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

 12
using namespace std;
 13
using namespace CryptoPP;
 14

 15
void CalculateDigest(string &Digest, const string &Message);
 16
bool VerifyDigest(const string &Digest, const string &Message);
 17

 18
int main( void )
 19
{
 20
    
//main函數(shù)中注釋掉的,關(guān)于strMessage2的代碼,其實是筆者模擬了一下
 21
    
//通過求Hash值來對“大”量數(shù)據(jù)進行校驗的這個功能的運用。
 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
    
//如果把這行代碼的注釋取消,那么之后的運行結(jié)果就不是預(yù)料中的一樣:
 36
    
//即使strDigest也無法對應(yīng)strMessage,筆者不知道為什么,希望高手指出,謝謝!
 37

 38
    
bool bIsSuccess = false;
 39
    bIsSuccess 
= VerifyDigest( strDigest, strMessage ); 
 40
    
//通過校驗,看看strDigest是否對應(yīng)原來的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是對應(yīng)的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
//基于某些原因,以下兩個子函數(shù)的實現(xiàn)跟原來參考代碼中的實現(xiàn)有所區(qū)別,
 67
//詳細原因,筆者在CalculateDigest函數(shù)的注釋中寫明
 68
void 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, 
0sizeof(strDigest));
 80
    
//uCharToHex(strDigest, byDigest, DigestSize);
 81
    
//參考的代碼中有以上這么一行,但是貌似不是什么庫函數(shù)。
 82
    
//原作者大概是想把Hash值轉(zhuǎn)換成16進制數(shù)保存到一個string buffer中,
 83
    
//然后在主程序中輸出,方便debug的時候?qū)φ詹榭础?br> 84
    
//但是這并不影響計算Hash值的行為。
 85
    
//因此筆者注釋掉了這行代碼,并且修改了一下這個函數(shù)和后面的VerifyDigest函數(shù),
 86
    
//略去原作者這部分的意圖,繼續(xù)我們的程序執(zhí)行。
 87

 88
    Digest 
= byDigest;
 89

 90
    delete []byDigest;
 91
    byDigest 
= NULL;
 92
    delete []strDigest;
 93
    strDigest 
= NULL;
 94

 95
    
return;
 96
}

 97

 98
bool 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函數(shù)的注釋
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




        后記:
        為什么寫這篇文章呢?因為筆者在搜索過程中覺得這方面的資料有點分散,因此想把它們集中起來,方便剛剛?cè)腴T的朋友。
         同時,也算是為自己留點學(xué)習(xí)資料吧。


鳴謝:
jingzhongrong
vczh
沒了這兩位,在這個宇宙、這個時間、這個維度肯定不會有這篇文章,哈哈!
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
OpenSSL使用指南
使用openssl中的加密函數(shù)AES、RC4、RSA對文件加密的一個例子
RSA算法加解密---crypto++庫和OpenSSL庫
str 與*str
用OpenSSL 做HMAC(C++)
迅雷協(xié)議分析
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服