CSP應用開發-CryptAPI函數庫介紹

基本加密函數爲開發加密應用程序提供了足夠靈活的空間。所有CSP的通訊都是通過這些函數。一個CSP是實現所有加密操作的獨立模塊。在每一個應用程序中至少需要提供一個CSP來完成所需的加密操作。如果使用多於一個以上的CSP,在加密函數調用中就要指定所需的CSP。微軟基本加密提供者(Microsoft Base Cryptographic Provider),是缺省綁定到CryptoAPI 裏的。如果沒有指定其他CSP時,這個CSP 就是卻省的。每一個CSP對CryptoAPI 提供了一套不同的實現。一些提供了更加強大的加密算法,而其他一些CSP包含了對硬件的支持,比如智能卡。另外,一些CSP 偶爾和使用者直接通訊,比如數字簽名就使用了用戶的簽名私鑰。

基本加密函數包含了以下幾種:

1.1服務提供者函數

應用程序使用服務提供者函數來連接和斷開一個CSP。下面就是主要的API:

CryptAcquireContext獲得指定CSP的密鑰容器的句柄

CryptContextAddRef對HCRYPTPROV句柄增加一個應用計數

CryptEnumProviders枚舉當前計算機中的CSP

CryptEnumProviderTypes枚舉CSP的類型

CryptGetDefaultProvider對於指定CSP類型的卻省CSP

CryptGetProvParam得到一個CSP的屬性

CryptInstallDefaultContext安裝先前得到的HCRYPTPROV上下文作爲當前卻省的上下文

CryptReleaseContext釋放由CryptAcquireContext得到的句柄

CryptSetProvider和CryptSetProviderEx爲指定CSP類型指定一個卻省的CSP

CryptSetProvParam指定一個CSP的屬性

CryptUninstallDefaultContext刪除先前由CryptInstallDefaultContext安裝的卻省上下文

1.2密鑰的產生和交換函數

密鑰產生函數創建、配置和銷燬加密密鑰。他們也用於和其他用戶進行交換密鑰。下面就是主要的一些函數:

CryptAcquireCertificatePrivateKey對於指定證書上下文得到一個HCRYPTPROV句柄和dwKeySpec

CryptDeriveKey從一個密碼中派生一個密鑰

CryptDestoryKey銷燬密鑰

CryptDuplicateKey製作一個密鑰和密鑰狀態的精確複製

CryptExportKey把CSP的密鑰做成BLOB 傳送到應用程序的內存空間中

CryptGenKey創建一個隨機密鑰

CryptGenRandom產生一個隨機數

CryptGetKeyParam得到密鑰的參數

CryptGetUserKey得到一個密鑰交換或簽名密鑰的句柄

CryptImportKey把一個密鑰BLOB傳送到CSP 中

CryptSetKeyParam指定一個密鑰的參數

1.3編碼/解碼函數

有一些編碼/解碼函數,他們可以用來對證書、證書撤銷列表、證書請求和證書擴展進行編碼和解碼。

以下就是這幾個函數:

CryptDecodeObject對lpszStructType結構進行解碼

CryptDecodeObjectEx對lpszStructType結構進行解碼,此函數支持內存分配選項

CryptEncodeObject對lpszStructType結構進行編碼

CyptEncodeObjectEx對lpszStructType結構進行編碼,此函數支持內存分配選項

1.4數據加密/解密函數

這些函數支持數據的加密/解密操作。

CryptEncrypt 和CryptDecrypt 要求在被調用前指定一個密鑰。

注:這個密鑰可以由CryptGenKey、CryptDeriveKey 或CryptImportKey 產生。創建密鑰時要指定加密算法。

CryptSetKeyParam函數可以指定額外的加密參數。

CryptDecrypt使用指定加密密鑰來解密一段密文

CryptEncrypt使用指定加密密鑰來加密一段明文

CryptProtectData執行對DATA_BLOB結構的加密

CryptUnprotectData執行對DATA_BLOB結構的完整性驗證和解密

1.5哈希和數字簽名函數

這些函數在應用程序中完成計算哈希、創建和校驗數字簽名。

CryptCreateHash創建一個空哈希對象

CryptDestoryHash銷燬一個哈希對象

CryptDuplicateHash複製一個哈希對象

CryptGetHashParam得到一個哈希對象參數

CryptHashData對一塊數據進行哈希,把它加到指定的哈希對象中

CryptHashSessionKey對一個會話密鑰進行哈希,把它加到指定的哈希對象中

CryptSetHashParam設置一個哈希對象的參數

CryptSignHash對一個哈希對象進行簽名

CryptVerifySignature校驗一個數字簽名

1.6函數詳解

1.6.1獲得CSP密鑰容器句柄

1.6.1.1 CryptAcquireContext

BOOL WINAPI CryptAcquireContext(

HCRYPTPROV *phProv,

LPCTSTR pszContainer,

LPCTSTR pszProvider,

DWORD dwProvType,

DWORD dwFlags

);

參數:

phProv[out] CSP句柄指針

pszContainer[in]密鑰容器名稱, 指向密鑰容器的字符串指針。如果dwFlags爲CRYPT_VERIFYCONTEXT,pszContainer必須爲NULL。

pszProvider[in]指向CSP名稱的字符串指針。如果爲NULL,就使用卻省的CSP。

dwProvType[in]CSP類型。下表是就中常見的CSP類型

 

CSP類型

交換算法

簽名算法

對稱加密算法

Hash算法

PROV_RSA_FULL

RSA

RSA

RC2
RC4

MD5
SHA

PROV_RSA_SIG

none

RSA

none

MD5
SHA

PROV_RSA_SCHANNEL

RSA

RSA

RC4
DES
Triple DES

MD5
SHA

PROV_DSS

DSS

none

DSS

MD5
SHA

PROV_DSS_DH

DH

DSS

CYLINK_MEK

MD5
SHA

PROV_DH_SCHANNEL

DH

DSS

DES
Triple DES

MD5
SHA

PROV_FORTEZZA

KEA

DSS

Skipjack

SHA

PROV_MS_EXCHANGE

RSA

RSA

CAST

MD5

PROV_SSL

RSA

RSA

Varies

Varies

 

dwFlags[in]標誌:

 

CRYPT_VERIFYCONTEXT

指出應用程序不需要使用公鑰/私鑰對,如程序只執行哈希和對稱加密。只有程序需要創建簽名和解密消息時才需要訪問私鑰。

CRYPT_NEWKEYSET

使用指定的密鑰容器名稱創建一個新的密鑰容器。如果pszContainer爲NULL,密鑰容器就使用卻省的名稱創建。

CRYPT_MACHINE_KEYSET

由此標誌創建的密鑰容器只能由創建者本人或有系統管理員身份的人使用。

CRYPT_DELETEKEYSET

刪除由pszContainer指定的密鑰容器。如果pszContainer 爲NULL,缺省名稱的容器就會被刪除。此容器裏的所有密鑰對也會被刪除。

CRYPT_SLIENT

應用程序要求CSP不顯示任何用戶界面。

 

說明:

這個函數是用來取得指定CSP密鑰容器句柄,以後的任何加密操作就是針對此CSP 句柄而言。函數首先查找由dwProvType和pszProvider 指定的CSP,如果找到了CSP,函數就查找由此CSP指定的密鑰容器。由適當的dwFlags 標誌,這個函數就可以創建和銷燬密鑰容器,如果不要求訪問私鑰的話,也可以提供對CSP臨時密鑰容器的訪問。

1.6.1.2 CryptReleaseContext

BOOL WINAPI CryptReleaseContext(

HCRYPTPROV hProv,

DWORD dwFlags

);

參數:

hProv[in]由CryptAcquireContext獲得的CSP 句柄。

dwFlags[in]保留。必須爲0。

說明:

此函數釋放CSP的句柄。對於每一次調用,CSP 的引用計數都減1。當引用計數爲0時,CSP上下文就會被系統釋放變成無效句柄,以後針對此CSP 句柄的函數不再可用。

此函數並不銷燬密鑰容器或密鑰對。

//--------------------------------------------------------------------

HCRYPTPROV hCryptProv;

if (CryptAcquireContext(

hCryptProv, NULL,

MS_DEF_PROV,

PROV_RSA_FULL,

CRYPT_VERIFYCONTEXT))

CryptReleaseContext(hCryptProv, NULL);

1.6.2枚舉CSP

4.1.6.2.1 CryptEnumProviders

BOOL WINAPI CryptEnumProviders(

DWORD dwIndex,

DWORD *pdwReserved,

DWORD dwFlags,

DWORD *pdwProvType,

LPTSTR pszProvName,

DWORD *pcbProvName

);

參數:

dwIndex[in]枚舉下一個CSP的索引。

pdwReserved[in]保留。必須爲NULL。

dwFlags[in]保留。必須爲NULL。

pdwProvType[out]CSP的類型。

pszProvName[out]指向接收CSP名稱的緩衝區字符串指針。此指針可爲NULL,用來得到字符串的大小。

pcbProvName[in/out]指出pszProvName字符串的大小。

說明:

此函數得到第一個或下一個可用的CSP。如果使用循環,就可以得到計算機上所有可用的CSP。 


1.6.3獲得CSP參數

4.1.6.3.1 CryptGetProvParam

BOOL WINAPI CryptGetProvParam(

HCRYPTPROV hProv,

DWORD dwParam,

BYTE *pbData,

DWORD *pdwDataLen,

DWORD dwFlags

);

參數:

hProv[in]CSP句柄。

dwParam[in]指定查詢的參數。

 

參數名

作用

PP_CONTAINER

指向密鑰名稱的字符串

PP_ENUMALGS

不斷的讀出CSP支持的所有算法

PP_ENUMALGS_EX

比PP_ENUMALGS獲得更多的算法信息

PP_ENUMCONTAINERS

不斷的讀出CSP支持的密鑰容器

PP_IMPTYPE

指出CSP怎樣實現的

PP_NAME

指向CSP名稱的字符串

PP_VERSION

CSP的版本號

PP_KEYSIZE_INC

AT_SIGNATURE的位數

PP_KEYX_KEYSIZE_INC

AT_KEYEXCHANGE的位數

PP_KEYSET_SEC_DESCR 

密鑰的安全描述符

PP_UNIQUE_CONTAINER

當前密鑰容器的唯一名稱

PP_PROVTYPE

CSP類型

PP_USE_HARDWARE_RNG

指出硬件是否支持隨機數發生器

PP_KEYSPEC

返回CSP密鑰的信息

 

pbData[out]指向接收數據的緩衝區指針。

pdwDataLen[in/out]指出pbData數據長度。

dwFlags[in]如果指定PP_ENUMCONTAINERS,就指定CRYPT_MACHINE_KEYSET。

說明:

此函數獲得CSP的各種參數。

[cpp] view plaincopy
 
 
 
  1. //-----------------------------------------------------------------  
  2.   
  3. //  
  4.   
  5. HCRYPTPROV hCryptProv;  
  6.   
  7. BYTE pbData[1000];  
  8.   
  9. DWORD cbData;  
  10.   
  11. //-------------------------------------------------------------------  
  12.   
  13. //缺省CSP名稱  
  14.   
  15. cbData = 1000;  
  16.   
  17. if(CryptGetProvParam(  
  18.   
  19.    hCryptProv,  
  20.   
  21.    PP_NAME,  
  22.   
  23.    pbData,  
  24.   
  25.    &cbData,  
  26.   
  27.    0))  
  28.   
  29. {  
  30.   
  31.     printf("CryptGetProvParam succeeded.\n");  
  32.   
  33.     printf("Provider name: %s\n", pbData);  
  34.   
  35. }  
  36.   
  37. else  
  38.   
  39. {  
  40.   
  41.     printf("Error reading CSP name. \n");  
  42.   
  43.     exit(1);  
  44.   
  45. }  
  46.   
  47. //--------------------------------------------------------------------  
  48.   
  49. cbData = 1000;  
  50.   
  51. if(CryptGetProvParam(  
  52.   
  53.    hCryptProv,  
  54.   
  55.    PP_CONTAINER,  
  56.   
  57.    pbData,  
  58.   
  59.    &cbData,  
  60.   
  61.    0))  
  62.   
  63. {  
  64.   
  65.     printf("CryptGetProvParam succeeded. \n");  
  66.   
  67.     printf("Key Container name: %s\n", pbData);  
  68.   
  69. }  
  70.   
  71. else  
  72.   
  73. {  
  74.   
  75.     printf("Error reading key container name. \n");  
  76.   
  77.     exit(1);  
  78.   
  79. }  

4.1.6.4創建哈希

4.1.6.4.1 CryptCreateHash

BOOL WINAPI CryptCreateHash(

HCRYPTPROV hProv,

ALG_ID Algid,

HCRYPTKEY hKey,

DWORD dwFlags,

HCRYPTHASH *phHash

);

參數:

hProv[in]CSP句柄

Algid[in]哈希算法的標示符。

hKey[in]如果哈希算法是密鑰哈希,如HMAC或MAC 算法,就用此密鑰句柄傳遞密鑰。對於非密鑰算法,此參數爲NULL。

dwFlags[in]保留。必須爲0。

phHash[out]哈希對象的句柄。

說明:

此函數初始化哈希數據流。它創建並返回了一個CSP哈希對象的句柄。此句柄由CryptHashData和CryptHashSessionKey來調用。

4.1.6.4.2 CryptHashData

BOOL WINAPI CryptHashData(

HCRYPTHASH hHash,

BYTE *pbData,

DWORD dwDataLen,

DWORD dwFlags

);

參數:

hHash[in]哈希對象句柄

pbData[in]指向要加入到哈希對象的數據指針

dwDataLen[in]數據長度

dwFlags[in]標誌

CRYPT_USERDATA所有微軟CSP都忽略此參數。所有其他CSP 都不能忽略此參數,如果置此參數,CSP提示用戶直接數據數據。

說明:

此函數把一段數據加入到指定的哈希對象中去。

4.1.6.4.3 CryptGetHashParam

BOOL WINAPI CryptGetHashParam(

HCRYPTHASH hHash,

DWORD dwParam,

BYTE *pbData,

DWORD *pdwDataLen,

DWORD dwFlags

);

參數:

hHash[in]哈希對象的句柄

dwParam[in]查詢類型。可以是下列:

 

參數名稱

作用

HP_ALGID

哈希算法

HP_HASHSIZE

哈希值長度

HP_HASHVAL

哈希值,由hHash指定的哈希值或者消息哈希

 

說明:

此函數得到指定哈希對象的數據。

4.1.6.4.4 CryptDestroyHash

BOOL WINAPI CryptDestroyHash(

HCRYPTHASH hHash

);

參數:

hHash[in]要銷燬的哈希對象句柄

說明:

此函數銷燬由hHash指定的哈希對象。當一個哈希對象被銷燬後,它對程序來說不可用。

[cpp] view plaincopy
 
 
 
  1. …  
  2.   
  3. HCRYPTHASH hCryptHash;  
  4.   
  5. if (CryptCreateHash(  
  6.   
  7. hCryptProv,  
  8.   
  9. CALG_MD5,  
  10.   
  11. 0,  
  12.   
  13. 0,  
  14.   
  15. &hCryptHash  
  16.   
  17. ))  
  18.   
  19. CryptDestroyHash(hCryptHash);  
  20.   
  21. …  

4.1.6.5派生密鑰

4.1.6.5.1 CryptDeriveKey

BOOL WINAPI CryptDeriveKey(

HCRYPTPROV hProv,

ALG_ID Algid,

HCRYPTHASH hBaseData,

DWORD dwFlags,

HCRYPTKEY *phKey

);

參數:

hProv[in]CSP句柄

Algid[in]要產生密鑰的對稱加密算法

hBaseData[in]哈希對象的句柄

dwFlags[in]指定密鑰的類型

 

參數

作用

CRYPT_CREATE_SALT

由哈希值產生一個會話密鑰,有一些需要補位。如果用此標誌,密鑰將會賦予一個鹽值

CRYPT_EXPORTABLE

如果置此標誌,密鑰就可以用CryptExportKey函數導出。

CRYPT_NO_SALT

如果置此標誌,表示40位的密鑰不需要分配鹽值。

CRYPT_UPDATE_KEY

有些CSP從多個哈希值中派生會話密鑰。如果這種情況,CryptDeriveKey需要多次調用。

 

phKey[in/out]密鑰的句柄

說明:

此函數從一基本數據值中派生會話密鑰。函數保證當CSP和算法相同時,從相同基本數據值中產生的密鑰是唯一的。

4.1.6.5.2 CryptDestroyKey

BOOL WINAPI CryptDestroyKey(

HCRYPTKEY hKey

);

參數:

hKey[in]需要銷燬的密鑰句柄

說明:

此函數釋放密鑰句柄。

[cpp] view plaincopy
 
 
 
  1. …  
  2.   
  3. HCRYPTKEY hCryptKey;  
  4.   
  5. if (CryptDeriveKey(hCryptProv, m_algid, m_hHash, 0, &hCryptKey))  
  6.   
  7. CryptDestroyKey(hCryptKey);  
  8.   
  9. …  

4.1.6.6加密/解密

4.1.6.6.1 CryptEncrypt

BOOL WINAPI CryptEncrypt(

HCRYPTKEY hKey,

HCRYPTHASH hHash,

BOOL Final,

DWORD dwFlags,

BYTE *pbData,

DWORD *pdwDataLen,

DWORD dwBufLen

);

參數:

hKey[in]加密密鑰的句柄

hHash[in]哈希對象的句柄。如果數據需要同時被哈希並且加密,hHash就指出了哈希對象。

Final[in]指出是否是最後一次加密操作。如果Final爲TRUE,就爲最後一次,否則爲FALSE。

dwFlags[in]保留

pbData[in/out]指向被加密的數據地址。

pdwDataLen[in/out]指向一個DWORD值的地址。在調用此函數前,這個值就是需要加密的數據長度。在調用此函數後,這個值就是已經加密的數據長度。如果此值爲NULL,函數就返回需要數據的長度。

dwBufferLen[in]指出pbData的數據長度。

說明:

此函數用於加密數據。加密數據所需要的算法由hKey的密鑰指定。

4.1.6.6.2 CryptDecrypt

BOOL WINAPI CryptDecrypt(

HCRYPTKEY hKey,

HCRYPTHASH hHash,

BOOL Final,

DWORD dwFlags,

BYTE *pbData,

DWORD *pdwDataLen

);

參數:

hKey[in]解密密鑰的句柄

hHash[in]哈希對象的句柄。如果需要解密數據並且同時作哈希,hHash傳遞此參數。

Final[in]指出是否是最後一次解密操作。

dwFlags[in]保留

pbData[in/out]需要解密數據的地址

pdwDataLen[in/out]指向DWORD值的指針,此值指出解密數據的長度。在調用此函數前,此值爲需要解密數據的長度,調用此函數後,此值爲已經解密的數據長度。

說明:

此函數對由CryptEncrypt加密過的數據進行解密。

[cpp] view plaincopy
 
 
 
  1. //---------------------------------------------------  
  2.   
  3. HCRYPTPROV hCryptProv;  
  4.   
  5. HCRYPTHASH hCryptHash;  
  6.   
  7. HCRYPTKEY hCryptKey;  
  8.   
  9. CryptAcquireContext(  
  10.   
  11.              hCryptProv, NULL,  
  12.   
  13.              MS_DEF_PROV,  
  14.   
  15.              PROV_RSA_FULL,  
  16.   
  17.              CRYPT_VERIFYCONTEXT);  
  18.   
  19. CryptCreateHash(  
  20.   
  21.         hCryptProv,  
  22.   
  23.         CALG_MD5,  
  24.   
  25.         0,  
  26.   
  27.         0,  
  28.   
  29.         &hCryptHash  
  30.   
  31.         );  
  32.   
  33. static char szHash[]=”PISAHASHDATA”; //原始字符串  
  34.   
  35. DWORD dwLen=strlen(szHash);  
  36.   
  37. CryptHashData(hCryptHash, (BYTE*)szHash, dwLen, 0);  
  38.   
  39. CryptDeriveKey(hCryptProv, CALG_RC2, hCryptHash, 0, &hCryptKey);  
  40.   
  41. static char szEntry[]=“PISA2002”;  
  42.   
  43. DWORD dwLenIn = strlen(szEntry);  
  44.   
  45. DWORD dwLenOut=dwLenIn;  
  46.   
  47. CryptEncrypt(hCryptKey, 0, TRUE, 0, (BYTE*)szEntry, &dwLenOut, dwLenIn);  
  48.   
  49. CryptDecrypt(hCryptKey, 0, TRUE, 0,(BYTE*)szEntry,&dwLenOut);  
  50.   
  51. CryptDestroyKey(hCryptKey);  
  52.   
  53. CryptDestroyHash(hCryptHash);  
  54.   
  55. CryptReleaseContext(hCryptProv, NULL);  

4.1.6.7簽名/驗證

4.1.6.7.1 CryptSignMessage

BOOL WINAPI CryptSignMessage(

PCRYPT_SIGN_MESSAGE_PARA pSignPara,

BOOL fDetachedSignature,

DWORD cToBeSigned,

const BYTE *rgpbToBeSigned[ ],

DWORD rgcbToBeSigned[ ],

BYTE *pbSignedBlob,

DWORD *pcbSignedBlob

);

參數:

pSignPara[in]指向CRYPT_SIGN_MESSAGE_PARA結構的指針。

