Está en la página 1de 11

27/8/2020 Práctica 1

1. Técnicas de cifrado clásico


1. Introducción
El objetivo de esta primera práctica es familiarizarse con las técnicas
empleadas en la criptografía tradicional. Aunque estas técnicas no
resultan de aplicación inmediata en las aplicaciones modernas de
seguridad, su estudio nos permite mostrar las bases de la criptografía
simétrica (o de clave secreta) que sigue teniendo vigencia en la actualidad
y sí que se utiliza en el ámbito de la seguridad de computadores.
Relacionado con las técnicas a estudiar, veremos cómo llevar a cabo
criptoanálisis de las mismas.

2. Algunas definiciones básicas


Sin pretender hacer aquí una descripción exhaustiva de todas las palabras
relacionadas con la criptografía, vamos a describir de forma muy breve algunas de
las más utilizadas:

Criptografía: arte o ciencia que estudia los principios y métodos para alterar el
aspecto de la información, de manera que resulte ininteligible pero que
permita recuperar, cuando se desea su aspecto original.
Texto nativo o normal: el mensaje original que se desea alterar.
Texto cifrado: el mensaje una vez transformado.
Cifrado: algoritmo para transformar el mensaje, se apoya en técnicas de
substitución y transposición.
Clave: información utilizada por el cifrado y que permite variar la salida del
mismo. En el cifrado simétrico la clave es secreta y conocida sólo por el emisor
y el receptor del mensaje.
Cifrar: Convertir texto nativo en texto cifrado empleando un algoritmo de
cifrado y una clave.
Descifrar: Recuperar el texto nativo a partir del texto cifrado empleando el
algoritmo de cifrado y la clave.
Criptoanálisis: Estudio de los principios y métodos para transformar un
mensaje cifrado en su texto original sin conocer la clave.
Criptología: Incluye a la criptología y al criptoanálisis.

1. Cifrado simétrico
El proceso general de cifrado podría representarse de la forma
siguiente:

El cifrado se basa en la utilización de un algoritmo y una clave. La clave


es un valor independiente del texto que se desea cifrar y que permite
obtener diferentes resultados sin variar el algoritmo ni el texto a
cifrar.

Para descifrar se emplea un algoritmo de descifrado y una clave que


puede ser igual o distinta a la que se utilizó para cifrar el mensaje.

En el caso del cifrado simétrico, conocido también como cifrado de


clave secreta o cifrado convencional, la clave es única. Es decir, se
necesita la misma clave para cifrar que para descifrar el mensaje.

Lógicamente para que el cifrado sea efectivo parte de las


herramientas (algoritmos y clave) deben ser conocidas únicamente
www.disca.upv.es/elvira/practicasIR/pracs97-98/prac1/cifrado_clasico.html 1/11
27/8/2020 Práctica 1

por los dos usuarios que intercambian el mensaje. Algunas personas


creen que mantener los algoritmos de cifrado y de descifrado en
secreto mejora la seguridad. Por el contrario, otros piensan que
resulta más seguro hacerlos públicos. Por una parte, lógicamente si el
método de cifrado es secreto el criptoanalista tendrá la dificultad
añadida de averiguarlo. Por otra, hacerlo público permite someterlo a
prueba por parte de una comunidad grande de usuarios. Esto permite
comprobar si el método es efectivo o detectar sus puntos débiles y
hacerlos públicos, para que puedan ser corregidos. Además, es muy
probable que si el método va a ser empleado por un número elevado
de usuarios sea difícil mantenerlo en secreto. Por lo tanto, un buen
método de cifrado debe tener complejidad suficiente para que su
seguridad no radique en mantener ocultos los algoritmos de cifrado y
de descifrado, sino en mantener oculta la clave, que debe ser conocida
únicamente por aquéllos que van a intercambiar el mensaje.

2. Tipos de criptoanálisis
Dependiendo del tipo de información disponible puede llevarse a cabo
criptoanálisis de un texto cifrado de diversas maneras:

Si sólo se dispone de texto cifrado hay que recurrir a ataques estadísticos. Es


