- Cifrado por sustitución monoalfabética (Cifrado César)
- Procedimiento de descifración
- Cifrado por sustitución simple polialfabético (Cifrado Vigenère)
- Descifrar
- Cifrado por transposición
- Desencriptación
- Cifrado por sustitución monoalfabética y transposición
- Texto cifrado
- Cifrado de Vigenère más transposición
Cifrado por sustitución monoalfabética (Cifrado César)
El cifrado César, también conocido como cifrado por desplazamiento es un cifrado por sustitución monoalfabética.
La codificación de cifrado Cesar tiene la siguiente forma
$$
E_n(x) = x + n \mod 27
$$
La decodificación se hace de manera similar
$$
D_n(x) = x - n \mod 27
$$
Procedimiento de descifración
Supongamos que tenemos siguiente texto cifrado por el cifrado César con un desplazamiento desconocido
OV M1SZ3YKXKVS2S2 O2 VK ZK13O NO VK M1SZ3YVYQSK 04O 2O NONSMK KV O234NSY NO 2S23OWK2 M1SZ3YQ1KPSMY2 MYX OV PSX NO OXMYX31K1 NOLSVSNKNO2 OX VY2 2S23OWK2 8 1YWZO1 24 2OQ41SNKN 2SX OV MYXYMSWSOX3Y NO SXPY1WKMSYX 2OM1O3K OX OV VOXQ4KTO XY 3OMXSMY 2O MYXYMO O23K Z1KM3SMK MYWY 1YWZO1 Y PY19K1 OV MYNSQY K4X04O O23K O7Z1O2SYX 3SOXO 4X 2SQXSPSMKNY O2ZOMSPSMY NOX31Y NOV K1QY3 3OMXSMY K VK2 ZO12YXK2 04O 2O NONSMKX KV M1SZ3YKXKVS2S2 2O VO2 VVKWK M1SZ3YKXKVS23K2
Si el texto no es aleatorio, con el análisis de frecuencia podemos encontrar la clave $n$ sin mucha dificultad. Sabemos que normalmente en un texto español los vocales aparecen más frecuente.
Hemos creado una función que analiza la frecuencia de aparición de cada letra dada, y observa cual era las letras que tenía una mayor frecuencia de aparición y las distancias entre ellas obtuvimos la “A”.
Con lo cual, sacamos el número -10 para descifrar y 10 para cifrar, en este caso, a la hora de descifrar, es lo mismo poner -10 que 26.
def count(content):
for c in "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789":
print(c, " appears ", content.count(c))
El resultado es siguiente
A appears 0
B appears 0
C appears 0
D appears 0
E appears 0
F appears 0
G appears 0
H appears 0
I appears 0
J appears 0
K appears 37
L appears 1
M appears 27
N appears 18
O appears 51
P appears 6
Q appears 7
R appears 0
S appears 37
T appears 1
U appears 0
V appears 21
W appears 8
X appears 27
Y appears 35
Z appears 12
0 appears 3
1 appears 23
2 appears 34
3 appears 21
4 appears 9
5 appears 0
6 appears 0
7 appears 1
8 appears 1
9 appears 1
Notamos que K, O, S, Y apareces muchas veces y las distancias entre ellos es 4, 4, 6 que justo son las distancias entre a, e, i, o, deducimos que la K es a y el desplazamiento es 10
def encrypt(content, n):
alphabets = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
return "".join([alphabets[(alphabets.index(c) + n + len(alphabets)) % len(alphabets)] if c in alphabets else c for c in content])
Para descifrar el algoritmo que se emplea es el mismo que el del cifrado y n tenemos que usar -10.
El contenido del archivo descifrado es
EL CRIPTOANALISIS ES LA PARTE DE LA CRIPTOLOGIA QUE SE DEDICA AL ESTUDIO DE SISTEMAS CRIPTOGRAFICOS CON EL FIN DE ENCONTRAR DEBILIDADES EN LOS SISTEMAS Y ROMPER SU SEGURIDAD SIN EL CONOCIMIENTO DE INFORMACION SECRETA EN EL LENGUAJE NO TECNICO SE CONOCE ESTA PRACTICA COMO ROMPER O FORZAR EL CODIGO AUNQUE ESTA EXPRESION TIENE UN SIGNIFICADO ESPECIFICO DENTRO DEL ARGOT TECNICO A LAS PERSONAS QUE SE DEDICAN AL CRIPTOANALISIS SE LES LLAMA CRIPTOANALISTAS
Cifrado por sustitución simple polialfabético (Cifrado Vigenère)
El cifrado Vigenère es un cifrado de
sustitución simple poli alfabético. Su
funcionamiento es siguiente
$$
E(X_i) = (X_i + K_i)
\mod L
$$
donde $X_i$ es la letra en la posición $i$ del
texto a cifrar, $K_{i}$ es el carácter de la clave correspondiente
a $X_i$, pues se encuentran en la misma posición, y $L$ es el
tamaño del alfabeto.
Para descifrar realizamos la operación inversa:
$$
D(C_i)
= (C_i - K_i) \mod L
$$
Donde $C_{i}$ es el
carácter en la posición i del texto cifrado, $K_{i}$ viene siendo
el carácter de la clave correspondiente a $C_{i}$, y $L$ el tamaño
del alfabeto.
Descifrar
Para el texto cifrado más corto que la clave es imposible crackearlo, y si la clave no es aleatoria y el texto es sufiencientemente largo entonces se puede obtener información sobre la clave utilizada.
Ahora tenemos un texto cifrado que queremos descifrar
GW CCMR4OVRCWIDMU PS 6E RLREI FP LV GTTPESNZG3E S5E DI FPD3GC LL ZWV5D3S FP S3WVPMVW E2IAXQRRVJKNOD GQY E6 JKY DZ IPNO8XTLR YIDTL3HCOED IP WOD WK3TZQC3 Y CSO0EC WW 3E1YTTDVH UTN ZP EZN9GKXIZRVZ DZ MPQOCQCNI9R UPCCIVL E8 IN WE8KWLJZ RQ 4EXRKNO DI EZN9GG PSEE R2AXXKNA XSOZ R9QRPR 9 JQ2ZVV GW C9HKRO VYP1UZ IU4A Z1R2EDMQY T3IPP U8 WKRN3JKNAYS G3PZGKQIXS FPNEVQ OE6 ETROE XGNN3GQ L LVW RPRDSPLS BYG 3E YIFTCVR CW CCMR4OVRCWIDMU 3E 6IU WLVQC NR3TVZA8ENTSEEU
Adivinar la longitud de la clave
Lo primero que vamos a hacer es buscar las repeticiones de las secuencias, para ello, hemos implementado este script.
from collections import OrderedDict
def cal_distance(content):
alphabets = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
sequences = content.split()
for s in list(OrderedDict.fromkeys(sequences)):
count = sequences.count(s)
if count > 1:
index = sequences.index(s)
lastIndex = len(sequences) - sequences[::-1].index(s) - 1
distance = 0
for i in range(index, lastIndex):
distance += len(sequences[i])
print(s, index, lastIndex, distance)
Y el resultado que obtenemos es
secuencia | distancia |
---|---|
GW | 240 |
CCMR4OVRCWIDMU | 340 |
FP | 35 |
DI | 160 |
DZ | 70 |
3E | 25 |
Siguiendo el proceso de encriptación de Vigenère sabemos que cada letra de clave se vuelve a aplicar otra vez cuando han pasado L caracteres. Deducimos desde aquí́ que la longitud de la clave debe ser como máximo el común divisor de las distancias que hemos encontrado. A ojo creemos que la clave tiene la longitud 5.
Dividir la entrada en longitud de cinco
Cuando ya sabemos la longitud de la clave, dividimos la entrada en bloque de cinco caracteres también, la misma posición de cada bloque se cifra contra la misma posición de la clave. Y vemos si existe algún patrón
def divive_bloque(string):
strings = "".join(string.split())
blocks = [strings[i:i+5] for i in range(0, len(strings), 5)]
for block in blocks:
print(block)
El resultado que tenemos siguiente
GWCCM
R4OVR
CWIDM
UPS6E
RLREI
FPLVG
TTPES
NZG3E
S5EDI
FPD3G
CLLZW
V5D3S
FPS3W
VPMVW
E2IAX
QRRVJ
KNODG
QYE6J
KYDZI
PNO8X
TLRYI
DTL3H
COEDI
PWODW
K3TZQ
C3YCS
O0ECW
W3E1Y
TTDVH
UTNZP
EZN9G
KXIZR
VZDZM
PQOCQ
CNI9R
UPCCI
VLE8I
NWE8K
WLJZR
Q4EXR
KNODI
EZN9G
GPSEE
R2AXX
KNAXS
OZR9Q
RPR9J
Q2ZVV
GWC9H
KROVY
P1UZI
U4AZ1
R2EDM
QYT3I
PPU8W
KRN3J
KNAYS
G3PZG
KQIXS
FPNEV
QOE6E
TROEX
GNN3G
QLLVW
RPRDS
PLSBY
G3EYI
FTCVR
CWCCM
R4OVR
CWIDM
U3E6I
UWLVQ
CNR3T
VZA8E
NTSEE
U
Análisis sobre cada grupo
Para cada posición de la clave formamos cada grupo de entrada y nos encontraría con el problema de cifrado Cesar que podemos hacer el análisis de frecuencia como hemos comentado en su apartado. Agrupamos la salida del resultado anterior con el siguiente script
def group(content):
lines = content.split("\n")
groups = [""] * 5
for line in lines:
for i in range(len(line)):
groups[i] += line[i]
for g in groups:
print(g)
Obtenemos siguientes cincos tiras de cadenas
GRCURFTNSFCVFVEQKQKPTDCPKCOWTUEKVPCUVNWQKEGRKORQGKPURQPKKGKFQTGQRPGFCRCUUCVNU
W4WPLPTZ5PL5PP2RNYYNLTOW3303TTZXZQNPLWL4NZP2NZP2WR142YPRN3QPORNLPL3TW4W3WNZT
COISRLPGEDLDSMIROEDORLEOTYEEDNNIDOICEEJEONSAARRZCOUAETUNAPINEONLRSECCOIELRAS
CVD6EVE3D3Z33VAVD6Z8Y3DDZCC1VZ9ZZC9C88ZXD9EXX99V9VZZD383YZXE6E3VDBYVCVD6V38E
MRMEIGSEIGWSWWXJGJIXIHIWQSWYHPGRMQRIIKRRIGEXSQJVHYI1MIWJSGSVEXGWSYIRMRMIQTEE
Usamos la función que usamos para contar la frecuencia en cifrado Cesar para cada cadena
A appears 0
B appears 0
C appears 8
D appears 1
E appears 3
F appears 5
G appears 6
H appears 0
I appears 0
J appears 0
K appears 10
L appears 0
M appears 0
N appears 3
O appears 2
P appears 6
Q appears 7
R appears 7
S appears 1
T appears 4
U appears 7
V appears 5
W appears 2
X appears 0
Y appears 0
Z appears 0
0 appears 0
1 appears 0
2 appears 0
3 appears 0
4 appears 0
5 appears 0
6 appears 0
7 appears 0
8 appears 0
9 appears 0
El primer caracter de la clave parece que es C.
Repetimos las prueba y finalmente hemos encontrado que la clave es CLAVE.
def frecuency_per_group(text, x):
alphabets = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
text = "".join([b if b in alphabets else "" for b in text])
groups = []
for i in range(x):
groups.append("")
for i in range(len(text)):
groups[i % 5] += text[i]
for i in range(x):
print("columna ", i)
count(groups[i])
Cifrado por transposición
Un cifrado por transposición es un tipo de cifrado en el que unidades de texto plano se cambian de posición siguiendo un esquema bien definido. Es decir, hay una permutación de unidades de texto.
En una transposición columnar, el mensaje se escribe en filas de una longitud fija, la longitud de clave, y luego se lee columna por columna, y las columnas se eligen por el orden alfabético de las letras en la palabra clave.
Por ejemplos con la clave 432143 ciframos WE ARE DISCOVERED. FLEE AT ONCE y un padding al final
6 3 2 4 1 5
W E A R E D
I S C O V E
R E D F L E
E A T O N C
E ? ? ? ? ?
El resultado es
EVLN? ACDT? ESEA? ROFO? DEEC? WIREE
Desencriptación
Supongamos que tenemos siguiente texto cifrado
IA O ECEOISTIOF TEANSAOSU LCTIASAEGNNSOTCCOOAC,UAETUNDEOR CLR EC OS LRNA LTISAEROUD TDTCGO NNAIELS P IICM FIC A C E IMPF DA EIE F ID RE.SOUDNRNSEMPL.CAILTLPI DLD MIA LDO I SE REA NEERNENEEE,OERA RRLGNSPNEICSINEONAPA DAPLS OS EPLEPDCLQ AS S OCNIERBD ISMURS IONCE.LUOIECATOM RO E SINIOC OATOASQ ACAILAIASRNSAEATASI ISAPFC ENDDE MR GDEON M T N C NSA R Z OQTR GAPCTLTI ESSILTIELCAT OS R IGEEAUEERRSE CRLSOTYESDNOIDOORELJTOC PCOEOEIUEXONSIEFEDGC NEE IA SATID
Primero de todo tenemos que fijar la longitud de la clave, con la esquema anterior sabemos que la longitud de la debe ser tiene un divisor de la longitud del texto cifrado. La longitud de nuestro texto cifrado es 462 y sus divisores son 1, 2, 3, 6, 7, 11, 14, 21, 22, 33, 42, 66, 77, 154, 231, 462.
Probamos diferentes longitudes que sea divisor de la longitud del texto usando siguiente función Python
def split(text, x):
alphabets = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
s = ""
n = int(len(text) / x)
for i in range(n):
for j in range(x):
if text[i + j * n] in alphabets:
s += text[i + j * n]
else:
s += "-"
s += " "
s += "\n"
return s
Observamos que en el caso de la longitud 6
I L C E R -
A T A P N O
- I I L S S
- S L E A -
- A T P E R
- E L D A -
O R P C T I
- O I L A G
E U - Q S E
C D D - I E
E - L A - A
O T D S I U
I D - - S E
S T M S A E
T C I - P R
I G A O F R
O O - C C S
F - L N - E
- N D I E -
T N O E N C
E A - R D R
A I I B D L
N E - D E S
S L S - - O
A S E I M T
O - - S R Y
S P R M - E
U - E U G S
- I A R D D
L I - S E N
C C N - O O
T M E I N I
I - E O - D
A F R N M O
S I N C - O
A C E E T R
E - N - - E
G - E L N L
N A E U - J
N - E O C T
S C - I - O
O - O E N C
T E E C S -
C - R A A P
C I A T - C
O M - O R O
O P R M - E
A F R - Z O
C - L R - E
- D G O O I
U A N - Q U
A - S E T E
E E P - R X
T I N S - O
U E E I - N
N - I N G S
D F C I A I
E - S O P E
O I I C C F
R D N - T E
- - E O L D
- R O A T G
C E N T I C
L - A O - -
R S P A E -
- O A S S N
E U - Q S E
C D D - I E
- N A A L -
O R P C T I
S N L A I A
- S S I E -
L E - L L S
R M - A C A
N P O I A T
A L S A T I
- - - S - D
Observamos el resultado obtenido y ordenamos a ojo y obtenemos el orden de aparición es Columna 4, Columna 2, Columna 6, Columna 1, Columna 5, Columna 3, su clave númerica es 426351 y la clave alfabético es DBFCEA, la cual se obtiene por orden de columnas tomando como referencia la posición de letra en su alfabeto.
Cifrado por sustitución monoalfabética y transposición
Si nos tocamos hacer una desencriptación combinada de cifrado por César y transposition que haríamos. Si tenemos siguiente texto cifrado:
TX W NLJJFZJJWWXJ HWQXTY3JXISTNITTWJQOYTH UHTJTJNZJ2TSXNJKJILH SJJ NF XFYNDJUQJUIHQV FX X THSNJWGI NXRZWX NTSHJ QZTNJHFYTR WT J XNSNTH TFYTFXV FHFNQFNFXNF T JHJTNXYNTK YJFSXFTXZ QHYNFXFJLSSXTYHHTTFH ZFJYZSIJTW HQW JH TX QWSF WSXFJFYFXN NXFUKH JSIIJ RW LIJTS R Y S H SXF W 4 TVYW LFUHYQYN JXXNQYNJQHFY HFNQYQUN IQI RNF QIT N XJ WJF SJJWSJSJJJ TJWF WWQLSXUSJNHXNSJTSFUF IFUQX TX QYNXFJWTZI YIYHLT SSFNJQX U NNHR KNH F H J NRUK IF JNJ K NI WJ XTZISWSXJRUQ
Texto cifrado
Primero desencriptamos la parte de sustitución monoalfabética, usamos la estrategia que hemos empleado en el cifrado César, contamos la frecuencia de aparición de cada letra.
A appears 0
B appears 0
C appears 0
D appears 1
E appears 0
F appears 37
G appears 1
H appears 27
I appears 18
J appears 51
K appears 6
L appears 7
M appears 0
N appears 37
O appears 1
P appears 0
Q appears 21
R appears 8
S appears 27
T appears 35
U appears 12
V appears 3
W appears 23
X appears 34
Y appears 21
Z appears 9
0 appears 0
1 appears 0
2 appears 1
3 appears 1
4 appears 1
5 appears 0
6 appears 0
7 appears 0
8 appears 0
9 appears 0
Observamos que la clave de encriptación de sustitución es muy probable que sea 5.
Desencriptamos primero el cifrado monoalfabética usando la llave y la función que usemos en cifrado de César. Ahora tenemos siguiente texto:
OS R IGEEAUEERRSE CRLSOTYESDNOIDOORELJTOC PCOEOEIUEXONSIEFEDGC NEE IA SATI8EPLEPDCLQ AS S OCNIERBD ISMURS IONCE LUOIECATOM RO E SINIOC OATOASQ ACAILAIASIA O ECEOISTIOF TEANSAOSU LCTIASAEGNNSOTCCOOAC UAETUNDEOR CLR EC OS LRNA\x00RNSAEATASI ISAPFC ENDDE MR GDEON M T N C NSA R Z OQTR GAPCTLTI ESSILTIELCAT\x00CAILTLPI DLD MIA LDO I SE REA NEERNENEEE OERA RRLGNSPNEICSINEONAPA DAPLS OS\x00LTISAEROUD TDTCGO NNAIELS P IICM FIC A C E IMPF DA EIE F ID RE SOUDNRNSEMPL
Seguimos con los pasos que hemos explicado en cifrado por transposición, hallamos primero la longitud de la clave a partir de la longitud de texto cifrado que es 462, y sus divisores son 1, 2, 3, 6, 7, 11, 14, 21, 22, 33, 42, 66, 77, 154, 231, 462. Probamos esas posibilidades y encontramos que con la longitud 6, obtenemos siguiente resultado
- E I R C L
O P A N A T
S L - S I I
- E - A L S
R P - E T A
- D - A L E
I C O T P R
G L - A I O
E Q E S - U
E - C I D D
A A E - L -
U S O I D T
E - I S - D
E S S A M T
R - T P I C
R O I F A G
S C O C - O
E N F - L -
- I - E D N
C E T N O N
R R E D - A
L B A D I I
S D N E - E
O - S - S L
T I A M E S
Y S O R - -
E M S - R P
S U U G E -
D R - D A I
N S L E - I
O - C O N C
I I T N E M
D O I - E -
O N A M R F
O C S - N I
R E A T E C
E - E - N -
L L G N E -
J U N - E A
T O N C E -
O I S - - C
C E O N O -
- C T S E E
P A C A R -
C T C - A I
O O O R - M
E M O - R P
O - A Z R F
E R C - L -
I O - O G D
U - U Q N A
E E A T S -
X - E R P E
O S T - N I
N I U - E E
S N N G I -
I I D A C F
E O E P S -
F C O C I I
E - R T N D
D O - L E -
G A - T O R
C T C I N E
- O L - A -
- A R E P S
N S - S A O
E Q E S - U
E - C I D D
- A - L A N
I C O T P R
A A S I L N
- I - E S S
S L L L - E
A A R C - M
T I N A O P
I A A T S L
8 S - - - -
Observamos que el orden de columnas es: 316542 y por lo tanto, la clave de la transposición es BFAEDC por la misma razón que explicamos que cifrado por transposición, ahora sobre el texto desencriptado aplicamos esta transposición y obtenemos texto original.
Cifrado de Vigenère más transposición
Primero buscamos la longitud de la clave, la longitud de texto cifrado es 460, y sus divisores son 1, 2, 4, 5, 10, 20, 23, 46, 92, 115, 230, 460. Y con la longitud de la clave 5 obtenemos las siguientes columnas
P J T R -
1 T U A 1
V Y F S T
M T X 5 -
- - L U L
P I 4 - T
Y I M A -
Q - N 2 W
W T Z T Q
V I L 2 -
P R - - S
I I M N Q
Y F - - I
2 E 3 Q Y
I I Z M -
3 - 5 Y I
3 M Z - A
P H Z 4 V
A T O Q 4
S N K - 1
- N T R V
N L - V Q
- - Q P E
N S K 4 1
- W I D 4
Y P G I Q
R O F S L
- - P T S
3 1 S N -
X 0 6 F E
- 0 - R B
R Z R R X
- - 3 0 Z
W R G Q 5
- Q A X O
E Q 0 W -
0 - H O W
V N N E U
- Y Y Q W
S E - N T
F 1 R K X
- V O X Y
P M P Y R
R I - N -
- - P T Q
Z R N I R
Y W E T -
C - 1 Y R
- N K - 1
H S P W -
J 0 O - N
L M 5 - T
C U Z 4 N
- N K C N
- Z R 4 W
M O X 4 U
Q - O T -
2 Z C - A
P J T O -
1 O N - O
S - A Y 5
P 7 E X -
E 1 N 8 -
S U Z T R
6 T V I -
- P S 7 M
N N - O 3
N 0 I K Q
- N D J Z
N 0 2 N E
Z N V - C
T I M 2 0
R T - L L
O - L 1 W
J T - K 4
T 0 I - N
Y - I A -
M 3 - 4 U
I S Z 5 S
J - Q - 5
D 0 R P -
A I Q Y P
- - F P T
1 R T 1 U
T A Y V F
- S T 0 X
P R - X L
A - T X Y
4 F - I K
N 0 Y N W
5 L Q T Q
B L X - -
Y con la aparición de los espacios podemos deducir el orden, reordenamos las columnas
J T - P R
T U 1 1 A
Y F T V S
T X - M 5
- L L - U
I 4 T P -
I M - Y A -
N W Q 2
T Z Q W T
I L - V 2
R - S P -
I M Q I N
F - I Y -
E 3 Y 2 Q
I Z - I M -
5 I 3 Y
M Z A 3 -
H Z V P 4
T O 4 A Q
N K 1 S -
N T V - R
L - Q N V -
Q E - P
S K 1 N 4
W I 4 - D
P G Q Y I
O F L R S -
P S - T
1 S - 3 N
0 6 E X F
0 - B - R
Z R X R R - 3 Z - 0
R G 5 W Q
Q A O - X
Q 0 - E W -
H W 0 O
N N U V E
Y Y W - Q
E - T S N
1 R X F K
V O Y - X
M P R P Y
I - R N -
P Q - T R
N R Z I W
E - Y T -
1 R C Y N
K 1 - S P -
H W 0 O
N J - M 5
T L - U Z
N C 4 N K
N - C Z R
W - 4 O X
U M 4 - O - Q T Z C
A 2 - J T -
P O O N
O 1 - A 5
S Y 7 E -
P X 1 N -
E 8 U Z R
S T T V -
6 I P S M - 7 N - 3
N O 0 I Q
N K N D Z -
J 0 2 E
N N N V C
Z - I M 0
T 2 T - L
R L - L W
O 1 T - 4
J K 0 I N
T - I - Y
A 3 - U M
4 S Z S I
5 - Q 5 J -
0 R - D
P I Q P A
Y - F T -
P R T U 1
1 A Y F T
V S T X -
0 R - L P
X - T Y A
X F - K 4
I 0 Y W N
N L Q Q 5
T L X - -
Agrupamos en 5 grupos que debemos tener en cuenta las letras que no están en el alfabeto no cifra por Vigenère, usamos función que hemos comentado en cifrado por Vigenère frecuency_per_group y analizando las frecuencias de vocales hemos obtenido que la clave.