CRYPT_SIGN_MESSAGE_PARA結構如下:

[cpp] view plaincopy
 
 
 
  1. typedef struct _CRYPT_SIGN_MESSAGE_PARA {  
  2.   
  3.     DWORD cbSize;  
  4.   
  5.     DWORD dwMsgEncodingType;  
  6.   
  7.     PCCERT_CONTEXT pSigningCert;  
  8.   
  9.     CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm;  
  10.   
  11.     void *pvHashAuxInfo;  
  12.   
  13.     DWORD cMsgCert;  
  14.   
  15.     PCCERT_CONTEXT *rgpMsgCert;  
  16.   
  17.     DWORD cMsgCrl;  
  18.   
  19.     PCCRL_CONTEXT *rgpMsgCrl;  
  20.   
  21.     DWORD cAuthAttr;  
  22.   
  23.     PCRYPT_ATTRIBUTE rgAuthAttr;  
  24.   
  25.     DWORD cUnauthAttr;  
  26.   
  27.     PCRYPT_ATTRIBUTE rgUnauthAttr;  
  28.   
  29.     DWORD dwFlags;  
  30.   
  31.     DWORD dwInnerContentType;  
  32.   
  33. #ifdef CRYPT_SIGN_MESSAGE_PARA_HAS_CMS_FIELDS  
  34.   
  35.     CRYPT_ALGORITHM_IDNETIFIER HashEncryptionAlgorithm;  
  36.   
  37.     void pvHashEncryptionAuxInfo;  
  38.   
  39. #endif  
  40.   
  41. } CRYPT_SIGN_MESSAGE_PARA, *PCRYPT_SIGN_MESSAGE_PARA;  

cbSize此結構的大小。

dwMsgEncodingType使用的編碼類型。一般爲X509_ASN_ENCODING | PKCS_7_ASN_ENCODING

pSigningCert指向要簽名的CERT_CONTEXT指針。

HashAlgorithm CRYPT_ALGORITHM_IDENTIFIER指出了對要進行簽名的數據進行哈希的哈希算法

pvHashAuxInfo必須爲NULL

cMsgCert   rgpMsgCert數組中CERT_CONTEXT結構的元素數量。如果此值爲0,則簽名消息中不包含任何證書。

rgpMsgCert指向CERT_CONTEXT的數組指針。如果包含pSigningCert,它的指針必須放到rgpMsgCert數組中。

cMsgCrl rgpMsgCrl數組指向CRL_CONTEXT結構的元素數量。如果爲0,簽名消息中不包含任何CRL_CONTEXT結構。

rgpMsgCrl 指向CRL_CONTEXT結構的數組指針。

cAuthAttr必須爲0

rgAuthAttr指向CRYPT_ATTRIBUTE數組的指針。每一次都包含了認證信息。

cUnauthAttrrg UnauthAttr數組大小。

rgUnauthAttr指向CRYPT_ATTRIBUTE結構的數組指針。

dwFlags通常爲0。

dwInnerContentType通常爲0。

HashEncryptionAlgorithm  CRYPT_ALGORITHM_IDENTIFIER結構。通常爲0

pvHashEncryptionAuxInfo必須爲0。

fDetachedSignature[in]如果爲TRUE,就是已解邦定的簽名,否則爲FALSE。如果此參數爲TRUE,

pbSignedBlob中只有簽名哈希。否則rgpbToBeSigned和簽名哈希都要被編碼。

cToBeSigned[in]指出rgpbToBeSigned數據元素的個數。除非fDetachedSigned 爲TRUE,此參數就是1。

rgpbToBeSigned[in]指向要簽名數據的數組指針。

pbSignedBlob[out]指向一個接收簽名哈希的數據地址。如果此參數爲NULL,就是需要來接收數據的內存大小。

pcbSignedBlob[in/out]指向DWORD的地址,此數據指出pbSignedBlob 的大小。

說明:

此函數對指定數據進行哈希,然後對哈希值進行簽名,然後對原始消息和簽名哈希進行編碼。

[cpp] view plaincopy
 
 
 
  1. //--------------------------------------------------------------------  
  2.   
  3. …  
  4.   
  5. #define MY_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)  
  6.   
  7. #define SIGNER_NAME L"Insert_signer_name_here"  
  8.   
  9. #define CERT_STORE_NAME L"MY"  
  10.   
  11. void HandleError(char *s);  
  12.   
  13. void main(void)  
  14.   
  15. {  
  16.   
  17.     //系統證書庫句柄  
  18.   
  19.     HCERTSTORE hStoreHandle;  
  20.   
  21.     //--------------------------------------------------------------------  
  22.   
  23.     //待簽名的消息  
  24.   
  25.     BYTE* pbMessage =  
  26.   
  27.         (BYTE*)"CryptoAPI is a good way to handle security";  
  28.   
  29.     //--------------------------------------------------------------------  
  30.   
  31.     DWORD cbMessage = strlen((char*) pbMessage)+1;  
  32.   
  33.     //--------------------------------------------------------------------  
  34.   
  35.     //證書的上下文  
  36.   
  37.     PCCERT_CONTEXT pSignerCert;  
  38.   
  39.     CRYPT_SIGN_MESSAGE_PARA SigParams;  
  40.   
  41.     DWORD cbSignedMessageBlob;  
  42.   
  43.     BYTE *pbSignedMessageBlob;  
  44.   
  45.     DWORD cbDecodedMessageBlob;  
  46.   
  47.     BYTE *pbDecodedMessageBlob;  
  48.   
  49.     CRYPT_VERIFY_MESSAGE_PARA VerifyParams;  
  50.   
  51.     //--------------------------------------------------------------------  
  52.   
  53.     const BYTE* MessageArray[] = {pbMessage};  
  54.   
  55.     DWORD MessageSizeArray[1];  
  56.   
  57.     MessageSizeArray[0] = cbMessage;  
  58.   
  59.     //--------------------------------------------------------------------  
  60.   
  61.     //  
  62.   
  63.     printf("Begin processing. \n");  
  64.   
  65.     printf(" The message to be signed is\n-> %s.\n",pbMessage);  
  66.   
  67.     //--------------------------------------------------------------------  
  68.   
  69.     // Open a certificate store.  
  70.   
  71.     if ( !( hStoreHandle = CertOpenStore(  
  72.   
  73.         CERT_STORE_PROV_SYSTEM,  
  74.   
  75.         0,  
  76.   
  77.         NULL,  
  78.   
  79.         CERT_SYSTEM_STORE_CURRENT_USER,  
  80.   
  81.         CERT_STORE_NAME)))  
  82.   
  83.     {  
  84.   
  85.         HandleError("The MY store could not be opened.");  
  86.   
  87.     }  
  88.   
  89.     //--------------------------------------------------------------------  
  90.   
  91.     //  
  92.   
  93.     //得到證書的上下文,此證書必須能訪問簽名者的私鑰  
  94.   
  95.     if(pSignerCert = CertFindCertificateInStore(  
  96.   
  97.         hStoreHandle,  
  98.   
  99.         MY_TYPE,  
  100.   
  101.         0,  
  102.   
  103.         CERT_FIND_SUBJECT_STR,  
  104.   
  105.         SIGNER_NAME,  
  106.   
  107.         NULL))  
  108.   
  109.     {  
  110.   
  111.         printf("The signer's certificate was found.\n");  
  112.   
  113.     }  
  114.   
  115.     else  
  116.   
  117.     {  
  118.   
  119.         HandleError( "Signer certificate not found.");  
  120.   
  121.     }  
  122.   
  123.     //--------------------------------------------------------------------  
  124.   
  125.     //初始化簽名結構  
  126.   
  127.     SigParams.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA);  
  128.   
  129.     SigParams.dwMsgEncodingType = MY_TYPE;  
  130.   
  131.     SigParams.pSigningCert = pSignerCert;  
  132.   
  133.     SigParams.HashAlgorithm.pszObjId = szOID_RSA_MD5;  
  134.   
  135.     SigParams.HashAlgorithm.Parameters.cbData = NULL;  
  136.   
  137.     SigParams.cMsgCert = 1;  
  138.   
  139.     SigParams.rgpMsgCert = &pSignerCert;  
  140.   
  141.     SigParams.cAuthAttr = 0;  
  142.   
  143.     SigParams.dwInnerContentType = 0;  
  144.   
  145.     SigParams.cMsgCrl = 0;  
  146.   
  147.     SigParams.cUnauthAttr = 0;  
  148.   
  149.     SigParams.dwFlags = 0;  
  150.   
  151.     SigParams.pvHashAuxInfo = NULL;  
  152.   
  153.     SigParams.rgAuthAttr = NULL;  
  154.   
  155.     //--------------------------------------------------------------------  
  156.   
  157.     //  
  158.   
  159.     //首先得到BLOB的大小  
  160.   
  161.     if(CryptSignMessage(  
  162.   
  163.         &SigParams, // Signature parameters  
  164.   
  165.         FALSE, // Not detached  
  166.   
  167.         1, // Number of messages  
  168.   
  169.         MessageArray, // Messages to be signed  
  170.   
  171.         MessageSizeArray, // Size of messages  
  172.   
  173.         NULL, // Buffer for signed message  
  174.   
  175.         &cbSignedMessageBlob)) // Size of buffer  
  176.   
  177.     {  
  178.   
  179.         printf("The size of the BLOB is %d.\n",cbSignedMessageBlob);  
  180.   
  181.     }  
  182.   
  183.     else  
  184.   
  185.     {  
  186.   
  187.         HandleError("Getting signed BLOB size failed");  
  188.   
  189.     }  
  190.   
  191.     //--------------------------------------------------------------------  
  192.   
  193.     //分配BLOB的內存.  
  194.   
  195.     if(!(pbSignedMessageBlob =  
  196.   
  197.         (BYTE*)malloc(cbSignedMessageBlob)))  
  198.   
  199.     {  
  200.   
  201.         HandleError("Memory allocation error while signing.");  
  202.   
  203.     }  
  204.   
  205.     //--------------------------------------------------------------------  
  206.   
  207.     //  
  208.   
  209.     if(CryptSignMessage(  
  210.   
  211.         &SigParams, //  
  212.   
  213.         FALSE, //  
  214.   
  215.         1, //消息數量  
  216.   
  217.         MessageArray, //待簽名的消息  
  218.   
  219.         MessageSizeArray, //消息大小  
  220.   
  221.         pbSignedMessageBlob, //緩衝區  
  222.   
  223.         &cbSignedMessageBlob)) //緩衝區大小  
  224.   
  225.     {  
  226.   
  227.         printf("The message was signed successfully. \n");  
  228.   
  229.     }  
  230.   
  231.     else  
  232.   
  233.     {  
  234.   
  235.         HandleError("Error getting signed BLOB");  
  236.   
  237.     }  
  238.   
  239.     //--------------------------------------------------------------------  
  240.   
  241.     //驗證簽名信息  
  242.   
  243.     //--------------------------------------------------------------------  
  244.   
  245.     //初始化VerifyParams結構.  
  246.   
  247.     VerifyParams.cbSize = sizeof(CRYPT_VERIFY_MESSAGE_PARA);  
  248.   
  249.     VerifyParams.dwMsgAndCertEncodingType = MY_TYPE;  
  250.   
  251.     VerifyParams.hCryptProv = 0;  
  252.   
  253.     VerifyParams.pfnGetSignerCertificate = NULL;  
  254.   
  255.     VerifyParams.pvGetArg = NULL;  
  256.   
  257.     //--------------------------------------------------------------------  
  258.   
  259.     //  
  260.   
  261.     if(CryptVerifyMessageSignature(  
  262.   
  263.         &VerifyParams, //.  
  264.   
  265.         0, //  
  266.   
  267.         pbSignedMessageBlob, //.  
  268.   
  269.         cbSignedMessageBlob, //  
  270.   
  271.         NULL, //  
  272.   
  273.         &cbDecodedMessageBlob, //.  
  274.   
  275.         NULL)) // Pointer to signer certificate.  
  276.   
  277.     {  
  278.   
  279.         printf("%d bytes need for the buffer.\n",cbDecodedMessageBlob);  
  280.   
  281.     }  
  282.   
  283.     else  
  284.   
  285.     {  
  286.   
  287.         printf("Verification message failed. \n");  
  288.   
  289.     }  
  290.   
  291.     //--------------------------------------------------------------------  
  292.   
  293.     //爲緩衝區分配內存.  
  294.   
  295.     if(!(pbDecodedMessageBlob =  
  296.   
  297.         (BYTE*)malloc(cbDecodedMessageBlob)))  
  298.   
  299.     {  
  300.   
  301.         HandleError("Memory allocation error allocating decode BLOB.");  
  302.   
  303.     }  
  304.   
  305.     //--------------------------------------------------------------------  
  306.   
  307.     //  
  308.   
  309.     //得到緩衝區的大小  
  310.   
  311.     if(CryptVerifyMessageSignature(  
  312.   
  313.         &VerifyParams, // Verify parameters.  
  314.   
  315.         0, // Signer index.  
  316.   
  317.         pbSignedMessageBlob, // Pointer to signed BLOB.  
  318.   
  319.         cbSignedMessageBlob, // Size of signed BLOB.  
  320.   
  321.         pbDecodedMessageBlob, // Buffer for decoded message.  
  322.   
  323.         &cbDecodedMessageBlob, // Size of buffer.  
  324.   
  325.         NULL)) // Pointer to signer certificate.  
  326.   
  327.     {  
  328.   
  329.         printf("The verified message is \n-> %s \n",pbDecodedMessageBlob);  
  330.   
  331.     }  
  332.   
  333.     else  
  334.   
  335.     {  
  336.   
  337.         printf("Verification message failed. \n");  
  338.   
  339.     }  
  340.   
  341.     //--------------------------------------------------------------------  
  342.   
  343.     //  
  344.   
  345.     if(pbSignedMessageBlob)  
  346.   
  347.         free(pbSignedMessageBlob);  
  348.   
  349.     if(pbDecodedMessageBlob)  
  350.   
  351.         free(pbDecodedMessageBlob);  
  352.   
  353.     if(pSignerCert)  
  354.   
  355.         CertFreeCertificateContext(pSignerCert);  
  356.   
  357.     if(CertCloseStore(  
  358.   
  359.         hStoreHandle,  
  360.   
  361.         CERT_CLOSE_STORE_CHECK_FLAG))  
  362.   
  363.     {  
  364.   
  365.         printf("The store closed and all certificates are freed. \n");  
  366.   
  367.     }  
  368.   
  369.     else  
  370.   
  371.     {  
  372.   
  373.         printf("Store closed after signing -- \n"  
  374.   
  375.             "not all certificates, CRLs or CTLs were freed");  
  376.   
  377.     }  
  378.   
  379.     …  

