Firma de mensajes

Puede utilizar firmas con la SMS API al enviar y recibir mensajes SMS. Al enviar, generas una firma para enviarla con tu mensaje. Al recibir, el webhook entrante incluirá la firma y todos los campos que necesites para generar la firma en tu aplicación y verificar que las dos firmas coinciden.

Utilizas una firma para:

  • Verificar que una solicitud procede de una fuente de confianza
  • Asegurarse de que el mensaje no ha sido manipulado durante el trayecto.
  • Protegerse contra la interceptación y la reproducción posterior

Índice

Este documento explica cómo utilizar las firmas con los mensajes, tanto para firmar los mensajes que envías como para verificar que los mensajes entrantes tienen una firma correcta.

Utilizar firmas al enviar mensajes

Para enviar un mensaje con una firma, deberá utilizar la función SIGNATURE_SECRET en lugar de tu API_SECRET al enviar el mensaje. Puede encontrar el secreto de firma y elegir qué algoritmo de firma utilizar visitando la página cuadro de mando. El algoritmo por defecto es'Hash MD5' y también apoyamos MD5 HMAC, SHA1 HMAC, SHA-256 HMAC y SHA-512 HMAC.

Vonage te recomienda encarecidamente que utilices uno de nuestros bibliotecas de clientes para generar o validar firmas. Si tú no puedo hacer esto por alguna razón, usted puede puedes generar y validar las firmas tú mismo, pero esto puede resultar complicado y dar lugar a errores. Consulta la sección sobre la generación manual de firmas.

El proceso para enviar un mensaje firmado es el siguiente:

  1. Crear un archivo firmado solicitud para enviar un SMS.
  2. Compruebe el códigos de respuesta y asegúrate de que has enviado la solicitud correctamente.
  3. Su mensaje se entrega al terminal. El terminal del usuario devuelve un acuse de recibo.
  4. (opcional) Si has solicitado acuses de recibo firmados y mensajes entrantes, te interesará validar la firma de cada solicitud que recibas.

Si no has generado la firma correctamente, el estado es 14, invalid signature. Encontrará más información en solución de problemas apartado de esta guía.

Por defecto, las firmas de mensajes son opcionales cuando se envían mensajes y no se incluyen con los webhooks entrantes. Para activar los webhooks firmados o hacer que todos los mensajes enviados estén firmados, póngase en contacto con soporte.

El ejemplo de código que aparece a continuación muestra cómo enviar un mensaje firmado mediante la SMS API.

Requisitos previos

npm install @vonage/server-sdk

Crea un archivo llamado send-signed-sms.js y añade el siguiente código:

const { Vonage } = require('@vonage/server-sdk');

const vonage = new Vonage({
  apiKey: VONAGE_API_KEY,
  apiSecret: VONAGE_API_SECRET,
  // By passing in the signature, the SDK will sign the request for you
  // Isn't that neat?!
  signature: {
    secret: SMS_SIGNATURE,
    algorithm: 'md5hash',
  },
});

Ver fuente completa

Escriba el código

Añada lo siguiente a send-signed-sms.js:

const sendMessage = async () => {
  try {
    const result = await vonage.sms.send({
      from: SMS_SENDER_ID,
      to: SMS_TO_NUMBER,
      text: 'A text message sent using the Vonage SMS API',
    });

    console.log('Message sent successfully.');
    console.log(result);
  } catch (error) {
    console.error(`Message failed with error: ${error.message}`);
  }
};

sendMessage();

Ver fuente completa

Ejecute su código

Guarde este archivo en su máquina y ejecútelo:

node send-signed-sms.js

Requisitos previos

Añada lo siguiente a build.gradle:

implementation 'com.vonage:server-sdk-kotlin:2.1.1'

Crea un archivo llamado SendSignedSms y añade el siguiente código al método main:

fun main() {
    val client = Vonage {
        apiKey(VONAGE_API_KEY)
        signatureSecret(VONAGE_SIGNATURE_SECRET)
        hashType(HashType.HMAC_SHA256)

Ver fuente completa

Escriba el código

Añada lo siguiente al método main del archivo SendSignedSms:


val response = client.sms.sendText(
    from = SMS_SENDER_ID,
    to = SMS_TO_NUMBER,
    message = "Hello from Vonage SMS API"
)

if (response.wasSuccessfullySent()) {
    println("Message sent successfully.")
}
else {
    println("Message failed with error: ${response[0].errorText}")

Ver fuente completa

Ejecute su código

Podemos utilizar el plugin aplicación para Gradle para simplificar la ejecución de nuestra aplicación. Actualiza tu build.gradle con lo siguiente:

apply plugin: 'application'
mainClassName = project.hasProperty('main') ? project.getProperty('main') : ''

Ejecute el siguiente comando gradle para ejecutar su aplicación, sustituyendo com.vonage.quickstart.kt.sms por el paquete que contiene SendSignedSms:

gradle run -Pmain=com.vonage.quickstart.kt.sms.SendSignedSms

Requisitos previos

Añada lo siguiente a build.gradle:

implementation 'com.vonage:server-sdk:9.3.1'

Crea un archivo llamado SendSignedSms y añade el siguiente código al método main:

import com.vonage.client.VonageClient;
import com.vonage.client.auth.hashutils.HashType;
import com.vonage.client.sms.MessageStatus;
import com.vonage.client.sms.SmsSubmissionResponse;
import com.vonage.client.sms.messages.TextMessage;

Ver fuente completa

Añada lo siguiente al método main del archivo SendSignedSms:

);

SmsSubmissionResponse response = client.getSmsClient().submitMessage(message);

Ver fuente completa

Escriba el código

Añada lo siguiente al método main del archivo SendSignedSms:

            System.out.println("Message sent successfully.");
        } else {
            System.out.println("Message failed with error: " + response.getMessages().get(0).getErrorText());
        }
    }
}

Ver fuente completa

Ejecute su código

Podemos utilizar el plugin aplicación para Gradle para simplificar la ejecución de nuestra aplicación. Actualiza tu build.gradle con lo siguiente:

apply plugin: 'application'
mainClassName = project.hasProperty('main') ? project.getProperty('main') : ''

Ejecute el siguiente comando gradle para ejecutar su aplicación, sustituyendo com.vonage.quickstart.sms por el paquete que contiene SendSignedSms:

gradle run -Pmain=com.vonage.quickstart.sms.SendSignedSms

Requisitos previos

Install-Package Vonage

Crea un archivo llamado SendSignedSms.cs y añade el siguiente código:


var credentials = Credentials.FromApiKeySignatureSecretAndMethod(
    vonageApiKey,
    vonageApiSignatureSecret,
    Vonage.Cryptography.SmsSignatureGenerator.Method.md5hash
    );

Ver fuente completa

Escriba el código

Añada lo siguiente a SendSignedSms.cs:

var credentials = Credentials.FromApiKeySignatureSecretAndMethod(
    vonageApiKey,
    vonageApiSignatureSecret,
    Vonage.Cryptography.SmsSignatureGenerator.Method.md5hash
    );

var vonageClient = new VonageClient(credentials);

var response = await vonageClient.SmsClient.SendAnSmsAsync(new Vonage.Messaging.SendSmsRequest()
{
    To = SMS_TO_NUMBER,
    From = SMS_SENDER_ID,
    Text = "This is a Signed SMS"
});

Ver fuente completa

Requisitos previos

composer require vonage/client

Escriba el código

Añada lo siguiente a send-signed-sms.php:

$signed = new \Vonage\Client\Credentials\SignatureSecret(
    VONAGE_API_KEY,
    VONAGE_API_SIGNATURE_SECRET,
    'md5hash'
);
$client = new \Vonage\Client($signed);

$response = $client->sms()->send(
    new \Vonage\SMS\Message\SMS(TO_NUMBER, FROM_NUMBER, 'Super interesting message')
);

echo "Message status: " . $response->current()->getStatus() . "\n";

Ver fuente completa

Ejecute su código

Guarde este archivo en su máquina y ejecútelo:

php send-signed-sms.php

Requisitos previos

pip install vonage python-dotenv

Escriba el código

Añada lo siguiente a send-signed-sms.py:

from vonage import Auth, Vonage
from vonage_sms import SmsMessage, SmsResponse

client = Vonage(Auth(api_key=VONAGE_API_KEY, signature_secret=SMS_SIGNATURE))

message = SmsMessage(
    to=SMS_TO_NUMBER,
    from_=SMS_SENDER_ID,
    text="A text message sent using the Vonage SMS API.",
)

response: SmsResponse = client.sms.send(message)
print(response)

Ver fuente completa

Ejecute su código

Guarde este archivo en su máquina y ejecútelo:

python sms/send-signed-sms.py

Validar la firma de los mensajes entrantes

Para verificar el origen de los webhooks entrantes en tu punto final de SMS, puedes activar la firma de mensajes para los mensajes entrantes; ponte en contacto con soporte para solicitar que los mensajes entrantes vayan acompañados de una firma. Con esta configuración activada, los webhooks tanto para los SMS entrantes como para los recibos de entrega incluirán una sig parámetro. Utiliza los demás parámetros de la solicitud con tu secreto de firma para generar la firma y compararla con la firma enviada. Si ambas coinciden, la solicitud es válida.

Póngase en contacto con soporte para activar la firma de mensajes en su Account.

