View a markdown version of this page

Verificação da assinatura de uma mensagem do Amazon SNS usando solicitações baseadas em consulta HTTP - Amazon Simple Notification Service

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

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.

  2. 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")
  3. 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.

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

    curl -s "$SIGNING_CERT_URL" -o signing_cert.pem
  5. 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
  6. 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.

    • SubscriptionConfirmationou UnsubscribeConfirmation mensagem — Inclui MessageMessageId,SubscribeURL, TimestampToken,TopicArn,, Type e.

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

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

  9. 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
  10. 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
  11. 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).

  12. 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

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)