日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Microsoft CryptoAPI加密技术(二)

發布時間:2025/3/20 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Microsoft CryptoAPI加密技术(二) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文:http://www.vckbase.com/index.php/wv/717.html

上次我們講了Microsoft CryptoAPI的構成以及會話密鑰的使用。接下來我們將看一下公私密鑰對的使用、HASH算法、數字簽名等技術。

一、 公用密鑰加密技術

公用密鑰加密技術使用兩個不同的密鑰:公鑰和私鑰。私鑰必須安全的保管好不能被外人知道,而公鑰可以告訴任何人,只要他需要。通常公鑰是以數字證書的形式發布的。

用公私密鑰對中的一個密鑰加密的數據只能用密鑰對中的另一個密鑰才能解密。也就是說用用戶A的公鑰加密的數據只能用A的私鑰才能解密,同樣,用A的私鑰加密的數據只能用A的公鑰才能解密。

如果用私鑰簽名一個消息,那么必須用與之對應的公鑰去驗證簽名的有效性。

不幸的是公用密鑰加密技術的效率非常低甚至只有對稱加密的千分之一,所以不適合對大量的數據進行加密。實際上,公用密鑰加密技術一般用來加密會話密鑰,而數據加密可以用對稱加密的方法。

好了,讓我們回到Microsoft CryptoAPI。我們知道一個CSP有一個密鑰庫,這個密鑰庫有一個或多個密鑰容器。而密鑰容器中有什么呢?一般來說,一個密鑰容器中有兩對公私密鑰對,一對用來加密會話密鑰,而另一對用來進行數字簽名,也就是大家知道的key exchange key pair和signature key pair。

那么,怎么得到這些密鑰對呢?

