六月婷婷综合激情-六月婷婷综合-六月婷婷在线观看-六月婷婷在线-亚洲黄色在线网站-亚洲黄色在线观看网站

明輝手游網中心:是一個免費提供流行視頻軟件教程、在線學習分享的學習平臺!

使用Visual C++創建Crypto加/解密組件

[摘要]作者: 討飯貓 簡介這篇文章將教你如何使用 Visual C++ 和 ATL 工具和 Microsoft CryptoAPI 建立一個能加/解密數據的組件。Crypto 101 本文使用Microsoft® Cryptographic Application Programmi...
作者: 討飯貓

  簡介
這篇文章將教你如何使用 Visual C++ 和 ATL 工具和 Microsoft CryptoAPI 建立一個能加/解密數據的組件。
Crypto 101
本文使用Microsoft® Cryptographic Application Programming Interface (CryptoAPI),將苦澀難懂的邏輯算法操作隱藏起來,如果想知道詳細信息請參看[url href=http://premium.microsoft.com/msdn/library/]MSDN Library[/url].如果想知道更多的密碼系統,我推薦你看看這本書 [url href=http://www.aspzone.com/books/bookRedir.asp?url=http://www.amazon.com/exec/obidos/ASIN/0471117099/aspzonecom]Bruce Schneier's Applied Cryptography: Protocols, Algorithms, and Source Code in C[/url]

建立組件
首先,用"ATL COM AppWizard”建立一個新project。在這個例子中,我將其命名為”CryptoProj”。在 server type中選擇”Dynamic Link Library (DLL)”,點按”Finish”繼續。

定義界面
在 insert 菜單中點按"New ATL Object...",選擇 “Simple Object”,然后按 Next。

在 “Names” 欄中,設 short name 為 “Crypto”,其他項照下面的填寫。

在 Attributes 欄,確定 Apartment Threading Model 被選上,Support IsupportErrorInfo 選項勾上,然后按 OK.

按右鍵點擊 Icrypto ,點”Add Method”加一個方法.

將該方法取名為”Encrypt”,在參數欄輸入"[in] BSTR bstrPlainText, [in] BSTR bstrPassword, [out, retval] VARIANT *vCipherText".

再加一個方法,取名為”Decrypt”,參數為"[in] VARIANT vCipherText, [in] BSTR bstrPassword, [out, retval] BSTR *bstrPlainText"

實現加密方法
需要包括 CryptoAPI 庫,在 Crypto.cpp 頭加一句: #include <wincrypt.h>


現在來定義我們需要的各種變量。 STDMETHODIMP CCrypto::Encrypt(BSTR bstrPlainText,
BSTR bstrPassword,
VARIANT *vCipherText)
{
BYTE *pbData;
BYTE *pbPassword;
SAFEARRAY* psa;
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
HCRYPTKEY hKey = 0;
DWORD dwCryptDataLen = 0;
DWORD dwDataLen = 0;
DWORD dwError = 0;
char buffer[200];

USES_CONVERSION;


由于許多CryptoAPI 調用要用注冊表,所以需要執行一句RevertToSelf(). RevertToSelf();


下一步,我們需要將輸入變量轉化為我們能用的格式。 dwDataLen = SysStringLen(bstrPlainText);
pbData = (BYTE*)OLE2A(bstrPlainText);
pbPassword = (BYTE*)OLE2A(bstrPassword);


然后,用CryptAcquireContext function取得省缺 Crypto provider的句柄。 // Get handle to the default provider.
if (! CryptAcquireContext(&hProv,
"aspZoneCryptoComponent\0", MS_DEF_PROV,
PROV_RSA_FULL, CRYPT_MACHINE_KEYSET))
{
if (! CryptAcquireContext(&hProv,
"aspZoneCryptoComponent\0", MS_DEF_PROV,
PROV_RSA_FULL, (CRYPT_NEWKEYSET
CRYPT_MACHINE_KEYSET)))
{
dwError = GetLastError();
sprintf(buffer, "Error %x during CryptAcquireContext",
dwError);
return Error(buffer);
}
}


我們通過創建一個 one-way-hash密碼得到session key。 // Create a hash object.
if ( ! CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) {
dwError = GetLastError();
sprintf(buffer, "Error %x during CryptCreateHash", dwError);
return Error(buffer);
}

// Hash in the password.
if ( ! CryptHashData(hHash, pbPassword, SysStringLen(bstrPassword), 0)) {
dwError = GetLastError();
sprintf(buffer, "Error %x during CryptHashData", dwError);
return Error(buffer);
}

// Derive a session key from the hash object.
if ( ! CryptDeriveKey(hProv, ENCRYPT_ALGORITHM, hHash, 0, &hKey)) {
dwError = GetLastError();
sprintf(buffer, "Error %x during CryptDeriveKey", dwError);
return Error(buffer);
}

// Destroy hash object.
CryptDestroyHash(hHash);
hHash = 0;


現在來加密我們的數據。 // Encrypt the Data.
dwCryptDataLen = dwDataLen;
if ( ! CryptEncrypt(hKey, 0, true, 0, pbData, &dwCryptDataLen, dwDataLen)) {
dwError = GetLastError();
sprintf(buffer, "Error %x during CryptEncrypt", dwError);
return Error(buffer);
}


我們將加密后的數據放入一個數組中,而不是一個string里,因為它可能會包含null。雖然 BSTR 能處理null的情況,但不能保證用戶調用環境能正確處理,所以一個數組是最好的選擇。 // Place Encrypted Data into a VARIANT SAFEARRAY of VARIANT BYTE
SAFEARRAYBOUND rgsabound[] = {dwCryptDataLen, 0};
psa = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
VARIANT* rgElems;
SafeArrayAccessData(psa, (LPVOID*)&rgElems);
for(DWORD i=0;i<dwCryptDataLen;i++){
VariantInit(&rgElems[i]);
rgElems[i].vt = VT_UI1;
rgElems[i].uiVal = pbData[i];
}
SafeArrayUnaccessData(psa);
VariantInit(vCipherText);
vCipherText->vt = (VT_ARRAY VT_VARIANT) ;
vCipherText->parray = psa;


稍微整理一下,搞定。 // Destroy session key.
if(hKey) CryptDestroyKey(hKey);

// Release provider handle.
if(hProv) CryptReleaseContext(hProv, 0);

return S_OK;


實現解密方法
首先定義變量。 STDMETHODIMP CCrypto::Decrypt(VARIANT vCipherText,
BSTR bstrPassword,
BSTR *bstrPlainText)
{
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
HCRYPTKEY hKey = 0;
SAFEARRAY* psa;
VARIANT HUGEP *pVar;
BYTE *pbData;
BYTE *pbPassword;
long lBound, uBound;
DWORD dwCryptDataLen = 0;
DWORD dwOffset = 0;
DWORD dwError = 0;
char buffer[200];

USES_CONVERSION;


同樣的原因,我們要調用RevertToSelf() RevertToSelf();


現在,當接收一個數組參數作為變量,該數組可能藏在結構中的某個地方,所以需要一個判斷嵌套。 //Get the safe array out of the Variant.
if (vCipherText.vt == (VT_VARIANT VT_BYREF))
{
if (vCipherText.pvarVal->vt == (VT_ARRAY VT_VARIANT))
SafeArrayCopy(vCipherText.pvarVal->parray, &psa);
else
{
if (vCipherText.pvarVal->vt == (VT_ARRAY VT_VARIANT VT_BYREF))
SafeArrayCopy(*(vCipherText.pvarVal->pparray), &psa);
}
}
else
{
if (vCipherText.vt == (VT_ARRAY VT_VARIANT VT_BYREF))
SafeArrayCopy(*(vCipherText.pparray), &psa);
else
{
if (vCipherText.vt == (VT_ARRAY VT_VARIANT))
SafeArrayCopy(vCipherText.parray, &psa);
else
return DISP_E_TYPEMISMATCH;
}
}


需要密文和密碼都是BYTE*類型。 //Convert the SAFEARRAY into a form we can use.
SafeArrayAccessData(psa, (void HUGEP* FAR*)&pVar);
SafeArrayGetLBound(psa, 1, &lBound);
SafeArrayGetUBound(psa, 1, &uBound);

dwOffset = 0 - lBound;
dwCryptDataLen = uBound + dwOffset + 1;

//Allocate memory
pbData = (BYTE *)malloc(dwCryptDataLen);

//Copy the array
for(DWORD i = lBound; i <= uBound; i++){ if( ! (pVar[i].vt & VT_UI1)){ //Data Elements must be VT_UI1 (Bytes). free(pbData); return DISP_E_TYPEMISMATCH; } pbData[i + dwOffset]="pVar[i].uiVal;" } //Get Password pbPassword="(BYTE*)OLE2A(bstrPassword);</PRE">


取得 Crypto Provider 的句柄。 // Get handle to the default provider.
if (! CryptAcquireContext(&hProv, "aspZoneCryptoComponent\0",
MS_DEF_PROV, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET))
{
if (! CryptAcquireContext(&hProv, "aspZoneCryptoComponent\0",
MS_DEF_PROV, PROV_RSA_FULL, (CRYPT_NEWKEYSET CRYPT_MACHINE_KEYSET)))
{
dwError = GetLastError();
sprintf(buffer, "Error %x during CryptAcquireContext", dwError);
return Error(buffer);
}
}


從 password 中得到 session key. // Create a hash object.
if ( ! CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) {
dwError = GetLastError();
sprintf(buffer, "Error %x during CryptCreateHash", dwError);
return Error(buffer);
}

// Hash in the password.
if ( ! CryptHashData(hHash, pbPassword, SysStringLen(bstrPassword), 0)) {
dwError = GetLastError();
sprintf(buffer, "Error %x during CryptHashData", dwError);
return Error(buffer);
}

// Derive a session key from the hash object.
if ( ! CryptDeriveKey(hProv, ENCRYPT_ALGORITHM, hHash, 0, &hKey)) {
dwError = GetLastError();
sprintf(buffer, "Error %x during CryptDeriveKey", dwError);
return Error(buffer);
}

// Destroy hash object.
CryptDestroyHash(hHash);
hHash = 0;


將密文解密到純文本中。 // Decrypt the Data.
if ( ! CryptDecrypt(hKey, 0, true, 0, pbData, &dwCryptDataLen)) {
dwError = GetLastError();
sprintf(buffer, "Error %x during CryptDecrypt", dwError);
return Error(buffer);
}

//Terminate the string with a null
pbData[dwCryptDataLen] = NULL;


設置返回值,大掃除,然后搞定。 //Place Decrypted data into retval
*bstrPlainText = SysAllocString(A2OLE((const char *)pbData));

// Destroy session key.
if(hKey) CryptDestroyKey(hKey);

// Release provider handle.
if(hProv) CryptReleaseContext(hProv, 0);

return S_OK;
}

原著:討飯貓
來自:chinaasp.com


主站蜘蛛池模板: 天天操天天操天天干 | 四虎影库永久在线 | 人人天天夜夜 | 欧美一区二区在线观看 | 热热影院 | 神马热 | 日韩乱码中文字幕视频 | 午夜欧美视频 | 天堂avav| 日韩一级高清 | 四虎4hu永久免费视频大全 | 中国xxxx色视频在线观看 | 亚洲va久久久噜噜噜久久天堂 | 天天热天天干 | 午夜影院免费观看 | 一级做a爰片性色毛片思念网 | 亚洲国产欧美在线人成精品一区二区 | 午夜老司机在线观看 | 性欧美xxx极品另类 性欧美xxxx性 | 四虎永久免费在线观看 | 日韩福利视频导航 | 伊人55 | 日韩亚洲欧美一区 | 中文婷婷 | 午夜污污 | 亚洲免费在线播放 | 在线波多野结衣 | 日韩三级毛片 | 日本porno动漫 | 日韩毛片免费看 | 欧美一级视频高清片 | 青草视频网 | 伊人小视频 | 一本伊人 | 日韩毛片高清在线看 | 日本成人精品 | 色图自拍偷拍 | 欧美在线不卡视频 | 手机在线毛片免费播放 | 午夜国产精品久久影院 | 欧洲性xxxx免费视频下载软件 |