4.2證書和證書庫函數

這組函數管理、使用和取得證書、證書撤銷列表和證書信任列表。這些函數可以分成一下幾組:

4.2.1證書庫函數

一個用戶站點可以收集許多證書。這些證書是爲這個站點的用戶所使用的,證書描述了這個用戶的具體身份。對於每個人,可能有一個以上的證書。證書庫和其相關的函數提供了

對庫獲得、枚舉、驗證和使用證書庫裏的信息。

以下就是這些函數:

CertAddStoreToCollection在證書庫中增加一個證書

CertCloseStore關閉一個證書庫句柄

CertControlStore如果證書緩衝區和證書本身內容不相符時,允許給應用程序發一個通知

CertDuplicateStore通過增加引用計數來複制證書庫句柄

CertEnumPhysicalStore對於指定系統庫枚舉物理庫

CertEnumSystemStore枚舉所有可用的系統庫

CertEnumSystemStoreLocation枚舉可用系統庫的所有位置

CertGetStoreProperty得到一個庫的屬性

CertOpenStore使用指定庫類型來打開證書庫

CertOpenSystemStore打開一個系統證書庫

CertRegisterPhysicalStore在一個註冊系統庫裏增加一個物理庫

CertRegisterSystemStore註冊一個系統庫

CertRemoveStoreFromCollection從一個庫集合裏刪除證書庫

CertSaveStore保存證書庫

CertSetStoreProperty設置證書屬性

CertUnregisterPhysicalStore從系統庫中刪除一個物理庫

CertUnregisterSystemStore反註冊一個指定系統庫

4.2.2維護函數

CryptoAPI提供了證書和證書庫函數如下:

CertAddSerializeElementToStore在庫中增加一系列證書或CRL

CertCreateContext從編碼字節中創建指定上下文

CertEnumSubjectInSortedCTL在CTL庫中枚舉信任主題

CertFindSubjectInCTL在CTL中尋找指定主題

CertFindSubjectInSortedCTL在分類CTL中尋找指定主題

4.2.3證書函數

下列函數是針對於證書的。大多數函數都是處理CRL和CTL 的。

CertAddCertificateContextToStore在證書庫裏增加一個證書上下文

CertAddCertificateLinkToStore在證書庫裏增加一個對不同庫裏的證書上下文的鏈接

CertAddEncodedCertificateToStore把編碼證書轉換成證書上下文並且把它加到證書庫裏

CertCreateCertificateContext從編碼證書中創建一個證書上下文。但這個上下文並不放到證書庫裏

CertCreateSelfSignCertificate創建一個自簽名證書

CertDeleteCertificateFromStore從證書庫裏刪除一個證書

CertDuplicateCertificate通過增加引用計數來複制證書上下文

CertEnumCertificateInStore在證書庫裏枚舉證書上下文

CertFindCertificateInStore在證書庫裏尋找證書上下文

CertFreeCertificateContext釋放一個證書上下文

CertGetIssuerCertificateFromStore在證書庫裏得到指定主題證書的發行者

CertGetSubjectCertificateFromStore獲得主題證書的上下文

CertGetValidUsages返回所有證書的用法

CertSerializeCertificateStoreElement串行化編碼證書的證書上下文

CertVerifySubjectCertificateContext使用發行者來驗證主題證書

CryptUIDlgViewContext顯示證書、CRL或CTL

CryptUIDlgSelectCertificateFromStore從指定庫中顯示對話框,可以從中選擇證書

4.2.4證書撤銷列表函數

CertAddCRLContextToStore在證書庫裏增加一個CRL上下文

CertAddCRLLinkToStore在不同的庫裏增加一個CRL上下文鏈接

CertAddEncodedCRLToStore把編碼CRL轉化成CRL 上下文然後把它加入到證書庫中

CertCreateCRLContext從編碼CRL中創建CRL 句柄,但不把它加到庫中

CertDeleteCRLFromStore從證書庫裏刪除一個CRL

CertDuplicateCRLContext通過增加引用計數來複制CRL上下文

CertEnumCRLsInStore枚舉庫裏的CRL句柄

CertFindCertificateInCRL從指定證書裏尋找CRL列表

CertFindCRLInStore在庫裏尋找CRL上下文

CertFreeCRLContext釋放CRL上下文

CertGetCRLFromStore從庫裏得到CRL上下文句柄

CertSerializeCRLStoreElement串行化CRL上下文的編碼CRL 和它的屬性

4.2.5證書信任列表函數

CertAddCTLContextToStore把一個CTL上下文加入到證書庫裏

CertAddCTLLinkToStore給不同庫裏的CRL上下文添加鏈接

CertAddEncodedCTLToStore把編碼CTL轉化成CTL 上下文並且把它加到證書庫裏

CertCreateCTLContext從編碼CTL中創建CTL 上下文

CertDeleteCTLFromStore從證書庫裏刪除CTL

CertDuplicateCTLContext通過增加引用計數來複制CTL上下文

CertEnumCTLsInStore在證書庫裏枚舉CTL上下文

CertFindCTLInStore在證書庫裏查找CTL上下文

CertFreeCTLContext釋放CTL上下文

CertSerializeCTLStoreElement串行化CTL上下文的編碼CTL 和屬性

4.2.6擴展屬性函數

CertEnumCertificateContextProperties枚舉指定證書上下文的屬性

CertEnumCRLContextProperties枚舉指定CRL上下文的屬性

CertEnumCTLContextProperties枚舉指定CTL上下文的屬性

CertGetCertificateContextProperty得到證書屬性

CertGetCRLContextProperty得到CRL屬性

CertGetCTLContextProperty得到CTL屬性

CertSetCertificateContextProperty設置證書屬性

CertSetCRLContextProperty設置CRL屬性

CertSetCTLContextProperty設置CTL屬性

4.2.7函數詳解

4.2.7.1打開/關閉系統證書庫

4.2.7.1.1 CertOpenSystemStore

HCERTSTORE WINAPI CertOpenSystemStore(

HCRYPTPROV hProv,

LPCTSTR szSubsystemProtocol,

);

參數:

hProv[in] CSP句柄。如果爲NULL,就爲卻省CSP。如果不爲NULL,它必須是由CryptAcquireContext得到的CSP句柄。

szSubsystemProtocol[in]系統證書庫的名稱。可以爲”CA”、”MY”、”ROOT”、”SPC”。

說明:

此函數用來打開通用的系統證書庫。

4.2.7.1.2 CertCloseStore

BOOL WINAPI CertCloseStore(

HCERTSTORE hCertStore,

DWORD dwFlags

);

參數:

hCertStore[in]證書庫句柄。

dwFlags[in]典型地,此參數爲0。卻省就是關閉證書庫,對於爲上下文分配的內存並不釋放。如果想要檢查並且釋放所有爲證書、CRL和CTL 上下文的分配的內存,就要置下列標誌。

