er);
}
// 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 pbPas