CoCalc Public Filesex_Vigenere.ipynbOpen in with one click!
Author: J Soto
Views : 21

Criptosistema de Vigenère

In [15]:
A = AlphabeticStrings() k=A("THEFORCE") C=VigenereCryptosystem(A,len(k)) m=A.encoding("""Master Kenobi, you disappoint me. Yoda holds you in such high esteem. Surely you can do better!""") M=C.enciphering(k, m) print m print M
MASTERKENOBIYOUDISAPPOINTMEYODAHOLDSYOUINSUCHHIGHESTEEMSURELYYOUCANDOBETTER FHWYSIMIGVFNMFWHBZEUDFKRMTIDCUCLHSHXMFWMGZYHVYKKALWYSVOWNYIQMPQYVHRICSGXMLV

## Ataque al criptosistema de Vigenère

In [7]:
A=AlphabeticStrings() mensaje="KIEPELUJTBPUIVTVBOYKNLZDTGEAVMKQMVUJGQLETRQBRWFVKSMISBBEXWEIALXXKCYDOVXQLZASAVWKPSQPOVEQMVQBOWEKDBASWPTLBHYAAVLLXABPABBGGWOWNBKWLWEPWMEDBYZKWBASMGEDEQLETRQKFAFGDSNQTQOWECEPMGPSRGTAKVHOLHTWTQTEUFAGEJNLBAGOTXESRHQIPBTLBCZECIGLKSEESBWMMQTLIVDSGRUPATBSGPXQEAAWBGFDEZXOTWFENOYGKMAQMGPAEZTWSLBKTDBAAZXVGCIYOVYMLWAJIALGVZQWRBXEIHMPIWGAVOZPRMLALH" M=A.encoding(mensaje)
In [13]:
# Funciones: def encontrar_todos(cadena, subcadena): lugares=[] inicial=0 pos=cadena.find(subcadena, inicial) while pos != -1 : lugares=lugares+[pos] inicial=pos+len(subcadena) pos=cadena.find(subcadena,inicial) return lugares def diferencias(l): if len(l)>1: return [l[i]-l[i-1] for i in range(1,len(l))] else: return [] def agregar_diferencias_letras(M): L=flatten([diferencias(encontrar_todos(str(M),c)) for c in "ABCDEFGHIJKLMNOPRSTUVWXYZ"]) m=max(L) return [(i,L.count(i)) for i in range(1,m+1)] def ordenar_por_frecuencias(l): return sorted(l, key=lambda x: x[1]) # digrafos únicos en el mensaje def digrafos(M): return list( set ( [M[i:i+2] for i in range(len(M)-1)])) def contar_diferencias_digrafos(N): M=str(N) L=flatten([diferencias(encontrar_todos(M,c)) for c in digrafos(M)]) s=[(p, L.count(p)) for p in list(set(L))] return sorted(s , key= lambda x: x[0]) def IC(texto, alfabeto=None): """ Calcula el índice de coincidencia de un texto respecto de un alfabeto dado. Por ejemplo, para calcular el IC de un texto en español, habría que pasar el argumento alfabeto="ABCDEFGHIJKLMN~OPQRSTUVWXYZ" Si no se pasa ningún argumento, el alfabeto se define como el conjunto de símbolos que aparecen en el texto. Ejemplo: """ letras = alfabeto if alfabeto else list(set(texto)) N = len(letras) l = len(texto) denominador = 1/float(l*(l-1)) S = 0 for c in letras: n = texto.count(c) S += n*(n-1) return N*S*denominador def romper(s, n): """ Rompe el texto en n tiras. """ return [s[i::n] for i in range(n)] def partir_cadena(M, n): L=[ [] for i in range(n)] for i in range(len(M)): L[i % n] += str(M[i]) # Convertido a cadena return map(lambda x: "".join(x), L)
In [16]:
print M sM = str(M) for i in range(2,20): print i, mean([IC(r, alfabeto="ABCDEFGHIJKLMNOPQRSTUVWXYZ") for r in romper(sM, i)])
FHWYSIMIGVFNMFWHBZEUDFKRMTIDCUCLHSHXMFWMGZYHVYKKALWYSVOWNYIQMPQYVHRICSGXMLV 2 1.23281175913 3 1.96444444444 4 1.43326453388 5 1.04 6 2.60606060606 7 0.840404040404 8 1.49861111111 9 1.74250440917 10 1.26904761905 11 1.55324675325 12 3.30158730159 13 0.533333333333 14 0.619047619048 15 1.56 16 1.57083333333 17 0.81568627451 18 2.45555555556 19 0.912280701754
In [18]:
A=AlphabeticStrings() S=ShiftCryptosystem(A) def candidatos(sub_strings): L=[] LL=[] for C in sub_strings: L += [S.brute_force(S.encoding( C ), ranking="chisquare")[ :3 ] ] for h in L: LL+=[map( lambda x: A.gens()[x[0]], h)] return LL C=candidatos(partir_cadena(M,8)) C
[[T, Z, U], [H, L, S], [E, D, A], [F, W, M], [Z, K, O], [R, N, O], [I, O, S], [E, T, F]]
In [11]:
V=VigenereCryptosystem(A,8) V.deciphering(A('TOMWAITS'),A(M))
RUSTEDBRANDYINADIAMONDGLASSEVERYTHINGISMADEFROMDREAMSTIMEISMADEFROMHONEYSLOWANDSWEETONLYTHEFOOLSKNOWWHATITMEANSTEMPTATIONICANTRESISTWELLIKNOWTHATSSHEISMADEOFSMOKEBUTIVELOSTMYWAYSHEKNOWSTHATIAMBROKEBUTIMUSTPLAYTEMPTATIONICANTRESISTDUTCHPINKANDITALIANBLUESHEISTHEREWAITINGFORYOUMYWILLHASDISAPPEAREDNOWCONFUSIONISSOCLEARTEMPTATIONICANTRESIST
In [ ]: