Configurer des notifications de modification qui incluent des données de ressources (notifications enrichies)

Microsoft Graph permet aux applications de s’abonner aux ressources qui les intéressent et de recevoir des notifications de modifications. Bien que vous puissiez vous abonner aux notifications de modification de base, les ressources telles que les messages de conversation microsoft Teams et les ressources de présence, par exemple, prennent en charge les notifications enrichies.

Les notifications enrichies incluent les données de ressources qui ont été modifiées, ce qui permet à votre application d’exécuter la logique métier sans avoir à effectuer un appel d’API distinct pour extraire la ressource modifiée. Cet article vous guide tout au long du processus de configuration des notifications enrichies dans votre application.

Ressources prises en charge

Des notifications enrichies sont disponibles pour les ressources suivantes.

Remarque

Les notifications enrichies pour les abonnements aux points de terminaison marqués d’un astérisque (*) sont uniquement disponibles sur le point de /beta terminaison.

Resource Chemins d’accès aux ressources pris en charge Limitations
événement Outlook Modifications apportées à tous les événements dans la boîte aux lettres d’un utilisateur : /users/{id}/events Nécessite $select de retourner uniquement un sous-ensemble de propriétés dans la notification enrichie. Pour plus d’informations, voir Notifications de modification pour les ressources Outlook.
message Outlook Modifications apportées à tous les messages dans la boîte aux lettres d’un utilisateur : /users/{id}/messages

Modifications apportées aux messages dans la boîte de réception d’un utilisateur : /users/{id}/mailFolders/{id}/messages
Nécessite $select de retourner uniquement un sous-ensemble de propriétés dans la notification enrichie. Pour plus d’informations, voir Notifications de modification pour les ressources Outlook.
contact personnel Outlook Modifications apportées à tous les contacts personnels dans la boîte aux lettres d’un utilisateur : /users/{id}/contacts

Modifications apportées à tous les contacts personnels dans le dossier contactFolder d’un utilisateur : /users/{id}/contactFolders/{id}/contacts
Nécessite $select de retourner uniquement un sous-ensemble de propriétés dans la notification enrichie. Pour plus d’informations, voir Notifications de modification pour les ressources Outlook.
CallRecording Teams Tous les enregistrements d’un organization :communications/onlineMeetings/getAllRecordings

Tous les enregistrements d’une réunion spécifique : communications/onlineMeetings/{onlineMeetingId}/recordings

Enregistrement d’appel qui devient disponible dans une réunion organisée par un utilisateur spécifique : users/{id}/onlineMeetings/getAllRecordings