view source print? 01.if(CryptGetUserKey( 02.???hCryptProv,???????????????????? // 我們已經得到的CSP句柄 03.???AT_SIGNATURE,?????????????????? // 這里想得到signature key pair 04.???&hKey))???????????????????????? // 返回密鑰句柄 05.{ 06.????printf("A signature key is available.\n"); 07.} 08.else??????? //取signature key pair錯誤 09.{ 10.????printf("No signature key is available.\n"); 11.????if(GetLastError() == NTE_NO_KEY) //密鑰容器里不存在signature key pair 12.????{ 13.???????// 創建 signature key pair.? 14.???????printf("The signature key does not exist.\n"); 15.???????printf("Create a signature key pair.\n");? 16.???????if(CryptGenKey( 17.??????????hCryptProv,?????? //CSP句柄 18.??????????AT_SIGNATURE, //創建的密鑰對類型為signature key pair 19.??????????0,??????????? //key類型,這里用默認值 20.??????????&hKey))?????? //創建成功返回新創建的密鑰對的句柄 21.???????{ 22.??????????printf("Created a signature key pair.\n"); 23.???????} 24.???????else 25.???????{ 26.??????????printf ("Error occurred creating a signature key.\n");? 27.???????} 28.????} 29.????else 30.????{ 31.????????printf ("An error other than NTE_NO_KEY getting signature\key.\n"); 32.????} 33.} // end if

將參數AT_SIGNATURE換成AT_KEYEXCHANGE就可以得到key exchange key pair。

現在我們得到的僅僅是一個句柄,我們需要把這個key值存儲的磁盤或文件中,這樣才能傳給對方來進行解密。下面讓我們來看一個用于導出密鑰的API。

view source print? 1.BOOL WINAPI CryptExportKey( 2.??HCRYPTKEY hKey, 3.??HCRYPTKEY hExpKey, 4.??DWORD dwBlobType, 5.??DWORD dwFlags, 6.??BYTE* pbData, 7.??DWORD* pdwDataLen 8.);

hKey:需要被導出的密鑰句柄

hExpKey:前面咱們提到公用密鑰加密技術的效率非常低所以公用密鑰加密技術一般用來加密會話密鑰。這里傳入的密鑰就是用來加密被導出的密鑰的。也就是說,被導出的密鑰hKey的數據是經過這個密鑰hExpKey加密的。如果為NULL表示不經過加密直接導出。

dwBlobType:被導出的密鑰類型,比如公鑰還是私鑰等

dwFlags:標志位

pbData:保存導出的數據,如果為NULL, pdwDataLen將返回導出數據的長度

pdwDataLen:輸入pbData緩沖區的大小,輸出導出數據的長度

下面的例子演示如何導出密鑰。

view source print? 01.if(CryptExportKey(??? 02.???hKey,???? 03.???NULL,???? 04.???PUBLICKEYBLOB,?????? //導出公鑰 05.???0,???? 06.???NULL,? 07.???&dwBlobLen))???????? //返回密鑰數據長度 08.{ 09.?????printf("Size of the BLOB for the public key determined. \n"); 10.} 11.else 12.{ 13.?????printf("Error computing BLOB length.\n"); 14.?????exit(1); 15.} 16.//-------------------------------------------------------------------- 17.// Allocate memory for the pbKeyBlob. 18.?? 19.if(pbKeyBlob = (BYTE*)malloc(dwBlobLen))? 20.{ 21.????printf("Memory has been allocated for the BLOB. \n"); 22.} 23.else 24.{ 25.????printf("Out of memory. \n"); 26.????exit(1); 27.} 28.//-------------------------------------------------------------------- 29.// Do the actual exporting into the key BLOB. 30.?? 31.if(CryptExportKey(??? 32.???hKey,? 33.???NULL,???? 34.???PUBLICKEYBLOB,???? 35.???0,???? 36.???pbKeyBlob,?????? //返回密鑰數據 37.???&dwBlobLen)) //導出的密鑰數據的長度 38.{ 39.?????printf("Contents have been written to the BLOB. \n"); 40.} 41.else 42.{ 43.????printf("Error exporting key.\n"); 44.????exit(1); 45.}

如果要導出用公用密鑰加密技術加密的密鑰,只要把API的第二個參數傳入一個key exchange key pair句柄就可以了。

既然有了導出當然要有導入。

view source print? 1.BOOL WINAPI CryptImportKey( 2.??HCRYPTPROV hProv, //CSP句柄 3.??BYTE* pbData,???? //要導入的密鑰數據 4.??DWORD dwDataLen,? //數據長度 5.??HCRYPTKEY hPubKey,??? //如果數據是被加密的這里輸入解密用的密鑰句柄 6.??DWORD dwFlags,??????? //標志位 7.??HCRYPTKEY* phKey? //導入后返回的密鑰句柄 8.);

這個API比較簡單,這里就不舉例說明了,在以后的例子里會看到。

二、 HASH

Hash簡單點講就是把任意一段數據經過某種算法生成一段唯一的固定長度的數據。也叫做摘要。為了確保數據A免受意外或者故意(惡意)的修改,往往用這段數據A產生一個hash數據一起發送出去,接收方可以通過相同的hash算法用這段接收到的數據A產生一個新的hash數據并與接收到的hash數據比較,來驗證數據A是否為真實完整的數據。

下面的API用來創建hash對象

view source print? 01.BOOL WINAPI CryptCreateHash( 02.??HCRYPTPROV hProv, //CSP句柄 03.??ALG_ID Algid, //選擇hash算法,比如CALG_MD5等 04.??HCRYPTKEY hKey,?? //HMAC 和MAC算法時有用 05.??DWORD dwFlags,??? //保留,傳入0即可 06.??HCRYPTHASH* phHash??? //返回hash句柄 07.); 08.?? 09.if(CryptCreateHash( 10.???hCryptProv,? 11.???CALG_MD5,? 12.???0,? 13.???0,? 14.???&hHash))? 15.{ 16.????printf("An empty hash object has been created. \n"); 17.} 18.else 19.{ 20.????printf("Error during CryptBeginHash!\n"); 21.????exit(1); 22.} 23.?? 24.// Insert code that uses the hash object here. 25.?? 26.//-------------------------------------------------------------------- 27.// After processing, hHash must be released. 28.?? 29.if(hHash)? 30.???CryptDestroyHash(hHash); //釋放句柄

我們已經得到hash對象了,下面就找點數據試試,咱也去哈一下,當然這里可不是哈日哈韓的哈,更不是哈巴狗的哈,嘿嘿。Let’s go!!

哎呀!!不好意思,忘記了介紹一個API,看看先。

view source print? 1.BOOL WINAPI CryptHashData( 2.??HCRYPTHASH hHash,???? //hash對象 3.??BYTE* pbData,???? //被hash的數據 4.??DWORD dwDataLen,????? //數據的長度 5.??DWORD dwFlags???? //微軟的CSP這個值會被忽略 6.);

下面代碼:

view source print? 01.BYTE *pbBuffer= (BYTE *)"The data that is to be hashed."; 02.DWORD dwBufferLen = strlen((char *)pbBuffer)+1; 03.?? 04.if(CryptHashData( 05.???hHash,? 06.???pbBuffer,? 07.???dwBufferLen,? 08.???0))? 09.{ 10.?????printf("The data buffer has been added to the hash.\n"); 11.} 12.else 13.{ 14.?????printf("Error during CryptHashData.\n"); 15.?????exit(1); 16.}

現在,pbBuffer里的內容已經被hash了,然后我們需要導出哈希后的數據。

view source print? 01.BYTE???????? *pbHash; 02.BYTE???????? *pbHashSize; 03.DWORD??????? dwHashLen = sizeof(DWORD); 04.DWORD??????? i; 05.?? 06.if(!(pbHashSize =(BYTE *) malloc(dwHashLen))) 07.MyHandleError("Memory allocation failed."); 08.?? 09.//下面的這次調用我沒搞清楚:( 我怎么覺得沒有必要!! 10.if(CryptGetHashParam( 11.???hHash,? 12.???HP_HASHSIZE,???? //取hash數據的大小 13.???pbHashSize,? //輸出hash數據大小的緩沖區 14.???&dwHashLen,? //緩沖區大小 15.???0))? 16.{ 17.// It worked. Free pbHashSize. 18.???free(pbHashSize); 19.} 20.else 21.{ 22.????MyHandleError("CryptGetHashParam failed to get size."); 23.} 24.?? 25.if(CryptGetHashParam( 26.???hHash,? 27.???HP_HASHVAL,? //取hash值 28.???NULL,??????? //設為NULL,在dwHashLen返回需要的輸出緩沖區大小 29.???&dwHashLen,? //輸出緩沖區大小 30.???0))? 31.{ 32.// It worked. Do nothing. 33.} 34.else 35.{ 36.????MyHandleError("CryptGetHashParam failed to get length."); 37.} 38.?? 39.if(pbHash = (BYTE*)malloc(dwHashLen)) 40.{ 41.// It worked. Do nothing. 42.} 43.else 44.{ 45.?????MyHandleError("Allocation failed."); 46.} 47.?? 48.if(CryptGetHashParam( 49.???hHash,? 50.???HP_HASHVAL,? //取hash值 51.???pbHash,????? //返回Hash數據 52.???&dwHashLen,? //hash數據長度 53.???0))? 54.{ 55.????// Print the hash value. 56.????printf("The hash is:? "); 57.???for(i = 0 ; i < dwHashLen ; i++)? 58.???{ 59.???????printf("%2.2x ",pbHash[i]); 60.???} 61.printf("\n"); 62.} 63.else 64.{ 65.????MyHandleError("Error during reading hash value."); 66.} 67.free(pbHash);

三、 數字簽名

發布一個純文本形式信息時,接收者可以用數字簽名來鑒別和驗證信息的發送者。對信息簽名并不改變這個信息,只是生成一個數字簽名串隨信息一起傳送,或單獨傳送。

一個數字簽名,就是一段被用發送者的私鑰加密的數據段,而接收者只有擁有發送者的公鑰才能解密這個數據段。表示如下:

由Message生成數字簽名有兩步。首先,對Message進行hash處理,產生hash數據。然后用簽名者A的私鑰對這個hash數據加密。具體如下:

?

驗證一個簽名需要上圖表示的Message和Digital signatures。首先跟生成時一樣對Message進行hash處理,產生hash數據。然后通過簽名者A的公鑰、Digital signatures以及剛生成的hash數據進行驗證。具體如下:

?

好了,你是否學會數字簽名了呢?很多技術名詞聽起來很唬人,其實本來是很簡單的!!嘿嘿。

隨文檔的例程幾乎將用到我們上面講的所有內容。

參考資料:

MSDN相關章節。

總結

以上是生活随笔為你收集整理的Microsoft CryptoAPI加密技术(二)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。