Seguridad

Un modelo de confianza que se explica se puede auditar; uno que se esconde, no. Esto es lo que hace SecureChat, y también lo que no hace.

En resumen

Cómo se cifra un mensaje (sobre v1)

Usamos libsodium, una biblioteca criptográfica auditada y ampliamente utilizada. Estas son las piezas del sobre v1 (sc1):

Primitivas criptográficas del sobre v1
PiezaConstrucción
Identidad (tu dispositivo y la empresa)Par de llaves X25519
Clave de la conversación32 bytes aleatorios generados por tu teléfono al canjear la invitación. Si la generáramos nosotros, la conoceríamos.
Reparto de esa claveSe sella por separado (crypto_box_seal) para tu llave pública y para la de la empresa. Nosotros solo guardamos los dos sobres sellados.
Cifrado de cada mensajeXChaCha20-Poly1305 con nonce aleatorio de 24 bytes
Datos asociadosCada mensaje queda ligado a su conversación, a quién lo envía, a su identificador y a la versión de llave. Un servidor no puede moverlo de conversación, duplicarlo con otro identificador ni hacer pasar un mensaje tuyo por uno de la empresa.
RellenoHasta múltiplos de 256 bytes, para ocultar la longitud exacta
Firma de la llave de empresaEd25519, con la llave de plataforma
Firma de la rotación de llaveEd25519, con la llave de firma de la propia empresa (más abajo)
HuellasBLAKE2b-256 con separación de dominio

Adjuntos cifrados

Las fotos y los documentos se cifran en el dispositivo que los envía (tu teléfono o el servidor de la empresa), igual que el texto:

Qué protege

Qué no protege

Llave de plataforma y verificación de empresas

Antes de que una empresa pueda invitar, comprobamos su existencia legal, que controla su dominio (registro DNS) y el número de WhatsApp desde el que invita. Después firmamos su llave pública con nuestra llave de plataforma Ed25519. La app verifica esa firma y muestra la insignia de Empresa verificada.

Llave pública de plataforma (Ed25519, base64url):

qxh_sOak_wQVqZifJjDcoy-TeWIF3NADjqsjta0GPlw

Lo que se firma es exactamente SecureChat|v1|company-key|<companyId>|<keyVersion>|<llave pública>. Esto concentra el riesgo en nosotros: si alguien robara la llave de plataforma, podría suplantar a una marca. Por eso existe también la comprobación del enlace.

La empresa genera su propio par de llaves en su infraestructura con nuestro SDK (npx @securechat/sdk keygen) y solo nos sube la pública. El portal no ofrece generarla en el navegador: si la llave privada pasara por nuestros servidores, la promesa dejaría de ser verificable.

Empresas sin verificar y Modo pruebas

Para que una empresa pueda probar su integración mientras la revisamos, puede crear invitaciones de pruebas. Su llave no está firmada como verificada, así que cualquiera podría registrarse como “Banco X” y usarlas para suplantar a una marca. Por eso:

El cifrado es el mismo que en una conversación normal. Lo que cambia es la garantía de identidad: en una conversación de pruebas no comprobamos quién es la empresa.

La huella en el enlace de invitación

Cuando la empresa crea la invitación con el SDK, agrega al enlace un fragmento #s=…&fp=…. El navegador no envía el fragmento al servidor, así que nosotros no lo vemos, pero el enlace viaja por WhatsApp, un canal que no controlamos. Al canjearla:

  1. La app comprueba que la llave de la empresa que le damos tiene la huella fp del enlace.
  2. La app liga su propia llave al secreto s con un MAC, y la empresa lo verifica.

Si sustituyéramos cualquiera de las dos llaves, uno de los dos extremos lo detectaría. Límites: solo cubre el canje por enlace, no el código corto tecleado, y las invitaciones creadas a mano desde el portal no llevan ese secreto.

Rotación de llave firmada por la empresa

Además de su llave de cifrado, la empresa genera con el SDK una llave de firma Ed25519 que también se queda en su infraestructura; solo nos sube la pública. La app la fija en el primer contacto, junto con la de cifrado. Cuando la empresa rota su llave de cifrado, firma el cambio con esa llave de firma: SecureChat|v1|company-key-rotation|<companyId>|<versión anterior>|<llave anterior>|<versión nueva>|<llave nueva>. Comprobamos la firma antes de aceptar la llave nueva y la app la vuelve a comprobar.

Por qué importa: con solo nuestra firma de plataforma, una rotación legítima y una suplantación nuestra se verían igual. Con la firma de la empresa, suplantar a una empresa que ya tienes fijada exige su llave de firma, que nunca pasa por nosotros. La firma de plataforma sigue siendo obligatoria en ambos casos. Por ahora la llave de firma no rota: cambiarla se trata como una rotación sin firmar.

Sin forward secrecy en v1

Cada conversación usa una clave estable. Si en el futuro se filtrara tu llave privada o la de la empresa, junto con los mensajes cifrados guardados, se podrían descifrar también los mensajes anteriores de esa conversación. Protocolos como Signal renuevan las claves con cada mensaje para evitarlo; lo dejamos fuera de la primera versión del protocolo de forma deliberada y está en nuestra hoja de ruta.

Metadatos

Aunque no veamos el contenido, vemos quién habla con qué empresa, cuándo y con qué frecuencia, el tamaño aproximado de cada mensaje (redondeado a 256 bytes), el tamaño y la fecha de cada adjunto, las direcciones IP y datos del dispositivo. Con eso se puede inferir bastante, y por eso lo declaramos en la política de privacidad.

El historial está ligado a tu dispositivo: si lo pierdes, recuperas cada conversación con una nueva invitación de la empresa, que vuelve a sellar la clave para tu dispositivo nuevo.

Reportar una vulnerabilidad

Escríbenos a soporte@securechat-app.com con el asunto “Seguridad”. Te pedimos un plazo razonable para corregirla antes de publicarla.