CERT_CLOSE_STORE_CHECK_FLAG檢查沒有釋放的證書、CRL和CTL 上下文。

CERT_CLOSE_STORE_FORCE_FLAG強制釋放所有和證書庫相關的上下文。

說明:

此函數釋放證書庫句柄。

[cpp] view plaincopy
 
 
 
  1. //-----------------------------------------------------------------  
  2.   
  3. …  
  4.   
  5. HCERTSTORE hSystemStore;  
  6.   
  7. if(hSystemStore = CertOpenSystemStore(0,"MY"))  
  8.   
  9. {  
  10.   
  11.     printf("The MY system store is open. Continue.\n");  
  12.   
  13.     CertCloseStore(hSystemStore, CERT_CLOSE_STORE_CHECK_FLAG);  
  14.   
  15. }  
  16.   
  17. else  
  18.   
  19. {  
  20.   
  21.     printf("The MY system store did not open.\n");  
  22.   
  23.     exit(1);  
  24.   
  25. }  
  26.   
  27. …  

4.3證書驗證函數

證書驗證是通過CTL和證書列表進行的。

4.3.1使用CTL的函數

CertVerifyCTLUsage驗證CTL用法

CryptMsgEncodeAndSignCTL編碼和驗證CTL

CryptMsgGetAndVerifySigner從一個消息中獲得和驗證CTL

CryptMsgSignCTL對包含CTL的消息進行簽名

4.3.2證書鏈驗證函數

CertCreateCertificateChainEngine爲應用程序創建一個新的非卻省的鏈引擎

CertCreateCTLEntryFromCertificateContextProperties創建一個CTL入口

CertDuplicateCertificateChain通過增加引用計數來複制證書鏈

CertFindChainInStore在證書庫裏查找證書鏈

CertFreeCertificateChain釋放證書鏈

CertFreeCertificateChainEngine釋放證書鏈引擎

CertGetCertificateChain從最後一個證書建立一個上下文鏈表

CertSetCertificateContextPropertiesFromCTLEntry通過CTL入口屬性來設置證書上下文的屬性

CertIsValidCRLForCertificate通過檢查CRL來確定CRL 是否包括指定被撤銷的證書

CertVerifyCertificateChainPolicy通過檢查證書鏈來確定它的完整性

4.4消息函數

CryptoAPI消息函數包括兩組:低級消息函數和簡化消息函數。

  • 低級消息函數直接和PKCS#7消息工作。這些函數對傳輸的PKCS#7 數據進行編碼,對接收到的PKCS#7數據進行解碼,並且對接收到的消息進行解密和驗證。
  • 簡化消息函數是比較高級的函數,是對幾個低級消息函數和證書函數的封裝,用來執行指定任務。這些函數在完成一個任務時,減少了函數調用的數量,因此簡化了CryptoAPI的使用。

4.4.1低級消息函數

CryptMsgCalculateEncodedLength計算加密消息的長度

CryptMsgClose關閉加密消息的句柄

CryptMsgControl執行指定的控制函數

CryptMsgCountersign標記消息中已存在的簽名

CryptMsgCountersignEncoded標記已存在的簽名

CryptMsgDuplicate通過增加引用計數來複制加密消息句柄

CryptMsgGetParam對加密消息進行編碼或者解碼後得到的參數

CryptMsgOpenToDecode打開加密消息進行解碼

CryptMsgOpenToEncode打開加密消息進行編碼

CryptMsgUpdate更新加密消息的內容

CryptMsgVerifyCountersignatureEncoded驗證SignerInfo結構中標記時間

CryptMsgVerifyCountersignatureEncodedEx驗證SignerInfo結構中標記時間,簽名者可以是CERT_PUBLIC_KEY_INFO結構

4.4.2簡化消息函數

CryptDecodeMessage對加密消息進行解碼

CryptDecryptAndVerifyMessageSignature對指定消息進行解密並且驗證簽名者

CryptDecryptMessage解密指定消息

CryptEncryptMessage加密指定消息

CryptGetMessageCertificates返回包含消息的證書和CRL的證書庫

CryptGetMessageSignatureCount返回簽名消息的簽名者數量

CryptHashMessage創建消息的哈希

CryptSignAndEncryptMessage對消息進行簽名並且加密

CryptSignMessage對消息進行簽名

CryptVerifyDetachedMessageHash驗證包含已解邦定哈希的哈希消息

CryptVerifyDetachedMessageSignature驗證包含已解邦定簽名的簽名消息

CryptVerifyMessageHash驗證一個哈希消息

CryptVerifyMessageSignature驗證一個簽名消息

4.5輔助函數

4.5.1數據管理函數

CertCompareCertificate比較兩個證書是否相同

CertCompareCertificateName通過比較兩個證書名稱來決定他們是否相同

CertCompareIntegerBlob比較兩個整數BLOB

CertComparePublicKeyInfo通過比較兩個證書公鑰來決定他們是否相同

CertFindAttribute通過OID來查找屬性

CertFindExtension通過OID來查找擴展

CertFindRDNAttr通過OID來查找RDN 屬性

CertGetIntendedKeyUsage從證書中取得相關密鑰用法

CertGetPublicKeyLength從公鑰BLOB中取得公鑰/私鑰長度

CertIsRDNAttrsInCertificateName通過指定RDN數組屬性比較證書名稱屬性來決定證書是否已包含了所有屬性

CertVerifyCRLRevocation驗證主題證書是否在CRL中

CertVerifyCRLTimeValidity驗證CRL的有效時間

CertVerifyRevocation驗證主題證書是否在CRL中

CertVerifyTimeValidity驗證CRL的有效時間

CertVerifyValidityNesting驗證主題時間的有效性是否在發行者有效時間內

CryptExportPublicKeyInfo導出公鑰信息

CryptExportPublicKeyInfoEx導出公鑰信息(用戶可以指定算法)

CryptFindCertificateKeyProvInfo枚舉CSP和它的密鑰容器來查找對應於公鑰的相應私鑰

CryptFindLocalizedName查找指定名字的局部化名稱

CryptHashCertificate哈希證書內容

CryptHashPublicKeyInfo計算公鑰信息的哈希

CryptHashToBeSigned計算簽名內容的信息哈希值

CryptImportPublicKeyInfo把公鑰信息導入CSP並且返回它的句柄

CryptImportPublicKeyInfoEx把公鑰信息導入CSP並且返回它的句柄

CryptMemAlloc分配內存

CryptMemFree釋放內存

CryptMemRealloc重新分配內存

CryptQueryObject得到BLOB或文件的內容信息

CryptSignAndEncodeCertificate對信息進行簽名並且編碼

CryptSignCertificate對證書進行簽名

CryptVerifyCertificateSignature使用公鑰信息對主題證書或CRL的簽名進行驗證

CryptVerifyCertificateSignatureEx使用公鑰信息對主題證書或CRL的簽名進行驗證

4.5.2數據轉換函數

CertAlgIdToOID把CSP算法標示符轉換成OID

CertGetNameString得到證書的主題或頒發者名稱並且把它轉換成字符串

CertNameToStr把證書名稱BLOB轉換成字符串

CertOIDToAlgId把OID轉換成CSP 算法表示符

CertRDNValueToStr把名稱值轉換成字符串

CertStrToName把字符串轉換成編碼證書名稱

CryptBinaryToString把二進制序列轉換成字符串

CryptFormatObject格式化編碼數據,返回Unicode字符串

CryptStringToBinary把格式化的字符串轉換成二進制序列

4.5.3增強密鑰用法函數

CertAddEnhancedKeyUsageIdentifier在證書EKU屬性中增加一個用法標示符

CertGetEnhancedKeyUsage獲得證書的EKU擴展或屬性信息

CertRemoveEnhancedKeyUsageIdentifier從證書EKU擴展屬性中刪除用法標示符OID

CertSetEnhancedKeyUsage設置證書的EKU屬性

4.5.4密鑰標示函數

CryptCreateKeyIdentifierFromCSP創建CSP公鑰的密鑰標示符

CryptEnumKeyIdentifierProperties枚舉標示符和其屬性

CryptGetKeyIdentifierProperty從指定密鑰標示符中獲得指定屬性

CryptSetKeyIdentifierProperty設置指定密鑰標示符的屬性

4.5.5證書庫回調函數

CertDllOpenStoreProv定義庫提供者打開函數

CertStoreProvCloseCallback決定當證書庫引用計數爲0時將發生的動作

CertStoreProvDeleteCertCallback決定當從證書庫中刪除一個證書之前的動作

CertStoreProvDeleteCRLCallback決定當從證書庫中刪除一個CRL之前的動作

CertStoreProvReadCertCallback保留

CertStoreProvReadCRLCallback保留

CertStoreProvSetCertPropertyCallback決定在CertSetCertificateContextProperty和

CertGetCertificateContext調用之前的動作

CertStoreProvSetCRLPropertyCallback決定在CertSetCRLContextProperty和

CertGetCRLContextProperty調用之前的動作

CertStoreProvWriteCertCallback決定在證書庫中加入一個證書前的動作

CertStoreProvWriteCRLCallback決定在證書庫中加入一個CRL前的動作

CertStoreProvReadCTL讀CSP的CTL 上下文

CertStoreProvWriteCTL決定CTL是否可被加入到證書庫中

CertStoreProvDeleteCTL決定CTL是否可被刪除

CertStoreProvSetCTLProperty決定是否可以設置CTL的屬性

CertStoreProvControl當緩衝庫和存儲庫不同時,通知應用程序

CertStoreProvFindCert在證書庫中查找下一個證書

CertStoreProvFreeFindCert釋放前一個找到的證書上下文

CertStoreProvGetCertProperty得到指定的證書屬性

CertStoreProvFindCRL查找第一個或下一個匹配的CRL

CertStoreProvFreeFindCRL釋放前一個找到的CRL上下文

CertStoreProvGetCRLProperty得到指定CRL屬性

CertStoreProvFindCTL查找第一個或下一個匹配的CTL

CertStoreProvFreeFindCTL釋放前一個找到的CTL上下文

CertStoreProvGetCTLProperty得到指定CTL屬性

4.5.6 OID支持函數

CryptEnumOIDFuction枚舉由編碼類型、函數名和OID指定註冊的OID函數

CryptEnumOIDInfo枚舉註冊的OID信息

CryptEnumOIDInfo使用指定的密鑰和組查找OID信息

CryptFreeOIDFuctionAddress釋放OID函數地址句柄

CryptGetDefaultOIDDllList對於指定的函數結合和類型獲得卻省註冊的DLL入口

CryptGetDefaultOIDFuctionAddress獲得已安裝的第一次或下一個卻省函數或者加載包含卻省函數的DLL

CryptGetOIDFuctionAddress搜索匹配指定編碼類型和OID函數列表,如果沒有找到,就查找註冊表。

