

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

# Verificação da assinatura de uma mensagem do Amazon SNS usando solicitações baseadas em consulta HTTP
<a name="sns-verify-signature-of-message-verify-message-signature"></a>

Verificação da assinatura de uma mensagem do Amazon SNS usando solicitações baseadas em consulta HTTP garante a autenticidade e integridade da mensagem. Esse processo confirma que a mensagem é originária do Amazon SNS e não foi adulterada durante o trânsito. Ao analisar a mensagem, criar a string correta para assinar e validar a assinatura em relação a uma chave pública confiável, você protege seu sistema contra falsificações e alterações não autorizadas de mensagens.

1. Extraia os **pares chave/valor** do documento JSON no corpo da solicitação HTTP POST enviada pelo Amazon SNS. Esses campos são obrigatórios para criar a **string a ser assinada**.
   + `Message`
   + `Subject` (se presente)
   + `MessageId`
   + `Timestamp`
   + `TopicArn`
   + `Type`

   Por exemplo:

   ```
   MESSAGE_FILE="message.json"
   FIELDS=("Message" "MessageId" "Subject" "Timestamp" "TopicArn" "Type")
   ```
**nota**  
Se algum campo contiver caracteres de escape (por exemplo, `\n`), converta-os para o **formato original** para garantir uma correspondência exata.

1. Localize o campo `SigningCertURL` na mensagem do Amazon SNS. Esse certificado contém a chave pública necessária para verificar a assinatura da mensagem. Por exemplo:

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

1. Certifique-se de que `SigningCertURL` seja de um AWS domínio confiável (por exemplo,https://sns.us-east-1.amazonaws.com). Rejeite qualquer ** AWS domínio URLs externo** por motivos de segurança.

1. Baixe o **certificado X.509** do URL fornecido. Por exemplo:

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

1. Extraia a **chave pública** do certificado X.509 baixado. A chave pública permite descriptografar a assinatura da mensagem e verificar sua integridade. Por exemplo:

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

1. Tipos de mensagem diferentes exigem pares de chave/valor diferentes na string a ser assinada. Identifique o **tipo de mensagem** (campo `Type` da mensagem do Amazon SNS) para determinar quais **pares de chave/valor** incluir:
   + **Mensagem de notificação**: inclui `Message`, `MessageId`, `Subject` (se presente), `Timestamp`, `TopicArn` e `Type`.
   + **SubscriptionConfirmation**ou **UnsubscribeConfirmation mensagem** — Inclui `Message``MessageId`,`SubscribeURL`, `Timestamp``Token`,`TopicArn`,, `Type` e.

1. O Amazon SNS exige que a string seja assinada para seguir uma ordem de campo fixa e rígida para verificação. **Somente os campos explicitamente obrigatórios devem ser incluídos**. Nenhum outro campo pode ser adicionado. Campos opcionais, como `Subject`, devem ser incluídos somente se estiverem presentes na mensagem e devem aparecer na posição exata definida pela ordem dos campos obrigatórios. Por exemplo:

   ```
   KeyNameOne\nValueOne\nKeyNameTwo\nValueTwo
   ```
**Importante**  
Não adicione um caractere de nova linha no final da mensagem.

1. Organize os **pares de chave/valor** em ordem de classificação por bytes (alfabética pelo nome da chave).

1. Crie a **string a ser assinada** usando o seguinte exemplo de formato:

   ```
   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
   ```

   **Exemplo de mensagem de notificação:**

   ```
   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 exemplo:**

   ```
   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. O campo `Signature` na mensagem é codificado em Base64. Você precisa **decodificá-lo** para comparar sua **forma binária bruta** com o **hash derivado**. Por exemplo:

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

1. Use o campo `SignatureVersion` para selecionar o algoritmo de hash:
   + Para `SignatureVersion` **1**, use **SHA1**(por exemplo,`-sha1`).
   + Para `SignatureVersion` **2**, use **SHA256**(por exemplo,`-sha256`).

1. Para confirmar a autenticidade da mensagem do Amazon SNS, gere um **hash** da string criada e verifique a assinatura usando a **chave pública**.

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

   Se a assinatura for válida, o resultado será `Verified OK`. Caso contrário, o resultado será `Verification Failure`.

## Exemplo de script com tratamento de erros
<a name="sns-verify-signature-of-message-example"></a>

O seguinte script de exemplo automatiza o processo de verificação:

```
#!/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)
```