El ejemplo de código que aparece a continuación muestra cómo verificar la firma de un mensaje SMS recibido, utilizando el sig parámetro en la cadena de consulta.

Requisitos previos

npm install express @vonage/server-sdk

Escriba el código

Añada lo siguiente a verify-signed-sms.js:

const { Vonage } = require('@vonage/server-sdk');

const app = require('express')();
const bodyParser = require('body-parser');

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
  extended: true,
}));

app
  .route('/webhooks/inbound-sms')
  .get(handleInboundSms)
  .post(handleInboundSms);

const  handleInboundSms = (request, response) => {
  const params = Object.assign(request.query, request.body);
  const { sig } = params;

  if (Vonage.sms.verifySignature(
    sig,
    params,
    VONAGE_SIGNATURE_SECRET,
    'md5hash', // one of md5hash, md5, sha1, sha256, or sha512
  )) {
    console.log('Valid signature');
  } else {
    console.log('Invalid signature');
  }

  response.status(204).send();
};

app.listen(process.env.PORT || 3000);

Ver fuente completa

Ejecute su código

Guarde este archivo en su máquina y ejecútelo:

node verify-signed-sms.js

Requisitos previos

Añada lo siguiente a build.gradle:

implementation 'com.vonage:server-sdk:9.3.1'

Crea un archivo llamado ReceiveSignedSms y añade el siguiente código al método main:

import com.vonage.client.auth.RequestSigning;
import spark.Route;
import spark.Spark;

Ver fuente completa

Escriba el código

Añada lo siguiente al método main del archivo ReceiveSignedSms:

     * Route to handle incoming SMS GET request.
     */
    Route inboundSmsAsGet = (req, res) -> {
        String signatureSecret = VONAGE_SIGNATURE_SECRET;
        System.out.println(signatureSecret);
        if (RequestSigning.verifyRequestSignature(
                req.raw().getInputStream(),
                req.contentType(),
                req.queryMap().toMap(),
                signatureSecret
        )) {
            System.out.println("msisdn: " + req.queryParams("msisdn"));
            System.out.println("messageId: " + req.queryParams("messageId"));
            System.out.println("text: " + req.queryParams("text"));
            System.out.println("type: " + req.queryParams("type"));
            System.out.println("keyword: " + req.queryParams("keyword"));
            System.out.println("messageTimestamp: " + req.queryParams("message-timestamp"));

            res.status(204);    
        }
        else {
            System.out.println("Bad signature");
            res.status(401);
        }
        
        return "";
    };        

    Spark.port(5000);
    Spark.get("/webhooks/inbound-sms", inboundSmsAsGet);        
}

Ver fuente completa

Ejecute su código

Podemos utilizar el plugin aplicación para Gradle para simplificar la ejecución de nuestra aplicación. Actualiza tu build.gradle con lo siguiente:

apply plugin: 'application'
mainClassName = project.hasProperty('main') ? project.getProperty('main') : ''

Ejecute el siguiente comando gradle para ejecutar su aplicación, sustituyendo com.vonage.quickstart.sms por el paquete que contiene ReceiveSignedSms:

gradle run -Pmain=com.vonage.quickstart.sms.ReceiveSignedSms

Requisitos previos

Install-Package Vonage

Crea un archivo llamado SmsController.cs y añade el siguiente código:

{
    [HttpGet("webhooks/inbound-sms")]        

Ver fuente completa

Escriba el código

Añada lo siguiente a SmsController.cs:

        public IActionResult VerifySms()
        {
            var vonageApiSignatureSecret = Environment.GetEnvironmentVariable("VONAGE_API_SIGNATURE_SECRET") ?? "VONAGE_API_SIGNATURE_SECRET";
            var sms = WebhookParser.ParseQuery<InboundSms>(Request.Query);
            if (sms.ValidateSignature(vonageApiSignatureSecret, Vonage.Cryptography.SmsSignatureGenerator.Method.md5hash))
            {
                Console.WriteLine("Signature is valid");
            }
            else
            {
                Console.WriteLine("Signature not valid");
            }
            return NoContent();
        }
    }
}

Ver fuente completa

Requisitos previos

composer require vonage/client

Escriba el código

Añada lo siguiente a verify-signed-sms.php:

$inbound = \Vonage\Message\InboundMessage::createFromGlobals();

if ($inbound->isValid()) {
    $params = $inbound->getRequestData();
    $signature = new Vonage\Client\Signature(
        $params,
        VONAGE_API_SIGNATURE_SECRET,
        'md5hash'
    );
    $validSig = $signature->check($params['sig']);

    if($validSig) {
        error_log("Valid signature");
    } else {
        error_log("Invalid signature");
    }

} else {
    error_log('Invalid message');
}

