La mensajería entrega el contenedor
Secure Chat funciona al margen de Telegram, el correo y otros medios de envío. En el dispositivo del remitente, el texto o archivo se convierte en un contenedor cifrado. Ese contenedor se transmite por el canal elegido y el destinatario lo descifra localmente con su clave privada.
- Los interlocutores crean sus propios perfiles e intercambian tarjetas de claves públicas.
- Comparan de forma independiente las huellas completas de las claves y confirman el contacto en la aplicación.
- El remitente elige su perfil, el destinatario y el algoritmo. Secure Chat cifra el contenido y firma el contenedor.
- El destinatario abre el contenedor, introduce la contraseña del almacén si es necesario y obtiene el resultado verificado.
Acceder al historial de la mensajería no proporciona por sí solo la clave privada de Secure Chat. Esta capa adicional protege el contenido que hayas cifrado previamente. No oculta la comunicación, sus participantes, la hora del envío ni las direcciones de red, y no protege un dispositivo que ya esté infectado por software malicioso.
Dos pares de claves por perfil
| Función | Mecanismo |
|---|---|
| Transporte de la clave del contenido | RSA-3072 con OAEP-SHA256 |
| Firma del contenedor | ECDSA, curva NIST P-256, hash SHA-256 |
| Formato de claves públicas | SubjectPublicKeyInfo (SPKI) en DER canónico |
| Formato de claves privadas | DER PKCS#8, dentro del almacén cifrado |
La tarjeta pública
.scpub
contiene el nombre, ambas claves públicas, la huella y la versión del formato. No contiene claves privadas. La tarjeta utiliza JSON legible; los campos binarios se codifican en Base64.
Format: SecureChat.PublicKey
Version: 1
Name
EncryptionPublicKey
SigningPublicKey
Fingerprint
Cómo se verifica al interlocutor
La huella combina ambas claves públicas en un único hash SHA-256 de 64 caracteres hexadecimales. Antes de enviar, hay que compararla completa en persona o por otro canal de confianza. El nombre de una tarjeta importada no demuestra la identidad.
SHA256(
UTF8("SecureChat.Identity.v1\0")
|| int32BE(length(RSA_SPKI)) || RSA_SPKI
|| int32BE(length(ECDSA_SPKI)) || ECDSA_SPKI
)
Un contacto importado siempre se marca como no verificado. La aplicación permite cifrar para ese contacto después de confirmar la comparación. También puedes elegir tus propios perfiles como destinatarios para probar la aplicación.
Una firma digital válida confirma que el contenedor corresponde a la clave de firma. La relación de esa clave con una persona se establece comparando la huella. Si la clave es desconocida o no se ha verificado, la aplicación indica por separado que la identidad del remitente no está confirmada.
Una clave aleatoria independiente por contenedor
Cada nuevo mensaje y archivo recibe una nueva clave aleatoria de 256 bits mediante
RandomNumberGenerator.GetBytes
. El usuario elige entre dos algoritmos de cifrado autenticado, AEAD:
| Algoritmo | Clave | Nonce | Etiqueta |
|---|---|---|---|
| AES-256-GCM | 32 bytes | 12 bytes | 16 bytes |
| ChaCha20-Poly1305 | 32 bytes | 12 bytes | 16 bytes |
ChaCha20-Poly1305 solo se ofrece si el sistema operativo lo admite. El algoritmo elegido forma parte del encabezado autenticado; no se cambia automáticamente a una opción más débil.
La clave aleatoria del contenido se cifra con la clave RSA pública del destinatario. Otra copia se cifra con la clave RSA pública del remitente, de modo que este también puede abrir su mensaje saliente. Al enviarse contenido a uno mismo, se crea una sola ranura de clave.
AEAD verifica la integridad del contenido y de los datos asociados. La firma ECDSA-P256/SHA-256 vincula además el contenedor a la clave del remitente. Si la verificación falla, el descifrado se interrumpe.
Almacén protegido con contraseña
Los perfiles con claves privadas, contactos, ajustes protegidos e historial se guardan en un solo archivo
Data/wallet.scvault
junto a la aplicación. El almacén se cifra con AES-256-GCM.
| Parámetro | Valor |
|---|---|
| Derivación de clave desde la contraseña | PBKDF2-HMAC-SHA-256, 600 000 iteraciones |
| Sal aleatoria | 32 bytes |
| Clave derivada | 32 bytes |
| Nonce al guardar | 12 bytes aleatorios nuevos |
| Etiqueta de autenticación | 16 bytes |
| Longitud de contraseña al crear el almacén | De 12 a 1024 caracteres |
| Tamaño máximo del almacén sin cifrar | 64 MiB |
No se guardan la contraseña ni un hash independiente para verificarla. PBKDF2 ralentiza los ataques por fuerza bruta, pero la protección sigue dependiendo de la propia contraseña. Para una frase de contraseña larga y única, conviene usar palabras aleatorias o un gestor de contraseñas.
El encabezado de 64 bytes también se autentica. A continuación se escriben el texto cifrado y la etiqueta:
"SCVAULT1"[8]
|| version:int32LE
|| iterations:int32LE
|| salt[32]
|| nonce[12]
|| ciphertext_length:int32LE
|| ciphertext
|| tag[16]
El formato de la versión 1 solo acepta los parámetros KDF definidos, un tamaño limitado y la longitud exacta del archivo. Para guardar, se prepara una copia cifrada completa y se sustituye el archivo. Se rechazan las escrituras simultáneas y los intentos de sobrescribir cambios externos detectados. El archivo auxiliar
.lock
no contiene claves.
Qué contiene el encabezado sin cifrar
El contenedor de un mensaje o archivo empieza por cuatro bytes de tipo, la longitud del encabezado JSON y el propio encabezado. El JSON se limita a 16 384 bytes.
magic[4] || header_length:int32LE || header_json[header_length]
| Campo | Contenido |
|---|---|
Version
|
Versión del formato: 1 |
Kind
|
text
o
file
|
Algorithm
|
0 — AES-256-GCM; 1 — ChaCha20-Poly1305 |
SenderEncryptionPublicKey
,
SenderSigningPublicKey
|
Claves públicas del remitente |
RecipientFingerprint
|
Huella del destinatario principal |
PlaintextLength
|
Longitud del contenido original en bytes |
OriginalFileName
|
Nombre del archivo; cadena vacía para texto |
ChunkSize
|
1 048 576 para archivos, 0 para texto |
Nonce
|
12 bytes aleatorios para texto o un prefijo aleatorio de 4 bytes para archivos |
KeySlots
|
Una o dos ranuras: huella y clave encapsulada con RSA de 384 bytes |
Estos metadatos no están cifrados. Son visibles el algoritmo, el tamaño, el nombre del archivo, las claves públicas y las huellas. Las claves persistentes permiten relacionar contenedores del mismo remitente. Si el nombre del archivo es sensible, cámbialo antes de cifrar.
El encabezado sin cifrar está protegido contra modificaciones no detectadas: la firma y AEAD usan sus bytes originales, no un JSON reconstruido. En la descripción siguiente,
||
indica concatenación de bytes. Los enteros se escriben en little-endian; las excepciones big-endian se señalan expresamente.
Texto: contenedor SC1 y adjunto .scmsg
El texto original se limita a 1 MiB con codificación UTF-8 estricta. El tipo del contenedor binario es
SCT1
:
"SCT1"
|| header_length:int32LE || header_json
|| ciphertext_length:int32LE || ciphertext
|| tag[16] || signature[64]
Como datos autenticados adicionales (AAD) se usa todo el prefijo: tipo, longitud y JSON del encabezado. La firma ECDSA-P256 se calcula sobre el SHA-256 de todos los bytes anteriores. El formato de la firma es
IeeeP1363FixedFieldConcatenation
:
r || s
, de 32 bytes cada uno.
Para transmitirlo, el contenedor binario se convierte a Base64url sin caracteres de relleno
=
:
SC1:<base64url(binary_container)>
securechat://message/<base64url(binary_container)>
Antes de mostrar el texto, la aplicación verifica la estructura, la longitud exacta y la firma, descifra la clave encapsulada con RSA y comprueba AEAD. Se rechazan caracteres no válidos, saltos de línea dentro del sobre, parámetros URI adicionales y datos dañados.
Envío mediante Telegram
El botón «Archivo para el chat» copia el archivo cifrado
.scmsg
al portapapeles de archivos de Windows. Pégalo en el chat con
Ctrl
+
V
y envía el adjunto. El destinatario descarga el archivo y lo abre en Secure Chat. Si la aplicación está bloqueada, primero pedirá la contraseña.
El sobre normal
SC1:…
también se puede copiar y pegar manualmente. El enlace de Windows
securechat://…
se limita a 8000 caracteres y no es pulsable en todos los clientes. Telegram Desktop no convierte este esquema personalizado en un enlace automático normal; para él está pensado el adjunto
.scmsg
. Los enlaces antiguos
.sct
se abren explícitamente dentro de la aplicación.
Archivos: bloques, firma y verificación en dos pasadas
El archivo cifrado recibe la extensión
.scx
y el tipo
SCF1
. El formato admite archivos originales de hasta 1 TiB. El procesamiento es en flujo: no se carga el archivo entero en memoria, sino que se divide el contenido en bloques de 1 MiB.
"SCF1" || header_length:int32LE || header_json
|| (chunk_length:int32LE || ciphertext[chunk_length] || tag[16])*
|| 0:int32LE || terminal_tag[16]
|| signature[64]
Cada bloque obtiene un nonce propio de 12 bytes, compuesto por el prefijo aleatorio de cuatro bytes del contenedor y el índice de bloque de ocho bytes:
nonce = Nonce[4] || uint64BE(chunk_index)
AAD = SHA256(full_prefix)[32]
|| uint64BE(chunk_index)
|| int32LE(chunk_length)
El índice empieza en cero. El bloque vacío final recibe el índice siguiente y su propia etiqueta. Incluso un archivo vacío tiene encabezado, bloque final, etiqueta y firma. Para cada archivo nuevo se genera una nueva clave de contenido.
La firma incluye todos los bytes desde
SCF1
hasta la etiqueta AEAD final, inclusive. Se comprueban el orden y el tamaño de los bloques, la longitud exacta del contenedor y el final del archivo. Reordenar, duplicar o borrar bloques, truncar o añadir datos provoca el rechazo.
Qué ocurre al descifrar
- Se verifican el encabezado con tamaño limitado, la longitud del archivo y la disponibilidad de una clave privada adecuada.
- La primera pasada lee el contenedor y verifica la firma completa. Todavía no se crea un archivo temporal sin cifrar.
- La segunda pasada verifica AEAD en cada bloque, escribe los datos descifrados en un archivo temporal y vuelve a verificar la firma final.
- Una vez completado el proceso, el resultado se renombra al nuevo archivo elegido por el usuario. No se sobrescriben archivos existentes.
La barra de estado muestra el porcentaje total: verificación de firma, descifrado y guardado. El 100 % indica que el resultado se ha guardado correctamente. Durante el procesamiento se puede cancelar; ante un error normal o una cancelación, se elimina el archivo temporal.
Se conserva el archivo original. El resultado descifrado no se ejecuta automáticamente. Un corte de corriente, la finalización forzosa del proceso o un identificador externo que impida eliminar el archivo pueden dejar un archivo temporal sin cifrar. Proteger la carpeta de salida y el disco sigue siendo esencial al trabajar con secretos.
Almacenamiento local, historial y bloqueo
| Archivo o carpeta | Función |
|---|---|
Data/wallet.scvault
|
Perfiles, claves, contactos, ajustes e historial cifrados |
Data/window-state.json
|
Tamaño, posición y estado de la ventana; sin claves ni conversaciones |
Data/ui-preferences.json
|
Idioma y preferencia de comprobación de actualizaciones; sin datos del almacén |
Data/ClipboardAttachments
|
Copias temporales de mensajes cifrados para pegarlos en el chat |
El historial contiene metadatos de las operaciones y sobres de texto cifrados. No guarda texto en claro ni el contenido de los archivos. Se conservan las últimas 100 entradas, con unos 8 MiB de sobres en total; las antiguas se eliminan automáticamente. El historial se puede desactivar o borrar.
El almacén se bloquea con Ctrl + L , al minimizar, bloquear o desconectar la sesión de Windows, al entrar en suspensión y por inactividad. El intervalo de inactividad se elige entre 1 y 15 minutos; el predeterminado es 5 minutos. Antes de liberar las claves se cancela la operación de archivo en curso.
Al bloquear, se vacían los campos y las referencias a registros, y se ponen a cero las matrices de claves privadas y de la clave derivada que pertenecen a la aplicación. No se garantiza eliminar todas las copias de memoria: las cadenas administradas, el portapapeles, los volcados y el archivo de paginación pueden conservar restos de datos.
Dos modos distintos de portapapeles
«Copiar texto» marca la entrada de la aplicación y la borra tras 30 segundos o al bloquear, si todavía pertenece a Secure Chat. No borra una entrada más reciente de otra aplicación. La copia normal con el comando del sistema Ctrl + C no está sujeta a este temporizador.
«Archivo para el chat» coloca en Windows FileDrop la ruta al archivo preparado
.scmsg
, que solo contiene texto cifrado. La copia sigue disponible después de bloquear y cerrar el almacén para que la mensajería tenga tiempo de leerla. Cada copia crea un adjunto independiente.
Las copias de más de 24 horas se limpian al iniciar la aplicación o copiar de nuevo. Se guardan hasta 128 adjuntos temporales a la vez; si se alcanza el límite, se puede guardar el mensaje explícitamente en una carpeta elegida. Las prohibiciones de historial y portapapeles en la nube se envían como indicaciones a Windows; otros gestores de portapapeles pueden ignorarlas.
Copias de seguridad, traslado y actualización
Una copia de seguridad contiene el almacén cifrado completo. Para abrirla se necesita la contraseña que tenía al crearla. Actualiza la copia tras añadir claves nuevas. No se ofrece recuperación de acceso sin contraseña y claves privadas.
Cambiar la contraseña, eliminar un perfil o borrar el historial modifica el almacén actual. Las copias antiguas conservan la contraseña, las claves y el historial anteriores. Eliminar una entrada tampoco garantiza borrarla físicamente del SSD, de instantáneas o de un sistema de archivos con registro.
Para actualizar a 0.1.6, cierra Secure Chat y sustituye
SecureChat.exe
en la misma carpeta.
Conserva toda la carpeta Data.
Los formatos del almacén y los contenedores siguen en la versión 1; no se necesita migración. Las instrucciones de migración para versiones futuras con cambios de formato se documentarán por separado.
Al trasladar la aplicación a otra carpeta, mueve el EXE junto con
Data
y las traducciones externas necesarias de
Languages
. Después, vuelve a activar en los ajustes la apertura de
.scmsg
,
.scx
y de enlaces: el registro de Windows guarda una ruta absoluta. El EXE de archivo único puede extraer bibliotecas nativas de .NET a la caché del sistema del usuario.
Qué solicitudes de red realiza la aplicación
No se necesita servidor para cifrar ni descifrar. Secure Chat no tiene transporte de mensajes, cuenta de intercambio de claves ni servicio de restablecimiento de contraseña. Los contenedores se entregan mediante la mensajería, el correo u otro canal que elijas.
Al pulsar «Buscar actualizaciones», la aplicación obtiene un pequeño JSON de
https://itmsft.com/securechat/update/latest.json
. La comprobación al iniciar se activa por separado y está desactivada de forma predeterminada. Se transmiten los datos de red normales de una solicitud HTTPS y un User-Agent genérico con la versión del programa. La solicitud no incluye contraseñas, claves, perfiles, historial ni contenido de archivos.
El cliente limita la respuesta a 64 KiB y la lectura a 10 segundos, y verifica la versión y la disponibilidad del paquete para su arquitectura. Un error de servidor, red o formato indica que no se pudo comprobar; no declara actualizada la versión instalada.
El botón de descarga abre en el navegador habitual una URL HTTPS permitida del paquete en
itmsft.com
. La aplicación no instala automáticamente ni ejecuta el archivo descargado. Verifica el formato del campo SHA-256, pero no los bytes del ZIP descargado por el navegador. El EXE de la versión 0.1.6 no tiene firma digital del editor.
Límites que debes tener en cuenta
- Seguridad del dispositivo. El software malicioso, los registradores de teclas, la lectura de memoria, la sustitución del EXE o el acceso remoto pueden revelar texto antes de cifrarlo o después de descifrarlo.
- Metadatos. Son visibles el encabezado sin cifrar del contenedor y los datos de red del canal de entrega. No es una herramienta de anonimato.
- Claves estáticas. No se implementa secreto hacia adelante (forward secrecy): una clave privada robada permite leer contenedores interceptados previamente y dirigidos a esa clave.
- Recuperación de la confidencialidad. No hay Double Ratchet ni seguridad posterior al compromiso (post-compromise security). Se trata de un formato propio, no de una implementación del protocolo Signal.
- Repeticiones y reversión. Un contenedor válido se puede reenviar. Una copia antigua válida del almacén no está protegida frente a una reversión: la integridad no demuestra que sea la más reciente.
- Contraseña. La longitud mínima y la espera de la interfaz no impiden ataques por fuerza bruta sin conexión sobre un almacén robado. Las medidas principales son una contraseña fuerte y la KDF.
- Borrado de datos. No se garantiza el borrado completo de la RAM, el archivo de paginación, el portapapeles en la nube ni el almacenamiento.
- Propiedades criptográficas. El esquema no es poscuántico. Los terceros que obtengan el contenedor pueden verificar la firma; no se ofrece negación criptográfica.
- Estado de revisión. Las primitivas estándar y las pruebas automatizadas no sustituyen una auditoría independiente del protocolo y la implementación.
Secure Chat añade un control independiente sobre el contenido que elijas. Para datos especialmente sensibles se necesita evaluar tu modelo de amenazas, proteger el dispositivo y someter la implementación a una revisión experta independiente.