Como desencriptar un texto usando análisis de frecuencia

Como desencriptar un texto usando análisis de frecuencia

Recientemente encontré una oferta laboral en la que como proceso de preselección pedía desencriptar el siguiente texto y explicar el procedimiento realizado.

ΣΦΨΞΔλΨΔΛΣΦΔλΨξΔϗΞΔΦΨΞϑλΨΛΣΘϑΞϗΦϑλΨΣΞΨλϑΞΨζβΣφΔΨΣΦΨΣΞΨξΛϗΞΞϑΨϖΣΞΨΠΣϖΛΣφΔΞΨΩΨΠΛΣΦϖϗϖϑΨΔΨΞΔΨΘΔφϗΔΨϖΣΨΞϑλΨΓΔΘϗΦϑλΨΣΞΨΔΛΛϗΣΛϑΨαΔΨΣΞΨΔΛΛϗΣΛϑΨαΔΨΣλΨξΔΦϖΣΛΔΨϖΣΨΦϗΣξΞΔΨλβΨΠϑΦΓΡϑΨΔΞΨαϗΣΦμϑΨΞϑΨλΔΞβϖΔΦΨΞΔλΨεΞΔβμΔλΨϖΣΞΨΠΔζϑΦΔΞΨΩΨΔΦϗΘΔΦϖϑΨΞΔΨμΛϑΠΔΨΠΔΛΨΣλϑλΨΓΣΛΛϑλΨΣΞΨΔΛΛϗΣΛϑΨαΔΨΣΞΨΔΛΛϗΣΛϑΨαΔΨΞΔλΨΠΣΦΔλΨΩΨΞΔλΨαΔηβϗμΔλΨλΣΨαΔΦΨΠΔΛΨΞΔΨΘϗλΘΔΨλΣΦϖΔΨΞΔλΨΠΣΦΔλΨλϑΦΨϖΣΨΦϑλϑμΛϑλΨΞΔλΨαΔηβϗμΔλΨλϑΦΨΔζΣΦΔλ

Hace poco también leí el libro “Los códigos secretos” de Simon Singh, donde cuenta toda la historia de la criptografía y sus usos, muy bueno y lo súper recomiendo.

Portada del libro

Así que pensé que sería algo interesante para hacer, me arremangue la camisa y comencé.

Análisis de la situación y suposiciones

En este punto sabemos muy poco asi que vamos a suponer lo siguiente y ver hacia donde nos lleva:

  • Que el lenguaje original del mensaje es en español, dado que la oferta laboral estaba precisamente en este idioma.
  • Que se utilizó una de las encriptaciones más simple e históricas, llamada cifrado clásico más específicamente un subconjunto de éste, llamado cifrado por sustitución.

En un cifrado por sustitución, las letras (o grupos de letras) son sistemáticamente reemplazadas en el mensaje por otras letras (o grupos de letras).

Ejemplo de cifrado por sustitución

Análisis de frecuencia

Para poder romper la encriptación vamos a utilizar el método análisis de frecuencia.

El análisis de frecuencias está basado en el hecho que, dado un texto, ciertas letras o combinaciones de letras aparecen más a menudo que otras, existiendo distintas frecuencias para ellas.

Por ejemplo, en español las letras A y E son muy comunes, mientras que la K y W son muy raras.

gráfico frecuencia de uso de letras en español

Mediante un pequeño programa escrito en Python vemos los diferentes signos utilizados, y la cantidad de uso de cada uno de ellos

from collections import Counter

text = "ΣΦΨΞΔλΨΔΛΣΦΔλΨξΔϗΞΔΦΨΞϑλΨΛΣΘϑΞϗΦϑλΨΣΞΨλϑΞΨζβΣφΔΨΣΦΨΣΞΨξΛϗΞΞϑΨϖΣΞΨΠΣϖΛΣφΔΞΨΩΨΠΛΣΦϖϗϖϑΨΔΨΞΔΨΘΔφϗΔΨϖΣΨΞϑλΨΓΔΘϗΦϑλΨΣΞΨΔΛΛϗΣΛϑΨαΔΨΣΞΨΔΛΛϗΣΛϑΨαΔΨΣλΨξΔΦϖΣΛΔΨϖΣΨΦϗΣξΞΔΨλβΨΠϑΦΓΡϑΨΔΞΨαϗΣΦμϑΨΞϑΨλΔΞβϖΔΦΨΞΔλΨεΞΔβμΔλΨϖΣΞΨΠΔζϑΦΔΞΨΩΨΔΦϗΘΔΦϖϑΨΞΔΨμΛϑΠΔΨΠΔΛΨΣλϑλΨΓΣΛΛϑλΨΣΞΨΔΛΛϗΣΛϑΨαΔΨΣΞΨΔΛΛϗΣΛϑΨαΔΨΞΔλΨΠΣΦΔλΨΩΨΞΔλΨαΔηβϗμΔλΨλΣΨαΔΦΨΠΔΛΨΞΔΨΘϗλΘΔΨλΣΦϖΔΨΞΔλΨΠΣΦΔλΨλϑΦΨϖΣΨΦϑλϑμΛϑλΨΞΔλΨαΔηβϗμΔλΨλϑΦΨΔζΣΦΔλ"
letters = Counter(text)
print(f"cantidad de letras = {len(letters)}")
print(letters)

Obteniendo el resultado:

cantidad de letras = 23

Counter({'Ψ': 74, 'Δ': 53, 'Σ': 34, 'Ξ': 31, 'λ': 31, 'ϑ': 26, 'Λ': 24, 'Φ': 23, 'ϗ': 16, 'ϖ': 12, 'Π': 9, 'α': 8, 'Θ': 6, 'β': 6, 'μ': 6, 'ξ': 4, 'ζ': 3, 'φ': 3, 'Ω': 3, 'Γ': 3, 'η': 2, 'Ρ': 1, 'ε': 1})