Ver fuente completa

Ejecute su código

Guarde este archivo en su máquina y ejecútelo:

php verify-signed-sms.php

Requisitos previos

pip install vonage python-dotenv fastapi[standard]

Escriba el código

Añada lo siguiente a main.py:

import os
from os.path import dirname, join

from dotenv import load_dotenv

envpath = join(dirname(__file__), '../.env')
load_dotenv(envpath)

VONAGE_API_KEY = os.getenv("VONAGE_API_KEY")
VONAGE_SIGNATURE_SECRET = os.getenv("VONAGE_SIGNATURE_SECRET")

from fastapi import FastAPI, Request
from vonage import Auth, Vonage

client = Vonage(Auth(api_key=VONAGE_API_KEY, signature_secret=VONAGE_SIGNATURE_SECRET))

app = FastAPI()


@app.post('/')
async def verify_signed_webhook(request: Request):
    data = await request.json()

    if client.http_client.auth.check_signature(data):
        print('Valid signature')
    else:
        print('Invalid signature')

Ver fuente completa

Ejecute su código

Guarde este archivo en su máquina y ejecútelo:

fastapi dev sms/verify-signed-sms/main.py

Nota: A POST La solicitud también puede incluir datos de la cadena de consulta. Al enviar ambos POST y los datos de la cadena de consulta no se admiten en la SMS API y los resultados podrían ser inesperados.

Generar una firma manualmente

Es muy recomendable que utilices la funcionalidad existente de tu biblioteca de Vonage para generar y validar firmas. Si no utilizas una biblioteca con esta funcionalidad, deberás generar la firma tú mismo. La técnica es ligeramente diferente si estás generando una firma "hash MD5" o una de las firmas HMAC.

Paso 1: Para firmas hash y HMAC

Si eres generar una firma: Añade la marca de tiempo actual a la lista de parámetros con la clave timestamp. Debe ser un número entero que contenga el número de segundos transcurridos desde la época (a veces también se conoce como hora UNIX).

Si eres validación de una firma De Vonage: Elimina el sig antes de generar su firma, y utilice el parámetro timestamp especificados en los parámetros de la solicitud.

A continuación:

  • Recorrer cada uno de los parámetros, ordenados por clave
  • Para cada valor de la lista de parámetros, sustituye todas las instancias de & y = con un guión bajo _.
  • Genera una cadena compuesta por &akey=value&bkey=value. Tenga en cuenta que hay un ampersand & ¡al principio de la cadena!

Llegados a este punto, el proceso para MD5 y HMAC El proceso de hash variará. Sigue el paso 2 que se indica a continuación para decidir qué técnica de hash utilizar.

Paso 2

  • Hash MD5

    1. Añade el secreto de firma al final de la cadena, justo después del último valor. Ahora debería tener un aspecto similar a este: &akey=value&bkey=valueyour_signature_secret
    2. Ahora ejecute la cadena a través de una función hash md5 y convierta los bytes resultantes en una cadena de dígitos hexadecimales. Esta es su firma hash MD5, y debe añadirse a los parámetros HTTP de su solicitud como el parámetro sig parámetro.
  • HMAC

    1. Crea un generador HMAC con el algoritmo que desees y el secreto de tu firma como clave.
    2. Ahora pasa la cadena por un generador HMAC y convierte los bytes resultantes en una cadena de dígitos hexadecimales. Esta es tu firma HMAC, y debes añadirla a los parámetros HTTP de tu solicitud como el sig (por ejemplo, para PHP es el siguiente hash_hmac($algorithm, $data, $secret)).

Paso 3: Notas adicionales

Ten en cuenta que, aunque hayas modificado los valores de los parámetros al generar la firma, los valores que se pasan como parámetros HTTP deben ser sin cambios al enviar esos parámetros a la SMS API.

Solución de problemas relacionados con las firmas

A continuación te ofrecemos algunos consejos y aspectos que debes tener en cuenta al trabajar con mensajes firmados.

Compruebe la respuesta para más detalles

Si el mensaje no se envía como se esperaba, comprueba si la respuesta contiene algún códigos de error que se han devuelto. Esto suele ofrecerte más detalles sobre qué hacer a continuación.

Error 14: Firma no válida

Si el texto que se envía incluye algún carácter especial, como & (ampersand) o = (iguales), entonces hay que sustituirlos en el texto utilizado para crear la firma.

Para ello, sigue estas instrucciones:

  • Detecte que el texto incluye & o =.
  • Crear una versión del texto que utilice _ (guión bajo) en lugar de estos caracteres especiales.
  • Utilice la versión desinfectada del texto para crear la firma.

El texto original se puede seguir enviando y recibiendo; la sustitución de caracteres solo es necesaria para generar la firma.