CryptGetOIDFuctionValue獲得指定編碼類型、函數名稱和OID的值

CryptInitOIDFuctionSet初始化OID函數集合的句柄

CryptInstallOIDFuctionAddress安裝可調用的OID函數地址集合

CryptRegisterDefaultOIDFuction註冊包含卻省函數的DLL

CryptRegisterOIDFuction註冊包含指定函數的DLL

CryptRegisterOIDInfo註冊由CRYPT_OID_INFO指定的OID 信息

CryptSetOIDFuctionValue設置編碼類型、函數名稱等的值

CryptUnregisterDefaultOIDFunction卸載包含卻省函數的DLL

CryptUnregisterOIDFuction卸載包含函數的DLL

CryptUnregisterOIDInfo卸載指定OID的信息

4.5.7遠程對象恢複函數

CryptGetObjectUrl從證書、CTL或CRL 中取得遠程對象的URL

CryptRetrieveObjectByUrl由URL指定位置恢復PKI 對象

4.5.8 PFX函數

PFXExportCertStore從證書庫中導出證書或證書和私鑰

PFXExportCertStoreEx從證書庫中導出證書或證書和私鑰

PFXImportCertStore從PFX BLOB導入到指定證書庫

PFXIsPFXBlob把外層BLOB像pfx 包那樣解碼

PFXVerifyPassword把外層BLOB像pfx 包那樣解碼,並且用指定口令解密

 

一些加密解密標準函數示例——DES,RSA

 

  

 一. DES加密、解密

 

[cpp] view plaincopy
 
 
 
  1. //默認密鑰向量  
  2.   
  3. private byte[] Keys = { 0xEF, 0xAB, 0x56, 0x78, 0x90, 0x34, 0xCD, 0x12 };  
  4.   
  5. /// <summary>  
  6.   
  7. /// DES加密字符串  
  8.   
  9. /// </summary>  
  10.   
  11. /// <param name="encryptString">待加密的字符串</param>  
  12.   
  13. /// <param name="encryptKey">加密密鑰,要求爲8位</param>  
  14.   
  15. /// <returns>加密成功返回加密後的字符串,失敗返回源串</returns>  
  16.   
  17. public string EncryptDES(string encryptString, string encryptKey)  
  18.   
  19. {  
  20.   
  21.     try  
  22.   
  23.     {  
  24.   
  25.         byte[] rgbKey = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 8));  
  26.   
  27.         byte[] rgbIV = Keys;  
  28.   
  29.         byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptString);  
  30.   
  31.         DESCryptoServiceProvider dCSP = new DESCryptoServiceProvider();  
  32.   
  33.         MemoryStream mStream = new MemoryStream();  
  34.   
  35.         CryptoStream cStream = new CryptoStream(mStream, dCSP.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);  
  36.   
  37.         cStream.Write(inputByteArray, 0, inputByteArray.Length);  
  38.   
  39.         cStream.FlushFinalBlock();  
  40.   
  41.         return Convert.ToBase64String(mStream.ToArray());  
  42.   
  43.     }  
  44.   
  45.     catch  
  46.   
  47.     {  
  48.   
  49.         return encryptString;  
  50.   
  51.     }  
  52.   
  53. }  
  54.   
  55.   
  56.   
  57. /// <summary>  
  58.   
  59. /// DES解密字符串  
  60.   
  61. /// </summary>  
  62.   
  63. /// <param name="decryptString">待解密的字符串</param>  
  64.   
  65. /// <param name="decryptKey">解密密鑰,要求爲8位,和加密密鑰相同</param>  
  66.   
  67. /// <returns>解密成功返回解密後的字符串,失敗返源串</returns>  
  68.   
  69. public string DecryptDES(string decryptString, string decryptKey)  
  70.   
  71. {  
  72.   
  73.     try  
  74.   
  75.     {  
  76.   
  77.         byte[] rgbKey = Encoding.UTF8.GetBytes(decryptKey.Substring(0, 8));  
  78.   
  79.         byte[] rgbIV = Keys;  
  80.   
  81.         byte[] inputByteArray = Convert.FromBase64String(decryptString);  
  82.   
  83.         DESCryptoServiceProvider DCSP = new DESCryptoServiceProvider();  
  84.   
  85.         MemoryStream mStream = new MemoryStream();  
  86.   
  87.         CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write);  
  88.   
  89.         cStream.Write(inputByteArray, 0, inputByteArray.Length);  
  90.   
  91.         cStream.FlushFinalBlock();  
  92.   
  93.         return Encoding.UTF8.GetString(mStream.ToArray());  
  94.   
  95.     }  
  96.   
  97.     catch  
  98.   
  99.     {  
  100.   
  101.         return decryptString;  
  102.   
  103.     }  
  104.   
  105. }  

二.  DES/3DES加密算法源代碼

[cpp] view plaincopy
 
 
 
  1. /* Project xxxx 
  2. * Package com.xxxx.utils 
  3. */  
  4. package com.xxxxx.utils;  
  5.   
  6. import java.io.FileInputStream;  
  7. import java.io.ObjectInputStream;  
  8. import java.security.NoSuchAlgorithmException;  
  9. import java.security.Security;  
  10.   
  11. import javax.crypto.Cipher;  
  12. import javax.crypto.KeyGenerator;  
  13. import javax.crypto.NoSuchPaddingException;  
  14. import javax.crypto.SecretKey;  
  15.   
  16. public class DES {  
  17.     private String Algorithm = "DESede"; //"DESede" for Triple DES  
  18.     private KeyGenerator keygen;  
  19.     private SecretKey deskey;  
  20.     private Cipher c;  
  21.     private byte[] cipherByte;  
  22.   
  23.     public DES() {  
  24.         init();  
  25.     }  
  26.     public DES(String filename) {  
  27.         init(filename);  
  28.     }  
  29.     public SecretKey genKey() {  
  30.         try {  
  31.             keygen = KeyGenerator.getInstance(Algorithm);  
  32.             deskey = keygen.generateKey();   //利用JavaBean的持久化將key保存爲文件XXX.key  
  33.         } catch (NoSuchAlgorithmException ex) {  
  34.             ex.printStackTrace();  
  35.         } catch (Exception ex) {  
  36.             ex.printStackTrace();  
  37.         }  
  38.   
  39.         return deskey;  
  40.     }  
  41.     /** 
  42.     *  
  43.     * @param filename 
  44.     */  
  45.     public void init(String filename) {  
  46.         //  restore key  
  47.         Security.addProvider(new com.sun.crypto.provider.SunJCE());  
  48.         try {  
  49.             FileInputStream fis = new FileInputStream(filename);  
  50.             fis = new FileInputStream(filename);  
  51.             ObjectInputStream ois = new ObjectInputStream(fis);  
  52.             deskey = (SecretKey) ois.readObject();  
  53.             ois.close();  
  54.             fis.close();  
  55.             c = Cipher.getInstance(Algorithm);  
  56.         } catch (NoSuchAlgorithmException ex) {  
  57.             ex.printStackTrace();  
  58.         } catch (NoSuchPaddingException ex) {  
  59.             ex.printStackTrace();  
  60.         } catch (Exception ex) {  
  61.             ex.printStackTrace();  
  62.         }  
  63.     }  
  64.     public void init() {  
  65.         Security.addProvider(new com.sun.crypto.provider.SunJCE());  
  66.         try {  
  67.             keygen = KeyGenerator.getInstance(Algorithm);  
  68.             deskey = keygen.generateKey();  
  69.   
  70.             c = Cipher.getInstance(Algorithm);  
  71.         } catch (NoSuchAlgorithmException ex) {  
  72.             ex.printStackTrace();  
  73.         } catch (NoSuchPaddingException ex) {  
  74.             ex.printStackTrace();  
  75.         }  
  76.     }  
  77.   
  78.     public byte[] encryptor(String str) {  
  79.         try {  
  80.             c.init(Cipher.ENCRYPT_MODE, deskey);  
  81.             cipherByte = c.doFinal(str.getBytes());  
  82.         } catch (java.security.InvalidKeyException ex) {  
  83.             ex.printStackTrace();  
  84.         } catch (javax.crypto.BadPaddingException ex) {  
  85.             ex.printStackTrace();  
  86.         } catch (javax.crypto.IllegalBlockSizeException ex) {  
  87.             ex.printStackTrace();  
  88.         } catch (Exception ex) {  
  89.             ex.printStackTrace();  
  90.         }  
  91.         return cipherByte;  
  92.     }  
  93.   
  94.     public String decryptor(byte[] buff) {  
  95.         try {  
  96.             c.init(Cipher.DECRYPT_MODE, deskey);  
  97.             cipherByte = c.doFinal(buff);  
  98.         } catch (java.security.InvalidKeyException ex) {  
  99.             ex.printStackTrace();  
  100.         } catch (javax.crypto.BadPaddingException ex) {  
  101.             ex.printStackTrace();  
  102.         } catch (javax.crypto.IllegalBlockSizeException ex) {  
  103.             ex.printStackTrace();  
  104.         } catch (Exception ex) {  
  105.             ex.printStackTrace();  
  106.         }  
  107.         return (new String(cipherByte));  
  108.     }  
  109. }  
  110.   
  111. /* 
  112. * Project xxxx 
  113. * Package com.xxxx.utils 
  114. * Created on 2003-11-24 
  115. * Author Derys 
  116. */  
  117. package com.xxxx.utils;  
  118.   
  119. /** 
  120. *  
  121. */  
  122. public class XXXDES {  
  123.     private static XXXDES instance = new XXXDES();  
  124.     public XXXDES() {  
  125.   
  126.     }  
  127.     /** 
  128.     *  
  129.     * @param str 
  130.     * @return 
  131.     */  
  132.     public String encrypt(String str) {  
  133.         StringBuffer buffer = new StringBuffer();  
  134.         DES des = new DES("XXX.key");  
  135.   
  136.         byte[] en = des.encryptor(str);  
  137.   
  138.         for (int i = 0; i < en.length; i++) {  
  139.             buffer.append((char) en[i]);  
  140.         }  
  141.         return buffer.toString();  
  142.     }  
  143.     /** 
  144.     *  
  145.     * @param str 
  146.     * @return 
  147.     */  
  148.     public String decrypt(String str) {  
  149.         DES des = new DES("XXX.key");  
  150.         byte[] en = new byte[str.length()];  
  151.         for (int i = 0; i < str.length(); i++) {  
  152.             en[i] = (byte) str.charAt(i);  
  153.         }  
  154.   
  155.         String de = des.decryptor(en);  
  156.         return de;  
  157.     }  
  158.     /** 
  159.     *  
  160.     * @param str 
  161.     * @return 
  162.     */  
  163.     public String replaceChar(String str) {  
  164.         StringBuffer buffer = new StringBuffer();  
  165.   
  166.         int index = str.indexOf("'");  
  167.         if (index == -1) {  
  168.             return str;  
  169.         }  
  170.         while (index > -1) {  
  171.             buffer.append(str.substring(0, index));  
  172.             buffer.append("''");  
  173.             str = str.substring(index + 1);  
  174.             index = str.indexOf("'");  
  175.         }  
  176.         buffer.append(str);  
  177.         return buffer.toString();  
  178.     }  
  179.     /** 
  180.     *  
  181.     * @return 
  182.     */  
  183.     public static XXXDES getInstance(){  
  184.         if(instance == null){  
  185.             instance = new XXXDES();  
  186.         }  
  187.         return instance;  
  188.     }  
  189. }  