Enregistrement d’appel qui devient disponible dans une réunion où une application Teams particulière est installée : appCatalogs/teamsApps/{id}/installedToOnlineMeetings/getAllRecordings *
Quotas maximaux d'abonnement :
  • Par application et combinaison de réunion en ligne : 1
  • Par combinaison d’application et d’utilisateur : 1
  • Par utilisateur (pour les enregistrements de suivi des abonnements dans tous les onlineMeetings organisés par l’utilisateur) : 10 abonnements.
  • Par organization : 10 000 abonnements au total.
  • Teams callTranscript Toutes les transcriptions d’un organization :communications/onlineMeetings/getAllTranscripts

    Toutes les transcriptions d’une réunion spécifique : communications/onlineMeetings/{onlineMeetingId}/transcripts

    Transcription d’appel qui devient disponible dans une réunion organisée par un utilisateur spécifique : users/{id}/onlineMeetings/getAllTranscripts

    Transcription d’appel qui devient disponible dans une réunion où une application Teams particulière est installée : appCatalogs/teamsApps/{id}/installedToOnlineMeetings/getAllTrancripts *
    Quotas maximaux d'abonnement :
  • Par application et combinaison de réunion en ligne : 1
  • Par combinaison d’application et d’utilisateur : 1
  • Par utilisateur (pour les transcriptions de suivi des abonnements dans tous les onlineMeetings organisés par l’utilisateur) : 10 abonnements.
  • Par organization : 10 000 abonnements au total.
  • Canal Teams Modifications apportées aux canaux dans toutes les équipes : /teams/getAllChannels

    Modifications apportées au canal dans une équipe spécifique : /teams/{id}/channels
    -
    Conversation Teams Modifications apportées à n’importe quelle conversation dans le locataire : /chats

    Modifications apportées à une conversation spécifique : /chats/{id}
    -
    chatmessage Teams Modifications apportées aux messages de conversation dans tous les canaux de toutes les équipes : /teams/getAllMessages

    Modifications apportées aux messages de conversation dans un canal spécifique : /teams/{id}/channels/{id}/messages

    Modifications apportées aux messages de conversation dans toutes les conversations : /chats/getAllMessages

    Modifications apportées aux messages de conversation dans une conversation spécifique : /chats/{id}/messages

    Modifications apportées aux messages de conversation dans toutes les conversations dont un utilisateur particulier fait partie : /users/{id}/chats/getAllMessages
    Ne prend pas en charge l’utilisation $select de pour retourner uniquement les propriétés sélectionnées. La notification enrichie se compose de toutes les propriétés du instance modifié.
    conversationMember Teams Modifications apportées à l’appartenance à une équipe spécifique : /teams/{id}/members



    Modifications apportées à l’appartenance à une conversation spécifique : /chats/{id}/members
    -
    Teams onlineMeeting * Modifications apportées à une réunion en ligne : /communications/onlineMeetings(joinWebUrl='{encodedJoinWebUrl}')/meetingCallEvents * Ne prend pas en charge l’utilisation $select de pour retourner uniquement les propriétés sélectionnées. La notification enrichie se compose de toutes les propriétés du instance modifié. Un abonnement autorisé par application et par réunion en ligne. Pour plus d’informations, consultez Obtenir des notifications de modification pour les mises à jour des événements d’appel de réunion Microsoft Teams.
    présenceTeams Modifications apportées à la présence d’un seul utilisateur : /communications/presences/{id}

    Modifications apportées à la présence de plusieurs utilisateurs : /communications/presences?$filter=id in ({id},{id}...)
    L’abonnement pour la présence de plusieurs utilisateurs est limité à 650 utilisateurs distincts. Ne prend pas en charge l’utilisation $select de pour retourner uniquement les propriétés sélectionnées. La notification enrichie se compose de toutes les propriétés du instance modifié. Un abonnement autorisé par application et par utilisateur délégué. Pour plus d’informations, consultez Obtenir des notifications de modification pour les mises à jour de présence dans Microsoft Teams.
    Équipe Teams Modifications apportées à n’importe quelle équipe dans le locataire : /teams

    Modifications apportées à une équipe spécifique : /teams/{id}
    -

    Données de ressources dans la charge utile de notification

    Les notifications enrichies incluent les données de ressources suivantes dans la charge utile :

    • ID et type de l’instance de ressource modifiée, renvoyée dans la propriété resourceData.
    • Toutes les valeurs de propriété de cette instance de ressource, cryptées comme spécifié dans l’abonnement, sont renvoyées dans la propriété encryptedContent.
    • Ou, selon la ressource, les propriétés spécifiques renvoyées par la propriété resourceData. Pour obtenir uniquement des propriétés spécifiques, spécifiez-les dans le cadre de l’URL deressource dans l’abonnement, à l’aide d’un paramètre de $select.

    Création d’un abonnement

    Les notifications enrichies sont configurées de la même façon que les notifications de modification de base, sauf que vous devez spécifier les propriétés suivantes :

    • includeResourceData qui doit être paramétré sur true pour demander explicitement des données de ressource.
    • encryptionCertificate qui contient uniquement la clé publique utilisée par Microsoft Graph pour chiffrer les données de ressources qu’il retourne à votre application. Pour des questions de sécurité, Microsoft Graph chiffre les données de ressources retournées dans une notification enrichie. Vous devez fournir une clé de chiffrement publique dans le cadre de la création de l’abonnement. Pour plus d’informations sur la création et la gestion des clés de chiffrement, consultez Déchiffrement des données de ressources à partir de notifications de modification.
    • encryptionCertificateId qui est votre propre identificateur pour le certificat. Utilisez cet ID pour faire correspondre dans chaque notification de modification, quel certificat utiliser pour le déchiffrement.

    Vous devez également valider les deux points de terminaison comme décrit dans Validation du point de terminaison de notification. Si vous choisissez d’utiliser la même URL pour les deux points de terminaison, vous recevez et devez répondre à deux demandes de validation.

    Exemple de demande d’abonnement

    L’exemple suivant s’abonne aux messages de canal en cours de création ou de mise à jour dans Microsoft Teams.

    POST https://graph.microsoft.com/v1.0/subscriptions
    Content-Type: application/json
    
    {
      "changeType": "created,updated",
      "notificationUrl": "https://webhook.azurewebsites.net/api/resourceNotifications",
      "resource": "/teams/{id}/channels/{id}/messages",
      "includeResourceData": true,
      "encryptionCertificate": "{base64encodedCertificate}",
      "encryptionCertificateId": "{customId}",
      "expirationDateTime": "2019-09-19T11:00:00.0000000Z",
      "clientState": "{secretClientState}"
    }
    

    Réponse de l’abonnement

    HTTP/1.1 201 Created
    Content-Type: application/json
    
    {
      "changeType": "created,updated",
      "notificationUrl": "https://webhook.azurewebsites.net/api/resourceNotifications",
      "resource": "/teams/{id}/channels/{id}/messages",
      "includeResourceData": true,
      "encryptionCertificateId": "{custom ID}",
      "expirationDateTime": "2019-09-19T11:00:00.0000000Z",
      "clientState": "{secret client state}"
    }
    

    Notifications de cycle de vie d’abonnement

    Certains événements peuvent interférer avec un flux normal de notification de modification dans un abonnement existant. Les notifications de cycle de vie d’abonnement vous informent des actions à entreprendre afin de maintenir un flux ininterrompu. Contrairement à une notification de modification de ressource qui informe une modification d’une ressource instance, une notification de cycle de vie concerne l’abonnement lui-même et son état actuel dans le cycle de vie.

    Pour plus d’informations sur la façon de recevoir des notifications de cycle de vie et d’y répondre, consultez Réduire les abonnements manquants et les notifications de modification.

    Validation de l’authenticité des notifications

    Avant d’exécuter une logique métier basée sur les données de ressources incluses dans les notifications de modification, vous devez d’abord vérifier l’authenticité de chaque notification de modification. Dans le cas contraire, un tiers peut usurper votre application avec de fausses notifications de modification et lui faire exécuter sa logique métier de manière incorrecte, ce qui peut entraîner un incident de sécurité.

    Pour les notifications de modification de base qui ne contiennent pas de données de ressources, validez-les simplement en fonction de la valeur clientState , comme décrit dans Traitement de la notification de modification. Cette validation est acceptable, car vous pouvez effectuer des appels Microsoft Graph approuvés suivants pour obtenir l’accès aux données de ressources, et par conséquent, l’impact des tentatives d’usurpation d’identité est limité.

    Pour les notifications enrichies, effectuez une validation plus approfondie avant de traiter les données.

    Dans cette section, vous explorez les concepts de validation suivants :

    Jetons de validation dans la notification de modification

    Une notification de modification avec des données de ressource contient une propriété supplémentaire, validationTokens, qui contient un tableau de jetons web JSON (JWT) générés par Microsoft Graph. Microsoft Graph génère un jeton unique pour chaque paire d’applications distinctes et de locataire pour laquelle il existe un élément dans le tableau de valeurs . Gardez à l’esprit que les notifications de modification peuvent contenir une combinaison d’éléments pour différentes applications et locataires qui se sont abonnés à l’aide de la même notificationUrl.

    Remarque

    Microsoft Graph n’envoie pas de jetons de validation pour les notifications de modification remises via Azure Event Hubs, car le service d’abonnement n’a pas besoin de valider la notificationUrl pour Event Hubs.

    Dans l’exemple suivant, la notification de modification contient deux éléments pour la même application, et pour deux clients différents ; par conséquent, la matrice validationTokens contient deux jetons qui doivent être validés.

    {
        "value": [
            {
                "subscriptionId": "76619225-ff6b-4489-96ca-4ef547e78b22",
                "tenantId": "aaaabbbb-0000-cccc-1111-dddd2222eeee",
                "changeType": "created",
                ...
            },
            {
                "subscriptionId": "5cfe2387-163c-4006-81bb-1b5e1e060afe",
                "tenantId": "bbbbcccc-1111-dddd-2222-eeee3333ffff",
                "changeType": "created",
                ...
            }
        ],
        "validationTokens": [
            "eyJ0eXAiOiJKV1QiLCJhb...",
            "cGlkYWNyIjoiMiIsImlkc..."
        ]
    }
    

    L’objet de notification de modification se trouve dans la structure du type de ressource changeNotificationCollection.

    Comment valider

    Utilisez la bibliothèque d’authentification Microsoft (MSAL) pour vous aider à gérer la validation des jetons ou une bibliothèque tierce pour une autre plateforme.

    Gardez à l’esprit les principes suivants :

    • Veillez à toujours envoyer un code d’état HTTP 202 Accepted dans le cadre de la réponse à la notification de modification.
    • Répondez avant de valider la notification de modification, même si la validation ultérieure échoue. Autrement dit, répondez immédiatement, vous recevez la notification de modification, que vous stockiez des notifications dans des files d’attente pour un traitement ultérieur ou que vous les traitez à la volée.
    • L’acceptation d’une notification de modification évite toute tentative inutile de remise des messages, empêchant également les acteurs potentiellement malveillants de savoir s’ils ont échoué ou réussi la validation. Vous pouvez toujours choisir d’ignorer une notification de modification non valide après la réception de celle-ci.

    En particulier, effectuez une validation sur chaque jeton JWT dans la collection validationTokens. En cas d’échec d’un jeton, considérez la notification de modification comme suspecte et examinez-la de manière plus approfondie.

    Procédez comme suit pour valider les jetons et les applications qui génèrent des jetons :

    1. Vérifiez que le jeton n’a pas expiré.

    2. Vérifiez que le Plateforme d'identités Microsoft émis le jeton et que le jeton n’est pas falsifié.

      • Obtenez les clés de signature à partir du point de terminaison de configuration commun : https://login.microsoftonline.com/common/.well-known/openid-configuration. Votre application peut mettre en cache cette configuration pendant un certain temps. La configuration est fréquemment mise à jour au fur et à mesure que les clés de signature font l’objet d’une rotation quotidienne.
      • Vérifiez la signature du jeton JWT à l’aide de ces clés.

      N’acceptez pas les jetons émis par une autre autorité.

    3. Vérifiez que le jeton a été émis pour votre application qui s’abonne aux notifications de modifications.

      Les étapes suivantes font partie de la logique de validation standard dans les bibliothèques de jetons JWT et peuvent être exécutées en tant qu’appel de fonction unique.

      • Validez que l’« audience » dans le jeton corresponde à votre ID d’application.
      • Si vous avez plusieurs applications recevant des notifications de modifications, vérifiez s’il existe plusieurs ID.
    4. Critique: Vérifiez que l’application ayant généré le jeton représente l’éditeur de notification de modifications Microsoft Graph.

      • Vérifiez que la azp propriété dans le jeton correspond à la valeur attendue de 0bf30f3b-4a52-48df-9a82-234910c4a086.
      • Cette case activée garantit qu’une autre application qui n’est pas Microsoft Graph n’a pas envoyé les notifications de modification.

    Exemple de jeton JWT

    L’exemple suivant montre les propriétés incluses dans le jeton JWT nécessaires à la validation.

    {
      // aud is your app's id
      "aud": "925bff9f-f6e2-4a69-b858-f71ea2b9b6d0",
      "iss": "https://login.microsoftonline.com/9f4ebab6-520d-49c0-85cc-7b25c78d4a93/v2.0",
      "iat": 1624649764,
      "nbf": 1624649764,
      "exp": 1624736464,
      "aio": "E2ZgYGjnuFglnX7mtjJzwR5lYaWvAA==",
      // azp represents the notification publisher and must always be the same value of 0bf30f3b-4a52-48df-9a82-234910c4a086
      "azp": "0bf30f3b-4a52-48df-9a82-234910c4a086",
      "azpacr": "2",
      "oid": "1e7d79fa-7893-4d50-bdde-164260d9c5ba",
      "rh": "0.AX0AtrpOnw1SwEmFzHslx41KkzsP8wtSSt9ImoIjSRDEoIZ9AAA.",
      "sub": "1e7d79fa-7893-4d50-bdde-164260d9c5ba",
      "tid": "9f4ebab6-520d-49c0-85cc-7b25c78d4a93",
      "uti": "mIB4QKCeZE6hK71XUHJ3AA",
      "ver": "2.0"
    }
    

    Exemple : vérification des jetons de validation

    // add Microsoft.IdentityModel.Protocols.OpenIdConnect and System.IdentityModel.Tokens.Jwt nuget packages to your project
    public async Task<bool> ValidateToken(string token, string tenantId, IEnumerable<string> appIds)
    {
        var configurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(
            "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration",
            new OpenIdConnectConfigurationRetriever());
        var openIdConfig = await configurationManager.GetConfigurationAsync();
        var handler = new JwtSecurityTokenHandler();
        try
        {
        handler.ValidateToken(token, new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateIssuerSigningKey = true,
            ValidateLifetime = true,
            ValidIssuer = $"https://sts.windows.net/{tenantId}/",
            ValidAudiences = appIds,
            IssuerSigningKeys = openIdConfig.SigningKeys
        }, out _);
        return true;
        }
        catch (Exception ex)
        {
        Trace.TraceError($"{ex.Message}:{ex.StackTrace}");
        return false;
        }
    }
    

    Déchiffrement des données de ressource à partir de notifications de modifications

    La propriété resourceData d’une notification de modification comprend uniquement l’ID de base et les informations de type d’une instance de ressource. La propriété encryptedData contient les données de ressources complètes, cryptées par Microsoft Graph à l’aide de la clé publique incluse dans l’abonnement. La propriété contient également des valeurs requises pour la vérification et le déchiffrement. Ce chiffrement est effectué pour renforcer la sécurité des données client accessibles via des notifications de modification. Il vous incombe de sécuriser la clé privée pour vous assurer qu’un tiers ne peut pas déchiffrer les données client, même s’il parvient à intercepter les notifications de modification d’origine.

    Dans cette section, vous allez découvrir les concepts suivants :

    Gestion des clés de chiffrement

    1. Obtenir un certificat à l’aide d’une paire de clés asymétriques.

      • Vous pouvez utiliser un certificat auto-signé, car Microsoft Graph ne vérifie pas l’émetteur du certificat et utilise la clé publique uniquement pour le chiffrement.

      • Utilisez Azure Key Vault pour créer, faire pivoter et gérer les certificats de manière sécurisée. Assurez-vous que les clés répondent aux critères suivants :

        • La clé doit être de type RSA.
        • La taille de clé doit être comprise entre 2 048 bits et 4 096 bits.
    2. Exportez le certificat au format X.509 codé en Base64 et incluez uniquement la clé publique.

    3. Lors de la création d’un abonnement :

      • Fournissez le certificat dans la propriété encryptionCertificate , à l’aide du contenu codé en Base64 dans lequel le certificat a été exporté.

      • Fournissez votre propre identificateur dans la propriété encryptionCertificateId.

        Cet identifiant vous permet de faire correspondre vos certificats aux notifications de modifications que vous recevez et de récupérer des certificats de votre magasin de certificats. Cet identifiant peut contenir jusqu’à 128 caractères.

    4. Gérez la clé privée de façon sécurisée afin que votre code de traitement de notification de modification puisse accéder à la clé privée de façon à déchiffrer les données de ressource.

    Clés de rotation

    Pour réduire le risque de compromission d’une clé privée, modifiez régulièrement vos clés asymétriques. Pour introduire une nouvelle paire de clés, procédez comme suit :

    1. Obtenir un nouveau certificat à l’aide d’une nouvelle paire de clés asymétriques. Utilisez-la pour tous les nouveaux abonnements créés.

    2. Mettez à jour les abonnements existants à l’aide de la nouvelle clé de certificat.

      • Faites en sorte que cette mise à jour fasse partie du renouvellement d’abonnement standard.
      • Vous pouvez également énumérer tous les abonnements et fournir la clé. Utilisez l’opération de correctif sur l’abonnement et mettez à jour les propriétés encryptionCertificate et encryptionCertificateId.
    3. Gardez à l’esprit les principes suivants :

      • Pendant un certain temps, l’ancien certificat peut toujours être utilisé pour le chiffrement. Votre application doit avoir accès à la fois aux certificats anciens et nouveaux afin de pouvoir déchiffrer le contenu.
      • Utilisez la propriété encryptionCertificateId dans chaque notification de modification pour identifier la clé correcte à utiliser.
      • Ignorez l’ancien certificat uniquement lorsque vous ne voyez pas de notifications de modification récentes le référençant.

    Déchiffrement des données de ressource

    Pour optimiser les performances, Microsoft Graph utilise un processus de chiffrement en deux étapes :

    • Il génère une clé symétrique à usage unique et l’utilise pour chiffrer les données de ressources.
    • Il utilise la clé asymétrique publique (que vous avez fournie lors de l’abonnement) pour chiffrer la clé symétrique et l’inclut dans chaque notification de modification de cet abonnement.

    Partez toujours du principe que la clé symétrique est différente pour chaque élément de la notification de modification.

    Pour déchiffrer des données de ressources, votre application doit effectuer les étapes inverses, à l’aide des propriétés de encryptedContent dans chaque notification de modification :

    1. Utilisez la propriété encryptionCertificateId pour identifier le certificat correct à utiliser.

    2. Initialisez un composant de chiffrement RSA avec la clé privée. Un moyen simple d’initialiser un composant RSA consiste à utiliser la méthode RSACertificateExtensions.GetRSAPrivateKey(X509Certificate2) avec un instance X509Certificate2, qui contient la clé privée décrite dans Gestion des clés de chiffrement.

    3. Déchiffrez la clé symétrique livrée dans la propriété dataKey de chaque élément de la notification de modification.

      Utilisez OAEP (Optimal Asymmetric Encryption Padding) pour l’algorithme de déchiffrement.

    4. Utilisez la clé symétrique pour calculer la signature HMAC-SHA256 de la valeur des données.

      Comparez-le à la valeur de dataSignature. Si elles ne correspondent pas, supposons que la charge utile est falsifiée et ne la déchiffrez pas.

    5. Utilisez la clé symétrique avec un AES (Advanced Encryption Standard) (tel que .NET Aes) pour déchiffrer le contenu dans les données.

      • Utilisez les paramètres de déchiffrement suivants pour l’algorithme AES :

        • Remplissage : PKCS7
        • Mode de chiffrement : CBC
      • Configurez le « vecteur d’initialisation » en copiant les 16 premiers octets de la clé symétrique utilisée pour le déchiffrement.

    6. La valeur déchiffrée est une chaîne JSON qui représente l’instance de ressource dans la notification de modification.

    Exemple : déchiffrement d’une notification avec des données de ressource chiffrées

    L’exemple JSON suivant montre une notification de modification qui inclut des valeurs de propriété chiffrées d’un instance chatMessage dans un message de canal. La @odata.id valeur spécifie le instance.

    {
      "value": [
        {
          "subscriptionId": "76222963-cc7b-42d2-882d-8aaa69cb2ba3",
          "changeType": "created",
          // Other properties typical in a resource change notification
          "resource": "teams('d29828b8-c04d-4e2a-b2f6-07da6982f0f0')/channels('19:f127a8c55ad949d1a238464d22f0f99e@thread.skype')/messages('1565045424600')/replies('1565047490246')",
          "resourceData": {
            "id": "1565293727947",
            "@odata.type": "#Microsoft.Graph.ChatMessage",
            "@odata.id": "teams('88cbc8fc-164b-44f0-b6a6-b59b4a1559d3')/channels('19:8d9da062ec7647d4bb1976126e788b47@thread.tacv2')/messages('1565293727947')/replies('1565293727947')"
          },
          "encryptedContent": {
            "data": "{encrypted data that produces a full resource}",
            "dataSignature": "<HMAC-SHA256 hash>",
            "dataKey": "{encrypted symmetric key from Microsoft Graph}",
            "encryptionCertificateId": "MySelfSignedCert/DDC9651A-D7BC-4D74-86BC-A8923584B0AB",
            "encryptionCertificateThumbprint": "07293748CC064953A3052FB978C735FB89E61C3D"
          }
        }
      ],
      "validationTokens": [
        "eyJ0eXAiOiJKV1QiLCJhbGciOiJSU..."
      ]
    }
    

    Pour obtenir une description complète des données envoyées lors de la remise des notifications de modification, consultez type de ressource changeNotificationCollection.

    Déchiffrer la clé symétrique

    Cette section contient des extraits de code utiles qui utilisent C# et .net pour chaque étape du déchiffrement.

    // Initialize with the private key that matches the encryptionCertificateId.
    X509Certificate2 certificate = <instance of X509Certificate2 matching the encryptionCertificateId property>;
    RSA rsa = certificate.GetRSAPrivateKey();
    byte[] encryptedSymmetricKey = Convert.FromBase64String(<value from dataKey property>);
    
    // Decrypt using OAEP padding.
    byte[] decryptedSymmetricKey = rsa.Decrypt(encryptedSymmetricKey, fOAEP: true);
    
    // Can now use decryptedSymmetricKey with the AES algorithm.
    

    Comparer les signatures de données à l’aide de HMAC-SHA256

    byte[] decryptedSymmetricKey = <the aes key decrypted in the previous step>;
    byte[] encryptedPayload = <the value from the data property, still encrypted>;
    byte[] expectedSignature = <the value from the dataSignature property>;
    byte[] actualSignature;
    
    using (HMACSHA256 hmac = new HMACSHA256(decryptedSymmetricKey))
    {
        actualSignature = hmac.ComputeHash(encryptedPayload);
    }
    if (actualSignature.SequenceEqual(expectedSignature))
    {
        // Continue with decryption of the encryptedPayload.
    }
    else
    {
        // Do not attempt to decrypt encryptedPayload. Assume notification payload has been tampered with and investigate.
    }
    

    Déchiffrer le contenu des données de la ressource

    Aes aesProvider = Aes.Create();
    aesProvider.Key = decryptedSymmetricKey;
    aesProvider.Padding = PaddingMode.PKCS7;
    aesProvider.Mode = CipherMode.CBC;
    
    // Obtain the initialization vector from the symmetric key itself.
    int vectorSize = 16;
    byte[] iv = new byte[vectorSize];
    Array.Copy(decryptedSymmetricKey, iv, vectorSize);
    aesProvider.IV = iv;
    
    byte[] encryptedPayload = Convert.FromBase64String(<value from data property>);
    
    string decryptedResourceData;
    // Decrypt the resource data content.
    using (var decryptor = aesProvider.CreateDecryptor())
    {
      using (MemoryStream msDecrypt = new MemoryStream(encryptedPayload))
      {
          using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
          {
              using (StreamReader srDecrypt = new StreamReader(csDecrypt))
              {
                  decryptedResourceData = srDecrypt.ReadToEnd();
              }
          }
      }
    }
    
    // decryptedResourceData now contains a JSON string that represents the resource.