tag:blogger.com,1999:blog-18464936613970271372024-03-16T02:12:49.815+01:00El blog de García Larragan y CíaMikel García Larraganhttp://www.blogger.com/profile/03118239524461394157noreply@blogger.comBlogger733125tag:blogger.com,1999:blog-1846493661397027137.post-51192051963274860632023-12-12T11:25:00.003+01:002023-12-16T09:02:46.154+01:00Forense (XXIII): Solución Reto InCTF 2020 "LOGarithm"<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkfMQEOA9M-YEtS8qB72zcP_bVVAdBatZNM0Ve8hDvRNYixzRgsJNrUStmSZDdOSRvbxd_TqnXfGYig0nIjl3tAVeyZgUaWMcNDmyAGcy9wAXLXGJ3H8mXj3UGdZdMDiCPsaR_5T_mt3XzpIOgPPN8GsyvXWPWcRG3jA0AcZCmfxu-SlfY52fIDcOk/s210/Retos%20InCTF.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="210" data-original-width="200" height="210" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkfMQEOA9M-YEtS8qB72zcP_bVVAdBatZNM0Ve8hDvRNYixzRgsJNrUStmSZDdOSRvbxd_TqnXfGYig0nIjl3tAVeyZgUaWMcNDmyAGcy9wAXLXGJ3H8mXj3UGdZdMDiCPsaR_5T_mt3XzpIOgPPN8GsyvXWPWcRG3jA0AcZCmfxu-SlfY52fIDcOk/s1600/Retos%20InCTF.png" width="200" /></a></div>En este post la <b><span style="color: #45818e;">solución a uno de los retos de análisis forense de InCTF 2020</span></b>.<div><br /></div><div>Este reto tiene el título <span style="color: #45818e;"><b>"LOGarithm"</b></span> y mi valoración sobre su <b><span style="color: #45818e;">dificultad</span></b> es <span><span style="background-color: white;"><b><span style="color: #45818e;">★</span></b></span></span><span><span style="color: #45818e;"><span style="color: black; font-family: inherit;"><span style="color: #45818e;"><span style="color: black; font-family: inherit;"><span style="color: #45818e;"><b style="color: black;"><span style="color: #45818e;">★</span></b></span></span><b style="color: black;"><span style="color: #45818e;">★</span></b></span></span><b style="color: black;"><span style="color: #45818e;">★</span></b>☆</span></span>.</div><div><p></p><span><span style="background-color: white; font-family: inherit;"><span style="color: #333333;">Su </span><b><span style="color: #45818e;">enunciado</span></b><span style="color: #333333;">, que me he permitido traducir al español, dice lo siguiente:</span></span></span><br /><span><span style="background-color: white;"><span style="color: #333333; font-family: inherit;"><br /></span></span></span><div class="MsoNormal"><span style="line-height: 18.4px;"><span style="color: #333333;">Nuestra empresa detectó una gran brecha en la seguridad de los datos. Creemos que el sistema de nuestro director Mike seguramente estaba comprometido. Según la declaración de Mike, él asegura que estaba hablando de temas muy confidenciales con otro empleado en el momento de esta brecha. Nuestro equipo recopiló rápidamente tanto el volcado de memoria como el tráfico de red del sistema. Se especula que el adversario podría haber extraído los datos confidenciales de forma bastante "segura". ¿Puedes averiguar qué estaba enviando Mike?</span></span></div><div class="MsoNormal"><span style="line-height: 18.4px;"><span style="color: #333333;"><br /></span></span></div><div class="MsoNormal"><span style="line-height: 18.4px;"><span style="color: #333333;">Como recursos asociados al reto se proporcionan dos archivos: Evidence.vmem y capture.pcapng </span></span></div><div class="MsoNormal"><span style="line-height: 18.4px;"><span style="color: #333333;"><br /></span></span></div><div class="MsoNormal"><span style="color: #45818e; font-weight: bold;">Solución:</span><span> Comienzo por el primero de los archivos, y lo primero que hago, como siempre que se analiza un volcado de memoria con 'Volatility', es identificar el perfil del sistema de la máquina de la que se realizó la adquisición: volatility_2.6_win64_standalone -f Evidence.vmem imageinfo:</span></div></div><div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpvTZ_TJdv4OGPvO0xLWn0niYzzNt2l3-2MRU7iA15FFuxWIVlUON6KLvVZcPpEkOMd_kL5YwtKhQ1Ni5NO4nzpSPWxWxr93NOPEMFCbhhdC6oJZQHn6OYrRZHwFkOMOxKnLCGSTMfawrapWZMbjGlTPWlK6FQqAc94E3fs8yFHIxvMJyQdcYo7-Mb/s594/volatility_1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="300" data-original-width="594" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpvTZ_TJdv4OGPvO0xLWn0niYzzNt2l3-2MRU7iA15FFuxWIVlUON6KLvVZcPpEkOMd_kL5YwtKhQ1Ni5NO4nzpSPWxWxr93NOPEMFCbhhdC6oJZQHn6OYrRZHwFkOMOxKnLCGSTMfawrapWZMbjGlTPWlK6FQqAc94E3fs8yFHIxvMJyQdcYo7-Mb/s16000/volatility_1.png" /></a></div><div class="MsoNormal">A continuación, listo los procesos en formato de árbol para analizar qué dependencias existen entre ellos, de manera que se pueda conocer si un posible <i>malware</i> está haciendo uso de otros procesos del sistema: volatility_2.6_win64_standalone --profile Win7SP1x64 -f Evidence.vmem pstree</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPNykOZy3k6HP9AOJpI_5EUE5XfEzKMubelhmnUWFz5TP_jmIDHgzycVF4tgoOdvBVdNb4oIlKhFFdoKD34RVnJt75tBNLAwxuNXezJe6IEg25ovzmJjdlOJyUIxSE6PHc7ImShOCzveRuF1uHQeXOi0aYm_ULXZqQYJFyuyM2_ydNjdLysaSMHgEN/s609/volatility_2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="285" data-original-width="609" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPNykOZy3k6HP9AOJpI_5EUE5XfEzKMubelhmnUWFz5TP_jmIDHgzycVF4tgoOdvBVdNb4oIlKhFFdoKD34RVnJt75tBNLAwxuNXezJe6IEg25ovzmJjdlOJyUIxSE6PHc7ImShOCzveRuF1uHQeXOi0aYm_ULXZqQYJFyuyM2_ydNjdLysaSMHgEN/s16000/volatility_2.png" /></a></div>Y veo dos procesos sospechosos que podrían haber sido los responsables de la exfiltración de datos.</div><div class="MsoNormal"><br /></div><div class="MsoNormal">Seguidamente, intento ver qué archivo se ejecutó en python, y veo un script con un nombre más que sospechoso: volatility_2.6_win64_standalone --profile Win7SP1x64 -f Evidence.vmem -p 2216 cmdline</div><div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgj_IMLPQYJ1xZ36MFW8G5wH0ZjcxEYy5B-FmShhaGBkNPTQQqq6W4pHZ5sMChrkB_gYtQtsReCuy7T4Na0Qwd4E4FGEygnCiWtlmAjGUOrbE2o-jIhR6TCmwmWHB_osvspf_KIB755fwf2nwm_93Zrralk9yng4qHIVui2D2AtuqQ-5JGkf_BP4lW7/s624/volatility_3.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="78" data-original-width="624" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgj_IMLPQYJ1xZ36MFW8G5wH0ZjcxEYy5B-FmShhaGBkNPTQQqq6W4pHZ5sMChrkB_gYtQtsReCuy7T4Na0Qwd4E4FGEygnCiWtlmAjGUOrbE2o-jIhR6TCmwmWHB_osvspf_KIB755fwf2nwm_93Zrralk9yng4qHIVui2D2AtuqQ-5JGkf_BP4lW7/s16000/volatility_3.png" /></a></div><div class="MsoNormal">Para analizar el contenido de este script (keylogger.py), lo extraigo. En primer lugar, obtengo la dirección física del fichero (PHYSOFFSET): volatility_2.6_win64_standalone --profile=Win7SP1x64 -f Evidence.vmem filescan | findstr keylogger.py</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJolRu2VMrl48W8mU9UQXmDULKd4lue_h4QykIvte2fXqv5-XnOxjJ6KDOJBagAj4p_kxVtXqOG0MwreJkZ8nXmMKKEacmhobUUsfhUAySGpqH-Uq7YwCt3t-64iefZLqe2fUShGa9J2Up82SYmQ1F0WWVMcsmceqJwBd9yjGXHpJ5hL-mFRkgPklz/s625/volatility_4.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="69" data-original-width="625" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJolRu2VMrl48W8mU9UQXmDULKd4lue_h4QykIvte2fXqv5-XnOxjJ6KDOJBagAj4p_kxVtXqOG0MwreJkZ8nXmMKKEacmhobUUsfhUAySGpqH-Uq7YwCt3t-64iefZLqe2fUShGa9J2Up82SYmQ1F0WWVMcsmceqJwBd9yjGXHpJ5hL-mFRkgPklz/s16000/volatility_4.png" /></a></div><div class="MsoNormal">Y, posteriormente, lo extraigo: volatility_2.6_win64_standalone -f Evidence.vmem --profile=Win7SP1x64 dumpfiles --physoffset=0x000000003ee119b0 --dump-dir=script_Python</div><div class="MsoNormal"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiflckHb80BsZ-1pPWeNcIt7SJZmlnS_GtgKPElRtVc1JmQbZpm6sCnNzJXxiTszoiFXDK1hyphenhyphenJIx4fmH4q4ECvhtLfTMdpIV-yoKFtCFnB_QicB8D6Qno02a89e_vHz-a4nscVCMekZVtRK1ZNE9nn62IILQf88rC-vW7yH6nLlXG_-3VSVtsUtAcci/s966/script_python.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="966" data-original-width="620" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiflckHb80BsZ-1pPWeNcIt7SJZmlnS_GtgKPElRtVc1JmQbZpm6sCnNzJXxiTszoiFXDK1hyphenhyphenJIx4fmH4q4ECvhtLfTMdpIV-yoKFtCFnB_QicB8D6Qno02a89e_vHz-a4nscVCMekZVtRK1ZNE9nn62IILQf88rC-vW7yH6nLlXG_-3VSVtsUtAcci/s16000/script_python.png" /></a></div><div class="MsoNormal">Al analizar el código fuente del <i>keylogger</i>, puedo ver que el script recopila todas las pulsaciones del teclado y las guarda en el archivo C:/Users/Mike/Desktop/key.log (que se eliminará una vez finalizado el proceso). Cuando se termina la captura de teclas se realiza una XOR de la captura realizada con el contenido de una variable de entorno (t3mp), el resultado se codifica en base64 y se envía a través del puerto 1337 al servidor C2 del atacante (18.140.60.203).</div><div class="MsoNormal"><br /></div><div class="MsoNormal">Extraigo el valor de la variable de entorno (t3mp) con el que se ha hecho XOR con la captura de teclas pulsadas: volatility_2.6_win64_standalone>volatility_2.6_win64_standalone -f Evidence.vmem --profile=Win7SP1x64 envars | findstr t3mp</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEge7kUpZVBkCZIOJSMEAAQLuYqyNscsRD8AbMdNE1XDjJ8AWwWUd-GBivBAADCWdOyG2vbUUheyMnH6JIj0FMpyLVpGNEqsQ_QdYOIZibZBZmnNTd77iejToNnCjVwArSYqzB208XcoAHq6U0Wct5Lwsfe-jDZOXj_Qldl-Vh06iFwuiko_PqiSN9fg/s618/volatility_5.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="105" data-original-width="618" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEge7kUpZVBkCZIOJSMEAAQLuYqyNscsRD8AbMdNE1XDjJ8AWwWUd-GBivBAADCWdOyG2vbUUheyMnH6JIj0FMpyLVpGNEqsQ_QdYOIZibZBZmnNTd77iejToNnCjVwArSYqzB208XcoAHq6U0Wct5Lwsfe-jDZOXj_Qldl-Vh06iFwuiko_PqiSN9fg/s16000/volatility_5.png" /></a></div><div class="MsoNormal">Y ya, para averiguar los datos exfiltrados, únicamente debo hacerme con los datos codificados en base64 que se enviaron al servidor C2 del atacante (18.140.60.203) por el puerto 1337, información que puedo obtener de la captura de tráfico de red que se proporciona en el reto (capture.pcapng).</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi37_xhRT5yD4w1t5-2jtggcqiN2AL1YOlXCb47YLMaESnPGqgbV7-cjYjd8VNoVow0bUvo7eeSFnjZXO6hIS5nwRe7qnNhDO3EUd_2UuvrwJ1mMuwL0eJUuIH4ZPhwWDcVI0ZY5SxpB6NY7W0GJU4QiJ2RJpGheuFFcBICQ3asQKxCmUL0Rxo-zbr8/s605/wireshark.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="219" data-original-width="605" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi37_xhRT5yD4w1t5-2jtggcqiN2AL1YOlXCb47YLMaESnPGqgbV7-cjYjd8VNoVow0bUvo7eeSFnjZXO6hIS5nwRe7qnNhDO3EUd_2UuvrwJ1mMuwL0eJUuIH4ZPhwWDcVI0ZY5SxpB6NY7W0GJU4QiJ2RJpGheuFFcBICQ3asQKxCmUL0Rxo-zbr8/s16000/wireshark.png" /></a></div><div class="MsoNormal">Y, finalmente, utilizo la herramienta <i>on-line</i> ‘Cyberchef’ para obtener los datos exfiltrados:</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBiTh3KR5j-e7hXXbWg6RzLctyZJHFxKyGB_xzTtxbhqjOx7MYM0JCGCJK_A9ipegaNsbwi7FRewFDaK-Wv6qOXfr7mubVdRYhukovTWSQpyeRqeGiWuX5rShPCSxK3a6vVLMPec8MYf0NtqcVMGiQFr3x8Pi8wzr319XSO1rmo-aKD5dNEIxHd_Wm/s621/cyberchef.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="243" data-original-width="621" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBiTh3KR5j-e7hXXbWg6RzLctyZJHFxKyGB_xzTtxbhqjOx7MYM0JCGCJK_A9ipegaNsbwi7FRewFDaK-Wv6qOXfr7mubVdRYhukovTWSQpyeRqeGiWuX5rShPCSxK3a6vVLMPec8MYf0NtqcVMGiQFr3x8Pi8wzr319XSO1rmo-aKD5dNEIxHd_Wm/s16000/cyberchef.png" /></a></div><div class="MsoNormal">Y entre los datos exfiltrados encontramos la solución a este reto: inctf{n3v3r_TrUs7_Sp4m_e_m41Ls}</div></div>Mikel García Larraganhttp://www.blogger.com/profile/03118239524461394157noreply@blogger.com0tag:blogger.com,1999:blog-1846493661397027137.post-78108649953617807702023-12-11T10:40:00.018+01:002023-12-14T09:06:46.588+01:00Forense (XXII): Solución Reto CyberCamp 2018 "Vacaciones"<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8_S4NFEc3QfwxgJEe8zEVLD6RV-rqcJEqJOVB8krXlgF8BGdDOlMr62bEpLPOWYg9NLULt_68pQLeVNJ-xc8yISJfD8VYRc7tTSVOBv01aYa7irRnup0TtNJFgQNFtQEI69vu2DH-5umYXmToGAoQw4zsahAuhKHym9i9a63etpAF5JdN9DMHIi0I/s210/Retos%20Cybercamp.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="210" data-original-width="200" height="210" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8_S4NFEc3QfwxgJEe8zEVLD6RV-rqcJEqJOVB8krXlgF8BGdDOlMr62bEpLPOWYg9NLULt_68pQLeVNJ-xc8yISJfD8VYRc7tTSVOBv01aYa7irRnup0TtNJFgQNFtQEI69vu2DH-5umYXmToGAoQw4zsahAuhKHym9i9a63etpAF5JdN9DMHIi0I/s1600/Retos%20Cybercamp.png" width="200" /></a></div>En este post la <b><span style="color: #45818e;">solución a uno de los retos de análisis forense de Cybercamp 2018 Online</span></b>.<div><br /></div><div>Este reto tiene el título <span style="color: #45818e;"><b>"Vacaciones"</b></span> y mi valoración sobre su <b><span style="color: #45818e;">dificultad</span></b> es <span><span style="background-color: white;"><b><span style="color: #45818e;">★</span></b></span></span><span><span style="color: #45818e;"><span style="color: black; font-family: inherit;"><span style="color: #45818e;"><span style="color: black; font-family: inherit;"><span style="color: #45818e;"><b style="color: black;"><span style="color: #45818e;">★</span></b></span></span><b style="color: black;"><span style="color: #45818e;">★</span></b></span></span><b style="color: black;"><span style="color: #45818e;">★</span></b>☆</span></span>.</div><div><p></p><span><span style="background-color: white; font-family: inherit;"><span style="color: #333333;">Su </span><b><span style="color: #45818e;">enunciado</span></b><span style="color: #333333;"> dice lo siguiente:</span></span></span><br /><span><span style="background-color: white;"><span style="color: #333333; font-family: inherit;"><br /></span></span></span><div class="MsoNormal"><span style="line-height: 18.4px;"><span style="color: #333333;">Por orden de un juez, se ha intervenido un equipo en casa de un sospechoso ciberdelincuente, por suerte su portátil aún se encontraba encendido cuando se produjo la detención. Se sabe que ha intentado eliminar pruebas, pero creemos que aún es posible obtener alguna. ¿Cuál era su nick en la red? (Respuesta: flag{NICK}).</span></span></div><div class="MsoNormal"><span style="line-height: 18.4px;"><span style="color: #333333;"><br /></span></span></div><div class="MsoNormal"><span style="line-height: 18.4px;"><span style="color: #333333;">Como recursos asociados al reto se proporcionan dos archivos: volume.bin y dump.elf </span></span></div><div class="MsoNormal"><span style="line-height: 18.4px;"><br /></span></div><div class="MsoNormal"><span style="line-height: 18.4px;"><span style="color: #45818e; font-weight: bold;">Solución:</span><span> Comienzo por el primero de los archivos, que parece ser una imagen o volcado de un disco, y lo monto con la herramienta ‘FTK Imager’:</span></span></div><div class="MsoNormal"><span style="line-height: 18.4px;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPZZ89Q0btsFoZgVt3WjRDYBBoE6VKqnC5oVlF9YXMfyZP8KwmVNHMzAbWimLUPURv0GMsir8BRfMfHyd6rSuwcpYwWdkJQGlUFjHwFTE41UfdsklgOFRAya1OiTyAWLkTL6FXlieNIX9-6cOcxqq1nCM3ejkTzvbP8pifsejRh0NXLhSRjmKsceU/s617/FTK_Imager_1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="464" data-original-width="617" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPZZ89Q0btsFoZgVt3WjRDYBBoE6VKqnC5oVlF9YXMfyZP8KwmVNHMzAbWimLUPURv0GMsir8BRfMfHyd6rSuwcpYwWdkJQGlUFjHwFTE41UfdsklgOFRAya1OiTyAWLkTL6FXlieNIX9-6cOcxqq1nCM3ejkTzvbP8pifsejRh0NXLhSRjmKsceU/s16000/FTK_Imager_1.png" /></a></div>Y pide que se formatee el disco para poder usarlo, por lo que no reconoce su contenido.</span></div><div class="MsoNormal"><span style="line-height: 18.4px;"><br /></span></div><div class="MsoNormal"><span style="line-height: 18.4px;">Añado la imagen (volume.bin) como evidencia en la herramienta ‘FTK Imager’:</span></div><div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwftKOzDd2KaN4I2fPEdbPKPWiAKPctb7Jv8sQjt2PyvLGLEanD_zeaofwmrYGAobgIX4OF0CzjEraZvCmjL_R5TwlNvFRjlXmRUVs5eJb5y0qXOmGIRE_lLZwwg3fgi0NRY2SsV-HNcKNCNiFBKTL3nyAdn99qM3sR0TbjAeBkiH4DpuUlWDVGOcC/s615/FTK_Imager_2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="265" data-original-width="615" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwftKOzDd2KaN4I2fPEdbPKPWiAKPctb7Jv8sQjt2PyvLGLEanD_zeaofwmrYGAobgIX4OF0CzjEraZvCmjL_R5TwlNvFRjlXmRUVs5eJb5y0qXOmGIRE_lLZwwg3fgi0NRY2SsV-HNcKNCNiFBKTL3nyAdn99qM3sR0TbjAeBkiH4DpuUlWDVGOcC/s16000/FTK_Imager_2.png" /></a></div>Y veo que el volumen está cifrado usando LUKS (del inglés, <i>‘Linux Unified Key Setup’</i>), una especificación de cifrado estándar originalmente destinado para Linux pero actualmente multiplataforma. En concreto el algoritmo de cifrado utilizado es AES en modo de operación CBC.</div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwnfqsjAiN7NE5k2yxNuLYuDrCgupBxG_aNd3emIOJJafXrZV3OMG2jbGeCQkUu0c9e50O60Kj9hLzOD-WMkwlCxKHoeR96ZXeUHAPknGwoeVrSLgfu5ijjfSBuL31RMaWjVd-AHwLtl0zwuLs3TbNgSu1MUQXRjmF42k6ksat51HW8U1sHXA7NLSi/s620/FTK_Imager_3.png" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="337" data-original-width="620" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwnfqsjAiN7NE5k2yxNuLYuDrCgupBxG_aNd3emIOJJafXrZV3OMG2jbGeCQkUu0c9e50O60Kj9hLzOD-WMkwlCxKHoeR96ZXeUHAPknGwoeVrSLgfu5ijjfSBuL31RMaWjVd-AHwLtl0zwuLs3TbNgSu1MUQXRjmF42k6ksat51HW8U1sHXA7NLSi/s16000/FTK_Imager_3.png" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;"></td></tr></tbody></table><div>Lo siguiente que hago es utilizar ‘kpartx’ para detectar las particiones de la imagen de disco (volume.bin) y generar en /dev/mapper/loopXpX los mapeos necesarios para poder montarlas como si fueran particiones en un disco real: $ sudo kpartx -a -v volume.bin</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjucqVqn96y7sLaWPTXYtjwWWU-DE0aI1bp9CsP1YWdUa_C7cwxUYfiysDzaKardS38MmaUqKd3k2DBZNSHDLQfMeV2ZMSV4Q9vECGXalHtnsIAkkEC9PNHSJ1uUho3CtUdR2rnyigIrIr5PiX30jNr7JmNCYF_w-teOsXzeS4nUcc84geOXGKjw7Mg/s524/kpartx.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="49" data-original-width="524" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjucqVqn96y7sLaWPTXYtjwWWU-DE0aI1bp9CsP1YWdUa_C7cwxUYfiysDzaKardS38MmaUqKd3k2DBZNSHDLQfMeV2ZMSV4Q9vECGXalHtnsIAkkEC9PNHSJ1uUho3CtUdR2rnyigIrIr5PiX30jNr7JmNCYF_w-teOsXzeS4nUcc84geOXGKjw7Mg/s16000/kpartx.png" /></a></div><div>Ahora puedo utilizar ‘cryptsetup’ para obtener más información sobre el cifrado de la partición: $ sudo cryptsetup luksDump /dev/mapper/loop0p1</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXJXq0alBmjqY4LyL7KS-OQzUaAXMMu8fdPebFLXmWt9bHwEJRUomkfwn89ThjAXgmZCU8p9qr00D-MAcAK9z0aqp2SXe4ximb-bCcy55F9GLRdDcPMhvBdBOknhgmkqqcScA5LaQ-S8GildihnVub7nFYHAR6smSFVo00Vo_02sRsXpqxFCsVkuI8/s525/cryptsetup.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="195" data-original-width="525" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXJXq0alBmjqY4LyL7KS-OQzUaAXMMu8fdPebFLXmWt9bHwEJRUomkfwn89ThjAXgmZCU8p9qr00D-MAcAK9z0aqp2SXe4ximb-bCcy55F9GLRdDcPMhvBdBOknhgmkqqcScA5LaQ-S8GildihnVub7nFYHAR6smSFVo00Vo_02sRsXpqxFCsVkuI8/s16000/cryptsetup.png" /></a></div><div>Se trata de un cifrado AES con una clave de 128 bits.</div><div>Ahora me centro en el otro archivo que se proporciona (dump.elf). Por su extensión podría tratarse sólo de un ejecutable de Linux y así parece confirmarlo 'file', pero por su nombre, su tamaño, lo que de él se extrae con ‘binwalk’ (muchísimas más cosas que un archivo .elf) y porque en el enunciado se dice que: “por suerte su portátil aún se encontraba encendido cuando se produjo la detención”, bien podría tratarse de un volcado de la memoria del portátil del ciberdelincuente.</div><div><br /></div><div>Si es así, puedo utilizar ‘aeskeyfind’ para intentar localizar claves AES de 128 y 256 bits en la imagen de memoria capturada:</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeMdQRiUDu0w_WuVSjyFfbEZ4SPqKte0pBn3uvO7J2r8YPWqzethP0cs604wldbujsYBKKy10fqtOwqjhjSk3hl9CF7s4yjIRJq2E3zpwqnwO4IbPdXlbZH-xgGiw7Akzb6cdcGAkAjpVrNI2tryQTd_ODXFm_ezeWxfd3H-hmLf2IcTP9_1H-28V2/s606/aeskeyfind.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="77" data-original-width="606" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeMdQRiUDu0w_WuVSjyFfbEZ4SPqKte0pBn3uvO7J2r8YPWqzethP0cs604wldbujsYBKKy10fqtOwqjhjSk3hl9CF7s4yjIRJq2E3zpwqnwO4IbPdXlbZH-xgGiw7Akzb6cdcGAkAjpVrNI2tryQTd_ODXFm_ezeWxfd3H-hmLf2IcTP9_1H-28V2/s16000/aeskeyfind.png" /></a></div>Y tal y como se muestra en la figura anterior, se obtienen dos claves: la primera de 256 bits y la segunda de 128 bit. Como antes he llegado a la conclusión de que se trata de un cifrado AES de 128 bits, la clave maestra correcta es la segunda.</div><div><br /></div><div>Ahora utilizo 'cryptsetup' para descifrar la partición, pero para ello previamente debo convertir la clave hallada de hexadecimal a binario:<div><div><br /></div><div>$ echo "84 bc d9 8c fc f2 de db 26 06 35 bf ca a9 a4 7d" | xxd -r -p > key</div><div><br /></div><div>$ sudo cryptsetup --master-key-file key luksOpen /dev/mapper/loop0p1 volume_descifrado</div><div><br /></div><div>A continuación monto la partición: $ sudo mount /dev/mapper/volume_descifrado /mnt, pero no veo contenido; ya decía el enunciado que “Se sabe que ha intentado eliminar pruebas”:</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiI4a061FJbp7XStu__8W2HmHLwWKuAl9KVHhrEHjves_hTeV4tWqdTZA61ig68iAi5UCEKaUsEDcBkSFzYWIpspK1cLP6nY7wAkVg5QeOsRSDZgboZfy9LMyWUzO3KIay1ay7F4XmXmt9aljnKvMwMftUQvhaR2z6r4O1z7RT2hOcQJGxcZFcRURCs/s481/ls.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="89" data-original-width="481" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiI4a061FJbp7XStu__8W2HmHLwWKuAl9KVHhrEHjves_hTeV4tWqdTZA61ig68iAi5UCEKaUsEDcBkSFzYWIpspK1cLP6nY7wAkVg5QeOsRSDZgboZfy9LMyWUzO3KIay1ay7F4XmXmt9aljnKvMwMftUQvhaR2z6r4O1z7RT2hOcQJGxcZFcRURCs/s16000/ls.png" /></a></div>No obstante, si su contenido no ha sido sobrescrito podré recuperarlo.</div><div><br /></div><div>Para intentar recuperar el contenido utilizo 'scalpel'; una herramienta rápida de <i>‘file carver’</i> que extrae los archivos que coinciden con determinadas cabeceras y finales: $ sudo scalpel -v /dev/mapper/volume_descifrado</div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhREvmfMtWAXu3jdLiO740wq6yG2D32vc3JO8RCuUyqMEU_efT5mpFevKMP9HDf9NSeyLeRdHtYXPO3pcTNMtMWrMBUYhrZOM55Lo-Fug-qFnJB_DD-uJkl3nJ8ppXut3DZWwdaCK2O9JJNPc19r8h9ZR-lgatHDQCqZR9p66S1t75FoV5UrMdD_OQA/s622/scalpel.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="187" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhREvmfMtWAXu3jdLiO740wq6yG2D32vc3JO8RCuUyqMEU_efT5mpFevKMP9HDf9NSeyLeRdHtYXPO3pcTNMtMWrMBUYhrZOM55Lo-Fug-qFnJB_DD-uJkl3nJ8ppXut3DZWwdaCK2O9JJNPc19r8h9ZR-lgatHDQCqZR9p66S1t75FoV5UrMdD_OQA/s16000/scalpel.png" /></a></div><div>Y veo que ha extraído un archivo comprimido (00000000.zip), pero está protegido con una contraseña.</div><div><br /></div><div>Intento 'crackear' la contraseña del archivo .zip con 'John the Ripper'.</div><div><br /></div><div>zip2john 00000000.zip > 00000000.hash</div><div><br /></div><div>john --wordlist=rockyou.txt 00000000.hash</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMuv45vmAg2i1B5ALzxfXO5XmXKZoVMB115eVgsJtlYn2xkTu_Ag3kGhx9fjiWArZ-pLP7D5x6P9T8dVyM9S-L9HsycRZwgQvL3cY-NwshQB3g26i5U9uasU-nDnQisx07Ki553HgsFNZRKHyeZRzP-CHf3SN05JxC_gcCCm09zzGslvmxBJ_P39Kl/s607/john.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="146" data-original-width="607" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMuv45vmAg2i1B5ALzxfXO5XmXKZoVMB115eVgsJtlYn2xkTu_Ag3kGhx9fjiWArZ-pLP7D5x6P9T8dVyM9S-L9HsycRZwgQvL3cY-NwshQB3g26i5U9uasU-nDnQisx07Ki553HgsFNZRKHyeZRzP-CHf3SN05JxC_gcCCm09zzGslvmxBJ_P39Kl/s16000/john.png" /></a></div><div>Accedo al contenido del archivo.zip y en el archivo secret.txt, utilizando la contraseña obtenida (iloveyou), puedo ver la flag o solución a este reto:</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghEzSwwJb8PKCRWhyoIg7euyo3sPo5bFIEHmcHmPHVzQyoZNgAKB3dymiU_l4ACVr9zmqsxRwPO6IuZzY2FBwQLA9iY5T3ZTB2CLCiFS9dqg6NikDH2dNAqrvsXiRUBfgyWgjf4Jj8Cw98LlL4IGud8ctWhGiRIJb49ub5JkWzpd9URrau0IbWeB2d/s620/soluci%C3%B3n.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="90" data-original-width="620" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghEzSwwJb8PKCRWhyoIg7euyo3sPo5bFIEHmcHmPHVzQyoZNgAKB3dymiU_l4ACVr9zmqsxRwPO6IuZzY2FBwQLA9iY5T3ZTB2CLCiFS9dqg6NikDH2dNAqrvsXiRUBfgyWgjf4Jj8Cw98LlL4IGud8ctWhGiRIJb49ub5JkWzpd9URrau0IbWeB2d/s16000/soluci%C3%B3n.png" /></a></div><div>En el enunciado se solicita que se dé la respuesta en formato flag{NICK}, por lo que la solución es: flag{_Z3R0.C00L!_}</div></div></div>Mikel García Larraganhttp://www.blogger.com/profile/03118239524461394157noreply@blogger.com0tag:blogger.com,1999:blog-1846493661397027137.post-44125117737405049382023-08-22T12:56:00.025+02:002023-08-23T08:48:54.100+02:00Criptografía (CCXCIV): Intercambio de clave de Diffie-Hellman en curvas elípticas (ECDH)<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjawnOUv9xLnz4q9jh2TAgIdwxufvPkSaf_ML3tz1Aqg3X8BFJ3KdXXJVB80jPxqw6dNQhwDpqSTgnFVDqWT_ZQmrQ1_yRlD41l40vEx4epu0er8G3HJyfkQD2KIekZgU79Gea3owa9OZLzeY0B_JL8JBJr0qeYTCYUX8WtLK3OEM3_a5PzIt9VBdyK/s179/Criptograf%C3%ADa%20de%20curva%20el%C3%ADptica.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="179" data-original-width="144" height="179" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjawnOUv9xLnz4q9jh2TAgIdwxufvPkSaf_ML3tz1Aqg3X8BFJ3KdXXJVB80jPxqw6dNQhwDpqSTgnFVDqWT_ZQmrQ1_yRlD41l40vEx4epu0er8G3HJyfkQD2KIekZgU79Gea3owa9OZLzeY0B_JL8JBJr0qeYTCYUX8WtLK3OEM3_a5PzIt9VBdyK/s1600/Criptograf%C3%ADa%20de%20curva%20el%C3%ADptica.png" width="144" /></a></div><p style="text-align: left;"><span style="font-family: inherit;">Ya expliqué en <a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxx-intercambio-de.html"><span style="color: #2b00fe;">este post</span></a> en qué consiste el protocolo de <a href="https://es.wikipedia.org/wiki/Diffie-Hellman"><span style="color: #2b00fe;">intercambio de clave de Diffie-Hellman</span></a> y cómo se lleva a efecto entre dos usuarios. Además, también decía que<span> este <a href="https://es.wikipedia.org/wiki/Protocolo_criptogr%C3%A1fico"><span style="color: #2b00fe;">protocolo criptográfico</span></a> <span style="background-color: white;">se utiliza generalmente para el intercambio seguro de una clave, que será empleada en una sesión para el cifrado y descifrado utilizando un <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_sim%C3%A9trica"><span style="color: #2b00fe;">criptosistema de clave simétrica o secreta</span></a>, entre dos </span><span style="background-color: white;">interlocutores a través de un canal inseguro</span><span style="background-color: white;">, c<span><span style="color: #292929;">omo puede ser Internet, y, por tanto, su objetivo</span><span> es salvaguardar</span></span></span></span><span><span style="background-color: white;"> el secreto de la <a href="https://es.wikipedia.org/wiki/Clave_de_sesi%C3%B3n"><span style="color: #2b00fe;">clave de sesión</span></a> si las comunicaciones entre ambos son interceptadas por un tercero</span><span style="background-color: white;">.</span></span></span></p><p style="text-align: left;"></p><p style="text-align: left;"><span style="font-family: inherit;"><span style="background-color: white;"><span style="color: #292929;">Pues bien, </span><b><span style="color: #45818e;">en esta entrada voy a explicar cómo se lleva a cabo </span></b></span><b><span style="color: #45818e;">el</span></b> <a href="https://es.wikipedia.org/wiki/Elliptic-curve_Diffie-Hellman"><span style="color: #2b00fe;">protocolo de Diffie-Hellmann en Curvas Elíptic</span></a><span><a href="https://es.wikipedia.org/wiki/Elliptic-curve_Diffie-Hellman"><span style="color: #2b00fe;">as</span></a> <span style="color: #292929;">(<i>'</i></span></span><span><span style="background-color: white; color: #202122;"><i>Elliptic curve Diffie–Hellman' o</i> <i>'ECDH'</i> por sus siglas en inglés)</span><span style="background-color: white;"><span style="color: #292929;">.</span></span></span></span></p><p style="text-align: left;"><b style="font-family: inherit;"><span style="color: #45818e;">Sean A
(Alicia) y B (Bernardo) los dos interlocutores que desean intercambiar una
clave de sesión</span></b><span style="font-family: inherit;">.</span></p><p style="text-align: left;"><span style="font-family: inherit;">A y B <b><span style="color: #45818e;">actuarían de la siguiente manera:</span></b></span></p><p style="text-align: left;"><span style="font-family: inherit;"><span style="background-color: white;">1.-</span><b style="background-color: white;"><span style="color: #45818e;"> Se ponen de acuerdo para escoger un</span></b><span style="background-color: white;"> </span><a href="https://es.wikipedia.org/wiki/Cuerpo_finito" style="background-color: white;"><span style="color: #2b00fe;">cuerpo finito</span></a><span style="background-color: white;"> </span><span style="background-color: white;"><b style="color: #45818e;">ℤ𝑝, una </b><a href="https://es.wikipedia.org/wiki/Curva_el%C3%ADptica"><span style="color: #2b00fe;">curva elíptica</span></a><b style="color: #45818e;"> 𝔼 definida sobre él y un punto </b><i style="color: #45818e; font-weight: bold;">‘P’</i><b style="color: #45818e;"> de la misma.</b></span></span></p><p style="text-align: left;"><span style="font-family: inherit;"><span style="background-color: white;"><b style="color: #45818e;"><span style="color: black; font-weight: 400;">Sin entrar en mayores disquisiciones matemáticas, decir que el punto </span><i style="color: black; font-weight: 400;">'P'</i><span style="color: black; font-weight: 400;"> seleccionado desempeña el papel de elemento generador (</span><i style="color: black; font-weight: 400;">'g'</i><span style="color: black; font-weight: 400;">) del grupo cíclico de puntos de la curva que van a formar el grupo delimitado con sus operaciones.</span></b></span></span></p><p class="MsoNormal" style="text-align: left;"><span style="background-color: white; font-family: inherit;">Cualquier punto de la curva es un generador de un grupo cíclico, pero para lograr mayor seguridad conviene que éste incluya a todos los puntos de la curva.</span></p><p class="MsoNormal" style="text-align: left;"><span style="background-color: white;">¿Cómo nos aseguramos de elegir un punto </span><i style="background-color: white;">'P'</i><span style="background-color: white;"> que sea un elemento generador del resto de puntos de la curva?, es decir, que si lo vamos multiplicando por los sucesivos valores desde 1 a </span><i style="background-color: white;">p + 1</i><span style="background-color: white;"> vayamos obteniendo todos los puntos de la curva, punto en el infinito (</span><span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #202122;">𝒪</span><span style="background-color: white;">) incluido. Pues, si no lo he entendido mal, basta con decir que en el caso de que la curva tenga un número de puntos (orden o valor cardinal de la curva) que sea un número primo nos aseguramos de que todos los puntos de la misma tienen el mismo orden (escalar entero positivo más pequeño que multiplicado por el punto da como resultado el punto en el infinito), que coincide con el orden de la curva, y, por tanto, nos aseguramos de que cualquiera de ellos puede utilizarse como elemento generador del resto de puntos de la curva, razón por la cual en criptografía se suelen utilizar curvas cuyo orden, es decir, cuyo número de puntos (punto en el infinito, </span><span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #202122;">𝒪</span><span style="background-color: white;">, incluido) sea un número primo.</span></p><p class="MsoNormal" style="text-align: left;"><span style="color: #45818e; font-family: inherit;"><b>Estos datos son públicos</b></span><span style="font-family: inherit;">, es decir, pueden ser conocidos por cualquiera, incluso por un atacante que intercepte las comunicaciones en las que A y B los eligen.</span></p><p class="MsoNormal" style="text-align: left;"><span style="font-family: inherit;"><span style="font-family: inherit;">2.- </span><b style="font-family: inherit;"><span style="color: #45818e;">A escoge un número entero aleatorio <i>'a'</i></span></b><span style="font-family: inherit;"> de orden de magnitud </span><i style="font-family: inherit;">'p'</i><span style="font-family: inherit;">, que será secreto (sólo ella debe conocerlo), </span><span style="font-family: inherit;"><span><b style="color: #45818e;">y envía a B el resultado de la operación </b><i style="color: #45818e; font-weight: bold;">a * P</i>.</span></span></span></p><p class="MsoNormal" style="text-align: left;"><span style="font-family: inherit;"><span style="font-family: inherit;">3.- De forma análoga, </span><b style="font-family: inherit;"><span style="color: #45818e;">B escoge un número entero aleatorio <i>'b'</i></span></b><span style="font-family: inherit;"> de orden de magnitud </span><i style="font-family: inherit;">'p</i><span style="font-family: inherit;">', que será secreto (sólo él debe conocerlo), </span><span style="font-family: inherit;"><span><b style="color: #45818e;">y envía a A el resultado de la operación </b><b style="color: #45818e; font-style: italic;">b * P</b>.</span></span></span></p><p class="MsoNormal" style="text-align: left;"><span style="font-family: inherit;"><span style="font-family: inherit;">4.- En este momento, </span><b style="font-family: inherit;"><span style="color: #45818e;">tanto A como B están ya en disposición de calcular la clave de sesión (<i>'k'</i>) compartida sin intercambiarla por ningún sitio</span></b><span style="font-family: inherit;">. Es decir, </span><b style="font-family: inherit;"><span style="color: #45818e;">A puede calcular el secreto compartido</span></b><span style="font-family: inherit;"> (la clave de sesión) a partir del número que le ha mandado B en el paso anterior (</span><i style="font-family: inherit;">b * P</i><span style="font-family: inherit;">) y el número secreto que ella ha escogido en el paso 2 (</span><i style="font-family: inherit;">'a'</i><span style="font-family: inherit;">), es decir, sin más que realizar la siguiente operación: </span><b style="font-family: inherit;"><span style="color: #45818e;"><i>k =</i> (<i>b * P</i>) * <i>a</i>; mientras que B puede calcularlo</span></b><span style="font-family: inherit;"> a partir del número que le ha mandado A en el paso 2 (</span><i style="font-family: inherit;">a * P</i><span style="font-family: inherit;">) y el número secreto que él ha escogido en el paso 3 (</span><i style="font-family: inherit;">'b'</i><span style="font-family: inherit;">), es decir, sin más que realizar la siguiente operación: </span><span style="font-family: inherit;"><span><i style="color: #45818e; font-weight: bold;">k = (a * P) * b</i>.</span></span></span></p><p class="MsoNormal" style="text-align: left;"><span style="font-family: inherit;"><span style="font-family: inherit;">Veamos </span><span style="font-family: inherit;"><span><b style="color: #45818e;">un ejemplo</b>:</span></span></span></p><p class="MsoNormal" style="text-align: left;"><span style="font-family: inherit;"><span style="font-family: inherit;">1.- A y B acuerdan utilizar la curva elíptica 𝔼: </span><i style="font-family: inherit;">y<sup>2</sup> = </i><i style="font-family: inherit;"><span style="line-height: 18.4px;">x<sup>3</sup> - 1 x + 1</span></i><span style="font-family: inherit;"> definida sobre ℤ</span><span style="font-family: inherit; font-size: 8.5pt; line-height: 13.0333px;"><span style="font-family: inherit;">13</span></span><span style="font-family: inherit;">, y como punto </span><i style="font-family: inherit;">‘P’</i><span style="font-family: inherit;"> = (6, 4).</span></span></p><p class="MsoNormal" style="text-align: left;"><span style="font-family: inherit;"><span style="font-family: inherit;">Con el script en Python que puse en </span><a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-ccxci-curva-eliptica-sobre.html" style="font-family: inherit;"><span style="color: #2b00fe;">este post</span></a><span style="font-family: inherit;">, vemos que el número de puntos de esta curva es 19 (18 más el punto en el infinito):</span></span></p><div class="separator" style="clear: both; text-align: center;"><span><span style="background-color: white; font-family: inherit;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpK8DXS5WYVZKTJuWq12NDsrtzrSJuBUgPdzRmwEfPiG0xKg7fATxjIYkOAWlDuvhj56fxfwspaXob7lX9WS2MmBcEpGecivtxPkjIP1cfRDfcix4Me8OUk-8AEmrFkWykjtpN48HJL_OcHLJ9Y6Lne9Yk5LvNRAU0u7aDDKQuPsak1RII5ncimWwe/s640/ECDH_1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="480" data-original-width="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpK8DXS5WYVZKTJuWq12NDsrtzrSJuBUgPdzRmwEfPiG0xKg7fATxjIYkOAWlDuvhj56fxfwspaXob7lX9WS2MmBcEpGecivtxPkjIP1cfRDfcix4Me8OUk-8AEmrFkWykjtpN48HJL_OcHLJ9Y6Lne9Yk5LvNRAU0u7aDDKQuPsak1RII5ncimWwe/s16000/ECDH_1.png" /></a></span></span></div><span><span style="background-color: white;"><span style="font-family: inherit; line-height: 115%;">2.- A
escoge 11 como número secreto y envía a B el resultado de <i>a * P</i>. Con el
script en Python que puse en <a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-ccxciii-multiplicacion.html"><span style="color: #2b00fe;">esta entrada</span></a>, vemos que 11 * (6, 4) = (1, 12).</span></span></span><p></p><p><span style="font-family: inherit;"></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: inherit;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWsVScnB8vMuuK5RS1McKNdB4paWTKZV44kpXcmJbplQ4jjPgBG_FvBD-gzG7pw_AYBB4afOnsnZB3gvwxop8VAcHjc1SpyvvyrvUXXiJHbyAGw0Ds9T_iB77mN7yjo7vuAa-3kcPA59xALCLEgV0EZJHILgLlOwkBtIOKcTmR5FdqUu8xGT91HdNL/s622/ECDH_2_1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="442" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWsVScnB8vMuuK5RS1McKNdB4paWTKZV44kpXcmJbplQ4jjPgBG_FvBD-gzG7pw_AYBB4afOnsnZB3gvwxop8VAcHjc1SpyvvyrvUXXiJHbyAGw0Ds9T_iB77mN7yjo7vuAa-3kcPA59xALCLEgV0EZJHILgLlOwkBtIOKcTmR5FdqUu8xGT91HdNL/s16000/ECDH_2_1.png" /></a></span></div><span><span style="background-color: white; font-family: inherit;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7ccVtlG3ErU4w5JadmCAlN8vwirqcBDq3L3Hz0nlE-WMMWo9ha_T_S9AOwhXDN_8ZIEVtJ0xPJxclk_nAdrUyVkpm_WfT78ownd49I-yqeRik5b8QehdgkocoTRtMK-sIUdjsNXCLIm1svCgb9mBGuFOpMXOoZajgqDcekotsdh0wo4P7SJ6YqnHx/s640/ECDH_2_2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="480" data-original-width="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7ccVtlG3ErU4w5JadmCAlN8vwirqcBDq3L3Hz0nlE-WMMWo9ha_T_S9AOwhXDN_8ZIEVtJ0xPJxclk_nAdrUyVkpm_WfT78ownd49I-yqeRik5b8QehdgkocoTRtMK-sIUdjsNXCLIm1svCgb9mBGuFOpMXOoZajgqDcekotsdh0wo4P7SJ6YqnHx/s16000/ECDH_2_2.png" /></a></div><span style="line-height: 115%;">3.- B escoge
8 como número secreto y envía a A el resultado de <i>b * P</i>. Con el script
en Python que puse en <a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-ccxciii-multiplicacion.html"><span style="color: #2b00fe;">esta entrada</span></a>, vemos que 8 * (6, 4) = (1, 1).</span></span></span><p></p><p><span style="font-family: inherit;"></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: inherit;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8MOXBIN6sU0-b-B4RYLMNV_vrL95zny4GkqFvzJSCokn-MUT_dXbGRih9P-9wVqK4OQt1R3X0oIrjYEo9vRF5JKMao3h8M-8z0PSh2TDl4z4VXsCb2_DCQoYpzwv-SCk2YDHgcskYdxLC8kyWle3ld7n1vhPrmFKM_xPMiNQ38TYt_e7FGY0p9C6S/s622/ECDH_3_1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="442" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8MOXBIN6sU0-b-B4RYLMNV_vrL95zny4GkqFvzJSCokn-MUT_dXbGRih9P-9wVqK4OQt1R3X0oIrjYEo9vRF5JKMao3h8M-8z0PSh2TDl4z4VXsCb2_DCQoYpzwv-SCk2YDHgcskYdxLC8kyWle3ld7n1vhPrmFKM_xPMiNQ38TYt_e7FGY0p9C6S/s16000/ECDH_3_1.png" /></a></span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCCilDy7V-YEn82eA77H8Egmi5ERajG2Fl_T6EqYXlW9z3Rm5CzraRvvM31uTFFxK6DBqjxUO6kkqZ2DNx0DfgcZzz5DM1AnyVsukypibzIDUe58F7_1sZWQ4CxC76LC5mFMY6HBGPvk15aSECr0STH7ORoGhhZo3gryrh4hQH2vevlxPFJuQbgbGt/s640/ECDH_3_2.png" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: inherit;"><img border="0" data-original-height="480" data-original-width="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCCilDy7V-YEn82eA77H8Egmi5ERajG2Fl_T6EqYXlW9z3Rm5CzraRvvM31uTFFxK6DBqjxUO6kkqZ2DNx0DfgcZzz5DM1AnyVsukypibzIDUe58F7_1sZWQ4CxC76LC5mFMY6HBGPvk15aSECr0STH7ORoGhhZo3gryrh4hQH2vevlxPFJuQbgbGt/s16000/ECDH_3_2.png" /></span></a></div><p></p><p class="MsoNormal" style="background: white; break-after: avoid; line-height: normal; mso-margin-bottom-alt: auto; mso-margin-top-alt: auto; page-break-after: avoid;"><span style="font-family: inherit;">4.- <b><span style="color: #45818e;">El secreto
compartido es (<i>k =</i> a * <i>b * P</i>)</span></b>:<o:p></o:p></span></p><p class="MsoNormal" style="background: white; break-after: avoid; line-height: normal; mso-margin-bottom-alt: auto; mso-margin-top-alt: auto; page-break-after: avoid;"><span style="font-family: inherit;">4.1.- A calcula: <i>k
= a * (b * P) = 11 * (1, 1) = <b><span style="color: #45818e;">(7, 8)</span></b></i>.<o:p></o:p></span></p><p>
<span style="line-height: 115%;"><span style="font-family: inherit;">4.2.- B calcula: <i>k = b * (a * P) = 8 * (1, 12) = <b><span style="color: #45818e;">(7,
8)</span></b></i>.</span></span></p><p><span><span style="background-color: white; font-family: inherit;"></span></span></p><div class="separator" style="clear: both; text-align: center;"><span><span style="background-color: white; font-family: inherit;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYJY0uG4fHQfCtbGmjQzGYcw1XRchflPmLyO-sXX2S_IaNt1fV2xDEngSGdj2FE0ddH6_oscSBGgTM_x3owNu5B3snOAcxD-28AKEVxkCLoF9bS8HNI6Ir53m_r3AXmKz4P8VfGhBdY8vQJIxnpvZB8GoyjjyJwVqq11d4X92znkJvZifcBUGDLF-g/s640/ECDH_4.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="480" data-original-width="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYJY0uG4fHQfCtbGmjQzGYcw1XRchflPmLyO-sXX2S_IaNt1fV2xDEngSGdj2FE0ddH6_oscSBGgTM_x3owNu5B3snOAcxD-28AKEVxkCLoF9bS8HNI6Ir53m_r3AXmKz4P8VfGhBdY8vQJIxnpvZB8GoyjjyJwVqq11d4X92znkJvZifcBUGDLF-g/s16000/ECDH_4.png" /></a></span></span></div><p></p><p><span style="font-family: inherit;"><b><i>Quizás también te interese</i></b><span style="background-color: white;">:</span></span></p><p><span><span style="background-color: white;"><span style="color: #292929; font-family: inherit;"></span></span></span></p><div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><p style="text-align: left;"><span><span style="background-color: white; color: #202122; font-family: inherit;"></span></span></p><div class="MsoNormal" style="text-align: left;"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-ccxc-criptografia-de-curva.html" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: inherit;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMERz99VdieQdO9YzCd3PISijiejGS-A32SvV_ss6PyHKRQF0r3uf1o1W1uNhKym9TcPWdtzM6letjal_Mgo0mf4d-eaQmZW_KDKSLNkpPq-caoPMbb7HplZv26JJhRhTzRThezYeZeMbb1H4bBZpGh1CuTL8J0m_ZVtDuo7N1N3Q62s_CoYHUqmCR/s16000/Criptograf%C3%ADa%20de%20curva%20el%C3%ADptica%20(ECC).png" /></span></a></div><div class="separator" style="clear: both; text-align: center;"><div class="MsoNormal" style="text-align: left;"><div class="separator" style="clear: both; text-align: center;"><div class="MsoNormal" style="text-align: left;"><div class="separator" style="clear: both; text-align: center;"><div class="MsoNormal" style="text-align: left;"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-ccxci-curva-eliptica-sobre.html" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: inherit;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTA4BKIzdryx4GDpEHPrIwQ-TcrdOVUGqvY0CflYtQ44Sa5QzyOEJPUQS15iJdNIzZQPNoF61rXaWqx-jDLZ17RkEOjCJicS0pcQlj5oUU6twLMjTh2udKNgkREYOjsatP4quXdIHJoK4kS9GYBDMKbSj-9UvCc-eBIg6ccOBRjg1_YDIBfFH-OtZz/s16000/Curva%20el%C3%ADptica%20sobre%20cuerpo%20finito%20en%20python.png" /></span></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-ccxciii-multiplicacion.html" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: inherit;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3QDU3F_OpqjT6MoYcMWZniNA1Mims14w-kRuvdwT3pzoRDlrqTPodc37YKNOsc8Q78iPLL57kJvIZ6w2Bof3uWggNZNxGqIop-XxQjJM2cbWEYs1Pevj-Es_mvGG53abrZvBNEXt4IPcIltOk7pa74rml9u29LbIPHPhkdxX3Cg8lF6vpgoYP-H14/s16000/Multiplicaci%C3%B3n%20escalar%20en%20una%20curva%20el%C3%ADptica%20sobre%20un%20cuerpo%20finito%20en%20python.png" /></span></a></div></div></div></div></div></div></div></div></div></div>Mikel García Larraganhttp://www.blogger.com/profile/03118239524461394157noreply@blogger.com0tag:blogger.com,1999:blog-1846493661397027137.post-26875296932991813002023-08-20T20:13:00.001+02:002023-08-21T13:18:06.123+02:00Criptografía (CCXCIII): Multiplicación escalar en una curva elíptica sobre un cuerpo finito ℤp en python<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhm3DOiW_mf5wE93487fSoXL-rvbQ4cYj8uFxlKqowbI8GEAVTjEVUwhMmt4FAZm2au9FbhoRVr6eaowHcAteeZbAZ3_ZuAjC4PnSWw6m3KxQGNDrcm5jQ7EtcUUq1_SWDRZxIlXoSK6PEzyarKZws7TP-hzX-toXZYF5d50pM8F3eJDYzV7RahAsNh/s179/Criptograf%C3%ADa%20de%20curva%20el%C3%ADptica.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="179" data-original-width="144" height="179" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhm3DOiW_mf5wE93487fSoXL-rvbQ4cYj8uFxlKqowbI8GEAVTjEVUwhMmt4FAZm2au9FbhoRVr6eaowHcAteeZbAZ3_ZuAjC4PnSWw6m3KxQGNDrcm5jQ7EtcUUq1_SWDRZxIlXoSK6PEzyarKZws7TP-hzX-toXZYF5d50pM8F3eJDYzV7RahAsNh/s1600/Criptograf%C3%ADa%20de%20curva%20el%C3%ADptica.png" width="144" /></a></div>Continúo poniendo scripts de programación en python para automatizar tareas que tengan relación con la <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa"><span style="color: #2b00fe;">criptografía</span></a>.<p></p><p>En el <a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-ccxcii-suma-de-puntos-de.html"><span style="color: #2b00fe;">post anterior</span></a> puse un script en python para implementar <span>la suma de dos puntos de una</span><span> </span><a href="https://es.wikipedia.org/wiki/Curva_el%C3%ADptica"><span><span style="color: #2b00fe;">curva elíptica</span></span></a> <span>definida sobre un</span> <a href="https://es.wikipedia.org/wiki/Cuerpo_finito"><span style="color: #2b00fe;">cuerpo finito</span></a> <span style="background-color: white;"><span><i>ℤ</i></span></span><i><sub><span>p</span></sub></i>, y en éste <b><span style="color: #45818e;">incluyo uno </span></b><span style="color: #45818e; font-weight: bold;">que implementa la multiplicación escalar de un punto de una</span><span style="font-weight: bold;"> </span><a href="https://es.wikipedia.org/wiki/Curva_el%C3%ADptica"><span style="color: #2b00fe;">curva elíptica</span></a> <b><span style="color: #45818e;">definida sobre el mismo tipo de cuerpo</span></b>; la operación que constituye la base de la <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_de_curva_el%C3%ADptica"><span style="color: #2b00fe;">Criptografía de Curva Elíptica (ECC)</span></a>.</p><p><span>E</span><span style="color: #45818e; font-weight: bold;">l</span> <a href="https://es.wikipedia.org/wiki/Pseudoc%C3%B3digo"><span style="color: #2b00fe;">pseudocódigo</span></a> para implementar la multiplicación escalar es:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDPtXURunA-IKG1zm18EjgOoR1WmWo-slBU2YgnlffAt2_xMTL0Miq_XtzgX4j_XOWocHksoAUUKlQn3K95Hk-iZGMj1KH4euqyA4xljAMC_XLLSIHuDRsccvn988hwtPgwwwASUJE-YcBKscOXRody-6mIZhN3DzosHUG8XGMyGIO2ky0K40NH8ZF/s618/Algoritmo%20multiplicaci%C3%B3n%20escalar.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="376" data-original-width="618" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDPtXURunA-IKG1zm18EjgOoR1WmWo-slBU2YgnlffAt2_xMTL0Miq_XtzgX4j_XOWocHksoAUUKlQn3K95Hk-iZGMj1KH4euqyA4xljAMC_XLLSIHuDRsccvn988hwtPgwwwASUJE-YcBKscOXRody-6mIZhN3DzosHUG8XGMyGIO2ky0K40NH8ZF/s16000/Algoritmo%20multiplicaci%C3%B3n%20escalar.png" /></a></div><p>- <i><u>Script python para implementar la multiplicación escalar de un punto de una curva elíptica definida sobre un cuerpo finito </u></i><u><span style="background-color: white;"><span><i>ℤ</i></span></span><i><sub><span>p</span></sub></i></u>:</p><p>El <b><span style="color: #45818e;">script</span></b> es el siguiente:<code class="html"></code></p><pre><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# MULTIPLICACIÓN DE UN PUNTO DE UNA CURVA ELÍPTICA (CE) POR UN ESCALAR:
#
# http://mikelgarcialarragan.blogspot.com/
import sympy
def suma_puntos(p,a,x1,y1,x2,y2):
if x1 == -1 and y1 == -1:
x3, y3 = x2, y2
return x3, y3
if x2 == -1 and y2 == -1:
x3, y3 = x1, y1
return x3, y3
if x1 == x2 and y1 == y2:
if y1 == 0:
x3, y3 = -1, -1
return x3, y3
else:
m = (3*pow(x1,2)+a)*pow(2*y1,-1,p)
else:
if x1 == x2:
x3, y3 = -1, -1
return x3, y3
else:
m = (y2-y1)*pow(x2-x1,-1,p)
x3 = (pow(m,2)-x1-x2)%p
y3 = (m*(x1-x3)-y1)%p
return x3, y3
def main():
# MENÚ:
# Se presenta el menú para que se seleccione una opción.
salir = False
while not salir:
print ("")
print ("*** MENÚ *****************************************")
print ("1. Multiplicación de un punto de una Curva Elíptica por un escalar.")
print ("2. Salir.")
print ("")
opcion = input("Por favor, seleccione una opción: ")
if opcion == "1":
print ("")
print ("--- MULTIPLICACIÓN DE UN PUNTO DE UNA CURVA ELÍPTICA POR UN ESCALAR:")
# Se introducen:
# p = número primo que caracteriza al cuerpo finito.
# a = coeficiente 'a' de la curva elíptica.
# b = coeficiente 'b' de la curva elíptica.
# k = escalar por el que se va a multiplicar el punto de la curva.
# x1, y1 = coordenadas del punto que se va a multiplicar por el escalar.
primo = a_entero = b_entero = k_ok = p_ok = p_si_no_inf = False
while not primo:
p = input("Introduzca el número primo que caracteriza al cuerpo finito: ")
if p.isnumeric() and sympy.isprime(int(p)):
primo = True
while not a_entero:
a = input("Introduzca el coeficiente 'a' de la curva elíptica: ")
try:
int(a)
a_entero = True
while not b_entero:
b = input("Introduzca el coeficiente 'b' de la curva elíptica: ")
try:
int(b)
b_entero = True
while not k_ok:
k = input("Introduzca el escalar 'k' por el que se va a multiplicar el punto 'P' de la curva elíptica: ")
if k.isnumeric():
k_ok = True
while not p_si_no_inf:
p_sn_inf = input("¿Es el punto ('P') a multiplicar por el escalar el punto en el infinito (s/n)?: ")
if p_sn_inf == "s" or p_sn_inf == "S" or p_sn_inf == "n" or p_sn_inf == "N":
p_si_no_inf = True
if p_sn_inf == "s" or p_sn_inf == "S":
x1, y1 = -1, -1
elif p_sn_inf == "n" or p_sn_inf == "N":
while not p_ok:
x1 = input("Introduzca x1: ")
if not x1.isnumeric():
print ("*** ERROR: Valor x1 incorrecto.")
else:
y1 = input("Introduzca y1: ")
if not y1.isnumeric():
print ("*** ERROR: Valor y1 incorrecto.")
else:
if pow(int(y1),2,int(p)) == (pow(int(x1),3,int(p)) + int(x1)*int(a) + int(b))%int(p):
p_ok = True
else:
print ("*** ERROR: El punto 'P' introducido no es un punto de la curva.")
if (x1 == -1 and y1 == -1) or int(k) == 0:
print ("[+] El punto resultado es el punto en el infinito (𝒪).")
else:
xs, ys, xc, yc = -1, -1, x1, y1
while int(k) != 1:
r, k = int(k)%2, int(k)//2
if r == 1:
xs, ys = suma_puntos(int(p),int(a),int(xs),int(ys),int(xc),int(yc))
xc, yc = suma_puntos(int(p),int(a),int(xc),int(yc),int(xc),int(yc))
x2, y2 = suma_puntos(int(p),int(a),int(xs),int(ys),int(xc),int(yc))
if x2 == -1 and y2 == -1:
print ("[+] El punto resultado es el punto en el infinito (𝒪).")
else:
print ("[+] Q = k * P = (x2, y2) = (", x2, ",", y2, ")")
else:
print ("*** ERROR: Introduzca 's', 'S', 'n' o 'N'.")
else:
print ("*** ERROR: Valor del escalar 'k' incorrecto.")
except ValueError:
print ("*** ERROR: Coeficiente 'b' de la curva elíptica incorrecto.")
except ValueError:
print ("*** ERROR: Coeficiente 'a' de la curva elíptica incorrecto.")
else:
print ("*** ERROR: Número primo que caracteriza al cuerpo finito incorrecto.")
elif opcion == "2":
print ("*** FIN ******************************************")
salir = True
else:
print ("*** ERROR: Opción no válida.")
if __name__ == '__main__':
main()</code>
<br /></pre><p><b><span style="color: #45818e;">Lo ejecuto</span></b>:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTQt-f5xvoZvh0WWoOmgEOQto5c25l6oHOid4yndY8YZdakCuxoRFgZUiEwsF-3hiymth9SAS3NByOhpyiQ4n0wXS-EDeOy0ElDej2t1rjSuCn3jSb34YD4bsrXxIo4lVB5ce32rooBPhXhQAYe3Tbq1SRUwCRop5F11avvMxtCzQbGh6sMyl7iYxH/s622/Multiplicaci%C3%B3n%20escalar.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="442" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTQt-f5xvoZvh0WWoOmgEOQto5c25l6oHOid4yndY8YZdakCuxoRFgZUiEwsF-3hiymth9SAS3NByOhpyiQ4n0wXS-EDeOy0ElDej2t1rjSuCn3jSb34YD4bsrXxIo4lVB5ce32rooBPhXhQAYe3Tbq1SRUwCRop5F11avvMxtCzQbGh6sMyl7iYxH/s16000/Multiplicaci%C3%B3n%20escalar.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><p style="text-align: left;"><b style="font-family: inherit;"><i>Quizás también te interese</i></b><span style="background-color: white; font-family: inherit;">:</span></p><div class="MsoNormal" style="text-align: left;"><div class="separator" style="clear: both; text-align: center;"><p style="text-align: left;"><span style="font-family: inherit;"><span style="background-color: white; color: #202122;"></span></span></p><div class="MsoNormal" style="text-align: left;"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-ccxci-curva-eliptica-sobre.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTA4BKIzdryx4GDpEHPrIwQ-TcrdOVUGqvY0CflYtQ44Sa5QzyOEJPUQS15iJdNIzZQPNoF61rXaWqx-jDLZ17RkEOjCJicS0pcQlj5oUU6twLMjTh2udKNgkREYOjsatP4quXdIHJoK4kS9GYBDMKbSj-9UvCc-eBIg6ccOBRjg1_YDIBfFH-OtZz/s16000/Curva%20el%C3%ADptica%20sobre%20cuerpo%20finito%20en%20python.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><div class="MsoNormal" style="text-align: left;"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-ccxc-criptografia-de-curva.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMERz99VdieQdO9YzCd3PISijiejGS-A32SvV_ss6PyHKRQF0r3uf1o1W1uNhKym9TcPWdtzM6letjal_Mgo0mf4d-eaQmZW_KDKSLNkpPq-caoPMbb7HplZv26JJhRhTzRThezYeZeMbb1H4bBZpGh1CuTL8J0m_ZVtDuo7N1N3Q62s_CoYHUqmCR/s16000/Criptograf%C3%ADa%20de%20curva%20el%C3%ADptica%20(ECC).png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-ccxcii-suma-de-puntos-de.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxW4R2l9msxXxDUD0Ky8PxWgaA0fTTTj15lsnur4XIOuUViQyb1qc5TjZakjHKECRtbC4y4VXiX-99gOrhIGih5OON1RlPieArb8YpSbe2rjMiMC4n6P2WJzkfzNR8Gt_pGdxCZPNqNqm6N8Q0aB6L56uLPRaFKIlJJ1AE6r81KjI0ux0YpSIdTbpU/s16000/Suma%20de%20puntos%20de%20una%20curva%20el%C3%ADptica%20sobre%20un%20cuerpo%20finito%20en%20python.png" /></a></div></div></div></div></div></div></div>Mikel García Larraganhttp://www.blogger.com/profile/03118239524461394157noreply@blogger.com0tag:blogger.com,1999:blog-1846493661397027137.post-66640683658905660392023-08-14T19:51:00.033+02:002023-08-20T17:40:28.369+02:00Criptografía (CCXCII): Suma de puntos de una curva elíptica sobre un cuerpo finito ℤp en python<div class="separator" style="clear: both;"><div class="separator" style="clear: both;"><div class="separator" style="clear: both;"><div class="separator" style="clear: both;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6U20L7F_F-s3WIJoTn0mrh0X4rl8Cd4E6Jpn7fruCRQyzvLuhQTsybCGB2M93nOyr7nX8v4weZOmxjtlbcDxkq7MOCgB3ixyPLxEGGIOhabx-oeBUAhsMdEK5jijbgmlyPfeWpH_zAhgDxlaQWQQhtjLlRBunMXJcEEhFOKauiMqU0SHRtTjiOlXy/s179/Criptograf%C3%ADa%20de%20curva%20el%C3%ADptica.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="179" data-original-width="144" height="179" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6U20L7F_F-s3WIJoTn0mrh0X4rl8Cd4E6Jpn7fruCRQyzvLuhQTsybCGB2M93nOyr7nX8v4weZOmxjtlbcDxkq7MOCgB3ixyPLxEGGIOhabx-oeBUAhsMdEK5jijbgmlyPfeWpH_zAhgDxlaQWQQhtjLlRBunMXJcEEhFOKauiMqU0SHRtTjiOlXy/s1600/Criptograf%C3%ADa%20de%20curva%20el%C3%ADptica.png" width="144" /></a></div>Continúo poniendo scripts de programación en python para automatizar tareas que tengan relación con la <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa"><span style="color: #2b00fe;">criptografía</span></a>.</div></div></div></div><p></p><p></p><p></p><p><b><span style="color: #45818e;">En este post incluyo un </span></b><span style="color: #45818e; font-weight: bold;">script en python que implementa la suma de dos puntos de una</span><span style="font-weight: bold;"> </span><a href="https://es.wikipedia.org/wiki/Curva_el%C3%ADptica"><span style="color: #2b00fe;">curva elíptica</span></a> <b><span style="color: #45818e;">definida sobre un</span></b> <a href="https://es.wikipedia.org/wiki/Cuerpo_finito"><span style="color: #2b00fe;">cuerpo finito</span></a> <span style="background-color: white;"><b><span style="color: #45818e;"><i>ℤ</i></span></b></span><i><sub><b><span style="color: #45818e;">p</span></b></sub></i>.</p><p><b><span style="color: #45818e;">Ya expliqué en</span></b> <a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-ccxc-criptografia-de-curva.html"><span style="color: #2b00fe;">este post</span></a> como se podía obtener el punto resultado de sumar dos puntos de una <a href="https://es.wikipedia.org/wiki/Curva_el%C3%ADptica"><span style="color: #2b00fe;">curva elíptica</span></a> definida sobre los números reales mediante el llamado método de la cuerda y la tangente, y en esta entrada indico el algoritmo para hacerlo con las fórmulas matemáticas oportunas en una <a href="https://es.wikipedia.org/wiki/Curva_el%C3%ADptica"><span style="color: #2b00fe;">curva elíptica</span></a> definida sobre un <a href="https://es.wikipedia.org/wiki/Cuerpo_finito"><span style="color: #2b00fe;">cuerpo finito</span></a> <span style="background-color: white;"><span><i>ℤ</i></span></span><i><sub><span>p</span></sub></i>.</p><p><span>E</span><span style="color: #45818e; font-weight: bold;">l</span> <a href="https://es.wikipedia.org/wiki/Pseudoc%C3%B3digo"><span style="color: #2b00fe;">pseudocódigo</span></a> para implementar dicha suma es:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYGFpreulnIeTWldPd_nsMWyR0dOIAf_0kQuQYBOUs0vJkZK5rMyhEHFCO6Fiq6STOEL5NT0yyTpte49b4Eh73jh0Zls2Ok0UJ_4AlVSiFHG-avo_jpc2aWWwbXRXCXgcaNTb7TB2P0gQfafMSNfJIErNdQY7rOH0aXo84SvRwZuB7Vik2uM5CfPdI/s618/Algoritmo%20suma%20de%20puntos.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="535" data-original-width="618" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYGFpreulnIeTWldPd_nsMWyR0dOIAf_0kQuQYBOUs0vJkZK5rMyhEHFCO6Fiq6STOEL5NT0yyTpte49b4Eh73jh0Zls2Ok0UJ_4AlVSiFHG-avo_jpc2aWWwbXRXCXgcaNTb7TB2P0gQfafMSNfJIErNdQY7rOH0aXo84SvRwZuB7Vik2uM5CfPdI/s16000/Algoritmo%20suma%20de%20puntos.png" /></a></div><p>- <i><u>Script python para implementar la suma de dos puntos de una curva elíptica definida sobre un cuerpo finito </u></i><u><span style="background-color: white;"><span><i>ℤ</i></span></span><i><sub><span>p</span></sub></i></u>:</p><p>El <b><span style="color: #45818e;">script</span></b> es el siguiente:<code class="html"></code></p><pre><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# SUMA DE DOS PUNTOS DE UNA CURVA ELÍPTICA (CE):
#
# http://mikelgarcialarragan.blogspot.com/
import sympy
def suma_puntos(p,a,x1,y1,x2,y2):
if x1 == -1 and y1 == -1:
x3, y3 = x2, y2
return x3, y3
if x2 == -1 and y2 == -1:
x3, y3 = x1, y1
return x3, y3
if x1 == x2 and y1 == y2:
if y1 == 0:
x3, y3 = -1, -1
return x3, y3
else:
m = (3*pow(x1,2)+a)*pow(2*y1,-1,p)
else:
if x1 == x2:
x3, y3 = -1, -1
return x3, y3
else:
m = (y2-y1)*pow(x2-x1,-1,p)
x3 = (pow(m,2)-x1-x2)%p
y3 = (m*(x1-x3)-y1)%p
return x3, y3
def main():
# MENÚ:
# Se presenta el menú para que se seleccione una opción.
salir = False
while not salir:
print ("")
print ("*** MENÚ *****************************************")
print ("1. Suma de puntos de una Curva Elíptica.")
print ("2. Salir.")
print ("")
opcion = input("Por favor, seleccione una opción: ")
if opcion == "1":
print ("")
print ("--- SUMA DE DOS PUNTOS DE UNA CURVA ELÍPTICA:")
# Se introducen:
# p = número primo que caracteriza al cuerpo finito.
# a = coeficiente 'a' de la curva elíptica
# x1, y1 = coordenadas del primer punto a sumar.
# x2, y2 = coordenadas del segundo punto a sumar.
primo = a_entero = b_entero = p_ok = q_ok = p_si_no_inf = q_si_no_inf = False
while not primo:
p = input("Introduzca el número primo que caracteriza al cuerpo finito: ")
if p.isnumeric() and sympy.isprime(int(p)):
primo = True
while not a_entero:
a = input("Introduzca el coeficiente 'a' de la curva elíptica: ")
try:
int(a)
a_entero = True
while not b_entero:
b = input("Introduzca el coeficiente 'b' de la curva elíptica: ")
try:
int(b)
b_entero = True
while not p_si_no_inf:
p_sn_inf = input("¿Es el primer punto a sumar ('P') el punto en el infinito (s/n)?: ")
if p_sn_inf == "s" or p_sn_inf == "S" or p_sn_inf == "n" or p_sn_inf == "N":
p_si_no_inf = True
if p_sn_inf == "s" or p_sn_inf == "S":
x1, y1 = -1, -1
if p_sn_inf == "n" or p_sn_inf == "N":
while not p_ok:
x1 = input("Introduzca x1: ")
if not x1.isnumeric():
print ("*** ERROR: Valor x1 incorrecto.")
else:
y1 = input("Introduzca y1: ")
if not y1.isnumeric():
print ("*** ERROR: Valor y1 incorrecto.")
else:
if pow(int(y1),2,int(p)) == (pow(int(x1),3,int(p)) + int(x1)*int(a) + int(b))%int(p):
p_ok = True
else:
print ("*** ERROR: El punto 'P' introducido no es un punto de la curva.")
else:
print ("*** ERROR: Introduzca 's', 'S', 'n' o 'N'.")
while not q_si_no_inf:
q_sn_inf = input("¿Es el segundo punto a sumar ('Q') el punto en el infinito (s/n)?: ")
if q_sn_inf == "s" or q_sn_inf == "S" or q_sn_inf == "n" or q_sn_inf == "N":
q_si_no_inf = True
if q_sn_inf == "s" or q_sn_inf == "S":
x2, y2 = -1, -1
if q_sn_inf == "n" or q_sn_inf == "N":
while not q_ok:
x2 = input("Introduzca x2: ")
if not x2.isnumeric():
print ("*** ERROR: Valor x2 incorrecto.")
else:
y2 = input("Introduzca y2: ")
if not y2.isnumeric():
print ("*** ERROR: Valor y2 incorrecto.")
else:
if pow(int(y2),2,int(p)) == (pow(int(x2),3,int(p)) + int(x2)*int(a) + int(b))%int(p):
q_ok = True
else:
print ("*** ERROR: El punto 'Q' introducido no es un punto de la curva.")
else:
print ("*** ERROR: Introduzca 's', 'S', 'n' o 'N'.")
x3,y3 = suma_puntos(int(p),int(a),int(x1),int(y1),int(x2),int(y2))
if x3 == -1 and y3 == -1:
print ("[+] El punto resultado es el punto en el infinito (𝒪).")
else:
print ("[+] R = P + Q = (x3, y3) = (", x3, ",", y3, ")")
except ValueError:
print ("*** ERROR: Coeficiente 'b' de la curva elíptica incorrecto.")
except ValueError:
print ("*** ERROR: Coeficiente 'a' de la curva elíptica incorrecto.")
else:
print ("*** ERROR: Número primo que caracteriza al cuerpo finito incorrecto.")
elif opcion == "2":
print ("*** FIN ******************************************")
salir = True
else:
print ("*** ERROR: Opción no válida.")
if __name__ == '__main__':
main()</code>
<br /></pre><p><b><span style="color: #45818e;">Lo ejecuto</span></b>:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_ZHC83LCYOEpzIsUPLyKpISaBhey1cTi4jLcjAaFih3Pinjw4U6hmPtAvl71bc_S-ZeBWYWBtZJjo_GDNuSnl5l_dVZZR-Xu_OylS__7F_q2cWC_CBaRVsJUOSXPA_3DKVrdpjNn-n_VOF5z5hSgfaiEExhK9HqW7v4BmXU_YQC1iBjz6eJEqH13V/s622/Suma%20puntos.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="466" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_ZHC83LCYOEpzIsUPLyKpISaBhey1cTi4jLcjAaFih3Pinjw4U6hmPtAvl71bc_S-ZeBWYWBtZJjo_GDNuSnl5l_dVZZR-Xu_OylS__7F_q2cWC_CBaRVsJUOSXPA_3DKVrdpjNn-n_VOF5z5hSgfaiEExhK9HqW7v4BmXU_YQC1iBjz6eJEqH13V/s16000/Suma%20puntos.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><p style="text-align: left;"><b style="font-family: inherit;"><i>Quizás también te interese</i></b><span style="background-color: white; font-family: inherit;">:</span></p><div class="MsoNormal" style="text-align: left;"><div class="separator" style="clear: both; text-align: center;"><p style="text-align: left;"><span style="font-family: inherit;"><span style="background-color: white; color: #202122;"></span></span></p><div class="MsoNormal" style="text-align: left;"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-ccxci-curva-eliptica-sobre.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTA4BKIzdryx4GDpEHPrIwQ-TcrdOVUGqvY0CflYtQ44Sa5QzyOEJPUQS15iJdNIzZQPNoF61rXaWqx-jDLZ17RkEOjCJicS0pcQlj5oUU6twLMjTh2udKNgkREYOjsatP4quXdIHJoK4kS9GYBDMKbSj-9UvCc-eBIg6ccOBRjg1_YDIBfFH-OtZz/s16000/Curva%20el%C3%ADptica%20sobre%20cuerpo%20finito%20en%20python.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><div class="MsoNormal" style="text-align: left;"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-ccxc-criptografia-de-curva.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMERz99VdieQdO9YzCd3PISijiejGS-A32SvV_ss6PyHKRQF0r3uf1o1W1uNhKym9TcPWdtzM6letjal_Mgo0mf4d-eaQmZW_KDKSLNkpPq-caoPMbb7HplZv26JJhRhTzRThezYeZeMbb1H4bBZpGh1CuTL8J0m_ZVtDuo7N1N3Q62s_CoYHUqmCR/s16000/Criptograf%C3%ADa%20de%20curva%20el%C3%ADptica%20(ECC).png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxx-intercambio-de.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibE88VIh1BKGbWGm5Pc8tzm0QMJevU1F-rJPA8DoZ-nf8aVq6RcyuetH2lP5sOuQksZ9NAcE-7aZLkuV2FCXPnSlfMsRxYDNpkGyZ1ntUx5jzeVhtEgluACitqudFKqtH7mKqWaDJQd6wIJH9RC1nBDaJOtNzO7LEmNEkAOv0fyEYvJEDlbnI6AwQY/s16000/Intercambio%20de%20clave%20de%20Diffie-Hellman.png" /></a></div></div></div></div></div></div></div>Mikel García Larraganhttp://www.blogger.com/profile/03118239524461394157noreply@blogger.com0tag:blogger.com,1999:blog-1846493661397027137.post-20844708806985577762023-08-13T11:21:00.003+02:002023-08-15T18:18:27.513+02:00Criptografía (CCXCI): Curva elíptica sobre cuerpo finito ℤp en python<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSECcki2By3w28Yxo9w7JicNOMhA3ECu7XE4u4eyuyN2ZHJyOVIS6AzayFDekhf7zYU4aPd6CkYr3Syrmnqj_66b6CiWq4ZF6H72rH-m4lgle3KTu9xTLF4LVDYwQN9p9523SKICDg4itNcyblubDZZOrN4-IsqZMu3Csxgknlto7cO58VpBsuDW4q/s179/Criptograf%C3%ADa%20de%20curva%20el%C3%ADptica.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="179" data-original-width="144" height="179" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSECcki2By3w28Yxo9w7JicNOMhA3ECu7XE4u4eyuyN2ZHJyOVIS6AzayFDekhf7zYU4aPd6CkYr3Syrmnqj_66b6CiWq4ZF6H72rH-m4lgle3KTu9xTLF4LVDYwQN9p9523SKICDg4itNcyblubDZZOrN4-IsqZMu3Csxgknlto7cO58VpBsuDW4q/s1600/Criptograf%C3%ADa%20de%20curva%20el%C3%ADptica.png" width="144" /></a></div>Otro post con un script de programación en python para automatizar tareas que tengan relación con la <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa"><span style="color: #2b00fe;">criptografía</span></a>.<p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p><b><span style="color: #45818e;">En este post incluyo un </span></b><span style="color: #45818e; font-weight: bold;">script en python para obtener los puntos de una </span><a href="https://es.wikipedia.org/wiki/Curva_el%C3%ADptica" style="background-color: white;"><span style="color: #2b00fe;">curva elíptica</span></a><span style="color: #45818e; font-weight: bold;"> definida sobre un <a href="https://es.wikipedia.org/wiki/Cuerpo_finito" style="font-family: inherit; font-weight: 400;"><span style="color: #2b00fe;">cuerpo finito</span></a> del tipo </span><span style="background-color: white;"><b><span style="color: #45818e;"><i>ℤ</i></span></b></span><i><sub><b><span style="color: #45818e;">p </span></b></sub></i><span style="color: #45818e; font-weight: bold;">y para obtener la representación gráfica de ambas curvas,</span><span style="font-family: inherit;"> la definida sobre los número reales y la definida sobre el cuero finito </span><span style="background-color: white;"><b><span><i>ℤ</i></span></b></span><i><sub><span>p</span></sub></i><span style="font-family: inherit;">.</span></p><p><span style="font-family: inherit;">En el <a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-ccxc-criptografia-de-curva.html"><span style="color: #2b00fe;">post anterior</span></a> puse como ejemplo de lo anterior la curva sobre números reales que sirve para ilustrar este post:</span></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6aIvIyXR_8ckXec2zMZaYYkHtf9nwhvHKGozhp5bDV7d-zHMnyiogclX7fkuAHxpzTQxaHR6_tHUNo7NLtM4jp3ovwgsP97wO2vpy57hszlwVZl-143DFo8A4DXtVJHLCHzHDz7mRy1LrOyamCpI_824migZgHWXtMSo_TyP1WFZxQhLpBcXz2d0a/s620/Criptograf%C3%ADa%20de%20curva%20el%C3%ADptica%20EC%20sobre%20cuerpo%20finito.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="280" data-original-width="620" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6aIvIyXR_8ckXec2zMZaYYkHtf9nwhvHKGozhp5bDV7d-zHMnyiogclX7fkuAHxpzTQxaHR6_tHUNo7NLtM4jp3ovwgsP97wO2vpy57hszlwVZl-143DFo8A4DXtVJHLCHzHDz7mRy1LrOyamCpI_824migZgHWXtMSo_TyP1WFZxQhLpBcXz2d0a/s16000/Criptograf%C3%ADa%20de%20curva%20el%C3%ADptica%20EC%20sobre%20cuerpo%20finito.png" /></a></div><p></p><p><span style="font-family: inherit;">Y decía que </span><b style="background-color: white;"><span style="color: #45818e;">al definir la </span></b><a href="https://es.wikipedia.org/wiki/Curva_el%C3%ADptica" style="background-color: white;"><span style="color: #2b00fe;">curva elíptica</span></a><span style="background-color: white; color: #202122;"> </span><b style="background-color: white;"><span style="color: #45818e;">sobre un</span></b><span style="background-color: white; color: #202122;"> </span><a href="https://es.wikipedia.org/wiki/Cuerpo_finito" style="background-color: white; color: #202122; font-family: inherit;"><span style="color: #2b00fe;">cuerpo finito</span></a><span style="background-color: white; color: #202122;"> </span><b style="background-color: white;"><span style="color: #45818e;">se obtiene algo</span></b><b style="background-color: white;"><span style="color: #45818e;"> que</span></b><span style="background-color: white; color: #202122;"> se asemeja poco o nada a la representación gráfica de la curva sobre números reales, más bien </span><b style="background-color: white;"><span style="color: #45818e;">tiene el aspecto de un conjunto de puntos aleatorios</span></b><span style="background-color: white;"><b><span style="color: #45818e;">, pero</span></b><span style="color: #202122;"> que </span><b><span style="color: #45818e;">todavía se puede observar la simetría</span></b><span style="color: #202122;">.</span></span></p><p>El <b><span style="color: #45818e;">script</span></b> es el siguiente:</p><p><span style="font-family: inherit;"><span style="color: #292929;">- </span><span style="color: #292929;"><u><i>Script python para la obtención y representación de los puntos de una curva elíptica sobre un cuerpo finito </i></u></span></span><i><span style="background-color: white;"><b><span>ℤ</span></b></span><sub><span>p</span></sub></i><span style="color: #292929; font-family: inherit;">:</span></p><p></p><pre><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# PUNTOS DE UNA CURVA ELÍPTICA (EC):
#
# Obtención de los puntos de una Curva Elíptica (y^2 = x^3 + ax + b) definida
# sobre un cuerpo finito.
#
# http://mikelgarcialarragan.blogspot.com/
import sympy
import numpy as np
import matplotlib.pyplot as plt
def main():
# MENÚ:
# Se presenta el menú para que se seleccione una opción.
salir = False
while not salir:
print ("")
print ("*** MENÚ *****************************************")
print ("1. Obtención puntos Curva Elíptica sobre cuerpo finito.")
print ("2. Salir.")
print ("")
opcion = input("Por favor, seleccione una opción: ")
if opcion == "1":
print ("")
print ("--- PUNTOS DE UNA CURVA ELIPTICA DEFINIDA SOBRE UN CUERPO FINITO:")
# Se introducen:
# p = número primo que caracteriza al cuerpo finito.
# a = coeficiente 'a' de la curva elíptica.
# b = coeficiente 'b' de la curva elíptica.
primo = a_entero = b_entero = False
while not primo:
p = input("Introduzca el número primo que caracteriza al cuerpo finito: ")
if p.isnumeric() and sympy.isprime(int(p)):
primo = True
while not a_entero:
a = input("Introduzca el coeficiente 'a' de la curva elíptica: ")
try:
int(a)
a_entero = True
while not b_entero:
b = input("Introduzca el coeficiente 'b' de la curva elíptica: ")
try:
int(b)
b_entero = True
curva_eliptica_r = "y^2 = x^3 "
curva_eliptica_f = "y^2 mod " + p + " = x^3 "
if int(a) >= 0:
curva_eliptica_r += "+ "+ a + " x "
curva_eliptica_f += "+ "+ a + " x "
else:
curva_eliptica_r += a + " x "
curva_eliptica_f += a + " x "
if int(b) >= 0:
curva_eliptica_r += "+ "+ b + " "
curva_eliptica_f += "+ "+ b + " "
else:
curva_eliptica_r += b + " "
curva_eliptica_f += b + " "
curva_eliptica_f += "mod " + p
print ("[+] Curva elíptica sobre los números reales: ", curva_eliptica_r)
ec_r = plt.figure()
ec_r, ax = plt.subplots()
ax.set_title(curva_eliptica_r)
ax.xaxis.grid()
ax.yaxis.grid()
y, x = np.ogrid[-5:5:100j, -5:5:100j]
plt.contour(x.ravel(), y.ravel(), pow(y, 2) - pow(x, 3) - x * int(a) - int(b), [0], colors = ["r"])
plt.savefig('EC_R.png')
plt.show()
print ("[+] Curva elíptica definida sobre cuerpo finito:", curva_eliptica_f)
print ("[+] Puntos curva elíptica sobre cuerpo finito:")
exp = int((int(p)-1)/2)
y_2 = [pow(y,2,int(p)) for y in range(0, int(p))]
coordenadas = []
for x in range(0, int(p)):
f_x = (pow(x,3) + int(a)*x + int(b))%int(p)
if pow(f_x,exp,int(p)) == 0 or pow(f_x,exp,int(p)) == 1:
for y in range(len(y_2)):
if f_x == y_2[y]:
print (" (", x, ",", y, ")")
coordenadas.append(x)
coordenadas.append(y)
coordenadas_x = coordenadas[0::2]
coordenadas_y = coordenadas[1::2]
ec_f = plt.figure()
ec_f, ax = plt.subplots()
ax.set_title(curva_eliptica_f)
ax.xaxis.grid()
ax.yaxis.grid()
plt.scatter(coordenadas_x, coordenadas_y)
plt.savefig('EC_F.png')
plt.show()
except ValueError:
print ("*** ERROR: Coeficiente 'b' de la curva elíptica incorrecto.")
except ValueError:
print ("*** ERROR: Coeficiente 'a' de la curva elíptica incorrecto.")
else:
print ("*** ERROR: Número primo que caracteriza al cuerpo finito incorrecto.")
elif opcion == "2":
print ("*** FIN ******************************************")
salir = True
else:
print ("*** ERROR: Opción no válida.")
if __name__ == '__main__':
main()</code>
<br /></pre><p><span><span style="color: #292929;"></span></span></p><p><span><span style="color: #292929;"></span></span></p><p><span style="background-color: white; color: #202122;"></span></p><p><b><span style="color: #45818e;">Lo ejecuto</span></b>:</p><p><span style="font-family: inherit;">Tras pedir como datos de entrada: el número primo que caracteriza al cuerpo finito y los coeficientes <i>'a'</i> y <i>'b'</i> de la <a href="https://es.wikipedia.org/wiki/Curva_el%C3%ADptica" style="background-color: white;"><span style="color: #2b00fe;">curva elíptica</span></a>, el script obtiene los puntos de la curva definida sobre el <a href="https://es.wikipedia.org/wiki/Cuerpo_finito" style="background-color: white; color: #202122; font-family: inherit;"><span style="color: #2b00fe;">cuerpo finito</span></a> y genera sendos gráficos para la representación de la misma sobre números reales y sobre </span>el <a href="https://es.wikipedia.org/wiki/Cuerpo_finito" style="background-color: white; color: #202122; font-family: inherit;"><span style="color: #2b00fe;">cuerpo finito</span></a>.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJA7PvufltWovCjTwT40vdbtiG495qn9LBWpCxz4NltsINpRc7m4FU-O7SlBSRe_EgRt-8ucJ3BCn9sQXH4c7yiN_mSERzWTxAKGkN5ziNw2C2c6JxvKRgvfg4flQnIrX31yzkSrW7qEIHCiuYouLjAEBJ9CzDxdwmEnIIWYc98vnMBRmYU2qyETmY/s754/Puntos%20EC_F_1_1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="754" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJA7PvufltWovCjTwT40vdbtiG495qn9LBWpCxz4NltsINpRc7m4FU-O7SlBSRe_EgRt-8ucJ3BCn9sQXH4c7yiN_mSERzWTxAKGkN5ziNw2C2c6JxvKRgvfg4flQnIrX31yzkSrW7qEIHCiuYouLjAEBJ9CzDxdwmEnIIWYc98vnMBRmYU2qyETmY/s16000/Puntos%20EC_F_1_1.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJiKF_XXswlnzfUIlvDqMEptEoK-BbSw4MzEahg3WdTybWcGUclRYw5mdSA_BNpy0ZQYkBg67ZJiLBbU-EbJNjPANjkdrBasvcZSYRffI_4BrcOu957s8UkcvAGHYi-5nAYLEPgwEp2vyrsCgVqs2EOSrZ3cFoBqdQ3Jgja4rjv05QJZBb-kIL_xwY/s640/Puntos%20EC_R_1_3.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="480" data-original-width="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJiKF_XXswlnzfUIlvDqMEptEoK-BbSw4MzEahg3WdTybWcGUclRYw5mdSA_BNpy0ZQYkBg67ZJiLBbU-EbJNjPANjkdrBasvcZSYRffI_4BrcOu957s8UkcvAGHYi-5nAYLEPgwEp2vyrsCgVqs2EOSrZ3cFoBqdQ3Jgja4rjv05QJZBb-kIL_xwY/s16000/Puntos%20EC_R_1_3.png" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIsDfJvKYPt9fcjTr3qrWHsvbx3Mfo536tq6wUEuWz4ULlHOSM757-cXHr-OmcOJcwdYPCKgoojTZeuZTMa68MtvOPARC3kxmxp5V1lbTmYKpRHvKAGBguvRniQ-T_sSRGyPKxLQOoeQ1wmZksX0HoyUFcqu58qTWTL13HLfESJvJ_EYvAohPf-HEx/s640/Puntos%20EC_F_1_2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="480" data-original-width="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIsDfJvKYPt9fcjTr3qrWHsvbx3Mfo536tq6wUEuWz4ULlHOSM757-cXHr-OmcOJcwdYPCKgoojTZeuZTMa68MtvOPARC3kxmxp5V1lbTmYKpRHvKAGBguvRniQ-T_sSRGyPKxLQOoeQ1wmZksX0HoyUFcqu58qTWTL13HLfESJvJ_EYvAohPf-HEx/s16000/Puntos%20EC_F_1_2.png" /></a><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhDRQCnUN7k5mPtyaU6Bk2qgPydExETCtE6ktEdC1oAD5DKDkKnUrcWGfbS3lMZWWAeOUeKJFpsn1icfMaMpQGvsSMpX9310aqIOfjfpQY0n8BhUKrbhAzLtMDe4YvTlNug0uKN1PPaa5zHB8B3nEK_3XYc4Jn55SPMxzY9K7LrkwgwlzVYmzWEWAG/s826/Puntos%20EC_F_2_1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="826" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhDRQCnUN7k5mPtyaU6Bk2qgPydExETCtE6ktEdC1oAD5DKDkKnUrcWGfbS3lMZWWAeOUeKJFpsn1icfMaMpQGvsSMpX9310aqIOfjfpQY0n8BhUKrbhAzLtMDe4YvTlNug0uKN1PPaa5zHB8B3nEK_3XYc4Jn55SPMxzY9K7LrkwgwlzVYmzWEWAG/s16000/Puntos%20EC_F_2_1.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiw-5cC6jJNkewQX3B_uqU8TI5iHC9NoCZJtc6aD_MGxnVTiVA3DRvszZ-5e_-3b3a41YNjYVvVnBmeYkf7aF3fzhlrs0piIj803y8OppsMxucPGYIeXqqkrW1akqakFGxyRbVWMWvYHVNbKarWbhXP_yzEpGC2TOsslyDH5UnLAVGYjG5dhWmCKhK_/s640/Puntos%20EC_R_2_3.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="480" data-original-width="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiw-5cC6jJNkewQX3B_uqU8TI5iHC9NoCZJtc6aD_MGxnVTiVA3DRvszZ-5e_-3b3a41YNjYVvVnBmeYkf7aF3fzhlrs0piIj803y8OppsMxucPGYIeXqqkrW1akqakFGxyRbVWMWvYHVNbKarWbhXP_yzEpGC2TOsslyDH5UnLAVGYjG5dhWmCKhK_/s16000/Puntos%20EC_R_2_3.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7jJxzZ6KqfzEMe21wld2pOVut8FOZe-Ol1gAmd5x0sr44sQpN7SaWJaPsyO2YLO6tS6ujHVtpZ6e7U0C3h6-DEqjjULlBgc8Y9OwCm_ca8rfuUPXgP9yqaaGYgqGjGUE4DFAhH5gv0clbHTDKJar8YInxyJ6f4IiohIWIhtuuucpX2W4CGlpYw6Lm/s640/Puntos%20EC_F_2_2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="480" data-original-width="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7jJxzZ6KqfzEMe21wld2pOVut8FOZe-Ol1gAmd5x0sr44sQpN7SaWJaPsyO2YLO6tS6ujHVtpZ6e7U0C3h6-DEqjjULlBgc8Y9OwCm_ca8rfuUPXgP9yqaaGYgqGjGUE4DFAhH5gv0clbHTDKJar8YInxyJ6f4IiohIWIhtuuucpX2W4CGlpYw6Lm/s16000/Puntos%20EC_F_2_2.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIQ8x-5N75oB1dGrVxGRAoM-2QZqOkZX5y41wi1e2UR49YZlpd4Lqp5-8nuw3-l7nN8QhLXNOmeNzVYCYC55g9zOOLEBLAX3Ol0OaCUwcYAKhWmqT0UmGRYCWq623xoqX_1UI3YxOLWiQWlDIpfV_pRo1_Mgjd2UOeAjXMaGE3JP6J23lXPBh10IEN/s994/Puntos%20EC_F_3_1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="994" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIQ8x-5N75oB1dGrVxGRAoM-2QZqOkZX5y41wi1e2UR49YZlpd4Lqp5-8nuw3-l7nN8QhLXNOmeNzVYCYC55g9zOOLEBLAX3Ol0OaCUwcYAKhWmqT0UmGRYCWq623xoqX_1UI3YxOLWiQWlDIpfV_pRo1_Mgjd2UOeAjXMaGE3JP6J23lXPBh10IEN/s16000/Puntos%20EC_F_3_1.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXucKS-aITIgISIG31Tp6jmuUFjjwyKnqjBiMMqGN1bBez9O6a4HgXEKdPVBy21UmMXksqNfOG3Dbxgqemy92K8Lr2RZanQE8SuuR_Dp1o5YjwmpNzHQEn31s-Z6ApEvfLPaqDsd6x_i7mLBNedqD-unwK72xcBNaaFaTycgae6zGAlsdWMMDXM6Rc/s640/Puntos%20EC_R_3_3.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="480" data-original-width="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXucKS-aITIgISIG31Tp6jmuUFjjwyKnqjBiMMqGN1bBez9O6a4HgXEKdPVBy21UmMXksqNfOG3Dbxgqemy92K8Lr2RZanQE8SuuR_Dp1o5YjwmpNzHQEn31s-Z6ApEvfLPaqDsd6x_i7mLBNedqD-unwK72xcBNaaFaTycgae6zGAlsdWMMDXM6Rc/s16000/Puntos%20EC_R_3_3.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqTh_9HbiXErJT1BgFqA5dfXio9RJPuHCahmfa5sPonHjV3FZiFgVMBRUcvjLNUMWfWIiyxrblAm6xlnuLHqn6uJ89CQpPRB0QA6C21WR-zj9MFrjdaema_bCNOLx61NjWNI2U_2mdOhs9PBKLCFboPY-JtMZEyoEwqp5Y7F_mfK4Pr7x6qvtiFebL/s640/Puntos%20EC_F_3_2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="480" data-original-width="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqTh_9HbiXErJT1BgFqA5dfXio9RJPuHCahmfa5sPonHjV3FZiFgVMBRUcvjLNUMWfWIiyxrblAm6xlnuLHqn6uJ89CQpPRB0QA6C21WR-zj9MFrjdaema_bCNOLx61NjWNI2U_2mdOhs9PBKLCFboPY-JtMZEyoEwqp5Y7F_mfK4Pr7x6qvtiFebL/s16000/Puntos%20EC_F_3_2.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0oFe1aLitvSJhFoKwx-O7adXV7YsqDAV2Aw1_Jf0--kiNb5VaYLpVsdGvoxoXzE_twLkw1KoZcrnpQQanOrgAD9QFy6Vu4nePPFq63oCrjzSHTuFGbjf1je_rEpvj195t5AR8RfXbZobWNrt6bw-JtIOxOlu64bSDNHmBaUz_7S3ho0JHb-a6YDXw/s994/Puntos%20EC_F_4_1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="994" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0oFe1aLitvSJhFoKwx-O7adXV7YsqDAV2Aw1_Jf0--kiNb5VaYLpVsdGvoxoXzE_twLkw1KoZcrnpQQanOrgAD9QFy6Vu4nePPFq63oCrjzSHTuFGbjf1je_rEpvj195t5AR8RfXbZobWNrt6bw-JtIOxOlu64bSDNHmBaUz_7S3ho0JHb-a6YDXw/s16000/Puntos%20EC_F_4_1.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoApH4XArWX4_efhkyApp5Y4NfCZyZPCFAe3KASRbPlYXdjQTX1G0EbhJTfmnGx-HaVuLKaQ_N8nZBnKypWMxJmO8l3UqI3eJRyfBxB3W1Kq7EJaIirO-6avrZHkNtA4MKAXL7TDaDk4p4AolY-fbnwClqX4KqogNpbTvJT28Hoj3QMXm2TP6Q8vtm/s640/Puntos%20EC_R_4_3.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="480" data-original-width="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoApH4XArWX4_efhkyApp5Y4NfCZyZPCFAe3KASRbPlYXdjQTX1G0EbhJTfmnGx-HaVuLKaQ_N8nZBnKypWMxJmO8l3UqI3eJRyfBxB3W1Kq7EJaIirO-6avrZHkNtA4MKAXL7TDaDk4p4AolY-fbnwClqX4KqogNpbTvJT28Hoj3QMXm2TP6Q8vtm/s16000/Puntos%20EC_R_4_3.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEyWHBVtExsbqIRJb_VMGsW9XcN5luqHwGXb4yB6SE72RPDj5GyVH6dk5jkr2kwob0X70oSh6c2mVL3wz8F3WEkLALErwwEq4b-yO0d-c4AkQHJGc1DTKBlP3dEzjBePGpQJ36UUWgkYzVT-MO3MP5k8DQ8OkAIwAJlEIfjJBXNEDRkSA1KvaouLuw/s640/Puntos%20EC_F_4_2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="480" data-original-width="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEyWHBVtExsbqIRJb_VMGsW9XcN5luqHwGXb4yB6SE72RPDj5GyVH6dk5jkr2kwob0X70oSh6c2mVL3wz8F3WEkLALErwwEq4b-yO0d-c4AkQHJGc1DTKBlP3dEzjBePGpQJ36UUWgkYzVT-MO3MP5k8DQ8OkAIwAJlEIfjJBXNEDRkSA1KvaouLuw/s16000/Puntos%20EC_F_4_2.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi72WqbK4HkkaItyhaiwC25c7X91g-BhUdTFt9fBTRRTFufaWTNtNVLyeihhNQmt_Bokn0quZkcMd-ZmkQTa_T1ifvMQ0joUlUdFzkyQvEhms0OpEHkwQ5O-Giw9Vcli-tqbGqiZdQKKQ5vQXbcqJq5XZoYxjPq5Hv4bG8w8w8ph48QLkOTDBFmek0D/s994/Puntos%20EC_F_5_1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="994" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi72WqbK4HkkaItyhaiwC25c7X91g-BhUdTFt9fBTRRTFufaWTNtNVLyeihhNQmt_Bokn0quZkcMd-ZmkQTa_T1ifvMQ0joUlUdFzkyQvEhms0OpEHkwQ5O-Giw9Vcli-tqbGqiZdQKKQ5vQXbcqJq5XZoYxjPq5Hv4bG8w8w8ph48QLkOTDBFmek0D/s16000/Puntos%20EC_F_5_1.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmYqsVj1uJZQbmsxbeigWChnRfk5keQ9rRBaM1JOXkS5QuUkOLgKCBMBlYdGX_uohIUHIbCL099ZZS0KByUxp5Qvz5hOrwYoi18TjNbRA8o4PYw7E675LPC-DiN2tnCM154GE_425f_lM8JQuGbZgY14LTH90AwPPLU2l_lLdybK4IDedfHKl8qFPh/s640/Puntos%20EC_R_5_3.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="480" data-original-width="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmYqsVj1uJZQbmsxbeigWChnRfk5keQ9rRBaM1JOXkS5QuUkOLgKCBMBlYdGX_uohIUHIbCL099ZZS0KByUxp5Qvz5hOrwYoi18TjNbRA8o4PYw7E675LPC-DiN2tnCM154GE_425f_lM8JQuGbZgY14LTH90AwPPLU2l_lLdybK4IDedfHKl8qFPh/s16000/Puntos%20EC_R_5_3.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFQU3Tw3JEISU9mraR8iFp0IkBft6AessPtNnT32hlblXbEPebwwZgVzcNHSFD0fKcZplYK_lUKWlF27agfzs_Inw-NCB-WyfYSjyCp-TFrE5cTim_d549mfKglsry-0QwKPFDGkHMptiyI3dtbhw4GJdlfG3Hhxf92LICCsn36G_NmzkFrTyEYadq/s640/Puntos%20EC_F_5_2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="480" data-original-width="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFQU3Tw3JEISU9mraR8iFp0IkBft6AessPtNnT32hlblXbEPebwwZgVzcNHSFD0fKcZplYK_lUKWlF27agfzs_Inw-NCB-WyfYSjyCp-TFrE5cTim_d549mfKglsry-0QwKPFDGkHMptiyI3dtbhw4GJdlfG3Hhxf92LICCsn36G_NmzkFrTyEYadq/s16000/Puntos%20EC_F_5_2.png" /></a></div><div><p><b style="font-family: inherit;"><i>Quizás también te interese</i></b><span style="background-color: white; font-family: inherit;">:</span></p><p><span style="font-family: inherit;"><span style="background-color: white; color: #202122;"></span></span></p><div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-ccxc-criptografia-de-curva.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMERz99VdieQdO9YzCd3PISijiejGS-A32SvV_ss6PyHKRQF0r3uf1o1W1uNhKym9TcPWdtzM6letjal_Mgo0mf4d-eaQmZW_KDKSLNkpPq-caoPMbb7HplZv26JJhRhTzRThezYeZeMbb1H4bBZpGh1CuTL8J0m_ZVtDuo7N1N3Q62s_CoYHUqmCR/s16000/Criptograf%C3%ADa%20de%20curva%20el%C3%ADptica%20(ECC).png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxxiv-el-algoritmo.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhj1Ip-zJEXAS2NyqCSUI7IzEg94Y5Apo6MD2J21Th8Z16fsCL0XJu0p20h3Kjq_DeQddXofM_KyeiPcFLMs7Uq81LIZuOgPgWQvRltibvxFVS9Mfjn3gDsv7iAinvmx0x6N62U91ELaItPFe8xwy2SISAZdED77ANld-7DikHPvsQM-0b6JlMaJMTL/s16000/El%20algoritmo%20ElGamal.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><div class="MsoNormal" style="text-align: left;"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxx-intercambio-de.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibE88VIh1BKGbWGm5Pc8tzm0QMJevU1F-rJPA8DoZ-nf8aVq6RcyuetH2lP5sOuQksZ9NAcE-7aZLkuV2FCXPnSlfMsRxYDNpkGyZ1ntUx5jzeVhtEgluACitqudFKqtH7mKqWaDJQd6wIJH9RC1nBDaJOtNzO7LEmNEkAOv0fyEYvJEDlbnI6AwQY/s16000/Intercambio%20de%20clave%20de%20Diffie-Hellman.png" /></a></div></div></div></div></div>Mikel García Larraganhttp://www.blogger.com/profile/03118239524461394157noreply@blogger.com0tag:blogger.com,1999:blog-1846493661397027137.post-78950695487141461762023-08-11T19:51:00.019+02:002023-09-09T08:01:26.642+02:00Criptografía (CCXC): Criptografía de curva elíptica (ECC)<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3Q_9zMYwR9AIM3Ac54djn042fcgkMjVbCts310cdNXyriyqDanSCRGKdoQ0q4dsa5sK41A0ANudsATMBjjBOXexPPiq_EVSvdFRT34G7AF7XmWs4bWt8VTeM5EMTBhTse4J7-WevN-NFJkR72Bb7Wtnkvm0ksCm7DrlAgXtKnp2r4F_gZDQDk3dB5/s179/Criptograf%C3%ADa%20de%20curva%20el%C3%ADptica.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="179" data-original-width="144" height="179" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3Q_9zMYwR9AIM3Ac54djn042fcgkMjVbCts310cdNXyriyqDanSCRGKdoQ0q4dsa5sK41A0ANudsATMBjjBOXexPPiq_EVSvdFRT34G7AF7XmWs4bWt8VTeM5EMTBhTse4J7-WevN-NFJkR72Bb7Wtnkvm0ksCm7DrlAgXtKnp2r4F_gZDQDk3dB5/s1600/Criptograf%C3%ADa%20de%20curva%20el%C3%ADptica.png" width="144" /></a></div>Tal y como nos cuenta wikipedia, <b><span style="color: #45818e;">la </span></b><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_de_curva_el%C3%ADptica"><span style="color: #2b00fe;">Criptografía de Curva Elíptica</span></a> (ECC, por las siglas e<span style="font-family: inherit;">n inglés de '<i style="background-color: white; color: #202122;">Elliptic curve cryptography</i>') <b><span style="color: #45818e;">es una v<span style="font-family: inherit;">ariante </span><span style="background-color: white;">de la </span></span></b><span style="background-color: white;"><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica"><span style="color: #2b00fe;">criptografía asimétrica o de clave pública</span></a><span style="color: #45818e;"><b> basada en las </b></span></span><b><span style="color: #45818e;">matemáticas<span style="background-color: white;"> de las </span></span></b><span style="background-color: white;"><a href="https://es.wikipedia.org/wiki/Curva_el%C3%ADptica"><span style="color: #2b00fe;">curvas elípticas</span></a><span style="color: #202122;"> y se emplea para implementar algunos de los criptosistemas de este tipo ya existentes.</span></span></span><div><p style="text-align: left;"><span><span style="color: #202122;">Antes que nada, decir que sigo empeñado en compartir lo que voy aprendiendo sobre </span><a href="https://es.wikipedia.org/wiki/Criptolog%C3%ADa"><span style="color: #2b00fe;">criptología</span></a><span style="color: #202122;"> de la forma más comprensible que pueda y esperando no equivocarme demasiado al contarlo, pero en este caso no sé si voy a ser capaz; la </span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa"><span style="color: #2b00fe;">criptografía</span></a><span style="color: #202122;"> moderna tiene una profunda base matemática que supera con creces mi capacidad y talento (tal y como suelo decir, poco en ambos casos).</span></span></p><p style="text-align: left;"><span><span style="color: #202122;">Por tanto, fruto de ese empeño y de mi propia incapacidad, </span><b><span style="color: #45818e;">voy a evitar entrar en mayores profundidades matemáticas y a centrarme en lo que he entendido sobre el uso de estas curvas en la</span></b><span style="color: #202122;"> </span></span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa" style="font-family: inherit;"><span style="color: #2b00fe;">criptografía</span></a><span><span style="background-color: white; font-family: inherit;"><span><span style="color: #202122;">, </span><b><span style="color: #45818e;">pero en este caso es inevitable un breve barniz matemático</span></b><span style="color: #202122;"> antes de entrar en materia.</span></span></span></span></p><p style="text-align: left;"><span><span style="background-color: white; font-family: inherit;"><span><span style="color: #202122;">La </span><a href="https://es.wikipedia.org/wiki/Curva_el%C3%ADptica"><span style="color: #2b00fe;">curva elíptica</span></a><span style="color: #202122;"> cuya gráfica sirve para ilustrar este post está definida sobre los números reales, es decir, los infinitos puntos que la forman tienen como coordenadas número reales.</span></span></span></span></p><p style="text-align: left;"><span><span style="background-color: white; font-family: inherit;"><span style="color: #45818e;"><b>Las </b></span></span></span><a href="https://es.wikipedia.org/wiki/Curva_el%C3%ADptica"><span style="color: #2b00fe;">curvas elípticas</span></a><span><span style="background-color: white; font-family: inherit;"><span style="color: #45818e;"><b> tienen propiedades que las hacen idóneas para su uso en la </b></span></span></span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa" style="font-family: inherit;"><span style="color: #2b00fe;">criptografía</span></a>:<span style="background-color: white; color: #212529;"> son curvas suaves</span><span style="color: #202122;">, es decir, no presentan vértices ("picos"), no se cortan a sí mismas y presentan simetría respecto al eje de abcisas.</span></p><p style="text-align: left;"><span><span style="color: #202122;">Las </span><b><span style="color: #45818e;">operaciones sobre puntos de las curvas elípticas</span></b><span style="color: #202122;"> son:</span></span></p><p style="text-align: left;"><span><span style="color: #202122;"></span></span></p><div class="separator" style="clear: both; text-align: center;"><span><span style="color: #202122;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgY3MOG65Pj3yhSwogjVzQgAEYSFjMHpo6Siiv_JbyqnvPK7Jyafj0EYbwkm8jtAO0JLaK9FpaRLsJmnsrt37n-TVeq4hxR3yjBxltWId4c9Lp6wc-_7OlsWccSKL7VItbuzHTPyhrnd_axtJzqVBzsKtgLQUKY-7-LejIgcVEVZEYX6KUib7zFteUW/s222/Criptograf%C3%ADa%20de%20curva%20el%C3%ADptica_suma%20de%20puntos.png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="222" data-original-width="179" height="222" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgY3MOG65Pj3yhSwogjVzQgAEYSFjMHpo6Siiv_JbyqnvPK7Jyafj0EYbwkm8jtAO0JLaK9FpaRLsJmnsrt37n-TVeq4hxR3yjBxltWId4c9Lp6wc-_7OlsWccSKL7VItbuzHTPyhrnd_axtJzqVBzsKtgLQUKY-7-LejIgcVEVZEYX6KUib7zFteUW/s1600/Criptograf%C3%ADa%20de%20curva%20el%C3%ADptica_suma%20de%20puntos.png" width="179" /></a></span></span></div><span><span style="color: #202122;">1.- La </span><b><span style="color: #45818e;">suma de puntos</span></b><span style="color: #202122;">: sean </span><i style="color: #202122;">P = (</i></span><span style="font-family: inherit;"><i>x<sub>1</sub></i></span><i><sub style="font-family: Calibri, sans-serif;">, </sub></i><i>y<sub>1</sub></i><i style="color: #202122;">)</i><span style="color: #202122;"> y </span><i style="color: #202122;">Q </i><span><span style="color: #202122;"><i>= (</i></span><span style="color: black;"><i>x<sub>2</sub></i></span><i style="color: black;"><sub style="font-family: Calibri, sans-serif;">, </sub></i><i style="color: black;">y<sub>2</sub></i><i style="color: #202122;">)</i><span style="color: #202122;"> dos puntos de una </span><a href="https://es.wikipedia.org/wiki/Curva_el%C3%ADptica" style="background-color: white;"><span style="color: #2b00fe;">curva elíptica</span></a><span style="color: #202122;"> (</span></span><i style="color: #202122;">'E'</i><span style="color: #202122;">); la suma de ambos puntos, <i>P + Q</i>, será un tercer punto de la curva </span><span><i style="color: #202122;">R = (</i></span><i>x<sub>3</sub></i><i><sub style="font-family: Calibri, sans-serif;">, </sub></i><i>y<sub>3</sub></i><i style="color: #202122;">)</i><span style="color: #202122;"> que se puede obtener de la siguiente manera:</span><p></p><p style="text-align: left;"><span style="color: #202122;">1.1.- Se traza una recta secante entre los dos puntos de <i>'E'</i> a sumar, en nuestro caso <i>'P'</i> y <i>'Q'</i>.</span></p><p style="text-align: left;"><span style="color: #202122;">1.2.- Se busca el tercer punto de corte de la recta secante con <i>'E'</i>.</span></p><p style="text-align: left;"><span style="color: #202122;">1.3.- La suma de ambos puntos, <i>P + Q</i>, es el punto simétrico </span><span style="color: #202122;">respecto al eje de abcisas </span><span style="color: #202122;">del tercer punto de corte.</span></p><p style="text-align: left;"><span style="color: #202122;">¿Qué pasa si no hay un tercer punto de corte en <i>'E'</i> y la línea se pierde en el infinito? Pues en ese caso se dice que el tercer punto de corte es un punto situado </span><span style="color: #202122;">en el infinito, </span><span style="color: #202122;"><i>𝒪</i></span><span style="color: #202122;">, y que </span><i style="color: #202122;">P + Q = </i><i style="color: #202122;">𝒪</i><span style="color: #202122;">.</span></p><p style="text-align: left;"><span style="color: #202122;"><i>𝒪</i> es el elemento neutro para la suma, es decir: </span><i style="color: #202122;">P + </i><i style="color: #202122;">𝒪</i><i style="color: #202122;"> = </i><i style="color: #202122;">P</i><span style="color: #202122;">.</span></p><p style="text-align: left;"><span><span style="color: #202122;"></span></span></p><span><span style="color: #202122;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh--iuJqAsTOLz3uhv5qAY8P9PltdtmSsQiEZrshY7ZSy4iE7wIJ98qZWMULrXVX8Y71ZM4D5S8qoNp_g7AaMdr_q91bmUL8Xmvme3zqoZzrdB70SoGBtsuxM3QqzLIvNAhpi299iPkkpDyoBrKoM-vb3CMv0DdEiuVt0hK359vKYY-O-TxGuPwRfeP/s251/Criptograf%C3%ADa%20de%20curva%20el%C3%ADptica_multiplicaci%C3%B3n%20escalar.png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="251" data-original-width="202" height="251" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh--iuJqAsTOLz3uhv5qAY8P9PltdtmSsQiEZrshY7ZSy4iE7wIJ98qZWMULrXVX8Y71ZM4D5S8qoNp_g7AaMdr_q91bmUL8Xmvme3zqoZzrdB70SoGBtsuxM3QqzLIvNAhpi299iPkkpDyoBrKoM-vb3CMv0DdEiuVt0hK359vKYY-O-TxGuPwRfeP/s1600/Criptograf%C3%ADa%20de%20curva%20el%C3%ADptica_multiplicaci%C3%B3n%20escalar.png" width="202" /></a></div>2.- La </span><b><span style="color: #45818e;">multiplicación escalar</span></b><span><span style="color: #202122;">: esta operación </span><b><span style="color: #45818e;">es la base de la</span></b> </span></span><span><span style="color: #202122;"><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_de_curva_el%C3%ADptica"><span style="color: #2b00fe;">Criptografía de Curva Elíptica (ECC)</span></a> y consiste en multiplicar un escalar </span></span><span style="color: #202122;">(</span><i style="color: #202122;">'k'</i><span style="color: #202122;"> )</span><span><span style="color: #202122;"> por un punto. Si </span><i style="color: #202122;">'P'</i><span style="color: #202122;"> es un punto de la curva: </span><i style="color: #202122;">k * P = P + P + P...+ P</i><span style="color: #202122;"> (suma </span></span><i><span style="color: #202122;">'</span><span style="color: #202122;">k'</span></i><span style="color: #202122;"> veces </span><span><span style="color: #202122;">de </span></span><i style="color: #202122;">'P'</i><span style="color: #202122;">).</span></div><div><p></p><p style="text-align: left;"><span><span style="color: #202122;">Por ejemplo: sea </span><i style="color: #202122;">P = (</i></span><span><i>x<sub>1</sub></i></span><i><sub style="font-family: Calibri, sans-serif;">, </sub></i><i>y<sub>1</sub></i><i style="color: #202122;">)</i><span style="color: #202122;"> un</span><span><span style="color: #202122;"> punto de una </span><a href="https://es.wikipedia.org/wiki/Curva_el%C3%ADptica" style="background-color: white;"><span style="color: #2b00fe;">curva elíptica</span></a><span style="color: #202122;"> (</span></span><i style="color: #202122;">'E'</i><span style="color: #202122;">); el resultado de <i>2 * P = P + P</i></span><span style="color: #202122;"> </span><span style="color: #202122;">será otro punto de la curva </span><span><i style="color: #202122;">Q </i></span><span><i style="color: #202122;">= (</i></span><i>x<sub>2</sub></i><i><sub style="font-family: Calibri, sans-serif;">, </sub></i><i>y<sub>2</sub></i><i style="color: #202122;">)</i><span style="color: #202122;"> que se puede obtener de la siguiente manera</span><span style="color: #202122;">:</span></p><p></p><p><span style="color: #202122;">2.1.- Se traza la recta tangente al punto <i>'P'</i>.</span></p><p><span style="color: #202122;">2.2.- Se busca el segundo punto de corte de la recta tangente con <i>'E'</i>.</span></p><p><span style="color: #202122;">2.3.- <i>Q = 2 * P = P + P </i></span><span style="color: #202122;"><i>= (</i></span><span style="color: black;"><i>x<sub>2</sub></i></span><i><sub style="font-family: Calibri, sans-serif;">, </sub></i><i>y<sub>2</sub></i><i style="color: #202122;">)</i><span style="color: #202122;">, es el punto simétrico </span><span style="color: #202122;">respecto al eje de abcisas </span><span style="color: #202122;">del segundo punto de corte.</span></p><div><p><span><span style="background-color: white;"><span style="color: #202122;">Dicho lo anterior, </span><b><span style="color: #45818e;">en</span></b></span><b><span style="color: #45818e;"> </span></b></span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa" style="font-family: inherit;"><span style="color: #2b00fe;">criptografía</span></a><span style="color: #45818e; font-family: inherit;"><b> </b></span><span style="font-family: inherit;"><b><span style="color: #45818e;">se usan las </span></b><a href="https://es.wikipedia.org/wiki/Curva_el%C3%ADptica" style="background-color: white;"><span style="color: #2b00fe;">curvas elípticas</span></a><b><span style="color: #45818e;"> definidas sobre </span></b></span><a href="https://es.wikipedia.org/wiki/Cuerpo_finito" style="font-family: inherit;"><span style="color: #2b00fe;">cuerpos finitos</span></a><span style="color: #202122; font-family: inherit;">, es decir, </span><span style="background-color: white;"><span style="color: #212529;">curvas que tienen un número finito de puntos cuyas coordenadas son números enteros, lo que proporciona la posibilidad de realizar los cálculos sobre los puntos de forma eficiente y evita los errores de redondeo que podrían producirse con números reales. Habitualmente, </span><b><span style="color: #45818e;">se suelen definir las </span></b><a href="https://es.wikipedia.org/wiki/Curva_el%C3%ADptica"><span style="color: #2b00fe;">curvas elípticas</span></a><b><span style="color: #45818e;"> sobre un cuerpo finito del tipo <i>ℤ</i></span></b></span><i><sub><b><span style="color: #45818e;">p</span></b></sub></i><span style="background-color: white;"><b><span style="color: #45818e;">, que tienen un número primo de elementos</span></b><span style="color: #212529;">; </span></span><span style="color: #202122; font-family: inherit;">curvas definidas por la siguiente ecuación:</span></p><p style="text-align: center;"><span style="font-family: inherit;"><span style="background-color: white; color: #202122;"><i><span style="background-color: transparent;">y<sup>2</sup></span><span style="color: black;"> </span></i></span></span><i style="color: #202122;"><span style="color: black;"><span>mod p </span></span></i><i style="color: #202122; font-family: inherit;"><span style="color: black;">= (</span><span style="color: black;">x<sup>3</sup></span><span style="color: black;"> + ax<span> + b) mod p</span></span></i></p><p><span><span style="background-color: white; font-family: inherit;"><span><b><span style="color: #45818e;">Al definir la </span></b><a href="https://es.wikipedia.org/wiki/Curva_el%C3%ADptica"><span style="color: #2b00fe;">curva elíptica</span></a><span style="color: #202122;"> </span><b><span style="color: #45818e;">sobre un</span></b><span style="color: #202122;"> </span><a href="https://es.wikipedia.org/wiki/Cuerpo_finito" style="color: #202122; font-family: inherit;"><span style="color: #2b00fe;">cuerpo finito</span></a><span style="color: #202122;"> </span><b><span style="color: #45818e;">se obtiene algo</span></b><b><span style="color: #45818e;"> que</span></b><span style="color: #202122;"> se asemeja poco o nada a la representación gráfica de la curva sobre números reales, más bien </span><b><span style="color: #45818e;">tiene el aspecto de un conjunto de puntos aleatorios</span></b><span style="color: #202122;">, pero todavía se puede observar la simetría:</span></span></span></span></p><p><span><span style="background-color: white; font-family: inherit;"></span></span></p><div class="separator" style="clear: both; color: #202122; text-align: center;"><span><span style="background-color: white; font-family: inherit;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqRacWdVlNgoXdXTUPeH0BxtZbSHUqrwQt3pEVyZ6-97z1Oy_JiWBCFohmSJN8aJ8P8OExyYiVrjRuiXas5Br_NMmNPKRI7u8IzzSOgPA8vjgBp_EmvXr8ifMzIao2Hz0dzOj_Ph6RbQAouqzlpqdS7WyvxRrXyFUoHxf5kmYbFmHwJHO1R0AR_Wnx/s620/Criptograf%C3%ADa%20de%20curva%20el%C3%ADptica%20EC%20sobre%20cuerpo%20finito.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="280" data-original-width="620" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqRacWdVlNgoXdXTUPeH0BxtZbSHUqrwQt3pEVyZ6-97z1Oy_JiWBCFohmSJN8aJ8P8OExyYiVrjRuiXas5Br_NMmNPKRI7u8IzzSOgPA8vjgBp_EmvXr8ifMzIao2Hz0dzOj_Ph6RbQAouqzlpqdS7WyvxRrXyFUoHxf5kmYbFmHwJHO1R0AR_Wnx/s16000/Criptograf%C3%ADa%20de%20curva%20el%C3%ADptica%20EC%20sobre%20cuerpo%20finito.png" /></a></span></span></div><span><span style="background-color: white; font-family: inherit;"><b><span style="color: #45818e;">Y ya tenemos todo listo para empezar a utilizar la</span></b><span style="color: #202122;"> </span></span></span><span style="background-color: white; font-family: inherit;"><span style="color: #202122;"><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_de_curva_el%C3%ADptica"><span style="color: #2b00fe;">Criptografía de Curva Elíptica (ECC)</span></a>: </span><b><span style="color: #45818e;">la </span></b></span><a href="https://es.wikipedia.org/wiki/Curva_el%C3%ADptica" style="background-color: white;"><span style="color: #2b00fe;">curva elíptica</span></a><span style="background-color: white; color: #45818e; font-family: inherit;"><b> definida sobre un </b></span><a href="https://es.wikipedia.org/wiki/Cuerpo_finito" style="background-color: white; font-family: inherit;"><span style="color: #2b00fe;">cuerpo finito</span></a><span style="background-color: white; font-family: inherit;"><b><span style="color: #45818e;"> y la operación de multiplicación escalar sobre un punto de ésta</span></b><span style="color: #202122;">. Es decir, dicho de forma muy resumida, se trata de multiplicar un punto de esta curva (</span><i style="color: #202122;">'P'</i><span style="color: #202122;">) por un escalar (</span><i style="color: #202122;">'k'</i><span style="color: #202122;"> ) hasta obtener un nuevo punto de la curva (</span><i style="color: #202122;">'Q'</i><span style="color: #202122;">), y nadie podrá saber, aún conociendo la curva empleada, el punto de partida y el punto final, cuál es el escalar utilizado (</span><i style="color: #202122;">'k'</i><span style="color: #202122;">), que será la clave privada.</span><br /></span><p></p><p><span><span style="background-color: white; color: #202122; font-family: inherit;"><span style="color: #212529;"><span style="color: #202122;"><span style="color: #292929;">Es decir, al igual que en todos los algoritmos de </span></span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica"><span style="color: #2b00fe;">criptografía asimétrica o de clave pública</span></a><span style="color: #292929;">, la </span></span></span></span><span style="background-color: white; font-family: inherit;"><span style="color: #292929;"><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_de_curva_el%C3%ADptica"><span style="color: #2b00fe;">Criptografía de Curva Elíptica (ECC)</span></a> basa su seguridad en la utilización de una </span><a href="https://es.wikipedia.org/wiki/Funci%C3%B3n_unidireccional#"><span style="color: #2b00fe;">función de un solo sentido</span></a><span style="color: #292929;">; </span></span><span style="background-color: white; color: #292929; font-family: inherit;">muy fácil de resolver en un sentido, pero <span style="font-family: inherit;">muy difícil de revertir; en el caso de la </span></span><span style="background-color: white; color: #292929; font-family: inherit;"><span style="font-family: inherit;"><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_de_curva_el%C3%ADptica"><span style="color: #2b00fe;">Criptografía de Curva Elíptica (ECC)</span></a> se trata del </span></span><span style="background-color: white; font-family: inherit;"><span style="color: #222222;">problema de logaritmo discreto de curva elíptica (PLDCE)</span><span style="color: #292929;">.</span></span></p><p><span style="font-family: inherit;"><span style="background-color: white;"><b><span style="color: #45818e;">Las ventajas</span></b><span style="color: #45818e;"><b> de la </b></span></span></span><span style="font-family: inherit;"><span style="background-color: white;"><span style="color: #202122;"><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_de_curva_el%C3%ADptica"><span style="color: #2b00fe;">Criptografía de Curva Elíptica (ECC)</span></a> frente a los criptosistemas anteriores de </span></span></span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica"><span style="color: #2b00fe;">criptografía asimétrica o de clave pública</span></a><span style="background-color: white; font-family: inherit;"><span style="color: #202122;">, tales como </span><a href="https://es.wikipedia.org/wiki/RSA"><span style="color: #2b00fe;">RSA</span></a><span style="color: #202122;"> o </span><a href="https://es.wikipedia.org/wiki/Cifrado_ElGamal"><span style="color: #2b00fe;">ElGamal</span></a><span style="color: #202122;">, serían </span><b><span style="color: #45818e;">su rapidez, la posibilidad de utilizar claves más cortas y su escalabilidad</span></b><span style="color: #202122;">, todo ello con un nivel de </span></span><span style="background-color: white; color: #202122; font-family: inherit;">seguridad equivalente.</span></p><div><div><span><span style="background-color: white; color: #202122; font-family: inherit;"><span style="color: #212529;">Para finalizar, decir que </span></span></span><span style="color: #45818e;"><b>la </b></span><span><span style="background-color: white; color: #202122; font-family: inherit;"><span style="color: #212529;"><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_de_curva_el%C3%ADptica"><span style="color: #2b00fe;">Criptografía de Curva Elíptica (ECC)</span></a>, como </span></span></span><span style="background-color: white; color: #202122;"><span style="color: #292929;">en<span style="font-family: inherit;"> el caso de todos los algoritmos de </span></span></span><span style="font-family: inherit;"><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica"><span style="color: #2b00fe;">criptografía asimétrica o de clave pública</span></a><span><span style="color: #292929;">, </span><b><span style="color: #45818e;">encuentra como principales áreas de aplicación las correspondientes a</span></b></span><span><b><span style="color: #45818e;">l cifrado de información, la firma
digital y el intercambio de claves</span></b><span style="color: #444444;">, para cada una de las cuales hay
diferentes estándares que utilizan curvas elípticas: </span><i style="color: #444444;">'</i></span></span><i><span style="background-color: white; font-family: inherit;">Integrated Encryption Scheme</span><span style="color: #444444; font-family: inherit;">' </span></i><span style="background-color: white; color: #202122; font-family: inherit;">(</span><a href="https://en.wikipedia.org/wiki/Integrated_Encryption_Scheme" style="font-family: inherit;"><span style="color: #2b00fe;">ECIES</span></a><span style="color: #444444; font-family: inherit;">) para cifrado, </span><i style="font-family: inherit;"><span style="background-color: white; color: #202122;">'E</span><span style="background-color: white; color: #202122;">lliptic </span><span style="background-color: white; color: #202122;">C</span><span style="background-color: white; color: #202122;">urve </span><span style="background-color: white; color: #202122;">D</span><span style="background-color: white; color: #202122;">igital </span><span style="background-color: white; color: #202122;">S</span><span style="background-color: white; color: #202122;">ignature </span><span style="background-color: white; color: #202122;">A</span></i><span style="background-color: white; color: #202122; font-family: inherit;"><i>lgorithm'</i> </span><span style="color: #444444; font-family: inherit;">(</span><a href="https://es.wikipedia.org/wiki/ECDSA" style="font-family: inherit;"><span style="color: #2b00fe;">ECDSA</span></a><span style="font-family: inherit;"><span style="color: #444444;">) para firma digital y <i>'</i></span></span><span style="background-color: white; font-family: inherit;"><i>Elliptic-curve Diffie-Hellman</i></span><span style="color: #444444; font-family: inherit;"><i>'</i> (</span><a href="https://es.wikipedia.org/wiki/Elliptic-curve_Diffie-Hellman#" style="font-family: inherit;"><span style="color: #2b00fe;">ECDH</span></a><span style="font-family: inherit;"><span><span style="color: #444444;">) para intercambio de claves, </span><b><span style="color: #45818e;">pero también se utiliza</span></b><span style="color: #444444;">, por ejemplo, </span><b><span style="color: #45818e;">en la tecnología </span></b></span><a href="https://es.wikipedia.org/wiki/Cadena_de_bloques"><span style="color: #2b00fe;"><i>'</i></span></a></span><span style="background-color: #fbfbfb;"><a href="https://es.wikipedia.org/wiki/Cadena_de_bloques"><span style="color: #2b00fe;"><i>blockchain'</i></span></a><span style="color: #444444;">, por </span></span><span><span style="font-family: inherit;"><span style="color: #444444;">lo que es de aplicación a otros muy diversos campos, tales como: </span><b><span style="color: #45818e;">las criptomonedas</span></b><span style="color: #444444;">, </span><b><span style="color: #45818e;">el voto electrónico</span></b><span style="color: #444444;">, </span></span></span><span style="background-color: #fbfbfb; color: #444444;">etc</span><span style="background-color: #fbfbfb; color: #444444; font-family: inherit;">.</span></div><p style="text-align: left;"><span style="font-family: inherit;"><span style="background-color: #fbfbfb;"><b><span style="color: #45818e;">Por ejemplo</span></b><span style="color: #444444;">, </span></span><span style="background-color: white;"><a href="https://es.wikipedia.org/wiki/Generador_de_claves"><span style="color: #2b00fe;">secp256k1</span></a></span><span style="background-color: white;"><span style="color: #222222;"> </span><b><span style="color: #45818e;">es el tipo de curva elíptica utilizada como curva</span></b><span style="color: #222222;"> </span></span></span><a href="https://es.wikipedia.org/wiki/ECDSA" style="font-family: inherit;"><span style="color: #2b00fe;">ECDSA</span></a><span style="font-family: inherit;"><span style="background-color: white;"><span style="color: #222222;"> </span><b><span style="color: #45818e;">en el modelo criptográfico de</span></b> <a href="https://es.wikipedia.org/wiki/Bitcoin"><span style="color: #2b00fe;">Bitcoin</span></a><span style="color: #222222;">:</span></span></span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHfG2sG8LQ8peTofUOG6dtDzEYu8zwQqBeoX6uNlnw17ahhNr0-ENQPHE7WaViniJF3isPLUon4U9U666uBJ0tESU5yKC6gfILsfwJp2fXLmoh7fAvuIV3vBrrrBbnMJGafD-ij9fJQ3RvJN4_2AHFJLqjAaApM16CA0Qmu1ukgAisU5F_7sEibpel/s620/secp256k1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="290" data-original-width="620" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHfG2sG8LQ8peTofUOG6dtDzEYu8zwQqBeoX6uNlnw17ahhNr0-ENQPHE7WaViniJF3isPLUon4U9U666uBJ0tESU5yKC6gfILsfwJp2fXLmoh7fAvuIV3vBrrrBbnMJGafD-ij9fJQ3RvJN4_2AHFJLqjAaApM16CA0Qmu1ukgAisU5F_7sEibpel/s16000/secp256k1.png" /></a></div><div><p><b style="font-family: inherit;"><i>Quizás también te interese</i></b><span style="background-color: white; font-family: inherit;">:</span></p><p><span style="font-family: inherit;"><span style="background-color: white; color: #202122;"></span></span></p><div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-ccxci-curva-eliptica-sobre.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTA4BKIzdryx4GDpEHPrIwQ-TcrdOVUGqvY0CflYtQ44Sa5QzyOEJPUQS15iJdNIzZQPNoF61rXaWqx-jDLZ17RkEOjCJicS0pcQlj5oUU6twLMjTh2udKNgkREYOjsatP4quXdIHJoK4kS9GYBDMKbSj-9UvCc-eBIg6ccOBRjg1_YDIBfFH-OtZz/s16000/Curva%20el%C3%ADptica%20sobre%20cuerpo%20finito%20en%20python.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxxiv-el-algoritmo.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhj1Ip-zJEXAS2NyqCSUI7IzEg94Y5Apo6MD2J21Th8Z16fsCL0XJu0p20h3Kjq_DeQddXofM_KyeiPcFLMs7Uq81LIZuOgPgWQvRltibvxFVS9Mfjn3gDsv7iAinvmx0x6N62U91ELaItPFe8xwy2SISAZdED77ANld-7DikHPvsQM-0b6JlMaJMTL/s16000/El%20algoritmo%20ElGamal.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2016/10/criptografia-xxxv-el-algoritmo-rsa-i.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmuLy3WfFzpqlRc3oQmUt4XlQmD1JeJqRphUGdhRvInqrtUUmo8yu2rZglxHQD67fXOiQi7_tpz7Wk0vL1w8J6ncgZ3J3m9LGfvaKJ8pknSUSXyeKgu-lTc8QzLzI8pk2wgjShME3zztHuJu1okd9GwLBfvoS1MGAr607DDCzy_YQe2IhYlF5WIARP/s16000/El%20algoritmo%20RSA%20(I).png" /></a></div><div class="separator" style="clear: both; text-align: center;"></div></div></div></div></div></div>Mikel García Larraganhttp://www.blogger.com/profile/03118239524461394157noreply@blogger.com0tag:blogger.com,1999:blog-1846493661397027137.post-39891567691493481592023-08-07T19:41:00.008+02:002023-08-08T09:55:18.084+02:00Criptografía (CCLXXXVIII): Descifrado y verificación firma digital ElGamal en python<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjT4pVx0QKcyiM42rWCN6o-llxcRtVAPR4P97u8Rsdb6LvnvObUNe-KkwyxfEIAITfez_FubvOFNg2jw3oLc7jQaXtItWy9RhvYjBJg2PzzdxoJhzBAulVEZAMqXQjukrx-Y0Flxj8ppqt3EJp-JgG_sHPVgSGY7dRdScKcjhPhM-fXTkFZ7lp5ptlH/s350/ElGamal.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="108" data-original-width="350" height="99" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjT4pVx0QKcyiM42rWCN6o-llxcRtVAPR4P97u8Rsdb6LvnvObUNe-KkwyxfEIAITfez_FubvOFNg2jw3oLc7jQaXtItWy9RhvYjBJg2PzzdxoJhzBAulVEZAMqXQjukrx-Y0Flxj8ppqt3EJp-JgG_sHPVgSGY7dRdScKcjhPhM-fXTkFZ7lp5ptlH/s320/ElGamal.png" width="320" /></a></div><p style="text-align: left;">En un <a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-cclxxxvii-firma-digital-y.html"><span style="color: #2b00fe;">post anterior</span></a> puse un script <span>en python para implementar la firma digital y el cifrado </span><span><span>con el </span><span><a href="https://es.wikipedia.org/wiki/Esquema_de_firma_ElGamal#"><span style="color: #2b00fe;">esquema de firma digital</span></a><span> </span></span><span>y el</span><span> <a href="https://es.wikipedia.org/wiki/Cifrado_ElGamal"><span style="color: #2b00fe;">esquema de cifrado</span></a> <span>ElGamal, respectivamente</span></span>, y en éste </span><b><span style="color: #45818e;">incluyo otro </span></b><span style="color: #45818e; font-weight: bold;">script en python para implementar el descifrado y la verificación de la firma digital</span><span> con esos mismos esquemas, e</span>s decir, para las operaciones <span style="background-color: white; color: #292929;">que se realizan en la comunicación en el lado del receptor.</span></p><p></p><p style="text-align: left;"><span style="background-color: white;"><span style="color: #292929;">Antes de ver el script, </span><b><span style="color: #45818e;">creo que conviene recordar cómo se realizan dichas operaciones</span></b><span style="color: #292929;">, para lo que recomiendo leer </span><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxix-descifrado-rsa-y.html"><span style="color: #2b00fe;">este post</span></a><span style="color: #292929;"> en el que expliqué este asunto referido al caso de </span><a href="https://es.wikipedia.org/wiki/RSA"><span style="color: #2b00fe;">RSA</span></a><span style="color: #292929;">, pero que es lo mismo para el caso de aplicar los esquemas de </span></span><span><a href="https://es.wikipedia.org/wiki/Esquema_de_firma_ElGamal#"><span style="color: #2b00fe;">firma digital</span></a><span> </span></span><span>y de</span><span> <a href="https://es.wikipedia.org/wiki/Cifrado_ElGamal"><span style="color: #2b00fe;">cifrado</span></a> <span>ElGamal.</span></span></p><div><span style="background-color: white;"><p><span style="color: black; font-family: inherit;"><span><b style="color: #45818e;">El script que pongo a continuación implementa las operaciones </b></span></span><span><span><b style="color: #45818e;">de descifrado de la clave de sesión</b><span><b><span style="color: #45818e;"> </span></b><b><span style="color: #45818e;">mediante el </span></b><a href="https://es.wikipedia.org/wiki/Cifrado_ElGamal#"><span style="color: #2b00fe;">esquema de cifrado ElGamal</span></a><b style="color: black;"> </b></span></span></span><span style="color: black;"><span style="color: #45818e;"><b>y el descifrado del texto en claro </b></span></span><span style="color: black; font-family: inherit;"><span><b><span style="color: #45818e;">mediante</span></b> </span></span><span style="color: black; font-family: inherit;"><span style="color: #292929;">el algoritmo </span></span><a href="https://es.wikipedia.org/wiki/Advanced_Encryption_Standard" style="color: black;"><span style="color: #2b00fe;">AES</span></a><span style="color: #292929; font-family: inherit;"> de </span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_sim%C3%A9trica" style="color: black;"><span style="color: #2b00fe;">criptografía simétrica</span></a><span style="color: black; font-family: inherit;"><span style="color: #292929;"> en </span><a href="https://es.wikipedia.org/wiki/Modos_de_operaci%C3%B3n_de_una_unidad_de_cifrado_por_bloques#Modo_CBC_(Cipher-block_chaining)"><span style="color: #2b00fe;">modo de operación CBC</span></a></span><span>, mientras que la verificación de la firma digital se realiza utilizando el <a href="https://es.wikipedia.org/wiki/Esquema_de_firma_ElGamal"><span style="color: #2b00fe;">esquema de firma ElGamal</span></a>. </span></p><p style="color: black;"><span style="font-family: inherit;"><span style="color: #292929;">El par de claves </span></span><span style="color: #292929; font-family: inherit;"><a href="https://es.wikipedia.org/wiki/Cifrado_ElGamal"><span style="color: #2b00fe;">ElGamal</span></a>, publica y privada, para los dos usuarios participantes en la comunicación, emisor y receptor, son las mismas que las que generé </span><span style="color: #292929;">mediante el </span><span style="font-family: inherit;"><span style="color: #292929;"><a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-cclxxxv-generacion-de.html"><span style="color: #2b00fe;">script que puse en esta entrada</span></a> y utilicé en el </span><a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-cclxxxvii-firma-digital-y.html"><span style="color: #2b00fe;">post citado al principio</span></a><span style="color: #292929;">: </span></span><span style="font-family: inherit;"><span style="color: #292929;"><a href="https://drive.google.com/file/d/1E8kVLU2NGmdsUmHMH9E2wcrNGLOFW9IX/view?usp=sharing" style="font-family: inherit;"><span style="color: #2b00fe;">clave pública emisor</span></a><span style="color: #292929;">, </span><a href="https://drive.google.com/file/d/1aHACuNoSXxLYBheqyLpXn6BVK2DTbyWk/view?usp=sharing" style="font-family: inherit;"><span style="color: #2b00fe;">clave privada emisor</span></a><span style="color: #292929;">, </span><a href="https://drive.google.com/file/d/1uCRobe3ed_l-sgTUdJuZzc5d6E3pHiRC/view?usp=sharing" style="font-family: inherit;"><span style="color: #2b00fe;">clave pública receptor</span></a><span style="color: black;"><span style="color: #292929;">, </span><a href="https://drive.google.com/file/d/1uUDKIgRNCLiES9LiYojXvtXJqa-rUGi0/view?usp=sharing"><span style="color: #2b00fe;">clave privada receptor</span></a></span>.</span></span></p><p><span style="font-family: inherit;"><span><span><span style="color: #292929;">Para simular la recepción del mensaje cifrado utilizo un archivo que se ha creado tras la ejecución del script que puse en el </span><span><a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-cclxxxvii-firma-digital-y.html" style="color: black;"><span style="color: #2b00fe;">post citado al principio</span></a>, <a href="https://drive.google.com/file/d/1nmU5pdfWWlecFOc0ok3hIgkidL_pKKyw/view?usp=sharing"><span style="color: #2b00fe;">comunicación.txt</span></a></span></span><span style="color: #292929;">, y que contiene, codificada en base64, la siguiente información: </span></span></span>el par de valores correspondientes al cifrado de la clave de sesión <a href="https://es.wikipedia.org/wiki/Advanced_Encryption_Standard" style="color: black;"><span style="color: #2b00fe;">AES</span></a>, el criptograma y el par de valores correspondientes a la firma digital<span style="color: #292929; font-family: inherit;">.</span></p><p style="color: black;">Asimismo, para que el script funcione se necesita importar el siguiente módulo en el programa principal, que se encargará de <span>hacer de forma </span>eficiente<span> las operaciones de exponenciación modular</span><span style="font-family: inherit;">.</span></p><p style="color: black;"></p><pre style="color: black;"><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ALGORITMO DE EXPONENCIACIÓN MODULAR RÁPIDA:
#
# Algoritmo utilizado en operaciones de exponenciación modular
# con números muy grandes con objeto de hacerlas de forma
# más eficiente.
#
# http://mikelgarcialarragan.blogspot.com/
def exp_modular_rapida(b, e, m):
c = 1
e = bin(e)[2:]
for i in range(0, len(e)):
c = pow(c, 2, m)
if e[i]=="1":
c = c*b%m
return c</code>
<br /></pre><p style="color: black;"><span><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><p style="color: black;"><span style="color: #292929; font-family: inherit;"></span></p><p style="color: black;">El <b><span style="color: #45818e;">script</span></b> es el siguiente:</p><p style="color: black;"><span style="font-family: inherit;"><span style="color: #292929;">- </span><i style="color: #292929;"><u>Script python para el descifrado y verificación de la firma digital </u></i></span><i style="color: #292929;"><u>ElGamal</u></i><span style="color: #292929; font-family: inherit;">:</span></p><p style="color: black;"></p><pre style="color: black;"><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# DESCIFRADO Y VERIFICACIÓN DE FIRMA ELGAMAL:
#
# Descifrar y verificar firma digital utilizando el criptosistema ElGamal.
#
# http://mikelgarcialarragan.blogspot.com/
import hashlib
from Crypto.Cipher import AES
import pyasn1.type.univ
from pyasn1.codec.der import decoder
from base64 import b64decode
from exponenciacion_modular_rapida import exp_modular_rapida
# CIFRADO AES (CRIPTOGRAFÍA SIMÉTRICA).
def descifrar_aes(criptograma,clave):
iv = criptograma[:AES.block_size]
descifrar = AES.new(clave, AES.MODE_CBC, iv)
texto_claro = descifrar.decrypt(criptograma[AES.block_size:]).decode()
return texto_claro[:-ord(texto_claro[len(texto_claro) - 1:])]
# OBTENER DATOS DE LA CLAVE PÚBLICA ELGAMAL
def clave_publica_elgamal(fichero_pem):
f_clave_publica_elgamal = open(fichero_pem, "r")
clave_publica = f_clave_publica_elgamal.read()
clave_publica = clave_publica.replace("-----BEGIN ELGAMAL PUBLIC KEY-----","")
clave_publica = clave_publica.replace("-----END ELGAMAL PUBLIC KEY-----","")
datos_clave_publica_elgamal = pyasn1.codec.der.decoder.decode(b64decode(clave_publica.encode('ascii')))
f_clave_publica_elgamal.close()
return datos_clave_publica_elgamal
# OBTENER DATOS DE LA CLAVE PRIVADA ELGAMAL
def clave_privada_elgamal(fichero_pem):
f_clave_privada_elgamal = open(fichero_pem, "r")
clave_privada =f_clave_privada_elgamal.read()
clave_privada = clave_privada.replace("-----BEGIN ELGAMAL PRIVATE KEY-----","")
clave_privada = clave_privada.replace("-----END ELGAMAL PRIVATE KEY-----","")
datos_clave_privada_elgamal = pyasn1.codec.der.decoder.decode(b64decode(clave_privada.encode('ascii')))
f_clave_privada_elgamal.close()
return datos_clave_privada_elgamal
def main():
# MENÚ:
# Se presenta el menú para que se seleccione una opción.
salir = False
while not salir:
print ("")
print ("*** MENÚ *****************************************")
print ("1. Descifrar y verificar firma digital.")
print ("2. Salir.")
print ("")
opcion = input("Por favor, seleccione una opción: ")
if opcion == "1":
print ("")
print ("--- DESCIFRAR Y VERIFICAR FIRMA DIGITAL:")
# Descifrar y verificar firma digital: se reciben el par de valores correspondientes al
# cifrado de la clave de sesión AES, el criptograma y el par de valores correspondientes
# a la firma digital.
f_comunicacion = open("comunicacion.txt")
datos_comunicacion = f_comunicacion.readlines()
print ("[+] Clave de sesión AES cifrada (base64): (", datos_comunicacion[0].rstrip(), ",", datos_comunicacion[1].rstrip(),")")
print ("[+] Criptograma (base64):", datos_comunicacion[2].rstrip())
print ("[+] Firma digital (base64): (", datos_comunicacion[3], ",", datos_comunicacion[4].rstrip(),")")
# Se lee la clave privada del receptor para descifrar la clave de sesión.
datos_clave_privada = clave_privada_elgamal("private_receptor.pem")
print ("[+] Clave privada del receptor:")
print (" p:", datos_clave_privada[0][0])
print (" g:", datos_clave_privada[0][1])
print (" k:", datos_clave_privada[0][2])
print (" a:", datos_clave_privada[0][3])
# Se descifra la clave de sesión AES con la que se cifró el texto en claro con la clave
# privada del receptor (criptografía asimétrica).
clave_sesion = exp_modular_rapida(int(b64decode(datos_comunicacion[0])), datos_clave_privada[0][0]-1-datos_clave_privada[0][3],int(datos_clave_privada[0][0]))
clave_sesion = (clave_sesion * int(b64decode(datos_comunicacion[1])))%datos_clave_privada[0][0]
print ("[+] Clave de sesión AES descifrada (hexadecimal):", hex(clave_sesion)[2:])
# Se descifra el criptograma con la clave de sesión AES (criptografía simétrica).
texto_claro = descifrar_aes(b64decode(datos_comunicacion[2]),bytes.fromhex(hex(clave_sesion)[2:]))
print ("[+] Texto claro descifrado con la clave de sesión AES:", texto_claro)
# Se calcula el hash SHA-256 (256 bits) del texto en claro descifrado.
h_M = (hashlib.sha256(texto_claro.encode()).digest())
print ("[+] Hash calculado para el texto en claro descifrado (hexadecimal):", h_M.hex())
# Se lee la clave pública del emisor para verificar la firma digital.
datos_clave_publica = clave_publica_elgamal("public_emisor.pem")
print ("[+] Clave pública del emisor:")
print (" p:", datos_clave_publica[0][0])
print (" g:", datos_clave_publica[0][1])
print (" k:", datos_clave_publica[0][2])
# Se realizan los cálculos utilizando la clave pública del emisor (criptografía asimétrica)
# para verificar la firma recibida.
g_elevado_h_M = exp_modular_rapida(datos_clave_publica[0][1], int(h_M.hex(),16), int(datos_clave_publica[0][0]))
print ("[+] g ** h'(M) =", g_elevado_h_M)
k_elevado_r = exp_modular_rapida(datos_clave_publica[0][2], int(b64decode(datos_comunicacion[3])), int(datos_clave_publica[0][0]))
r_elevado_s = exp_modular_rapida(int(b64decode(datos_comunicacion[3])), int(b64decode(datos_comunicacion[4])), int(datos_clave_publica[0][0]))
print ("[+] (k ** r) * (r ** s) =", (k_elevado_r * r_elevado_s)%datos_clave_publica[0][0])
if g_elevado_h_M == (k_elevado_r * r_elevado_s)%datos_clave_publica[0][0]:
print ("[+] Se ha verificado la firma digital del contenido de la comunicación con el resultado de FIRMA DIGITAL VÁLIDA.")
else:
print ("[+] Se ha verificado la firma digital del contenido de la comunicación con el resultado de FIRMA DIGITAL NO VÁLIDA.")
elif opcion == "2":
print ("*** FIN ******************************************")
salir = True
else:
print ("*** ERROR: Opción no válida.")
if __name__ == '__main__':
main()</code>
<br /></pre><p style="color: black;"><span><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><p style="color: black;"><span><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><p style="color: black;"><b><span style="color: #45818e;">Lo ejecuto</span></b>:</p><p><span style="font-family: inherit;"><span style="color: black;"><span><span><span style="color: #292929;">Tras leerse del fichero que simula la comunicación, </span></span></span></span><span><a href="https://drive.google.com/file/d/1nmU5pdfWWlecFOc0ok3hIgkidL_pKKyw/view?usp=sharing"><span style="color: #2b00fe;">comunicacion.txt</span></a>: </span><span style="color: black;"><span><span><span style="color: #292929;"><span style="color: black;">el par de valores correspondientes al cifrado de la clave de sesión </span><a href="https://es.wikipedia.org/wiki/Advanced_Encryption_Standard"><span style="color: #2b00fe;">AES</span></a><span style="color: black;">, el criptograma y el par de valores correspondientes a la firma digital</span>, </span><b><span style="color: #45818e;">lo primero que hace el script es descifrar la clave de sesión </span></b><a href="https://es.wikipedia.org/wiki/Advanced_Encryption_Standard"><span style="color: #2b00fe;">AES</span></a><span><span style="color: #292929;"> </span><b><span style="color: #45818e;">con la</span></b><span style="color: #292929;"> </span></span></span></span></span></span><span style="color: black; font-family: inherit;"><span><span><span><span style="color: #292929;"><a href="https://drive.google.com/file/d/1uUDKIgRNCLiES9LiYojXvtXJqa-rUGi0/view?usp=sharing"><span style="color: #2b00fe;">clave privada del receptor</span></a> </span></span></span></span><span style="color: #292929;">(</span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica"><span style="color: #2b00fe;">criptografía asimétrica</span></a><span><span style="color: #292929;">) </span><b><span style="color: #45818e;">y descifrar el texto en claro cifrado con ella por el emisor</span></b><span style="color: #292929;"> (</span></span></span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_sim%C3%A9trica" style="color: black;"><span style="color: #2b00fe;">criptografía simétrica</span></a><span style="color: black; font-family: inherit;"><span style="color: #292929;">).</span></span></p><p style="color: black;"><span><span><span></span></span></span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYKW2mwWDpco490Sst_g9bL21DXQR-DVHVk_EswF5iiZJgkFAwGoU7Tkm7__IC9Ixw90QRMMU2zgDESVv9HNdgvZFa35Ve6So1nHnPjRs-iFWF_S-OE9MsjeenuUh58sM8pgYhZC8AEJUO45ManyN9prpysqiRGqtbGt4nsXhj_NbJKMlxIT7W6jcf/s616/Descifrar%20y%20verificar%20firma%20digital_1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="325" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYKW2mwWDpco490Sst_g9bL21DXQR-DVHVk_EswF5iiZJgkFAwGoU7Tkm7__IC9Ixw90QRMMU2zgDESVv9HNdgvZFa35Ve6So1nHnPjRs-iFWF_S-OE9MsjeenuUh58sM8pgYhZC8AEJUO45ManyN9prpysqiRGqtbGt4nsXhj_NbJKMlxIT7W6jcf/s16000/Descifrar%20y%20verificar%20firma%20digital_1.png" /></a></div><p style="color: black;"></p><p style="color: black;"></p><p style="color: black;"><b><span style="color: #45818e;">Lo siguiente</span></b> que hace el script <b><span style="color: #45818e;">es calcular el hash</span></b> <a href="https://es.wikipedia.org/wiki/SHA-2"><span style="color: #2b00fe;">SHA-256</span></a> <span style="color: #45818e;"><b>del texto en claro descifrado</b></span>.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjV9WO9zw2jwSULvppYZfHMN5INP7ku1tZHOWBPYS-vYxBY9squHHB7AkavLGch61ljSnrCQHQUVwXLDDkpMvabx8q9_2bfZ8-pIqwXW8Bhmx5Y-YTOUIMYjZrPD08TLZbJ85C2ux3Kv4F85S0w74w5f_G0wZbPXWxpVCkPwAeGQ3d2Qxt-Xth-C5i-/s616/Descifrar%20y%20verificar%20firma%20digital_2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="145" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjV9WO9zw2jwSULvppYZfHMN5INP7ku1tZHOWBPYS-vYxBY9squHHB7AkavLGch61ljSnrCQHQUVwXLDDkpMvabx8q9_2bfZ8-pIqwXW8Bhmx5Y-YTOUIMYjZrPD08TLZbJ85C2ux3Kv4F85S0w74w5f_G0wZbPXWxpVCkPwAeGQ3d2Qxt-Xth-C5i-/s16000/Descifrar%20y%20verificar%20firma%20digital_2.png" /></a></div><p style="color: black;">Y, <b><span style="color: #45818e;">finalmente,</span></b> el script <b><span style="color: #45818e;">lee la</span></b> <a href="https://drive.google.com/file/d/1E8kVLU2NGmdsUmHMH9E2wcrNGLOFW9IX/view?usp=sharing" style="font-family: inherit;"><span style="color: #2b00fe;">clave pública del emisor</span></a> <b><span style="color: #45818e;">para validar mediante el </span></b><a href="https://es.wikipedia.org/wiki/Esquema_de_firma_ElGamal#"><span style="color: #2b00fe;">esquema de firma digital ElGamal</span></a><span> (</span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica"><span style="color: #2b00fe;">criptografía asimétrica</span></a><span>)</span> <b><span style="color: #45818e;">la firma digital que se ha recibido</span></b>.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgSyA82TYRo_nGdk_PotroGJO6p4LDHZ48Z77szmnpd4UNeQC8A_RkzXlzmk3G8WiqSYnFm9TfOjZqkMsoI6SFZZTI5UEuWbI94c37fUi4DSA8KBStbgolnRjm5G_gIU-bo_TyndwICipDsTEUQ8S2_GjKxmBp8QImc_Qi6yUBw8DZ7qgDAyTWcnlh/s729/Descifrar%20y%20verificar%20firma%20digital_3.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="729" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgSyA82TYRo_nGdk_PotroGJO6p4LDHZ48Z77szmnpd4UNeQC8A_RkzXlzmk3G8WiqSYnFm9TfOjZqkMsoI6SFZZTI5UEuWbI94c37fUi4DSA8KBStbgolnRjm5G_gIU-bo_TyndwICipDsTEUQ8S2_GjKxmBp8QImc_Qi6yUBw8DZ7qgDAyTWcnlh/s16000/Descifrar%20y%20verificar%20firma%20digital_3.png" /></a></div><p style="color: black;">Tal y como se puede observar en la figura anterior, en este caso el proceso de verificación de la firma digital termina con éxito y, por tanto, quedarían acreditadas tanto la autenticidad como la integridad del mensaje recibido.</p><p style="color: black;"><b style="font-family: inherit;"><i>Quizás también te interese</i></b><span style="font-family: inherit;">:</span></p></span></div><div><span style="background-color: white; color: #292929;"><div class="MsoNormal" style="color: black;"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-cclxxxvii-firma-digital-y.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNMt4fSRUcBTPyl5hd9K3MFW_m826SY5oowvUW3ieiVnnxJpiKik2zlyastQK-RUidTPnbBkef1stHF9YdgvRSDTnRVNznBPNA3B7PM-cqxJ69kZWBWId5NK7-YTnZ98_CpHIZcos74MtsgOIVGjBksT3lWswhyGV_9HZBceCyckxwZBqxA7wqZipu/s16000/Firma%20digital%20y%20cifrado%20ElGamal%20en%20python.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxxiv-el-algoritmo.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipFNBP3vjDI-BCwHt4L9LZy6KVoq1OE4XLIXCqTIDu2Uxca9udHt3KFH4p5F80DiIdmMzGzvsX6B1qUCcf8R7ElNFdXy1UXzMrST2CZIcKwNKcozaY9z_fbZF8naTWdms6OpxV5kk47dpgC043O71x3yUJ12uu5yEmOqAUehR7Drz79euz3Qj8aRG2/s16000/El%20algoritmo%20ElGamal.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-cclxxxvi-esquema-de-firma.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLnwM_PuujOdJkf8EnGdIxaOiXixrrhB8so4iqOr1HT1OZjuv7DKlSCo1-HbEGv75qynFQMlLJk6VMboQ69a5JumQOSKqkQfLWHaB6poYo8KPjEQJxVtAd-G5Yh4r_Yljl1l0z28YDz_DIonSV_09QjJC9_V08uyuKqTRk3AGbvrqAl_WYazu6IoLB/s16000/Esquema%20de%20firma%20digital%20ElGamal.png" /></a></div></div></span></div>Mikel García Larraganhttp://www.blogger.com/profile/03118239524461394157noreply@blogger.com0tag:blogger.com,1999:blog-1846493661397027137.post-74691476690244764242023-08-06T20:05:00.004+02:002023-08-13T12:34:52.906+02:00Criptografía (CCLXXXIX): Ataque a la firma digital ElGamal<p> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg_n-atz5wVi5YHx2BqiaGI3IaRgWrhfPDLN8nTvTtp9tQ1LhFt_EG-tPfC58SxouI2w1dDZPxHjOT5w_Jt6ssgTcVovJQ2CadqSKWWSbaN6luDvpu_rpR5nOkn0M_l3QHd6k6KDdhn0RLR_J3LejPhWzGEtoz2UA_3kPC5yv3sHOZeID_U-yJXRoL/s350/ElGamal.png" style="clear: left; display: inline; margin-bottom: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="108" data-original-width="350" height="99" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg_n-atz5wVi5YHx2BqiaGI3IaRgWrhfPDLN8nTvTtp9tQ1LhFt_EG-tPfC58SxouI2w1dDZPxHjOT5w_Jt6ssgTcVovJQ2CadqSKWWSbaN6luDvpu_rpR5nOkn0M_l3QHd6k6KDdhn0RLR_J3LejPhWzGEtoz2UA_3kPC5yv3sHOZeID_U-yJXRoL/s320/ElGamal.png" width="320" /></a><br /><b><span style="color: #45818e;">Tal y como decía</span></b> en <a href="http://mikelgarcialarragan.blogspot.com/2017/04/criptografia-lii-ataque-de.html"><span style="color: #2b00fe;">este post</span></a>:</p><p style="text-align: center;"><span style="color: #45818e; font-size: large;"><i><b>"El eslabón más débil de la cadena de seguridad (y la criptografía no es una excepción) lo constituimos las personas".</b></i></span></p><div class="separator" style="clear: both; text-align: center;"><p><a href="https://3.bp.blogspot.com/-2Mmz1X3gDlg/WP904Q2YVrI/AAAAAAAAH_Y/sHpnE6iNClULxslcgSHk_s0-EdtV7jitQCLcB/s1600/Vulnerabilidades.png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://3.bp.blogspot.com/-2Mmz1X3gDlg/WP904Q2YVrI/AAAAAAAAH_Y/sHpnE6iNClULxslcgSHk_s0-EdtV7jitQCLcB/s1600/Vulnerabilidades.png" /></a></p></div><p style="text-align: left;">Es decir, <b><span style="color: #45818e;">podemos tener un algoritmo criptográfico muy robusto</span></b> (muy seguro conceptualmente), como es el caso del <a href="https://es.wikipedia.org/wiki/Esquema_de_firma_ElGamal"><span style="color: #2b00fe;">esquema de firma digital Elgamal</span></a>, <b><span style="color: #45818e;">pero si las personas</span></b> que lo administramos y/o utilizamos <b><span style="color: #45818e;">no hacemos un uso adecuado del mismo éste podría ser "roto" con relativa facilidad</span></b>.</p><p style="text-align: left;">Ejemplos de lo anterior, pero hay multitud de ellos, son la mala utilización de la <a href="https://es.wikipedia.org/wiki/Enigma_(m%C3%A1quina)"><span style="color: #2b00fe;">máquina enigma</span></a> durante la <a href="https://es.wikipedia.org/wiki/Segunda_Guerra_Mundial"><span style="color: #2b00fe;">WWII</span></a> o la elección no adecuada de los dos números primos factores del módulo en <a href="https://es.wikipedia.org/wiki/RSA"><span style="color: #2b00fe;">RSA</span></a> o, incluso algo bastante más reciente y que tiene mucho que ver con lo que voy a contar en esta entrada, cuando en 2010 un grupo de hackers conocido como <i>'fail0verflow'</i> se hizo con la clave privada usada por Sony para firmar el software de la consola PlayStation 3 aprovechándose de la mala utilización por parte de esta empresa del <a href="https://es.wikipedia.org/wiki/ECDSA"><span style="color: #2b00fe;">esquema de firma digital ECDSA</span></a>.</p><p style="text-align: left;">Pues bien, <b><span style="color: #45818e;">en este post </span></b><span style="color: #45818e; font-weight: bold;">me voy a referir al ataque</span><b><span style="color: #45818e;"> que es posible realizar al</span></b> <a href="https://es.wikipedia.org/wiki/Esquema_de_firma_ElGamal"><span style="color: #2b00fe;">esquema de firma digital ElGamal</span></a> <b><span style="color: #45818e;">cuando se firman los hashes de dos documentos diferentes con el mismo valor de <i>'h'</i></span></b> (ver <a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-cclxxxvi-esquema-de-firma.html"><span style="color: #2b00fe;">este post</span></a> donde explico este protocolo de firma digital); lo que es una evidente mala utilización, ya que <i>'h'</i> deber ser un número primo aleatorio diferente para cada documento a firmar si no queremos que la firma se vea seriamente comprometida.</p><p style="text-align: left;">En este tipo de ataques <b><span style="color: #45818e;">el atacante</span><span style="color: #45818e;"> puede hacerse con la clave privada</span></b> del firmante, pero <b><span style="color: #45818e;">veamos cómo</span></b>:</p><p style="text-align: left;">1.- Supongamos que un <b><span style="color: #45818e;">usuario</span></b> tiene como valores de las claves, pública y privada, los siguientes (utilizo números pequeños para que se puedan realizar los cálculos manualmente):</p><div style="text-align: left;">1.1.- Clave pública: <b><span style="color: #45818e;"><i>(p = 995, g = 7, k = 832)</i></span></b>.</div><div style="text-align: left;">1.2.- Clave privada: <b><span style="color: #45818e;"><i>(a = 325)</i></span></b>.</div><p style="text-align: left;">2.- Supongamos también que <b><span style="color: #45818e;">el usuario firma dos documentos con el mismo valor de <i>'h'</i>, <i>103</i></span></b>; para <b><span style="color: #45818e;">el primero</span></b> de ellos se obtiene un hash (<i>h(M)</i>) de <b><span style="color: #45818e;"><i>939</i></span></b> y para <span style="color: #45818e;"><b>el segundo</b></span> un hash (<i>h(M')</i>) de <b style="color: #45818e;"><i>436</i></b>.</p><div style="text-align: left;">2.1.- Firma primer documento: <b><span style="color: #45818e;">(r = 13</span></b><b><span style="color: #45818e;">, s = 26)</span></b>.</div><div style="text-align: left;">2.2.- Firma segundo documento: <b><span style="color: #45818e;">(r = 13</span></b><b><span style="color: #45818e;">, s' = 687)</span></b></div><p style="text-align: left;">3.- Se calcula: <i>(h(M) * s' - h(M') * s) * inv(r * (s' - s), p-1) mod p-1 = (939 * 687 - 436 * 26))* 107 mod 994 = (981 - 402) * 107 mod 994 = 579 * 107 mod 994 = <b><span style="color: #45818e;">325</span></b></i></p><p>Y como se observa <b><span style="color: #45818e;">se obtiene la clave privada del usuario</span></b>, con lo que el atacante puede ahora firmar documentos como si fuera el usuario legítimo.</p><p style="text-align: left;"><b style="font-family: inherit;"><i>Quizás también te interese</i></b><span style="font-family: inherit;">:</span></p><div><div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-cclxxxvii-firma-digital-y.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNMt4fSRUcBTPyl5hd9K3MFW_m826SY5oowvUW3ieiVnnxJpiKik2zlyastQK-RUidTPnbBkef1stHF9YdgvRSDTnRVNznBPNA3B7PM-cqxJ69kZWBWId5NK7-YTnZ98_CpHIZcos74MtsgOIVGjBksT3lWswhyGV_9HZBceCyckxwZBqxA7wqZipu/s16000/Firma%20digital%20y%20cifrado%20ElGamal%20en%20python.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxxiv-el-algoritmo.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipFNBP3vjDI-BCwHt4L9LZy6KVoq1OE4XLIXCqTIDu2Uxca9udHt3KFH4p5F80DiIdmMzGzvsX6B1qUCcf8R7ElNFdXy1UXzMrST2CZIcKwNKcozaY9z_fbZF8naTWdms6OpxV5kk47dpgC043O71x3yUJ12uu5yEmOqAUehR7Drz79euz3Qj8aRG2/s16000/El%20algoritmo%20ElGamal.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-cclxxxvi-esquema-de-firma.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLnwM_PuujOdJkf8EnGdIxaOiXixrrhB8so4iqOr1HT1OZjuv7DKlSCo1-HbEGv75qynFQMlLJk6VMboQ69a5JumQOSKqkQfLWHaB6poYo8KPjEQJxVtAd-G5Yh4r_Yljl1l0z28YDz_DIonSV_09QjJC9_V08uyuKqTRk3AGbvrqAl_WYazu6IoLB/s16000/Esquema%20de%20firma%20digital%20ElGamal.png" /></a></div></div></div>Mikel García Larraganhttp://www.blogger.com/profile/03118239524461394157noreply@blogger.com0tag:blogger.com,1999:blog-1846493661397027137.post-53537188909331066842023-08-06T11:08:00.003+02:002023-08-06T11:34:53.296+02:00Criptografía (CCLXXXVII): Firma digital y cifrado ElGamal en python<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8zFmyuorWthgGqTVPEeWuRmYGmyhSH_7hmOHPa6lFd1SJ-tCadBinh0-poQ1uOEDGplsb3MNezByneCKTmiY_oAIrK-sMHjdXcWYnUZlL6oRuSGp8rW6JZMpZLKFoQk2-zl1q6SRodNIgt8AviOpN_o8uXv8pKQKipcWXlcp4oSHN8ZCm8wPh2uHM/s350/ElGamal.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="108" data-original-width="350" height="99" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8zFmyuorWthgGqTVPEeWuRmYGmyhSH_7hmOHPa6lFd1SJ-tCadBinh0-poQ1uOEDGplsb3MNezByneCKTmiY_oAIrK-sMHjdXcWYnUZlL6oRuSGp8rW6JZMpZLKFoQk2-zl1q6SRodNIgt8AviOpN_o8uXv8pKQKipcWXlcp4oSHN8ZCm8wPh2uHM/s320/ElGamal.png" width="320" /></a></div>Continúo poniendo scripts de programación en python para automatizar tareas que tengan relación con la <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa"><span style="color: #2b00fe;">criptografía</span></a>.<p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p><b><span style="color: #45818e;">En este post incluyo un </span></b><span style="color: #45818e; font-weight: bold;">script en python para implementar la firma digital y el cifrado con el </span><span><a href="https://es.wikipedia.org/wiki/Esquema_de_firma_ElGamal#"><span style="color: #2b00fe;">esquema de firma digital</span></a><b><span style="color: #45818e;"> </span></b></span><b><span style="color: #45818e;">y el</span></b><span style="font-family: inherit;"> <a href="https://es.wikipedia.org/wiki/Cifrado_ElGamal"><span style="color: #2b00fe;">esquema de cifrado</span></a> <span style="color: #45818e;"><b>ElGamal</b></span>.</span></p><p><span style="background-color: white;"><span style="background-color: transparent;">Antes de poner el script, recordar que en </span><a href="http://mikelgarcialarragan.blogspot.com/2016/10/criptografia-xxxv-el-algoritmo-rsa-i.html" style="background-color: transparent;"><span style="color: #2b00fe;">este post</span></a><span style="background-color: transparent;"> referido a </span></span><a href="https://es.wikipedia.org/wiki/RSA"><span style="color: #2b00fe;">RSA</span></a><span style="background-color: white;"><span style="background-color: transparent;">, decía que</span><span style="background-color: transparent;"> </span><b><span style="color: #45818e;">l</span></b></span><span style="font-family: inherit;"><span style="background-color: white;"><b><span style="color: #45818e;">os esquemas modernos de cifrado utilizan conjuntamente los conceptos de</span></b> <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica"><span style="color: #2b00fe;">clave pública</span></a> <b><span style="color: #45818e;">y</span></b> <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_sim%C3%A9trica"><span style="color: #2b00fe;">clave privada</span></a></span></span>, es decir, el mensaje o archivo completo se cifra con un algoritmo de <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_sim%C3%A9trica"><span style="color: #2b00fe;">clave privada o simétrica</span></a> (por ejemplo, <a href="https://es.wikipedia.org/wiki/Advanced_Encryption_Standard"><span style="color: #2b00fe;">AES</span></a>) y luego la clave empleada en ese cifrado (clave de sesión), a su vez, se cifra con un algoritmo de <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica"><span style="color: #2b00fe;">clave pública o asimétrica</span></a> (por ejemplo, <a href="https://es.wikipedia.org/wiki/RSA"><span style="color: #2b00fe;">RSA</span></a>):</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgL_3QoqhJSixvlKnGNRkIOymqGNE51zytCEcQ80v4wZfhiD0IjXmeJ4ihA0gT9VTpSKtBqXrWySmmZKTknx1N3khjCbq1i3p_ZSimqEd5m7S1nJuUMBHgRD_3uyjZ7TRjD-2g-tDWrwhxOvoUesdezSg08ArvD43HNqFi6VbCxV-Tz2f6AUaUhZD2C/s536/Criptograf%C3%ADa_Cifrado%20h%C3%ADbrido%20con%20firma%20digital.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="506" data-original-width="536" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgL_3QoqhJSixvlKnGNRkIOymqGNE51zytCEcQ80v4wZfhiD0IjXmeJ4ihA0gT9VTpSKtBqXrWySmmZKTknx1N3khjCbq1i3p_ZSimqEd5m7S1nJuUMBHgRD_3uyjZ7TRjD-2g-tDWrwhxOvoUesdezSg08ArvD43HNqFi6VbCxV-Tz2f6AUaUhZD2C/s16000/Criptograf%C3%ADa_Cifrado%20h%C3%ADbrido%20con%20firma%20digital.png" /></a></div><p><span style="font-family: inherit;"><span style="background-color: white; color: #292929;">Por tanto, como se ve en la figura anterior, el texto en claro se cifra mediante una clave de sesión, un número correspondiente a cada mensaje particular, y la clave de sesión se cifra utilizando la clave pública del receptor, de tal manera que sólo el receptor puede descifrar la clave de sesión mediante su clave privada (</span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica" style="background-color: white;"><span style="color: #2b00fe;">criptografía asimétrica</span></a><span style="background-color: white; color: #292929;">) y posteriormente descifrar el criptograma o texto en claro cifrado mediante la clave de sesión (</span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_sim%C3%A9trica"><span style="color: #2b00fe;">criptografía simétrica</span></a><span style="background-color: white; color: #292929;">).</span></span></p><p><span style="background-color: white;"><span style="font-family: inherit;">De esta forma, <b><span style="color: #45818e;">sólo se podrá obten<span style="font-family: inherit;">er la clave de sesión</span></span></b><span style="font-family: inherit;"> (</span></span></span><span style="font-family: inherit;"><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_sim%C3%A9trica"><span style="color: #2b00fe;">clave simétrica</span></a><span style="background-color: white;">) <b><span style="color: #45818e;">si se está en posesión de la</span></b> <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica"><span style="color: #2b00fe;">clave privada</span></a><b><span style="color: #45818e;">, y</span></b>, por consiguiente, <b><span style="color: #45818e;">si no se tiene esta última no se puede descifrar </span></b></span></span><b><span style="color: #45818e;">el criptograma o texto en claro cifrado</span></b><span style="background-color: white; font-family: inherit;">.</span></p><p><span style="font-family: inherit;"><span style="background-color: white;"><b><span style="color: #45818e;">Este esquema de cifrado se puede utilizar para mantener la confidencialidad de los mensajes y los archivos</span></b>, sin tardar demasiado ni consumir demasiados recursos informáticos, <b><span style="color: #45818e;">y <span><span>el esquema de firma digital</span><span> </span></span></span><span style="color: #45818e;">se puede utilizar para firmar digitalmente los mensajes y los archivos</span></b>, es decir, para garantizar al receptor que el emisor </span><span style="background-color: white;"><span style="color: #292929;">es realmente quien los ha enviado (</span><b><span style="color: #45818e;">autenticidad</span></b><span style="color: #292929;">: el emisor es quien dice ser) y para comprobar que no han sido interceptados y alterados por terceros (</span><b><span style="color: #45818e;">integridad</span></b><span style="color: #292929;">); con la característica adicional de </span><b><span style="color: #45818e;">no repudio</span></b><span><b><span style="color: #45818e;">, </span></b><b><span style="color: #45818e;">tanto </span></b><b><span style="color: #45818e;">en origen</span></b><span style="color: #292929;"> (el emisor no puede negar que creó y envió esos textos en claro) </span><b><span style="color: #45818e;">como en destino</span></b><span style="color: #292929;"> (</span></span></span></span><span style="background-color: white; color: #292929;">el receptor no puede negar que los recibió y recibió exactamente esos textos en claro</span><span style="background-color: white; color: #292929; font-family: inherit;">).</span></p><p><span style="background-color: white; font-family: inherit;"><span><b style="color: #45818e;">El script que pongo a continuación imple</b></span></span><b style="background-color: white; color: #45818e;">m</b><span style="background-color: white; font-family: inherit;"><span><b style="color: #45818e;">enta las operaciones de </b><span><a href="https://es.wikipedia.org/wiki/Esquema_de_firma_ElGamal#"><span style="color: #2b00fe;">firma digital</span></a></span><b style="color: #45818e;"> del texto en claro y de </b><span><a href="https://es.wikipedia.org/wiki/Cifrado_ElGamal"><span style="color: #2b00fe;">cifrado</span></a></span><b style="color: #45818e;"> de la clave de sesión</b><b><span style="color: #45818e;"> mediante ElGamal,</span></b></span></span><span style="background-color: white; font-family: inherit;"><span style="color: #45818e;"><b> y el cifrado del texto en claro mediante el algoritmo </b></span></span><a href="https://es.wikipedia.org/wiki/Advanced_Encryption_Standard"><span style="color: #2b00fe;">AES</span></a><span style="background-color: white; color: #292929; font-family: inherit;"> de </span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_sim%C3%A9trica"><span style="color: #2b00fe;">criptografía simétrica</span></a><span style="background-color: white; font-family: inherit;"><span style="color: #292929;"> en </span><a href="https://es.wikipedia.org/wiki/Modos_de_operaci%C3%B3n_de_una_unidad_de_cifrado_por_bloques#Modo_CBC_(Cipher-block_chaining)"><span style="color: #2b00fe;">modo de operación CBC</span></a></span><span style="background-color: white; color: #292929;">, es decir, las operaciones que se realizan en la comunicación desde el lado del emisor.</span></p><p><span style="background-color: white; font-family: inherit;"><span style="color: #292929;">Previamente he generado, mediante el </span><a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-cclxxxv-generacion-de.html"><span style="color: #2b00fe;">script que puse en esta entrada</span></a><span style="color: #292929;">, el par de claves </span></span><span style="font-family: inherit;"><span style="background-color: white;"><a href="https://es.wikipedia.org/wiki/Cifrado_ElGamal"><span style="color: #2b00fe;">ElGamal</span></a></span><span style="color: #292929;">, publica y privada, para los dos usuarios participantes en la comunicación, emisor y receptor: </span></span><a href="https://drive.google.com/file/d/1E8kVLU2NGmdsUmHMH9E2wcrNGLOFW9IX/view?usp=sharing" style="font-family: inherit;"><span style="color: #2b00fe;">clave pública emisor</span></a><span style="color: #292929; font-family: inherit;">, </span><a href="https://drive.google.com/file/d/1aHACuNoSXxLYBheqyLpXn6BVK2DTbyWk/view?usp=sharing" style="font-family: inherit;"><span style="color: #2b00fe;">clave privada emisor</span></a><span style="color: #292929; font-family: inherit;">, </span><a href="https://drive.google.com/file/d/1uCRobe3ed_l-sgTUdJuZzc5d6E3pHiRC/view?usp=sharing" style="font-family: inherit;"><span style="color: #2b00fe;">clave pública receptor</span></a><span style="font-family: inherit;"><span style="color: #292929;">, </span><a href="https://drive.google.com/file/d/1uUDKIgRNCLiES9LiYojXvtXJqa-rUGi0/view?usp=sharing"><span style="color: #2b00fe;">clave privada receptor</span></a><span style="color: #292929;">.</span></span></p><p>Asimismo, para que el script funcione se necesita importar el siguiente módulo en el programa principal, <span style="font-family: inherit;">que se encargará de hacer de forma </span>eficiente<span style="font-family: inherit;"> las operaciones de exponenciación modular</span><span style="font-family: inherit;">.</span></p><p></p><pre><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ALGORITMO DE EXPONENCIACIÓN MODULAR RÁPIDA:
#
# Algoritmo utilizado en operaciones de exponenciación modular
# con números muy grandes con objeto de hacerlas de forma
# más eficiente.
#
# http://mikelgarcialarragan.blogspot.com/
def exp_modular_rapida(b, e, m):
c = 1
e = bin(e)[2:]
for i in range(0, len(e)):
c = pow(c, 2, m)
if e[i]=="1":
c = c*b%m
return c</code>
<br /></pre><p><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><p><span style="background-color: white; color: #292929; font-family: inherit;"></span></p><p>El <b><span style="color: #45818e;">script</span></b> es el siguiente:</p><p><span style="font-family: inherit;"><span style="background-color: white; color: #292929;">- </span><i style="background-color: white; color: #292929;"><u>Script python para la firma digital y cifrado ElGamal</u></i><span style="background-color: white; color: #292929;">:</span></span></p><p></p><pre><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# FIRMA Y CIFRADO ELGAMAL:
#
# Firma digitalmente y cifra utilizando el esquema de firma y de cifrado ElGamal.
#
# http://mikelgarcialarragan.blogspot.com/
import hashlib
import random
import math
from Crypto import Random
from Crypto.Util.Padding import pad
from Crypto.Cipher import AES
import pyasn1.type.univ
from pyasn1.codec.der import decoder
from base64 import b64encode, b64decode
from exponenciacion_modular_rapida import exp_modular_rapida
# CIFRADO AES (CRIPTOGRAFÍA SIMÉTRICA).
def cifrar_aes(texto_claro,clave):
iv = Random.new().read(AES.block_size)
print("[+] IV (hexadecimal):", iv.hex())
cifrar = AES.new(clave, AES.MODE_CBC, iv)
criptograma = iv + cifrar.encrypt(pad(texto_claro.encode(), AES.block_size))
return criptograma
# OBTENER DATOS DE LA CLAVE PÚBLICA ELGAMAL
def clave_publica_elgamal(fichero_pem):
f_clave_publica_elgamal = open(fichero_pem, "r")
clave_publica = f_clave_publica_elgamal.read()
clave_publica = clave_publica.replace("-----BEGIN ELGAMAL PUBLIC KEY-----","")
clave_publica = clave_publica.replace("-----END ELGAMAL PUBLIC KEY-----","")
datos_clave_publica_elgamal = pyasn1.codec.der.decoder.decode(b64decode(clave_publica.encode('ascii')))
f_clave_publica_elgamal.close()
return datos_clave_publica_elgamal
# OBTENER DATOS DE LA CLAVE PRIVADA ELGAMAL
def clave_privada_elgamal(fichero_pem):
f_clave_privada_elgamal = open(fichero_pem, "r")
clave_privada =f_clave_privada_elgamal.read()
clave_privada = clave_privada.replace("-----BEGIN ELGAMAL PRIVATE KEY-----","")
clave_privada = clave_privada.replace("-----END ELGAMAL PRIVATE KEY-----","")
datos_clave_privada_elgamal = pyasn1.codec.der.decoder.decode(b64decode(clave_privada.encode('ascii')))
f_clave_privada_elgamal.close()
return datos_clave_privada_elgamal
def main():
# MENÚ:
# Se presenta el menú para que se seleccione una opción.
salir = False
while not salir:
print ("")
print ("*** MENÚ *****************************************")
print ("1. Firmar digitalmente y cifrar clave de sesión AES.")
print ("2. Salir.")
print ("")
opcion = input("Por favor, seleccione una opción: ")
if opcion == "1":
print ("")
print ("--- FIRMAR DIGITALMENTE Y CIFRAR CLAVE DE SESIÓN:")
# Firmar digitalmente y cifrar: Se introducen el texto en claro y la clave.
texto_claro = clave = ""
while texto_claro == "":
texto_claro = input('Texto en claro a cifrar: ')
if texto_claro != "":
while clave == "":
clave = input('Clave: ')
if clave != "":
# Se genera la clave de sesión AES con la que se va a cifrar el
# texto en claro y que, a su vez, va a ser cifrada con la clave
# pública del destinatario, que será descifrada por éste con su
# clave privada (criptografía asimétrica) para, a su vez, descifrar
# el criptograma (criptografía simétrica).
# La clave se genera a partir de la clave introducida por el usuario,
# que puede tener cualquier longitud, y de la cual se calcula su
# hash SHA-256 (256 bits).
# Ese hash será la clave de sesión (32 bytes).
clave_sesion = (hashlib.sha256(clave.encode()).digest())
print ("[+] Clave de sesión AES generada (hexadecimal):", clave_sesion.hex())
criptograma = cifrar_aes(texto_claro,clave_sesion)
print ("[+] Texto claro cifrado con la clave de sesión AES (hexadecimal):", criptograma.hex())
# Se lee la clave privada del emisor para firmar digitalmente el texto en claro.
datos_clave_privada = clave_privada_elgamal("private_emisor.pem")
print ("[+] Clave privada del emisor:")
print (" p:", datos_clave_privada[0][0])
print (" g:", datos_clave_privada[0][1])
print(" k:", datos_clave_privada[0][2])
print (" a:", datos_clave_privada[0][3])
#Se genera aleatoriamente un número primo ('h'), mayor o igual que 1 y menor o igual que p - 1,
#coprimo o primo relativo con phi(p)
while True:
h = random.randint(1, datos_clave_privada[0][0]-1)
if math.gcd(h, datos_clave_privada[0][0]-1) == 1:
break
print ("[+] Número primo 'h' coprimo con phi(p) generado aleatoriamente:", h)
# Se calcula la rúbrica del emisor ('r'), primera parte de la firma digital.
r = exp_modular_rapida(datos_clave_privada[0][1], h, int(datos_clave_privada[0][0]))
# Se calcula 's', segunda parte de la firma digital.
h_M = (hashlib.sha256(texto_claro.encode()).digest())
s = ((int(h_M.hex(),16) - datos_clave_privada[0][3] * r) * pow(h,-1,int(datos_clave_privada[0][0])-1))%(datos_clave_privada[0][0]-1)
print ("[+] Firma digital: (", r, ",", s, ")")
# Se lee la clave pública del receptor para cifrar la clave de sesión AES.
datos_clave_publica = clave_publica_elgamal("public_receptor.pem")
print ("[+] Clave pública del receptor:")
print (" p:", datos_clave_publica[0][0])
print (" g:", datos_clave_publica[0][1])
print(" k:", datos_clave_publica[0][2])
b = random.randint(1, (datos_clave_publica[0][0])-1)
c1 = exp_modular_rapida(datos_clave_publica[0][1], b,int(datos_clave_publica[0][0]))
c2 = (int(clave_sesion.hex(),16) * exp_modular_rapida(datos_clave_publica[0][2], b, int(datos_clave_publica[0][0])))%datos_clave_publica[0][0]
print ("[+] Clave de sesión cifrada con la clave pública Elgamal del receptor (hexadecimal): (", hex(c1)[2:], ",", hex(c2)[2:], ")")
f_comunicacion = open("comunicacion.txt", "w")
f_comunicacion.write((b64encode(str(c1).encode())).decode() + "\n")
f_comunicacion.write((b64encode(str(c2).encode())).decode() + "\n")
f_comunicacion.write(b64encode(criptograma).decode() + "\n")
f_comunicacion.write((b64encode(str(r).encode()).decode()) + "\n")
f_comunicacion.write((b64encode(str(s).encode()).decode()))
f_comunicacion.close()
else:
print ("*** ERROR: Por favor, introduzca la clave.")
else:
print ("*** ERROR: Por favor, introduzca el texto en claro a cifrar.")
elif opcion == "2":
print ("*** FIN ******************************************")
salir = True
else:
print ("*** ERROR: Opción no válida.")
if __name__ == '__main__':
main()</code>
<br /></pre><p><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><p><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><p><b><span style="color: #45818e;">Lo ejecuto</span></b>:</p><p><span><span style="background-color: white;"><span><span style="color: #292929;">Tras introducirse el mensaje o texto en claro a cifrar, </span><b><span style="color: #45818e;">lo primero que hace el script es generar la clave </span></b><a href="https://es.wikipedia.org/wiki/Advanced_Encryption_Standard"><span style="color: #2b00fe;">AES</span></a><span style="color: #292929;">, calculando el hash </span><a href="https://es.wikipedia.org/wiki/SHA-2"><span style="color: #2b00fe;">SHA-256</span></a><span style="color: #292929;"> de la clave introducida por el usuario, </span><b><span style="color: #45818e;">con la que se cifra el texto en claro y se obtiene el criptograma o texto en claro cifrado</span></b><span style="color: #292929;"> </span></span></span></span><span style="background-color: white; color: #292929;">(</span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_sim%C3%A9trica"><span style="color: #2b00fe;">criptografía simétrica</span></a><span style="background-color: white; color: #292929;">).</span></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKjgmbT7IE0AOmjb46s3zC8zdJsOOZ3k3818RlWoxTO9l7Tk8-XQtZMbFE0oATmUBaRFEAu_ewm6yq6P4HTh9rmhJX6M1nr17r6A4HWcQr5a1iwu8XXKclmPRPA7CUGIpHOVN5MtUzR4pbFqg_Fw_u5-cyyuZaZADjZiYyKWkT8EXI42SLahCJCNFJ/s893/Firmar%20digitalmente%20y%20cifrar_1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="893" data-original-width="618" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKjgmbT7IE0AOmjb46s3zC8zdJsOOZ3k3818RlWoxTO9l7Tk8-XQtZMbFE0oATmUBaRFEAu_ewm6yq6P4HTh9rmhJX6M1nr17r6A4HWcQr5a1iwu8XXKclmPRPA7CUGIpHOVN5MtUzR4pbFqg_Fw_u5-cyyuZaZADjZiYyKWkT8EXI42SLahCJCNFJ/s16000/Firmar%20digitalmente%20y%20cifrar_1.png" /></a></div><p></p><p><b><span style="color: #45818e;">Lo siguiente</span></b> que hace el script <b><span style="color: #45818e;">es leer la</span></b> <a href="https://drive.google.com/file/d/1aHACuNoSXxLYBheqyLpXn6BVK2DTbyWk/view?usp=sharing" style="font-family: inherit;"><span style="color: #2b00fe;">clave privada del emisor</span></a>, almacenada en formato PEM en un fichero, <b><span style="color: #45818e;">y generar</span></b> <span style="background-color: white; font-family: Lora, serif;"><b style="color: #45818e;">aleatoriamente un número primo (</b><i style="color: #45818e; font-weight: bold;">'h'</i><b style="color: #45818e;">)</b><span style="color: #292929;">, mayor o igual que 1 y menor o igual que p - 1, </span><a href="https://es.wikipedia.org/wiki/N%C3%BAmeros_coprimos"><span style="color: #2b00fe;">coprimo o primo relativo</span></a> </span><b style="background-color: white; color: #292929; font-family: Lora, serif;"><span style="color: #45818e;">con </span></b><span style="background-color: white; color: #292929; font-family: Lora, serif; text-align: justify;"><i><b><span style="color: #45818e;">ϕ(p)</span></b></i></span>, <b><span style="color: #45818e;">para firmar digitalmente</span></b>.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIRaKu2IyvBr09m_7-LPvvt3m0qjhp1WoYL_Bfpf2TiJRkO0Qd_QkzuJx9ThUKDRtAIsNrl8rgJBE9yCTuUpHIYUmlqkAfY38F4EilER00Lzq8r3ODGMFUcT4JANuWY_nRlDN_7CqJwPDeNyNFzsdj2Nt9Hc4o60NTv1z6F7WtCT8OhbzGhWx2x3Zp/s900/Firmar%20digitalmente%20y%20cifrar_2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="632" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIRaKu2IyvBr09m_7-LPvvt3m0qjhp1WoYL_Bfpf2TiJRkO0Qd_QkzuJx9ThUKDRtAIsNrl8rgJBE9yCTuUpHIYUmlqkAfY38F4EilER00Lzq8r3ODGMFUcT4JANuWY_nRlDN_7CqJwPDeNyNFzsdj2Nt9Hc4o60NTv1z6F7WtCT8OhbzGhWx2x3Zp/s16000/Firmar%20digitalmente%20y%20cifrar_2.png" /></a></div><p><span style="color: #45818e;"><b>Posterior</b></span><span style="color: #45818e; font-weight: bold;">mente,</span> el script <b><span style="color: #45818e;">lee la</span></b> <a href="https://drive.google.com/file/d/1uCRobe3ed_l-sgTUdJuZzc5d6E3pHiRC/view?usp=sharing" style="font-family: inherit;"><span style="color: #2b00fe;">clave pública del receptor</span></a>, almacenada en formato PEM en otro fichero, <b><span style="color: #45818e;">para cifrar mediante el algoritmo</span></b> <a href="https://es.wikipedia.org/wiki/Cifrado_ElGamal"><span style="color: #2b00fe;">ElGamal</span></a> <span style="background-color: white;">(</span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica" style="background-color: white;"><span style="color: #2b00fe;">criptografía asimétrica</span></a><span style="background-color: white;">)</span> <b><span style="color: #45818e;">la clave de sesión </span></b><span><span style="background-color: white;"><span><a href="https://es.wikipedia.org/wiki/Advanced_Encryption_Standard"><span style="color: #2b00fe;">AES</span></a><span style="color: #292929;"> con la que se ha cifrado el mensaje o texto en claro</span><span style="color: #292929;"> </span></span></span></span><span style="background-color: white; color: #292929;">(</span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_sim%C3%A9trica"><span style="color: #2b00fe;">criptografía simétrica</span></a><span style="background-color: white; color: #292929;">).</span></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1_IHTOKT2vm00jyve94TDmogT2PD41bPzj-yIfRGg6yCv5yuKyLZN3rVuUP_BKr4vM4a1VxAnZZJkCIo573Td2aLKDaEMnFecQYyzhbqPdvBcjDKjpFiM3MP37i1mcvfXCHTje-bk5dk5ttrdtrGWTJYkDQGaYpxp885FeKJ6YXgUXxEjHqXBhriM/s632/Firmar%20digitalmente%20y%20cifrar_3.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="566" data-original-width="632" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1_IHTOKT2vm00jyve94TDmogT2PD41bPzj-yIfRGg6yCv5yuKyLZN3rVuUP_BKr4vM4a1VxAnZZJkCIo573Td2aLKDaEMnFecQYyzhbqPdvBcjDKjpFiM3MP37i1mcvfXCHTje-bk5dk5ttrdtrGWTJYkDQGaYpxp885FeKJ6YXgUXxEjHqXBhriM/s16000/Firmar%20digitalmente%20y%20cifrar_3.png" /></a></div><p></p><p><span style="background-color: white;"><span style="color: black;">Y, </span><span><b><span style="color: #45818e;">finalmente</span></b>,</span> para simular el envió de la comunicación, <b><span style="color: #45818e;">se genera un fichero, comunicación.txt</span></b>, en el que se almacenan, codificados en base64, lo siguientes datos: el par de valores correspondientes al cifrado de la clave de sesión <a href="https://es.wikipedia.org/wiki/Advanced_Encryption_Standard"><span style="color: #2b00fe;">AES</span></a>, el criptograma y el par de valores correspondientes a la firma digital. </span></p><p><span style="background-color: white; color: #292929;">De esta forma, cuando el receptor reciba la comunicación, lo primero que se hará será descifrar la clave de sesión </span><a href="https://es.wikipedia.org/wiki/Advanced_Encryption_Standard" style="background-color: white;"><span style="color: #2b00fe;">AES</span></a><span style="background-color: white; color: #292929;"> con su </span><a href="https://drive.google.com/file/d/1uUDKIgRNCLiES9LiYojXvtXJqa-rUGi0/view?usp=drive_link"><span style="color: #2b00fe;">clave privada</span></a><span style="background-color: white; color: #292929;"> </span><span style="background-color: white; color: #292929;">(</span><span style="background-color: white; color: #292929;"><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica"><span style="color: #2b00fe;">criptografía asimétrica</span></a>) y con ésta descifrar el criptograma </span><span style="background-color: white; color: #292929;">(</span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_sim%C3%A9trica"><span style="color: #2b00fe;">criptografía simétrica</span></a><span style="background-color: white; color: #292929;">)</span><span style="background-color: white; color: #292929;">, para, posteriormente, verificar la firma digital con la <a href="https://drive.google.com/file/d/1E8kVLU2NGmdsUmHMH9E2wcrNGLOFW9IX/view?usp=sharing" style="font-family: inherit;"><span style="color: #2b00fe;">clave pública del emisor</span></a> </span><span style="background-color: white; color: #292929;">(</span><span style="background-color: white; color: #292929;"><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica"><span style="color: #2b00fe;">criptografía asimétrica</span></a>)</span><span style="background-color: white; color: #292929;">.</span></p><p><span style="background-color: white;"><span style="color: #292929;">En un </span><span>post posterior</span><span style="color: #292929;"> pondré el script en python para implementar esto último.</span></span></p><p><span style="background-color: white; font-family: inherit;"><b><i>Quizás también te interese</i></b>:</span></p><div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxxiv-el-algoritmo.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipFNBP3vjDI-BCwHt4L9LZy6KVoq1OE4XLIXCqTIDu2Uxca9udHt3KFH4p5F80DiIdmMzGzvsX6B1qUCcf8R7ElNFdXy1UXzMrST2CZIcKwNKcozaY9z_fbZF8naTWdms6OpxV5kk47dpgC043O71x3yUJ12uu5yEmOqAUehR7Drz79euz3Qj8aRG2/s16000/El%20algoritmo%20ElGamal.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-cclxxxv-generacion-de.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgm5ieQlEhTBhHYdxx1zzo4Bi5egW84izRlbkTuW0rg6Tejf6bBPS2iNo4PMHhXn7F2shFgZGJ-RBFeKKM_OJT7Aix22tYom2JprnUgVQhjGymjjNAA-geKEUOyL3q_4_QN-d3JGK1J9Ufd-6EwSG25Wlp1a01X3r4BRyuBlHS3XlPLpQgqPUqPbNB/s16000/Generaci%C3%B3n%20de%20claves%20ElGamal%20en%20python.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-cclxxxvi-esquema-de-firma.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLnwM_PuujOdJkf8EnGdIxaOiXixrrhB8so4iqOr1HT1OZjuv7DKlSCo1-HbEGv75qynFQMlLJk6VMboQ69a5JumQOSKqkQfLWHaB6poYo8KPjEQJxVtAd-G5Yh4r_Yljl1l0z28YDz_DIonSV_09QjJC9_V08uyuKqTRk3AGbvrqAl_WYazu6IoLB/s16000/Esquema%20de%20firma%20digital%20ElGamal.png" /></a></div></div>Mikel García Larraganhttp://www.blogger.com/profile/03118239524461394157noreply@blogger.com0tag:blogger.com,1999:blog-1846493661397027137.post-87502058027335182182023-08-03T19:47:00.006+02:002023-08-03T20:12:41.332+02:00Criptografía (CCLXXXVI): Esquema de firma digital ElGamal<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXXUZNuC9E1C_DDR6wPZba2L91Y3k3WVjuOimnRy3G4jztFnUxUo-e1Rr_ngx887XAm0XGftgqeF2FdtjOu55W5mXyPU5vfcGti2DjbnFg-9gDfJYytLcOMTiEw-4LNTt2sWmuW8VPQyKvWtzZhTUhHr9M_vuO-Ul369mj_wOtR8bVtJeVj6CgjdB3/s350/ElGamal.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="108" data-original-width="350" height="99" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXXUZNuC9E1C_DDR6wPZba2L91Y3k3WVjuOimnRy3G4jztFnUxUo-e1Rr_ngx887XAm0XGftgqeF2FdtjOu55W5mXyPU5vfcGti2DjbnFg-9gDfJYytLcOMTiEw-4LNTt2sWmuW8VPQyKvWtzZhTUhHr9M_vuO-Ul369mj_wOtR8bVtJeVj6CgjdB3/s320/ElGamal.png" width="320" /></a></div>En un <a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxxiv-el-algoritmo.html"><span style="color: #2b00fe;">post anterior</span></a> traté sobre el algoritmo de <a href="https://es.wikipedia.org/wiki/Cifrado_ElGamal"><span style="color: #2b00fe;">cifrado ElGamal</span></a> y <b><span style="color: #45818e;">en esta entrada voy a explicar el</span></b> <a href="https://es.wikipedia.org/wiki/Esquema_de_firma_ElGamal"><span style="color: #2b00fe;">esquema de firma digital ElGamal</span></a>, propuesto también por el criptógrafo egipcio <a href="https://es.wikipedia.org/wiki/Taher_Elgamal"><span style="color: #2b00fe;">Taher Elgamal</span></a> en 1984.<p></p><p>Como en el caso de <a href="https://es.wikipedia.org/wiki/RSA"><span style="color: #2b00fe;">RSA,</span></a> ya expliqué en <a href="http://mikelgarcialarragan.blogspot.com/2016/10/criptografia-xxxvi-el-algoritmo-rsa-ii.html"><span style="color: #2b00fe;">este post</span></a> cómo se firma y verifica la firma en ese <a href="https://es.wikipedia.org/wiki/Criptosistema"><span style="color: #2b00fe;">criptosistema</span></a>, <b><span style="color: #45818e;">el emisor del mensaje firma un </span></b><a href="https://es.wikipedia.org/wiki/Funci%C3%B3n_hash"><span style="color: #2b00fe;">hash</span></a><b style="color: #45818e;"> del mensaje con su </b><a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-cclxxxv-generacion-de.html"><span style="color: #2b00fe;">clave privada</span></a><b style="color: #45818e;"> y el receptor verifica la firma utilizando la </b><a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-cclxxxv-generacion-de.html"><span style="color: #2b00fe;">clave pública</span></a><b style="color: #45818e;"> del emisor</b>, con lo<span style="font-family: inherit;"> que se pretende garantizar tanto la autenticidad del mensaje como su integridad, <span style="background-color: white; color: #292929;">es decir, tanto que la persona que lo ha enviado es el emisor legítimo (es quien dice ser) como que el mensaje no ha sido interceptado y alterado por un tercero.</span></span></p><p><b><span style="color: #45818e;">Los protocolos de firma digital y verificación de la firma digital</span></b> utilizando este esquema de firma <b><span style="color: #45818e;">son los siguientes</span></b>:</p><p><i><u>Protocolo de firma digital</u></i>:</p><p><span style="font-family: inherit;"><span style="background-color: white; color: #292929;">1.- Para firmar digitalmente un mensaje (<i>'</i></span><span style="background-color: white; color: #292929;"><i>M'</i></span><span style="background-color: white; color: #292929;">) </span><b style="background-color: white; color: #292929;"><span style="color: #45818e;">el emisor obtiene un resumen del mismo mediante una función hash</span></b><span style="background-color: white; color: #292929;">, <i>h(M)</i>; de tamaño fijo mucho menor que el mensaje original, asociado unívocamente a éste (es prácticamente imposible encontrar otro mensaje que dé como resultado el mismo resumen) e irreversible (es prácticamente imposible obtener el mensaje a partir del resumen)</span><span style="background-color: white; color: #292929;">.</span></span></p><p>2.- <span><b style="color: #45818e;">El emisor genera aleatoriamente un número primo (</b><i style="color: #45818e; font-weight: bold;">'h'</i><b style="color: #45818e;">)</b>, mayor o igual que 1 y menor o igual que p - 1,</span> <a href="https://es.wikipedia.org/wiki/N%C3%BAmeros_coprimos"><span style="color: #2b00fe;">coprimo o primo relativo</span></a><b><span style="color: #45818e;"> con </span></b><span style="text-align: justify;"><i><b><span style="color: #45818e;">ϕ(p)</span></b></i>, o, lo que es lo mismo (como <i>'p'</i> es primo, entonces </span><i style="text-align: justify;">ϕ(p) = p -1</i>), el máximo común divisor de <i>'h'</i> y <i>p -1</i> deber ser 1.</p><p>3.- El emisor <b><span style="color: #45818e;">calcula su rúbrica</span></b> (<i>'r'</i>, primera parte de la firma digital):</p><p style="text-align: center;"><i><b><span style="color: #45818e;">r = g<sup>h</sup> mod p</span></b></i></p><p>4.- El emisor <b><span style="color: #45818e;">calcula la segunda parte de la firma digital</span></b>:</p><div style="text-align: center;"><b><span style="color: #45818e;"><span style="font-family: inherit;"><i>s = (h(M) - a * r) * inv(h<span style="font-size: 13.3333px;">, </span></i></span><i style="text-align: justify;">p - 1</i><i style="font-family: inherit;">) </i><i style="font-family: inherit;">mod </i><i style="text-align: justify;">(p -1)</i></span></b></div><p><b><span style="color: #45818e;">La firma digital es el par de valores <i>(r, s)</i></span></b>, que se envían junto con <i>'M'</i>.</p><p><i><u>Protocolo de verificación de la firma digital</u></i>:</p><p>1.- <b><span style="color: #45818e;">El receptor calcula el hash del mensaje recibido <i>h'(M)</i></span></b><span style="color: #292929;">.</span></p><p><span><span style="color: #292929;">2.- El receptor </span><b><span style="color: #45818e;">comprueba </span></b></span><b><span style="color: #45818e;">si<span style="font-family: inherit;"> </span></span></b><i style="text-align: center;"><b><span style="color: #45818e;">g</span></b></i><i style="text-align: center;"><b><span style="color: #45818e;"><sup>h'(M)</sup></span></b></i><span style="font-family: inherit;"><b style="background-color: white; color: #292929;"><span style="color: #45818e;"><i> mod p</i> es igual que </span></b></span><span style="color: #45818e; text-align: center;"><b><i>k</i></b></span><i style="text-align: center;"><b><span style="color: #45818e;"><sup>r</sup></span></b></i><b style="background-color: white; color: #292929; font-family: inherit;"><span style="color: #45818e;"><i>* </i></span></b><i style="text-align: center;"><b><span style="color: #45818e;">r</span></b></i><i style="text-align: center;"><b><span style="color: #45818e;"><sup>s </sup></span></b></i><b style="background-color: white; color: #292929; font-family: inherit;"><span style="color: #45818e;"><i>=</i> </span></b><i style="text-align: center;"><b><span style="color: #45818e;">g<sup>ar</sup></span></b></i><b style="background-color: white; color: #292929; font-family: inherit;"><span style="color: #45818e;"> * </span></b><i style="text-align: center;"><b><span style="color: #45818e;">g<sup>hs</sup></span></b></i><b style="color: #45818e; text-align: center;"><i> mod p</i></b><b style="background-color: white; color: #292929; font-family: inherit;"><span style="color: #45818e;">. Si son iguales se acepta la firma como válida</span></b><span style="background-color: white; color: #292929; font-family: inherit;">, en caso contrario se rechaza.</span></p><p><span style="background-color: white; font-family: inherit;"><b><i>Quizás también te interese</i></b>:</span></p><div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxxiv-el-algoritmo.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhj1Ip-zJEXAS2NyqCSUI7IzEg94Y5Apo6MD2J21Th8Z16fsCL0XJu0p20h3Kjq_DeQddXofM_KyeiPcFLMs7Uq81LIZuOgPgWQvRltibvxFVS9Mfjn3gDsv7iAinvmx0x6N62U91ELaItPFe8xwy2SISAZdED77ANld-7DikHPvsQM-0b6JlMaJMTL/s16000/El%20algoritmo%20ElGamal.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-cclxxxv-generacion-de.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJSclOaaDCc8UJFwmUhVMXlHqdrAV_trndGECxrcFnSm-UM53webal69BE8D01V8zWpn-XG6rCeEyCTa7M_FpHY46Qvk9NHNukuvhK6mJ8rIsmAE5IWxqG1TdyTAHhpjFvURIT9BpSmDDSQR8fQ2kQyEW9yXtv3dF7m_QCocdno-2zm3bjZzJS3fuC/s16000/Generaci%C3%B3n%20de%20claves%20ElGamal%20en%20python.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2016/10/criptografia-xxxv-el-algoritmo-rsa-i.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmuLy3WfFzpqlRc3oQmUt4XlQmD1JeJqRphUGdhRvInqrtUUmo8yu2rZglxHQD67fXOiQi7_tpz7Wk0vL1w8J6ncgZ3J3m9LGfvaKJ8pknSUSXyeKgu-lTc8QzLzI8pk2wgjShME3zztHuJu1okd9GwLBfvoS1MGAr607DDCzy_YQe2IhYlF5WIARP/s16000/El%20algoritmo%20RSA%20(I).png" /></a></div></div>Mikel García Larraganhttp://www.blogger.com/profile/03118239524461394157noreply@blogger.com0tag:blogger.com,1999:blog-1846493661397027137.post-25694919778954257992023-08-01T19:32:00.004+02:002023-08-05T09:07:12.307+02:00Criptografía (CCLXXXV): Generación de claves ElGamal en python<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj25kFRO9pKvAXAU8cNGMbjKFFtKLWV7dmkL3phLfo5AXfh1vGKfmPjn67C2dfxhSmsB7FPGuphOWwRwpD-SgZgQzaVTgnTib0DZwlC1RWJ3aD9Zf2GdNomdARfgOIkqMQ8rI0139tIq8B7V8-eT5PwdYv_WKvjT29pMbCiQRDrweUB7JfkUdrg0FnA/s350/ElGamal.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="108" data-original-width="350" height="99" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj25kFRO9pKvAXAU8cNGMbjKFFtKLWV7dmkL3phLfo5AXfh1vGKfmPjn67C2dfxhSmsB7FPGuphOWwRwpD-SgZgQzaVTgnTib0DZwlC1RWJ3aD9Zf2GdNomdARfgOIkqMQ8rI0139tIq8B7V8-eT5PwdYv_WKvjT29pMbCiQRDrweUB7JfkUdrg0FnA/s320/ElGamal.png" width="320" /></a></div>Continúo poniendo scripts de programación en python para automatizar tareas que tengan relación con la <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa"><span style="color: #2b00fe;">criptografía</span></a>.<p></p><p></p><p></p><p></p><p></p><p></p><p></p><p><b><span style="color: #45818e;">En este post incluyo un </span></b><span style="color: #45818e; font-weight: bold;">script en python para la generación del par de claves de un usuario, pública y privada, en</span><span> </span><a href="https://es.wikipedia.org/wiki/Cifrado_ElGamal"><span style="color: #2b00fe;">ElGamal</span></a><span style="font-family: inherit;">.</span></p><p><span style="font-family: inherit;">Antes de poner el script, recordar que en <a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxxiv-el-algoritmo.html"><span style="color: #2b00fe;">este post</span></a> expliqué cómo se generaban ambas claves en este <a href="https://es.wikipedia.org/wiki/Criptosistema"><span style="color: #2b00fe;">criptosistema</span></a>, </span><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;"><span style="color: black;">que debe su nombre al criptógrafo egipcio </span><a href="https://es.wikipedia.org/wiki/Taher_Elgamal"><span style="color: #2b00fe;">Taher Elgamal</span></a><span style="color: black;"> que lo describió en 1984</span>.</span></span></span></p><p><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;">Conforme a lo que indiqué en el citado post, </span><span style="color: #45818e;"><b><span>l</span><span>a generación del par de claves para un usuario consiste en</span></b></span><span style="color: #292929;">:</span></span></span></p><p><span style="background-color: white; font-family: inherit;"><span style="color: #292929;">1.- </span><span>Se elige un número primo <i>'p'</i> muy grande y un </span><a href="https://es.wikipedia.org/wiki/Ra%C3%ADz_primitiva_m%C3%B3dulo_n"><span style="color: #2b00fe;">generador <i>'g'</i> o raíz primitiva módulo <i>'p'</i></span></a><span style="color: #292929;">. Al igual que en el </span></span><a href="https://es.wikipedia.org/wiki/Diffie-Hellman"><span style="color: #2b00fe;">intercambio de clave de Diffie-Hellman</span></a><span style="background-color: white; font-family: inherit;"><span style="color: #292929;"> y por el mismo motivo, se puede obviar que <i>'g'</i> sea un </span></span><a href="https://es.wikipedia.org/wiki/Ra%C3%ADz_primitiva_m%C3%B3dulo_n"><span style="color: #2b00fe;">generador <i>'g'</i> o raíz primitiva módulo <i>'p'</i></span></a><span style="background-color: white; color: #292929; font-family: inherit;">, aunque es recomendable que sí lo sea.</span></p><p><span style="background-color: white; font-family: inherit;"><span><span style="color: #292929;">2.-</span> </span><span>Se escoge aleatoriamente un número <i>'a'</i></span><span> <span style="color: #292929;">mayor que cero y menor que </span></span><i style="color: #292929;">'p'</i><span style="color: #292929;">.</span></span></p><p><span style="background-color: white; font-family: inherit;"><span style="color: #292929;">3.- Se calcula </span></span><i>k = g<sup>a</sup> mod p</i><span style="background-color: white; font-family: inherit;"><span style="color: #292929;">.</span></span></p><p>4.- <b><span style="color: #45818e;">La clave pública será (<i>p</i>, <i>g</i>, <i>k</i>)</span></b>.</p><p><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><p>5.- <b><span style="color: #45818e;">La clave privada será (<i>a</i>)</span></b>.</p><p><span style="font-family: inherit;">Para que el script para la generación del par de claves funcione se necesita importar</span><span style="font-family: inherit;"> los dos siguientes módulos en el programa principal, </span><span style="font-family: inherit;">que se encargarán, respectivamente, de la generación de un número primo aleatorio <i>'p'</i> (mínimo de 2.048 bits) y de realizar la operación de exponenciación modular de forma </span><span style="font-family: inherit;">eficiente.</span></p><p></p><pre><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# GENERACIÓN DE UN NÚMERO PRIMO ALEATORIO:
#
# Generación de un número primo aleatorio a partir de un número de b bits.
#
# http://mikelgarcialarragan.blogspot.com/
from sympy import primerange, prime
from random import randint, getrandbits
def test_miller_rabin(n,k):
# n = número natural mayor que 1 e impar del que queremos conocer si es primo.
# k = número de veces o rondas a ejecutar el test.
# t = indicador de que n es primo con un cierto nivel de confianza (0: primo; 1: compuesto).
# s = número de veces que 2 divide a n - 1.
t = 0
s = 0
r = n - 1
while r%2 == 0:
s+=1
r = r//2
i=0
while i in range(0, k) and t != 1:
a = randint(2, n - 1)
j = 0
y = pow(a, r, n)
if y != 1 and y != n - 1:
j = 1
while y != n - 1 and t != 1 and j <= s - 1:
y = pow(y, 2, n)
if y == 1:
t = 1
else:
j = j + 1
if y != n -1:
t = 1
i = i + 1
if t == 0:
return True
else:
return False
def generar_primo_aleatorio(b,k):
# b = número de bits que tendrá como mínimo el número primo aleatorio.
# k = número de veces o rondas a ejecutar el test de primalidad.
# Se genera un número aleatorio impar (p) de b bits.
p = getrandbits(int(b))
if p%2 == 0:
p+=1
# Se crea una lista con los primeros 2048 números primos, para descartar rápidamente aquellos
# candidatos no primos, es decir, aquellos que son divisibles por alguno de los números primos
# integrantes de esta lista.
primeros_2048_primos = list(primerange(prime(2048 + 1)))
# Se realizan las comprobaciones tendentes a verificar si el candidato es primo con un cierto
# nivel de confianza.
puede_ser_primo = False
while not puede_ser_primo:
puede_ser_primo = True
for primo in primeros_2048_primos:
if p%primo == 0:
puede_ser_primo = False
break
# Si el candidato supera la primera criba, es decir no es divisible entre ninguno de los primeros
# 2048 números primos, entonces se le somete al test de primalidad de Miller-Rabin.
if puede_ser_primo:
if not test_miller_rabin(p,int(k)):
puede_ser_primo = False
# Si el candidato no supera la primera criba, es decir es divisible entre alguno de los primeros
# 2048 números primos o no supera el test de primalidad de Miller-Rabin, entonces se incrementa
# al candidato en dos unidades y se vuelve a comprobar si el nuevo candidato puede ser primo.
if not puede_ser_primo:
p+=2
return p</code>
<br /></pre><pre></pre><pre><pre><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ALGORITMO DE EXPONENCIACIÓN MODULAR RÁPIDA:
#
# Algoritmo utilizado en operaciones de exponenciación modular
# con números muy grandes con objeto de hacerlas de forma
# más eficiente.
#
# http://mikelgarcialarragan.blogspot.com/
def exp_modular_rapida(b, e, m):
c = 1
e = bin(e)[2:]
for i in range(0, len(e)):
c = pow(c, 2, m)
if e[i]=="1":
c = c*b%m
return c</code>
<br /></pre><p style="font-family: "Times New Roman"; white-space: normal;"><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><p style="font-family: "Times New Roman"; white-space: normal;"><span style="background-color: white; color: #292929; font-family: inherit;"></span></p><p style="font-family: "Times New Roman"; white-space: normal;">El <b><span style="color: #45818e;">script</span></b> es el siguiente:</p></pre><p><span style="font-family: inherit;"><span style="background-color: white; color: #292929;">- </span><i style="background-color: white; color: #292929;"><u>Script python para la generación del par de claves ElGamal, pública y privada, de un usuario</u></i><span style="background-color: white; color: #292929;">:</span></span></p><p></p><pre><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ElGamal:
#
# Generación de las claves, pública (p, g, k) y privada (a), para un usuario.
#
# http://mikelgarcialarragan.blogspot.com/
import primo_aleatorio
import random
import pyasn1.type.univ
import pyasn1.codec.der.encoder
import base64
from time import time
from exponenciacion_modular_rapida import exp_modular_rapida
def pempubl(p, g, k):
template = '-----BEGIN ELGAMAL PUBLIC KEY-----\n{}-----END ELGAMAL PUBLIC KEY-----\n'
seq = pyasn1.type.univ.Sequence()
for i,x in enumerate((p, g, k)):
seq.setComponentByPosition(i, pyasn1.type.univ.Integer(x))
der = pyasn1.codec.der.encoder.encode(seq)
return template.format(base64.encodebytes(der).decode('ascii'))
def pempriv(p, g, k, a):
template = '-----BEGIN ELGAMAL PRIVATE KEY-----\n{}-----END ELGAMAL PRIVATE KEY-----\n'
seq = pyasn1.type.univ.Sequence()
for i,x in enumerate((p, g, k, a)):
seq.setComponentByPosition(i, pyasn1.type.univ.Integer(x))
der = pyasn1.codec.der.encoder.encode(seq)
return template.format(base64.encodebytes(der).decode('ascii'))
def main():
# MENÚ:
# Se presenta el menú para que se seleccione una opción.
salir = False
while not salir:
print ("")
print ("*** MENÚ *****************************************")
print ("1. Generar par de claves.")
print ("2. Salir.")
print ("")
opcion = input("Por favor, seleccione una opción: ")
if opcion == "1":
print ("")
print ("--- GENERACIÓN DE LA CLAVE PÚBLICA Y PRIVADA PARA UN USUARIO:")
# Se introducen el tamaño mínimo, número de bits, que tendrá el número primo aleatorio 'p' a generar y el generador 'g' o
# raíz primitiva módulo 'p'.
b = g = "*"
while not b.isnumeric() or int(b) < 2048:
b = input("Introduzca el número de bits, sin punto decimal y mayor o igual que 2048, que tendrá el número primo aleatorio 'p': ")
if b.isnumeric() and int(b) >= 2048:
inicio_generacion_par_claves = inicio_generacion_primo = time()
print("[+] Generando número primo aleatorio 'p'...")
p = primo_aleatorio.generar_primo_aleatorio(b,5)
print("[+] Número primo aleatorio 'p' generado:", p)
print("[+] Tiempo de ejecucion de la generación del número primo aleatorio 'p':", time() - inicio_generacion_primo)
while not g.isnumeric() or int(g) < 1 or int(g) > p -1:
g = input("Introduzca el generador 'g' o raíz primitiva módulo 'p': ")
if g.isnumeric() and int(g) > 0 and int(g) < p:
a = random.randint(1, p-1)
k = exp_modular_rapida(int(g), a, p)
print("[+] Clave pública (p, g, k): (", p, ",", g, ",", k, ")")
print("[+] Clave privada (a): (", a)
print("[+] Tiempo de ejecucion de la generación del par de claves, pública y privada:", time() - inicio_generacion_par_claves)
publpem = pempubl(p, g, k)
print("[+] Clave pública en formato PEM:")
print(publpem)
with open("public.pem", "w") as f:
f.write(publpem)
privpem = pempriv(p, g, k, a)
print("[+] Clave privada en formato PEM:")
print(privpem)
with open("private.pem", "w") as f:
f.write(privpem)
else:
print ("*** ERROR: Generador 'g' o raíz primitiva módulo 'p' incorrecto. Debe ser un número natural, sin punto decimal, mayor que 0 y menor que 'p'.")
else:
print ("*** ERROR: Número de bits incorrecto. Debe ser un número natural, sin punto decimal, mayor o igual que 2048.")
elif opcion == "2":
print ("*** FIN ******************************************")
salir = True
else:
print ("*** ERROR: Opción no válida.")
if __name__ == '__main__':
main()</code>
<br /></pre><p><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><p><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><p><b><span style="color: #45818e;">Lo ejecuto</span></b>:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEJEiYQs4Ip-WkfVfmP9A7SdiCNAZVR4A0tohaVbK_X0DzRFVu5rE-vbJgSqfAqbDDqwG_eZaVm03uFLpXozc7I5WC7Txs4n-z_fZPEElpE6fg6NhWZYJj0gTFx7hxiHNIuBSjevkDjHyDShlDDYqefilMZV9g_itI5qHTYI6DdJLwTT2SJv0wmgeK/s617/Generar%20Claves_1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="370" data-original-width="617" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEJEiYQs4Ip-WkfVfmP9A7SdiCNAZVR4A0tohaVbK_X0DzRFVu5rE-vbJgSqfAqbDDqwG_eZaVm03uFLpXozc7I5WC7Txs4n-z_fZPEElpE6fg6NhWZYJj0gTFx7hxiHNIuBSjevkDjHyDShlDDYqefilMZV9g_itI5qHTYI6DdJLwTT2SJv0wmgeK/s16000/Generar%20Claves_1.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkhwRkiGTEt6iqhtGTU5mgQc-5G-P-HfCEF1TtBEeASpcW0mbvkcg4qlBxSXCNC6TmZXvF_j9NL826tnPRzCjM7PUk0htsLBhs_6tnk6MEST0599vlvxHeTzAzDRP2QEfFQUio1E5wRzXuncU6xPYgx1o6VHzME8ZnCmPJUVD4nXVe2bnqxT6DdYPy/s617/Generar%20Claves_2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="494" data-original-width="617" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkhwRkiGTEt6iqhtGTU5mgQc-5G-P-HfCEF1TtBEeASpcW0mbvkcg4qlBxSXCNC6TmZXvF_j9NL826tnPRzCjM7PUk0htsLBhs_6tnk6MEST0599vlvxHeTzAzDRP2QEfFQUio1E5wRzXuncU6xPYgx1o6VHzME8ZnCmPJUVD4nXVe2bnqxT6DdYPy/s16000/Generar%20Claves_2.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJSYlbjOSDFtDb26j3Yg6jlwRmXGxRJz63i-KwfgRPlYVSm5i8N6sH0oTrXs1dPGgRrB_vQkXz6hXtJZdG9ldKg-0pL1H6JudlPD5bOcYo6RBFbyklQC9qH2HAI7AsuYlpAXNsuo2QnhKNGMltPQ1oNk5KUD3A-IPLEm_XO0jcH_F0dCJfBcJkb2lq/s617/Generar%20Claves_3.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="525" data-original-width="617" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJSYlbjOSDFtDb26j3Yg6jlwRmXGxRJz63i-KwfgRPlYVSm5i8N6sH0oTrXs1dPGgRrB_vQkXz6hXtJZdG9ldKg-0pL1H6JudlPD5bOcYo6RBFbyklQC9qH2HAI7AsuYlpAXNsuo2QnhKNGMltPQ1oNk5KUD3A-IPLEm_XO0jcH_F0dCJfBcJkb2lq/s16000/Generar%20Claves_3.png" /></a></div><p></p><p><span style="background-color: white;">El script muestra la clave pública (p, g, k) y la clave privada (a) generadas y guarda ambas en sendos archivos .PEM, para que puedan ser utilizadas en el cifrado (otro usuario con la clave pública del</span><span style="background-color: white;"> usuario para el que se ha generado este par de claves</span><span style="background-color: white;">), descifrado y firma digital (el usuario para el que se ha generado este par de claves con la clave privada)</span><span style="background-color: white;">.</span></p><p><span style="background-color: white; font-family: inherit;"><b><i>Quizás también te interese</i></b>:</span></p><div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxxiv-el-algoritmo.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhj1Ip-zJEXAS2NyqCSUI7IzEg94Y5Apo6MD2J21Th8Z16fsCL0XJu0p20h3Kjq_DeQddXofM_KyeiPcFLMs7Uq81LIZuOgPgWQvRltibvxFVS9Mfjn3gDsv7iAinvmx0x6N62U91ELaItPFe8xwy2SISAZdED77ANld-7DikHPvsQM-0b6JlMaJMTL/s16000/El%20algoritmo%20ElGamal.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2016/10/criptografia-xxxv-el-algoritmo-rsa-i.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmuLy3WfFzpqlRc3oQmUt4XlQmD1JeJqRphUGdhRvInqrtUUmo8yu2rZglxHQD67fXOiQi7_tpz7Wk0vL1w8J6ncgZ3J3m9LGfvaKJ8pknSUSXyeKgu-lTc8QzLzI8pk2wgjShME3zztHuJu1okd9GwLBfvoS1MGAr607DDCzy_YQe2IhYlF5WIARP/s16000/El%20algoritmo%20RSA%20(I).png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2016/10/criptografia-xxxvi-el-algoritmo-rsa-ii.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirNSpIv8NCi7fdLEAqb_jymUk6SWabYFk82YzeHl4hqLSp-L7WHZaCC_Jy1mpN6VRrOELIwFL9lFnlbPP-OKFiR7B_XrdBiu7991oaCtzqtkvROW7fCYCAERxlu2v66iUlzbVbWulg12rHw_Ri9h2CuWsjPycWvr6qQVFMu3MFz2R0tCfOR3oaHONN/s16000/El%20algoritmo%20RSA%20(II).png" /></a></div></div>Mikel García Larraganhttp://www.blogger.com/profile/03118239524461394157noreply@blogger.com0tag:blogger.com,1999:blog-1846493661397027137.post-72725334304727589952023-07-31T08:22:00.006+02:002023-08-04T21:21:08.170+02:00Criptografía (CCLXXXIV): el algoritmo ElGamal<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOsvzuJraiXZYQtpuVZvHbRfu7C4sKvp18_v3w0XmyxQiSxSh4NscuZSeBQ5zbdDpxmj8OQYB02nyRaSPAvgBNyJ44OqlfIububJaHWUk78xZiZEUB50Mwxgpmi6v4lXNWZKQs4SHfm1cxE5eu_9AOdX16gXZrRM0qBZI8UeMZBh1D7Ya-wy8Sii3k/s350/ElGamal.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="108" data-original-width="350" height="99" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOsvzuJraiXZYQtpuVZvHbRfu7C4sKvp18_v3w0XmyxQiSxSh4NscuZSeBQ5zbdDpxmj8OQYB02nyRaSPAvgBNyJ44OqlfIububJaHWUk78xZiZEUB50Mwxgpmi6v4lXNWZKQs4SHfm1cxE5eu_9AOdX16gXZrRM0qBZI8UeMZBh1D7Ya-wy8Sii3k/s320/ElGamal.png" width="320" /></a></div><p style="text-align: left;"><b><span style="color: #45818e;">El </span></b><a href="https://es.wikipedia.org/wiki/Cifrado_ElGamal"><span style="color: #2b00fe;">algoritmo ElGamal</span></a>, un algoritmo de <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica"><span style="color: #2b00fe;">cifrado asimétrico</span></a> que debe su nombre al criptógrafo egipcio <a href="https://es.wikipedia.org/wiki/Taher_Elgamal"><span style="color: #2b00fe;">Taher Elgamal</span></a> que lo describió en 1984, <b><span style="color: #45818e;">se basa en el mismo principio que en el que se fundamenta el </span></b><a href="https://es.wikipedia.org/wiki/Diffie-Hellman"><span style="color: #2b00fe;">intercambio de clave de Diffie-Hellman</span></a> (ver <a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxx-intercambio-de.html"><span style="color: #2b00fe;">este post</span></a> donde explico este <a href="https://es.wikipedia.org/wiki/Protocolo_criptogr%C3%A1fico"><span style="color: #2b00fe;">protocolo criptográfico</span></a>).</p><p style="text-align: left;"><b style="background-color: white; color: #292929;"><span style="color: #45818e;">Como en todo criptosistema de clave pública un usuario dispone de dos claves</span></b><span style="background-color: white; color: #292929;">: </span><b style="background-color: white; color: #292929;"><span style="color: #45818e;">una pública</span></b><span style="background-color: white; color: #292929;">, que debe estar en posesión de cualquier persona que pretenda enviarle un mensaje cifrado, </span><b style="background-color: white; color: #292929;"><span style="color: #45818e;">y otra privada</span></b><span style="background-color: white; color: #292929;">, que el usuario utilizará para descifrar los mensajes que le envíen y que sólo él posee. Es decir, </span><b style="background-color: white; color: #292929;"><span style="color: #45818e;">el emisor cifrará el mensaje con la clave pública del receptor y sólo éste podrá descifrarlo utilizando su clave privada</span></b><span style="background-color: white; color: #292929;">.</span></p><p></p><p style="text-align: left;">Pues bien, <b><span style="color: #45818e;">estableciendo una analogía entre este algoritmo de cifrado y el citado protocolo de intercambio de clave con dos intervinientes</span></b> en la comunicación, que comparten una clave de sesión (<i>'k'</i>), el secreto compartido, que viene dada por: <span><i>k = g<sup>ab</sup> mod p</i></span>, siendo <i>'a'</i> y <i>'b'</i> sendos números secretos; cada interviniente ha escogido uno de ellos y lo mantiene en secreto, <b><span style="color: #45818e;">podemos decir que <i>g<sup>a</sup> mod p</i> sería la clave pública del primer interviniente y <i>g<sup>b</sup> mod p</i> la clave publica del segundo, mientras que <i>'a'</i> sería la clave privada del primer interviniente y <i>'b'</i> la clave privada del segundo</span></b>.</p><p style="text-align: left;">Además de este algoritmo de cifrado, <a href="https://es.wikipedia.org/wiki/Taher_Elgamal"><span style="color: #2b00fe;">Taher Elgamal</span></a> <b><span style="color: #45818e;">propone otro algoritmo para firmar digitalmente</span></b>, que será objeto de un <a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-cclxxxvi-esquema-de-firma.html"><span style="color: #2b00fe;">próximo post</span></a>.</p><p style="text-align: left;">Continuando con el algoritmo de cifrado, al igual que en <a href="https://es.wikipedia.org/wiki/RSA"><span style="color: #2b00fe;">RSA</span></a><span style="font-family: inherit;">, <span style="color: #45818e;"><b>lo que se cifra son</b><b style="background-color: white;"> números </b></span><span style="background-color: white;"><b><span style="color: #45818e;">y su seguridad</span></b><span style="color: #292929;">, al igual que en el </span></span></span><a href="https://es.wikipedia.org/wiki/Diffie-Hellman"><span style="color: #2b00fe;">intercambio de clave de Diffie-Hellman</span></a><span style="background-color: white; font-family: inherit;"><span style="color: #292929;">, </span><b><span style="color: #45818e;">se basa en</span></b><b><span style="color: #45818e;"> que un atacante</span></b><span style="color: #292929;">, conociendo la clave pública de un usuario, para hacerse con la clave privada </span><b><span style="color: #45818e;">se enfrentaría al</span></b> <a href="https://es.wikipedia.org/wiki/Logaritmo_discreto"><span style="color: #2b00fe;">problema del logaritmo discreto (PLD)</span></a><span style="color: #292929;">, de muy difícil solución en un tiempo razonable para números primos muy grandes, es decir, al igual que en el caso de </span></span><a href="https://es.wikipedia.org/wiki/RSA"><span style="color: #2b00fe;">RSA</span></a><span style="background-color: white; font-family: inherit;"><span style="color: #292929;"> se utiliza una </span><a href="https://es.wikipedia.org/wiki/Funci%C3%B3n_unidireccional#"><span style="color: #2b00fe;">función de un solo sentido</span></a><span style="color: #292929;">; </span></span><span style="background-color: white; color: #292929; font-family: inherit;">muy fácil de resolver en un sentido pero cuya resolución en sentido contrario se vuelve inabordable para números lo suficientemente grandes, por mucha potencia de cálculo de la que se disponga con los ordenadores actuales.</span></p><p style="text-align: left;"><span style="background-color: white; color: #292929; font-family: inherit;">Dicho lo anterior, la generación del par de claves de un usuario se realiza de la siguiente manera:</span></p><p style="text-align: left;"><span style="background-color: white; font-family: inherit;"><span style="color: #292929;">1.- </span><span style="color: #45818e;"><b>Se elige un número primo </b><b><i>'p'</i> muy grande y un </b></span><a href="https://es.wikipedia.org/wiki/Ra%C3%ADz_primitiva_m%C3%B3dulo_n"><span style="color: #2b00fe;">generador <i>'g'</i> o raíz primitiva módulo <i>'p'</i></span></a><span style="color: #292929;">. Al igual que en el </span></span><a href="https://es.wikipedia.org/wiki/Diffie-Hellman"><span style="color: #2b00fe;">intercambio de clave de Diffie-Hellman</span></a><span style="background-color: white; font-family: inherit;"><span style="color: #292929;"> y por el mismo motivo, se puede obviar que <i>'g'</i> sea un </span></span><a href="https://es.wikipedia.org/wiki/Ra%C3%ADz_primitiva_m%C3%B3dulo_n"><span style="color: #2b00fe;">generador <i>'g'</i> o raíz primitiva módulo <i>'p'</i></span></a><span style="background-color: white; color: #292929; font-family: inherit;">, aunque es recomendable que lo sea.</span></p><p style="text-align: left;"><span style="background-color: white; font-family: inherit;"><span style="color: #292929;">2.- </span><b><span style="color: #45818e;">Se escoge aleatoriamente un número <i>'a'</i></span></b><span style="color: #292929;"> mayor que cero y menor que </span><i style="color: #292929;">'p'</i><span style="color: #292929;">.</span></span></p><p style="text-align: left;"><span style="background-color: white; font-family: inherit;"><span style="color: #292929;">3.- Se calcula </span></span><i><b><span style="color: #45818e;">k = g<sup>a</sup> mod p</span></b></i><span style="background-color: white; font-family: inherit;"><span style="color: #292929;">.</span></span></p><p style="text-align: left;">4.- <b><span style="color: #45818e;">La clave pública será (<i>p</i>, <i>g</i>, <i>k</i>)</span></b>.</p><p style="text-align: left;">5.- <b><span style="color: #45818e;">La clave privada será (<i>a</i>)</span></b>.</p><p style="text-align: left;"><b><span style="color: #45818e;">Veamos un ejemplo de cifrado y descifrado</span></b>:</p><p style="text-align: left;">Supongamos que el usuario A tiene <i>p = 997</i>, <i>g = 7</i> y <i>a = 851</i>, entonces: <i>k = 7<sup>851</sup> mod 997 = 184</i> y, por tanto, tiene como clave pública (<i>997</i>, <i>7</i>, <i>184</i>)</p><p style="text-align: left;">a) <u><i>Cifrado</i></u>:</p><p style="text-align: left;">Supongamos ahora que el usuario B quiere enviar a A un número secreto (<i>'m'</i>), <i>783</i>. Actuaría de la siguiente manera:</p><p style="text-align: left;"><span style="font-family: inherit;">- Escoge <span style="background-color: white;">un número entero aleatorio <i>'b'</i> mayor que 0 y menor que <i>'p'</i></span><span style="background-color: white;">, <i>328</i>.</span></span></p><div><span style="font-family: inherit;"><span style="background-color: white;">- Con la clave pública de A y el número escogido en el paso anterior, B calcula y envía a A el siguiente par de valores: (</span></span><i>g<sup>b</sup> mod p</i><span style="background-color: white; font-family: inherit;">, <i>m</i> * </span><i>k<sup>b</sup> mod p</i><span style="background-color: white; font-family: inherit;">), que serán el mensaje cifrado o criptograma (<i>'c'</i>). Es decir:</span></div><p style="text-align: center;"><span style="background-color: white; font-family: inherit;"> c = (</span><i>7<sup>328</sup> mod 997</i><span style="background-color: white; font-family: inherit;">, <i>783</i> * </span><i>184<sup>328</sup> mod 997</i><span style="background-color: white; font-family: inherit;">) = (<i>645</i>, <i>63</i>)</span></p><p style="text-align: left;">b) <u><i>Descifrado</i></u>:</p><p style="text-align: left;">A con su clave privada, calcula:</p><p style="text-align: center;"><i>m = <span style="text-align: center;">645<sup>p-1-a </sup></span>* 63 mod p = </i><i><span style="text-align: center;">645<sup>997-1-851 </sup></span>* 63 mod 997 = </i><i>645<sup>145 </sup>* 63 mod 997 = 783</i>.</p><div><b style="font-family: inherit;"><i>Quizás también te interese</i></b><span style="background-color: white; font-family: inherit;">:</span></div><div><p><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/08/criptografia-cclxxxv-generacion-de.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5K5yHxTnTYh9I15EvGtBSd3o3RTWRYbcEdMjLASmDV0AHSp_6u4mw5oAwCNj0BWcTI3w6OPCdRBtMFeYAnjVLxJdZtElh_zO0SEGOy8RbgkFbg4J9jH8cRvFe_237SWRjyxDjHOlpzoSq0vscLGKN2kPmptdXvo52zII5YKYkG3cyfjJW0E-Btz6c/s16000/Generaci%C3%B3n%20de%20claves%20ElGamal%20en%20python.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2016/10/criptografia-xxxv-el-algoritmo-rsa-i.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmuLy3WfFzpqlRc3oQmUt4XlQmD1JeJqRphUGdhRvInqrtUUmo8yu2rZglxHQD67fXOiQi7_tpz7Wk0vL1w8J6ncgZ3J3m9LGfvaKJ8pknSUSXyeKgu-lTc8QzLzI8pk2wgjShME3zztHuJu1okd9GwLBfvoS1MGAr607DDCzy_YQe2IhYlF5WIARP/s16000/El%20algoritmo%20RSA%20(I).png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2016/10/criptografia-xxxvi-el-algoritmo-rsa-ii.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirNSpIv8NCi7fdLEAqb_jymUk6SWabYFk82YzeHl4hqLSp-L7WHZaCC_Jy1mpN6VRrOELIwFL9lFnlbPP-OKFiR7B_XrdBiu7991oaCtzqtkvROW7fCYCAERxlu2v66iUlzbVbWulg12rHw_Ri9h2CuWsjPycWvr6qQVFMu3MFz2R0tCfOR3oaHONN/s16000/El%20algoritmo%20RSA%20(II).png" /></a></div></div></div>Mikel García Larraganhttp://www.blogger.com/profile/03118239524461394157noreply@blogger.com0tag:blogger.com,1999:blog-1846493661397027137.post-43173725353389113082023-07-30T08:22:00.002+02:002023-08-05T09:02:34.037+02:00Criptografía (CCLXXXIII): Ataque de intermediario al Intercambio de clave de Diffie-Hellman en python<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNrAzhBgkw2v67MyvvDGaHa28l_tFe2BA1PQbYLuIREzOLim75l181PS4N51o5uzSImrHHvKanFs3zX1ysNernR-sUW7N_XZaCOTMIn_Yc8QMVjDC5qWT-fIPmMrYmb_LfVhr2UIUhcnZtvaHyxXqRpFwbxX-BgBmisBJ_gXMAWKKgLWKqHwI-DaZv/s256/Diffie-Hellman.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="145" data-original-width="256" height="145" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNrAzhBgkw2v67MyvvDGaHa28l_tFe2BA1PQbYLuIREzOLim75l181PS4N51o5uzSImrHHvKanFs3zX1ysNernR-sUW7N_XZaCOTMIn_Yc8QMVjDC5qWT-fIPmMrYmb_LfVhr2UIUhcnZtvaHyxXqRpFwbxX-BgBmisBJ_gXMAWKKgLWKqHwI-DaZv/s1600/Diffie-Hellman.png" width="256" /></a></div>Continúo poniendo scripts de programación en python para automatizar tareas que tengan relación con la <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa"><span style="color: #2b00fe;">criptografía</span></a>.<p></p><p></p><p></p><p><span style="font-family: inherit;">Ya puse una <a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxx-intercambio-de.html"><span style="color: #2b00fe;">entrada</span></a> en la que expliqué el funcionamiento del protocolo criptográfico para el <a href="https://es.wikipedia.org/wiki/Diffie-Hellman"><span style="color: #2b00fe;">intercambio de clave de Diffie-Hellman</span></a>, que se utiliza en canales de comunicación inseguros, <span style="background-color: white; color: #292929;">como puede ser Internet, </span><span style="background-color: white; color: #292929;">para salvaguardar el secreto de la clave si las comunicaciones entre las partes son interceptadas por un tercero.</span></span></p><p><span style="font-family: inherit;">Asimismo, en <a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxxii-ataque-de.html"><span style="color: #2b00fe;">esta entrada</span></a> expliqué en que<span style="font-family: inherit;"> consiste </span><span style="background-color: white;"><span style="color: #292929;">el </span><a href="https://es.wikipedia.org/wiki/Ataque_de_intermediario"><span style="color: #2b00fe;">ataque de intermediario</span></a></span><span style="background-color: white; color: #292929;"> </span><span style="background-color: white; color: #292929;"><span style="color: #202122;">(MitM, por las siglas en inglés de '</span><i lang="en" style="color: #202122;">Man in the Middle</i><span style="color: #202122;">')</span></span><span style="background-color: white; color: #292929;"> aplicado a este protocolo cuando se realiza sin autenticación, y</span><span style="background-color: white; color: #292929;"> </span><span style="background-color: white;"><b style="color: #45818e;">en esta entrada incluyo un script en python para implementar este ataque</b>.</span></span></p><p><span style="font-family: inherit;"><span style="background-color: white;"><b><span style="color: #45818e;">El script simula el intercambio de clave</span></b>, por ejemplo: una clave de sesión para ser utilizada en el cifrado y descifrado de mensajes mediante <a href="https://es.wikipedia.org/wiki/Advanced_Encryption_Standard"><span style="color: #2b00fe;">AES</span></a>, entre A y B, <span style="color: #45818e; font-weight: bold;">de la misma manera</span><span><b style="color: #45818e;"> que el que puse en </b><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxxi-intercambio-de.html"><span style="color: #2b00fe;">este post</span></a><b style="color: #45818e;">, pero añade la participación de un atacante (C)</b></span> que se interpone en las comunicaciones entre A y B.</span></span></p><p>Para que el script funcione se necesita importar los dos siguientes módulos en el programa principal, <span>que se encargarán, respectivamente, de la generación de un número primo <i>'p'</i> de 2.048 bits y de realizar las operaciones de exponenciación modular de forma </span><span>eficiente.</span></p><p></p><pre><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# GENERACIÓN DE UN NÚMERO PRIMO ALEATORIO:
#
# Generación de un número primo aleatorio a partir de un número de b bits.
#
# http://mikelgarcialarragan.blogspot.com/
from sympy import primerange, prime
from random import randint, getrandbits
def test_miller_rabin(n,k):
# n = número natural mayor que 1 e impar del que queremos conocer si es primo.
# k = número de veces o rondas a ejecutar el test.
# t = indicador de que n es primo con un cierto nivel de confianza (0: primo; 1: compuesto).
# s = número de veces que 2 divide a n - 1.
t = 0
s = 0
r = n - 1
while r%2 == 0:
s+=1
r = r//2
i=0
while i in range(0, k) and t != 1:
a = randint(2, n - 1)
j = 0
y = pow(a, r, n)
if y != 1 and y != n - 1:
j = 1
while y != n - 1 and t != 1 and j <= s - 1:
y = pow(y, 2, n)
if y == 1:
t = 1
else:
j = j + 1
if y != n -1:
t = 1
i = i + 1
if t == 0:
return True
else:
return False
def generar_primo_aleatorio(b,k):
# b = número de bits que tendrá como mínimo el número primo aleatorio.
# k = número de veces o rondas a ejecutar el test de primalidad.
# Se genera un número aleatorio impar (p) de b bits.
p = getrandbits(int(b))
if p%2 == 0:
p+=1
# Se crea una lista con los primeros 2048 números primos, para descartar rápidamente aquellos
# candidatos no primos, es decir, aquellos que son divisibles por alguno de los números primos
# integrantes de esta lista.
primeros_2048_primos = list(primerange(prime(2048 + 1)))
# Se realizan las comprobaciones tendentes a verificar si el candidato es primo con un cierto
# nivel de confianza.
puede_ser_primo = False
while not puede_ser_primo:
puede_ser_primo = True
for primo in primeros_2048_primos:
if p%primo == 0:
puede_ser_primo = False
break
# Si el candidato supera la primera criba, es decir no es divisible entre ninguno de los primeros
# 2048 números primos, entonces se le somete al test de primalidad de Miller-Rabin.
if puede_ser_primo:
if not test_miller_rabin(p,int(k)):
puede_ser_primo = False
# Si el candidato no supera la primera criba, es decir es divisible entre alguno de los primeros
# 2048 números primos o no supera el test de primalidad de Miller-Rabin, entonces se incrementa
# al candidato en dos unidades y se vuelve a comprobar si el nuevo candidato puede ser primo.
if not puede_ser_primo:
p+=2
return p</code>
<br /></pre><p><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><p><span style="background-color: white; color: #292929; font-family: inherit;"></span></p><p><span></span></p><p></p><pre><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ALGORITMO DE EXPONENCIACIÓN MODULAR RÁPIDA:
#
# Algoritmo utilizado en operaciones de exponenciación modular
# con números muy grandes con objeto de hacerlas de forma
# más eficiente.
#
# http://mikelgarcialarragan.blogspot.com/
def exp_modular_rapida(b, e, m):
c = 1
e = bin(e)[2:]
for i in range(0, len(e)):
c = pow(c, 2, m)
if e[i]=="1":
c = c*b%m
return c</code>
<br /></pre><p><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><p><span style="background-color: white; color: #292929; font-family: inherit;"></span></p><p>El <b><span style="color: #45818e;">script</span></b> es el siguiente:</p><p></p><pre><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ATAQUE DE INTERMEDIARIO ('MAN IN THE MIDDLE') AL INTERCAMBIO DE CLAVE DE DIFFIE-HELLMAN:
#
# Ataque de intermediario (MitM) al Protocolo de intercambio de clave de Diffie-Hellman cuando éste se realiza sin autenticación.
#
# http://mikelgarcialarragan.blogspot.com/
import hashlib
import primo_aleatorio
from exponenciacion_modular_rapida import exp_modular_rapida
def main():
# MENÚ:
# Se presenta el menú para que se seleccione una opción.
salir = False
while not salir:
print ("")
print ("*** MENÚ *****************************************")
print ("1. Ataque MitM al protocolo Diffie-Hellman.")
print ("2. Salir.")
print ("")
opcion = input("Por favor, seleccione una opción: ")
if opcion == "1":
print ("")
print ("--- ATAQUE DE INTERMEDIARIO ('MAN IN THE MIDDLE') AL INTERCAMBIO DE CLAVE DE DIFFIE-HELLMAN:")
print ("*** A genera un número primo aleatorio 'p' de 2.048 bits y escoge 'g' = 5")
p = primo_aleatorio.generar_primo_aleatorio(2048,5)
g = 5
print ("[+] Número primo aleatorio 'p' generado:", p)
print ("[+] Número 'g' escogido:", g)
print ("*** A envía a C, que se ha interpuesto en las comunicaciones entre A y B, el número primo aleatorio 'p' y 'g'")
print ("*** C envía a B, el número primo aleatorio 'p' y 'g' que ha recibido de A")
print ("*** A introduce una frase de contraseña de la que se calcula el hash SHA-256 para obtener su número secreto 'a'")
frase_password = ""
while frase_password == "":
frase_password = input('Por favor, introduzca su frase de contraseña: ')
if frase_password != "":
a = (hashlib.sha256(frase_password.encode()).digest()).hex()
print ("[+] Número secreto de A (hexadecimal), 'a':", a)
print ("*** A envía a C, creyendo que se lo envía a B, el resultado de g^a mod p")
print ("*** C introduce una frase de contraseña de la que se calcula el hash SHA-256 para obtener su propio número secreto 'c'")
frase_password = ""
while frase_password == "":
frase_password = input('Por favor, introduzca su frase de contraseña: ')
if frase_password != "":
c = (hashlib.sha256(frase_password.encode()).digest()).hex()
print ("[+] Número secreto del atacante C (hexadecimal), 'c':", c)
print ("*** C envía a B, que cree que se lo ha enviado A, el resultado de g^c mod p")
print ("*** B introduce una frase de contraseña de la que se calcula el hash SHA-256 para obtener su número secreto 'b'")
frase_password = ""
while frase_password == "":
frase_password = input('Por favor, introduzca su frase de contraseña: ')
if frase_password != "":
b = (hashlib.sha256(frase_password.encode()).digest()).hex()
print ("[+] Número secreto de B (hexadecimal), 'b':", b)
print ("*** B envía a C, creyendo que se lo envía a A, el resultado de g^b mod p")
print ("*** C envía a A, que cree que se lo ha enviado B, el resultado de g^c mod p")
print ("*** A calcula la clave de sesión que cree que va a compartir con B, pero que realmente va a compartir con C: k = (g^c mod p)^a mod p")
ka = exp_modular_rapida(exp_modular_rapida(g, int(c,16), p), int(a,16), p)
print ("[+] Clave de sesión compartida ('k') calculada por A, que cree que va a compartir con B pero realmente lo va a hacer con el atacante (C):", ka)
print ("*** B calcula la clave de sesión que cree que va a compartir con A, pero que realmente va a compartir con C: k = (g^c mod p)^b mod p")
kb = exp_modular_rapida(exp_modular_rapida(g, int(c,16), p), int(b,16), p)
print ("[+] Clave de sesión compartida ('k') calculada por B, que cree que va a compartir con A pero realmente lo va a hacer con el atacante (C):", kb)
print ("*** C calcula la clave de sesión que va a compartir de forma ilegítima con A: k = (g^a mod p)^c mod p")
kca = exp_modular_rapida(exp_modular_rapida(g, int(a,16), p), int(c,16), p)
print ("[+] Clave de sesión compartida ('k') calculada por C para suplantar a B de forma ilegítima en las comunicaciones con A:", kca)
print ("*** C calcula la clave de sesión que va a compartir de forma ilegítima con B: k = (g^b mod p)^c mod p")
kcb = exp_modular_rapida(exp_modular_rapida(g, int(b,16), p), int(c,16), p)
print ("[+] Clave de sesión compartida ('k') calculada por C para suplantar a A de forma ilegítima en las comunicaciones con B:", kcb)
else:
print ("*** ERROR: Por favor, introduzca su frase de contraseña.")
else:
print ("*** ERROR: Por favor, introduzca su frase de contraseña.")
else:
print ("*** ERROR: Por favor, introduzca su frase de contraseña.")
elif opcion == "2":
print ("*** FIN ******************************************")
salir = True
else:
print ("*** ERROR: Opción no válida.")
if __name__ == '__main__':
main()</code>
<br /></pre><p><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><p><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><p><span></span></p><p><span style="font-family: inherit;"><span style="background-color: white;"></span></span></p><p><b><span style="color: #45818e;">Lo ejecuto</span></b>:</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRnzl-ItnQDAOtUusYX08xIHUmQp_BJhB2zg9wZVuybWX45UTzIOel7Sf7g9WUGynCW1N1aoUDL69ivt7Og41ppykart6RAa4_usoahnHr19jxnbVCO22zjVloeErcrQNHl7dPYXmnNFND_2h1SusNx21U8gVAbWQk3sYdIISd0FLkjVJysBfqmYbu/s826/Ataque%20de%20intermediario%20al%20Intercambio%20de%20clave%20de%20Diffie-Hellman_1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="826" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRnzl-ItnQDAOtUusYX08xIHUmQp_BJhB2zg9wZVuybWX45UTzIOel7Sf7g9WUGynCW1N1aoUDL69ivt7Og41ppykart6RAa4_usoahnHr19jxnbVCO22zjVloeErcrQNHl7dPYXmnNFND_2h1SusNx21U8gVAbWQk3sYdIISd0FLkjVJysBfqmYbu/s16000/Ataque%20de%20intermediario%20al%20Intercambio%20de%20clave%20de%20Diffie-Hellman_1.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgADnxgNUug9GDvLIinQMZFSSN_lCwKXuDPp4axH7y7Z4NSjp1Sr2Zd_s1H-1WOrFH3IFbdzNsKG5ce8sX_i3eyc9FgboT7kuW1TH2kKDrVkuAGlESfEMxPi6TKKDey9irJujnZGceApAxgCyHXkZ_AEXapkC3czF7lY1Q4YcwxGylZT-8lfEzcW0Mp/s622/Ataque%20de%20intermediario%20al%20Intercambio%20de%20clave%20de%20Diffie-Hellman_2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="322" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgADnxgNUug9GDvLIinQMZFSSN_lCwKXuDPp4axH7y7Z4NSjp1Sr2Zd_s1H-1WOrFH3IFbdzNsKG5ce8sX_i3eyc9FgboT7kuW1TH2kKDrVkuAGlESfEMxPi6TKKDey9irJujnZGceApAxgCyHXkZ_AEXapkC3czF7lY1Q4YcwxGylZT-8lfEzcW0Mp/s16000/Ataque%20de%20intermediario%20al%20Intercambio%20de%20clave%20de%20Diffie-Hellman_2.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjguM9g04sOjnRUC1pbjSphEzmdR1E1t3LKBIuKP5X1_PMC9vRHVDqd2wUPhWQFwYE3AkFLU68_vaaretzeYVkOCHj3sE8RKZGTG5rVCXLgFdWq_kTjcqK8XOJ2IY12U5xzpWwTdptUCT0qW9P_eqCj9nQtEpbj2oOtPw17CFI_wPVA8LYgfMFqlBCQ/s622/Ataque%20de%20intermediario%20al%20Intercambio%20de%20clave%20de%20Diffie-Hellman_3.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="346" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjguM9g04sOjnRUC1pbjSphEzmdR1E1t3LKBIuKP5X1_PMC9vRHVDqd2wUPhWQFwYE3AkFLU68_vaaretzeYVkOCHj3sE8RKZGTG5rVCXLgFdWq_kTjcqK8XOJ2IY12U5xzpWwTdptUCT0qW9P_eqCj9nQtEpbj2oOtPw17CFI_wPVA8LYgfMFqlBCQ/s16000/Ataque%20de%20intermediario%20al%20Intercambio%20de%20clave%20de%20Diffie-Hellman_3.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJrQJV7M1t-gnha79diUNg96_7WxzJRsmgDkZA-J3XuP2hqLAS6ys1IGgTsqv9Dmv8dY1yZ7RKNEYM0vYXuCcgOJtVS7mT1vCsoocB5LJfIi3ZvvutDCfwRcLNBiOK35ubE1E5v1cd30MfRIutGSmmWcjCpFl1GoJ76CdLuZ2lhTE1omosbb9xgxVb/s622/Ataque%20de%20intermediario%20al%20Intercambio%20de%20clave%20de%20Diffie-Hellman_4.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="370" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJrQJV7M1t-gnha79diUNg96_7WxzJRsmgDkZA-J3XuP2hqLAS6ys1IGgTsqv9Dmv8dY1yZ7RKNEYM0vYXuCcgOJtVS7mT1vCsoocB5LJfIi3ZvvutDCfwRcLNBiOK35ubE1E5v1cd30MfRIutGSmmWcjCpFl1GoJ76CdLuZ2lhTE1omosbb9xgxVb/s16000/Ataque%20de%20intermediario%20al%20Intercambio%20de%20clave%20de%20Diffie-Hellman_4.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEje_1VA3Kf0XuViLTFvxVzza0C5KgTGAwIH43s3jaR9PKiCe9fqvNFgoev5nbNwe_sFGqMQXcbe_-IfcKaS2ALlVHOEUGMAWAnU_WeHIKReHdfc83nzmzyGZbaSvEte4fSzyOAC47UO8n6N8OxR4Glbfw67ppAtxBHgOIat3s29JLS3CSRtaqo9-V7H/s994/Ataque%20de%20intermediario%20al%20Intercambio%20de%20clave%20de%20Diffie-Hellman_5.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="994" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEje_1VA3Kf0XuViLTFvxVzza0C5KgTGAwIH43s3jaR9PKiCe9fqvNFgoev5nbNwe_sFGqMQXcbe_-IfcKaS2ALlVHOEUGMAWAnU_WeHIKReHdfc83nzmzyGZbaSvEte4fSzyOAC47UO8n6N8OxR4Glbfw67ppAtxBHgOIat3s29JLS3CSRtaqo9-V7H/s16000/Ataque%20de%20intermediario%20al%20Intercambio%20de%20clave%20de%20Diffie-Hellman_5.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgV8h5wtmbSTDFXqEmc02jE4nm2wqqTy32BKoaHxTRtSU7sJFAuovstuQaNyF3-TmYQOtC_tCWmL5_yZkGkTYSDy8Di1DKwcp-fPjE5u5XKhv8kFGi7-0EikM23qDUjNMozQlSQTjic8csBZ4LJxxu7Z5JDRIedb9RHsJxR2v5UlKUrpnh5wAcODUbH/s994/Ataque%20de%20intermediario%20al%20Intercambio%20de%20clave%20de%20Diffie-Hellman_6.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="994" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgV8h5wtmbSTDFXqEmc02jE4nm2wqqTy32BKoaHxTRtSU7sJFAuovstuQaNyF3-TmYQOtC_tCWmL5_yZkGkTYSDy8Di1DKwcp-fPjE5u5XKhv8kFGi7-0EikM23qDUjNMozQlSQTjic8csBZ4LJxxu7Z5JDRIedb9RHsJxR2v5UlKUrpnh5wAcODUbH/s16000/Ataque%20de%20intermediario%20al%20Intercambio%20de%20clave%20de%20Diffie-Hellman_6.png" /></a></div><p>Tal y como decía en <a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxxii-ataque-de.html"><span style="color: #2b00fe;">este post</span></a> y se puede ver en las dos últimas imágen<span style="font-family: inherit;">es, <b style="background-color: white; color: #292929;"><span style="color: #45818e;">A y B realmente comparten la clave de sesión (<i>'k'</i>) con C y no entre ellos</span></b><span style="background-color: white; color: #292929;">, y, por tanto, cuando C reciba un mensaje cifrado de A con la clave de sesión que cree compartir con B cuando realmente la comparte con C, éste lo descifrará, es decir, tendrá acceso a su contenido, y, además, se lo enviará a B para que no se dé cuenta de que el mensaje ha sido interceptado y leído, nótese que si lo desea, además, podrá modificarlo a su entera conveniencia y volver a cifrarlo con la clave que comparte con B, y B lo descifrará con la clave de sesión que cree compartir con A cuando realmente la comparte con C, y viceversa cuando C reciba un mensaje cifrado de B.</span></span></p><p><span style="font-family: inherit;"><span style="background-color: white;"><b style="color: #45818e;">Sus comunicaciones cifradas se encuentran totalmente comprometidas</b>, pudiendo el atacante no sólo tener acceso a su contenido sino también modificarlas a conveniencia, <b style="color: #45818e;">y lo peor de todo es que ni siquiera se dan cuenta de que han sido hackeados</b></span><span style="background-color: white; color: #292929;">.</span></span></p><div><span><span style="background-color: white; font-family: inherit;"><p><span style="font-family: inherit;"><b><i>Quizás también te interese</i></b>:</span></p><div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxxii-ataque-de.html" style="font-family: inherit; margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEha8OPcjRFwFl5l6V9PGqAcWOXCoP7GPRZSRW92sWXmUPU32i0MA9OgwquOmZqD7JvhMvAdXfUswKtLD02-uZ7lwOsWE_DHXo_gX0uQd3ne-fMkZcQzq29bBRWaianUFrFMVW-jrNn_pLNkk2wXdumcMtoW1g9D16ZF5Yj5fpO2FRybdzshulv8QmZd/s16000/Ataque%20de%20intermediario%20al%20Intercambio%20de%20clave%20de%20Diffie-Hellman.png" /></a></div></div><div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxx-intercambio-de.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibE88VIh1BKGbWGm5Pc8tzm0QMJevU1F-rJPA8DoZ-nf8aVq6RcyuetH2lP5sOuQksZ9NAcE-7aZLkuV2FCXPnSlfMsRxYDNpkGyZ1ntUx5jzeVhtEgluACitqudFKqtH7mKqWaDJQd6wIJH9RC1nBDaJOtNzO7LEmNEkAOv0fyEYvJEDlbnI6AwQY/s16000/Intercambio%20de%20clave%20de%20Diffie-Hellman.png" /></a><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxxi-intercambio-de.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfcSoVnVdomvgNzqaaV3Zlkeqf_1X152m1quefTv59g6kpMvkOk5sL5PKkT0Xd7UhOV2b-8qoHx78dIZWMoeAVj-HiUs3eFFGafke0xAI-eap_bepM5c_SsD-0sGnPBhYeuEDov7YvQQSal5BHfgohYbdc-kudBfnuswm8o_f5xcYFMFNC4T3MblAF/s16000/Intercambio%20de%20clave%20de%20Diffie-Hellman%20en%20python.png" /></a></div></div></span></span></div>Mikel García Larraganhttp://www.blogger.com/profile/03118239524461394157noreply@blogger.com0tag:blogger.com,1999:blog-1846493661397027137.post-59200407336496796662023-07-29T17:54:00.009+02:002023-07-30T08:34:07.000+02:00Criptografía (CCLXXXII): Ataque de intermediario al Intercambio de clave de Diffie-Hellman<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTXk2yCJr2Dvg-FDWrc9AYTUCL0r7cpSRLF5ek_sy7xUCmnxbQfRw3vhMDNZU-rz5rh8r_mexUr1-rnVxP5xXqsQwlpvcRuSBjzDYNIzzBHKGfx3yY0NsgSTVsf18O4Be8TLGpVMoYHK_aFgHqB4C4k2cuv2UxtXzu6qCDyDITCKizDLm8KqTzyVn2/s256/Diffie-Hellman.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="145" data-original-width="256" height="145" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTXk2yCJr2Dvg-FDWrc9AYTUCL0r7cpSRLF5ek_sy7xUCmnxbQfRw3vhMDNZU-rz5rh8r_mexUr1-rnVxP5xXqsQwlpvcRuSBjzDYNIzzBHKGfx3yY0NsgSTVsf18O4Be8TLGpVMoYHK_aFgHqB4C4k2cuv2UxtXzu6qCDyDITCKizDLm8KqTzyVn2/s1600/Diffie-Hellman.png" width="256" /></a></div>Ya expliqué en <a href="http://mikelgarcialarragan.blogspot.com/2017/04/criptografia-lii-ataque-de.html"><span style="color: #2b00fe;">este post</span></a> en que consistía el <a href="https://es.wikipedia.org/wiki/Ataque_de_intermediario"><span style="color: #2b00fe;">ataque de intermediario</span></a> <span style="font-family: inherit;"><span style="background-color: white; color: #202122;">(MitM, por las siglas en inglés de '</span><i lang="en" style="background-color: white; color: #202122;">Man in the Middle</i><span style="background-color: white; color: #202122;">')</span></span> aplicado al criptosistema <a href="https://es.wikipedia.org/wiki/RSA"><span style="color: #2b00fe;">RSA</span></a>, y <b><span style="color: #45818e;">en esta entrada aplico este mismo ataque al</span></b> <span style="background-color: white;"><a href="https://es.wikipedia.org/wiki/Diffie-Hellman"><span style="color: #2b00fe;">intercambio de clave de Diffie-Hellman</span></a>, que como decía en este <a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxx-intercambio-de.html"><span style="color: #2b00fe;">otro post</span></a> </span>es un protocolo que <span>se utiliza para el intercambio seguro de una clave entre dos </span><span>interlocutores a través de un canal inseguro</span>, como puede ser Internet.<p></p><p>Como también decía en el <a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxx-intercambio-de.html"><span style="color: #2b00fe;">último de los citados posts</span></a>, este <b><span style="color: #45818e;">protocolo de intercam</span></b><span style="font-family: inherit;"><b><span style="color: #45818e;">bio de clave es vulnerable a este tipo de ataques </span></b><span style="background-color: white;"><b><span style="color: #45818e;">cuando se realiza de forma no autenticada</span></b>,</span><span style="background-color: white;"> y que consiste en que un atacante se interponga en las comunicaciones entre A y B, suplantando a uno frente al otro y haciendo que ninguno de los dos se dé cuenta de que están siendo hackeados.</span></span></p><p><span style="font-family: inherit;"><span style="background-color: white;">Pero <b><span style="color: #45818e;">veamos cómo</span></b>:</span></span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuxy__1CAWqE7PYBXrqJdYkAszIbjAHd28Vc8NXNh12UaLSg7y0xpPAjL5WHGqJT7uhwxfLoI_shFXasW5x-Aup1-Lp8aL9CJkYbMf1Ye20bDRBcpsS8_jmwzIWaNcV324-qamnoWRexCSmhDyugFsakkqqvgGVUFp9-k9k1rZWhnvrIGOssSUQQmm/s624/Man%20in%20the%20middle.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="430" data-original-width="624" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuxy__1CAWqE7PYBXrqJdYkAszIbjAHd28Vc8NXNh12UaLSg7y0xpPAjL5WHGqJT7uhwxfLoI_shFXasW5x-Aup1-Lp8aL9CJkYbMf1Ye20bDRBcpsS8_jmwzIWaNcV324-qamnoWRexCSmhDyugFsakkqqvgGVUFp9-k9k1rZWhnvrIGOssSUQQmm/s16000/Man%20in%20the%20middle.png" /></a></div><p style="text-align: left;">Si un atacante (C) se interpone en las comunicaciones entre A y B, suplantando a uno frente al otro:</p><p style="text-align: left;">1.- C se hará con el valor de <i>g<sup>a</sup> mod p</i> que A ha calculado con su número secreto 'a' y que cree que está enviando a B.</p><p style="text-align: left;">2.- Seguidamente, C enviará a B el valor de <i>g<sup>c</sup> mod p</i>, que ha calculado con su propio número secreto 'c', y que B cree estar recibiendo de A.</p><p style="text-align: left;">3.- C se hará con el valor de <i>g<sup>b</sup> mod p</i> que B ha calculado con su número secreto 'b' y que cree que está enviando a A.</p><p style="text-align: left;">4.- Seguidamente, C enviará a A el valor de <i>g<sup>c</sup> mod p</i>, que ha calculado con su propio número secreto 'c', y que A cree estar recibiendo de B.</p><p style="text-align: left;">A partir de ahí, <b><span style="color: #45818e;">A y B realmente comparten la clave de sesión (<i>'K'</i>) con C y no entre ellos</span></b>, y, por tanto, cuando C reciba un mensaje cifrado de A con la clave de sesión que cree compartir con B cuando realmente la comparte con C, éste lo descifrará, es decir, tendrá acceso a su contenido, y, además, se lo enviará a B para que no se dé cuenta de que el mensaje ha sido interceptado y leído, nótese que si lo desea, además, podrá modificarlo a su entera conveniencia y volver a cifrarlo con la clave que comparte con B, y B lo descifrará con la clave de sesión que cree compartir con A cuando realmente la comparte con C, y viceversa cuando C reciba un mensaje cifrado de B.</p><p style="text-align: left;">De esta forma <b><span style="color: #45818e;">A y B han sido hackeados y sus comunicaciones cifradas se encuentran totalmente comprometidas, pudiendo el atacante no sólo tener acceso a su contenido sino también modificarlas a conveniencia sin que ninguno de los dos se dé cuenta</span></b>. </p><p style="text-align: left;">Evidentemente, para que esto no ocurra, la autenticación con certificados es totalmente recomendable antes de la negociación de la clave entre los intervinientes, bien se trate de clientes o de servidores.</p><p><span style="background-color: white; font-family: inherit;"><b><i>Quizás también te interese</i></b>:</span></p><div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxx-intercambio-de.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibE88VIh1BKGbWGm5Pc8tzm0QMJevU1F-rJPA8DoZ-nf8aVq6RcyuetH2lP5sOuQksZ9NAcE-7aZLkuV2FCXPnSlfMsRxYDNpkGyZ1ntUx5jzeVhtEgluACitqudFKqtH7mKqWaDJQd6wIJH9RC1nBDaJOtNzO7LEmNEkAOv0fyEYvJEDlbnI6AwQY/s16000/Intercambio%20de%20clave%20de%20Diffie-Hellman.png" /></a><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxxi-intercambio-de.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfcSoVnVdomvgNzqaaV3Zlkeqf_1X152m1quefTv59g6kpMvkOk5sL5PKkT0Xd7UhOV2b-8qoHx78dIZWMoeAVj-HiUs3eFFGafke0xAI-eap_bepM5c_SsD-0sGnPBhYeuEDov7YvQQSal5BHfgohYbdc-kudBfnuswm8o_f5xcYFMFNC4T3MblAF/s16000/Intercambio%20de%20clave%20de%20Diffie-Hellman%20en%20python.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxxiii-ataque-de.html" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRAubF_R0fu_rGGpL_VXcfhLHu57a7mYtIrYaNvRGrwHI-JJq4gHKjwZ_5CI68aAdNag0iWuUXrhKyMRVW7jawcslgODBoiiBKXYFmKqzPXiyNH_xvopjPbzvxqUy5Sp7PjjPUc_4TpFAd0LuC-o6WtCZQI8ycWCtPjTgwAnMPk8jAgy0l8GX4lj5y/s16000/Ataque%20de%20intermediario%20al%20Intercambio%20de%20clave%20de%20Diffie-Hellman%20en%20python.png" /></a></div></div>Mikel García Larraganhttp://www.blogger.com/profile/03118239524461394157noreply@blogger.com0tag:blogger.com,1999:blog-1846493661397027137.post-59576773372674123642023-07-29T12:29:00.009+02:002023-08-13T09:41:31.075+02:00Criptografía (CCLXXXI): Intercambio de clave de Diffie-Hellman en python<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrWMpkwc9NzdxvB3EtKt1SB477q-ne7uZQh0KRGcK34rnVFOMJvWokRFrK3Pau-CKTNQGfHYYZLswpHJ6sVDnzB1fS_ysrRPDF2NCjOQX0SA7Ds6a5iYz18dJT4Zoqf8tG9IvwKeae-gb7KJw6UPVMd_Dn2F7uN7NOBoDIKBrGWROm5HSfzm85RbRa/s256/Diffie-Hellman.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="145" data-original-width="256" height="145" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrWMpkwc9NzdxvB3EtKt1SB477q-ne7uZQh0KRGcK34rnVFOMJvWokRFrK3Pau-CKTNQGfHYYZLswpHJ6sVDnzB1fS_ysrRPDF2NCjOQX0SA7Ds6a5iYz18dJT4Zoqf8tG9IvwKeae-gb7KJw6UPVMd_Dn2F7uN7NOBoDIKBrGWROm5HSfzm85RbRa/s1600/Diffie-Hellman.png" width="256" /></a></div>Continúo poniendo scripts de programación en python para automatizar tareas que tengan relación con la <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa"><span style="color: #2b00fe;">criptografía</span></a>.<p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p><b><span style="color: #45818e;">En este post incluyo un </span></b><span style="color: #45818e; font-weight: bold;">script en python para implementar </span><span style="font-family: inherit;"><span style="background-color: white;">el </span><a href="https://es.wikipedia.org/wiki/Diffie-Hellman"><span style="color: #2b00fe;">intercambio de clave de Diffie-Hellman</span></a>.</span></p><p><span style="font-family: inherit;"><span><span>Antes de poner el script, recordar que en <a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxx-intercambio-de.html"><span style="color: #2b00fe;">este post</span></a> decía que este </span></span></span><a href="https://es.wikipedia.org/wiki/Protocolo_criptogr%C3%A1fico" style="font-family: inherit;"><span style="color: #2b00fe;">protocolo criptográfico</span></a><span style="font-family: inherit;"><span> </span></span><b><span style="color: #45818e;"><span>se utiliza para el intercambio seguro de una clave entre dos </span><span>interlocutores a través de un canal inseguro</span></span></b>, como puede ser Internet, <span style="font-family: inherit;"><span>sin poner en peligro el secreto de ésta si las comunicaciones entre ambos son interceptadas por un tercero</span></span><span>.</span></p><p><span><b><span style="color: #45818e;">El script simula el intercambio de clave</span></b>, por ejemplo: una clave de sesión para ser utilizada en el cifrado y descifrado de mensajes mediante <a href="https://es.wikipedia.org/wiki/Advanced_Encryption_Standard"><span style="color: #2b00fe;">AES</span></a>, entre Alicia (A) y Bernardo (B), <b><span style="color: #45818e;">de la siguiente manera</span></b>:</span></p><p><span>1.- A genera un número primo aleatorio <i>'p'</i> de 2.048 bits y se lo envía a B junto con el número 5, que le propone utilizar como número </span><i>'g'</i> para este intercambio de clave.</p><p><span style="font-family: inherit;">2.- <span>A introduce una <a href="https://es.wikipedia.org/wiki/Frase_de_contrase%C3%B1a"><span style="color: #2b00fe;">frase de contraseña</span></a> de la que se calcula el hash <a href="https://es.wikipedia.org/wiki/SHA-2"><span style="color: #2b00fe;">SHA-256</span></a> para obtener su número <i>'a'</i></span>, que será secreto (sólo ella debe conocerlo), <span>y envía a B el resultado de la operación </span></span><i><span>g<sup>a</sup> mod p</span></i><span style="font-family: inherit;"><span style="line-height: 18.4px;"><span>.</span></span></span></p><p><span style="font-family: inherit;"><span style="color: #222222; line-height: 18.4px;">3.- </span></span><span>B </span>introduce su <a href="https://es.wikipedia.org/wiki/Frase_de_contrase%C3%B1a"><span style="color: #2b00fe;">frase de contraseña</span></a> de la que se calcula el hash <a href="https://es.wikipedia.org/wiki/SHA-2"><span style="color: #2b00fe;">SHA-256</span></a> para obtener su número <i>'b'</i>, que será secreto (sólo él debe conocerlo), <span>y envía a A el resultado de la operación </span><span style="line-height: 18.4px;"><i><span>g<sup>b</sup> mod p</span></i><span>.</span></span></p><p><span style="line-height: 18.4px;"><span><span style="color: black;"><span style="color: #222222;">4.- A y B calculan, cada uno de forma separa del otro, la clave d</span>e sesión </span><span style="color: black;"><span>(<i>'k'</i>) que van a compartir en </span></span></span></span>el cifrado y descifrado de mensajes mediante <a href="https://es.wikipedia.org/wiki/Advanced_Encryption_Standard"><span style="color: #2b00fe;">AES</span></a>:</p><p>4.1.- A calcula: <span><i>k = (g<sup>b</sup> mod p)<sup>a</sup> mod p</i></span>.</p><p><span>4.2.- B clacula: </span><span><span><i>k = (g<sup>a</sup> mod p)<sup>b</sup> mod p</i></span></span><span style="color: black;">.</span></p><p><span style="color: black;">5.- Se comprueba que la clave de sesión calculada por ambos de forma independiente es la misma y, por tanto, se concluye si el intercambio se ha realizado con éxito o no.</span></p><p>Para que el script funcione se necesita importar los dos siguientes módulos en el programa principal, <span>que se encargarán, respectivamente, de la generación del número primo <i>'p'</i> de 2.048 bits y de realizar las operaciones de exponenciación modular de forma </span><span>eficiente.</span></p><p></p><pre><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# GENERACIÓN DE UN NÚMERO PRIMO ALEATORIO:
#
# Generación de un número primo aleatorio a partir de un número de b bits.
#
# http://mikelgarcialarragan.blogspot.com/
from sympy import primerange, prime
from random import randint, getrandbits
def test_miller_rabin(n,k):
# n = número natural mayor que 1 e impar del que queremos conocer si es primo.
# k = número de veces o rondas a ejecutar el test.
# t = indicador de que n es primo con un cierto nivel de confianza (0: primo; 1: compuesto).
# s = número de veces que 2 divide a n - 1.
t = 0
s = 0
r = n - 1
while r%2 == 0:
s+=1
r = r//2
i=0
while i in range(0, k) and t != 1:
a = randint(2, n - 1)
j = 0
y = pow(a, r, n)
if y != 1 and y != n - 1:
j = 1
while y != n - 1 and t != 1 and j <= s - 1:
y = pow(y, 2, n)
if y == 1:
t = 1
else:
j = j + 1
if y != n -1:
t = 1
i = i + 1
if t == 0:
return True
else:
return False
def generar_primo_aleatorio(b,k):
# b = número de bits que tendrá como mínimo el número primo aleatorio.
# k = número de veces o rondas a ejecutar el test de primalidad.
# Se genera un número aleatorio impar (p) de b bits.
p = getrandbits(int(b))
if p%2 == 0:
p+=1
# Se crea una lista con los primeros 2048 números primos, para descartar rápidamente aquellos
# candidatos no primos, es decir, aquellos que son divisibles por alguno de los números primos
# integrantes de esta lista.
primeros_2048_primos = list(primerange(prime(2048 + 1)))
# Se realizan las comprobaciones tendentes a verificar si el candidato es primo con un cierto
# nivel de confianza.
puede_ser_primo = False
while not puede_ser_primo:
puede_ser_primo = True
for primo in primeros_2048_primos:
if p%primo == 0:
puede_ser_primo = False
break
# Si el candidato supera la primera criba, es decir no es divisible entre ninguno de los primeros
# 2048 números primos, entonces se le somete al test de primalidad de Miller-Rabin.
if puede_ser_primo:
if not test_miller_rabin(p,int(k)):
puede_ser_primo = False
# Si el candidato no supera la primera criba, es decir es divisible entre alguno de los primeros
# 2048 números primos o no supera el test de primalidad de Miller-Rabin, entonces se incrementa
# al candidato en dos unidades y se vuelve a comprobar si el nuevo candidato puede ser primo.
if not puede_ser_primo:
p+=2
return p</code>
<br /></pre><p><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><p><span style="background-color: white; color: #292929; font-family: inherit;"></span></p><p><span></span></p><p></p><pre><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ALGORITMO DE EXPONENCIACIÓN MODULAR RÁPIDA:
#
# Algoritmo utilizado en operaciones de exponenciación modular
# con números muy grandes con objeto de hacerlas de forma
# más eficiente.
#
# http://mikelgarcialarragan.blogspot.com/
def exp_modular_rapida(b, e, m):
c = 1
e = bin(e)[2:]
for i in range(0, len(e)):
c = pow(c, 2, m)
if e[i]=="1":
c = c*b%m
return c</code>
<br /></pre><p><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><p><span style="background-color: white; color: #292929; font-family: inherit;"></span></p><p>El <b><span style="color: #45818e;">script</span></b> es el siguiente:</p><p><span style="font-family: inherit;"><span style="background-color: white; color: #292929;">- </span><i style="background-color: white; color: #292929;"><u>Script python para el intercambio de clave de Diffie-Hellman</u></i><span style="background-color: white; color: #292929;">:</span></span></p><p></p><pre><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# INTERCAMBIO DE CLAVE DE DIFFIE-HELLMAN:
#
# Protocolo Diffie-Hellman para el intercambio seguro de una clave de sesión a través de un canal inseguro.
#
# http://mikelgarcialarragan.blogspot.com/
import hashlib
import primo_aleatorio
from exponenciacion_modular_rapida import exp_modular_rapida
def main():
# MENÚ:
# Se presenta el menú para que se seleccione una opción.
salir = False
while not salir:
print ("")
print ("*** MENÚ *****************************************")
print ("1. Intercambio de clave de sesión entre A y B.")
print ("2. Salir.")
print ("")
opcion = input("Por favor, seleccione una opción: ")
if opcion == "1":
print ("")
print ("--- INTERCAMBIAR CLAVE DE SESIÓN ENTRE A Y B:")
print ("*** A genera un número primo aleatorio 'p' de 2.048 bits y escoge 'g' = 5")
p = primo_aleatorio.generar_primo_aleatorio(2048,5)
g = 5
print ("[+] Número primo aleatorio 'p' generado:", p)
print ("[+] Número 'g' escogido:", g)
print ("*** A envía a B el número primo aleatorio 'p' y 'g'")
print ("*** A introduce una frase de contraseña de la que se calcula el hash SHA-256 para obtener su número secreto 'a'")
frase_password = ""
while frase_password == "":
frase_password = input('Por favor, introduzca su frase de contraseña: ')
if frase_password != "":
a = (hashlib.sha256(frase_password.encode()).digest()).hex()
print ("[+] Número secreto de A (hexadecimal), 'a':", a)
print ("*** A envía a B el resultado de g^a mod p")
print ("*** B introduce una frase de contraseña de la que se calcula el hash SHA-256 para obtener su número secreto 'b'")
frase_password = ""
while frase_password == "":
frase_password = input('Por favor, introduzca su frase de contraseña: ')
if frase_password != "":
b = (hashlib.sha256(frase_password.encode()).digest()).hex()
print ("[+] Número secreto de B (hexadecimal), 'b':", b)
print ("*** B envía a A el resultado de g^b mod p")
print ("*** A calcula la clave de sesión que va a compartir con B, k = (g^b mod p)^a mod p")
ka = exp_modular_rapida(exp_modular_rapida(g, int(b,16), p), int(a,16), p)
print ("[+] Clave de sesión compartida ('k') calculada por A:", ka)
print ("*** B calcula la clave de sesión que va a compartir con A, k = (g^a mod p)^b mod p")
kb = exp_modular_rapida(exp_modular_rapida(g, int(a,16), p), int(b,16), p)
print ("[+] Clave de sesión compartida ('k') calculada por B:", kb)
if ka == kb:
print ("[+] Las claves de sesión calculadas por A y B de forma independiente son iguales. INTERCAMBIO DE CLAVE CORRECTO.")
else:
print ("[+] Las claves de sesión calculadas por A y B de forma independiente son diferentes. INTERCAMBIO DE CLAVE INCORRECTO.")
else:
print ("*** ERROR: Por favor, introduzca su frase de contraseña.")
else:
print ("*** ERROR: Por favor, introduzca su frase de contraseña.")
elif opcion == "2":
print ("*** FIN ******************************************")
salir = True
else:
print ("*** ERROR: Opción no válida.")
if __name__ == '__main__':
main()</code>
<br /></pre><p><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><p><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><p><span></span></p><p><b><span style="color: #45818e;">Lo ejecuto</span></b>:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjysVX_s-Moge5VnRxPONBLWaPbcHYXVxaiXF35rh_vu9lntzYH1kQt2fWsvhk_tybBjDCwd4cvPu9K-l626JcvAJGdg3N883eqnca0RSsELBg-nvoZShZyQnLVtGJneyFTVDrXTRR666A7qnZ09ayCYZaz-lRgoQtDb3mpeNZfRfFm8W-C0uqJCesv/s730/Diffie-Hellman_1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="730" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjysVX_s-Moge5VnRxPONBLWaPbcHYXVxaiXF35rh_vu9lntzYH1kQt2fWsvhk_tybBjDCwd4cvPu9K-l626JcvAJGdg3N883eqnca0RSsELBg-nvoZShZyQnLVtGJneyFTVDrXTRR666A7qnZ09ayCYZaz-lRgoQtDb3mpeNZfRfFm8W-C0uqJCesv/s16000/Diffie-Hellman_1.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXVFWh4xs_2hA66mcLdranlrFNRD3n8u4N2RjfIQoAIxodqnIOqZ_0KvAkaQ_UQ-Rb6z4Hl4dynQ2b1ScbOwAgrso78WjJiaajGMOhj6vH-pycIk1V3kNbV3X0XsLLb1hUWa5HB4gERhxXi2MACePDAp5uwY47OIhMApdP2nRenKNPEzjOr1kIahNy/s622/Diffie-Hellman_2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="322" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXVFWh4xs_2hA66mcLdranlrFNRD3n8u4N2RjfIQoAIxodqnIOqZ_0KvAkaQ_UQ-Rb6z4Hl4dynQ2b1ScbOwAgrso78WjJiaajGMOhj6vH-pycIk1V3kNbV3X0XsLLb1hUWa5HB4gERhxXi2MACePDAp5uwY47OIhMApdP2nRenKNPEzjOr1kIahNy/s16000/Diffie-Hellman_2.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWL4a-NkvD_CIy4FrXvyRO8QdQP7JhZGp72qYcn82DOJ2hHeK5882ZvEPyxduv8j_fM90NKFPy4Y91fBj7wAB9Ue-e3DssbXJ3v1SDejmkTv2u1sNiw63vh8vfE9zJXvx4FedHb9riACo_vbkc7ThA5n3Y14d6N1yrlBvH4VCSaGzsIt5EAiFdRtqW/s622/Diffie-Hellman_3.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="322" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWL4a-NkvD_CIy4FrXvyRO8QdQP7JhZGp72qYcn82DOJ2hHeK5882ZvEPyxduv8j_fM90NKFPy4Y91fBj7wAB9Ue-e3DssbXJ3v1SDejmkTv2u1sNiw63vh8vfE9zJXvx4FedHb9riACo_vbkc7ThA5n3Y14d6N1yrlBvH4VCSaGzsIt5EAiFdRtqW/s16000/Diffie-Hellman_3.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTa1mzyiBmnsOeBbNXH0DaV0lHlfOjTHlEkvOnD1RMZ8CmLcyG7Eu6B7MHayPfIRnSaI6e1hri-POoWG1YFdmwwARHUxIue2jkQbDBw_RZMGcJcsaAbKLfJEIaTwhQCAXw4Hv7TH31qgApGoHeMfZ0aEGG-wzoBOuTayck9QFQ1JCvs6XVohh6qAKc/s922/Diffie-Hellman_4.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="922" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTa1mzyiBmnsOeBbNXH0DaV0lHlfOjTHlEkvOnD1RMZ8CmLcyG7Eu6B7MHayPfIRnSaI6e1hri-POoWG1YFdmwwARHUxIue2jkQbDBw_RZMGcJcsaAbKLfJEIaTwhQCAXw4Hv7TH31qgApGoHeMfZ0aEGG-wzoBOuTayck9QFQ1JCvs6XVohh6qAKc/s16000/Diffie-Hellman_4.png" /></a></div><p><span style="background-color: white; font-family: inherit;"><b><i>Quizás también te interese</i></b>:</span></p><div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxx-intercambio-de.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibE88VIh1BKGbWGm5Pc8tzm0QMJevU1F-rJPA8DoZ-nf8aVq6RcyuetH2lP5sOuQksZ9NAcE-7aZLkuV2FCXPnSlfMsRxYDNpkGyZ1ntUx5jzeVhtEgluACitqudFKqtH7mKqWaDJQd6wIJH9RC1nBDaJOtNzO7LEmNEkAOv0fyEYvJEDlbnI6AwQY/s16000/Intercambio%20de%20clave%20de%20Diffie-Hellman.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><div class="MsoNormal" style="text-align: left;"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxxii-ataque-de.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEha8OPcjRFwFl5l6V9PGqAcWOXCoP7GPRZSRW92sWXmUPU32i0MA9OgwquOmZqD7JvhMvAdXfUswKtLD02-uZ7lwOsWE_DHXo_gX0uQd3ne-fMkZcQzq29bBRWaianUFrFMVW-jrNn_pLNkk2wXdumcMtoW1g9D16ZF5Yj5fpO2FRybdzshulv8QmZd/s16000/Ataque%20de%20intermediario%20al%20Intercambio%20de%20clave%20de%20Diffie-Hellman.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxxiii-ataque-de.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRAubF_R0fu_rGGpL_VXcfhLHu57a7mYtIrYaNvRGrwHI-JJq4gHKjwZ_5CI68aAdNag0iWuUXrhKyMRVW7jawcslgODBoiiBKXYFmKqzPXiyNH_xvopjPbzvxqUy5Sp7PjjPUc_4TpFAd0LuC-o6WtCZQI8ycWCtPjTgwAnMPk8jAgy0l8GX4lj5y/s16000/Ataque%20de%20intermediario%20al%20Intercambio%20de%20clave%20de%20Diffie-Hellman%20en%20python.png" /></a></div></div></div></div>Mikel García Larraganhttp://www.blogger.com/profile/03118239524461394157noreply@blogger.com0tag:blogger.com,1999:blog-1846493661397027137.post-1818862687756983512023-07-27T22:04:00.114+02:002023-09-14T21:18:17.481+02:00Criptografía (CCLXXX): Intercambio de clave de Diffie-Hellman<p><span style="font-family: inherit;"><span style="background-color: white;"></span></span></p><div class="separator" style="clear: both; text-align: left;"><span style="font-family: inherit;"><div class="separator" style="clear: both; text-align: left;"><span style="font-family: inherit;"><div class="separator" style="clear: both; text-align: left;"><span style="font-family: inherit;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiWJQ0qoSXyunRipqVVfNLZ882PvS6cllQBddyrE9vZ1QrEoPWLnTsr5bTA2JfZ9JEZ9HRvh52veQfjwqyV1H5bETfROTWdqz_dEjAFwbSPiuOBglNs2oAtFSsEv3gXTkMmTShAmnwSRhiDHR5Oi1DAMDJD9_F3SJissvJ7Uz2WMVDXfvOWxa9Le37/s256/Diffie-Hellman.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="145" data-original-width="256" height="145" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiWJQ0qoSXyunRipqVVfNLZ882PvS6cllQBddyrE9vZ1QrEoPWLnTsr5bTA2JfZ9JEZ9HRvh52veQfjwqyV1H5bETfROTWdqz_dEjAFwbSPiuOBglNs2oAtFSsEv3gXTkMmTShAmnwSRhiDHR5Oi1DAMDJD9_F3SJissvJ7Uz2WMVDXfvOWxa9Le37/s1600/Diffie-Hellman.png" width="256" /></a></div></span><p><span style="font-family: inherit;">Entre las entradas que pongo en este blog para contar de la forma más comprensible de la que sea capaz lo que voy aprendiendo sobre <a href="https://es.wikipedia.org/wiki/Criptolog%C3%ADa"><span style="color: #2b00fe;">criptología</span></a>, <b><span style="color: #45818e;">le toca el turno al</span></b> <a href="https://es.wikipedia.org/wiki/Protocolo_criptogr%C3%A1fico"><span style="color: #2b00fe;">protocolo criptográfico</span></a> <b><span style="color: #45818e;">para el intercambio de clave propuesto por</span></b> </span><span style="background-color: white; font-family: inherit;"><a href="https://es.wikipedia.org/wiki/Whitfield_Diffie"><span style="color: #2b00fe;">Whitfield Diffie</span></a> y </span><span style="background-color: white; font-family: inherit;"><a href="https://es.wikipedia.org/wiki/Martin_Hellman"><span style="color: #2b00fe;">Martin Hellman</span></a> </span><span style="background-color: white; font-family: inherit;">en 1976.</span></p><p><span style="background-color: white; font-family: inherit;">El <a href="https://es.wikipedia.org/wiki/Diffie-Hellman"><span style="color: #2b00fe;">intercambio de clave de Diffie-Hellman</span></a> </span>es un protocolo que <b><span style="color: #45818e;">se utiliza para el intercambio seguro de una clave entre dos </span></b><b><span style="color: #45818e;">interlocutores a través de un canal inseguro</span></b>, como puede ser Internet.</p><p><b><span style="color: #45818e;">Sean A (Alicia) y B (Bernardo) los dos interlocutores que desean intercambiar una clave de sesión</span></b>, un número que se utiliza como clave para cifrar y descifrar utilizando un <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_sim%C3%A9trica"><span style="color: #2b00fe;">criptosistema de clave simétrica o secreta</span></a> y que ambos interlocutores deben conocer (compartir), <b><span style="color: #45818e;">sin poner en peligro el secreto de ésta si las comunicaciones entre ambos son interceptadas por un tercero</span></b>.</p><p><b><span style="color: #45818e;">A y B actuarían de la siguiente manera</span></b>:</p><p><span style="text-align: justify;">1.- <b><span style="color: #45818e;">Se ponen de acuerdo para escoger un número primo </span></b></span><i style="color: #45818e; font-weight: bold; text-align: justify;">'p' </i><span style="color: #45818e; font-weight: bold; text-align: justify;">y</span><span style="color: #45818e; font-weight: bold; text-align: justify;">
</span><a href="https://es.wikipedia.org/wiki/Ra%C3%ADz_primitiva_m%C3%B3dulo_n"><span style="color: #2b00fe;"><span style="text-align: justify;">un generador </span><i style="text-align: justify;">'g'</i><span style="text-align: justify;"> o raíz primitiva módulo </span><i style="text-align: justify;">'p'</i></span></a><span style="text-align: justify;">. </span><span style="text-align: justify;"><b><span style="color: #45818e;">Ambos números son públicos</span></b>,</span><span style="text-align: justify;"> es decir, pueden ser conocidos por cualquiera, incluso por un atacante
que intercepte las comunicaciones en las que A y B los escogen.</span></p></div></span></div></span></div><div><p class="MsoNormal" style="text-align: justify;"><o:p></o:p></p>
<p class="MsoNormal" style="text-align: justify;"><span style="line-height: 107%;">¿Qué es un generador <i>‘g’</i> o raíz primitiva
módulo <i>‘p’</i>? Pues esto no es tan importante, ya que como diré más adelante el protocolo funciona aunque el segundo número escogido no lo sea, pero lo explico (espero haberlo entendido bien y no equivocarme mucho): es un resto de <i>‘p’</i> cuyas
operaciones </span><i><span style="font-family: "inherit", serif; line-height: 107%;">g</span></i><i><sup><span style="font-family: "inherit", serif; line-height: 107%;">1</span></sup></i><i><span style="line-height: 107%;"> mod p</span></i><span style="line-height: 107%;">, </span><i><span style="font-family: "inherit", serif; line-height: 107%;">g</span></i><i><sup><span style="font-family: "inherit", serif; line-height: 107%;">2</span></sup></i><i><span style="line-height: 107%;"> mod p</span></i><span style="line-height: 107%;">,…, </span><i><span style="font-family: "inherit", serif; line-height: 107%;">g</span></i><i><sup><span style="font-family: "inherit", serif; line-height: 107%;">p-1</span></sup></i><i><span style="line-height: 107%;"> mod p</span></i><span style="line-height: 107%;"> dan como resultado todos los restos de <i>‘p’</i> desde 1 a <i>p
- 1</i>.<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: justify;"><span style="line-height: 107%;">Así, por ejemplo, si <i>p = 7</i>, entonces 3 es un generador
o raíz primitiva módulo 7, ya que:<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: center;"><i><span style="font-family: "inherit", serif; line-height: 107%;">3</span><sup><span style="font-family: "inherit", serif; line-height: 107%;">1</span></sup><span style="line-height: 107%;"> mod 7</span><span style="line-height: 107%;"> = 3; </span><span style="font-family: "inherit", serif; line-height: 107%;">3</span><sup><span style="font-family: "inherit", serif; line-height: 107%;">2</span></sup><span style="line-height: 107%;"> mod 7</span><span style="line-height: 107%;"> = 2; </span><span style="font-family: "inherit", serif; line-height: 107%;">3</span><sup><span style="font-family: "inherit", serif; line-height: 107%;">3</span></sup><span style="line-height: 107%;"> mod 7</span><span style="line-height: 107%;"> = 6; </span><span style="font-family: "inherit", serif; line-height: 107%;">3</span><sup><span style="font-family: "inherit", serif; line-height: 107%;">4</span></sup><span style="line-height: 107%;"> mod 7</span><span style="line-height: 107%;"> = 4; </span><span style="font-family: "inherit", serif; line-height: 107%;">3</span><sup><span style="font-family: "inherit", serif; line-height: 107%;">5</span></sup><span style="line-height: 107%;"> mod 7</span><span style="line-height: 107%;"> = 5; </span><span style="font-family: "inherit", serif; line-height: 107%;">3</span><sup><span style="font-family: "inherit", serif; line-height: 107%;">6</span></sup><span style="line-height: 107%;"> mod 7</span></i><span style="line-height: 107%;"><i> = 1</i><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: justify;"><span style="line-height: 107%;">Pero 2 no lo es:<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: center;"><i><span style="font-family: "inherit", serif; line-height: 107%;">2</span><sup><span style="font-family: "inherit", serif; line-height: 107%;">1</span></sup><span style="line-height: 107%;"> mod 7</span><span style="line-height: 107%;"> = 2; </span><span style="font-family: "inherit", serif; line-height: 107%;">2</span><sup><span style="font-family: "inherit", serif; line-height: 107%;">2</span></sup><span style="line-height: 107%;"> mod 7</span><span style="line-height: 107%;"> = 4; </span><span style="font-family: "inherit", serif; line-height: 107%;">2</span><sup><span style="font-family: "inherit", serif; line-height: 107%;">3</span></sup><span style="line-height: 107%;"> mod 7</span><span style="line-height: 107%;"> = 1; </span><span style="font-family: "inherit", serif; line-height: 107%;">2</span><sup><span style="font-family: "inherit", serif; line-height: 107%;">4</span></sup><span style="line-height: 107%;"> mod 7</span><span style="line-height: 107%;"> = 2; </span><span style="font-family: "inherit", serif; line-height: 107%;">2</span><sup><span style="font-family: "inherit", serif; line-height: 107%;">5</span></sup><span style="line-height: 107%;"> mod 7</span><span style="line-height: 107%;"> = 4; </span><span style="font-family: "inherit", serif; line-height: 107%;">2</span><sup><span style="font-family: "inherit", serif; line-height: 107%;">6</span></sup><span style="line-height: 107%;"> mod 7</span></i><span style="line-height: 107%;"><i> = 1</i><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: justify;"><span style="line-height: 107%;">¿Cómo puedo saber si un número concreto, <i>‘g’</i>, es un generador o raíz primitiva módulo <i>‘p’</i>? Pues lo es si el </span><span style="color: black; line-height: 107%; text-decoration-line: none;">orden</span><span style="line-height: 107%;"> de <i>‘g’ </i>respecto al módulo <i>‘p’</i> (el exponente
positivo <i>‘o’</i> más pequeño tal que </span><i><span style="font-family: "inherit", serif; line-height: 107%;">g</span></i><i><sup><span style="font-family: "inherit", serif; line-height: 107%;">o</span></sup></i><i><span style="line-height: 107%;"> ≡ 1 (mod p)</span></i><span style="line-height: 107%;">) es <i>ϕ(p)</i>.<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: justify;"><span style="line-height: 107%;">En nuestro caso, como <i>‘p’</i> es primo, entonces<i>
ϕ(p) = p - 1</i>, por lo que en el ejemplo anterior <i>ϕ(7) = 7 - 1</i> = 6 y,
por tanto, sólo los restos de 7 cuyo orden (<i>‘o’</i>) sea 6 son un generador
o raíz primitiva módulo 7. El orden de los restos de 7 es el siguiente:<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: center;"><i><span style="font-family: "inherit", serif; line-height: 107%;">1</span></i><i><sup><span style="font-family: "inherit", serif; line-height: 107%;">1</span></sup></i><i><span style="line-height: 107%;"> ≡ 1 (mod 7); o(1) = 1 </span></i><i><span style="line-height: 107%;">≠</span></i><i><span style="line-height: 107%;"> ϕ(7)</span></i><span style="line-height: 107%;">. 1 no es un generador o raíz primitiva de 7.<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: center;"><i><span style="font-family: "inherit", serif; line-height: 107%;">2</span></i><i><sup><span style="font-family: "inherit", serif; line-height: 107%;">3</span></sup></i><i><span style="line-height: 107%;"> ≡ 1 (mod 7); o(2) = 3 </span></i><i><span style="line-height: 107%;">≠</span></i><i><span style="line-height: 107%;"> ϕ(7)</span></i><span style="line-height: 107%;">. 2 no es un generador o raíz primitiva de 7.<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: center;"><span style="color: red;"><i><span style="font-family: "inherit", serif; line-height: 107%;">3</span></i><i><sup><span style="font-family: "inherit", serif; line-height: 107%;">6</span></sup></i><i><span style="line-height: 107%;"> ≡ 1 (mod 7); o(3) = 6 = ϕ(7)</span></i></span><span style="line-height: 107%;"><span style="color: red;">. 3 es un generador o
raíz primitiva de 7.</span><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: center;"><i><span style="font-family: "inherit", serif; line-height: 107%;">4</span></i><i><sup><span style="font-family: "inherit", serif; line-height: 107%;">3</span></sup></i><i><span style="line-height: 107%;"> ≡ 1 (mod 7); o(4) = 3 </span></i><i><span style="line-height: 107%;">≠</span></i><i><span style="line-height: 107%;"> ϕ(7)</span></i><span style="line-height: 107%;">. 4 no es un generador o raíz primitiva de 7.<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: center;"><span style="color: red;"><i><span style="font-family: "inherit", serif; line-height: 107%;">5</span></i><i><sup><span style="font-family: "inherit", serif; line-height: 107%;">6</span></sup></i><i><span style="line-height: 107%;"> ≡ 1 (mod 7); o(5) = 6 = ϕ(7)</span></i></span><span style="line-height: 107%;"><span style="color: red;">. 5 es un generador o
raíz primitiva de 7.</span><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: center;"><i><span style="font-family: "inherit", serif; line-height: 107%;">6</span></i><i><sup><span style="font-family: "inherit", serif; line-height: 107%;">2</span></sup></i><i><span style="line-height: 107%;"> ≡ 1 (mod 7); o(6) = 2 </span></i><i><span style="line-height: 107%;">≠</span></i><i><span style="line-height: 107%;"> ϕ(7)</span></i><span style="line-height: 107%;">. 6 no es un generador o raíz primitiva de 7.<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: justify;"><span style="line-height: 107%;">Por lo que sólo 3 y 5 son generadores o raíces primitivas
módulo 7.<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: justify;"><span style="line-height: 107%;"><span>S</span><span>i se escoge un segundo número que no sea un
generador o raíz primitiva de <i>'p'</i> el protocolo también funciona</span> y, debido a que encontrar raíces primitivas de <span>un número primo <i>'p'</i> muy
grande puede ser muy costos en tiempo de cómputo y recursos, en la práctica se puede utilizar </span></span><span style="line-height: 107%;">un número pequeño (por ejemplo 2 o 5) que en realidad no lo sea, ya que </span><span style="line-height: 17.12px;">para un número </span>primo <i>'p'</i> muy grande <span style="line-height: 107%;">el sistema no será inseguro por esto</span>.</p></div><p style="text-align: left;"><span style="font-family: inherit;">2.- <b><span style="color: #45818e;">A escoge un número entero aleatorio <i>'a'</i> mayor que 0 y menor que <i>'p'</i></span></b>, que será secreto (sólo ella debe conocerlo), <b><span style="color: #45818e;">y envía a B el resultado de la operación </span></b></span><i><b><span style="color: #45818e;">g<sup>a</sup> mod p</span></b></i><span style="font-family: inherit;"><span style="line-height: 115%;"><span style="color: #222222;">.</span></span></span></p><p style="text-align: left;"><span style="font-family: inherit;"><span style="color: #222222; line-height: 115%;">3.- De forma análoga, </span></span><b><span style="color: #45818e;">B escoge un número entero aleatorio <i>'b'</i> mayor que 0 y menor que <i>'p'</i></span></b>, que será secreto (sólo él debe conocerlo), <b><span style="color: #45818e;">y envía a A el resultado de la operación </span></b><span style="line-height: 18.4px;"><i><b><span style="color: #45818e;">g<sup>b</sup> mod p</span></b></i><span style="color: #222222;">.</span></span></p><p style="text-align: left;"><span style="line-height: 18.4px;"><span style="color: #222222;"><span style="color: black;">4.- En este momento, </span><b style="color: black;"><span style="color: #45818e;">t</span></b><span style="color: black;"><b><span style="color: #45818e;">anto A como B están ya en disposición de calcular la clave de sesión (<i>'k'</i>) compartida sin intercambiarla por ningún sitio</span></b>. Es decir, <b><span style="color: #45818e;">A puede calcular el secreto compartido</span></b> (la clave de sesión) a partir del número que le ha mandado B en el paso anterior (<i><span style="color: #222222;">g<sup>b</sup></span><span style="color: #222222;"> mod </span><span style="color: #222222;">p</span></i>) y el número secreto que ella ha escogido en el paso 2 (<i>'a'</i>), es decir, sin más que realizar la siguiente operación: <b><span style="color: #45818e;"><i>k = (g<sup>b</sup> mod p)<sup>a</sup> mod p</i></span></b>; <b><span style="color: #45818e;">mientras que B puede calcularlo</span></b> </span><span style="color: black;">a partir del número que le ha mandado A en el paso 2 (</span><i style="color: black;"><span style="color: #222222;">g<sup>a</sup></span><span style="color: #222222;"> mod </span><span style="color: #222222;">p</span></i><span style="color: black;">) y el número secreto que él ha escogido en el paso 3 (</span><i style="color: black;">'b'</i><span style="color: black;">), es decir, sin más que realizar la siguiente operación: </span><b style="color: black;"><span style="color: #45818e;"><i>k = (g<sup>a</sup> mod p)<sup>b</sup> mod p</i></span></b><span style="color: black;">.</span></span></span></p><p style="text-align: left;"><span style="line-height: 18.4px;"><span style="color: #222222;"><span style="color: black;">Veamos <b><span style="color: #45818e;">un ejemplo</span></b> con un número primo <i>'p'</i> pequeño, pero para que este protocolo sea seguro es necesario utilizar un número mucho más grande, por ejemplo de 2.048 bits:</span></span></span></p><p style="text-align: left;"><span style="line-height: 18.4px;"><span style="color: #222222;"><span style="color: black;">1.- A y B acuerdan utilizar 997 como número primo </span><i style="color: black;">'p'</i><span style="color: black;"> y 3 como generador (</span><i style="color: black;">'g'</i><span style="color: black;">) de </span><i style="color: black;">'p'</i><span style="color: black;">.</span></span></span></p><p style="text-align: left;"><span style="line-height: 18.4px;"><span style="color: #222222;"><span style="color: black;">2.- A escoge 8 como número secreto y envía a B el resultado de </span><i style="color: black;">3<sup>8</sup> mod 997</i><span style="color: black; line-height: 18.4px;"> = 579.</span></span></span></p><p style="text-align: left;"><span style="line-height: 18.4px;"><span style="color: #222222;"><span style="color: black; line-height: 18.4px;">3.- B</span><span style="color: black;"> escoge 14 como número secreto y envía a A el resultado de </span><i style="color: black;">3<sup>14</sup> mod 997</i><span style="color: black; line-height: 18.4px;"> = 360.</span></span></span></p><p style="text-align: left;"><span style="line-height: 18.4px;"><span style="color: #222222;"><span style="color: black; line-height: 18.4px;">4.- <b><span style="color: #45818e;">El secreto compartido es</span></b>:</span></span></span></p><p style="text-align: left;"><span style="line-height: 18.4px;"><span style="color: #222222;"><span style="color: black; line-height: 18.4px;">4.1.- A calcula: </span><i style="color: black;">k = (</i><span style="color: black;">360</span><i style="color: black;">)<sup>8</sup> mod 997 <span style="font-family: inherit;">= </span></i><span style="color: black;"><i><b><span style="color: #45818e;">30</span></b></i>.</span></span></span></p><p style="text-align: left;"><span style="line-height: 18.4px;"><span style="color: #222222;"><span style="color: black;">4.2.- B</span><span style="color: black; line-height: 18.4px;"> calcula: </span><i style="color: black;">k = (</i><span style="color: black;">579</span><i style="color: black;">)<sup>14</sup> mod 997 = </i><i style="color: black;"><b><span style="color: #45818e;">30</span></b></i><span style="color: black;">.</span></span></span></p><p style="text-align: left;"><span style="line-height: 18.4px;"><span style="color: #222222;"><span style="color: black;">La fortaleza de este protocolo reside en que para obtener el secreto compartido entre A y B (la clave de sesión </span><i style="color: black;">'k'</i><span style="color: black;">) el atacante, conociendo los números públicos intercambiados entre A y B, se enfrenta al </span><a href="https://es.wikipedia.org/wiki/Logaritmo_discreto"><span style="color: #2b00fe;">problema del logaritmo discreto (PLD)</span></a><span style="color: black;">, es decir, las operaciones que realizan A y B son muy rápidas y consumen muy pocos recursos, pero aunque el atacante conozca los números públicos el cálculo de </span><i style="color: black;">'k'</i><span style="color: black;"> se vuelve inabordable cuando </span><i style="color: black;">'p'</i><span style="color: black;"> es un número primo muy grande por los elevadísimos tiempo de cómputo y potencia de cálculo que se requieren.</span></span></span></p><p style="text-align: left;"><span style="line-height: 18.4px;"><span style="color: #222222;"><span style="color: black;">Sin embargo, si este protocolo se realiza de forma no autenticada puede ser vulnerable a un <a href="https://es.wikipedia.org/wiki/Ataque_de_intermediario"><span style="color: #2b00fe;">ataque de intermediario</span></a><span style="background-color: white; color: #202122;"> (MitM, por las siglas en inglés de '</span><i lang="en" style="background-color: white; color: #202122;">Man in the Middle</i><span style="background-color: white; color: #202122;">')</span> ya que un atacante podría interponerse en las comunicaciones entre A y B, suplantando a uno frente al otro y haciendo que ninguno de los dos se dé cuenta de que están siendo hackeados.</span></span></span></p><p><span style="background-color: white; font-family: inherit;"><b><i>Quizás también te interese</i></b>:</span></p><p><span style="line-height: 18.4px;"><span style="color: #222222;"><span style="color: black;"></span></span></span></p><div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxxi-intercambio-de.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfcSoVnVdomvgNzqaaV3Zlkeqf_1X152m1quefTv59g6kpMvkOk5sL5PKkT0Xd7UhOV2b-8qoHx78dIZWMoeAVj-HiUs3eFFGafke0xAI-eap_bepM5c_SsD-0sGnPBhYeuEDov7YvQQSal5BHfgohYbdc-kudBfnuswm8o_f5xcYFMFNC4T3MblAF/s16000/Intercambio%20de%20clave%20de%20Diffie-Hellman%20en%20python.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxxii-ataque-de.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEha8OPcjRFwFl5l6V9PGqAcWOXCoP7GPRZSRW92sWXmUPU32i0MA9OgwquOmZqD7JvhMvAdXfUswKtLD02-uZ7lwOsWE_DHXo_gX0uQd3ne-fMkZcQzq29bBRWaianUFrFMVW-jrNn_pLNkk2wXdumcMtoW1g9D16ZF5Yj5fpO2FRybdzshulv8QmZd/s16000/Ataque%20de%20intermediario%20al%20Intercambio%20de%20clave%20de%20Diffie-Hellman.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxxiii-ataque-de.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRAubF_R0fu_rGGpL_VXcfhLHu57a7mYtIrYaNvRGrwHI-JJq4gHKjwZ_5CI68aAdNag0iWuUXrhKyMRVW7jawcslgODBoiiBKXYFmKqzPXiyNH_xvopjPbzvxqUy5Sp7PjjPUc_4TpFAd0LuC-o6WtCZQI8ycWCtPjTgwAnMPk8jAgy0l8GX4lj5y/s16000/Ataque%20de%20intermediario%20al%20Intercambio%20de%20clave%20de%20Diffie-Hellman%20en%20python.png" /></a></div></div>Mikel García Larraganhttp://www.blogger.com/profile/03118239524461394157noreply@blogger.com0tag:blogger.com,1999:blog-1846493661397027137.post-78124110410122155282023-07-26T17:56:00.013+02:002023-08-07T19:09:46.044+02:00Criptografía (CCLXXIX): Descifrado RSA y verificación firma digital en python<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTVeLjjiPWjQE6fWxo9-oB1BaV232HyER7559TMTI_sfjzGYra8KinLdWyQ3XAEiHBm_UizdY3XJ3xYb9q7KuPo4XesHY7iwYaLvCEJFcLL5Yw0Jn-1Ry9-iym8YGFQiBj4SrFuQJ9A_m7_kOgdgg57dvOdYdvi91Tkiy76gVYcppFUrQeB9vtQ5Zp/s238/RSA.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="114" data-original-width="238" height="114" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTVeLjjiPWjQE6fWxo9-oB1BaV232HyER7559TMTI_sfjzGYra8KinLdWyQ3XAEiHBm_UizdY3XJ3xYb9q7KuPo4XesHY7iwYaLvCEJFcLL5Yw0Jn-1Ry9-iym8YGFQiBj4SrFuQJ9A_m7_kOgdgg57dvOdYdvi91Tkiy76gVYcppFUrQeB9vtQ5Zp/s1600/RSA.png" width="238" /></a></div>En el <a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxviii-firma-digital-y.html"><span style="color: #2b00fe;">post anterior</span></a> puse un script <span>en python para implementar la firma digital y el cifrado con el algoritmo</span><span> <a href="https://es.wikipedia.org/wiki/RSA"><span style="color: #2b00fe;">RSA</span></a></span><span>, y en éste </span><b><span style="color: #45818e;">incluyo otro </span></b><span style="color: #45818e; font-weight: bold;">script en python para implementar el descifrado con el mismo algoritmo y la verificación de la firma digital</span><span>, e</span>s decir, para las operaciones <span style="background-color: white; color: #292929;">que se realizan en la comunicación en el lado del receptor.</span><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgL_3QoqhJSixvlKnGNRkIOymqGNE51zytCEcQ80v4wZfhiD0IjXmeJ4ihA0gT9VTpSKtBqXrWySmmZKTknx1N3khjCbq1i3p_ZSimqEd5m7S1nJuUMBHgRD_3uyjZ7TRjD-2g-tDWrwhxOvoUesdezSg08ArvD43HNqFi6VbCxV-Tz2f6AUaUhZD2C/s536/Criptograf%C3%ADa_Cifrado%20h%C3%ADbrido%20con%20firma%20digital.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="506" data-original-width="536" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgL_3QoqhJSixvlKnGNRkIOymqGNE51zytCEcQ80v4wZfhiD0IjXmeJ4ihA0gT9VTpSKtBqXrWySmmZKTknx1N3khjCbq1i3p_ZSimqEd5m7S1nJuUMBHgRD_3uyjZ7TRjD-2g-tDWrwhxOvoUesdezSg08ArvD43HNqFi6VbCxV-Tz2f6AUaUhZD2C/s16000/Criptograf%C3%ADa_Cifrado%20h%C3%ADbrido%20con%20firma%20digital.png" /></a></div><p><span style="font-family: inherit;"><span style="background-color: white; color: #292929;">Como se ve en la figura anterior, la clave de sesión (la clave con la que se ha cifrado el texto en claro), se descifra utilizando la clave privada del receptor </span></span><span style="background-color: white; color: #292929;">(</span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica" style="background-color: white;"><span style="color: #2b00fe;">criptografía asimétrica</span></a><span style="background-color: white; color: #292929;">)</span><span style="background-color: white; color: #292929; font-family: inherit;">, que es el único que la posee y, por tanto, el único que puede descifrarla, y </span><span style="background-color: white; color: #292929; font-family: inherit;">posteriormente se descifra el criptograma o texto en claro cifrado mediante la clave de sesión (</span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_sim%C3%A9trica" style="font-family: inherit;"><span style="color: #2b00fe;">criptografía simétrica</span></a><span style="background-color: white; color: #292929; font-family: inherit;">).</span></p><p><span style="background-color: white; font-family: inherit;"><span style="color: #292929;">Tal y como indique en el </span><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxviii-firma-digital-y.html"><span style="color: #2b00fe;">citado post</span></a><span style="color: #292929;">, este esquema de cifrado, además de para mantener el secreto de la comunicación (</span><b><span style="color: #45818e;">confidencialidad</span></b><span style="color: #292929;">), sirve </span></span><span><span style="background-color: white;">para garantizar al receptor que el emisor </span><span style="background-color: white;"><span style="color: #292929;">es realmente quien ha enviado el texto en claro (</span><b><span style="color: #45818e;">autenticidad</span></b><span style="color: #292929;">: el emisor es quien dice ser) y para comprobar que no ha sido interceptado y alterado por terceros (</span><b><span style="color: #45818e;">integridad</span></b><span style="color: #292929;">); con la característica adicional de </span><b><span style="color: #45818e;">no repudio, tanto en </span></b><span><b><span style="color: #45818e;">origen</span></b><span style="color: #292929;"> (el emisor no puede negar que creó y envió ese texto en claro) </span><b><span style="color: #45818e;">como en destino</span></b><span style="color: #292929;"> (</span></span></span></span><span style="background-color: white; color: #292929;">el receptor no puede negar que lo recibió y recibió exactamente ese texto en claro</span><span style="background-color: white; color: #292929;">).</span></p><p><span style="background-color: white;"><b><span style="color: #45818e;">Estos último aspectos son los que se consiguen mediante la firma digital</span></b>. El emisor firmó el contenido mediante un hash o función resumen del mismo y cifró ese resumen utilizando su clave privada </span><a href="https://es.wikipedia.org/wiki/RSA"><span style="color: #2b00fe;">RSA</span></a><span style="background-color: white;"> (nótese que, evidentemente, es el único que puede hacer esto, ya que es el único que posee su clave privada). Esta operación de cifrado dota a la comunicación de las características de autenticidad del mensaje (sólo el emisor ha podido cifrar la firma digital o resumen del mensaje con su clave privada) e integridad (si el hash descifrado es igual que el hash del texto en claro descifrado que se calcula en la recepción, entonces el mensaje no ha sido modificado desde que se envió y, por tanto, su contenido es exactamente lo que el emisor envió), y las dos características anteriores (autenticidad e integridad) dan como resultado el no repudio de la comunicación.</span></p><p><span style="background-color: white; font-family: inherit;"><span><b style="color: #45818e;">El script que pongo a continuación implementa las operaciones </b></span></span><span style="background-color: white;"><span><b style="color: #45818e;">de descifrado de la clave de sesión</b><b><span style="color: #45818e;"> </span></b></span></span><span style="background-color: white;"><span style="color: #45818e;"><b>y </b></span></span><span style="background-color: white; font-family: inherit;"><span><b><span style="color: #45818e;">de la firma digital </span></b><b><span style="color: #45818e;">mediante</span></b> </span></span><a href="https://es.wikipedia.org/wiki/RSA"><span style="color: #2b00fe;">RSA</span></a><span style="background-color: white; font-family: inherit;"><span style="color: #292929;">, y el descifrado del criptograma mediante el algoritmo </span></span><a href="https://es.wikipedia.org/wiki/Advanced_Encryption_Standard"><span style="color: #2b00fe;">AES</span></a><span style="background-color: white; color: #292929; font-family: inherit;"> de </span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_sim%C3%A9trica"><span style="color: #2b00fe;">criptografía simétrica</span></a><span style="background-color: white; font-family: inherit;"><span style="color: #292929;"> en </span><a href="https://es.wikipedia.org/wiki/Modos_de_operaci%C3%B3n_de_una_unidad_de_cifrado_por_bloques#Modo_CBC_(Cipher-block_chaining)"><span style="color: #2b00fe;">modo de operación CBC</span></a></span><span style="background-color: white; color: #292929;">.</span></p><p><span style="background-color: white; font-family: inherit;"><span style="color: #292929;">El par de claves </span></span><span style="color: #292929; font-family: inherit;"><a href="https://es.wikipedia.org/wiki/RSA"><span style="color: #2b00fe;">RSA</span></a>, publica y privada, para los dos usuarios participantes en la comunicación, emisor y receptor, son las mismas que las que generé </span><span style="color: #292929;">mediante el </span><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxvii-generacion-de.html"><span style="color: #2b00fe;">script que puse en esta entrada</span></a><span style="font-family: inherit;"><span style="color: #292929;"> y utilicé en el </span><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxviii-firma-digital-y.html"><span style="color: #2b00fe;">post citado al principio</span></a><span style="color: #292929;">: </span></span><a href="https://drive.google.com/file/d/1BClZ3vXaNAb3CreewPXFrqP4PVNZpNqF/view?usp=sharing" style="font-family: inherit;"><span style="color: #2b00fe;">clave pública emisor</span></a><span style="color: #292929; font-family: inherit;">, </span><a href="https://drive.google.com/file/d/1w0a2lVE_AJVoPunBGEfPIMPUaCAu45vF/view?usp=sharing" style="font-family: inherit;"><span style="color: #2b00fe;">clave privada emisor</span></a><span style="color: #292929; font-family: inherit;">, </span><a href="https://drive.google.com/file/d/10JX_oOV3iTlhverf_nMsdOXSYNfgR_xa/view?usp=sharing" style="font-family: inherit;"><span style="color: #2b00fe;">clave pública receptor</span></a><span style="font-family: inherit;"><span style="color: #292929;">, </span><a href="https://drive.google.com/file/d/1A18AS6l2GZCsTTuIXkesH0v31H9LGP48/view?usp=sharing"><span style="color: #2b00fe;">clave privada receptor</span></a><span style="color: #292929;">.</span></span></p><p><span style="font-family: inherit;"><span><span><span style="color: #292929;">Para simular la recepción del mensaje cifrado utilizo un archivo que se ha creado tras la ejecución del script que puse en el </span><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxviii-firma-digital-y.html"><span style="color: #2b00fe;">post anterior</span></a><span style="color: #292929;">, </span></span><a href="https://drive.google.com/file/d/1Zl-Ohu9lrCxS6X-aK7DN33LR5XHzXChG/view?usp=sharing"><span style="color: #2b00fe;">comunicacion.txt</span></a><span style="color: #292929;">, y que contiene, codificada en base64, la siguiente información: la clave de sesión cifrada, el criptograma o texto en claro cifrado y la firma digital cifrada.</span></span></span></p><p>Asimismo, para que el script funcione se necesita importar el siguiente módulo en el programa principal, <span style="font-family: inherit;">que se encargará de la exponenciación modular rápida a realizar en las operaciones de descifrado </span><a href="https://es.wikipedia.org/wiki/RSA"><span style="color: #2b00fe;">RSA</span></a><span style="font-family: inherit;">, tanto de la clave de sesión como de la firma digital, para hacer éstas más eficientemente.</span></p><p></p><pre><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ALGORITMO DE EXPONENCIACIÓN MODULAR RÁPIDA:
#
# Algoritmo utilizado en operaciones de exponenciación modular
# con números muy grandes con objeto de hacerlas de forma
# más eficiente.
#
# http://mikelgarcialarragan.blogspot.com/
def exp_modular_rapida(b, e, m):
c = 1
e = bin(e)[2:]
for i in range(0, len(e)):
c = pow(c, 2, m)
if e[i]=="1":
c = c*b%m
return c</code>
<br /></pre><p><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><p><span style="background-color: white; color: #292929; font-family: inherit;"></span></p><p>El <b><span style="color: #45818e;">script</span></b> es el siguiente:</p><p><span style="font-family: inherit;"><span style="background-color: white; color: #292929;">- </span><i style="background-color: white; color: #292929;"><u>Script python para el descifrado y verificación de la firma digital</u></i><span style="background-color: white; color: #292929;">:</span></span></p><p></p><pre><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# CIFRADO RSA:
#
# Descifrar y verificar firma digital utilizando el criptosistema RSA.
#
# http://mikelgarcialarragan.blogspot.com/
import hashlib
from Crypto.Cipher import AES
from Crypto.PublicKey import RSA
from base64 import b64decode
from exponenciacion_modular_rapida import exp_modular_rapida
# CIFRADO AES (CRIPTOGRAFÍA SIMÉTRICA).
def descifrar_aes(criptograma,clave):
iv = criptograma[:AES.block_size]
descifrar = AES.new(clave, AES.MODE_CBC, iv)
texto_claro = descifrar.decrypt(criptograma[AES.block_size:]).decode()
return texto_claro[:-ord(texto_claro[len(texto_claro) - 1:])]
# OBTENER DATOS DE LA CLAVE RSA.
def clave_rsa(fichero_pem):
f_clave_rsa = open(fichero_pem, "r")
datos_clave_rsa = RSA.importKey(f_clave_rsa.read())
f_clave_rsa.close()
return datos_clave_rsa
def main():
# MENÚ:
# Se presenta el menú para que se seleccione una opción.
salir = False
while not salir:
print ("")
print ("*** MENÚ *****************************************")
print ("1. Descifrar y verificar firma digital.")
print ("2. Salir.")
print ("")
opcion = input("Por favor, seleccione una opción: ")
if opcion == "1":
print ("")
print ("--- DESCIFRAR Y VERIFICAR FIRMA DIGITAL:")
# Descifrar y verificar firma digital: se reciben la clave de sesión cifrada,
# el criptograma y la firma digital cifrada.
f_comunicacion = open("comunicacion.txt")
datos_comunicacion = f_comunicacion.readlines()
print ("[+] Clave de sesión AES cifrada (base64):", datos_comunicacion[0].rstrip())
print ("[+] Criptograma (base64):", datos_comunicacion[1].rstrip())
print ("[+] Firma digital cifrada (base64):", datos_comunicacion[2])
# Se lee la clave privada del receptor: el módulo (n), el exponente de
# la clave privada (d) y el resto de datos, para descifrar la clave de sesión.
datos_clave_privada = clave_rsa("private_receptor.pem")
print ("[+] Clave privada del receptor:")
print (" Módulo (n):", datos_clave_privada.n)
print (" Exponente clave privada (d):", datos_clave_privada.d)
print (" Primer número primo factor de n (p):", datos_clave_privada.p)
print (" Segundo número primo factor de n (q):", datos_clave_privada.q)
print (" Coeficiente CRT (inv(p) mod q):", datos_clave_privada.u)
# Se descifra la clave de sesión AES con la que se cifró el texto en claro
# con la clave privada del receptor (criptografía asimétrica), utilizando el
# teoema chino del resto (CRT, por sus siglas en inglés).
# 1.- dp = d mod (p – 1); dq = d mod (q – 1)
# 2.- cp = c mod p; cq = c mod q
# 3.- k1 = cp**dp mod p; k2 = cq**dq mod q
# 4.- k = k1 + (((k2 - k1)*inv(p) mod q)) mod q) * p
dp = datos_clave_privada.d%(datos_clave_privada.p-1)
dq = datos_clave_privada.d%(datos_clave_privada.q-1)
cp = int(b64decode(datos_comunicacion[0]))%datos_clave_privada.p
cq = int(b64decode(datos_comunicacion[0]))%datos_clave_privada.q
k1 = exp_modular_rapida(cp, dp, datos_clave_privada.p)
k2 = exp_modular_rapida(cq, dq, datos_clave_privada.q)
clave_sesion = k1 + (((k2 - k1)*datos_clave_privada.u)%datos_clave_privada.q) * datos_clave_privada.p
print ("[+] Clave de sesión AES descifrada (hexadecimal):", hex(clave_sesion)[2:])
# Se descifra el criptograma con la clave de sesión AES (criptografía simétrica).
texto_claro = descifrar_aes(b64decode(datos_comunicacion[1]),bytes.fromhex(hex(clave_sesion)[2:]))
print ("[+] Texto claro descifrado con la clave de sesión AES:", texto_claro)
# Se calcula el hash SHA-256 (256 bits) del texto en claro descifrado,
# es decir, su firma digital, para compararla después con la firma digital
# recibida que se descifra a continuación.
h = (hashlib.sha256(texto_claro.encode()).digest())
print ("[+] Firma digital calculada para el texto en claro descifrado (hexadecimal):", h.hex())
# Se lee la clave pública del emisor, el módulo (n) y el exponente de
# la clave pública (e), para descifrar la firma digital.
datos_clave_publica = clave_rsa("public_emisor.pem")
print ("[+] Clave pública del emisor:")
print (" Módulo (n):", datos_clave_publica.n)
print (" Exponente clave pública (e):", datos_clave_publica.e)
# Se descifra la firma digital correspondiente al texto en claro que se ha
# recibido con la clave pública del emisor (criptografía asimétrica).
firma_digital = exp_modular_rapida(int(b64decode(datos_comunicacion[2])), datos_clave_publica.e, datos_clave_publica.n)
print ("[+] Firma digital correspondiente al texto en claro que se ha recibido (hexadecimal):", hex(firma_digital)[2:])
if hex(firma_digital)[2:] == h.hex():
print ("[+] Se ha verificado la firma digital del contenido de la comunicación con el resultado de FIRMA DIGITAL VÁLIDA.")
else:
print ("[+] Se ha verificado la firma digital del contenido de la comunicación con el resultado de FIRMA DIGITAL NO VÁLIDA.")
elif opcion == "2":
print ("*** FIN ******************************************")
salir = True
else:
print ("*** ERROR: Opción no válida.")
if __name__ == '__main__':
main()</code>
<br /></pre><p><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><p><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><p><b><span style="color: #45818e;">Lo ejecuto</span></b>:</p><p><span style="font-family: inherit;"><span><span style="background-color: white;"><span><span style="color: #292929;">Tras leerse del fichero que simula la comunicación, </span></span></span></span><a href="https://drive.google.com/file/d/1Zl-Ohu9lrCxS6X-aK7DN33LR5XHzXChG/view?usp=sharing"><span style="color: #2b00fe;">comunicacion.txt</span></a><span style="color: #292929;">: la clave de sesión cifrada, el criptograma o texto en claro cifrado y la firma digital cifrada</span><span><span style="background-color: white;"><span><span style="color: #292929;">, </span><b><span style="color: #45818e;">lo primero que hace el script es descifrar la clave de sesión </span></b><a href="https://es.wikipedia.org/wiki/Advanced_Encryption_Standard"><span style="color: #2b00fe;">AES</span></a><span><span style="color: #292929;"> </span><b><span style="color: #45818e;">con la</span></b><span style="color: #292929;"> </span></span></span></span></span></span><a href="https://drive.google.com/file/d/1A18AS6l2GZCsTTuIXkesH0v31H9LGP48/view?usp=sharing"><span style="color: #2b00fe;">clave privada del receptor</span></a><span style="font-family: inherit;"><span><span style="background-color: white;"><span><span style="color: #292929;"> </span></span></span></span><span style="background-color: white; color: #292929;">(</span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica" style="background-color: white;"><span style="color: #2b00fe;">criptografía asimétrica</span></a><span style="background-color: white;"><span style="color: #292929;">) </span><b><span style="color: #45818e;">y descifrar el texto en claro cifrado con ella por el emisor</span></b><span style="color: #292929;"> (</span></span></span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_sim%C3%A9trica"><span style="color: #2b00fe;">criptografía simétrica</span></a><span style="background-color: white; font-family: inherit;"><span style="color: #292929;">). Para optimizar el consumo de tiempo y recursos en este descifrado el script utiliza el </span><a href="https://es.wikipedia.org/wiki/Teorema_chino_del_resto"><span style="color: #2b00fe;">Teorema Chino del Resto</span></a><span style="color: #292929;"> (TCR o CRT por sus siglas en inglés, <i>'</i></span></span><span style="color: #292929; font-family: inherit;"><i>Chinese Remainder Theorem</i></span><span style="background-color: white; color: #292929; font-family: inherit;"><i>'</i>).</span></p><p><span><span style="background-color: white;"><span></span></span></span></p><div class="separator" style="clear: both; text-align: center;"><span><span style="background-color: white;"><span><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGV4Ni39rzN46AAO0wKSCJndrrCo9YN1FU9-fdoPFEpx_KshsArugI-hsg7H5OxkpEp-WXcEYEEAnKlIsBgLyydkNkAZ8ez3u_3phQX6L0irG93LsXtUrMj8dgEmBWNCm1n6nKxzAaDPeAWS5hK3zv2g5DQuBRtUm9cm5o4Kn1SnqzlvBSZ5JOuYw4/s622/Descifrar%20y%20verificar%20firma%20digital_1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="370" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGV4Ni39rzN46AAO0wKSCJndrrCo9YN1FU9-fdoPFEpx_KshsArugI-hsg7H5OxkpEp-WXcEYEEAnKlIsBgLyydkNkAZ8ez3u_3phQX6L0irG93LsXtUrMj8dgEmBWNCm1n6nKxzAaDPeAWS5hK3zv2g5DQuBRtUm9cm5o4Kn1SnqzlvBSZ5JOuYw4/s16000/Descifrar%20y%20verificar%20firma%20digital_1.png" /></a></span></span></span></div><p></p><p></p><p><b><span style="color: #45818e;">Lo siguiente</span></b> que hace el script <b><span style="color: #45818e;">es calcular el hash</span></b> <a href="https://es.wikipedia.org/wiki/SHA-2"><span style="color: #2b00fe;">SHA-256</span></a> <span style="color: #45818e;"><b>del texto en claro descifrado</b></span>, para compararlo con la firma digital que se descifra justo después.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4rmR84ioibgLAPS5Bb1dTB4l0WuBo73W9icilIPxH0Ur2q7W4IgZ_oeZE8bC-GbxiweqsMorO1yNNbqp8MekLMNy5TPEga-8bPkJwjKoPG_kLpNm33ZYcqXv-Qna5VMsir9Oltjd0MTi_rqDUiLgFhBaSnnLOlvYm4FDYdYFFkLLaIWuus4vvf1XA/s622/Descifrar%20y%20verificar%20firma%20digital_2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="154" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4rmR84ioibgLAPS5Bb1dTB4l0WuBo73W9icilIPxH0Ur2q7W4IgZ_oeZE8bC-GbxiweqsMorO1yNNbqp8MekLMNy5TPEga-8bPkJwjKoPG_kLpNm33ZYcqXv-Qna5VMsir9Oltjd0MTi_rqDUiLgFhBaSnnLOlvYm4FDYdYFFkLLaIWuus4vvf1XA/s16000/Descifrar%20y%20verificar%20firma%20digital_2.png" /></a></div><p>Y, <b><span style="color: #45818e;">finalmente,</span></b> el script <b><span style="color: #45818e;">lee la</span></b> <a href="https://drive.google.com/file/d/1BClZ3vXaNAb3CreewPXFrqP4PVNZpNqF/view?usp=sharing" style="font-family: inherit;"><span style="color: #2b00fe;">clave pública del emisor</span></a> (módulo y exponente de la clave pública) <b><span style="color: #45818e;">para descifrar mediante el algoritmo</span></b> <a href="https://es.wikipedia.org/wiki/RSA"><span style="color: #2b00fe;">RSA</span></a> <span style="background-color: white;">(</span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica" style="background-color: white;"><span style="color: #2b00fe;">criptografía asimétrica</span></a><span style="background-color: white;">)</span> <b><span style="color: #45818e;">la firma digital cifrada que se ha recibido</span></b>, <b><span style="color: #45818e;">y compara ésta con la obtenida en el punto anterior</span></b>.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKsLCe96hEL6m8yQh9X4WRBkqSFGbj4A_7UarearQOrI_eOBBf5Sq2eycrhcR867SSl69qWVlvWDWn44npLVkvhNjd1uFbqpOCk-GWraZoMdcSlt3-sKl4WX-bRHPpXpJ8BA8nPoGNweQkKiJFdqqPz7CnfR5P67mPGjYAaDofbIVJMb-wnWdovTC_/s622/Descifrar%20y%20verificar%20firma%20digital_3.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="250" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKsLCe96hEL6m8yQh9X4WRBkqSFGbj4A_7UarearQOrI_eOBBf5Sq2eycrhcR867SSl69qWVlvWDWn44npLVkvhNjd1uFbqpOCk-GWraZoMdcSlt3-sKl4WX-bRHPpXpJ8BA8nPoGNweQkKiJFdqqPz7CnfR5P67mPGjYAaDofbIVJMb-wnWdovTC_/s16000/Descifrar%20y%20verificar%20firma%20digital_3.png" /></a></div><p>Tal y como se puede observar en la figura anterior, en este caso el proceso de verificación de la firma digital termina con éxito y, por tanto, quedarían acreditadas tanto la autenticidad como la integridad del mensaje recibido.</p><p><span style="background-color: white; font-family: inherit;"><b><i>Quizás también te interese</i></b>:</span></p><div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2016/10/criptografia-xxxv-el-algoritmo-rsa-i.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmuLy3WfFzpqlRc3oQmUt4XlQmD1JeJqRphUGdhRvInqrtUUmo8yu2rZglxHQD67fXOiQi7_tpz7Wk0vL1w8J6ncgZ3J3m9LGfvaKJ8pknSUSXyeKgu-lTc8QzLzI8pk2wgjShME3zztHuJu1okd9GwLBfvoS1MGAr607DDCzy_YQe2IhYlF5WIARP/s16000/El%20algoritmo%20RSA%20(I).png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2016/10/criptografia-xxxvi-el-algoritmo-rsa-ii.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirNSpIv8NCi7fdLEAqb_jymUk6SWabYFk82YzeHl4hqLSp-L7WHZaCC_Jy1mpN6VRrOELIwFL9lFnlbPP-OKFiR7B_XrdBiu7991oaCtzqtkvROW7fCYCAERxlu2v66iUlzbVbWulg12rHw_Ri9h2CuWsjPycWvr6qQVFMu3MFz2R0tCfOR3oaHONN/s16000/El%20algoritmo%20RSA%20(II).png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxviii-firma-digital-y.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0MG4LDX7RX-KsdKbM52LvKnpkpDmkIoOXVHnDHFiWWdz_OztXZIXn-e5lIfrk0pG0_G2aHERSPPI32uGCTpnxPb2mQCUhOYIy7v4fgWGVhmoq8t9Qekuk3AFz0FaMFX0Jh7lzIlLrfUsB9sO2G4xGIH5VPbm-gorS3J1HoQRc-2YquTiC3m-DoVsn/s16000/Firma%20digital%20y%20cifrado%20RSA%20en%20python.png" /></a></div></div></div>Mikel García Larraganhttp://www.blogger.com/profile/03118239524461394157noreply@blogger.com0tag:blogger.com,1999:blog-1846493661397027137.post-48138129950938274682023-07-24T09:45:00.020+02:002023-08-05T12:10:52.803+02:00Criptografía (CCLXXVIII): Firma digital y cifrado RSA en python<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNa_B2EV7WV2kyTENifTw9HsbqzeikHJ5yptohM16__u_HjQYxWyp0l81KdFSb0jFSpEAJKamFSHbQhftK5oH0c2p4ohISpvj-uPkX-PLZ_ilm57iXH0w8oFRXHkVxaR9luFFVXi18_px2rRRRG7GFZY1NcfhCUz9yMFVe66OWYOgL6cGtcvxYVOt0/s238/RSA.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="114" data-original-width="238" height="114" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNa_B2EV7WV2kyTENifTw9HsbqzeikHJ5yptohM16__u_HjQYxWyp0l81KdFSb0jFSpEAJKamFSHbQhftK5oH0c2p4ohISpvj-uPkX-PLZ_ilm57iXH0w8oFRXHkVxaR9luFFVXi18_px2rRRRG7GFZY1NcfhCUz9yMFVe66OWYOgL6cGtcvxYVOt0/s1600/RSA.png" width="238" /></a></div>Continúo poniendo scripts de programación en python para automatizar tareas que tengan relación con la <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa"><span style="color: #2b00fe;">criptografía</span></a>.<p></p><p></p><p></p><p></p><p></p><p></p><p></p><p><b><span style="color: #45818e;">En este post incluyo un </span></b><span style="color: #45818e; font-weight: bold;">script en python para implementar la firma digital y el cifrado con el algoritmo</span><span> <a href="https://es.wikipedia.org/wiki/RSA"><span style="color: #2b00fe;">RSA</span></a></span><span style="font-family: inherit;">.</span></p><p><span style="font-family: inherit;"><span>Antes de poner el script, recordar que en <a href="http://mikelgarcialarragan.blogspot.com/2016/10/criptografia-xxxv-el-algoritmo-rsa-i.html"><span style="color: #2b00fe;">este post</span></a> decía que <b><span style="color: #45818e;">el algoritmo</span></b> </span><a href="https://es.wikipedia.org/wiki/RSA"><span style="color: #2b00fe;">RSA</span></a><span> <b><span style="color: #45818e;">s</span><span style="color: #45818e;">irve tanto para cifrar y descifrar (confidencialidad) como para firmar digitalmente un texto en claro (autenticidad e integridad)</span></b>, y que en la práctica se usa en el cifrado híbrido para cifrar una clave de sesión (un número) que, a su vez, se utiliza como clave para cifrar el mensaje o archivo completo mediante un algoritmo de <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_sim%C3%A9trica"><span style="color: #2b00fe;">cifrado simétrico</span></a>.</span><span style="background-color: white;"> Esto es debido a que </span></span><a href="https://es.wikipedia.org/wiki/RSA"><span style="color: #2b00fe;">RSA</span></a><span style="background-color: white;"><span style="font-family: inherit;"> (<a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica"><span style="color: #2b00fe;">criptografía asimétrica</span></a>) es menos eficiente, </span></span><span style="background-color: white;">es decir, es más lento y consume más recursos,</span><span style="background-color: white;"><span style="font-family: inherit;"> que un </span></span><span style="font-family: inherit;"><span style="background-color: white;"><span style="color: #202122;">algoritmo de los usados en </span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_sim%C3%A9trica"><span style="color: #2b00fe;">criptografía simétrica</span></a></span><span style="background-color: white;">.</span></span></p><p><span style="background-color: white;">Para hacer ambas cosas más eficientes, <b><span style="color: #45818e;">l</span></b></span><span style="font-family: inherit;"><span style="background-color: white;"><b><span style="color: #45818e;">os esquemas modernos de cifrado utilizan conjuntamente los conceptos de</span></b> <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica"><span style="color: #2b00fe;">clave pública</span></a> <b><span style="color: #45818e;">y</span></b> <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_sim%C3%A9trica"><span style="color: #2b00fe;">clave privada</span></a></span></span>, es decir, el mensaje o archivo completo se cifra con un algoritmo de <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_sim%C3%A9trica"><span style="color: #2b00fe;">clave privada o simétrica</span></a> (por ejemplo, <a href="https://es.wikipedia.org/wiki/Advanced_Encryption_Standard"><span style="color: #2b00fe;">AES</span></a>) y luego la clave empleada en ese cifrado (clave de sesión), a su vez, se cifra con un algoritmo de <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica"><span style="color: #2b00fe;">clave pública o asimétrica</span></a> (por ejemplo, <a href="https://es.wikipedia.org/wiki/RSA"><span style="color: #2b00fe;">RSA</span></a>):</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgL_3QoqhJSixvlKnGNRkIOymqGNE51zytCEcQ80v4wZfhiD0IjXmeJ4ihA0gT9VTpSKtBqXrWySmmZKTknx1N3khjCbq1i3p_ZSimqEd5m7S1nJuUMBHgRD_3uyjZ7TRjD-2g-tDWrwhxOvoUesdezSg08ArvD43HNqFi6VbCxV-Tz2f6AUaUhZD2C/s536/Criptograf%C3%ADa_Cifrado%20h%C3%ADbrido%20con%20firma%20digital.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="506" data-original-width="536" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgL_3QoqhJSixvlKnGNRkIOymqGNE51zytCEcQ80v4wZfhiD0IjXmeJ4ihA0gT9VTpSKtBqXrWySmmZKTknx1N3khjCbq1i3p_ZSimqEd5m7S1nJuUMBHgRD_3uyjZ7TRjD-2g-tDWrwhxOvoUesdezSg08ArvD43HNqFi6VbCxV-Tz2f6AUaUhZD2C/s16000/Criptograf%C3%ADa_Cifrado%20h%C3%ADbrido%20con%20firma%20digital.png" /></a></div><p style="text-align: left;"><span style="font-family: inherit;"><span style="background-color: white; color: #292929;">Por tanto, como se ve en la figura anterior, el texto en claro se cifra mediante una clave de sesión, un número correspondiente a cada mensaje particular, y la clave de sesión se cifra utilizando la clave pública del receptor, de tal manera que sólo el receptor puede descifrar la clave de sesión mediante su clave privada (</span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica" style="background-color: white;"><span style="color: #2b00fe;">criptografía asimétrica</span></a><span style="background-color: white; color: #292929;">) y posteriormente descifrar el criptograma o texto en claro cifrado mediante la clave de sesión (</span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_sim%C3%A9trica"><span style="color: #2b00fe;">criptografía simétrica</span></a><span style="background-color: white; color: #292929;">).</span></span></p><p style="text-align: left;"><span style="background-color: white;"><span style="font-family: inherit;">De esta forma, <b><span style="color: #45818e;">sólo se podrá obten<span style="font-family: inherit;">er la clave de sesión</span></span></b><span style="font-family: inherit;"> (</span></span></span><span style="font-family: inherit;"><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_sim%C3%A9trica"><span style="color: #2b00fe;">clave simétrica</span></a><span style="background-color: white;">) <b><span style="color: #45818e;">si se está en posesión de la</span></b> <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica"><span style="color: #2b00fe;">clave privada RSA</span></a><b><span style="color: #45818e;">, y</span></b>, por consiguiente, <b><span style="color: #45818e;">si no se tiene esta última no se puede descifrar </span></b></span></span><b><span style="color: #45818e;">el criptograma o texto en claro cifrado</span></b><span style="background-color: white; font-family: inherit;">.</span></p><p style="text-align: left;"><span style="font-family: inherit;"><span style="background-color: white;"><b><span style="color: #45818e;">Este esquema de cifrado se puede utilizar para mantener la confidencialidad de los mensajes y los archivos</span></b>, sin tardar demasiado ni consumir demasiados recursos informáticos, pero, como digo, <b><span style="color: #45818e;">también se puede utilizar para firmar digitalmente los mensajes y los archivos</span></b>, es decir, para garantizar al receptor que el emisor </span><span style="background-color: white;"><span style="color: #292929;">es realmente quien los ha enviado (</span><b><span style="color: #45818e;">autenticidad</span></b><span style="color: #292929;">: el emisor es quien dice ser) y para comprobar que no han sido interceptados y alterados por terceros (</span><b><span style="color: #45818e;">integridad</span></b><span style="color: #292929;">); con la característica adicional de </span><b><span style="color: #45818e;">no repudio</span></b><span><b><span style="color: #45818e;">, </span></b><b><span style="color: #45818e;">tanto </span></b><b><span style="color: #45818e;">en origen</span></b><span style="color: #292929;"> (el emisor no puede negar que creó y envió esos textos en claro) </span><b><span style="color: #45818e;">como en destino</span></b><span style="color: #292929;"> (</span></span></span></span><span style="background-color: white; color: #292929;">el receptor no puede negar que los recibió y recibió exactamente esos textos en claro</span><span style="background-color: white; color: #292929; font-family: inherit;">).</span></p><p style="text-align: left;"><span style="background-color: white; font-family: inherit;"><span><b style="color: #45818e;">El script que pongo a continuación implementa las operaciones de firma digital del texto en claro y de cifrado de la clave de sesión</b> mediante </span></span><a href="https://es.wikipedia.org/wiki/RSA"><span style="color: #2b00fe;">RSA</span></a><span style="background-color: white; font-family: inherit;"><span style="color: #292929;">, y el cifrado del texto en claro mediante el algoritmo </span></span><a href="https://es.wikipedia.org/wiki/Advanced_Encryption_Standard"><span style="color: #2b00fe;">AES</span></a><span style="background-color: white; color: #292929; font-family: inherit;"> de </span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_sim%C3%A9trica"><span style="color: #2b00fe;">criptografía simétrica</span></a><span style="background-color: white; font-family: inherit;"><span style="color: #292929;"> en </span><a href="https://es.wikipedia.org/wiki/Modos_de_operaci%C3%B3n_de_una_unidad_de_cifrado_por_bloques#Modo_CBC_(Cipher-block_chaining)"><span style="color: #2b00fe;">modo de operación CBC</span></a></span><span style="background-color: white; color: #292929;">, es decir, las operaciones que se realizan en la comunicación desde el lado del emisor.</span></p><p style="text-align: left;"><span style="background-color: white; font-family: inherit;"><span style="color: #292929;">Previamente he generado, mediante el </span><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxvii-generacion-de.html"><span style="color: #2b00fe;">script que puse en esta entrada</span></a><span style="color: #292929;">, el par de claves </span></span><span style="color: #292929; font-family: inherit;"><a href="https://es.wikipedia.org/wiki/RSA"><span style="color: #2b00fe;">RSA</span></a>, publica y privada, para los dos usuarios participantes en la comunicación, emisor y receptor: </span><a href="https://drive.google.com/file/d/1BClZ3vXaNAb3CreewPXFrqP4PVNZpNqF/view?usp=sharing" style="font-family: inherit;"><span style="color: #2b00fe;">clave pública emisor</span></a><span style="color: #292929; font-family: inherit;">, </span><a href="https://drive.google.com/file/d/1w0a2lVE_AJVoPunBGEfPIMPUaCAu45vF/view?usp=sharing" style="font-family: inherit;"><span style="color: #2b00fe;">clave privada emisor</span></a><span style="color: #292929; font-family: inherit;">, </span><a href="https://drive.google.com/file/d/10JX_oOV3iTlhverf_nMsdOXSYNfgR_xa/view?usp=sharing" style="font-family: inherit;"><span style="color: #2b00fe;">clave pública receptor</span></a><span style="font-family: inherit;"><span style="color: #292929;">, </span><a href="https://drive.google.com/file/d/1A18AS6l2GZCsTTuIXkesH0v31H9LGP48/view?usp=sharing"><span style="color: #2b00fe;">clave privada receptor</span></a><span style="color: #292929;">.</span></span></p><p>Asimismo, para que el script funcione se necesita importar el siguiente módulo en el programa principal, <span style="font-family: inherit;">que se encargará de la exponenciación modular rápida a realizar en las operaciones de cifrado </span><a href="https://es.wikipedia.org/wiki/RSA"><span style="color: #2b00fe;">RSA</span></a><span style="font-family: inherit;">, tanto de la firma digital como de la clave de sesión, para hacer éstas más eficientemente.</span></p><p></p><pre><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ALGORITMO DE EXPONENCIACIÓN MODULAR RÁPIDA:
#
# Algoritmo utilizado en operaciones de exponenciación modular
# con números muy grandes con objeto de hacerlas de forma
# más eficiente.
#
# http://mikelgarcialarragan.blogspot.com/
def exp_modular_rapida(b, e, m):
c = 1
e = bin(e)[2:]
for i in range(0, len(e)):
c = pow(c, 2, m)
if e[i]=="1":
c = c*b%m
return c</code>
<br /></pre><p><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><p><span style="background-color: white; color: #292929; font-family: inherit;"></span></p><p>El <b><span style="color: #45818e;">script</span></b> es el siguiente:</p><p><span style="font-family: inherit;"><span style="background-color: white; color: #292929;">- </span><i style="background-color: white; color: #292929;"><u>Script python para la firma digital y cifrado RSA</u></i><span style="background-color: white; color: #292929;">:</span></span></p><p></p><pre><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# CIFRADO RSA:
#
# Firma digitalmente y cifra utilizando el criptosistema RSA.
#
# http://mikelgarcialarragan.blogspot.com/
import hashlib
from Crypto import Random
from Crypto.Util.Padding import pad
from Crypto.Cipher import AES
from Crypto.PublicKey import RSA
from base64 import b64encode
from exponenciacion_modular_rapida import exp_modular_rapida
# CIFRADO AES (CRIPTOGRAFÍA SIMÉTRICA).
def cifrar_aes(texto_claro,clave):
iv = Random.new().read(AES.block_size)
print("[+] IV (hexadecimal):", iv.hex())
cifrar = AES.new(clave, AES.MODE_CBC, iv)
criptograma = iv + cifrar.encrypt(pad(texto_claro.encode(), AES.block_size))
return criptograma
# OBTENER DATOS DE LA CLAVE RSA.
def clave_rsa(fichero_pem):
f_clave_rsa = open(fichero_pem, "r")
datos_clave_rsa = RSA.importKey(f_clave_rsa.read())
f_clave_rsa.close()
return datos_clave_rsa
def main():
# MENÚ:
# Se presenta el menú para que se seleccione una opción.
salir = False
while not salir:
print ("")
print ("*** MENÚ *****************************************")
print ("1. Firmar digitalmente y cifrar clave de sesión AES.")
print ("2. Salir.")
print ("")
opcion = input("Por favor, seleccione una opción: ")
if opcion == "1":
print ("")
print ("--- FIRMAR DIGITALMENTE Y CIFRAR CLAVE DE SESIÓN:")
# Firmar digitalmente y cifrar: Se introducen el texto en claro y la clave.
texto_claro = clave = ""
while texto_claro == "":
texto_claro = input('Texto en claro a cifrar: ')
if texto_claro != "":
while clave == "":
clave = input('Clave: ')
if clave != "":
# Se genera la clave de sesión AES con la que se va a cifrar el
# texto en claro y que, a su vez, va a ser cifrada con la clave
# pública del destinatario, que será descifrada por éste con su
# clave privada (criptografía asimétrica) para, a su vez, descifrar
# el criptograma (criptografía simétrica).
# La clave se genera a partir de la clave introducida por el usuario,
# que puede tener cualquier longitud, y de la cual se calcula su
# hash SHA-256 (256 bits).
# Ese hash será la clave de sesión (32 bytes).
clave_sesion = (hashlib.sha256(clave.encode()).digest())
print ("[+] Clave de sesión AES generada (hexadecimal):", clave_sesion.hex())
criptograma = cifrar_aes(texto_claro,clave_sesion)
print ("[+] Texto claro cifrado con la clave de sesión AES (hexadecimal):", criptograma.hex())
# Se lee la clave privada del emisor, el módulo (n) y el exponente de
# la clave privada (d), para firmar digitalmente el texto en claro.
datos_clave_privada = clave_rsa("private_emisor.pem")
print ("[+] Clave privada del emisor:")
print (" Módulo (n):", datos_clave_privada.n)
print (" Exponente clave privada (d):", datos_clave_privada.d)
h = (hashlib.sha256(texto_claro.encode()).digest())
print ("[+] Firma digital del texto en claro (hexadecimal):", h.hex())
s = exp_modular_rapida(int(h.hex(),16), datos_clave_privada.d, datos_clave_privada.n)
print ("[+] Firma digital cifrada con la clave privada RSA del emisor (hexadecimal):", hex(s)[2:])
# Se lee la clave pública del receptor, el módulo (n) y el exponente de
# la clave pública (e), para cifrar la clave de sesión AES.
datos_clave_publica = clave_rsa("public_receptor.pem")
print ("[+] Clave pública del receptor:")
print (" Módulo (n):", datos_clave_publica.n)
print (" Exponente clave pública (e):", datos_clave_publica.e)
c = exp_modular_rapida(int(clave_sesion.hex(),16), datos_clave_publica.e, datos_clave_publica.n)
print ("[+] Clave de sesión cifrada con la clave pública RSA del receptor (hexadecimal):", hex(c)[2:])
f_comunicacion = open("comunicacion.txt", "w")
f_comunicacion.write((b64encode(str(c).encode())).decode() + "\n")
f_comunicacion.write(b64encode(criptograma).decode() + "\n")
f_comunicacion.write((b64encode(str(s).encode()).decode()))
f_comunicacion.close()
else:
print ("*** ERROR: Por favor, introduzca la clave.")
else:
print ("*** ERROR: Por favor, introduzca el texto en claro a cifrar.")
elif opcion == "2":
print ("*** FIN ******************************************")
salir = True
else:
print ("*** ERROR: Opción no válida.")
if __name__ == '__main__':
main()</code>
<br /></pre><p><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><p><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><p><b><span style="color: #45818e;">Lo ejecuto</span></b>:</p><p><span><span style="background-color: white;"><span><span style="color: #292929;">Tras introducirse el mensaje o texto en claro a cifrar, </span><b><span style="color: #45818e;">lo primero que hace el script es generar la clave </span></b><a href="https://es.wikipedia.org/wiki/Advanced_Encryption_Standard"><span style="color: #2b00fe;">AES</span></a><span style="color: #292929;">, calculando el hash </span><a href="https://es.wikipedia.org/wiki/SHA-2"><span style="color: #2b00fe;">SHA-256</span></a><span style="color: #292929;"> de la clave introducida por el usuario, </span><b><span style="color: #45818e;">con la que se cifra el texto en claro y se obtiene el criptograma o texto en claro cifrado</span></b><span style="color: #292929;"> </span></span></span></span><span style="background-color: white; color: #292929;">(</span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_sim%C3%A9trica"><span style="color: #2b00fe;">criptografía simétrica</span></a><span style="background-color: white; color: #292929;">).</span></p><p><span style="background-color: white;"><span style="font-family: inherit;"></span></span></p><p><span style="font-family: inherit;"><span style="background-color: white;"><span style="color: #292929;"></span></span></span></p><p style="text-align: left;"><span style="font-family: inherit;"><span style="background-color: white;"></span></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: inherit;"><span style="background-color: white;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMIyvyXcjLzQ3xG0O6oOzdGRKz8yQm0SfhL_b5l9b05kL0mmnBOrmh-1lhoZhH0WeG9buZg_7juYrnDZxBTPCLQs3OAGXBwlXKh2QSKY2UHYM2Locp7vQzhxwGG0GtlSsxPvXjwHk9rNfD8xB2jc0f17Rr3harpiE_q_loX7y3vdSiOtXXNcmcesjq/s698/Firmar%20digitalmente%20y%20cifrar_1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="698" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMIyvyXcjLzQ3xG0O6oOzdGRKz8yQm0SfhL_b5l9b05kL0mmnBOrmh-1lhoZhH0WeG9buZg_7juYrnDZxBTPCLQs3OAGXBwlXKh2QSKY2UHYM2Locp7vQzhxwGG0GtlSsxPvXjwHk9rNfD8xB2jc0f17Rr3harpiE_q_loX7y3vdSiOtXXNcmcesjq/s16000/Firmar%20digitalmente%20y%20cifrar_1.png" /></a></span></span></div><p></p><p style="text-align: left;"><b><span style="color: #45818e;">Lo siguiente</span></b> que hace el script <b><span style="color: #45818e;">es leer la</span></b> <a href="https://drive.google.com/file/d/1w0a2lVE_AJVoPunBGEfPIMPUaCAu45vF/view?usp=sharing" style="font-family: inherit;"><span style="color: #2b00fe;">clave privada del emisor</span></a> (módulo y exponente de la clave privada), almacenada en formato PEM en un fichero, <b><span style="color: #45818e;">para cifrar mediante el algoritmo</span></b> <a href="https://es.wikipedia.org/wiki/RSA"><span style="color: #2b00fe;">RSA</span></a> <span style="background-color: white;">(</span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica" style="background-color: white;"><span style="color: #2b00fe;">criptografía asimétrica</span></a><span style="background-color: white;">)</span> <b><span style="color: #45818e;">la firma digital del mensaje o texto claro</span></b>, previamente calculada mediante la obtención del <span style="background-color: white;"><span style="color: #292929;">hash </span><a href="https://es.wikipedia.org/wiki/SHA-2"><span style="color: #2b00fe;">SHA-256</span></a></span> de este último.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi29CNxd7J9ZwBnO-cZk_-2lMJp7oC4ynpXq2bCJy6CX7wQjyBfk28VcCSkMDEVNIOLP9pXbaQPlkVxeNUjHbtDNMggT1JxlLDry3L1xkfLVnpPfMpjZ3kuPqyOJpntx94gzYAG8gJnFL8jIN1q5xgHxgxiREtHfG6JnlqhY5oX09x7Xf21J_euWer-/s622/Firmar%20digitalmente%20y%20cifrar_2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="492" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi29CNxd7J9ZwBnO-cZk_-2lMJp7oC4ynpXq2bCJy6CX7wQjyBfk28VcCSkMDEVNIOLP9pXbaQPlkVxeNUjHbtDNMggT1JxlLDry3L1xkfLVnpPfMpjZ3kuPqyOJpntx94gzYAG8gJnFL8jIN1q5xgHxgxiREtHfG6JnlqhY5oX09x7Xf21J_euWer-/s16000/Firmar%20digitalmente%20y%20cifrar_2.png" /></a></div><p style="text-align: left;"><span style="color: #45818e;"><b>Posterior</b></span><span style="color: #45818e; font-weight: bold;">mente,</span> el script <b><span style="color: #45818e;">lee la</span></b> <a href="https://drive.google.com/file/d/10JX_oOV3iTlhverf_nMsdOXSYNfgR_xa/view?usp=sharing" style="font-family: inherit;"><span style="color: #2b00fe;">clave pública del receptor</span></a> (módulo y exponente de la clave pública), almacenada en formato PEM en otro fichero, <b><span style="color: #45818e;">para cifrar mediante el algoritmo</span></b> <a href="https://es.wikipedia.org/wiki/RSA"><span style="color: #2b00fe;">RSA</span></a> <span style="background-color: white;">(</span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica" style="background-color: white;"><span style="color: #2b00fe;">criptografía asimétrica</span></a><span style="background-color: white;">)</span> <b><span style="color: #45818e;">la clave de sesión </span></b><span><span style="background-color: white;"><span><a href="https://es.wikipedia.org/wiki/Advanced_Encryption_Standard"><span style="color: #2b00fe;">AES</span></a><span style="color: #292929;"> con la que se ha cifrado el mensaje o texto en claro</span><span style="color: #292929;"> </span></span></span></span><span style="background-color: white; color: #292929;">(</span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_sim%C3%A9trica"><span style="color: #2b00fe;">criptografía simétrica</span></a><span style="background-color: white; color: #292929;">).</span></p><p style="text-align: left;"><span style="background-color: white;"><span style="color: black;">Y, </span><span><b><span style="color: #45818e;">finalmente</span></b>,</span> para simular el envió de la comunicación, <b><span style="color: #45818e;">se genera un fichero, comunicación.txt</span></b>, en el que se almacenan, codificados en base64, lo siguientes datos: la clave de sesión <a href="https://es.wikipedia.org/wiki/Advanced_Encryption_Standard"><span style="color: #2b00fe;">AES</span></a> cifrada, el criptograma y la firma digital cifrada. </span></p><p style="text-align: left;"><span style="background-color: white; color: #292929;">De esta forma, cuando el receptor reciba la comunicación, lo primero que se hará será descifrar la clave de sesión </span><a href="https://es.wikipedia.org/wiki/Advanced_Encryption_Standard" style="background-color: white;"><span style="color: #2b00fe;">AES</span></a><span style="background-color: white; color: #292929;"> con su </span><a href="https://drive.google.com/file/d/1A18AS6l2GZCsTTuIXkesH0v31H9LGP48/view?usp=sharing"><span style="color: #2b00fe;">clave privada</span></a><span style="background-color: white; color: #292929;"> </span><span style="background-color: white; color: #292929;">(</span><span style="background-color: white; color: #292929;"><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica"><span style="color: #2b00fe;">criptografía asimétrica</span></a>) y con ésta descifrar el criptograma </span><span style="background-color: white; color: #292929;">(</span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_sim%C3%A9trica"><span style="color: #2b00fe;">criptografía simétrica</span></a><span style="background-color: white; color: #292929;">)</span><span style="background-color: white; color: #292929;">, para, posteriormente, verificar la firma digital del mensaje o texto en claro con la clave pública del emisor </span><span style="background-color: white; color: #292929;">(</span><span style="background-color: white; color: #292929;"><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica"><span style="color: #2b00fe;">criptografía asimétrica</span></a>)</span><span style="background-color: white; color: #292929;">.</span></p><p style="text-align: left;"><span style="background-color: white;"><span style="color: #292929;">En un </span><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxix-descifrado-rsa-y.html"><span style="color: #2b00fe;">post posterior</span></a><span style="color: #292929;"> pondré el script en python para implementar esto último.</span></span></p><p><span style="background-color: white; font-family: inherit;"><b><i>Quizás también te interese</i></b>:</span></p><div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2016/10/criptografia-xxxv-el-algoritmo-rsa-i.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmuLy3WfFzpqlRc3oQmUt4XlQmD1JeJqRphUGdhRvInqrtUUmo8yu2rZglxHQD67fXOiQi7_tpz7Wk0vL1w8J6ncgZ3J3m9LGfvaKJ8pknSUSXyeKgu-lTc8QzLzI8pk2wgjShME3zztHuJu1okd9GwLBfvoS1MGAr607DDCzy_YQe2IhYlF5WIARP/s16000/El%20algoritmo%20RSA%20(I).png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2016/10/criptografia-xxxvi-el-algoritmo-rsa-ii.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirNSpIv8NCi7fdLEAqb_jymUk6SWabYFk82YzeHl4hqLSp-L7WHZaCC_Jy1mpN6VRrOELIwFL9lFnlbPP-OKFiR7B_XrdBiu7991oaCtzqtkvROW7fCYCAERxlu2v66iUlzbVbWulg12rHw_Ri9h2CuWsjPycWvr6qQVFMu3MFz2R0tCfOR3oaHONN/s16000/El%20algoritmo%20RSA%20(II).png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxvii-generacion-de.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGIK1uByciF8ysOGRo6MFspKPr2l3KcMGjugIOX2P3vFzrwG_N101Ks5goqM8uOivrj_xodjUVpujGiXdbldfwFhf2_WVafJWBHmGdPbMrqq5yFHmXLh-fPEV1WOI-66WBRHtkLzfwk9sdsGPBuPgn8DYKZJVjdS1FtXmiYVhnixPPi2eXYovMtTQt/s16000/Generaci%C3%B3n%20de%20claves%20RSA%20en%20python.png" /></a></div></div>Mikel García Larraganhttp://www.blogger.com/profile/03118239524461394157noreply@blogger.com0tag:blogger.com,1999:blog-1846493661397027137.post-9692601067815600082023-07-21T18:18:00.011+02:002023-08-05T08:44:46.828+02:00Criptografía (CCLXXVII): Generación de claves RSA en python<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNbHVwdCwX0a1b-w6zLodt6lk5q64EFRG_PqGZBz3o9RSgzTkpVhkQIrgpWwa01SM5aSE6wygD5z_OglEBljiambcjrflnxiB1AsPHFgG1Gu_39nZshTkTkACwzpfrF23fpjM6P_Btv5x_JOELVV2HFHb5fVRzvpWig78PQVCfad7c83lBYxOBiYTr/s238/RSA.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="114" data-original-width="238" height="114" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNbHVwdCwX0a1b-w6zLodt6lk5q64EFRG_PqGZBz3o9RSgzTkpVhkQIrgpWwa01SM5aSE6wygD5z_OglEBljiambcjrflnxiB1AsPHFgG1Gu_39nZshTkTkACwzpfrF23fpjM6P_Btv5x_JOELVV2HFHb5fVRzvpWig78PQVCfad7c83lBYxOBiYTr/s1600/RSA.png" width="238" /></a></div>Continúo poniendo scripts de programación en python para automatizar tareas que tengan relación con la <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa"><span style="color: #2b00fe;">criptografía</span></a>.<p></p><p></p><p></p><p></p><p></p><p></p><p><b><span style="color: #45818e;">En este post incluyo un </span></b><span style="color: #45818e; font-weight: bold;">script en python para la generación del par de claves de un usuario, pública y privada, en</span><span> <a href="https://es.wikipedia.org/wiki/RSA"><span style="color: #2b00fe;">RSA</span></a></span><span style="font-family: inherit;">.</span></p><p><span style="font-family: inherit;">Antes de poner el script, recordar que en <a href="http://mikelgarcialarragan.blogspot.com/2016/10/criptografia-xxxv-el-algoritmo-rsa-i.html"><span style="color: #2b00fe;">este post</span></a> expliqué cómo se generaban ambas claves en este <a href="https://es.wikipedia.org/wiki/Criptosistema"><span style="color: #2b00fe;">criptosistema</span></a>, posiblemente<span style="font-family: inherit;"> el </span></span><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;">algoritmo de </span><a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica"><span style="color: #2b00fe;">cifrado asimétrico</span></a><span style="color: #292929;"> más utilizado actualmente y que debe su nombre a las iniciales de los apellidos de sus tres inventores: </span><a href="https://es.wikipedia.org/wiki/Ronald_Rivest"><span style="color: #2b00fe;">Ronald Rivest</span></a><span style="color: #292929;">, </span><a href="https://es.wikipedia.org/wiki/Adi_Shamir"><span style="color: #2b00fe;">Adi Shamir</span></a><span style="color: #292929;"> y </span><a href="https://es.wikipedia.org/wiki/Leonard_Adleman"><span style="color: #2b00fe;">Leonard Adleman</span></a><span style="color: #292929;">, que lo desarrollaron en 1977.</span></span></span></p><p><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;">Conforme a lo que indiqué en el citado post, </span><span style="color: #45818e;"><b><span>l</span><span>a generación del par de claves para un usuario consiste en</span></b></span><span style="color: #292929;">:</span></span></span></p><p><span style="font-family: inherit;"><span style="background-color: white; color: #292929;">1.-Se eligen aleatoriamente dos </span><span style="background-color: white;"><a href="https://es.wikipedia.org/wiki/N%C3%BAmero_primo"><span style="color: #2b00fe;">numero primos</span></a> <span style="color: #292929;">grandes (</span></span><i style="background-color: white; color: #292929;">p</i><span style="background-color: white; color: #292929;"> y </span><i style="background-color: white; color: #292929;">q</i><span style="background-color: white; color: #292929;">), actualmente de un tamaño mínimo de 1.024 bits cada uno de ellos, y se calcula el producto (</span><i style="background-color: white; color: #292929;">n</i><span style="background-color: white; color: #292929;">) de ambos. Es decir, </span><i style="background-color: white; color: #292929;">n = pq</i><span style="background-color: white; color: #292929;">.</span></span></p><p><span style="font-family: inherit;"><span style="background-color: white; color: #292929;">2.- Se calcula la </span><span style="background-color: white;"><a href="https://es.wikipedia.org/wiki/Funci%C3%B3n_%CF%86_de_Euler"><span style="color: #2b00fe;">función de Euler</span></a> <span style="color: #292929;">del módulo (</span></span><i style="background-color: white; color: #292929;">n</i><span style="background-color: white; color: #292929;">), que para dos números primos es: </span></span><span style="background-color: white; color: #292929; font-family: symbol; font-style: italic;">j</span><span style="font-family: inherit;"><span style="background-color: white; color: #292929;"><i>(n) = (p - 1)(q - 1)</i></span><span style="background-color: white; color: #292929;">.</span></span></p><p><span style="font-family: inherit;"><span style="background-color: white; color: #292929;">3.- Se escoge un número </span><i style="background-color: white; color: #292929;">e </i><span style="background-color: white; color: #292929;">(</span></span><span style="background-color: white; color: #292929;">de </span><i style="background-color: white; color: #292929;">'encrypt'</i><span style="background-color: white; color: #292929;">)</span><span style="font-family: inherit;"><span style="background-color: white; color: #292929;">, en el intervalo 1 < </span><i style="background-color: white; color: #292929;">e</i><span style="background-color: white; color: #292929;"> < </span></span><span style="background-color: white; color: #292929; font-family: symbol; font-style: italic;">j</span><span style="background-color: white; color: #292929; font-family: inherit;"><i>(n)</i>, </span><span style="background-color: white; color: #292929; font-family: inherit;">que sea </span><span style="background-color: white; font-family: inherit;"><a href="https://es.wikipedia.org/wiki/N%C3%BAmeros_coprimos"><span style="color: #2b00fe;">coprimo o primo relativo</span></a><span style="color: #292929;"> con </span></span><span style="background-color: white; color: #292929; font-family: symbol; font-style: italic;">j</span><i style="background-color: white; color: #292929; font-family: inherit;">(n)</i><span style="background-color: white; color: #292929; font-family: inherit;">, es decir, de forma que el máximo común divisor de </span><i style="background-color: white; color: #292929; font-family: inherit;">e</i><span style="background-color: white; color: #292929; font-family: inherit;"> y </span><span style="background-color: white; color: #292929; font-family: symbol; font-style: italic;">j</span><i style="background-color: white; color: #292929; font-family: inherit;">(n)</i><span style="background-color: white; color: #292929; font-family: inherit;"> sea 1 (</span><i style="background-color: white; color: #292929; font-family: inherit;">mcd(e, </i><span style="background-color: white; color: #292929; font-family: symbol; font-style: italic;">j</span><i style="background-color: white; color: #292929; font-family: inherit;">(n))= 1</i><span style="background-color: white; color: #292929; font-family: inherit;">). </span><b style="background-color: white; color: #292929; font-family: inherit;"><span style="color: #45818e;">La clave pública será (<i>e</i>, <i>n</i>)</span></b><span style="background-color: white; color: #292929; font-family: inherit;">.</span></p><p><span style="font-family: inherit;"><span style="background-color: white; color: #292929;">Como valor estándar de <i>e</i> se utiliza el </span><span><a href="https://es.wikipedia.org/wiki/N%C3%BAmero_de_Fermat"><span style="color: #2b00fe;">número 4 de Fermat</span></a><span style="color: #292929;">: </span></span><span style="color: #292929;">65.537 (un número primo de 17 bits)</span><span style="color: #292929;">.</span></span></p><p><span style="font-family: inherit;"><span style="background-color: white; color: #292929;">4.- Se calcula, mediante el </span><span style="background-color: white;"><a href="https://es.wikipedia.org/wiki/Algoritmo_de_Euclides#Algoritmo_de_Euclides_extendido"><span style="color: #2b00fe;">algoritmo de Euclides extendido</span></a><span style="color: #292929;"> el inverso mutiplicativo </span></span><i style="background-color: white; color: #292929;">d </i><span style="background-color: white; color: #292929;">(de </span><i style="background-color: white; color: #292929;">'decrypt'</i><span style="background-color: white; color: #292929;">) de </span></span><i style="background-color: white; color: #292929;">e</i><span style="font-family: inherit;"><span style="background-color: white; color: #292929;"> módulo </span></span><span style="background-color: white; color: #292929; font-family: symbol; font-style: italic;">j</span><span style="font-family: inherit;"><span style="background-color: white; color: #292929;">(</span><i style="background-color: white; color: #292929;">n</i><span style="background-color: white; color: #292929;">), es decir, que satisfaga: </span><i style="background-color: white; color: #292929;">de</i><span style="background-color: white; color: #292929;"> </span></span><span style="background-color: white; color: #292929; font-family: symbol;">º</span><span style="font-family: inherit;"><span style="background-color: white; color: #292929;"> </span><i style="background-color: white; color: #292929;">1 mod (</i></span><span style="background-color: white; color: #292929; font-family: symbol; font-style: italic;">j</span><span style="font-family: inherit;"><i style="background-color: white; color: #292929;">(n)</i><i style="background-color: white; color: #292929;">)</i><span style="background-color: white; color: #292929;">. </span><b style="background-color: white; color: #292929;"><span style="color: #45818e;">La clave privada será (<i>d, n</i>)</span></b><span style="background-color: white; color: #292929;">.</span></span></p><p>Para que el script para la generación del par de claves funcione se necesita importar el siguiente módulo en el programa principal, <span style="font-family: inherit;">que se encargará de generar los dos números primos aleatorios, <i>p</i> y <i>q</i>.</span></p><pre><pre><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# GENERACIÓN DE UN NÚMERO PRIMO ALEATORIO:
#
# Generación de un número primo aleatorio a partir de un número de b bits.
#
# http://mikelgarcialarragan.blogspot.com/
from sympy import primerange, prime
from random import randint, getrandbits
def test_miller_rabin(n,k):
# n = número natural mayor que 1 e impar del que queremos conocer si es primo.
# k = número de veces o rondas a ejecutar el test.
# t = indicador de que n es primo con un cierto nivel de confianza (0: primo; 1: compuesto).
# s = número de veces que 2 divide a n - 1.
t = 0
s = 0
r = n - 1
while r%2 == 0:
s+=1
r = r//2
i=0
while i in range(0, k) and t != 1:
a = randint(2, n - 1)
j = 0
y = pow(a, r, n)
if y != 1 and y != n - 1:
j = 1
while y != n - 1 and t != 1 and j <= s - 1:
y = pow(y, 2, n)
if y == 1:
t = 1
else:
j = j + 1
if y != n -1:
t = 1
i = i + 1
if t == 0:
return True
else:
return False
def generar_primo_aleatorio(b,k):
# b = número de bits que tendrá como mínimo el número primo aleatorio.
# k = número de veces o rondas a ejecutar el test de primalidad.
# Se genera un número aleatorio impar (p) de b bits.
p = getrandbits(int(b))
if p%2 == 0:
p+=1
# Se crea una lista con los primeros 2048 números primos, para descartar rápidamente aquellos
# candidatos no primos, es decir, aquellos que son divisibles por alguno de los números primos
# integrantes de esta lista.
primeros_2048_primos = list(primerange(prime(2048 + 1)))
# Se realizan las comprobaciones tendentes a verificar si el candidato es primo con un cierto
# nivel de confianza.
puede_ser_primo = False
while not puede_ser_primo:
puede_ser_primo = True
for primo in primeros_2048_primos:
if p%primo == 0:
puede_ser_primo = False
break
# Si el candidato supera la primera criba, es decir no es divisible entre ninguno de los primeros
# 2048 números primos, entonces se le somete al test de primalidad de Miller-Rabin.
if puede_ser_primo:
if not test_miller_rabin(p,int(k)):
puede_ser_primo = False
# Si el candidato no supera la primera criba, es decir es divisible entre alguno de los primeros
# 2048 números primos o no supera el test de primalidad de Miller-Rabin, entonces se incrementa
# al candidato en dos unidades y se vuelve a comprobar si el nuevo candidato puede ser primo.
if not puede_ser_primo:
p+=2
return p</code>
<br /></pre><p style="font-family: "Times New Roman"; white-space: normal;">El <b><span style="color: #45818e;">script</span></b> es el siguiente:</p></pre><p><span style="font-family: inherit;"><span style="background-color: white; color: #292929;">- </span><i style="background-color: white; color: #292929;"><u>Script python para la generación del par de claves RSA, pública y privada, de un usuario</u></i><span style="background-color: white; color: #292929;">:</span></span></p><pre><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# RSA:
#
# Generación de las claves, pública (e, n) y privada (d,n), para un usuario.
#
# http://mikelgarcialarragan.blogspot.com/
import primo_aleatorio
import pyasn1.type.univ
import pyasn1.codec.der.encoder
import base64
from time import time
def pempubl(n, e):
template = '-----BEGIN RSA PUBLIC KEY-----\n{}-----END RSA PUBLIC KEY-----\n'
seq = pyasn1.type.univ.Sequence()
for i,x in enumerate((n, e)):
seq.setComponentByPosition(i, pyasn1.type.univ.Integer(x))
der = pyasn1.codec.der.encoder.encode(seq)
return template.format(base64.encodebytes(der).decode('ascii'))
def pempriv(n, e, d, p, q):
template = '-----BEGIN RSA PRIVATE KEY-----\n{}-----END RSA PRIVATE KEY-----\n'
seq = pyasn1.type.univ.Sequence()
dP = d%(p-1)
dQ = d%(q-1)
qInv = pow(q, -1, p)
for i,x in enumerate((0, n, e, d, p, q, dP, dQ, qInv)):
seq.setComponentByPosition(i, pyasn1.type.univ.Integer(x))
der = pyasn1.codec.der.encoder.encode(seq)
return template.format(base64.encodebytes(der).decode('ascii'))
def main():
# MENÚ:
# Se presenta el menú para que se seleccione una opción.
salir = False
while not salir:
print ("")
print ("*** MENÚ *****************************************")
print ("1. Generar par de claves.")
print ("2. Salir.")
print ("")
opcion = input("Por favor, seleccione una opción: ")
if opcion == "1":
print ("")
print ("--- GENERACIÓN DE LA CLAVE PÚBLICA Y PRIVADA PARA UN USUARIO:")
# Se introduce el tamaño mínimo, número de bits, que tendrán los números primos aleatorios p y q a generar
b = "*"
while not b.isnumeric() or int(b) < 1024:
b = input("Introduzca el número de bits, sin punto decimal y mayor o igual que 1024, que tendrán los números primos aleatorios 'p' y 'q' a generar: ")
if b.isnumeric() and int(b) >= 1024:
inicio_generacion_par_claves = inicio_generacion_primo = time()
print("[+] Generando número primo aleatorio 'p'...")
p = q = primo_aleatorio.generar_primo_aleatorio(b,5)
print("[+] Número primo aleatorio 'p' generado:", p)
print("[+] Tiempo de ejecucion de la generación del número primo aleatorio 'p':", time() - inicio_generacion_primo)
inicio_generacion_primo = time()
print("[+] Generando número primo aleatorio 'q'...")
while p == q:
q = primo_aleatorio.generar_primo_aleatorio(b,5)
print("[+] Número primo aleatorio 'q' generado:", q)
print("[+] Tiempo de ejecucion de la generación del número primo aleatorio 'q':", time() - inicio_generacion_primo)
n = p * q
print("[+] Módulo 'n':", n)
phi = (p-1) * (q-1)
print("[+] 'phi':", phi)
e = 65537
print("[+] Clave pública (e, n): (",e, ",", n,")")
d = pow(e, -1, phi)
print("[+] Clave privada (d, n): (",d, ",", n,")")
print("[+] Tiempo de ejecucion de la generación del par de claves, pública y privada:", time() - inicio_generacion_par_claves)
publpem = pempubl(n, e)
print("[+] Clave pública en formato PEM:")
print(publpem)
with open("public.pem", "w") as f:
f.write(publpem)
privpem = pempriv(n, e, d, p, q)
print("[+] Clave privada en formato PEM:")
print(privpem)
with open("private.pem", "w") as f:
f.write(privpem)
else:
print ("*** ERROR: Número de bits incorrecto. Debe ser un número natural, sin punto decimal, mayor o igual que 1024.")
elif opcion == "2":
print ("*** FIN ******************************************")
salir = True
else:
print ("*** ERROR: Opción no válida.")
if __name__ == '__main__':
main()</code></pre><p><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><p><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><p><b><span style="color: #45818e;">Lo ejecuto</span></b>:</p><p><span style="background-color: white;"><span style="font-family: inherit;"></span></span></p><div class="separator" style="clear: both; text-align: center;"><span style="background-color: white;"><span style="font-family: inherit;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjb5I8UkhxFgIWs6dXcr-dho8ziImQcmUoQe2cQUCYWYCbdfcOm4r_PNAHcrSJtgpR977TzwtQc3WMsb0bpr1Bt_5SnNSDm6SwtN31kZmKhG03EXSitVFO5c38nZXJEh54Qf6uM6cuTynrW4n2A57Z05wqfV9sBSlgX8u9wTLv3D3UuyKgBioOEZeVD/s616/Generar%20Claves_1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="554" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjb5I8UkhxFgIWs6dXcr-dho8ziImQcmUoQe2cQUCYWYCbdfcOm4r_PNAHcrSJtgpR977TzwtQc3WMsb0bpr1Bt_5SnNSDm6SwtN31kZmKhG03EXSitVFO5c38nZXJEh54Qf6uM6cuTynrW4n2A57Z05wqfV9sBSlgX8u9wTLv3D3UuyKgBioOEZeVD/s16000/Generar%20Claves_1.png" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgL6DvtiprGF1AoLoQMKrQ9z6V8-YcVUw8o3MEpVvJKfbu0g_IgIyaSimW9Y5Sy2n4MN3ZCrzfqbi1TPiT01l3QaMD-uln2Kj04UlC6XVzP0K8_xNqpBuA3dlktaVKVjPVUUFSEEXGY3NhMa_pm1i-IE9MmllYKxMCzqeN08LDKNUCT1p3AmDiH4cn2/s616/Generar%20Claves_2.png" style="font-family: inherit; margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="570" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgL6DvtiprGF1AoLoQMKrQ9z6V8-YcVUw8o3MEpVvJKfbu0g_IgIyaSimW9Y5Sy2n4MN3ZCrzfqbi1TPiT01l3QaMD-uln2Kj04UlC6XVzP0K8_xNqpBuA3dlktaVKVjPVUUFSEEXGY3NhMa_pm1i-IE9MmllYKxMCzqeN08LDKNUCT1p3AmDiH4cn2/s16000/Generar%20Claves_2.png" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2p4WNRJeVTLzEO0I0PA-Xx4KObHuB7gstKKYwZrn3zW0itR7-RnthVcloci5n6lib23sJFXe-RHpyv9XyamXhkirMgOULXjreiNXM2D6aD7nyaMgTdTZgM5qNhSAlh0z4ZVwSkTd4u_GtZxBJcGuM3am7fUXqC0aN2hNL256mw_g07LefkN5Exzss/s617/Generar%20Claves_3.png" style="font-family: inherit; margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="311" data-original-width="617" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2p4WNRJeVTLzEO0I0PA-Xx4KObHuB7gstKKYwZrn3zW0itR7-RnthVcloci5n6lib23sJFXe-RHpyv9XyamXhkirMgOULXjreiNXM2D6aD7nyaMgTdTZgM5qNhSAlh0z4ZVwSkTd4u_GtZxBJcGuM3am7fUXqC0aN2hNL256mw_g07LefkN5Exzss/s16000/Generar%20Claves_3.png" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPcbLF_TLVxU1OlB-JjxVD2BrhYBD46OSNCN9pJFtK8dNJG-iR78pC9vN8rVLJ-fqIJ3KW2HqiuXCdKl9hjOrDz4KXSHw3XEvyR1kP4KlPhIM7xgW6KNz3wtGfLQXRGfG9JuQsNdXA53bw2-q5Xd8jQGQ8r5JwZeNxY4ATXmEJ1zgBh9VVG1mQDYcp/s616/Generar%20Claves_4.png" style="font-family: inherit; margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="555" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPcbLF_TLVxU1OlB-JjxVD2BrhYBD46OSNCN9pJFtK8dNJG-iR78pC9vN8rVLJ-fqIJ3KW2HqiuXCdKl9hjOrDz4KXSHw3XEvyR1kP4KlPhIM7xgW6KNz3wtGfLQXRGfG9JuQsNdXA53bw2-q5Xd8jQGQ8r5JwZeNxY4ATXmEJ1zgBh9VVG1mQDYcp/s16000/Generar%20Claves_4.png" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh768DiOxNrWU9EG6XY178zXuij8k8mQy0HH5PjemOhzKh2ACZ9T_VrFvaN-xp9jLXR3HZqptDuSSUpwHd4OXYkjAGkL-i9UEMFOBVsarcEttUV-LIQKttsltsfqWSXryY1BAWXBSdijvaf-yFg-vRGRvUN1RWD-bZwLdydwQIn709xyMBq6w5vxGz7/s615/Generar%20Claves_5.png" style="font-family: inherit; margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="280" data-original-width="615" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh768DiOxNrWU9EG6XY178zXuij8k8mQy0HH5PjemOhzKh2ACZ9T_VrFvaN-xp9jLXR3HZqptDuSSUpwHd4OXYkjAGkL-i9UEMFOBVsarcEttUV-LIQKttsltsfqWSXryY1BAWXBSdijvaf-yFg-vRGRvUN1RWD-bZwLdydwQIn709xyMBq6w5vxGz7/s16000/Generar%20Claves_5.png" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr85uL3G13PaaAMF8GTBnxEiWpaXq45iTZ_Cj9Fi9hx2nzWqoql-LsvDVv4tZ8R2qX88NTp13e-zMvyOoPowxxRk20E2dvYFp59JHxGw3zoEmMYWjz69rwpoiUB5gUA68KEc6EbDH51VIY1I0qF5tDEwmv8N-g5C0oPBlQSdkJchrFt3dT91AWliOx/s735/Generar%20Claves_6.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="735" data-original-width="621" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr85uL3G13PaaAMF8GTBnxEiWpaXq45iTZ_Cj9Fi9hx2nzWqoql-LsvDVv4tZ8R2qX88NTp13e-zMvyOoPowxxRk20E2dvYFp59JHxGw3zoEmMYWjz69rwpoiUB5gUA68KEc6EbDH51VIY1I0qF5tDEwmv8N-g5C0oPBlQSdkJchrFt3dT91AWliOx/s16000/Generar%20Claves_6.png" /></a></span></span></div><p></p><p><span style="background-color: white;">El script muestra la clave pública (e, n) y la clave privada (d , n) generadas y guarda ambas en sendos archivos .PEM, para que puedan ser utilizadas en el cifrado (otro usuario con la clave pública del</span><span style="background-color: white;"> usuario para el que se ha generado este par de claves</span><span style="background-color: white;">), descifrado y firma digital (el usuario para el que se ha generado este par de claves con la clave privada)</span><span style="background-color: white;">.</span></p><p><span style="background-color: white; font-family: inherit;"><b><i>Quizás también te interese</i></b>:</span></p><p><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #292929;"></span></span></span></p><div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2016/07/criptografia-xxi-criptologia-para-todos.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKaP5ai565PqqwfhREy_CiB-A2vbyLwsTJodv93faoqjIosCwN6Zz0jI7Na038PY0UbLP6wgA5S88OLWcuPpsqjPoTn2_8022DcM_l8ROKMQtALXkE4fqeJDQiE-WJcemR8c8DAuo_6RMxZbPskM6rNkFrc7ItOejBmFds00T-MW6IJ5x-DfNC4nhX/s16000/Criptolog%C3%ADa%20para%20todos%20(III).png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2016/10/criptografia-xxxv-el-algoritmo-rsa-i.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmuLy3WfFzpqlRc3oQmUt4XlQmD1JeJqRphUGdhRvInqrtUUmo8yu2rZglxHQD67fXOiQi7_tpz7Wk0vL1w8J6ncgZ3J3m9LGfvaKJ8pknSUSXyeKgu-lTc8QzLzI8pk2wgjShME3zztHuJu1okd9GwLBfvoS1MGAr607DDCzy_YQe2IhYlF5WIARP/s16000/El%20algoritmo%20RSA%20(I).png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2016/10/criptografia-xxxvi-el-algoritmo-rsa-ii.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirNSpIv8NCi7fdLEAqb_jymUk6SWabYFk82YzeHl4hqLSp-L7WHZaCC_Jy1mpN6VRrOELIwFL9lFnlbPP-OKFiR7B_XrdBiu7991oaCtzqtkvROW7fCYCAERxlu2v66iUlzbVbWulg12rHw_Ri9h2CuWsjPycWvr6qQVFMu3MFz2R0tCfOR3oaHONN/s16000/El%20algoritmo%20RSA%20(II).png" /></a></div></div>Mikel García Larraganhttp://www.blogger.com/profile/03118239524461394157noreply@blogger.com0tag:blogger.com,1999:blog-1846493661397027137.post-4531095663376941362023-07-17T20:06:00.011+02:002023-07-19T17:13:40.460+02:00Criptografía (CCLXXVI): Cifrado Vernam en python<div class="separator" style="clear: both;"><div class="separator" style="clear: both; text-align: left;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQJcmACD-8ngRKmxD6LXS2lX6p-e0EOQxT4C2w7aHNIF50XnlhPqvzxObZ8yCiiBz0eOdqkLm2uilJ034mKgpAfn0miBQMNjagDgK6BnUUb1sTAUIA5PbWQZrnhLV1DK6Yw8I3xOIaZYd3Z6_hvDRE3K79XtPZqFhBfwtPdNsh0CoQvXrOVGvBlf2c/s270/Gilbert%20Vernam.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="270" data-original-width="200" height="270" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQJcmACD-8ngRKmxD6LXS2lX6p-e0EOQxT4C2w7aHNIF50XnlhPqvzxObZ8yCiiBz0eOdqkLm2uilJ034mKgpAfn0miBQMNjagDgK6BnUUb1sTAUIA5PbWQZrnhLV1DK6Yw8I3xOIaZYd3Z6_hvDRE3K79XtPZqFhBfwtPdNsh0CoQvXrOVGvBlf2c/s1600/Gilbert%20Vernam.png" width="200" /></a></div>Continúo poniendo scripts de programación en python para automatizar tareas que tengan relación con la <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa"><span style="color: #2b00fe;">criptografía</span></a>.</div></div><p></p><p></p><p></p><p></p><p></p><p><b><span style="color: #45818e;">En este post incluyo un </span></b><span style="color: #45818e; font-weight: bold;">script en python para el cifrado y descifrado utilizando el</span><span style="font-family: inherit;"> <a href="https://es.wikipedia.org/wiki/Cifrado_Vernam"><span style="color: #2b00fe;">cifrado Vernam</span></a>.</span></p><p>Antes de poner el script, recordar que en <a href="http://mikelgarcialarragan.blogspot.com/2015/10/criptografia-xviii-criptologia-para.html"><span style="color: #2b00fe;">este post</span></a> expliqué cómo se cifraba y descifraba utilizando este <a href="https://es.wikipedia.org/wiki/Criptosistema"><span style="color: #2b00fe;">criptosistema</span></a>, que fue inventado <span style="font-family: inherit;">por <span style="text-align: justify;"><a href="https://es.wikipedia.org/wiki/Gilbert_Vernam"><span style="color: #2b00fe;">Gilbert S. Vernam</span></a> en 1917</span> <span>para su uso </span></span><span style="background-color: #fcfdfd; text-align: justify;"><span style="font-family: inherit;"><span style="color: #222222;"><span style="font-family: inherit;">en la transmisión</span> telegráfica con el </span><a href="https://es.wikipedia.org/wiki/C%C3%B3digo_Baudot"><span style="color: #2b00fe;">código Baudot</span></a></span><span style="color: #222222;"><span><span style="font-family: inherit;">. <span style="font-family: inherit;">No obstante,</span></span><span style="font-family: inherit;"> se puede utilizar con </span></span></span></span><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #202122;"><span style="font-family: inherit;">diferentes codificaciones para el alfabeto</span> y en este script voy a utilizar la codificación </span><a href="https://es.wikipedia.org/wiki/ASCII"><span style="color: #2b00fe;">ASCII</span></a><span style="color: #202122;">.</span></span></span></p><p><span style="background-color: white;"><span style="font-family: inherit;"><span><span style="color: #202122;">Un cifrado que yo creo que está a caballo entre los cifrados clásicos y los cifrados modernos, y que pienso que en terminología clásica se puede clasificar como un </span><a href="https://es.wikipedia.org/wiki/Cifrado_por_sustituci%C3%B3n#Polialfab%C3%A9tico"><span style="color: #2b00fe;">cifrado de sustitución simple polialfabética</span></a><span style="color: #202122;"> de clave no periódica (tal y como lo es, por ejemplo, el </span><a href="http://mikelgarcialarragan.blogspot.com/2017/02/criptografia-xlviii-cifrado-autoclave.html"><span style="color: #2b00fe;">cifrado autoclave</span></a><span style="color: #202122;">), mientras que en terminología moderna se puede clasificar como un </span><a href="https://es.wikipedia.org/wiki/Cifrador_de_flujo"><span style="color: #2b00fe;">cifrado de flujo</span></a><span style="color: #202122;"> (tal y como lo es, por ejemplo, </span><a href="http://mikelgarcialarragan.blogspot.com/2022/09/criptografia-ccxxvii-el-algoritmo-rc4-i.html"><span style="color: #2b00fe;">RC4</span></a><span style="color: #202122;">). </span></span></span></span></p><p><span style="background-color: white;"><span style="font-family: inherit;"><span style="color: #202122;">Este <a href="https://es.wikipedia.org/wiki/Criptosistema"><span style="color: #2b00fe;">criptosistema</span></a><span style="font-family: inherit;">, al que </span></span></span></span><span style="font-family: inherit;"><a href="https://en.wikipedia.org/wiki/Joseph_Mauborgne"><span style="color: #2b00fe;">Joseph Mauborgne</span></a><span style="background-color: white; color: #292929;"> hizo una contribución fundam</span><span style="background-color: white;">en<span style="font-family: inherit;">tal: </span></span><span style="background-color: white;">utilizar como clave una secuencia aleatoria de igual longitud que el mensaje, que se usa una única vez</span><span style="background-color: white;"> (lo que se conoce en inglés como </span><i style="background-color: white;">'one-time pad'</i><span style="background-color: white;">) y que tras su uso se destruye, presenta la propiedad de <a href="https://es.wikipedia.org/wiki/Secreto_perfecto"><span style="color: #2b00fe;">secreto perfecto</span></a> tal y como la formuló <a href="https://es.wikipedia.org/wiki/Claude_Shannon"><span style="color: #2b00fe;">Claude Shannon</span></a> a mediados del siglo XX.</span></span></p><p><span style="font-family: inherit;"><span style="background-color: white;">Las <b><span style="color: #45818e;">funciones de cifrado y descifrado</span></b> consisten en aplicar una operación XOR</span><span style="background-color: white;"> u o-exclusivo (suma módulo 2) entre los bits de la clave y </span><span style="background-color: white;">los bits de los caracteres, tanto del texto en plano, para cifrar, como del criptograma, para descifrar:</span></span></p><p style="text-align: center;"><span style="font-family: inherit;"><span style="background: white; line-height: 107%;"><i>E<sub>k</sub>(m<sub>i</sub>)</i> = (<i>m<sub>i</sub></i> + <i>k<sub>i</sub></i>)
mod 2 = <i>m<sub>i</sub></i> </span><span style="background: white; line-height: 107%;">⊕</span><span style="background: white; line-height: 107%;"> <i>k<sub>i</sub></i></span></span></p><p style="text-align: center;"><span style="font-family: inherit;"><span style="background: white; line-height: 107%;"><i>D<sub>k</sub> (c<sub>i</sub>)</i> = (<i>c<sub>i</sub></i> + <i>k<sub>i</sub></i>)
mod 2 = <i>c<sub>i</sub></i> </span><span style="background: white; line-height: 107%;">⊕ </span><span style="background: white; line-height: 107%;">k<sub><i>i</i></sub></span></span></p><div style="text-align: left;"><span style="background-color: white;">Donde:</span></div><div style="text-align: left;"><span style="font-family: inherit;"><i style="background-color: white; color: #292929;">k</i><span style="background-color: white; color: #292929;">: clave.<br /></span></span><span style="font-family: inherit;"><span style="background-color: white; color: #292929;"><i>E</i>: función de cifrado.<br /></span></span><span style="font-family: inherit;"><span style="background-color: white; color: #292929;"><i>m</i><span style="bottom: -0.25em; line-height: 0; position: relative; vertical-align: baseline;"><i>i</i></span>: bit i-ésimo del mensaje o texto en claro a cifrar.</span></span></div><div style="text-align: left;"><span style="font-family: inherit;"><span style="background-color: white; color: #292929;"><i>k</i><span style="bottom: -0.25em; line-height: 0; position: relative; vertical-align: baseline;"><i>i</i></span>: bit i-ésimo de la clave.<br /></span></span><span style="font-family: inherit;"><span style="background-color: white; color: #292929;"><i>D</i>: función de descifrado.<br /></span></span><span style="font-family: inherit;"><span style="background-color: white; color: #292929;"><i>c</i></span><span style="background-color: white; bottom: -0.25em; color: #292929; line-height: 0; position: relative; vertical-align: baseline;"><i>i</i></span><span style="background-color: white; color: #292929;">: bit i-ésimo del criptograma o texto cifrado.</span></span><br /></div><p>- <i><u>Script python del cifrado Vernam</u></i>:</p><p>El <b><span style="color: #45818e;">script</span></b> es el siguiente: <code class="html"></code></p><pre><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# CIFRADO DE VERNAM:
#
# Cifra y descifra textos en claro y criptogramas, respectivamente,
# utilizando el criptosistema de Vernam.
#
# http://mikelgarcialarragan.blogspot.com/
import os
import pyperclip
import string
# FUNCIÓN DE CIFRADO / DESCIFRADO:
# La función de cifrado es: Ek(mi) = (mi + Ki) mod 2 = mi XOR Ki
# La función de descifrado es: Dk(Ci) = (Ci + Ki) mod 2 = Ci XOR Ki
def cifrar_descifrar(mensaje_criptograma,clave):
mensaje_criptograma = (bin(int(mensaje_criptograma,2) ^ int(clave,2)))[2:].zfill(len(clave))
return mensaje_criptograma
def main():
# MENÚ:
# Se presenta el menú para que se seleccione una opción.
salir = False
while not salir:
print ("")
print ("*** MENÚ *****************************************")
print ("1. Generar clave aleatoria y copiarla en el portapapeles.")
print ("2. Cifrar.")
print ("3. Descifrar.")
print ("4. Salir.")
print ("")
opcion = input("Por favor, seleccione una opción: ")
if opcion == "1":
print ("")
print ("--- GENERAR CLAVE ALEATORIA:")
# Generar clave aleatoria: Genera una clave aleatoria y la copia en el portapapeles.
tamaño_mensaje = "*"
while not tamaño_mensaje.isnumeric():
tamaño_mensaje = input('[+] Tamaño del mensaje a cifrar: ')
if tamaño_mensaje.isnumeric():
clave = (os.urandom(int(tamaño_mensaje))).hex()
print ("[+] Clave generada (hexadecimal):", clave)
pyperclip.copy(str(clave))
print ("[+] Clave copiada en el portapapeles.")
else:
print ("*** ERROR: El tamaño del mensaje a cifrar debe ser un número natural.")
elif opcion == "2":
print ("")
print ("--- CIFRAR:")
# Cifrar: Se introduce el mensaje a cifrar y se recupera la clave del portapapeles.
mensaje = ""
while mensaje == "":
mensaje = input('Mensaje a cifrar: ')
if mensaje != "":
clave = pyperclip.paste()
if all(digito in string.hexdigits for digito in clave):
print ("[+] Clave recuperada del portapapeles (hexadecimal):", clave)
if len(mensaje) == len(clave)/2:
mensaje = ''.join(bin(ord(caracter))[2:].zfill(8) for caracter in mensaje)
print ("[+] Mensaje (binario): ", mensaje)
clave = (bin(int(clave, 16))[2:]).zfill(len(mensaje))
print ("[+] Clave (binario): ", clave)
criptograma = cifrar_descifrar(mensaje,clave)
print ("[+] Criptograma (binario): ", criptograma)
criptograma = (hex(int(criptograma,2))[2:]).zfill(len(mensaje)//4)
print ("[+] Criptograma (hexadecimal):", criptograma)
pyperclip.copy(criptograma + " " + pyperclip.paste())
print ("[+] Criptograma y clave copiados en el portapapeles.")
else:
print ("*** ERROR: El mensaje a cifrar y la clave recuperada del portapapeles deben tener la misma longitud.")
mensaje = ""
else:
print ("*** ERROR: Clave recuperada del portapapeles incorrecta.")
mensaje = ""
elif opcion == "3":
print ("")
print ("--- DESCIFRAR:")
# Descifrar: Se recuperan el criptograma a descifrar y la clave del portapapeles.
criptograma, clave = pyperclip.paste().split(' ')
if criptograma != "" and all(digito in string.hexdigits for digito in criptograma):
print ("[+] Criptograma recuperado del portapapeles (hexadecimal):", criptograma)
if clave !="" and all(digito in string.hexdigits for digito in clave):
print ("[+] Clave recuperada del portapapeles (hexadecimal):", clave)
if len(criptograma) == len(clave):
criptograma = (bin(int(criptograma, 16))[2:]).zfill(len(criptograma)*4)
print ("[+] criptograma (binario):", criptograma)
clave = (bin(int(clave, 16))[2:]).zfill(len(criptograma))
print ("[+] Clave (binario): ", clave)
mensaje = cifrar_descifrar(criptograma,clave)
print ("[+] mensaje (binario): ", mensaje)
mensaje = (hex(int(mensaje,2))[2:]).zfill(len(criptograma)//4)
print ("[+] mensaje (hexadecimal):", mensaje)
print ("[+] mensaje (ascii): ", (bytes.fromhex(mensaje)).decode("ASCII"))
else:
print ("*** ERROR: El criptograma a descifrar y la clave recuperada del portapapeles deben tener la misma longitud.")
else:
print ("*** ERROR: Clave recuperada del portapapeles incorrecta.")
else:
print ("*** ERROR: Criptograma recuperado del portapapeles incorrecto.")
elif opcion == "4":
print ("*** FIN ******************************************")
salir = True
else:
print ("*** ERROR: Opción no válida.")
if __name__ == '__main__':
main()</code>
<br /></pre><p><b><span style="color: #45818e;">Lo ejecuto</span></b>:</p><p>- <i><u>Generar la clave aleatoria</u></i>:</p><p><b><span style="color: #45818e;">Lo primero es generar la clave aleatoria</span></b>. Nos pedirá la longitud del mensaje a cifrar, ya que la clave debe tener un tamaño igual que éste.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqpnk_xQzencA-GhX3dBz0YP5wWxbGpR35ZlicMBMmN7LMWLKMfF4QwqA0fmUkuLe2v2t8wdtscFE4883a9bPJTTC5XYu1tLcyBcl4ltNCicU-V1fPmq9xGyYfprOz95R2IiiWrCGmNZtrYW_piyeVTz-UZmyAW20wyja27be5RowqHgMtGmoh_mP0/s622/Generar%20clave.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="466" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqpnk_xQzencA-GhX3dBz0YP5wWxbGpR35ZlicMBMmN7LMWLKMfF4QwqA0fmUkuLe2v2t8wdtscFE4883a9bPJTTC5XYu1tLcyBcl4ltNCicU-V1fPmq9xGyYfprOz95R2IiiWrCGmNZtrYW_piyeVTz-UZmyAW20wyja27be5RowqHgMtGmoh_mP0/s16000/Generar%20clave.png" /></a></div><p>Una vez generada, la clave <b><span style="color: #45818e;">se copia en el portapapeles</span></b>.</p><p>- <i><u>Cifrar</u></i>:</p><p><b><span style="color: #45818e;">Después se cifra el mensaje</span></b> con la clave que se recupera del portapapeles.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdLVPxL84P7yVbzGuxIgCNFwstnn5vhJVNEJX6nQDYig2ivFpZQaFQEcr2bLVRoST8vMZXMq71C16LMbKXUm5_mK5XLFHwTgzgVLbpJHIJdK8ra5NXrL1z8x6YoyvQB7hxVXEnkxomA5QUBZGPdMt8vFTUf72Y5xx6v19BswQmwzKKnZFsqhcEvJtf/s802/Cifrar.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="802" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdLVPxL84P7yVbzGuxIgCNFwstnn5vhJVNEJX6nQDYig2ivFpZQaFQEcr2bLVRoST8vMZXMq71C16LMbKXUm5_mK5XLFHwTgzgVLbpJHIJdK8ra5NXrL1z8x6YoyvQB7hxVXEnkxomA5QUBZGPdMt8vFTUf72Y5xx6v19BswQmwzKKnZFsqhcEvJtf/s16000/Cifrar.png" /></a></div><p style="clear: both; text-align: left;"><span style="font-family: inherit;"><span style="background-color: white;"><span style="color: #202122;">Nótese que al utilizarse la operación XOR el criptograma puede tener </span><a href="https://es.wikipedia.org/wiki/ASCII#Los_caracteres_de_control_ASCII"><span style="color: #2b00fe;">caracteres de control de la tabla ASCII</span></a></span></span><span style="background-color: white; font-family: inherit;"><span style="background-color: white; color: #202122;">, es decir, no imprimibles, por lo que el criptograma se representa con los números de código </span></span><a href="https://es.wikipedia.org/wiki/ASCII" style="background-color: white;"><span style="color: #2b00fe;">ASCII</span></a><span style="background-color: white; font-family: inherit;"><span style="background-color: white; color: #202122;"> de cada carácter, para lo que el script utiliza la numeración hexadecimal.</span></span></p><p style="clear: both; text-align: left;"><span style="background-color: white; font-family: inherit;"><span style="background-color: white;"><span style="color: #202122;">Una vez cifrado el mensaje, </span><b><span style="color: #45818e;">el criptograma junto con la clave se copian en el portapapeles</span></b><span style="color: #202122;"> (para mayor comodidad en el descifrado, ya que así no hay que incluirlos manualmente).</span></span></span></p><p>- <i><u>Descifrar</u></i>:</p><p><b><span style="color: #45818e;">Y, finalmente, se descifra el criptograma</span></b>, que se recupera del portapapeles junto con la clave.</p><p><span style="background-color: white;"></span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLy6cjAYTWspKsMj0b_m0CvJghBZsfOml8KqGisk1CDVsIzQ9sY5i9hbYwGE4bsQiKy2dlmJf9ZZltiMi_1CZ7LZatCSVKdOR57IRXDFab9NlzEov-j6jqhcFCO4SkotX2p5CSJ5_JY165WwWwYq901GpJZhID-2ocNNtpfFJ-2AU__pG1J_HeLwup/s802/Descifrar.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="802" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLy6cjAYTWspKsMj0b_m0CvJghBZsfOml8KqGisk1CDVsIzQ9sY5i9hbYwGE4bsQiKy2dlmJf9ZZltiMi_1CZ7LZatCSVKdOR57IRXDFab9NlzEov-j6jqhcFCO4SkotX2p5CSJ5_JY165WwWwYq901GpJZhID-2ocNNtpfFJ-2AU__pG1J_HeLwup/s16000/Descifrar.png" /></a></div><div class="separator" style="clear: both; text-align: left;"><p><span style="background-color: white; font-family: inherit;"><b><i>Quizás también te interese</i></b>:</span></p><div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxx-cifrado-autoclave.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPJVKwaMV_R2X787VoTDDBqbM6Qfe0KBiTUdfJlRQhoTtf2g8yc6f6KKokz_Aw9ZOicmCh1jG-QBaI4Pd0XM8g-fD4zxYY53xxJYFRxHXBF5G_nYW4D4fDjBu5o1uGursBKVccow6dE2FOrmhdAHmYqS7OTERhG8vauC-TbmjSuPmGpZq7-IkVurRg/s16000/Cifrado%20autoclave%20(Vigen%C3%A8re)%20en%20python.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/06/criptografia-cclix-cifrado-rc4-en-python.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAgMAQfWS-Iuw2QjegNBNNSZRTuc3l8gXWahezH5PjCq0P5Nt1zNujjw8AmWU-t0Hb7qRUzq2QOaaAVYnFnalNemAVnjMJrtMf--tNaze9yEyIJ0m1E1tuGUeML2d2XvvO-dZD6KTuDf8ryMlRWL0gE9V2aJKIpFJdC8O9xodchVm9qQZeNNOuvdIF/s16000/Cifrado%20RC4%20en%20python.png" /></a></div></div></div>Mikel García Larraganhttp://www.blogger.com/profile/03118239524461394157noreply@blogger.com0tag:blogger.com,1999:blog-1846493661397027137.post-61239011125743778742023-07-15T11:59:00.003+02:002023-07-15T12:17:23.148+02:00Criptografía (CCLXXV): Exponenciación modular rápida en python<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgshCR-Ct8Ew3IF4GX2Mk-fZqAc785w38OvLtbkzioQaDzJ46DEmxnKdvdFbjwwKEgKp-9_4K2xR_QGq1kqay15tR5EjY9_nnj1QVF3eC_VxxDrDPluPLszuO2YWzauobHc-SNpGNzEW9-6J2NkHzbNSYM2QWyNFOY5mY_BadW3L6otrYKiWga9hXDZ/s211/Exponenciaci%C3%B3n%20modular.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="150" data-original-width="211" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgshCR-Ct8Ew3IF4GX2Mk-fZqAc785w38OvLtbkzioQaDzJ46DEmxnKdvdFbjwwKEgKp-9_4K2xR_QGq1kqay15tR5EjY9_nnj1QVF3eC_VxxDrDPluPLszuO2YWzauobHc-SNpGNzEW9-6J2NkHzbNSYM2QWyNFOY5mY_BadW3L6otrYKiWga9hXDZ/s1600/Exponenciaci%C3%B3n%20modular.png" width="211" /></a></div>Continúo poniendo scripts de programación en python para automatizar tareas que tengan relación con la <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa"><span style="color: #2b00fe;">criptografía</span></a>.<p></p><p></p><p></p><p></p><p><b><span style="color: #45818e;">En este post incluyo un </span></b><span style="color: #45818e; font-weight: bold;">script en python que implementa el algoritmo de exponenciación modular rápida</span>.</p><p>La <a href="https://es.wikipedia.org/wiki/Exponenciaci%C3%B3n_modular"><span style="color: #2b00fe;">exponenciación modular</span></a> con números muy grandes es ampliamente utilizada en <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica"><span style="color: #2b00fe;">criptografía asimétrica</span></a>, por lo que <b><span style="color: #45818e;">se hace necesario utilizar un algoritmo para su cálculo más eficiente que con el método directo</span></b>, es decir, un algoritmo con menores requerimientos de memoria y más rápido que calcular primero la potencia y después reducir el resultado obtenido al módulo.</p><p><b><span style="color: #45818e;">El algoritmo más eficiente para ello es el conocido como de exponenciación rápida o</span></b> <a href="https://es.wikipedia.org/wiki/Exponenciaci%C3%B3n_binaria"><span style="color: #2b00fe;">exponenciación binaria</span></a>, que utiliza la expansión binaria del exponente, y cuyo pseudocódigo para su uso en aritmética modular pongo a continuación.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1skByfC7Pn_NMSGgMGYuMiqwdE_7qphKkbWNM-qWHhxUmKkHxyOMhUjDbc-BcOrauAN0jEkX_kCPK9TYGxKDKHmCub7mhhzAtpsDIjh7pBpgs22YYwujUaUpYEESekoeNXvV1Oyvc4TyGxdACuV9WkUImL-Hv_QkUgGRpvebe1YWwAMLqhPxY_LCi/s622/Algoritmo%20exponenciaci%C3%B3n%20modular%20r%C3%A1pida.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="382" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1skByfC7Pn_NMSGgMGYuMiqwdE_7qphKkbWNM-qWHhxUmKkHxyOMhUjDbc-BcOrauAN0jEkX_kCPK9TYGxKDKHmCub7mhhzAtpsDIjh7pBpgs22YYwujUaUpYEESekoeNXvV1Oyvc4TyGxdACuV9WkUImL-Hv_QkUgGRpvebe1YWwAMLqhPxY_LCi/s16000/Algoritmo%20exponenciaci%C3%B3n%20modular%20r%C3%A1pida.png" /></a></div><p>- <i><u>Script python para implementar el algoritmo de exponenciación modular rápida</u></i>:</p><p>El <b><span style="color: #45818e;">script</span></b> es el siguiente:<code class="html"></code></p><pre><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
from time import time
# ALGORITMO DE EXPONENCIACIÓN MODULAR RÁPIDA:
#
# Algoritmo utilizado en operaciones de exponenciación modular
# con números muy grandes con objeto de hacerlas de forma
# más eficiente.
#
# http://mikelgarcialarragan.blogspot.com/
def exp_modular_rapida(b, e, m):
c = 1
e = bin(e)[2:]
for i in range(0, len(e)):
c = pow(c, 2, m)
if e[i]=="1":
c = c*b%m
return c
def main():
# MENÚ:
# Se presenta el menú para que se seleccione una opción.
salir = False
while not salir:
print ("")
print ("*** MENÚ *****************************************")
print ("1. Algoritmo de exponenciación modular rápida.")
print ("2. Salir.")
print ("")
opcion = input("Por favor, seleccione una opción: ")
if opcion == "1":
print ("")
print ("--- ALGORITMO DE EXPONENCIACIÓN MODULAR RÁPIDA:")
# Se introducen la base, el exponente y el módulo.
base = exponente = modulo = "*"
while not base.isnumeric() or not exponente.isnumeric() or not modulo.isnumeric():
base = input('Introduzca la base (b): ')
exponente = input('Introduzca el exponente (e): ')
modulo = input('Introduzca el módulo (m): ')
if base.isnumeric() and exponente.isnumeric() and modulo.isnumeric():
inicio_exponenciacion = time()
c = exp_modular_rapida(int(base),int(exponente),int(modulo))
print("[+] c = b**e mod m =", c)
print("[+] Tiempo de ejecucion en segundos:", time() - inicio_exponenciacion)
else:
print ("*** ERROR: La base, el exponente y el módulo deben ser números enteros positivos.")
elif opcion == "2":
print ("*** FIN ******************************************")
salir = True
else:
print ("*** ERROR: Opción no válida.")
if __name__ == '__main__':
main()</code>
<br /></pre><p><b><span style="color: #45818e;">Lo ejecuto</span></b>:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWa1PP0QOQP6fdYSrIwTFgtgYN1_8G0Dsvw4nRbOyJFMe-aWswtnnOo7evNvHrtDI1Sobtl1zw-dsijWtZjajzDd5LWHLFAeJUtoEJR1CwiUsTwhflLwM3biGYqKYbZer3eCxMIbG7G5OcgHAC7KkiNV28EF3gut1MtCwab6TE_wUXnZej3rvoXUm8/s606/Exponenciaci%C3%B3n%20modular%20r%C3%A1pida.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="527" data-original-width="606" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWa1PP0QOQP6fdYSrIwTFgtgYN1_8G0Dsvw4nRbOyJFMe-aWswtnnOo7evNvHrtDI1Sobtl1zw-dsijWtZjajzDd5LWHLFAeJUtoEJR1CwiUsTwhflLwM3biGYqKYbZer3eCxMIbG7G5OcgHAC7KkiNV28EF3gut1MtCwab6TE_wUXnZej3rvoXUm8/s16000/Exponenciaci%C3%B3n%20modular%20r%C3%A1pida.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><p style="text-align: left;"><span style="background-color: white; font-family: inherit;"><b><i>Quizás también te interese</i></b>:</span></p><div class="MsoNormal" style="text-align: left;"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/06/criptografia-cclx-test-de-primalidad-de.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEzwi-3fRhx251EEWJdx8OZ8vSeGnfG2Q8JyShqLuKZ7fzbFgJwt83ViwWh2bmvpPbxwTQFlsqfgNoHxa816gRJCKH6tcqqCRbx8XLknznTejCUeVhuZOuMNxf6rtyilpotql8Ol_NT5wuvB9MJKTdwFgoU8gZKruAwTPWDzZNzP0fWzMGLjXMXbS_/s16000/Test%20primalidad%20Miller-Rabin%20en%20python.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/06/criptografia-cclxi-generacion-de-un.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9yffP3no2EI3S4oJwEAyd5S3J_ATFsDCIqWxfDdk5089eyl1pLyyxD95XOGCa0VBiMa-IZSbm_gdGE9zz5VrAZjOv3N45CBGCvhGPvTTCYnwYjDCcT8tf1YGa2AWJJ937LEto6vHhvcwl5TRLR_lrGyrFwW-hmCCnZenZlN9jfcsZyHGUHtbZ2Q/s16000/Generaci%C3%B3n%20de%20un%20n%C3%BAmero%20primo%20aleatorio%20en%20python.png" /></a></div></div></div>Mikel García Larraganhttp://www.blogger.com/profile/03118239524461394157noreply@blogger.com0tag:blogger.com,1999:blog-1846493661397027137.post-91080086211275072702023-07-13T19:25:00.001+02:002023-07-15T10:07:35.412+02:00Criptografía (CCLXXIV): Ataque de diccionario a la sustitución simple monoalfabética en python<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxfsuEuG6eejzRLZQqcy97X4dv8fNmGHqfzcH2LGd_tgDcg_LrOcOBFOu_vYtGrsFQiPdN6h3_tXwxOecVLiudSc3jZ3HTFDU2vcVRk_BKgK8m47tN8FwVcl8GcMd6Auw9USb96D-RUGto3lMMU85B_q7UsSFXZQ9uBqcrXCYkkAOY01oB8FmVHNaW/s193/Sustituci%C3%B3n%20monoalfab%C3%A9tica%20simple.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="193" data-original-width="193" height="193" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxfsuEuG6eejzRLZQqcy97X4dv8fNmGHqfzcH2LGd_tgDcg_LrOcOBFOu_vYtGrsFQiPdN6h3_tXwxOecVLiudSc3jZ3HTFDU2vcVRk_BKgK8m47tN8FwVcl8GcMd6Auw9USb96D-RUGto3lMMU85B_q7UsSFXZQ9uBqcrXCYkkAOY01oB8FmVHNaW/s1600/Sustituci%C3%B3n%20monoalfab%C3%A9tica%20simple.png" width="193" /></a></div>Continúo poniendo scripts de programación en python para automatizar tareas que tengan relación con la <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa"><span style="color: #2b00fe;">criptografía</span></a>.<p></p><p></p><p></p><p></p><p></p><p><span style="font-family: inherit;">Ya puse una <a href="http://mikelgarcialarragan.blogspot.com/2023/06/criptografia-ccliii-cifrado-por.html"><span style="color: #2b00fe;">entrada</span></a> con un script en python para cifrar y descifrar textos en claro y criptogramas, respectivamente, utilizando la <a href="https://es.wikipedia.org/wiki/Cifrado_por_sustituci%C3%B3n#Monoalfab%C3%A9tico"><span style="color: #2b00fe;">sustitución simple monoalfabética</span></a>.</span></p><p><span style="font-family: inherit;"><b><span style="color: #45818e;">Cuando se utiliza una clave (alfabeto de sustitución) aleatoria este</span></b> <a href="https://es.wikipedia.org/wiki/Criptosistema"><span style="color: #2b00fe;">criptosistema</span></a> <b><span style="color: #45818e;">gana en robustez comparado con otros sistemas criptográficos anteriores</span></b>, imposibilitando, por ejemplo, un <a href="https://es.wikipedia.org/wiki/Ataque_de_fuerza_bruta"><span style="color: #2b00fe;">ataque de fuerza bruta</span></a>, ya que el espacio de claves es muy grande.</span></p><p><span style="font-family: inherit;"><b><span style="color: #45818e;">Sin embargo, una clave aleatoria complica recodar la clave por parte del emisor y receptor</span></b> de los mensajes, ya que tienen que recordar la disposición, sin ningún sentido, de todas las letras del alfabeto de sustitución, por lo que <b><span style="color: #45818e;">en la práctica éstos solían acordar una clave fácil de recordar a partir de la que se construía el alfabeto de sustitución</span></b>, de la siguiente forma: primero se colocaba la clave acordada sin repetir letras y después el resto de letras del alfabeto en su orden normal sin incluir las letras ya incluidas de la clave.</span></p><p><span style="font-family: inherit;">Ejemplo: supongamos que la clave acordada es "SUSTITUCION". El alfabeto de sustitución sería:</span></p><p style="text-align: center;"><span style="font-family: inherit;">"SUTICONABDEFGHJKLMÑPQRVWXYZ"</span></p><p><span style="font-family: inherit;">Con esta forma de construir la clave (el alfabeto de sustitución) <b><span style="color: #45818e;">se gana en agilidad y cierta seguridad</span></b>, ya que no hay que anotarla en ningún lugar, <b style="color: #45818e;">pero los criptogramas pueden ser vulnerables a un </b><a href="https://es.wikipedia.org/wiki/Ataque_de_diccionario"><span style="color: #2b00fe;">ataque de diccionario</span></a> si la clave empleada para construir el alfabeto de sustitución es una palabra y ésta está en el diccionario con el que se realiza el ataque.</span></p><p><span style="font-family: inherit;"></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: inherit;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3cjUHKQMcBxnz9A2RUgbIZ74NVD0VsZji-RC2CzXOsAgz1GGrPlS-a3BwE2NpwNkkbbdMbfgcBavvCvqx3vi1tvHA53OZD2lBWCEKcVZbNlV-3v9bZ6Psol7nL2WK_kMtLagUfW-oOX8zT_UwnghlOhsqxzYKPcIrzYddqb2_bQjofvh5PUMW8awr/s165/Criptoan%C3%A1lisis.png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="151" data-original-width="165" height="151" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3cjUHKQMcBxnz9A2RUgbIZ74NVD0VsZji-RC2CzXOsAgz1GGrPlS-a3BwE2NpwNkkbbdMbfgcBavvCvqx3vi1tvHA53OZD2lBWCEKcVZbNlV-3v9bZ6Psol7nL2WK_kMtLagUfW-oOX8zT_UwnghlOhsqxzYKPcIrzYddqb2_bQjofvh5PUMW8awr/s1600/Criptoan%C3%A1lisis.png" width="165" /></a></span></div><span style="font-family: inherit;">Ya puse un post para realizar un ataque de este tipo al <a href="https://es.wikipedia.org/wiki/Cifrado_de_Vigen%C3%A8re"><span style="color: #2b00fe;">cifrado de vigenère</span></a> en el que expliqué en qué consiste y cómo llevarlo a cabo. En el script de esa entrada se utilizan dos </span><span style="font-family: inherit;"><span style="background-color: white; color: #292929;">diccionarios, uno en inglés </span><span style="background-color: white;"><span style="color: #292929;">(</span><a href="https://drive.google.com/file/d/1CiRgex4V2BUHHizVQlUrSgdo__9U2x04/view?usp=sharing"><span style="color: #2b00fe;">english_dict.txt</span></a><span style="color: #292929;">) y otro en español (</span><a href="https://drive.google.com/file/d/19XfBB1romJ8GKRkcqPz8iGogaYaHHUFF/view?usp=sharing"><span style="color: #2b00fe;">espanol_dicc.txt</span></a><span style="color: #292929;">)</span></span><span style="background-color: white; color: #292929;">, que serán también los que utilice el script que voy a poner en este post; también se utiliza el índice de coincidencia, que también lo utiliza este script para realizar un primer filtrado de los textos descifrados, y, adicionalmente, se utilizan archivos de trigramas y palabras frecuentes para afinar la detección de cuando el descifrado produce un texto inteligible, sin embargo en esta ocasión voy a emplear para esto último </span><span style="background-color: white;"><span style="color: #292929;">la </span><span style="background: transparent; cursor: pointer; outline: 0px; text-decoration-line: none;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxix-calificacion-de-la.html"><span style="color: #2b00fe;">calificación o puntuación basada en las estadísticas de tetragramas de la aptitud (<i><span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; cursor: pointer;">'fitness'</span></i><span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; cursor: pointer;">) de los textos</span></span></a></span><span style="color: #292929;"> que se vayan descifrando durante el ataque</span></span><span style="background-color: white; color: #292929;">.</span></span><p></p><p><span style="font-family: inherit;"><span style="background-color: white; color: #292929;">Por tanto, para que el script que voy a poner a continuación func<span style="font-family: inherit;">ione </span></span></span><span style="background-color: white; color: #292929;"><span style="font-family: inherit;">se necesita importar los dos siguientes módulo en el programa principal:</span></span></p><p>#!/usr/bin/env python</p><div><pre><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ÍNDICE DE COINCIDENCIA (IC):
#
# Cálculo del IC de un texto.
#
# http://mikelgarcialarragan.blogspot.com/
def calculo_ic(texto,alfabeto):
# Cálculo de la frecuencia relativa de cada uno de los caracteres del alfabeto en el texto.
frecuencia_relativa=[0 for caracter in alfabeto]
for caracter in alfabeto:
frecuencia_relativa[alfabeto.index(caracter)]=texto.count(caracter)
# Cálculo del número de pares de caracteres iguales que es posible obtener del texto tomando dos de ellos al azar.
pares_caracteres_iguales=[]
for caracter in alfabeto:
pares_caracteres_iguales.append(frecuencia_relativa[alfabeto.index(caracter)]*(frecuencia_relativa[alfabeto.index(caracter)]-1)/2)
# Cálculo del número de pares de caracteres que es posible obtener del texto.
pares_caracteres_posibles = len(texto) *(len(texto)-1)/2
# Cálculo del IC.
ic = 0
for caracter in alfabeto:
ic = ic + (pares_caracteres_iguales[alfabeto.index(caracter)]/pares_caracteres_posibles)
return ic</code>
<br /></pre><p>Y:</p></div><div><p></p><p>#!/usr/bin/env python</p><pre><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# CALIFICACIÓN APTITUD ('FITNESS') DE UN TEXTO:
#
# Califica la semejanza de un texto con respecto a un texto escrito en inglés o español.
#
# http://mikelgarcialarragan.blogspot.com/
import re
from unicodedata import normalize
from math import log10
# TEST FITNESS:
def test_fitness(texto,idioma):
N = 0
probabilidad_ngramas = {}
if idioma == "Inglés":
f_ocurrencias_ngramas = open("english_quadgrams.txt")
else:
f_ocurrencias_ngramas = open("tetragramas_español.txt")
for ngrama in f_ocurrencias_ngramas:
n_grama, ocurrencias = ngrama.split(' ')
probabilidad_ngramas[n_grama] = int(ocurrencias)
N += int(ocurrencias)
f_ocurrencias_ngramas.close()
fitness = 0
for i in range(len(texto)-3):
n_grama = texto[i:i+4]
if n_grama in probabilidad_ngramas.keys():
fitness += log10(float(probabilidad_ngramas[n_grama])/N)
else:
fitness += log10(0.01/N)
return fitness</code>
<br /></pre><p>El <b><span style="color: #45818e;">script</span></b> es el siguiente:</p><p>#!/usr/bin/env python</p><pre><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ATAQUE DE DICCIONARIO AL CIFRADO DE SUSTITUCIÓN SIMPLE MONOALFABÉTICA:
#
# Ataque de diccionario a un criptograma cifrado mediante sustitución simple monoalfabética.
#
# http://mikelgarcialarragan.blogspot.com/
import re
from unicodedata import normalize
from ic import calculo_ic
from fitness_texto import test_fitness
from tqdm import tqdm
# FUNCIÓN DE DESCIFRADO:
def descifrar(alfabeto,criptograma,clave):
texto_claro = ''
i = 0
for caracter in criptograma:
texto_claro = texto_claro + alfabeto[clave.find(caracter)]
i+=1
return texto_claro
def main():
# SELECCIÓN DE IDIOMA:
# Se solicita que se indique el idioma en el que se supone que está escrito el texto en claro.
idioma = ""
while idioma == "":
print ("")
print ("*** SELECCIÓN DE IDIOMA **************************")
print ('1. Inglés.')
print ('2. Español.')
print ("")
opcion = input("Por favor, seleccione el idioma en el que se supone que está escrito el texto en claro: ")
if opcion == "1":
idioma = "Inglés"
alfabeto = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
elif opcion == "2":
idioma = "Español"
alfabeto = "ABCDEFGHIJKLMNÑOPQRSTUVWXYZ"
else:
print ("*** ERROR: Opción no válida.")
print ("")
print ("[+] Idioma:", idioma)
# MENÚ:
# Se presenta el menú para que se seleccione una opción.
salir = False
while not salir:
print ("")
print ("*** MENÚ *****************************************")
print ("1. Ataque de diccionaro al cifrado por sustitución simple monoalfabética.")
print ("2. Salir.")
print ("")
opcion = input("Por favor, seleccione una opción: ")
if opcion == "1":
print ("")
print ("--- ATAQUE DE DICCIONARIO AL CIFRADO POR SUSTITUCIÓN SIMPLE MONOALFABÉTICA:")
# Se introduce el criptograma. Se convierten los caracteres a mayúsculas y
# se eliminan los espacios, las tildes, diéresis, etc.
criptograma = "*"
while not criptograma.isalpha():
criptograma = input("Criptograma a atacar: ").upper()
criptograma = criptograma.replace(' ','')
if idioma == 1:
criptograma = criptograma.replace('Ñ','')
criptograma = re.sub(r"([^n\u0300-\u036f]|n(?!\u0303(?![\u0300-\u036f])))[\u0300-\u036f]+",
r"\1", normalize("NFD", criptograma), 0, re.I)
criptograma = normalize("NFC", criptograma)
if criptograma.isalpha():
print ("[+] Criptograma a atacar:", criptograma)
print ("[+] Tamaño criptograma:", len(criptograma), "caracteres.")
posibles_soluciones = []
if idioma == "Inglés":
f_diccionario = open("english_dict.txt")
else:
f_diccionario = open("espanol_dicc.txt")
diccionario = f_diccionario.readlines()
barra_progreso = tqdm(total = len(diccionario))
for clave in diccionario:
barra_progreso.set_description("Procesando las entradas del diccionario...".format(clave))
barra_progreso.update(1)
clave = clave.strip()
alfabeto_sustitucion = ""
for caracter in range(0, len(clave)):
if clave[caracter] not in alfabeto_sustitucion:
alfabeto_sustitucion += clave[caracter]
for caracter in range(0, len(alfabeto)):
if alfabeto[caracter] not in alfabeto_sustitucion:
alfabeto_sustitucion += alfabeto[caracter]
texto_claro = descifrar(alfabeto,criptograma,alfabeto_sustitucion)
ic = calculo_ic(texto_claro,alfabeto)
if ic > 0.06:
fitness = test_fitness(texto_claro,idioma)
posibles_soluciones.append([ic, fitness, clave, texto_claro])
barra_progreso.close()
f_diccionario.close()
posibles_soluciones.sort(key=lambda x:x[1], reverse=True)
if (len(posibles_soluciones)) > 0:
print("[+] Descifrado más inteligible. 1 .- Clave: ", posibles_soluciones[0][2], "--> Texto en claro: ", posibles_soluciones[0][3])
if (len(posibles_soluciones)) > 1:
mostrar_10_mas = "S"
inicio_siguientes = 1
while mostrar_10_mas == "S":
mostrar_10_mas = input("¿Mostrar los siguientes 10 descifrados más inteligibles ('S')?: ").upper()
if mostrar_10_mas == "S":
fin_siguientes = inicio_siguientes + 10
if fin_siguientes > len(posibles_soluciones):
fin_siguientes = len(posibles_soluciones)
for posible_solucion in range(inicio_siguientes, fin_siguientes):
print(posible_solucion+1, ".- Clave: ", posibles_soluciones[posible_solucion][2], "--> Texto en claro: ", posibles_soluciones[posible_solucion][3])
if fin_siguientes == len(posibles_soluciones):
print("*** FIN: No hay más posibles soluciones.")
mostrar_10_mas = "N"
else:
inicio_siguientes+=10
else:
print("[+] No se han encontrado posibles descifrados inteligibles.")
else:
print ("*** ERROR: El criptograma a atacar sólo debe contener caracteres alfabéticos.")
elif opcion == "2":
print ("*** FIN ******************************************")
salir = True
else:
print ("*** ERROR: Opción no válida.")
if __name__ == '__main__':
main()</code>
<br /></pre><p><b><span style="color: #45818e;">Lo ejecuto</span></b>:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFDBh1OgDi5PkgR3JllF6oCHOk48B6Zm_hCTjWrDlF4fvA9WKG2K9Nh_vGaPvfPlr0DRgVOnbeNFLThNu-K0ierLz2VwUXVSbMwK6lXgI0A2TgdZk54Y2HWRS-K7PixbNGp7K1vUFgKEnjpDfTT18InH77FYvqBOrVtBe4fF2tDHnDR0rpi88qpfVH/s994/sustitucion_ataque_diccionario.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="994" data-original-width="610" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFDBh1OgDi5PkgR3JllF6oCHOk48B6Zm_hCTjWrDlF4fvA9WKG2K9Nh_vGaPvfPlr0DRgVOnbeNFLThNu-K0ierLz2VwUXVSbMwK6lXgI0A2TgdZk54Y2HWRS-K7PixbNGp7K1vUFgKEnjpDfTT18InH77FYvqBOrVtBe4fF2tDHnDR0rpi88qpfVH/s16000/sustitucion_ataque_diccionario.png" /></a></div><p>Tal y como se observa en la figura anterior, se obtiene la clave correcta "SUSTITUCION". El script, debido al tamaño del diccionario empleado, ha tardado 39:58, un tiempo un poco largo, aunque yo creo que asumible, y ha demostrado ser eficaz en el descifrado, aún con un criptograma bastante corto.</p><p>No obstante, lo dicho, recordar que, lógicamente, este método sólo tendrá éxito en caso de que la palabra clave se encuentre en el diccionario utilizado en el ataque.</p></div><p><span style="background-color: white; color: #292929;"><span style="font-family: inherit;"></span></span></p><div class="separator" style="clear: both;"><p><span style="background-color: white; font-family: inherit;"><b><i>Quizás también te interese</i></b>:</span></p><p><span style="font-family: inherit;"><span style="background-color: white;"><span style="color: #292929;"></span></span></span></p><div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/06/criptografia-ccliii-cifrado-por.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0t28skGvSquxFtkDdOD-J0FY2BTtyMbH9xsm-WqUKTS1MX42bnDsUguEZKZlUue9nS-Gq3cEw7TFVbTjSsmkSFMNETTRnlUmCORcsZ-uUXDuuav1VnumhC_89kz0UPp3lW86rInS7fb_E5ehPB-NXCyj_jXIUp39KvdVFC0068sybKo14hk9OL0c1/s16000/Cifrado%20por%20sustituci%C3%B3n%20simple%20monoalfab%C3%A9tica%20en%20python.png" /></a></div></div><div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxix-calificacion-de-la.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcDUt4Hlr6Y7VHYqZTLd38zHdlb138ostcvLkibTBIAKG1cC107t0nDjMLgFoMUdHlOzWEAcxZmGHq43-TG095MnFjmk7p5NonBoGksJUcC5VMrimVyPa6Pp-Ft9J4dQjI-3-H7kXdsz93a8JJvwiyBD85cH387Xii12azf200r1SIIB_A8c1B1eQz/s16000/Calificaci%C3%B3n%20de%20la%20aptitud%20de%20un%20texto%20(fitness)%20en%20python.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/05/criptografia-ccxlviii-ataque-de.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8LOaT9lg1f3PAh1rXMD--JORcYsH2WuToH-Me-RBWCE37yndCFLgbkk_fC6IasZGLvFnpJxRu1ejVel0bfOgRs4Pu-jo4vqhN8ghk0W_jcPPjBw7u23wCyU4_3RIaI2EkEcjkl7zLl9wouom9_J3RSJyTj4jV_ogW2bC8fBehcM-4GFUJ-lRSmLg7/s16000/Ataque%20de%20diccionario%20al%20cifrado%20de%20Vigen%C3%A8re%20en%20python.png" /></a></div></div></div>Mikel García Larraganhttp://www.blogger.com/profile/03118239524461394157noreply@blogger.com0tag:blogger.com,1999:blog-1846493661397027137.post-25128331837953779522023-07-12T20:17:00.006+02:002023-07-15T10:07:19.905+02:00Criptografía (CCLXXIII): Ataque 'Hill Climbing' a la sustitución simple monoalfabética en python<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGT2BCdjCinw8WZfpkt7YsrUyq8Zp3NS1TydwSm1vJ3j6JVWEwqRjdM6zHwqDDkdLCOBHRtW4612OBNgJ_nx6rtV9PYhChZm19uUBd0OmAFvZTcJP-soy2pmVQq2EKGX-SFkyeURe81BwMEsZuy6Wgwr0XHI7lMyaTnn-NZh-Pm5tm3UKObHv5061t/s193/Sustituci%C3%B3n%20monoalfab%C3%A9tica%20simple.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="193" data-original-width="193" height="193" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGT2BCdjCinw8WZfpkt7YsrUyq8Zp3NS1TydwSm1vJ3j6JVWEwqRjdM6zHwqDDkdLCOBHRtW4612OBNgJ_nx6rtV9PYhChZm19uUBd0OmAFvZTcJP-soy2pmVQq2EKGX-SFkyeURe81BwMEsZuy6Wgwr0XHI7lMyaTnn-NZh-Pm5tm3UKObHv5061t/s1600/Sustituci%C3%B3n%20monoalfab%C3%A9tica%20simple.png" width="193" /></a></div>Continúo poniendo scripts de programación en python para automatizar tareas que tengan relación con la <a href="https://es.wikipedia.org/wiki/Criptograf%C3%ADa"><span style="color: #2b00fe;">criptografía</span></a>.<p></p><p></p><p></p><p></p><p><span style="font-family: inherit;">Ya puse una <a href="http://mikelgarcialarragan.blogspot.com/2023/06/criptografia-ccliii-cifrado-por.html"><span style="color: #2b00fe;">entrada</span></a> con un script en python para cifrar y descifrar textos en claro y criptogramas, respectivamente, utilizando la <a href="https://es.wikipedia.org/wiki/Cifrado_por_sustituci%C3%B3n#Monoalfab%C3%A9tico"><span style="color: #2b00fe;">sustitución simple monoalfabética</span></a>, y también puse <a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxii-ataque-hill.html"><span style="color: #2b00fe;">un post</span></a> con la explicación de la implementación del <a href="https://es.wikipedia.org/wiki/Algoritmo_hill_climbing"><span style="color: #2b00fe;">algoritmo <i>'Hill Climbing'</i></span></a> que me propongo realizar <span style="background-color: white;"><span style="color: #292929;">para atacar criptogramas cifrados mediante este </span><a href="https://es.wikipedia.org/wiki/Criptosistema"><span style="color: #2b00fe;">criptosistema</span></a><span style="color: #292929;"> </span></span></span><span style="font-family: inherit;"><span style="background-color: white; color: #292929;">utilizand</span><span style="background-color: white;"><span style="color: #292929;">o la </span><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxix-calificacion-de-la.html"><span style="color: #2b00fe;">calificación o puntuación basada en las estadísticas de tetragramas de la aptitud (<i><span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; cursor: pointer;">'fitness'</span></i><span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; cursor: pointer;">) de los textos</span></span></a><span style="color: #292929;"> que se vayan descifrando durante el ataque</span></span></span><span style="font-family: inherit;">.</span></p><div class="separator" style="clear: both; text-align: center;"><span><b></b></span></div><div><p><span style="color: #45818e;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQlx2xB5Nt9BgfR4D3bC2l03SlgdsEubii63IifADu1Tog8nrMm9dC2DceMLiVr8CpoNXQeg90HuW30xqwV_odKUYvzqifWtvP03dnRcU075MQyysZItjzv0_sW4INxTjG1IsBOeRM_9wtMYMtodRncfng0UWNUXMzz-uT7v2Bw9pC_qCf3avy9zAX/s165/Criptoan%C3%A1lisis.png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="151" data-original-width="165" height="151" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQlx2xB5Nt9BgfR4D3bC2l03SlgdsEubii63IifADu1Tog8nrMm9dC2DceMLiVr8CpoNXQeg90HuW30xqwV_odKUYvzqifWtvP03dnRcU075MQyysZItjzv0_sW4INxTjG1IsBOeRM_9wtMYMtodRncfng0UWNUXMzz-uT7v2Bw9pC_qCf3avy9zAX/s1600/Criptoan%C3%A1lisis.png" width="165" /></a></span></p><p style="text-align: left;">Para que el script con este ataque funcione se necesita importar el siguiente módulo en el programa principal, <span style="font-family: inherit;">que se encargará, precisamente, de <span style="background-color: white;">la calificación de la aptitud <i>('fitness')</i> de los textos que se vayan obteniendo en el descifrado con respecto </span><span style="background-color: white;">al idioma en el que se escribió el texto en claro, es decir, de la obtención de una calificación o puntuación de la mayor o menor semejanza de un texto dado con respecto a un texto escrito en dicho idioma</span>:</span></p><p></p><p>#!/usr/bin/env python</p><pre><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# CALIFICACIÓN APTITUD ('FITNESS') DE UN TEXTO:
#
# Califica la semejanza de un texto con respecto a un texto escrito en inglés o español.
#
# http://mikelgarcialarragan.blogspot.com/
import re
from unicodedata import normalize
from math import log10
# TEST FITNESS:
def test_fitness(texto,idioma):
N = 0
probabilidad_ngramas = {}
if idioma == "Inglés":
f_ocurrencias_ngramas = open("english_quadgrams.txt")
else:
f_ocurrencias_ngramas = open("tetragramas_español.txt")
for ngrama in f_ocurrencias_ngramas:
n_grama, ocurrencias = ngrama.split(' ')
probabilidad_ngramas[n_grama] = int(ocurrencias)
N += int(ocurrencias)
f_ocurrencias_ngramas.close()
fitness = 0
for i in range(len(texto)-3):
n_grama = texto[i:i+4]
if n_grama in probabilidad_ngramas.keys():
fitness += log10(float(probabilidad_ngramas[n_grama])/N)
else:
fitness += log10(0.01/N)
return fitness</code>
<br /></pre><p>El <b><span style="color: #45818e;">script</span></b> es el siguiente:</p><p>#!/usr/bin/env python</p><pre><code class="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ATAQUE HILL CLIMBING AL CIFRADO DE SUSTITUCIÓN SIMPLE MONOALFABÉTICA:
#
# Ataque utilizando el algoritmo hill climbing con estadística de tetragramas a un criptograma cifrado
# mediante sustitución simple monoalfabética.
#
# http://mikelgarcialarragan.blogspot.com/
import re
from unicodedata import normalize
from fitness_texto import test_fitness
import random
from tqdm import tqdm
# FRECUENCIA RELATIVA MONOGRAMAS:
def frecuencia_relativa_monogramas(alfabeto,texto):
frecuencias_relativas=[]
for caracter in alfabeto:
frecuencias_relativas.append([caracter,texto.count(caracter)])
frecuencias_relativas.sort(key=lambda x:x[1], reverse=True)
return frecuencias_relativas
# FUNCIÓN DE DESCIFRADO:
def descifrar(alfabeto,criptograma,clave):
texto_claro = ''
i = 0
for caracter in criptograma:
texto_claro = texto_claro + alfabeto[clave.find(caracter)]
i+=1
return texto_claro
def main():
# SELECCIÓN DE IDIOMA:
# Se solicita que se indique el idioma en el que se supone que está escrito el texto en claro.
idioma = ""
while idioma == "":
print ("")
print ("*** SELECCIÓN DE IDIOMA **************************")
print ('1. Inglés.')
print ('2. Español.')
print ("")
opcion = input("Por favor, seleccione el idioma en el que se supone que está escrito el texto en claro: ")
if opcion == "1":
idioma = "Inglés"
alfabeto = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
monogramas = ['E','T','A','O','I','N','S','H','R','D','L','C','U','M','W','F','G','Y','P','B','V','K','J','X','Q','Z']
elif opcion == "2":
idioma = "Español"
alfabeto = "ABCDEFGHIJKLMNÑOPQRSTUVWXYZ"
monogramas = ['E','A','O','S','R','N','I','D','L','C','T','U','M','P','B','G','Y','V','Q','H','F','Z','J','Ñ','X','W','K']
else:
print ("*** ERROR: Opción no válida.")
print ("")
print ("[+] Idioma:", idioma)
# MENÚ:
# Se presenta el menú para que se seleccione una opción.
salir = False
while not salir:
print ("")
print ("*** MENÚ *****************************************")
print ("1. Ataque hill climbing a un criptograma cifrado mediante sustitución simple monoalfabética.")
print ("2. Salir.")
print ("")
opcion = input("Por favor, seleccione una opción: ")
if opcion == "1":
print ("")
print ("--- ATAQUE HILL CLIMBING AL CIFRADO DE SUSTITUCIÓN SIMPLE MONOALFABÉTICA:")
# Se introduce el criptograma. Se convierten los caracteres a mayúsculas y
# se eliminan los espacios, las tildes, diéresis, etc.
criptograma = "*"
while not criptograma.isalpha():
criptograma = input("Criptograma a atacar: ").upper()
criptograma = criptograma.replace(' ','')
if idioma == 1:
criptograma = criptograma.replace('Ñ','')
criptograma = re.sub(r"([^n\u0300-\u036f]|n(?!\u0303(?![\u0300-\u036f])))[\u0300-\u036f]+",
r"\1", normalize("NFD", criptograma), 0, re.I)
criptograma = normalize("NFC", criptograma)
if criptograma.isalpha():
print ("[+] Criptograma a atacar:", criptograma)
print ("[+] Tamaño criptograma:", len(criptograma), "caracteres.")
frecuencias_relativas = frecuencia_relativa_monogramas(alfabeto,criptograma)
nueva_clave = clave_mejor = ""
for i in range(0, len(alfabeto)):
nueva_clave += frecuencias_relativas[monogramas.index(alfabeto[i])][0]
fitness_mejor = -9999999
limite_maximo_iteraciones = 5000
limite_maximo_iteraciones_sin_mejora = limite_maximo_iteraciones // 2
barra_progreso = tqdm(total = limite_maximo_iteraciones)
for i in range(0, limite_maximo_iteraciones):
barra_progreso.set_description("Descifrando y calculando 'fitness'...".format(nueva_clave))
barra_progreso.update(1)
texto_claro = descifrar(alfabeto,criptograma,nueva_clave)
fitness = test_fitness(texto_claro,idioma)
if fitness > fitness_mejor:
clave_mejor = nueva_clave
fitness_mejor = fitness
n_iteraciones_sin_mejora = 0
else:
n_iteraciones_sin_mejora += 1
if n_iteraciones_sin_mejora > limite_maximo_iteraciones_sin_mejora:
break
n = m = random.randint(0, len(alfabeto)-1)
while n == m:
m = random.randint(0, len(alfabeto)-1)
nueva_clave = list(clave_mejor)
nueva_clave[n%len(alfabeto)], nueva_clave[m%len(alfabeto)] = nueva_clave[m%len(alfabeto)], nueva_clave[n%len(alfabeto)]
nueva_clave = ''.join(nueva_clave)
barra_progreso.close()
if n_iteraciones_sin_mejora > limite_maximo_iteraciones_sin_mejora:
print("[+] Fin: se ha superado el límite máximo de iteraciones sin mejora.")
print("[+] Nº iteración realizadas:", i+1)
print("[+] Nº iteraciones sin mejora a la finalización del algoritmo:", n_iteraciones_sin_mejora-1)
print("[+] Mejor puntuación aptitud texto descifrado:", fitness_mejor)
print("[+] Mejor clave encontrada para el descifrado:", clave_mejor)
texto_claro = descifrar(alfabeto,criptograma,clave_mejor)
print("[+] Texto en claro descifrado con la mejor clave encontrada:", texto_claro)
else:
print ("*** ERROR: El criptograma a atacar sólo debe contener caracteres alfabéticos.")
elif opcion == "2":
print ("*** FIN ******************************************")
salir = True
else:
print ("*** ERROR: Opción no válida.")
if __name__ == '__main__':
main()</code>
<br /></pre><p><b><span style="color: #45818e;">Lo ejecuto</span></b> para atacar varios criptogramas de diferentes tamaños, con objeto de comprobar su eficacia y eficiencia:</p><p>Consideraciones preliminares: En el script se establecen en 5.000 el límite máximo de iteraciones a realizar y en la mitad (2.500) el número de iteraciones a realizar sin mejora de la aptitud (<i>'fitness'</i>) de los textos descifrados. Ambos parámetros pueden ser cambiados a conveniencia.</p><p><b><span style="color: #45818e;">1.- Criptograma</span></b>: "DROXUSWFIXCLUCDÑOULXCEFSFXAQAWUWQOUFRDAQRNDWFEFEDOULXCEFSFXDÑMQDQRUECEDAEDWDKWFSÑCRFAFRAQAWUWQUECAOFRWDKWFOULXCEFAUIQUDREFQRAUAWDNCXDIQÑCXÑCAQRUECEDASQDEDRADXQRCAFÑCÑDWXCDÑOCAFNCAOFNQRSCXDAEDÑDWXCAWXUFAEDÑDWXCANDTOÑCAEDÑFCRWDXUFXDRWXDFWXFADÑXDODSWFXEDAOULXCDÑWDKWFXDCÑUTCREFÑCAQAWUWQOUFRURPDXACÑFAOULXCEFASFXAQAWUWQOUFRAFROFNSCXCJÑDACÑFAOULXCEFASFXWXCRASFAUOUFRDRQROULXCEFSFXWXCRASFAUOUFRÑCAQRUECEDAEDÑWDKWFSÑCRFAFROCNJUCECAQACREFQRCFXEDRCOUFREULDXDRWDGRFXNCÑNDRWDJCAWCRWDOFNSÑDHCSDXFÑCAQRUECEDADRAUNUANCARFAFRNFEULUOCECASFXDÑOFRWXCXUFDRQROULXCEFSFXAQAWUWQOUFRÑCAQRUECEDAEDÑWDKWFSÑCRFNCRWUDRDRDÑNUANFFXEDRÑFMQDBCODDAAQAWUWQUXÑCASXFSUCAQRUECEDAEDÑWDKWFSÑCRFDKUAWDREUPDXAFAWUSFAEDOULXCEFASFXAQAWUWQOUFRAUDÑOULXCEFFSDXCAFJXDÑDWXCAAUNSÑDAADEDRFNURCOULXCEFSFXAQAWUWQOUFRAUNSÑDAUFSDXCAFJXDIXQSFAEDÑDWXCAADEDRFNURCSFÑUIXCLUOFADEUODMQDQROULXCEFDANFRFCÑLCJDWUOFAUQACQRCAQAWUWQOUFRLUHCSCXCWFEFDÑNDRACHDNUDRWXCAMQDADEUODMQDDASFÑUCÑLCJDWUOFAUQACEULDXDRWDAAQAWUWQOUFRDADREULDXDRWDANFNDRWFAEDÑNDRACHDQRWUSFDASDOUCÑEDOULXCEFSFÑUCÑLCJDWUOFAFRÑFABFNFLFRFADRÑFAMQDQRCQRUECEEDÑWDKWFSÑCRFDAAQAWUWQUECSFXQRCEDDRWXDPCXUCASFAUJUÑUECEDADKUAWDRWDADRÑFAOULXCEFAEDAQAWUWQOUFRAUNSÑDQROCXCOWDXDRDÑWDKWFFXUIURCÑDAXDDNSÑCTCEFSFXQROCXCOWDXEDWDXNURCEFEDÑCÑLCJDWFEDAQAWUWQOUFRDAEDOUXADDAWCJÑDODRSCXDHCAEDOCXCOWDXDAEFREDDÑADIQREFDÑDNDRWFEDÑCSCXDHCDAWCJÑDODDÑOCXCOWDXMQDAQAWUWQGDCÑSXUNDXDÑDNDRWFEDÑCSCXDHCCPDODADÑAUAWDNCQACDÑNUANFCÑLCJDWFSCXCDÑWDKWFDROÑCXFGSCXCDÑWDKWFOULXCEFDAWFSDXNUWDCSXFPDOBCXDÑFXEDREDLURUEFSFXÑFACÑLCJDWFASCXCCAULCOUÑUWCXÑCEDAOXUSOUFREDÑFACÑIFXUWNFAECREFADCAUÑFAÑÑCNCEFAOULXCEFAEDCÑLCJDWFURPDXWUEFGEDCÑLCJDWFEDASÑCTCEFFWXCAPDODADÑFXEDRRFADQWUÑUTCGADEUODMQDDAQRCÑLCJDWFNDTOÑCEFFQRCÑLCJDWFAURXCRIFADEUODMQDQRAUAWDNCEDOULXCEFEDAQAWUWQOUFRAUNSÑDDANFRFCÑLCJDWUOFOQCREFOCECOCXCOWDXADAQAWUWQGDAUDNSXDSFXQREDWDXNURCEFOCXCOWDXEDÑCÑLCJDWFEDÑWDKWFOULXCEFDRDAWDWUSFEDOULXCEFACÑCÑLCJDWFQACEFSCXCDÑWDKWFOULXCEFADÑDÑÑCNCCÑLCJDWFEDAQAWUWQOUFRAUOCECAUNJFÑFEDÑWDKWFDROÑCXFDAAQAWUWQUEFSFXQRAUNJFÑFEUAWURWFAEDÑWDKWFOULXCEFGADCRDÑRQNDXFEDAUNJFÑFADÑRQNDXFEDAUNJFÑFAEDÑWDKWFDROÑCXFPDNFAMQDDÑSFAUJÑDRQNDXFEDAQAWUWQOUFRDAMQDADSQDEDREDLURUXDADÑRQNDXFSFAUJÑDEDSDXNQWCOUFRDA"</p><p style="clear: both; text-align: left;">Tamaño: <b><span style="color: #45818e;">2.131</span></b> caracteres.<br /></p><p style="text-align: left;"><span style="font-family: inherit;">Clave empleada en el cifrado: <b><span style="color: #45818e;">"CJOEDLIBUPZÑNRVFSMXAWQHYKGT"</span></b></span></p><p style="text-align: left;"></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqOt3i4apkuI0BfaP--O3lVcdBqBDezA2o-tL_9TYMoX5VokclN8eS3WlrT3DT_xvS2HSOEUo8glJbby39cisBFusAmTK24adhjzq0XMJXWtKar3HWZECjKLJ4lBp0jstY5NlDb6EgB-Dk28QZhRWQFtFx0o_hP5YUBGZ_UNyiZmTC313pZLSw5F5H/s1438/sustitucion_ataque_hillclimbing_1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1438" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqOt3i4apkuI0BfaP--O3lVcdBqBDezA2o-tL_9TYMoX5VokclN8eS3WlrT3DT_xvS2HSOEUo8glJbby39cisBFusAmTK24adhjzq0XMJXWtKar3HWZECjKLJ4lBp0jstY5NlDb6EgB-Dk28QZhRWQFtFx0o_hP5YUBGZ_UNyiZmTC313pZLSw5F5H/s16000/sustitucion_ataque_hillclimbing_1.png" /></a></div><p></p><p style="text-align: left;">Tiempo de ejecución: <b><span style="color: #45818e;">02:42</span></b></p><p style="text-align: left;">Mejor clave encontrada: <b><span style="color: #45818e;">"CJOEDLIBUHZÑNRVFSMXAWQPYKGT"</span></b></p><p style="text-align: left;">Comentarios tras el ataque realizado: <b><span style="color: #45818e;">La clave que se obtiene es la correcta</span></b> (los dos únicos caracteres de ella que no se corresponden a la clave original son los correspondientes a la "J" y "W" del texto plano, que están intercambiados, pero ninguno de ellos aparece en el texto en claro), por lo que <b><span style="color: #45818e;">el criptograma se descifra correctamente</span></b> al primer intento de ataque.</p><p><b style="color: #45818e;">2.- Criptograma</b>: "KATMUDSPBMXZUXKGTUZMXIPDPMJÑJSUSÑTUPAKJÑALKSPIPIKTUZMXIPDPMKGFÑKÑAUIXIKJIKSKYSPDGXAPJPAJÑJSUSÑUIXJTPASKYSPTUZMXIPJUBÑUKAIPÑAJUJSKLXMKBÑGXMGXJÑAUIXIKJDÑKIKAJKMÑAXJPGXGKSMXKGTXJPLXJTPLÑADXMKJIKGKSMXJSMUPJIKGKSMXJLKOTGXJIKGPXASKMUPMKASMKPSMPJKGMKTKDSPMIKJTUZMXKGSKYSPMKXGUOXAIPGXJÑJSUSÑTUPAUAVKMJXKAÑATUZMXIPDPMSMXAJDPJUTUPAGXJÑAUIXIKJIKGSKYSPDGXAPJPATXLWUXIXJÑJXAIPÑAXPMIKAXTUPAIUZKMKASKHAPMLXGLKASKWXJSXASKTPLDGKCXDKMPGXJÑAUIXIKJKAJULUJLXJAPJPALPIUZUTXIXJDPMKGTPASMXMUPKAÑATUZMXIPDPMJÑJSUSÑTUPAGXJÑAUIXIKJIKGSKYSPDGXAPLXASUKAKAKGLUJLPPMIKAGPFÑKNXTKKJJÑJSUSÑUMGXJDMPDUXJÑAUIXIKJIKGSKYSPDGXAP"</p><p style="clear: both;">Tamaño: <b><span style="color: #45818e;">589</span></b> caracteres.<br /></p><p><span style="font-family: inherit;">Clave empleada en el cifrado: <b><span style="color: #45818e;">"XWTIKZBNUCRGLAEPDFMJSÑVQYHO"</span></b></span></p><p></p></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvsPnJK4HYs47QH__n6PYI5Y-LHgoGdfaAPM20E1GoWJ3VAnDdy2Rvy-JKtnNjwy90Tlg1c1Xu82jKjkunbp2gWdSxQMu0DCJ_b7jxIMNjG4J-uukLMf5SAm0ayI5raTvJ8zpK3wVWUkbceJzqniWKqM9qBH62u7-NbOA9KY9nX3BZsftctTUin-1v/s658/sustitucion_ataque_hillclimbing_2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="658" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvsPnJK4HYs47QH__n6PYI5Y-LHgoGdfaAPM20E1GoWJ3VAnDdy2Rvy-JKtnNjwy90Tlg1c1Xu82jKjkunbp2gWdSxQMu0DCJ_b7jxIMNjG4J-uukLMf5SAm0ayI5raTvJ8zpK3wVWUkbceJzqniWKqM9qBH62u7-NbOA9KY9nX3BZsftctTUin-1v/s16000/sustitucion_ataque_hillclimbing_2.png" /></a></div><p>Tiempo de ejecución: <span style="color: #45818e;"><b>01:47</b></span></p><p>Mejor clave encontrada: <span style="color: #45818e;"><b>"XWTIKZBNUCRGLAEPDFMJSÑVQYHO"</b></span></p><p>Comentarios tras el ataque realizado: <b><span style="color: #45818e;">La clave que se obtiene es la correcta</span></b>, por lo que <b><span style="color: #45818e;">el criptograma se descifra correctamente</span></b> al primer intento de ataque.</p><div><p><b style="color: #45818e;">3.- Criptograma</b>:<b style="color: #45818e;"> </b>"ZUSIXERYQIDHXDZÑSXHIDOYEYIWTWRXRTSXYUZWTUAZRYOYOZSXHIDOYEYIZÑBTZTUXODOZWOZRZPRYEÑDUYWYUWTWRXRTXODWSYURZPRYSXHIDOYWXQTXZUOYTUWXWRZADIZQTÑDIÑDWTUXODOZWETZOZUWZITUDWYÑDÑZRIDZÑSDWYADWSYATUEDIZWOZÑZRIDWRIXYWOZÑZRIDWAZMSÑDWOZÑYDURZIXYIZURIZYRIYWZÑIZSZERYIOZWSXHIDZÑRZPRYIZDÑXMDUOYÑDWTWRXRTSXYUXUNZIWD"</p><p style="clear: both;">Tamaño: <b><span style="color: #45818e;">294</span></b> caracteres.<br /></p><p><span><span style="font-family: inherit;">Clave empleada en el cifrado: </span><span style="color: #45818e;"><b style="font-family: inherit;">"</b><b>DJSOZHQFXGKÑAULYEBIWRTNVPCM</b><b style="font-family: inherit;">"</b></span></span></p><p></p></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXatEf9b6uhG94wkXmTy29hb8GNfwF1VitQuY7w9oaMtyeWIuoRPS2mS7YEDU0hMCO7vUs-5OIkOxhQpfudGz-P9xvxEOsIz6D24bmc_Dvhy_IkxP1zVsAiFanBcXYjyQ8WpOHAv8X-dI40L9rPbslsvT3y_Uz8XJ1030z6iwVFI64iWt660BSWI1G/s622/sustitucion_ataque_hillclimbing_3.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="490" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXatEf9b6uhG94wkXmTy29hb8GNfwF1VitQuY7w9oaMtyeWIuoRPS2mS7YEDU0hMCO7vUs-5OIkOxhQpfudGz-P9xvxEOsIz6D24bmc_Dvhy_IkxP1zVsAiFanBcXYjyQ8WpOHAv8X-dI40L9rPbslsvT3y_Uz8XJ1030z6iwVFI64iWt660BSWI1G/s16000/sustitucion_ataque_hillclimbing_3.png" /></a></div><p>Tiempo de ejecución: <b><span style="color: #45818e;">02:28</span></b></p><p>Mejor clave encontrada: <span style="color: #45818e;"><b>"</b></span><span style="color: #45818e;"><b>DFSOZHQCXKVÑAUJYEBIWRTNLGPM</b></span><b style="color: #45818e;">"</b></p><p>Comentarios tras el ataque realizado: <b><span style="color: #45818e;">La clave que se obtiene no es del todo correcta</span></b> (hay varios caracteres que no se corresponden con la clave original que no tienen incidencia en el descifrado del criptograma por no aparecer en el texto en claro. El único carácter incorrecto que sí incide en que el texto plano obtenido no sea del todo correcto es el correspondiente a la "X", habiéndose obtenido en el texto en claro la "Y" en su lugar). No obstante lo dicho, <b><span style="color: #45818e;">el descifrado del criptograma es casi correcto</span></b> al primer intento de ataque.</p><div><p><b style="color: #45818e;">4.- Criptograma: </b>"DZUHPWGAÑHMLPMDXUPLHMYAWAHNFNGPGFUPAZDNFZVDGAYAYDUPLHMYAWAHDXJFDFZPYMYDNYDGDTGAWXMZANAZNFNGPGFPYMNUAZGDTGAUPLHMYANPÑFPDZYAFZNPNGDVMHDÑFXMH"</p><p style="clear: both;">Tamaño: <b><span style="color: #45818e;">138</span></b> caracteres.<br /></p><p><span style="font-family: inherit;">Clave empleada en el cifrado: <b><span style="color: #45818e;">"MKUYDLÑIPOCXVZEAWJHNGFSRTBQ"</span></b></span></p><p></p></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8i6x-Hr-xdfXubBZskYcCxJxCIOyi9DQHf_y5j4V9FLXAi_pqNGqwysYhw4kKmKzOgXrX3P5OpKcW_-MjPppn5F-lfUax4ALcrvjprjqHUW2zIwfPyNwx4fT6pHN0O6l2eg8s5HMcA_yi2hBg2lrD47L-v1dF1Yez9RWd-l6u4R-O08AsJf5aaqxv/s622/sustitucion_ataque_hillclimbing_4.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="418" data-original-width="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8i6x-Hr-xdfXubBZskYcCxJxCIOyi9DQHf_y5j4V9FLXAi_pqNGqwysYhw4kKmKzOgXrX3P5OpKcW_-MjPppn5F-lfUax4ALcrvjprjqHUW2zIwfPyNwx4fT6pHN0O6l2eg8s5HMcA_yi2hBg2lrD47L-v1dF1Yez9RWd-l6u4R-O08AsJf5aaqxv/s16000/sustitucion_ataque_hillclimbing_4.png" /></a></div><p>Tiempo de ejecución: <b><span style="color: #45818e;">02:26</span></b></p><p>Mejor clave encontrada: <span style="color: #45818e;"><b>"</b></span><span style="color: #45818e;"><b>AWUYDEÑOPBSXVZQMLJHNGFCRKTI</b></span><b style="color: #45818e;">"</b></p><p>Comentarios tras el ataque realizado: <span style="color: #45818e;"><b>La clave que se obtiene no es la correcta</b></span>, pero, tal y como se puede observar en la figura anterior, el texto en claro que se obtiene es bastante legible, por lo que <b><span style="color: #45818e;">es posible depurar manualmente la clave obtenida hasta dar con la correcta y descifrar el criptograma correctamente.</span></b></p><p style="clear: both; text-align: left;">Tras estas pruebas y algunas más que he realizado, <span><b style="color: #45818e;">concluyo que este método de ataque es bastante eficaz</b>, sobre todo con criptogramas no muy cortos,</span> <b><span style="color: #45818e;">y eficiente</span></b> (aunque seguro que se puede mejorar el algoritmo que he implementado). En cualquier caso, si no se obtuviera el texto en claro correcto tras un primer intento de ataque, tras reintentar éste, no hace falta que sea en muchas ocasiones, suele darse con el texto plano correcto o con uno parcialmente descifrado que nos permita hallar la clave correcta.</p><div class="separator" style="clear: both; text-align: left;"><p><span style="background-color: white; font-family: inherit;"><b><i>Quizás también te interese</i></b>:</span></p><p><span style="font-family: inherit;"><span style="background-color: white;"><span style="color: #292929;"></span></span></span></p><div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxii-ataque-hill.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvsjK4CyKaiMIcAtnUSQNtxCOtqB_WfWGHIWHwrlo0mZjro7cl4PKDYqorPeiv6QaS4FchWsW2JiTUMYVUWf9KqB1cqjGke6v2_1pY1Lp2LtagPZjmUWlw_cNvvDyRFzUkbLP3AWX_HRIO3zbbwvfC9v1o4QuWliOpa-9njb2tt2XUlmTasWv5unGm/s16000/Ataque%20Hill%20Climbing%20a%20la%20sustituci%C3%B3n%20simple%20monoalfab%C3%A9tica.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxi-el-algoritmo-hill.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXMfMuluYwZ5hD7BC0C8gaHwcuw31yrNFisFeHaf34dZOtoAqWJKk413PoQRmSwOcnYx6B3CHbAaVJIyUDrrTcjdtQJXsDJ_kQEUq87ipEyxIYBQD6EoB2Z_afiGUWqa2JlJeRvH9ewlVdiFLZ2FENyJHs0m1WWM8m8Emb5msqh3Oivh__UbIFYnr5/s16000/El%20algoritmo%20Hill%20Climbing.png" /></a></div></div><div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxix-calificacion-de-la.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcDUt4Hlr6Y7VHYqZTLd38zHdlb138ostcvLkibTBIAKG1cC107t0nDjMLgFoMUdHlOzWEAcxZmGHq43-TG095MnFjmk7p5NonBoGksJUcC5VMrimVyPa6Pp-Ft9J4dQjI-3-H7kXdsz93a8JJvwiyBD85cH387Xii12azf200r1SIIB_A8c1B1eQz/s16000/Calificaci%C3%B3n%20de%20la%20aptitud%20de%20un%20texto%20(fitness)%20en%20python.png" /></a></div></div></div>Mikel García Larraganhttp://www.blogger.com/profile/03118239524461394157noreply@blogger.com0tag:blogger.com,1999:blog-1846493661397027137.post-26133596291363440842023-07-12T09:10:00.004+02:002023-07-15T10:06:58.108+02:00Criptografía (CCLXXII): Ataque 'Hill Climbing' a la sustitución simple monoalfabética <p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6CddnvY55fUe1QLOV4YRRdKGnmHxyW18KO_Nk4D-AgfnnIC5oejhKb_ywoa0dd-AikD7Z5xLZ3VcI80_j2Auk7tpNY8dKjUgu_EM0DLGrTPQY8JUjwxha5aVH9f8SmdvJxKWW4EuTKLZY02LCRcfSGO3tjziA05G-RN9p4-oLk9NEWVIFeVhxfvlL/s308/Hill%20Climbing.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="150" data-original-width="308" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6CddnvY55fUe1QLOV4YRRdKGnmHxyW18KO_Nk4D-AgfnnIC5oejhKb_ywoa0dd-AikD7Z5xLZ3VcI80_j2Auk7tpNY8dKjUgu_EM0DLGrTPQY8JUjwxha5aVH9f8SmdvJxKWW4EuTKLZY02LCRcfSGO3tjziA05G-RN9p4-oLk9NEWVIFeVhxfvlL/s1600/Hill%20Climbing.png" width="308" /></a></div>Decía en <a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxi-el-algoritmo-hill.html"><span style="color: #2b00fe;">este post </span></a>que iba a desarrollar el <a href="https://es.wikipedia.org/wiki/Algoritmo_hill_climbing"><span style="color: #2b00fe;">algoritmo <i>'Hill Climbing'</i></span></a> para atacar criptogramas cifrados mediante <a href="https://es.wikipedia.org/wiki/Cifrado_por_sustituci%C3%B3n#Monoalfab%C3%A9tico"><span style="color: #2b00fe;">sustitución simple monoalfabética</span></a> utilizand<span style="font-family: inherit;">o <span style="background-color: white;"><span style="color: #292929;">la </span><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxix-calificacion-de-la.html"><span style="color: #2b00fe;">calificación o puntuación basada en las estadísticas de tetragramas de la aptitud (</span></a></span><i style="background-color: white;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxix-calificacion-de-la.html"><span style="color: #2b00fe;">'fitness'</span></a></i><span style="background-color: white;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxix-calificacion-de-la.html"><span style="color: #2b00fe;">) de los textos</span></a><span style="color: #292929;"> que se vayan descifrando con las sucesivas claves a probar. Todo ello, con objeto de obtener la clave correcta empleada en el cifrado.</span></span></span><p></p><p><span style="font-family: inherit;"><span style="background-color: white;"><span style="color: #292929;">El algoritmo que voy a implementar puede representarse </span><b><span style="color: #45818e;">gráficamente</span></b><span style="color: #292929;"> de la siguiente manera:</span></span></span></p><p><span style="font-family: inherit;"><span style="background-color: white;"></span></span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaPrKB2nZLFd0O_EHUVTRqT1wsWZm5n4fjrbaktnXBALJP_Ih9ntfWSEjkax1mfUcAkpcl3-I_4X1sYTn9bP1FT6TmnjJDtYJNG8bhBG2PlgKL-nEVoRr1RkRZaPW4TRRNJeqFVDJbUPkinGMCOhQOwLCb4YAUaLFwVh6UhoQZ2nJlI34wRjkkgLQR/s768/Hill%20Climbing.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="768" data-original-width="620" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaPrKB2nZLFd0O_EHUVTRqT1wsWZm5n4fjrbaktnXBALJP_Ih9ntfWSEjkax1mfUcAkpcl3-I_4X1sYTn9bP1FT6TmnjJDtYJNG8bhBG2PlgKL-nEVoRr1RkRZaPW4TRRNJeqFVDJbUPkinGMCOhQOwLCb4YAUaLFwVh6UhoQZ2nJlI34wRjkkgLQR/s16000/Hill%20Climbing.png" /></a></div><p></p><p><span style="font-family: inherit;"><span style="background-color: white;">1.- En primer lugar, <b><span style="color: #45818e;">se generará la clave con la que se iniciará la secuencia de descifrados</span></b>, pero no será aleatoria, sino que como clave inicial se generará aquella <b><span style="color: #45818e;">conforme a la frecuencia relativa de los caracteres (monogramas) del criptograma con respecto a las letras del idioma en el que esté escrito el texto en claro</span></b>.</span></span></p><p><span style="font-family: inherit;"><span style="background-color: white;">Es decir, si el idioma es el español, la letra "E" de la clave (el alfabeto de sustitución) será la que aparezca con mayor frecuencia en el criptograma, la letra "A" del alfabeto de la clave se corresponderá con la segunda con mayor frecuencia de aparición en el criptograma, y así sucesivamente.</span></span></p><p><span style="font-family: inherit;"><span style="background-color: white;">El orden de frecuencia de aparición de las letras (de mayor a menor) considerado para el español e inglés es el siguiente (ver <a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxvii-criptoanalisis_2.html"><span style="color: #2b00fe;">este post</span></a>):</span></span></p><p><span style="font-family: inherit;"><span style="background-color: white;">a) Español:</span></span></p><p><span style="background-color: white;">['E','A','O','S','R','N','I','D','L','C','T','U','M','P','B','G','Y','V','Q','H','F','Z','J','Ñ','X','W','K']</span></p><p><span style="font-family: inherit;"><span style="background-color: white;">b) Inglés:<br /></span></span></p><p style="text-align: left;"><span style="background-color: white;"><span style="color: #292929;">['E','T','A','O','I','N','S','H','R','D','L','C','U','M','W','F','G','Y','P','B','V','K','J','X','Q','Z']</span></span></p><p></p><p><span style="font-family: inherit;"><span style="background-color: white;"><span style="color: #292929;">además, </span><b><span style="color: #45818e;">se inicializarán: la mejor calificación o puntuación de la aptitud del texto descifrado (<i>'fitness'</i>) y el límite máximo de iteraciones sin mejora a realizar</span></b><span style="color: #292929;"> antes de dar por finalizada la ejecución del algoritmo.</span></span></span></p><p><span style="font-family: inherit;"><span style="background-color: white;"><span style="color: #292929;">2.- </span></span></span><span style="color: #45818e; font-family: inherit;"><span style="background-color: white;"><b>Se obtiene </b></span></span><span style="background-color: white;"><b><span style="color: #45818e;">el texto descifrado y se califica su aptitud (<i>'fitness'</i>)</span></b><span style="color: #292929;">.</span></span></p><p><span style="font-family: inherit;"><span style="background-color: white;"><span><span style="color: #292929;">3.- </span><b><span style="color: #45818e;">Si se ha obtenido una mejora</span></b><span style="color: #292929;">, es decir, el <i>'fitness'</i> del texto descifrado es mayor que el mejor </span><i style="color: #292929;">'fitness'</i><span style="color: #292929;"> obtenido hasta el momento, entonces se pondrá como </span><b><span style="color: #45818e;">mejor clave la utilizada en el descifrado del texto y</span></b><span style="color: #45818e;"><b> como mejor <i>'fitness'</i></b><b> el obtenido en este descifrado, y se pondrá a cero el número de iteraciones sin mejora</b></span><span style="color: #292929;">. Nótese que la primera vez siempre habrá mejora, ya que el mejor </span><i style="color: #292929;">'fitness'</i><span style="color: #292929;"> se ha inicializado con un número negativo grande.</span></span></span></span></p><p><span style="font-family: inherit;"><span style="background-color: white;"><span><span style="color: #292929;">Mientras que </span><b><span style="color: #45818e;">si no ha habido mejora se incrementará en una unidad el número de iteraciones sin mejora y en el caso de que éste haya superado el límite prestablecido el algoritmo finalizará</span></b><span style="color: #292929;">.</span></span></span></span></p><p><span style="font-family: inherit;"><span style="background-color: white;"><span><span style="color: #292929;">4.- </span><b><span style="color: #45818e;">La nueva clave</span></b><span style="color: #292929;"> (alfabeto de sustitución) a utilizar en el siguiente descifrado </span><span style="color: #45818e;"><b>será la mejor clave hasta el momento en la que se permutarán (intercambiarán) dos letras al azar</b></span><span style="color: #292929;">.</span></span></span></span></p><p><span style="font-family: inherit;"><span style="background-color: white;"><span style="color: #292929;">En un próximo post pondré un script en python con esta implementación, lo ejecutaré con varios criptogramas de diferentes tamaños, para comprobar su eficacia y eficiencia, y comentaré los resultados obtenidos.</span></span></span></p><p><span style="background-color: white; font-family: inherit;"><b><i>Quizás también te interese</i></b>:</span></p><p><span style="font-family: inherit;"><span style="background-color: white;"><span style="color: #292929;"></span></span></span></p><div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxxi-el-algoritmo-hill.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXMfMuluYwZ5hD7BC0C8gaHwcuw31yrNFisFeHaf34dZOtoAqWJKk413PoQRmSwOcnYx6B3CHbAaVJIyUDrrTcjdtQJXsDJ_kQEUq87ipEyxIYBQD6EoB2Z_afiGUWqa2JlJeRvH9ewlVdiFLZ2FENyJHs0m1WWM8m8Emb5msqh3Oivh__UbIFYnr5/s16000/El%20algoritmo%20Hill%20Climbing.png" /></a></div></div><div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxix-calificacion-de-la.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcDUt4Hlr6Y7VHYqZTLd38zHdlb138ostcvLkibTBIAKG1cC107t0nDjMLgFoMUdHlOzWEAcxZmGHq43-TG095MnFjmk7p5NonBoGksJUcC5VMrimVyPa6Pp-Ft9J4dQjI-3-H7kXdsz93a8JJvwiyBD85cH387Xii12azf200r1SIIB_A8c1B1eQz/s16000/Calificaci%C3%B3n%20de%20la%20aptitud%20de%20un%20texto%20(fitness)%20en%20python.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><div class="MsoNormal" style="text-align: left;"><div class="separator" style="clear: both; text-align: center;"><a href="http://mikelgarcialarragan.blogspot.com/2023/07/criptografia-cclxviii-criptoanalisis.html" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitSHYnBv9GSerNN1yPIx2UuDSmAmAANGPReDdYWjRHOJ6021oP4060zi0qctxScdyA7tWbYD76S5JGiYCOZB62Go8vmI-S50PjpWXdhWlzgeHJAMqynawBYTeyNOLffJrns7711QNgwyM1FfpAHN3Jyv2h9ndts441t9H0L1yvSX2KiHKBhk5Xb749/s16000/Criptoan%C3%A1lisis%20mediante%20an%C3%A1lisis%20de%20frecuencias%20(III).png" /></a></div></div></div></div>Mikel García Larraganhttp://www.blogger.com/profile/03118239524461394157noreply@blogger.com0