Share via


Nachrichtenauthentifizierung

Bei der Nachrichtenauthentifizierung handelt es sich um einen Prozess, mit dem Anwendungen und Dienstanbieter überprüfen können, ob die zwischen ihnen übergebenen Daten nicht manipuliert wurden. Windows Media Geräte-Manager ermöglicht Anwendungen und Dienstanbietern die Durchführung der Nachrichtenauthentifizierung mithilfe von Nachrichtenauthentifizierungscodes (Message Authentication Codes, MACs). So funktioniert die MAC-Authentifizierung:

Der Datensender, in der Regel der Dienstanbieter, übergibt ein oder mehrere Daten über eine unidirektionale kryptografische Funktion, die eine einzelne Signatur , den MAC, für alle Daten erzeugt. Der Absender sendet dann alle signierten Datenteile zusammen mit dem MAC an den Empfänger (in der Regel die Anwendung). Der Empfänger übergibt die Daten über dieselbe kryptografische Funktion, um einen MAC zu generieren, und vergleicht sie mit dem gesendeten MAC. Wenn der MAC übereinstimmt, wurden die Daten nicht geändert.

Für die MAC-Authentifizierung benötigt die Anwendung oder der Dienstanbieter einen Verschlüsselungsschlüssel und ein entsprechendes Zertifikat. Informationen dazu, wo Sie diese erhalten, finden Sie unter Tools for Development.

In den folgenden Schritten wird beschrieben, wie Daten vom Absender signiert und später vom Empfänger überprüft werden. In Windows Media Geräte-Manager verwendet der Dienstanbieter die CSecureChannelServer-Klasse, um MACs zu generieren, und die Anwendung verwendet die CSecureChannelClient-Klasse. Beide Klassen stellen identische Funktionen mit identischen Parametern bereit, sodass die folgenden Schritte für beide Klassen gelten.

Der Absender (in der Regel der Dienstanbieter):

  1. Rufen Sie die zu signierten Daten ab.
  2. Erstellen Sie ein neues MAC-Handle, indem Sie MACInit aufrufen.
  3. Fügen Sie eine Datenmenge hinzu, die dem Handle signiert werden soll, indem Sie MACUpdate aufrufen. Diese Funktion akzeptiert das zuvor erstellte Handle sowie ein Datenteil, das signiert werden muss.
  4. Wiederholen Sie Schritt 3 mit jedem zusätzlichen Datenabschnitt, der signiert werden muss. Es spielt keine Rolle, in welcher Reihenfolge Daten dem MAC hinzugefügt werden.
  5. Kopieren Sie den MAC aus dem Handle in einen neuen Bytepuffer, indem Sie MACFinal aufrufen. Diese Funktion akzeptiert das MAC-Handle und einen Puffer, den Sie zuweisen, und kopiert den MAC aus dem Handle in den bereitgestellten Puffer.

Beim Ausführen der MAC-Authentifizierung ist es wichtig, dass sowohl der Absender als auch der Empfänger die gleichen Daten in den MAC einfügen. Für die Anwendungsmethoden, die einen MAC bereitstellen, sind in der Regel alle Parameter im MAC-Wert enthalten (außer natürlich für den MAC selbst). Betrachten Sie beispielsweise die IWMDMOperation::TransferObjectData-Methode :

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

Bei dieser Methode enthält der MAC pData und pdwSize. Wenn Sie nicht beide Parameter einschließen, stimmt der von Ihnen erstellte MAC nicht mit dem an abMac übergebenen MAC überein. Ein Dienstanbieter muss sicherstellen, dass alle erforderlichen Parameter in der Anwendungsmethode in den MAC-Wert eingefügt werden.

Der folgende C++-Code veranschaulicht das Erstellen eines MAC in der Implementierung von IMDSPStorageGlobals::GetSerialNumber durch einen Dienstanbieter.

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;
}

Der Empfänger (in der Regel die Anwendung):

Wenn der Empfänger die IWMDMOperation3-Schnittstelle nicht implementiert hat, sollte er die gleichen Schritte wie der Absender ausführen und dann die beiden MAC-Werte vergleichen. Das folgende C++-Codebeispiel zeigt, wie eine Anwendung den mac überprüft, der in einem Aufruf von IWMDMStorageGlobals::GetSerialNumber empfangen wurde, um sicherzustellen, dass die Seriennummer während der Übertragung nicht manipuliert wurde.

//
// 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.
    }
}

Verwenden von sicher authentifizierten Kanälen