共用方式為


訊息驗證

訊息驗證是一種程式,可讓應用程式和服務提供者確認它們之間傳遞的資料並未遭到竄改。 Windows Media 裝置管理員可讓應用程式和服務提供者使用訊息驗證代碼 (MAC) 來執行訊息驗證。 以下是 MAC 驗證的運作方式:

資料傳送者通常是服務提供者,透過單向密碼編譯函式傳遞一或多個資料片段,以產生所有資料的單一簽章 MAC。 然後傳送者會將所有已簽署的資料片段連同 MAC 一起傳送給接收者, (通常是應用程式) 。 接收者會透過相同的密碼編譯函式傳遞資料,以產生 MAC,並將其與已傳送的 MAC 進行比較。 如果 MAC 相符,則資料尚未修改。

若要執行 MAC 驗證,應用程式或服務提供者需要加密金鑰和相符的憑證。 如需取得這些位置的資訊,請參閱 開發工具

下列步驟說明傳送者如何簽署資料,稍後由接收者檢查。 在 Windows 媒體裝置管理員中,服務提供者會使用CSecureChannelServer類別來產生 MAC,而應用程式會使用CSecureChannelClient類別。 這兩個類別都提供相同參數的相同函式,因此下列步驟適用于這兩個類別。

傳送者通常會 (服務提供者) :

  1. 取得要簽署的資料。
  2. 呼叫 MACInit以建立新的 MAC 控制碼。
  3. 藉由呼叫 MACUpdate,新增要簽署至控制碼的資料片段。 此函式接受先前建立的控制碼,再加上必須簽署的資料片段。
  4. 重複步驟 3,每個必須簽署的額外資料片段。 這並不重要,將資料新增至 MAC 的順序並不重要。
  5. 呼叫 MACFinal,將 MAC 從控制碼複製到新的位元組緩衝區。 此函式會接受 MAC 控制碼和您配置的緩衝區,並將 MAC 從控制碼複製到提供的緩衝區。

執行 MAC 驗證時,傳送者和接收者必須同時將相同的資料放入 MAC 中。 對於提供 MAC 的應用程式方法,通常所有參數都包含在 MAC 值 (,但 MAC 本身除外,當然) 。 例如,請考慮 IWMDMOperation::TransferObjectData 方法:

HRESULT TransferObjectData(BYTE* pData, DWORD* pdwSize, BYTE[WMDM_MAC_LENGTH] abMac);

在此方法中,MAC 會包含 pDatapdwSize。 如果您不包含這兩個參數,您建立的 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.
    }
}

使用安全驗證通道