訊息驗證
訊息驗證是一種程式,可讓應用程式和服務提供者確認它們之間傳遞的資料並未遭到竄改。 Windows Media 裝置管理員可讓應用程式和服務提供者使用訊息驗證代碼 (MAC) 來執行訊息驗證。 以下是 MAC 驗證的運作方式:
資料傳送者通常是服務提供者,透過單向密碼編譯函式傳遞一或多個資料片段,以產生所有資料的單一簽章 MAC。 然後傳送者會將所有已簽署的資料片段連同 MAC 一起傳送給接收者, (通常是應用程式) 。 接收者會透過相同的密碼編譯函式傳遞資料,以產生 MAC,並將其與已傳送的 MAC 進行比較。 如果 MAC 相符,則資料尚未修改。
若要執行 MAC 驗證,應用程式或服務提供者需要加密金鑰和相符的憑證。 如需取得這些位置的資訊,請參閱 開發工具。
下列步驟說明傳送者如何簽署資料,稍後由接收者檢查。 在 Windows 媒體裝置管理員中,服務提供者會使用CSecureChannelServer類別來產生 MAC,而應用程式會使用CSecureChannelClient類別。 這兩個類別都提供相同參數的相同函式,因此下列步驟適用于這兩個類別。
傳送者通常會 (服務提供者) :
- 取得要簽署的資料。
- 呼叫 MACInit以建立新的 MAC 控制碼。
- 藉由呼叫 MACUpdate,新增要簽署至控制碼的資料片段。 此函式接受先前建立的控制碼,再加上必須簽署的資料片段。
- 重複步驟 3,每個必須簽署的額外資料片段。 這並不重要,將資料新增至 MAC 的順序並不重要。
- 呼叫 MACFinal,將 MAC 從控制碼複製到新的位元組緩衝區。 此函式會接受 MAC 控制碼和您配置的緩衝區,並將 MAC 從控制碼複製到提供的緩衝區。
執行 MAC 驗證時,傳送者和接收者必須同時將相同的資料放入 MAC 中。 對於提供 MAC 的應用程式方法,通常所有參數都包含在 MAC 值 (,但 MAC 本身除外,當然) 。 例如,請考慮 IWMDMOperation::TransferObjectData 方法:
HRESULT TransferObjectData(BYTE* pData, DWORD* pdwSize, BYTE[WMDM_MAC_LENGTH] abMac);
在此方法中,MAC 會包含 pData 和 pdwSize。 如果您不包含這兩個參數,您建立的 MAC 將不會符合傳遞至 abMac的 MAC。 服務提供者必須確定將應用程式方法中的所有必要參數放入 MAC 值中。
下列 C++ 程式碼示範如何在服務提供者的 IMDSPStorageGlobals::GetSerialNumber實作中建立 MAC。
HRESULT CMyDevice::GetSerialNumber(
PWMDMID pSerialNumber,
BYTE abMac[WMDM_MAC_LENGTH])
{
HRESULT hr;
// g_pSecureChannelServer is a global CSecureChannelServer object
// created earlier.
// Standard check that the CSecureChannelServer was authenticated previously.
if ( !(g_pSecureChannelServer->fIsAuthenticated()) )
{
return WMDM_E_NOTCERTIFIED;
}
// Call a helper function to get the device serial number.
hr = UtilGetSerialNumber(m_wcsName, pSerialNumber, TRUE);
if(hr == HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED))
{
hr = WMDM_E_NOTSUPPORTED;
}
if(hr == S_OK)
{
// Create the MAC handle.
HMAC hMAC;
hr = g_pSecureChannelServer->MACInit(&hMAC);
if(FAILED(hr))
return hr;
// Add the serial number to the MAC.
g_pSecureChannelServer->MACUpdate(hMAC, (BYTE*)(pSerialNumber), sizeof(WMDMID));
if(FAILED(hr))
return hr;
// Get the created MAC value from the handle.
g_pSecureChannelServer->MACFinal(hMAC, abMac);
if(FAILED(hr))
return hr;
}
return hr;
}
接收者通常會 (應用程式) :
如果接收者尚未實作 IWMDMOperation3 介面,它應該執行與傳送者相同的步驟,然後比較兩個 MAC 值。 下列 C++ 程式碼範例示範應用程式如何檢查 呼叫 IWMDMStorageGlobals::GetSerialNumber 中所收到的 MAC,以確保序號不會遭到傳輸中竄改。
//
// Get and verify the serial number.
//
WMDMID serialNumber;
BYTE receivedMAC[WMDM_MAC_LENGTH];
hr = pIWMDMDevice->GetSerialNumber(&serialNumber, receivedMAC);
// Check the MAC to guarantee the serial number has not been tampered with.
if (hr == S_OK)
{
// Initialize a MAC handle,
// add all parameters to the MAC,
// and retrieve the calculated MAC value.
// m_pSAC is a global CSecureChannelClient object created earlier.
HMAC hMAC;
BYTE calculatedMAC[WMDM_MAC_LENGTH];
hr = m_pSAC->MACInit(&hMAC);
if(FAILED(hr))
return hr;
hr = m_pSAC->MACUpdate(hMAC, (BYTE*)(&serialNumber), sizeof(serialNumber));
if(FAILED(hr))
return hr;
hr = m_pSAC->MACFinal(hMAC, (BYTE*)calculatedMAC);
if(FAILED(hr))
return hr;
// If the two MAC values match, the MAC is authentic.
if (memcmp(calculatedMAC, receivedMAC, sizeof(calculatedMAC)) == 0)
{
// The MAC is authentic; print the serial number.
CHAR* serialNumberBuffer =
new CHAR[serialNumber.SerialNumberLength + 1];
ZeroMemory(serialNumberBuffer,
(serialNumber.SerialNumberLength + 1) * sizeof(CHAR));
memcpy(serialNumberBuffer, serialNumber.pID,
serialNumber.SerialNumberLength * sizeof(CHAR));
// TODO: Display the serial number.
delete serialNumberBuffer;
}
else
{
// TODO: Display a message indicating that the serial number MAC
// does not match.
}
}
相關主題