{"id":39,"date":"2019-12-20T03:45:38","date_gmt":"2019-12-20T03:45:38","guid":{"rendered":"http:\/\/blog.thepragmatic.xyz\/?p=39"},"modified":"2020-02-09T18:50:34","modified_gmt":"2020-02-09T18:50:34","slug":"maquina-de-babage","status":"publish","type":"post","link":"https:\/\/blog.thepragmatic.xyz\/?p=39","title":{"rendered":"M\u00e1quina de Babbage"},"content":{"rendered":"\n<h2>Historia<\/h2>\n\n\n\n<p>A lo largo de los a\u00f1os se ha venido evidenciando la gran importancia de la criptograf\u00eda para la evoluci\u00f3n y el desarrollo del mundo desde sus inicios hasta la actualidad. Desde proteger nuestra informaci\u00f3n confidencial, hasta la protecci\u00f3n y transmisi\u00f3n de mensajes de guerra son aplicaciones \u00fatiles que ha brindado la criptograf\u00eda. Con la codificaci\u00f3n de los cifrados ingenuos se comprender\u00e1 en el contexto hist\u00f3rico la relevancia que tuvo esta herramienta para dicha \u00e9poca. En contexto con el mundo moderno, se corroborar\u00e1 la importancia de utilizar un m\u00e9todo de cifrado seguro con el fin de promover uno de los pilares de la seguridad de la informaci\u00f3n que es la confidencialidad a partir de la sencilla implemenetaci\u00f3n de un cifrado antiguo muy reconocido denominado cifra de Vigen\u00e8re. <\/p>\n\n\n\n<h3>Implementaci\u00f3n<\/h3>\n\n\n\n<p>Se implementa el cifrado vigenere que fue roto por la m\u00e1quina de babage en el lenguaje python.  Se realiza el criptoan\u00e1lisis obteniendo la llave para descifrar el mensaje autom\u00e1ticamente.<br>Se importa del paquete itertools el plugin cycle, con el fin de optimizar funciones que crean iteradores para recorrer de forma eficiente la lista donde se tiene almacenado el alfabeto y para otras utilidades tales como la funci\u00f3n cycle que repite la llave autom\u00e1ticamente.<br> Zip es una funci\u00f3n para reorganizar listas en python. Como par\u00e1metros admite un conjunto de listas. Lo que realmente hace es tomar el elemento i\u00e9simo de cada lista y unirlos en una tupla, despu\u00e9s une todas las tuplas en una lista para manejar mas c\u00f3modamente la asignaci\u00f3n de cada letra cifrada con su correspondiente letra en el alfabeto.<br> Se define el alfab\u00e9tico con que que va a trabajar el cifrado.<br> Hay una funci\u00f3n para cifrar y otra para descifrar, iniciaremos explicando la funci\u00f3n cifrar.<br>Esta recibe dos argumentos, la clave y el mensaje, una vez tenemos tanto el mensaje como la clave vinculadas en una lista en forma de tuplas, por medio de un ciclo se recorre la lista para calcular la letra correspondiente al alfabeto de babage, esto se logra realizar utilizando la siguiente funci\u00f3n matem\u00e1tica en forma general:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" width=\"500\" height=\"93\" src=\"http:\/\/blog.thepragmatic.xyz\/wp-content\/uploads\/2020\/02\/algebraicNatureOfTheVigenereCipher.jpg\" alt=\"\" class=\"wp-image-131\" srcset=\"https:\/\/blog.thepragmatic.xyz\/wp-content\/uploads\/2020\/02\/algebraicNatureOfTheVigenereCipher.jpg 500w, https:\/\/blog.thepragmatic.xyz\/wp-content\/uploads\/2020\/02\/algebraicNatureOfTheVigenereCipher-300x56.jpg 300w\" sizes=\"(max-width: 500px) 100vw, 500px\" \/><\/figure><\/div>\n\n\n\n<h2>C\u00f3digo<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>\nfrom functools import reduce\nfrom itertools import cycle\n\nstring='''wubefiqlzurmvofehmymwtixcgtmpifkrzupmvoirqmmwozmpulmbnyvqqqmvmvjleimhfefnzpsdlppsdlpevqmw\ncxymdavqeefiqcaytqowcxymwmsemefcfwyeyqetrliqycgmtwcwfbsmyfplrxtqyeexmruluksgwfptlrqaerlqvpmvyqycxtw\nfqlmtelsfjpqehmozciwciwfpzslmaeziqvlqmzvppxawcsmzmorvgwwqszetrlqzpbjazvqiyxewwoiccgdwhqmmvowsgntjpf\nppaibiybjutwelqklllmdpyvacdcfqnzpifppksdvptidgxmqqvebmqalkezmgcvkuzkizbzliuammvz'''\ngramLength=4 # Pattern Length\n\nlocations = &#91;]; #Lista para las posiciones de los repetidos\ndistances = &#91;]; # Espaciamientos de los repetidos\ndef longitudLlave(string,gramLength):\t\n    #Asiganacion del subpatron\n    for i in range(len(string)):\n        gram = string&#91;i:i+gramLength];\t\n        # make sure we don't get stuck with shorties\n        if len(gram) &lt; gramLength: break #Validacion final del subpatron\n        locations.append(&#91;]); #Inicializa una lista dentro de una lista vacia.\n    \n        find = string.find(gram,0); # PENDIENTE\n        while find != -1: \n            locations&#91;i].append(find); #Cuando encuentre un patron repetitivo lo a\u00f1ade a lista\n            find = string.find(gram,find+1); #Desplazamiento del subpatron\n        \t\n        \t\n        if len(locations&#91;i]) > 1:  #SI hay dos o mas repeticiones, se calcula la distancia\n             for j in range(1,len(locations&#91;i])):\n                 distances.append(locations&#91;i]&#91;j] - locations&#91;i]&#91;0]) #Hallar la distancia Yf - Yi    \n    miMcd = McdArray(distances); # MCD de las distancias\n    return miMcd  # Tama\u00f1o de la llave\nprint(distances) #\n\n\ndef mcd(a,b):# calcular MCD\n\twhile b != 0:\n\t\tt = b;\n\t\tb = a % b;\n\t\ta = t;\n\treturn a\n\n\ndef McdArray(mcdz):# Si recibe un array y lo calcula\n\n\t\"\"\" Takes the greatest common divisor of an entire array \"\"\"\n\n\tif len(mcdz) &lt; 2: return mcdz&#91;0]; #El MCD es el mismo numero (Cuando el numero es indivisible)\n\t\n\tmiMcd = mcd(mcdz&#91;0],mcdz&#91;1]);\t#Se empieza a hallar el MCD con los dos primeros numeros, con el mod\n\n\tfor i in range(2,len(mcdz)):  # Es el mismo de arriba, pero con las posiciones siguientes hasta el final\t\n\t\tmiMcd = mcd(mcdz&#91;i],miMcd);\n\n\treturn miMcd;\n \ndef separarString(cipherText,longitudLlave): #Se debe separar el texto cifrado en subtextos del tama\u00f1o de la llave.\n        freqList=&#91;] #Lista donde se guardan las divisiones del texo cifrado\n        \n        for i in range(longitudLlave):freqList.append(''); # se inicializa la llave con strings vacios, con el fin de que la reconozca como string y no como int\n\n        for i in range(len(cipherText)):  \n            index=i%longitudLlave  #Correspondencia del texto cifrado con su letra del alfabeto que se cifro.(6%5= ) Toma la letra del texto cifrado y la pone en las posiciones donde deben estar para poderlas separar como las pide babage, se calcula el indice para saber donde se acomoda\"\"\"\n            freqList&#91;index]+=cipherText&#91;i] #Aca se acomodan letras de acuerdo al indice calculado anteriormente\n            \n        return freqList # parte dividida del texto\n\n\ndef calcProb(freqList):\n     cNums = map(chr, range(97, 123))   #Se crea un array con ciertos tipos de datos, array de caracteres del rango 97 al 123 que son las letras minusculas en ASCII\n     prob = &#91;] #Vector de vectores vacio\n     f = range(len(cNums))  #Lista que contiene las letras en ascii\n     p = &#91;.082,.015,.028,.043,.127,.022,.020,.061,.070,.002,.008,.040,.024,.067,.075,.019,.001,.060,.063,.091,.028,.010,.023,.001,.020,.001];  #Probabilidad de ocurrencia del letras en el idioma ingles\n\n     for i in range(len(cNums)): \n         f&#91;i] = freqList.count(cNums&#91;i]) # la cantidad de letras que hay en cada posicion de freq list, parte divididda del texto count( letra que se repite) Para cada subcadena del ciphertext\n         prob.append(0)  #\n\n     print (f)\n\t#parte clave\n     for g in range(len(cNums)): #Para recorrer el vector de probabilidad (prob)\n         #print g\n         for i in range(len(cNums)): #Para moverse en el vector de probabilidades del idioma ingles (p)\n             #print i\n             fig = f&#91;(i+g)% len(f)]  #COmo una sumatoria de la prob del acento ingles por  (OPERACION CLAVE)\n             prob&#91;g] += ((p&#91;i]*fig) \/ float(len(freqList)))   #(OPERACION CLAVE)\n             #print \"pos\",(i+g)% len(f) \n             #print \"prob\",prob  \n             \n             #print(p&#91;i])\n     return prob;  #retorna el vector de probabilidad\n\n\ndef sugKey(prob): # EL metodo que encuentra la llave, da una llave dependiendo de las probabilidades mas altas que hayan en cada vector de vectores\n\t\n\t\"\"\" Suggestes a key, given the maximum likelihood \"\"\"\n\tcNums = map(chr, range(97, 123))\n\n\ti = max(prob) # encuentra el numero mas grande en un array\n      \n\treturn cNums&#91;prob.index(i)]  #devuelve la letra en la posicion i \n\n\ndef criptoAnalisis(string,n):\n\t\n\ty = separarString(string,n) # se separa en partes de acuerdo al tama\u00f1o de la llave\n\t\n\tprobTotal = &#91;] #Probabilidades finales\n\n\tfor i in range(n): \n         m = calcProb(y&#91;i])  #Llama al metodo para calcular las probabilidades\n         probTotal.append(m)\n         print (probTotal)\t\t\n\n\t# suggest the key\n\tkey = \"\";\n\tfor i in range(n):\n\t\tkey += sugKey(probTotal&#91;i]) #COrrespondencia de la letra que tiene mayor probabilidad en el texto cifrado con la de mayor probabilidad del ifioma ingles\n\n\treturn key;  #Retorna la anhelada llave\n\ndef decrypt(ciphermessage, key):\n    pairs = zip(ciphermessage, cycle(key))\n    cNums = map(chr, range(97, 123)) # Crea una lista con los elementos que uno le mande en los argumentos\n    result = ''\n\n    for i in pairs:\n        total = reduce(lambda x, y: cNums.index(x) - cNums.index(y), i) # DOnde se evalua la operacion rara con el mod\n        result += cNums&#91;total % 26]  # operacion de desencriptado de vigenere\n\n    return result\n        \n        \n    \nv=longitudLlave(string,gramLength)\nprint (v)\nx=separarString(string,v)\na=criptoAnalisis(string,v)\nprint (\"llave:\",a)\ndec=decrypt(string,a)\nprint (dec)\n<\/code><\/pre>\n\n\n\n<p><strong>Nota* (Este script fue realizado con python 2)<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Historia A lo largo de los a\u00f1os se ha venido evidenciando la gran importancia de la criptograf\u00eda para la evoluci\u00f3n y [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":113,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[5],"tags":[],"_links":{"self":[{"href":"https:\/\/blog.thepragmatic.xyz\/index.php?rest_route=\/wp\/v2\/posts\/39"}],"collection":[{"href":"https:\/\/blog.thepragmatic.xyz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.thepragmatic.xyz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.thepragmatic.xyz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.thepragmatic.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=39"}],"version-history":[{"count":13,"href":"https:\/\/blog.thepragmatic.xyz\/index.php?rest_route=\/wp\/v2\/posts\/39\/revisions"}],"predecessor-version":[{"id":140,"href":"https:\/\/blog.thepragmatic.xyz\/index.php?rest_route=\/wp\/v2\/posts\/39\/revisions\/140"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.thepragmatic.xyz\/index.php?rest_route=\/wp\/v2\/media\/113"}],"wp:attachment":[{"href":"https:\/\/blog.thepragmatic.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=39"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.thepragmatic.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=39"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.thepragmatic.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=39"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}