la posibilidad más compleja y la que requiere mayor disponibilidad de texto
cifrado para poder llevar a cabo el criptoanálisis con éxito.
Algunas veces se dispone de parejas de texto nativo – texto cifrado. Bien
porque los mensajes resulten conocidos después de un cierto tiempo.
Supongamos por ejemplo, una serie de mensajes cifrados con información
militar que señalan el siguiente punto de un ataque militar a una ciudad, una
vez efectuado el ataque el mensaje pasaría aser conocido. Otra posibilidad es
que el criptoanalista conozca parte de la información que se envía. Por
ejemplo, un fichero codificado en formato postcript siempre empieza con el
mismo patrón de bits, o un empleado de una compañía puede conocer
determinadas palabras de aparición obligada en un fichero con información
comercial que su empresa envía.
En otras ocasiones (las más raras) el criptoanalista puede elegir el texto
nativo y obtener el correspondiente texto cifrado.

1. Técnicas de cifrado clásico


Vamos a describir en este apartado de forma breve las técnicas de
cifrado clásico más representativas. Veremos también, la forma de
llevar a cabo criptoanálisis sobre mensajes cifrados mediante estas
técnicas. Para su estudio las desglosaremos en dos grupos: basadas
en sustitución y basadas en transposición.

1. Técnicas basadas en sustitución

En esta técnica los símbolos que constituyen el texto nativo se


cambian por letras, números u otros símbolos en el mensaje
cifrado. En el caso de que el texto nativo se considere como una
secuencia de bits pueden cambiarse patrones de bits del texto
nativo por patrones diferentes en el texto cifrado.

1. Cifrado de César

Es la forma más antigua de un cifrado de sustitución que se conoce, y también


la más simple. Se llama así porque según la tradición fue el método empleado
www.disca.upv.es/elvira/practicasIR/pracs97-98/prac1/cifrado_clasico.html 2/11
27/8/2020 Práctica 1

por Julio César para cifrar sus mensajes durante algunas campañas de guerra.
Consiste en sustituir cada letra por la que le sigue tres posiciones detrás en el
alfabeto (considerado de forma cíclica). Así, por ejemplo:

A Þ D, B Þ E , CÞ F ..., Z Þ C
Con lo que el mensaje hola se transformaría en ksñd.

Si asignamos un valor numérico a cada letra (a = 1, b = 2, etc.), y


representamos por m un carácter del texto nativo y por c el carácter
equivalente cifrado, el algoritmo puede expresarse como:

c = ( p+3 ) mod 27

que puede generalizarse fácilmente a cualquier valor de desplazamiento k distinto


de 3:

c = ( p+k ) mod 27

El algoritmo de descifrado es:

p = ( c-k ) mod 27

En este caso k es el valor de la clave de cifrado. Como sólo se disponen de 27


claves distintas, el espacio de claves es muy reducido, y el método resulta muy
vulnerable a un ataque por fuerza bruta.

Si juntamos todos los elementos tenemos que se puede emplear la fuerza bruta
para recuperar el texto nativo porque:

1. Se conocen los algoritmos de cifrado y descifrado.


2. Sólo hay 26 claves distintas.
3. Conocemos el lenguaje del texto nativo y lo podemos reconocer fácilmente.

En la mayoría de los ataques a través de la red se puede asumir que el algoritmo de


cifrado es conocido, lo que va a dificultar el ataque es el tamaño del espacio de
claves. La tercera propiedad es también importante, porque lógicamente para
detectar que ha encontrado la clave correcta el atacante debe poder reconocer el
mensaje una vez descifrado. Si por ejemplo, enviamos un fichero ZIP cifrado a
través de la red difícilmente podrá ser reconocido si no se sabe que el fichero está
comprimido y el tipo de fichero que es.

1. Sustitución monoalfabética

Manteniendo la idea de sustituir una letra por otra, una manera de aumentar significativamente el espacio de claves
es permitir la sustitución arbitraria de una letra por otra. Ahora la clave está constituida por la secuencia de las 27
letras del alfabeto cifradas:

ABC DEFGHIJK LMN Ñ O PQ RSTUVXWXYZ

