🧠 / tech core / cibersecurity / Ejemplo de Criptoanálisis

Ejemplo de Criptoanálisis

Imagen criptográfica

Problema inicial

En markdown

  1. Se toma una tabla a partir de ejecutar un OCR.

    C1C2C3C4C5
    WIST\FOZC\AT_]UA]FGTXA_NT
    WSSOLO\ZE\AX_ISATE\TUN_N\
    DBHUBSSIFOIAVHQ]SRPABLU_T
    BBIEBSN\EOILV\C]ORNOCLI_M
    BCVDZBHIUDXU]QCEJWYSU_RRG
    ICENZBTOU\XSOQLEO\ESXIRRS
    YYGYB_MJSDUNHBJMMHWQFHKXG
    YTGE\_UJN\MNABLM\HLQFAK\G
    MNFTMJUP]JJP[UBZLU^YQHAME
    MIFGMJNPOJJR[ABZNUCYQIAMA
  2. Se identifica la correspondencia entre filas por pares.

    C1C2C3C4C5
    WIST\FOZC\AT_]UA]FGTXA_NT
    WSSOLO\ZE\AX_ISATE\TUN_N\
    -------------------------
    DBHUBSSIFOIAVHQ]SRPABLU_T
    BBIEBSN\EOILV\C]ORNOCLI_M
    -------------------------
    BCVDZBHIUDXU]QCEJWYSU_RRG
    ICENZBTOU\XSOQLEO\ESXIRRS
    -------------------------
    YYGYB_MJSDUNHBJMMHWQFHKXG
    YTGE\_UJN\MNABLM\HLQFAK\G
    -------------------------
    MNFTMJUP]JJP[UBZLU^YQHAME
    MIFGMJNPOJJR[ABZNUCYQIAMA
  3. Se retira todos los caracteres no textuales reemplazandolos por guion al piso.

    C1C2C3C4C5
    WIST_FOZC_AT__UA_FGTXA_NT
    WSSOLOZEAX_ISATE_TUNN
    -------------------------
    DBHUBSSIFOIAVHQ_SRPABLU_T
    BBIEBSN_EOILV_C_ORNOCLI_M
    -------------------------
    BCVDZBHIUDXU_QCEJWYSU_RRG
    ICENZBTOU_XSOQLEO_ESXIRRS
    -------------------------
    YYGYB_MJSDUNHBJMMHWQFHKXG
    YTGE_UJNMNABLM_HLQFAK_G
    -------------------------
    MNFTMJUP_JJP_UBZLU_YQHAME
    MIFGMJNPOJJR_ABZNUCYQIAMA
  4. Se consolida los guión bajo para que se iguale tanto la fila superior como la fila inferior en cada celda.

    C1C2C3C4C5
    WIST_FZCAT__UA_F_TXAN
    WSSO_OZEAX__SA_E_TUNN
    -------------------------
    DBHUBSS_FOIAV_Q_SRPABLU_T
    BBIEBSN_EOILV_C_ORNOCLI_M
    -------------------------
    BCVDZBHIU_XU_QCEJ_YSU_RRG
    ICENZBTOU_XS_QLEO_ESX_RRS
    -------------------------
    YYGY_MJSUNHBJM_HWQFHK_G
    YTGE_UJNMNABLM_HLQFAK_G
    -------------------------
    MNFTMJUP_JJP_UBZLU_YQHAME
    MIFGMJNP_JJR_ABZNU_YQIAMA
  5. Se recorre cada caracter de la fila superior en cada celda y si el caracter no es igual en posición y en caracter con la fila inferior, se reemplaza por un guion al piso.

    C1C2C3C4C5
    W_S__ZA____A___T__N
    WSSO_OZEAX__SA_E_TUNN
    -------------------------
    _B__BS___OI_V__R_L___
    BBIEBSN_EOILV_C_ORNOCLI_M
    -------------------------
    _C__ZB_UX_QE___S_RR
    ICENZBTOU_XS_QLEO_ESX_RRS
    -------------------------
    Y_G__JN_BM_H_QF_K_G
    YTGE_UJNMNABLM_HLQFAK_G
    -------------------------
    M_F_MJ_P_JJ___BZ_U_YQAM
    MIFGMJNP_JJR_ABZNU_YQIAMA
  6. Vuelvo a consolidar guiones.

    C1C2C3C4C5
    W_S__ZA____A___T__N
    W_S__ZA____A___T__N
    -------------------------
    _B__BS___OI_V__R_L___
    _B__BS___OI_V__R_L___
    -------------------------
    _C__ZB_UX_QE___S_RR
    _C__ZB_UX_QE___S_RR
    -------------------------
    Y_G__JN_BM_H_QF_K_G
    Y_G__JN_BM_H_QF_K_G
    -------------------------
    M_F_MJ_P_JJ___BZ_U_YQAM
    M_F_MJ_P_JJ___BZ_U_YQAM
  7. Dado que no tiene significado al juntar la letras restantes, Regreso al punto 3 y ahora elimino los caracteres repetidos.

    C1C2C3C4C5
    I_TFOC_T__U_FGXA__T
    _S_OLO_E_X_IS_TE__UN___
    -------------------------
    DHUSIF_A_HQ_S_PAB_U_T
    BIEN_E_L__C_O_NOC_I_M
    -------------------------
    BCVD__HI_D_U__CJWYU___G
    ICEN__TO___SO_LO_EXI__S
    -------------------------
    _Y_YB_M_SDU_H_JM_WH_X
    T_EU_NM_A_L__L_A___
    -------------------------
    N_T_U___P_U_L____H__E
    I_GN_OR_AN_C_I__A
  8. Al concatenar la fila inferior de cada celda, encontramos el siguiente mensaje: “SOLO EXISTE UN BIEN, EL CONOCIMIENTO. SOLO EXISTE UN MAL, LA IGNORANCIA”.

En Hojas de cálculo

  1. Se usa la misma tabla inicial.

    C1C2C3C4C5
    WIST\FOZC\AT_]UA]FGTXA_NT
    WSSOLO\ZE\AX_ISATE\TUN_N\
    DBHUBSSIFOIAVHQ]SRPABLU_T
    BBIEBSN?EOILV\C]ORNOCLI_M
    BCVDZBHIUDXU]QCEJWYSU_RRG
    ICENZBTOU+XSOQLEO\ESXIRRS
    YYGYB_MJSDUNHBJMMHWQFHKXG
    YTGE\_UJN\MNABLM?HLQFAK\G
    MNFTMJUP]JJP[UBZLU^YQHAME
    MIFGMJNPOJJR[ABZNUCYQIAMA
  2. Luego se concatenan las filas con la siguiente formula: =CONCATENAR(A1,B1,C1,D1,E1).

  3. Luego se concatenan las filas pares e impares resultantes con la siguiente formula: =CONCATENAR(A12,A14,A16,A18,A20) y =CONCATENAR(A13,A15,A17,A19,A21)

  4. Se hacen los calculos necesarios para mostrar el mensaje: =ARRAYFORMULA(TEXTJOIN("",VERDADERO,SI(EXTRAE(A23,FILA(INDIRECTO("1:"&LARGO(A23))),1)=EXTRAE(A24,FILA(INDIRECTO("1:"&LARGO(A24))),1),"_",EXTRAE(A24,FILA(INDIRECTO("1:"&LARGO(A24))),1))))

  5. Se reunen todos los caracteres para darle un sentido al mensaje: =REGEXREPLACE(A27,"[\_]","")

  6. Se separa cada palabra: =REGEXREPLACE(A28,"[\\]"," ")

  7. Y se ponen los signos de puntuación: =REGEXREPLACE(A29,"[\?]",", ")

Con Python

Se usa el siguiente código fuente:

Desencripción

import re

clave   = "WIST\\FOZC\\AT_]UA]FGTXA_NTDBHUBSSIFOIAVHQ]SRPABLU_TBCVDZBHIUDXU]QCEJWYSU_RRGYYGYB_MJSDUNHBJMMHWQFHKXGMNFTMJUP\\JJP[UBZLU^YQHAME"
mensaje = "WSSOLO\\ZE\\AX_ISATE\\TUN_N\\BBIEBSN?EOILV\\C]ORNOCLI_MICENZBTOU?XSOQLEO\\ESXIRRSYTGE\\_UJN\\MNABLM?HLQFAK\\GMIFGMJNPOJJR[ABZNUCYQIAMA"

def vernam_decode(clave, mensaje):
    mensaje_modificado_lista = list(mensaje)  # Convertimos el mensaje a una lista para poder modificarlo

    longitud_clave = len(clave)
    longitud_mensaje = len(mensaje)

    if longitud_mensaje != longitud_clave:
        print("Las longitudes de clave y mensaje no son iguales: ", longitud_clave, ", ", longitud_mensaje)
        return None

    for i in range(longitud_clave):
        if clave[i] == mensaje[i]:
            mensaje_modificado_lista[i] = "_"

    mensaje_modificado = "".join(mensaje_modificado_lista)  # Volvemos a unir la lista en una cadena

    mensaje_modificado = re.sub(r"[_?\\\\]", lambda m: "" if m.group(0) == "_" else "," if m.group(0) == "?" else " ", mensaje_modificado)

    return mensaje_modificado


mensaje_modificado = vernam_decode(clave, mensaje)

if mensaje_modificado:
    print("Clave:", clave)
    print("Mensaje Original:", mensaje)
    print("Mensaje Modificado:", mensaje_modificado)

Encripción

import random
import re

def generar_clave_dinamica(longitud):
    """Genera una clave aleatoria de la longitud especificada."""
    caracteres = [chr(i) for i in range(32, 127)]  # Caracteres ASCII imprimibles
    return "".join(random.choice(caracteres) for _ in range(longitud))

def agregar_intrones(mensaje, num_intrones_por_caracter=1):
    """Agrega caracteres aleatorios (intrones) entre los caracteres del mensaje."""
    mensaje_con_intrones = ""
    caracteres = [chr(i) for i in range(32, 127)]
    for char in mensaje:
        mensaje_con_intrones += char
        mensaje_con_intrones += "".join(random.choice(caracteres) for _ in range(num_intrones_por_caracter))
    return mensaje_con_intrones

def eliminar_intrones(mensaje_con_intrones, num_intrones_por_caracter=1):
    """Elimina los intrones agregados, extrayendo el mensaje original."""
    mensaje_original = ""
    for i in range(0, len(mensaje_con_intrones), num_intrones_por_caracter + 1):
        if i < len(mensaje_con_intrones):
            mensaje_original += mensaje_con_intrones[i]
    return mensaje_original

def vernam_encode_dinamico(mensaje_original, num_intrones=1):
    """
    "Encripta" el mensaje original generando una clave dinámica de la misma longitud
    y aplicando una lógica similar a la función vernam_encode anterior,
    además de agregar intrones.
    """
    clave = generar_clave_dinamica(len(mensaje_original))
    mensaje_encriptado_lista = list(clave)

    for i in range(len(mensaje_original)):
        caracter_original = mensaje_original[i]
        caracter_clave = clave[i]

        if caracter_original == ",":
            mensaje_encriptado_lista[i] = "?" if caracter_clave != "?" else random.choice([chr(j) for j in range(32, 127) if chr(j) != "?"])
        elif caracter_original == " ":
            mensaje_encriptado_lista[i] = "\\" if caracter_clave != "\\" else random.choice([chr(j) for j in range(32, 127) if chr(j) != "\\"])
        elif caracter_original == "_":
            mensaje_encriptado_lista[i] = caracter_clave
        elif caracter_original == clave[i]:
            mensaje_encriptado_lista[i] = random.choice([chr(j) for j in range(32, 127) if chr(j) != caracter_original])
        else:
            mensaje_encriptado_lista[i] = caracter_original

    mensaje_encriptado_base = "".join(mensaje_encriptado_lista)
    mensaje_encriptado_con_intrones = agregar_intrones(mensaje_encriptado_base, num_intrones)
    return clave + "|||" + mensaje_encriptado_con_intrones # Incluimos la clave al inicio separada por "|||"

def vernam_decode_dinamico(mensaje_completo_encriptado, num_intrones=1):
    """
    Decodifica el mensaje encriptado que incluye la clave y los intrones.
    """
    partes = mensaje_completo_encriptado.split("|||")
    if len(partes) != 2:
        print("Formato de mensaje encriptado incorrecto.")
        return None

    clave = partes[0]
    mensaje_con_intrones = partes[1]
    mensaje_encriptado_base = eliminar_intrones(mensaje_con_intrones, num_intrones)
    mensaje_modificado_lista = list(mensaje_encriptado_base)

    if len(mensaje_encriptado_base) != len(clave):
        print("Las longitudes de clave y mensaje encriptado no son iguales.")
        return None

    for i in range(len(clave)):
        if clave[i] == mensaje_encriptado_base[i]:
            mensaje_modificado_lista[i] = "_"

    mensaje_modificado = "".join(mensaje_modificado_lista)
    mensaje_desencriptado = re.sub(r"[_?\\\\]", lambda m: "" if m.group(0) == "_" else "," if m.group(0) == "?" else " ", mensaje_modificado)
    return mensaje_desencriptado

# Ejemplo de uso dinámico:
mensaje_original_dinamico = "ESTE ES UN MENSAJE SECRETO CON ESPACIOS, COMAS Y _"
num_intrones_a_agregar = 2

mensaje_completo_encriptado = vernam_encode_dinamico(mensaje_original_dinamico, num_intrones_a_agregar)

if mensaje_completo_encriptado:
    partes = mensaje_completo_encriptado.split("|||")
    clave_generada = partes[0]
    mensaje_con_intrones = partes[1]

    print("Mensaje Original:", mensaje_original_dinamico)
    print("Clave Generada:", clave_generada)
    print("Mensaje Encriptado con Intrones:", mensaje_con_intrones)

    mensaje_desencriptado_dinamico = vernam_decode_dinamico(mensaje_completo_encriptado, num_intrones_a_agregar)
    if mensaje_desencriptado_dinamico:
        print("Mensaje Desencriptado:", mensaje_desencriptado_dinamico)
        print("Clave usada:", clave_generada)

⏪ Regresar

Conversación en LinkedIn

"Espero tus comentarios y reflexiones para seguir expandiendo este sistema..."

Discutir en LinkedIn

ESTE NODO ESTÁ ABIERTO AL DIÁLOGO SOBERANO