Dándonos cierta confirmación de que vamos bien, ya que se utilizan 23 signos distintos, un valor cercano a la cantidad de letras en el alfabeto.

Además, vemos que de mayor a menor en cantidad de usos de un signo es: 74 - 53 - 34 - 31 - 31 …


Según el siguiente artículo (frecuencia de aparición de letras) en el idioma español la letra “a” es la más frecuente, seguida de cerca por la letra “e”, pero superándolas esta el “espacio” casi duplicando a la letra más frecuente.

Por lo tanto, hacemos los siguientes reemplazos:

  1. El signo Ψ por un espacio
  2. El signo Δ por una a
  3. El signo Σ por una e

Nota: Tener en cuenta por supuesto que esto no es una ciencia exacta, estamos haciendo uso de la probabilidad. “Puede fallar” dijo Tusam. Si este fuera el caso se puede volver atrás e intercambiar la “a” por la “e” y continuar el proceso.

Agregamos las siguientes líneas de código a nuestro programa:

text = text.replace('Ψ', ' ')
text = text.replace('Δ', 'a')
text = text.replace('Σ', 'e')
print(text)

Obteniendo:

eΦ Ξaλ aΛeΦaλ ξaϗΞaΦ Ξϑλ ΛeΘϑΞϗΦϑλ eΞ λϑΞ ζβeφa eΦ eΞ ξΛϗΞΞϑ ϖeΞ ΠeϖΛeφaΞ Ω ΠΛeΦϖϗϖϑ a Ξa Θaφϗa ϖe Ξϑλ ΓaΘϗΦϑλ eΞ aΛΛϗeΛϑ αa eΞ aΛΛϗeΛϑ αa eλ ξaΦϖeΛa ϖe ΦϗeξΞa λβ ΠϑΦΓΡϑ aΞ αϗeΦμϑ Ξϑ λaΞβϖaΦ Ξaλ εΞaβμaλ ϖeΞ ΠaζϑΦaΞ Ω aΦϗΘaΦϖϑ Ξa μΛϑΠa ΠaΛ eλϑλ ΓeΛΛϑλ eΞ aΛΛϗeΛϑ αa eΞ aΛΛϗeΛϑ αa Ξaλ ΠeΦaλ Ω Ξaλ αaηβϗμaλ λe αaΦ ΠaΛ Ξa ΘϗλΘa λeΦϖa Ξaλ ΠeΦaλ λϑΦ ϖe ΦϑλϑμΛϑλ Ξaλ αaηβϗμaλ λϑΦ aζeΦaλ

Analizando el resultado es muy posible que:

  • El signo “Ξ” sea una “l”, porque en una palabra se repite 2 veces seguidas y también se usaría para las palabras ‘las’ ‘los’, ‘el’, ‘la’.

Hacemos el reemplazo…

text = text.replace('Ξ', 'l')

Obteniendo:

eΦ laλ aΛeΦaλ ξaϗlaΦ lϑλ ΛeΘϑlϗΦϑλ el λϑl ζβeφa eΦ el ξΛϗllϑ ϖel ΠeϖΛeφal Ω ΠΛeΦϖϗϖϑ a la Θaφϗa ϖe lϑλ ΓaΘϗΦϑλ el aΛΛϗeΛϑ αa el aΛΛϗeΛϑ αa eλ ξaΦϖeΛa ϖe Φϗeξla λβ ΠϑΦΓΡϑ al αϗeΦμϑ lϑ λalβϖaΦ laλ εlaβμaλ ϖel ΠaζϑΦal Ω aΦϗΘaΦϖϑ la μΛϑΠa ΠaΛ eλϑλ ΓeΛΛϑλ el aΛΛϗeΛϑ αa el aΛΛϗeΛϑ αa laλ ΠeΦaλ Ω laλ αaηβϗμaλ λe αaΦ ΠaΛ la ΘϗλΘa λeΦϖa laλ ΠeΦaλ λϑΦ ϖe ΦϑλϑμΛϑλ laλ αaηβϗμaλ λϑΦ aζeΦaλ

Continuando de la misma forma es muy posible que:

  • Ω sea una “y”
  • ϑ sea una “o”
  • λ sea una ”s”
text = text.replace('Ω', 'y')
text = text.replace('ϑ', 'o')
text = text.replace('λ', 's')

Obteniendo:

eΦ las aΛeΦas ξaϗlaΦ los ΛeΘolϗΦos el sol ζβeφa eΦ el ξΛϗllo ϖel ΠeϖΛeφal y ΠΛeΦϖϗϖo a la Θaφϗa ϖe los ΓaΘϗΦos el aΛΛϗeΛo αa el aΛΛϗeΛo αa es ξaΦϖeΛa ϖe Φϗeξla sβ ΠoΦΓΡo al αϗeΦμo lo salβϖaΦ las εlaβμas ϖel ΠaζoΦal y aΦϗΘaΦϖo la μΛoΠa ΠaΛ esos ΓeΛΛos el aΛΛϗeΛo αa el aΛΛϗeΛo αa las ΠeΦas y las αaηβϗμas se αaΦ ΠaΛ la ΘϗsΘa seΦϖa las ΠeΦas soΦ ϖe ΦosoμΛos las αaηβϗμas soΦ aζeΦas

Esto es un proceso iterativo, donde en cada iteración nos vamos acercando cada vez más al objetivo.

A partir de acá ya es mucho más fácil deducir el resto, ¿Te animas a completarlo?

¡Buena suerte y nos vemos!