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.
- Defensa contra la interceptación y la repetición posterior
Contenido
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.
- Enviar mensajes con firmas. Utilice el bibliotecas de clientes para generar y enviar el mensaje firmado.
- Verificar las firmas de los mensajes entrantes para garantizar la autenticidad del mensaje en el webhook entrante.
- Generar manualmente una firma si no puede utilizar las bibliotecas existentes, se incluye aquí el proceso manual para la generación de firmas.
Utilizar firmas al enviar mensajes
Para enviar un mensaje con una firma, deberá utilizar la función SIGNATURE_SECRET en lugar de su API_SECRET al enviar el mensaje. Puede encontrar el secreto de firma y elegir qué algoritmo de firma utilizar visitando la página salpicadero. 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 usted no puede hacer esto por alguna razón, usted puede generar y validar firmas usted mismo, pero esto puede ser complicado y potencialmente propenso a errores. Consulte la sección sobre la generación manual de firmas.
El proceso para enviar un mensaje firmado es el siguiente:
- Crear una firma solicitar para enviar un SMS.
- Compruebe el códigos de respuesta y asegúrese de que ha enviado la solicitud correctamente.
- Su mensaje se entrega al terminal. El terminal del usuario devuelve un acuse de recibo.
- (opcional) Si solicitó recibos de entrega y mensajes entrantes firmados, querrá validar la firma para cada solicitud entrante.
Si no ha generado correctamente la firma, el estado es 14, invalid signature. Encontrará más información en solución de problemas 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 siguiente ejemplo de código muestra cómo enviar un mensaje firmado con la SMS API.
Requisitos previos
npm install @vonage/server-sdkCrea 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',
},
});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();Ejecute su código
Guarde este archivo en su máquina y ejecútelo:
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)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}")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:
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;Añada lo siguiente al método main del archivo SendSignedSms:
);
SmsSubmissionResponse response = client.getSmsClient().submitMessage(message);
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());
}
}
}
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:
Requisitos previos
Install-Package VonageCrea un archivo llamado SendSignedSms.cs y añade el siguiente código:
var credentials = Credentials.FromApiKeySignatureSecretAndMethod(
vonageApiKey,
vonageApiSignatureSecret,
Vonage.Cryptography.SmsSignatureGenerator.Method.md5hash
);
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"
});Requisitos previos
composer require vonage/clientEjecute su código
Guarde este archivo en su máquina y ejecútelo:
Requisitos previos
pip install vonage python-dotenvEscriba 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)Ejecute su código
Guarde este archivo en su máquina y ejecútelo:
Validar la firma de los mensajes entrantes
Para verificar el origen de los webhooks entrantes a su punto final de SMS, puede activar la firma de mensajes entrantes - póngase 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 siguiente ejemplo de código muestra cómo verificar una firma para un mensaje SMS entrante, utilizando la función sig en la cadena de consulta.
Requisitos previos
npm install express @vonage/server-sdkEscriba 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);Ejecute su código
Guarde este archivo en su máquina y ejecútelo:
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;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);
}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:
Requisitos previos
Install-Package VonageCrea un archivo llamado SmsController.cs y añade el siguiente código:
{
[HttpGet("webhooks/inbound-sms")] 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();
}
}
}Requisitos previos
composer require vonage/clientEjecute su código
Guarde este archivo en su máquina y ejecútelo:
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')Ejecute su código
Guarde este archivo en su máquina y ejecútelo:
Nota: A POST también puede incluir datos de cadena de consulta. Enviando 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 manualmente una firma
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 validar una firma de Vonage: Quitar el sig antes de generar su firma, y utilice el parámetro timestamp proporcionado en los parámetros de la solicitud.
Entonces:
- Recorrer en bucle 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_. - Generar una cadena compuesta por
&akey=value&bkey=value. Tenga en cuenta que hay un ampersand&¡al principio de la cadena!
En este punto, el proceso de MD5 y HMAC hash será diferente. Sigue el paso 2 para decidir qué técnica de hashing utilizar.
Paso 2
hash MD5
- Añade el secreto de firma al final de la cadena, justo después del último valor. Ahora debería ser algo como esto:
&akey=value&bkey=valueyour_signature_secret - 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
sigparámetro.
- Añade el secreto de firma al final de la cadena, justo después del último valor. Ahora debería ser algo como esto:
HMAC
- Crea un generador HMAC con el algoritmo que desees y el secreto de tu firma como clave.
- Ahora ejecute la cadena a través de un generador hmac y convierta los bytes resultantes en una cadena de dígitos hexadecimales. Esta es tu firma HMAC, y debe ser añadida a los parámetros HTTP de tu petición como el parámetro
sig(por ejemplo, para PHP es el siguientehash_hmac($algorithm, $data, $secret)).
Paso 3: Notas adicionales
Tenga en cuenta que aunque haya cambiado los valores de los parámetros al generar la firma, los valores pasados como parámetros HTTP deben ser sin cambios al enviar esos parámetros a la SMS API.
Solución de problemas de firmas
He aquí algunos consejos y peligros que hay que 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, compruebe la respuesta para ver si hay algún error. códigos de error que se han devuelto. Esto normalmente le dará más detalles sobre qué hacer a continuación.
Error 14: Firma no válida
Si el texto que se envía incluye caracteres especiales como & (ampersand) o = (iguales), entonces hay que sustituirlos en el texto utilizado para crear la firma.
Para ello, siga 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 puede seguir enviándose/recibiéndose, los caracteres sustituidos sólo son necesarios para generar la firma.