View a markdown version of this page

Verificación de la firma de un mensaje de Amazon SNS cuando se utilizan solicitudes basadas en consultas HTTP - Amazon Simple Notification Service

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

Verificación de la firma de un mensaje de Amazon SNS cuando se utilizan solicitudes basadas en consultas HTTP

Al verificar la firma de un mensaje de Amazon SNS cuando se utilizan solicitudes basadas en consultas HTTP se garantiza la autenticidad y la integridad del mensaje. Este proceso confirma que el mensaje proviene de Amazon SNS y no se ha manipulado durante el tránsito. Al analizar el mensaje, construir la cadena correcta para firmarlo y validar la firma con una clave pública de confianza, se protege el sistema contra la suplantación de identidad y las alteraciones no autorizadas de los mensajes.

  1. Extraiga los pares de clave-valor del documento JSON en el cuerpo de la solicitud HTTP POST que envía Amazon SNS. Estos campos son necesarios para construir la cadena que se va a firmar.

    • Message

    • Subject (si está presente)

    • MessageId

    • Timestamp

    • TopicArn

    • Type

    Por ejemplo:

    MESSAGE_FILE="message.json" FIELDS=("Message" "MessageId" "Subject" "Timestamp" "TopicArn" "Type")
    nota

    Si algún campo contiene caracteres de escape (por ejemplo,\n), conviértalos a su formato original para garantizar una coincidencia exacta.

  2. Localice el campo SigningCertURL en el mensaje de Amazon SNS. Este certificado contiene la clave pública necesaria para verificar la firma del mensaje. Por ejemplo:

    SIGNING_CERT_URL=$(jq -r '.SigningCertURL' "$MESSAGE_FILE")
  3. Asegúrese de que SigningCertURL sea de un AWS dominio de confianza (por ejemplo,https://sns.us-east-1.amazonaws.com). Rechaza cualquier AWS dominio URLs externo por motivos de seguridad.

  4. Descargue el certificado X.509 desde la URL proporcionada. Por ejemplo:

    curl -s "$SIGNING_CERT_URL" -o signing_cert.pem
  5. Extraiga la clave pública del certificado X.509 descargado. La clave pública le permite descifrar la firma del mensaje y comprobar su integridad. Por ejemplo:

    openssl x509 -pubkey -noout -in signing_cert.pem > public_key.pem
  6. Los diferentes tipos de mensajes requieren diferentes pares de clave-valor en la cadena para firmarlos. Identifique el tipo de mensaje (campo Type en el mensaje de Amazon SNS) para determinar qué pares de clave-valor incluir:

    • Mensaje de notificación: incluye Message, MessageId, Subject (si está presente), Timestamp, TopicArn y Type.

    • SubscriptionConfirmationo UnsubscribeConfirmation mensaje: incluye MessageMessageId,SubscribeURL, TimestampToken,TopicArn, yType.

  7. Amazon SNS requiere que la cadena se firme para seguir un orden de campos estricto y fijo para la verificación. Solo se deben incluir los campos explícitamente obligatorios; no se pueden añadir campos adicionales. Los campos opcionales, como Subject, deben incluirse solo si están presentes en el mensaje y deben aparecer en la posición exacta definida por el orden de los campos obligatorios. Por ejemplo:

    KeyNameOne\nValueOne\nKeyNameTwo\nValueTwo
    importante

    No agregue un carácter de nueva línea al final de la cadena.

  8. Organice los pares de clave-valor en orden de clasificación de bytes (alfabéticamente por nombre de clave).

  9. Construya la cadena para firmarla con el siguiente ejemplo 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

    Ejemplo de mensaje de notificación:

    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 ejemplo:

    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. El campo Signature del mensaje está codificado en Base64. Debe descodificarlo para comparar su formato binario sin procesar con el hash derivado. Por ejemplo:

    SIGNATURE=$(jq -r '.Signature' "$MESSAGE_FILE") echo "$SIGNATURE" | base64 -d > signature.bin
  11. Use el campo SignatureVersion para seleccionar el algoritmo de hash:

    • Para SignatureVersion 1, utilice SHA1(por ejemplo,-sha1).

    • Para SignatureVersion 2, utilice SHA256(por ejemplo,-sha256).

  12. Para confirmar la autenticidad del mensaje de Amazon SNS, genere un hash de la cadena construida y verifique la firma con la clave pública.

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

    Si la firma es válida, el resultado es Verified OK. En cualquier otro caso, el resultado esVerification Failure.

Script de ejemplo con gestión de errores

El siguiente script de ejemplo automatiza el proceso de verificación:

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