使用:
encryptedTextXXXDES.getInstance().encrypt("your plain text");
plainText=XXXDES.getInstance().decrypt("your encrypted text");

三.RSA加密、解密

RSA加密算法是一種非對稱加密算法。在公鑰加密標準和電子商業中RSA被廣泛使用。RSA是1977年由羅納德·李維斯特(Ron Rivest)、阿迪·薩莫爾(Adi Shamir)和倫納德·阿德曼(Leonard Adleman)一起提出的。當時他們三人都在麻省理工學院工作。RSA就是他們三人姓氏開頭字母拼在一起組成的。

RSA算法的可靠性基於分解極大的整數是很困難的。假如有人找到一種很快的分解因子的算法的話,那麼用RSA加密的信息的可靠性就肯定會極度下降。但找到這樣的算法的可能性是非常小的。今天只有短的RSA鑰匙纔可能被強力方式解破。到2008年爲止,世界上還沒有任何可靠的攻擊RSA算法的方式。只要其鑰匙的長度足夠長,用RSA加密的信息實際上是不能被解破的。

 

1. rsa基本結構

[cpp] view plaincopy
 
 
 
  1. struct      
  2.   
  3. {        
  4.   
  5.     int pad;        
  6.   
  7.     long version;        
  8.   
  9.     const rsa_method *meth;        
  10.   
  11.     engine *engine;        
  12.   
  13.     bignum *n;          
  14.   
  15.     n=p*q;        
  16.   
  17.     bignum *e;        //公開的加密指數,經常爲65537(ox10001)        
  18.   
  19.     bignum *d;        //私鑰        
  20.   
  21.     bignum *p;        //大素數p        
  22.   
  23.     bignum *q;       //大素數q        
  24.   
  25.     bignum *dmp1;     //d mod (p-1)        
  26.   
  27.     bignum *dmq1;     //d mod (q-1)        
  28.   
  29.     bignum *iqmp;     //(inverse of q) mod p        
  30.   
  31.     int references;        
  32.   
  33.     int flags;        // ...       
  34.   
  35. }rsa;  

2.初始化函數

rsa * rsa_new(void);初始化一個rsa結構

void rsa_free(rsa *rsa);釋放一個rsa結構

3.rsa私鑰產生函數

rsa *rsa_generate_key(int num, unsigned long e,void (*callback)(int,int,void *), void *cb_arg);產生一個模爲num位的密鑰對,e爲公開的加密指數,一般爲65537(ox10001),假如後兩個參數不爲null,將有些調用。在產生密鑰對之前,一般需要指定隨機數種子

4.判斷位數函數

 int rsa_size(const rsa *rsa);返回rsa模的位數,他用來判斷需要給加密值分配空間的大小 

 int rsa_check_key(rsa *rsa);他測試p,q是否爲素數,n=p*q,d*e = 1 mod (p-1*q-1), dmp1, dmq1, iqmp是否均設置正確了。

5.rsa的rsa_method函數

 瞭解rsa的運算那就必須瞭解rsa_method,下面我們先看看rsa_method結構

 

[cpp] view plaincopy
 
 
 
  1. typedef struct rsa_meth_st          
  2.   
  3. {          
  4.   
  5.     const char *name;          
  6.   
  7.     int (*rsa_pub_enc)(int flen,const unsigned char *from,            unsigned char *to,rsa *rsa,int padding);          
  8.   
  9.     int (*rsa_pub_dec)(int flen,const unsigned char *from,             unsigned char *to,rsa *rsa,int padding);          
  10.   
  11.     int (*rsa_priv_enc)(int flen,const unsigned char *from,                unsigned char *to, rsa *rsa,int padding);          
  12.   
  13.     int (*rsa_priv_dec)(int flen,const unsigned char *from,                unsigned char *to,rsa *rsa,int padding);          
  14.   
  15.     int (*rsa_mod_exp)(bignum *r0,const bignum *i,rsa *rsa);         
  16.   
  17.     int (*bn_mod_exp)(bignum *r, const bignum *a, const bignum *p,                const bignum *m, bn_ctx *ctx,bn_mont_ctx *m_ctx);          
  18.   
  19.     int (*init)(rsa *rsa);         /* called at new */  
  20.   
  21.     int (*finish)(rsa *rsa);       /* called at free */          
  22.   
  23.     int flags;             /* rsa_method_flag_* things */         char *app_data;                  /* may be needed! */          
  24.   
  25.     int (*rsa_sign)(int type,const unsigned char *m, unsigned int m_length,unsigned char *sigret, unsigned int *siglen, const rsa *rsa);          
  26.   
  27.     int (*rsa_verify)(int dtype,const unsigned char *m, unsigned int m_length,unsigned char *sigbuf, unsigned int siglen, const rsa *rsa);          
  28.   
  29. } rsa_method;  
  30. const rsa_method *rsa_pkcs1_ssleay(void);  
  31. <span style="font-family:Microsoft YaHei;font-size:16px;color:black;">const rsa_method *rsa_null_method(void);</span>  

主要有上面兩個函數。第二個函數是定義了rsa_null纔會調用,其實要調用這個函數以後幾乎什麼都不能幹,只是輸出錯誤信息。第一個是常用的method,下面我們看看它的定義

const rsa_method *rsa_pkcs1_ssleay(void)        

{        

return(&rsa_pkcs1_eay_meth);        

}

static rsa_method rsa_pkcs1_eay_meth={        "eric young's pkcs#1 rsa",         rsa_eay_public_encrypt,         rsa_eay_public_decrypt, /* signature verification */         rsa_eay_private_encrypt, /* signing */         rsa_eay_private_decrypt,         rsa_eay_mod_exp,         bn_mod_exp_mont,         rsa_eay_init,         rsa_eay_finish,         0, /* flags */         null,         0, /* rsa_sign */         0  /* rsa_verify */         };

由此可以看出,一般rsa->meth-> rsa_pub_enc對應於rsa_eay_public_encrypt,剛開始看openssl的時候最難得就是這個指向函數的指針,根本不知道rsa->meth-> rsa_pub_enc對應於哪裏。在openssl裏面這種指針很多,到以後也能夠看到。下面是設置meth的一些函數應該都很容易理解

void rsa_set_default_method(const rsa_method *meth); 

const rsa_method *rsa_get_default_method(void); 

int rsa_set_method(rsa *rsa, const rsa_method *meth); 

const rsa_method *rsa_get_method(const rsa *rsa); 

int rsa_flags(const rsa *rsa); 

rsa *rsa_new_method(engine *engine);

6.加解密函數

int rsa_public_encrypt(int flen, unsigned char *from,    unsigned char *to, rsa *rsa, int padding); 

int rsa_private_decrypt(int flen, unsigned char *from,    unsigned char *to, rsa *rsa, int padding); 

int rsa_private_encrypt(int flen, unsigned char *from,    unsigned char *to, rsa *rsa,int padding); 

int rsa_public_decrypt(int flen, unsigned char *from, unsigned char *to, rsa *rsa,int padding); 

假如rsa_set_method(rsa, rsa_pkcs1_ssleay())的話,那rsa_public_encrypt對應於rsa_eay_public_encrypt,這樣我們就可以調試公鑰加密的過程了。flen爲要加密信息的長度,from爲需要加密的信息,to爲加密後的信息,一般to至少要申請bn_num_bytes(rsa->n)大的空間。padding是採取的加解密方案。pkcs#1中主要提供了兩種加密方案,rsaex-oaep和psaes-pkcs1-v1_5(反正就是兩種加密過程了,有點複雜,它主要是先對先對需要加密的數據進行了編碼,比如rsaes-oaep採用eme-oaep編碼,再進行加密或解密)。編碼的函數:

case rsa_pkcs1_padding:    i=rsa_padding_add_pkcs1_type_2(buf,num,from,flen);

#ifndef openssl_no_sha case rsa_pkcs1_oaep_padding:       i=rsa_padding_add_pkcs1_oaep(buf,num,from,flen,null,0);

#endif case rsa_sslv23_padding:    i=rsa_padding_add_sslv23(buf,num,from,flen); 

case rsa_no_padding:    i=rsa_padding_add_none(buf,num,from,flen);等上面編好碼後,就調用bn_mod_exp_mont來進行模冪了。最後得出值,這也就是具體的加密和解密過程。在這裏還可以發現,加密時輸入的rsa有兩種方式,一是p,q,...爲null,只有rsa->d,和rsa->n不爲空,這樣就直接用rsa->d和rsa->n進行模冪計算,假如p,q.....都不爲空的話,他會調用中國剩餘定理來進行加密。

7.簽名函數

int rsa_sign(int type, unsigned char *m, unsigned int m_len,    unsigned char *sigret, unsigned int *siglen, rsa *rsa);

int rsa_verify(int type, unsigned char *m, unsigned int m_len,    unsigned char *sigbuf, unsigned int siglen, rsa *rsa);其實簽名其實和用私鑰加密差不多是一回事,所以簽名函數最終調用的就是私鑰加密的函數,在openssl中這個簽名函數很少單獨拿出來用的,都是爲了給evp_signfinal來調用的。所以假如是利用rsa進行簽名的話,rsa_private_encrypt,bn_mod_exp_mont是最基本的,所有的都需要調用他,區別無非就在於在需要簽名的信息上做了一下處理(一般將需要簽名的信息求取摘要值得到m)

8.寫入文件函數

 int rsa_print(bio *bp, rsa *x, int offset); 

 int rsa_print_fp(file *fp, rsa *x, int offset);offset是爲了調整輸出格式的,隨意一個數都可以(例如2,12,16。。)

9.其他

int rsa_blinding_on(rsa *rsa, bn_ctx *ctx);

void rsa_blinding_off(rsa *rsa);爲了防止時間攻擊,openssl還在簽名的時候產生一個隨機因子,附加在私鑰上。  

int rsa_sign_asn1_octet_string(int dummy, unsigned char *m,unsigned int m_len, unsigned char *sigret, unsigned int *siglen,rsa *rsa);  

int rsa_verify_asn1_octet_string(int dummy, unsigned char *m,unsigned int m_len, unsigned char *sigbuf, unsigned int siglen,rsa *rsa);   