Q AZWSXEDC RFVTGBYHN UJMIK O LPÑ

Por lo tanto, ahora tenemos la posibilidad de 27! claves distintas. Son muchas claves para probar, lo que dificulta
extraordinariamente un ataque por prueba y error de la clave. Sin embargo, este tipo de cifrado puede atacarse por
otra vía. Al cambiar una letra por otra siguen manteniéndose las regularidades del lenguaje. Cada idioma tiene una
frecuencia determinada de aparición de las diferentes letras en un mensaje, de parejas de letras (digramas), etc.

www.disca.upv.es/elvira/practicasIR/pracs97-98/prac1/cifrado_clasico.html 3/11
27/8/2020 Práctica 1

Conociendo estas frecuencias y disponiendo de una cantidad suficiente de texto cifrado, pueden hacerse tentativas
para encontrar el esqueleto del mensaje. Otro enfoque es adivinar una palabra o frase probable.

1. Técnicas basadas en transposición

Las técnicas de sustitución se basan en mantener el orden de los símbolos pero cambiando su representación, otra
posibilidad consiste en mantener el símbolo al cifrar pero cambiando su orden. Tendremos, entonces, un cifrado por
transposición. La forma más común es la transposición columnar. Para llevarla a cabo hay que elegir como clave
una palabra que no contenga letras repetidas. En nuestro ejemplo será NETWORK. La clave nos permite numerar
las columnas, ordenando las letras según su proximidad al comienzo del alfabeto. El texto normal se escribe
horizontalmente, en filas. El texto cifrado se lee por columnas, comenzando por la columna de numeración más baja
y en orden creciente.

N ETWO RK

3167452

e s t o e s u texto normal: estoesunejemplode

n e j e m p l cifradoportransposicion

o d e c ifr

a d o p o r t texto cifrado: sddaculrtsenoariemiopn

ransp o s

ic io n

El primer paso para criptoanalizar este tipo de cifrados es detectar que se trata de una transposición. Para ello hay
que obtener las frecuencias de las letras que aparecen más frecuentemente en el texto cifrado y comprobar si
coinciden con las frecuencias de aparición de esas letras en el idioma en el que esté escrito el mensaje. Si coinciden
aproximadamente, estaremos ante un cifrado por transposición, ya que como hemos dicho cada letra se representa
así misma y únicamente se altera su orden de aparición.

El paso siguiente es de detectar el número de columnas. Esto resultará más sencillo si se conoce la naturaleza del
mensaje y se pueden hacer hipótesis sobre palabras cuya aparición es probable. En ese caso podemos buscar letras
de esa palabra en el mensaje cifrado y comprobar cuál es la letra contigua, su distancia dentro de la palabra original
nos da la longitud de la clave. En nuestro ejemplo anterior si sabemos que la palabra cifrado tiene que aparecer en
el mensaje, analizándolo vemos que la única pareja de letras que contiene la c en el mensaje cifrado es la cu, como
la u no pertenece a la palabra cifrado, la clave debe ser como mínimo de longitud 7. Si hubiéramos conocido una
palabra o frase de longitud mayor que la clave la tarea se hubiese simplificado.

La última tarea es ordenar las columnas. Si la cantidad de columnas es pequeña puede analizarse cada uno de los
pares de columnas k(k-1) para ver si la frecuencia de aparición de los digramas coincide con la del texto normal. La
pareja con concordancia mayor se supone correctamente ubicada. Ahora, se prueba con las restantes columnas cuál
es la sucesora siguiendo el mismo procedimiento. Las columnas antecesoras se encuentran de la misma manera. El
proceso se repite hasta encontrar un posible orden. Probablemente, en este punto el texto normal resultará ya
reconocible, aunque no sea idéntico al original.

1. Trabajo a realizar en esta práctica


Suponed que habéis obtenido los siguientes mensajes cifrados:

www.disca.upv.es/elvira/practicasIR/pracs97-98/prac1/cifrado_clasico.html 4/11
27/8/2020 Práctica 1

Mensaje 1 (fichero cifrado1_pracIR):

