The Cryptography API, or How to Keep a Secret(四) (轉)

themoney發表於2007-10-04
The Cryptography API, or How to Keep a Secret(四) (轉)[@more@]

生成密鈅:CryptDeriveKey, CryptGenKey, CryptDestroyKey

這三個用來產生密鈅控制程式碼: :namespace prefix = o ns = "urn:schemas--com::office" />

  • CryptDeriveKey 函式從一個指定的密碼(pass)產生密鈅。
  • CryptGenKey 函式從一個隨機產生的數值產生密鈅。
  • CryptDestroyKey 函式釋放密鈅。

使用CryptGenKey 函式時,建議使用 CRYPT_EXPORTABLE 引數以建立一個可匯出的會話密鈅。這會建立一個可從一臺機器移到另一臺機器的值。不提供此引數,返回值僅在此機器/會話中有效。

下面是如何使用 CryptDeriveKey 函式的例子,假定 pPassword 指向一個指定的密碼, dwPasswordLength 為密碼長度。

#include   // 對Crypto的定義


/*


對於非C/C++使用者,此處用到的常量如下:


#define ALG_CLASS_HASH  (4 << 13)


#define ALG_TYPE_ANY  (0)


#define ALG_SID_MD5  3


#define CALG_MD5  (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MD5)


#define CRYPT_EXPORTABLE  0x00000001


#define ALG_CLASS_DATA_ENCRYPT  (3 << 13)


#define ALG_TYPE_STREAM  (4 << 9)


#define ALG_SID_RC2  2


#define CALG_RC4  (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_STREAM|ALG_SID_RC4)


*/


BOOL bResult;


HCRYPTHASH hHash;


HCRYPTKEY hKey;


 


// 獲得雜湊物件控制程式碼


bResult = CryptCreateHash(


  hProv,  // 之前獲得的CSP控制程式碼


  CALG_MD5,  // 雜湊演算法


  0,  // 非密鈅雜湊


  0,  // 置0


  &hHash);  // 儲存雜湊物件控制程式碼的變數


 


// 雜湊資料


bResult = CryptHashData(


  hHash,  // 雜湊物件控制程式碼


  pPassword,  // 指向密碼的指標


  dwPasswordLength,  // 資料長度


  0);  // 未指定值


 


 


// 從指定的密碼產生密鈅


bResult = CryptDeriveKey(


  hProv,   // 之前獲得的CSP控制程式碼


  CALG_RC4,  // 流


  hHash,  // 密碼雜湊後物件控制程式碼


  CRYPT_EXPORTABLE,  // 密鈅可匯出


  &hKey);  // 儲存密鈅物件控制程式碼的變數


.


.


.


// 用密鈅進行操作


.


.


.


// 釋放雜湊物件


CryptDestroyHash(hHash);


 


// 釋放密鈅物件


CryptDestroyKey(hKey);


加密與資料:CryptEncrypt, CryptDecrypt

簡單來說,儘管不全對,加密API 處理資料是圍繞兩個函式—加密(CryptEncrypt) 與解密(CryptDecrypt)。

這兩個函式非常易用,但需要對其引數進行一下說明 :

  • 每個函式的頭六個引數是相同的
  • 頭兩個引數僅是密鈅控制程式碼和一個可選的雜湊物件
  • 第三個引數是一個布林值,此值在最後一塊資料塊之前保持為FALSE,為讓函式對最後一塊資料進行特殊處理,在最後一塊資料時置為TRUE
  • 第四與第五個引數是標誌值和一個指向加密或解密資料的指標
  • 第六個引數是緩衝區中待加密字元的數量
  • 第七個引數通常與第六個引數相同,它指出資料塊長度。這是因為對於許多演算法來說,加密資料尺寸與解密資料尺寸是相同的。然而,某些演算法增加加密資料的長度。在這種情況下,第五個引數中的緩衝區必須大到足以容納額外的資料。

緩衝區長度的問題可以在加密前透過CryptEncrypt 函式返回需要緩衝區的尺寸來解決。下面的例子程式碼演示了這種技術。在這個例子中,某些值已假定之前已獲得,我們僅要加密pData指向的緩衝區中dwDataLen位元組長的資料。

BOOL bResult;


PBYTE pBuffer;


DWORD dwSize;


 


// 將緩衝中資料長度賦給變數


dwSize = dwDataLen;


 


// 讓API返回給我們需要的緩衝長度


bResult = CryptEncrypt(


  hKey,  // 之前獲得的密鈅物件


  0,  // 不雜湊資料


  TRUE,  // 最後的還是緩衝的資料


  0,  // 必須置0


  NULL,  // 無資料,簡單的返回尺寸


  &dwSize,  // 資料的尺寸


  dwSize);  // 資料塊尺寸


 


// 現在得到了輸出緩衝區尺寸,建立此緩衝區


pBuffer = new char[dwSize];


 


// 加密資料


bResult = CryptEncrypt(


   hKey,  // 之前獲得的密鈅物件


  0,  // 不雜湊資料


  TRUE,  // 最後的還是緩衝的資料


  0,  // 必須置0


  pBuffer,  // 資料緩衝區


  &dwSize,  // 資料尺寸


  dwSize);  // 資料塊尺寸


同時進行加密與解密

當使用同一個密鈅進行加密或解密兩個資料流時,必須採取一些措施。同一個物理會話密鈅不得被用於同一個操作,因為每個會話密鈅容器的內部狀態資訊在同時進行一個操作時會混亂。對此問題的簡單解決辦法是製作一份會話密鈅的複製。這樣,原始密鈅進行一個操作,複製密鈅進行另一個操作。

製作一個會話密鈅的複製可以透過調CryptExportKey 匯出密鈅,然後調CryptImportKey 將它導進來。密鈅匯入後,CSP 會給這個“新”的密鈅分配自己的內部區域,就好象它跟原來的密鈅完全沒有關聯一樣。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10794571/viewspace-974696/,如需轉載,請註明出處,否則將追究法律責任。

相關文章