Cifrado afín y código Cesar: Encriptación clásica

Si tenía que decir algo confidencial, lo escribía usando el cifrado, esto es, cambiando el orden de las letras del alfabeto, para que ni una palabra pudiera entenderse. Si alguien quiere decodificarlo, y entender su significado, debe sustituir la cuarta letra del alfabeto, es decir, la D por la A, y así con las demás.

Suetonio, Vida de los Césares 56

Entre los cifrados más básicos (y clásicos sin duda), encontramos el famoso código César, nombre que identifica a cierta variante del cifrado afín, el cual es uno de los tantos cifrados de sustitución. Este tipo de cifrados fueron muy populares en tiempos antiguos ya que ofrecían cierto grado de seguridad de manera muy accesible.

Un poco de teoría

En particular, los cifrados afines consisten en reemplazar cada letra del texto a cifrar por otra cuya posición sea el resultado de aplicar la siguiente función:

Formula de encriptacion del cifrado afín

Siendo m la cantidad de elementos del alfabeto utilizado,y a y b números enteros. Otra condición es que los números a y m deben ser coprimos entre ellos (esto es, que no tengan ningún divisor en común mayor a 1).

Para el caso del código César se cumple que a = 1, lo cual reduce la función a:

Función de cifrado CesarDe manera más visual, definimos un alfabeto resultante de aplicar el cifrado César con un desplazamiento (b en las formulas) de valor 3.
Cifrado Cesar

Como se puede ver, la codificación y decodificación con este tipo de alfabetos es bastante sencilla, donde la letra ‘a‘ será sustituida por la ‘d‘, la ‘b‘ por la ‘e‘ y así sucesivamente.

Para decodificar, se aplica una función inversa, de la forma:

Formula general de descifrado del cifrado afín

Donde se aplica el concepto de multiplicador modular inverso (chan!).

Implementando el cifrado afín en JavaScript

Obviamente, si esto aparece en este blog, es porque lo vamos a implementar programaticamente. Siendo el código César la versión más sencilla de este cifrado tenemos que una posible implementación es la siguiente:

function translate(str, offset) {
    // Definimos un alfabeto
    var alpha = 'abcdefghijklmnopqrstuvwxyz';

    // Reducimos el desplazamiento a su
    // menor representacion posible
    offset = offset % alpha.length;

    return str.replace(/./g, function(chr) {
        // Verificamos si existe en el alfabeto
        // caso contrario queda igual
        if(alpha.indexOf(chr) == -1) {
            return chr;
        }

        // Obtenemos el indice actual
        var index = alpha.indexOf(chr);

        // Generamos el nuevo indice
        var newIndex = (index + offset + alpha.length) % alpha.length;

        //console.log(chr, newIndex);
        return alpha[newIndex];
    });
}

translate('hello lovely world', 3); // "khoor oryhob zruog"
translate('khoor oryhob zruog', -3); // "hello lovely world"

En este repositorio, se puede encontrar una implementación un poco más prolija:

var caesar = new crypto.CaesarCypher({
    offset: 10
});

// "Ocdo oc ex otowzvy no dohdy"
caesar.encrypt('Este es un ejemplo de texto');

// "Este es un ejemplo de texto"
caesar.decrypt('Ocdo oc ex otowzvy no dohdy');

Así tambien como para el caso general de cifrado afín (en este repositorio), que nos permite agregarle un multiplicador:

var affine = new crypto.Affine({
    offset: 10,
    modifier: 3
});

// "Wmpw wm sx wlwudra tw pwbpa"
affine.encrypt('Este es un ejemplo de texto');

// "Este es un ejemplo de texto"
affine.decrypt('Wmpw wm sx wlwudra tw pwbpa');

Para este último caso hay que recordar la condición de que el modificador y el largo del alfabeto utilizado deben ser coprimos para garantizar que el cifrado sea reversible:

var broken = new crypto.Affine({ modifier: 13 });

// "ananananananananananananan"
broken.encrypt(crypto.alpha);

Casos más complejos, utilizando claves

Otra manera que tenemos de complejizar el cifrado, además de desplazar y multiplicar la posición, es manipular el alfabeto, alterando el orden de sus caracteres por medio de una clave. Este método puede combinarse con los modificadores vistos previamente (desplazamiento y multiplicadores).

Para una clave ‘cesar‘ el alfabeto a utilizar sería el siguiente:

Alterando el alfabeto mediante una clave

Nuevamente, tenemos una implementación (en este repositorio) con una implementación de este cifrado:

var affine = new crypto.AffineKey({
    key: 'aijoona',
    modifier: 7,
    offset: 12
});

// "Yszy ys hm zyczq ry xihyew"
affine.encrypt('Este es un texto de prueba');

// "Este es un texto de prueba"
affine.decrypt('Yszy ys hm zyczq ry xihyew');

// La clave es simplificada automaticamente
affine.key; //"aijon"

Descifrando mediante análisis de frecuencia

Al transformar los textos contra un único alfabeto, estos cifrados son permeables al análisis de frecuencia, técnica que básicamente cuenta la cantidad de veces que que aparece un carácter dado y busca su equivalencia en apariciones en un texto de referencia del mismo lenguaje que el texto cifrado. Se puede leer más sobre esta técnica en este artículo de la Wikipedia, Análisis de frecuencias.

Leer más:

 


Shortlink: http://goo.gl/opH6m




4 views shared on this article. Join in...

  1. _cronos2 dice:

    Muy bueno el post @Aijoona, me gustó mucho :3 +1
    Por cierto, en esta línea:
    var newIndex = (index + offset + alpha.length) % alpha.length;
    ¿Por qué sumas alpha.length? ¿El resultado no será el mismo?
    Saludos (:

    • Para el caso de que el índice + offset sea positivo si lo es. Distinto es si el resultado index + offset da negativo, donde sumarle el length normaliza la situación siendo que el indíce negativo equivale a restarle n posiciones desde el final.

      Para dejarlo más claro, acá tenés un jsfiddle con esa operación comentada: http://jsfiddle.net/Aijoona/8qxnf/

  2. _cronos2 dice:

    OH SHIT, claro :facepalm: Siempre se me escapan los edge cases XD



Pings to this post

  1. […] Blog « Cifrado afín y código Cesar: Encriptación clásica […]


Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Comment

You may use these tags : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>