hbib cgcocbi ygb vlvcug wxh lv glolvbicu ouguoli lq gutdil (u qb fciloocug

ch) fl qb tbrycgb oug qb ryl flvlbtuv ougloxbi (fugfl ilvcfl lq vlijcfui wxh).

hufltuv lvhlocwcobi lq gutdil lg qb tcvtb qcglb fl uiflglv flvfl qb ryl

cgjuobtuv bq hiuaibtb, u dclg ygb jls cgcocbfu lvxl vcg hbibtlxiuv tlfcbgxl lq

lthqlu fl qb uiflg uhlg.

Mensaje 2 (fichero cifrado2_pracIR):

ne roeras edo arn aeoscci

o u ii cnelseisplu sisae i,osdi e rao oc el aeb nw uaanniei rcocshnauc igr ee tni tL

atii eritaoa ñeaeniveubro uia. rea lag n erc

u atpmsrneeeopdblpeepsecit . re oeesue nes

ietp dsedneri galbdariwop dounhmaau ae s oeraal roromoh rndnslefnpczleplvófiuqeeta d i En,tj opawsebr acreyahpi
aernoceaqsccooedmahmasbsn cermrdor r nadea ccnts

Estos mensajes son fragmentos de un texto (en castellano), para el que la frecuencia de aparición de las distintas
letras se muestra en la tabla1. Escribir un programa que determine la frecuencia de aparición de las distintas letras en
cada uno de los mensajes y a partir de esos valores y de los que se muestran en la tabla 1:

Determinar el tipo de cifrado utilizado en cada caso,


Romperlo, (se sugiere hacer las pruebas de forma automática mediante un
programa)
Averiguad cuál ha sido la clave empleada para cada uno de los cifrados, y
Encontrar los mensajes originales,
E= 13,97
A= 10,10
O= 8,94
S= 7,35
N= 7,22
R= 7,15
I= 6,78
T= 5,48
L= 5,13
C= 5,02
D= 4,89
U= 3,92
M= 3,24
P= 3,23
B= 1,13
V= 1,09
G= 1,00
Q= 0,90
F= 0,88
H= 0,64
Y= 0,59
Z= 0,31
J= 0,31
X= 0,30
W= 0,30
www.disca.upv.es/elvira/practicasIR/pracs97-98/prac1/cifrado_clasico.html 5/11
27/8/2020 Práctica 1

K= 0,04

Apéndice: Clases java para manejo de


ficheros

Class java.io.FileInputStream
java.lang.Object

+----java.io.InputStream

+----java.io.FileInputStream

----------------------------------------------
--------------
public class FileInputStream extends InputStream

A file input stream is an input stream for reading data from a File or from a
FileDescriptor.

See Also: File, FileDescriptor, FileOutputStream

----------------------------------------------
--------------

Contructor index

FileInputStream(File)

Creates an input file stream to read from the specified File object.

FileInputStream(FileDescriptor)

Creates an input file stream to read from the specified file descriptor.

FileInputStream(String)

Creates an input file stream to read from a file with the specified name.

www.disca.upv.es/elvira/practicasIR/pracs97-98/prac1/cifrado_clasico.html 6/11
27/8/2020 Práctica 1

Method Index

available()

Returns the number of bytes that can be read from this file input stream without blocking.

close()

Closes this file input stream and releases any system resources associated with the stream.

finalize()

Ensures that the close method of this file input stream is called when there are no more references to it.

getFD()

Returns the opaque file descriptor object associated with this stream.

read()

Reads a byte of data from this input stream.

read(byte[])

Reads up to b.length bytes of data from this input stream into an array of bytes.

read(byte[], int, int)

Reads up to len bytes of data from this input stream into an array of bytes.

skip(long)

Skips over and discards n bytes of data from the input stream.

----------------------------------------------
--------------

Methods

read

public native int read() throws IOException

Reads a byte of data from this input stream. This method blocks if no input is yet available.

Returns: the next byte of data, or -1 if the end of the file is reached.

read

public int read(byte b[]) throws IOException

www.disca.upv.es/elvira/practicasIR/pracs97-98/prac1/cifrado_clasico.html 7/11
27/8/2020 Práctica 1

