

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

# Vérification de la signature d'un message Amazon SNS lors de l'utilisation de requêtes HTTP
<a name="sns-verify-signature-of-message-verify-message-signature"></a>

La vérification de la signature d'un message Amazon SNS lors de l'utilisation de requêtes HTTP garantit l'authenticité et l'intégrité du message. Ce processus confirme que le message provient d'Amazon SNS et qu'il n'a pas été falsifié pendant le transport. En analysant le message, en créant la chaîne appropriée à signer et en validant la signature par rapport à une clé publique fiable, vous protégez votre système contre l'usurpation d'identité et les modifications non autorisées des messages.

1. Extrayez les **paires clé-valeur** du document JSON dans le corps de la requête HTTP POST envoyée par Amazon SNS. Ces champs sont obligatoires pour créer la **chaîne à signer**.
   + `Message`
   + `Subject`(si présent)
   + `MessageId`
   + `Timestamp`
   + `TopicArn`
   + `Type`

   Par exemple :

   ```
   MESSAGE_FILE="message.json"
   FIELDS=("Message" "MessageId" "Subject" "Timestamp" "TopicArn" "Type")
   ```
**Note**  
Si un champ contient des caractères échappés (par exemple,`\n`), convertissez-les dans leur **forme d'origine** pour garantir une correspondance exacte.

1. Localisez le `SigningCertURL` champ dans le message Amazon SNS. Ce certificat contient la clé publique nécessaire pour vérifier la signature du message. Par exemple :

   ```
   SIGNING_CERT_URL=$(jq -r '.SigningCertURL' "$MESSAGE_FILE")
   ```

1. Assurez-vous qu'`SigningCertURL`il provient d'un AWS domaine fiable (par exemple,https://sns.us-east-1.amazonaws.com). Rejetez tous ** AWS les domaines URLs extérieurs** pour des raisons de sécurité.

1. Téléchargez le **certificat X.509** à partir de l'URL fournie. Par exemple :

   ```
   curl -s "$SIGNING_CERT_URL" -o signing_cert.pem
   ```

1. Extrayez la **clé publique** du certificat X.509 téléchargé. La clé publique permet de déchiffrer la signature du message et de vérifier son intégrité. Par exemple :

   ```
   openssl x509 -pubkey -noout -in signing_cert.pem > public_key.pem
   ```

1. Les différents types de messages nécessitent différentes paires clé-valeur dans la chaîne à signer. Identifiez le **type de message** (`Type`champ dans le message Amazon SNS) pour déterminer les paires **clé-valeur** à inclure :
   + **Message de notification** — Comprend `Message``MessageId`, `Subject` (le cas échéant)`Timestamp`,`TopicArn`, et`Type`.
   + **SubscriptionConfirmation**ou **UnsubscribeConfirmation message** — Comprend`Message`, `MessageId``SubscribeURL`,`Timestamp`,`Token`,`TopicArn`, et`Type`.

1. Amazon SNS exige que la chaîne à signer respecte un ordre de champs strict et fixe à des fins de vérification. **Seuls les champs explicitement obligatoires doivent être inclus**. Aucun champ supplémentaire ne peut être ajouté. Les champs facultatifs, tels que`Subject`, ne doivent être inclus que s'ils sont présents dans le message et doivent apparaître dans la position exacte définie par l'ordre des champs requis. Par exemple :

   ```
   KeyNameOne\nValueOne\nKeyNameTwo\nValueTwo
   ```
**Important**  
N'ajoutez pas de caractère de nouvelle ligne à la fin de la chaîne.

1. Disposez les **paires clé-valeur** par ordre de tri des octets (ordre alphabétique du nom de la clé).

1. Construisez la **chaîne à signer** en utilisant l'exemple de format suivant :

   ```
   STRING_TO_SIGN=""
   for FIELD in "${FIELDS[@]}"; do
       VALUE=$(jq -r --arg field "$FIELD" '.[$field]' "$MESSAGE_FILE")
       STRING_TO_SIGN+="$FIELD\n$VALUE"
       # Append a newline after each field except the last one
       if [[ "$FIELD" != "Type" ]]; then
           STRING_TO_SIGN+="\n"
       fi
   done
   ```

   **Exemple de message de notification :**

   ```
   Message
   My Test Message
   MessageId
   4d4dc071-ddbf-465d-bba8-08f81c89da64
   Subject
   My subject
   Timestamp
   2019-01-31T04:37:04.321Z
   TopicArn
   arn:aws:sns:us-east-2:123456789012:s4-MySNSTopic-1G1WEFCOXTC0P
   Type
   Notification
   ```

   **SubscriptionConfirmation exemple :**

   ```
   Message
   Please confirm your subscription
   MessageId
   3d891288-136d-417f-bc05-901c108273ee
   SubscribeURL
   https://sns.us-east-2.amazonaws.com/...
   Timestamp
   2024-01-01T00:00:00.000Z
   Token
   abc123...
   TopicArn
   arn:aws:sns:us-east-2:123456789012:MyTopic
   Type
   SubscriptionConfirmation
   ```

1. Le `Signature` champ du message est codé en Base64. Vous devez le **décoder** pour comparer sa **forme binaire brute** avec le hachage **dérivé**. Par exemple :

   ```
   SIGNATURE=$(jq -r '.Signature' "$MESSAGE_FILE")
   echo "$SIGNATURE" | base64 -d > signature.bin
   ```

1. Utilisez le `SignatureVersion` champ pour sélectionner l'algorithme de hachage :
   + Pour `SignatureVersion` **1**, utilisez **SHA1**(par exemple,`-sha1`).
   + Pour `SignatureVersion` **2**, utilisez **SHA256**(par exemple,`-sha256`).

1. **Pour confirmer l'authenticité du message Amazon SNS, générez un **hachage** de la chaîne construite et vérifiez la signature à l'aide de la clé publique.**

   ```
   openssl dgst -sha256 -verify public_key.pem -signature signature.bin <<< "$STRING_TO_SIGN"
   ```

   Si la signature est valide, le résultat est`Verified OK`. Dans le cas contraire, le résultat est`Verification Failure`.

## Exemple de script avec gestion des erreurs
<a name="sns-verify-signature-of-message-example"></a>

L'exemple de script suivant automatise le processus de vérification :

```
#!/bin/bash

# Path to the local message file
MESSAGE_FILE="message.json"

# Extract the SigningCertURL and Signature from the message
SIGNING_CERT_URL=$(jq -r '.SigningCertURL' "$MESSAGE_FILE")
SIGNATURE=$(jq -r '.Signature' "$MESSAGE_FILE")

# Fetch the X.509 certificate
curl -s "$SIGNING_CERT_URL" -o signing_cert.pem

# Extract the public key from the certificate
openssl x509 -pubkey -noout -in signing_cert.pem > public_key.pem

# Define the fields to include in the string to sign
FIELDS=("Message" "MessageId" "Subject" "Timestamp" "TopicArn" "Type")

# Initialize the string to sign
STRING_TO_SIGN=""

# Iterate over the fields to construct the string to sign
for FIELD in "${FIELDS[@]}"; do
    VALUE=$(jq -r --arg field "$FIELD" '.[$field]' "$MESSAGE_FILE")
    STRING_TO_SIGN+="$FIELD\n$VALUE"
    # Append a newline after each field except the last one
    if [[ "$FIELD" != "Type" ]]; then
        STRING_TO_SIGN+="\n"
    fi
done

# Verify the signature
echo -e "$STRING_TO_SIGN" | openssl dgst -sha256 -verify public_key.pem -signature <(echo "$SIGNATURE" | base64 -d)
```