加密和解密
Windows Media 裝置管理員需要加密服務提供者與應用程式之間傳送的檔案。 完成此步驟的方式有兩種:
- 如果服務提供者僅支援 IMDSPObject::Read 和 IMDSPObject::Write,則應用程式與服務提供者必須分別使用 CSecureChannelClient 和 CSecureChannelServer 方法來加密和解密資料。
- 如果服務提供者支援 IMDSPObject2::ReadOnClearChannel 和 IMDSPObject2::WriteOnClearChannel,您的應用程式可以避免成本高昂的安全通道訊息驗證。 (會保留安全通道,讓未實作 IMDSPObject2 的舊版服務提供者仍可繼續運作。)
加密需求可防止惡意應用程式取得在軟體元件之間傳遞的資料,同時保護傳送至裝置或從裝置傳送資料的完整性。
下列三種方法需要加密或解密。
方法 | 描述 |
---|---|
IWMDMOperation::TransferObjectData | (應用程式) 加密或解密,視應用程式傳送或接收資料而定。 |
IMDSPObject::Read | (服務提供者) 加密。 |
IMDSPObject::Write | (服務提供者) 解密。 |
加密和解密都是透過單一方法呼叫來完成。 加密是由應用程式的 CSecureChannelClient::EncryptParam 或服務提供者 的 CSecureChannelServer::EncryptParam 來完成。 解密是由 適用于應用程式的 CSecureChannelClient::D ecryptParam 或服務提供者 的 CSecureChannelServer::D ecryptParam 來完成。 這些參數在用戶端和伺服器方法之間完全相同。
下列步驟示範如何加密和解密資料。 (只有在您的應用程式與未實作 IWMDMOperation3::TransferObjectDataOnClearChannel.) 的舊版服務提供者通訊時,這些步驟才重要
加密
- 建立加密資料的 MAC 金鑰,如 訊息驗證中所述。
- 使用要加密的資料呼叫 EncryptParam ,以執行就地加密。
下列程式碼範例示範服務提供者的 IMDSPObject::Read實作。 這個方法會使用資料來加密和資料大小來建立 MAC 金鑰,並將這兩者傳送至應用程式。
HRESULT CMyStorage::Read(
BYTE *pData,
DWORD *pdwSize,
BYTE abMac[WMDM_MAC_LENGTH])
{
HRESULT hr;
DWORD dwToRead; // Bytes to read.
DWORD dwRead = NULL; // Bytes read.
BYTE *pTmpData = NULL; // Temporary buffer to hold data before
// it is copied to pData.
// Use a global CSecureChannelServer member to verify that
// the client is authenticated.
if (!(g_pAppSCServer->fIsAuthenticated()))
{
return WMDM_E_NOTCERTIFIED;
}
// Verify that the handle to the file to read is valid.
if(m_hFile == INVALID_HANDLE_VALUE)
{
return E_FAIL;
}
// Create a buffer to hold the data read.
dwToRead = *pdwSize;
pTmpData = new BYTE [dwToRead] ;
if(!pTmpData)
return E_OUTOFMEMORY;
// Read data into the temporary buffer.
if(ReadFile(m_hFile,(LPVOID)pTmpData,dwToRead,&dwRead,NULL))
{
*pdwSize = dwRead;
if( dwRead )
{
// Create a MAC from all the parameters.
// CORg is a macro that goes to Error label on failure.
// MAC consists of data and size of data.
HMAC hMAC;
CORg(g_pAppSCServer->MACInit(&hMAC));
CORg(g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(pTmpData), dwRead));
CORg(g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(pdwSize), sizeof(DWORD)));
CORg(g_pAppSCServer->MACFinal(hMAC, abMac));
// Encrypt the data.
CORg(g_pAppSCServer->EncryptParam(pTmpData, dwRead));
// Copy data from the temporary buffer into the out parameter.
memcpy(pData, pTmpData, dwRead);
}
hr = S_OK;
}
else
{
*pdwSize = 0;
hr = E_FAIL;
}
Error:
if(pTmpData)
{
delete [] pTmpData;
}
return hr;
}
解密
- 使用要加密的資料呼叫 DecryptParam ,以執行就地解密。
- 驗證解密資料的 MAC 金鑰,如 訊息驗證中所述。
下列程式碼範例示範服務提供者的 IMDSPObject::Write實作。 這個方法會使用資料來加密和資料大小來建立 MAC 金鑰,並將這兩者傳送至應用程式。
HRESULT CMyStorage::Write(BYTE *pData, DWORD *pdwSize,
BYTE abMac[WMDM_MAC_LENGTH])
{
HRESULT hr;
DWORD dwWritten = 0;
BYTE *pTmpData = NULL; // Temporary buffer to hold the
// data during decryption.
BYTE pTempMac[WMDM_MAC_LENGTH]; // Temporary MAC that will be
// copied into the abMac
// out parameter.
if( m_hFile == INVALID_HANDLE_VALUE )
{
return E_FAIL;
}
// Allocate the temporary buffer and copy the encrypted data into it.
pTmpData = new BYTE [*pdwSize];
if(!pTmpData)
return E_OUTOFMEMORY;
memcpy(pTmpData, pData, *pdwSize);
// Decrypt the data.
CHRg(g_pAppSCServer->DecryptParam(pTmpData, *pdwSize));
// Check the MAC passed to the method. The MAC is built from
// the data and data size parameters.
// CORg is a macro that goes to the Error label on failure.
HMAC hMAC;
CORg(g_pAppSCServer->MACInit(&hMAC));
CORg(g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(pTmpData), *pdwSize));
CORg(g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(pdwSize), sizeof(*pdwSize)));
CORg(g_pAppSCServer->MACFinal(hMAC, pTempMac));
// If the MAC values don't match, return an error.
if (memcmp(abMac, pTempMac, WMDM_MAC_LENGTH) != 0)
{
hr = WMDM_E_MAC_CHECK_FAILED;
goto Error;
}
// The MAC values matched, so write the decrypted data to a local file.
if( WriteFile(m_hFile,pTmpData,*pdwSize,&dwWritten,NULL) )
{
hr = S_OK;
}
else
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
*pdwSize = dwWritten;
Error:
if( pTmpData )
{
delete [] pTmpData;
}
return hr;
}
相關主題