Reads up to b.length bytes of data from this input stream into an array of bytes. This method blocks until
some input is available.

Parameters: b - the buffer into which the data is read.

Returns: the total number of bytes read into the buffer, or -1 if there is no more data because the end of
the file has been reached.

read

public int read(byte b[], int off, int len) throws IOException

Reads up to len bytes of data from this input stream into an array of bytes. This method blocks until some
input is available.

Parameters:

b - the buffer into which the data is read.

off - the start offset of the data.

len - the maximum number of bytes read.

Returns: the total number of bytes read into the buffer, or -1 if there is no more data because the end of
the file has been reached.

skip

public native long skip(long n) throws IOException

Skips over and discards n bytes of data from the input stream. The skip method may, for a variety of
reasons, end up skipping over some smaller number of bytes, possibly 0. The actual number of bytes
skipped is returned.

Parameters: n - the number of bytes to be skipped.

available

public native int available() throws IOException

Returns the number of bytes that can be read from this file input stream without blocking.

close

public native void close() throws IOException

Closes this file input stream and releases any system resources associated with the stream.

getFD

public final FileDescriptor getFD() throws IOException

Returns the opaque file descriptor object associated with this stream.

See Also: FileDescriptor

www.disca.upv.es/elvira/practicasIR/pracs97-98/prac1/cifrado_clasico.html 8/11
27/8/2020 Práctica 1

finalize

protected void finalize() throws IOException

Ensures that the close method of this file input stream is called when there are no more references to it.

See Also: close

----------------------------------------------
--------------

Class java.io.FileOutputStream
java.lang.Object

+----java.io.OutputStream

+----java.io.FileOutputStream

----------------------------------------------
--------------
public class FileOutputStream extends OutputStream

A file output stream is an output stream for writing data to a File or to a FileDescriptor.

See Also: File, FileDescriptor, FileInputStream

----------------------------------------------
--------------

Contructor Index
FileOutputStream(File)

Creates a file output stream to write to the specified File object.

FileOutputStream(FileDescriptor)

Creates an output file stream to write to the specified file descriptor.

FileOutputStream(String)

www.disca.upv.es/elvira/practicasIR/pracs97-98/prac1/cifrado_clasico.html 9/11
27/8/2020 Práctica 1

Creates an output file stream to write to the file with the specified name.

FileOutputStream(String, boolean)

Creates an output file with the specified system dependent file name.

----------------------------------------------
--------------Methods Index
close()

Closes this file output stream and releases any system resources associated with this stream.

finalize()

Ensures that the close method of this file output stream is called when there are
no more references to this stream.

getFD()

Returns the file descriptor associated with this stream.

write(byte[])

Writes b.length bytes from the specified byte array to this file output stream.

write(byte[], int, int)

Writes len bytes from the specified byte array starting at offset off to this file output stream.

write(int)

Writes the specified byte to this file output stream.

----------------------------------------------
--------------

Methods
write

public native void write(int b) throws IOException

Writes the specified byte to this file output stream.

Parameters: b - the byte to be written.

Overrides: write in class OutputStream

write

public void write(byte b[]) throws IOException

www.disca.upv.es/elvira/practicasIR/pracs97-98/prac1/cifrado_clasico.html 10/11
27/8/2020 Práctica 1

Writes b.length bytes from the specified byte array to this file output stream.

Parameters: b - the data.

write

public void write(byte b[], int off, int len) throws IOException

Writes len bytes from the specified byte array starting at offset off to this file output stream.

Parameters: b - the data.

off - the start offset in the data.

len - the number of bytes to write.

close

public native void close() throws IOException

Closes this file output stream and releases any system resources associated
with this stream.

getFD

public final FileDescriptor getFD() throws IOException

Returns the file descriptor associated with this stream.

See Also: FileDescriptor

finalize

protected void finalize() throws IOException

Ensures that the close method of this file output stream is called when there are
no more references to this stream.

See Also: close

www.disca.upv.es/elvira/practicasIR/pracs97-98/prac1/cifrado_clasico.html 11/11