代碼示例如下:

 

[cpp] view plaincopy
 
 
 
    1. using System;  
    2.   
    3. using System.Security.Cryptography;  
    4.   
    5. using System.IO;  
    6.   
    7. using System.Text;  
    8.   
    9.   
    10.   
    11. namespace Microsoft.Samples.Security.PublicKey  
    12.   
    13. {  
    14.   
    15.     class App  
    16.   
    17.     {  
    18.   
    19.         // Main entry point  
    20.   
    21.         static void Main(string[] args)  
    22.   
    23.         {  
    24.   
    25.             // Instantiate 3 People for example. See the Person class below  
    26.   
    27.             Person alice = new Person("Alice");  
    28.   
    29.             Person bob = new Person("Bob");  
    30.   
    31.             Person steve = new Person("Steve");  
    32.   
    33.   
    34.   
    35.             // Messages that will exchanged. See CipherMessage class below  
    36.   
    37.             CipherMessage aliceMessage;  
    38.   
    39.             CipherMessage bobMessage;  
    40.   
    41.             CipherMessage steveMessage;  
    42.   
    43.   
    44.   
    45.             // Example of encrypting/decrypting your own message  
    46.   
    47.             Console.WriteLine("Encrypting/Decrypting Your Own Message");  
    48.   
    49.             Console.WriteLine("-----------------------------------------");  
    50.   
    51.   
    52.   
    53.             // Alice encrypts a message using her own public key  
    54.   
    55.             aliceMessage = alice.EncryptMessage("Alice wrote this message");  
    56.   
    57.             // then using her private key can decrypt the message  
    58.   
    59.             alice.DecryptMessage(aliceMessage);  
    60.   
    61.             // Example of Exchanging Keys and Messages  
    62.   
    63.             Console.WriteLine();  
    64.   
    65.             Console.WriteLine("Exchanging Keys and Messages");  
    66.   
    67.             Console.WriteLine("-----------------------------------------");  
    68.   
    69.   
    70.   
    71.             // Alice Sends a copy of her public key to Bob and Steve  
    72.   
    73.             bob.GetPublicKey(alice);  
    74.   
    75.             steve.GetPublicKey(alice);  
    76.   
    77.   
    78.   
    79.             // Bob and Steve both encrypt messages to send to Alice  
    80.   
    81.             bobMessage = bob.EncryptMessage("Hi Alice! - Bob.");  
    82.   
    83.             steveMessage = steve.EncryptMessage("How are you? - Steve");  
    84.   
    85.   
    86.   
    87.             // Alice can decrypt and read both messages  
    88.   
    89.             alice.DecryptMessage(bobMessage);  
    90.   
    91.             alice.DecryptMessage(steveMessage);  
    92.   
    93.   
    94.   
    95.             Console.WriteLine();  
    96.   
    97.             Console.WriteLine("Private Key required to read the messages");  
    98.   
    99.             Console.WriteLine("-----------------------------------------");  
    100.   
    101.   
    102.   
    103.             // Steve cannot read the message that Bob encrypted  
    104.   
    105.             steve.DecryptMessage(bobMessage);  
    106.   
    107.             // Not even Bob can use the Message he encrypted for Alice.  
    108.   
    109.             // The RSA private key is required to decrypt the RS2 key used  
    110.   
    111.             // in the decryption.  
    112.   
    113.             bob.DecryptMessage(bobMessage);  
    114.   
    115.   
    116.   
    117.         } // method Main  
    118.   
    119.     } // class App  
    120.   
    121.   
    122.   
    123.     class CipherMessage  
    124.   
    125.     {  
    126.   
    127.         public byte[] cipherBytes; // RC2 encrypted message text  
    128.   
    129.         public byte[] rc2Key; // RSA encrypted rc2 key  
    130.   
    131.         public byte[] rc2IV; // RC2 initialization vector  
    132.   
    133.     }  
    134.   
    135.   
    136.   
    137.     class Person  
    138.   
    139.     {  
    140.   
    141.         private RSACryptoServiceProvider rsa;  
    142.   
    143.         private RC2CryptoServiceProvider rc2;  
    144.   
    145.         private string name;  
    146.   
    147.   
    148.   
    149.         // Maximum key size for the RC2 algorithm  
    150.   
    151.         const int keySize = 128;  
    152.   
    153.   
    154.   
    155.         // Person constructor  
    156.   
    157.         public Person(string p_Name)  
    158.   
    159.         {  
    160.   
    161.             rsa = new RSACryptoServiceProvider();  
    162.   
    163.             rc2 = new RC2CryptoServiceProvider();  
    164.   
    165.             rc2.KeySize = keySize;  
    166.   
    167.             name = p_Name;  
    168.   
    169.         }  
    170.   
    171.   
    172.   
    173.         // Used to send the rsa public key parameters  
    174.   
    175.         public RSAParameters SendPublicKey()  
    176.   
    177.         {  
    178.   
    179.             RSAParameters result = new RSAParameters();  
    180.   
    181.             try  
    182.   
    183.             {  
    184.   
    185.                 result = rsa.ExportParameters(false);  
    186.   
    187.             }  
    188.   
    189.             catch (CryptographicException e)  
    190.   
    191.             {  
    192.   
    193.                 Console.WriteLine(e.Message);  
    194.   
    195.             }  
    196.   
    197.             return result;  
    198.   
    199.         }  
    200.   
    201.   
    202.         // Used to import the rsa public key parameters  
    203.   
    204.         public void GetPublicKey(Person receiver)  
    205.   
    206.         {  
    207.   
    208.             try  
    209.   
    210.             {  
    211.   
    212.                 rsa.ImportParameters(receiver.SendPublicKey());  
    213.   
    214.             }  
    215.   
    216.             catch (CryptographicException e)  
    217.   
    218.             {  
    219.   
    220.                 Console.WriteLine(e.Message);  
    221.   
    222.             }  
    223.   
    224.         }  
    225.   
    226.         public CipherMessage EncryptMessage(string text)  
    227.   
    228.         {  
    229.   
    230.             // Convert string to a byte array  
    231.   
    232.             CipherMessage message = new CipherMessage();  
    233.   
    234.             byte[] plainBytes = Encoding.Unicode.GetBytes(text.ToCharArray());  
    235.   
    236.             // A new key and iv are generated for every message  
    237.   
    238.             rc2.GenerateKey();  
    239.   
    240.             rc2.GenerateIV();  
    241.   
    242.   
    243.   
    244.             // The rc2 initialization doesnt need to be encrypted, but will  
    245.   
    246.             // be used in conjunction with the key to decrypt the message.  
    247.   
    248.             message.rc2IV = rc2.IV;  
    249.   
    250.             try  
    251.   
    252.             {  
    253.   
    254.                 // Encrypt the RC2 key using RSA encryption  
    255.   
    256.                 message.rc2Key = rsa.Encrypt(rc2.Key, false);  
    257.   
    258.             }  
    259.   
    260.             catch (CryptographicException e)  
    261.   
    262.             {  
    263.   
    264.                 // The High Encryption Pack is required to run this sample  
    265.   
    266.                 // because we are using a 128-bit key. See the readme for  
    267.   
    268.                 // additional information.  
    269.   
    270.                 Console.WriteLine("Encryption Failed. Ensure that the" +  
    271.   
    272.                     " High Encryption Pack is installed.");  
    273.   
    274.                 Console.WriteLine("Error Message: " + e.Message);  
    275.   
    276.                 Environment.Exit(0);  
    277.   
    278.             }  
    279.   
    280.             // Encrypt the Text Message using RC2 (Symmetric algorithm)  
    281.   
    282.             ICryptoTransform sse = rc2.CreateEncryptor();  
    283.   
    284.             MemoryStream ms = new MemoryStream();  
    285.   
    286.             CryptoStream cs = new CryptoStream(ms, sse, CryptoStreamMode.Write);  
    287.   
    288.             try  
    289.   
    290.             {  
    291.   
    292.                 cs.Write(plainBytes, 0, plainBytes.Length);  
    293.   
    294.                 cs.FlushFinalBlock();  
    295.   
    296.                 message.cipherBytes = ms.ToArray();  
    297.   
    298.             }  
    299.   
    300.             catch (Exception e)  
    301.   
    302.             {  
    303.   
    304.                 Console.WriteLine(e.Message);  
    305.   
    306.             }  
    307.   
    308.             finally  
    309.   
    310.             {  
    311.   
    312.                 ms.Close();  
    313.   
    314.                 cs.Close();  
    315.   
    316.             }  
    317.   
    318.             return message;  
    319.   
    320.         } // method EncryptMessage  
    321.   
    322.         public void DecryptMessage(CipherMessage message)  
    323.   
    324.         {  
    325.   
    326.             // Get the RC2 Key and Initialization Vector  
    327.   
    328.             rc2.IV = message.rc2IV;  
    329.   
    330.             try  
    331.   
    332.             {  
    333.   
    334.                 // Try decrypting the rc2 key  
    335.   
    336.                 rc2.Key = rsa.Decrypt(message.rc2Key, false);  
    337.   
    338.             }  
    339.             catch (CryptographicException e)  
    340.             {  
    341.                 Console.WriteLine("Decryption Failed: " + e.Message);  
    342.   
    343.                 return;  
    344.   
    345.             }  
    346.   
    347.             ICryptoTransform ssd = rc2.CreateDecryptor();  
    348.   
    349.             // Put the encrypted message in a memorystream  
    350.   
    351.             MemoryStream ms = new MemoryStream(message.cipherBytes);  
    352.   
    353.             // the CryptoStream will read cipher text from the MemoryStream  
    354.   
    355.             CryptoStream cs = new CryptoStream(ms, ssd, CryptoStreamMode.Read);  
    356.   
    357.             byte[] initialText = new Byte[message.cipherBytes.Length];  
    358.   
    359.             try  
    360.   
    361.             {  
    362.   
    363.                 // Decrypt the message and store in byte array  
    364.   
    365.                 cs.Read(initialText, 0, initialText.Length);  
    366.   
    367.             }  
    368.   
    369.             catch (Exception e)  
    370.   
    371.             {  
    372.   
    373.                 Console.WriteLine(e.Message);  
    374.   
    375.             }  
    376.   
    377.             finally  
    378.   
    379.             {  
    380.   
    381.                 ms.Close();  
    382.   
    383.                 cs.Close();  
    384.   
    385.             }  
    386.   
    387.             // Display the message received  
    388.   
    389.             Console.WriteLine(name + " received the following message:");  
    390.   
    391.             Console.WriteLine(" " + Encoding.Unicode.GetString(initialText));  
    392.   
    393.         } // method DecryptMessage  
    394.   
    395.     } // class Person  
    396.   
    397. // namespace PublicKey   
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章