{"id":716,"date":"2025-09-22T23:09:58","date_gmt":"2025-09-22T22:09:58","guid":{"rendered":"https:\/\/jagumiel.xyz\/blog\/?p=716"},"modified":"2025-09-22T23:09:59","modified_gmt":"2025-09-22T22:09:59","slug":"criptografia-post-cuantica-facil-con-python","status":"publish","type":"post","link":"https:\/\/jagumiel.xyz\/blog\/2025\/09\/22\/criptografia-post-cuantica-facil-con-python\/","title":{"rendered":"Criptograf\u00eda post-cu\u00e1ntica f\u00e1cil con Python"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Introducci\u00f3n a la criptograf\u00eda post-cu\u00e1ntica<\/h2>\n\n\n\n<p>C\u00f3mo dec\u00eda <a href=\"https:\/\/pqcrypto.org\/www.springer.com\/cda\/content\/document\/cda_downloaddocument\/9783540887010-c1.pdf\" target=\"_blank\" rel=\"noopener nofollow\" title=\"Introduction to post-quantum cryptography - Daniel J. Bernstein\">Daniel Bernstein<\/a>, el d\u00eda que alguien consiga construir un computador cu\u00e1ntico funcional, se acab\u00f3 la criptograf\u00eda tal y como la conocemos. Todos los algoritmos de clave p\u00fablica usados actualmente para proteger nuestros datos y comunicaciones ser\u00e1n vulnerables. Pero que esta m\u00e1quina consiga romper algoritmos como RSA, DSA o ECDSA no implica que la criptograf\u00eda y la privacidad hayan llegado a su fin. Nace de este modo la criptograf\u00eda post-cu\u00e1ntica, el inicio de una nueva generaci\u00f3n de algoritmos que resistan el impacto de la computaci\u00f3n cu\u00e1ntica.<\/p>\n\n\n\n<div id=\"attachment_736\" style=\"width: 690px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/jagumiel.xyz\/blog\/wp-content\/uploads\/2025\/09\/post-quantum.png\">\n<img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-736\" class=\"aligncenter size-full wp-image-736\" \n     src=\"https:\/\/jagumiel.xyz\/blog\/wp-content\/uploads\/2025\/09\/post-quantum.png\" \n     alt=\"Criptograf\u00eda post-cu\u00e1ntica con Kyber y Dilithium: seguridad frente a ordenadores cu\u00e1nticos.\" \n     width=\"1024\" height=\"614\" srcset=\"https:\/\/jagumiel.xyz\/blog\/wp-content\/uploads\/2025\/09\/post-quantum.png 1024w, https:\/\/jagumiel.xyz\/blog\/wp-content\/uploads\/2025\/09\/post-quantum-300x180.png 300w, https:\/\/jagumiel.xyz\/blog\/wp-content\/uploads\/2025\/09\/post-quantum-768x461.png 768w, https:\/\/jagumiel.xyz\/blog\/wp-content\/uploads\/2025\/09\/post-quantum-250x150.png 250w, https:\/\/jagumiel.xyz\/blog\/wp-content\/uploads\/2025\/09\/post-quantum-150x90.png 150w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/>\n<\/a><p id=\"caption-attachment-736\" class=\"wp-caption-text\">Imagen 1. Visualizaci\u00f3n de la transici\u00f3n de RSA hacia algoritmos de criptograf\u00eda post-cu\u00e1ntica como Kyber y Dilithium, base de la nueva generaci\u00f3n de seguridad digital.<\/p><\/div>\n\n\n\n<p>La criptograf\u00eda post-cu\u00e1ntica surge precisamente para anticiparse a este escenario. Los candidatos post-cu\u00e1nticos se basan en problemas para los cuales no se conocen algoritmos cu\u00e1nticos capaces de resolverlos de forma pr\u00e1ctica. De ah\u00ed que organismos como el NIST est\u00e9n estandarizando esquemas como Kyber (para cifrado e intercambio de claves) y Dilithium (para firmas digitales).<\/p>\n\n\n\n<p>En esta entrada vamos a ver c\u00f3mo trabajar con algoritmos post-cu\u00e1nticos, concretamente los dos m\u00e1s famosos, Kyber y Dilithium. Aprenderemos a clonar e instalar <a href=\"https:\/\/github.com\/Anish-M-code\/pqcrypt\" target=\"_blank\" rel=\"noopener nofollow\" title=\"PQcrypt - Github\">PQcrypt<\/a>, una sencilla herramienta en Python que nos permitir\u00e1 generar pares de claves, cifrar y descifrar ficheros, as\u00ed como firmar y verificar documentos a trav\u00e9s de una interfaz muy f\u00e1cil de usar.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Preparaci\u00f3n del entorno<\/h2>\n\n\n\n<p>Como se ha mencionado, para adentrarnos en la criptograf\u00eda post-cu\u00e1ntica vamos a utilizar la herramienta <a href=\"http:\/\/PQcrypt : Post Quantum Cryptography toolkit\" target=\"_blank\" rel=\"noopener nofollow\" title=\"PQcrypt - Github\">PQcrypt<\/a>. En principio, necesitaremos un ordenador con sistema operativo Linux y al menos 4GB de memoria RAM. Yo he usado una m\u00e1quina virtual con 8 cores y 4GB de RAM y el proceso de creaci\u00f3n de claves, as\u00ed como otras operaciones, ha sido bastante r\u00e1pido.<\/p>\n\n\n\n<p>Lo primero que hacemos es actualizar la lista de repositorios y los paquetes.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo apt-get update &amp;&amp; sudo apt-get upgrade -y<\/code><\/pre>\n\n\n\n<p>Despu\u00e9s, tenemos que clonar el repositorio. Para ello, es posible que haya que instalar el paquete git con sus dependencias, aunque lo m\u00e1s probable es que ya lo tengamos en el sistema.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ git clone https:\/\/github.com\/Anish-M-code\/pqcrypt.git<\/code><\/pre>\n\n\n\n<p>Por \u00faltimo, compilamos el repositorio:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ cd pqcrypt &amp;&amp; source check_deps.sh<\/code><\/pre>\n\n\n\n<p>\u00a1Con esto ya tenemos el entorno preparado! Ha sido f\u00e1cil, \u00bfverdad?<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Utilizando PQcrypt<\/h2>\n\n\n\n<p>La herramienta de criptograf\u00eda post-cu\u00e1ntica se ejecuta desde la raiz de su directorio. Al realizar la compilaci\u00f3n mediante el <code>script <\/code>anterior, nos ha cambiado el path, por lo que tendremos que volver a la carpeta \u00ab<code>pqcrypt<\/code>\u00ab, que es la del repositorio clonado de <code>git<\/code>. El comando es el siguiente (y muestra un men\u00fa):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ source run.sh                                                                                                                                                                                                  \n\n --- PQcrypt : Post Quantum Cryptography Toolkit --- \n\n\n Menu:-\n\n 1) Encrypt\/Decrypt Data\n 2) Digitally Sign\/Verify Data\n 3) Check Fingerprint of Public key\n 4) Export\/Extract Public key from Private key\n 5) Update Dependencies\n 6) About\n\nEnter choice:<\/code><\/pre>\n\n\n\n<p>La herramienta nos ofrece varios algoritmos de cifrado, todos ellos son:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Algoritmos de cifrado de clave p\u00fablica y establecimiento de claves que fueron seleccionados en la 3\u00aa ronda del proceso de estandarizaci\u00f3n del NIST.<\/li>\n\n\n\n<li>Algoritmos de firma digital que tambi\u00e9n fueron seleccionados para estandarizaci\u00f3n en esa ronda.<\/li>\n\n\n\n<li>Adem\u00e1s, se consideran algoritmos que est\u00e1n siendo evaluados para una posible 4\u00aa ronda de an\u00e1lisis (es decir, candidatos avanzados, pero a\u00fan no estandarizados).<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Cifrado y descifrado de datos con criptograf\u00eda post-cu\u00e1ntica<\/h3>\n\n\n\n<p>Para cifrar datos lo primero que necesitamos es un fichero que queramos ofuscar. Yo he creado el fichero <code>hello.txt<\/code>, que contiene el texto \u00ab<code>Hello World<\/code>\u00bb como ejemplo. A continuaci\u00f3n vamos a cifrarlo con el algoritmo Kyber.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Generar una pareja de claves<\/h4>\n\n\n\n<p>Lo primero que tenemos que hacer es lo mismo que en la criptograf\u00eda tradicional, generar una pareja de claves. Podremos verlas en el mismo directorio en el que estamos trabajando. Posteriormente le decimos que queremos cifrar un fichero. Nos preguntar\u00e1 cu\u00e1l es la p\u00fablica, si queremos protegerlo con contrase\u00f1a y cu\u00e1l es el nombre del fichero a cifrar. Aqu\u00ed debajo dejo una captura del log:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code> --- PQcrypt : Post Quantum Cryptography Toolkit --- \n\n Menu:-\n\n 1) Encrypt\/Decrypt Data\n 2) Digitally Sign\/Verify Data\n 3) Check Fingerprint of Public key\n 4) Export\/Extract Public key from Private key\n 5) Update Dependencies\n 6) About\n\nEnter choice:1\n\n --- Encryption\/Decryption Mode ---\n\n 1) Generate key pair\n 2) Encrypt data\n 3) Decrypt Data\n\nEnter choice:1\n\n--- Supported Ciphers ---\n\n 1) Kyber1024 &#091; Recommended ]\n 2) HQC-256\n 3) Classic-McEliece-6688128\n...\n\nEnter choice:1\n\n&lt;--- Task Started ---&gt;\n\nEnter Password to protect secret key:\nDo you need ASCII armoured public key?(Y\/N):N\n\n&lt;--- Task Completed ---&gt;\n\n --- Encryption\/Decryption Mode ---\n\n 1) Generate key pair\n 2) Encrypt data\n 3) Decrypt Data\n\nEnter choice:2\n\n&lt;--- Task Started ---&gt;\n\nEnter Public key:82ab1c3def1c65b4639cb87b0904538b.pub\n\nEnter file:hello.txt\n\n&lt;--- Task Completed ---&gt;\n\nDo you need ASCII armoured Encrypted Message ?(Y\/N):N<\/code><\/pre>\n\n\n\n<p>Despu\u00e9s de esto, si listamos el directorio actual, aparecer\u00e1n dos nuevos ficheros con extensi\u00f3n <code>.sec<\/code> y <code>.pub<\/code>, los cuales se corresponden con las claves privada y p\u00fablica.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ ls -l | awk '{print $1, $3, $5, $9}'                                                                                                                                                                      \n-rw-r--r-- osboxes 8192 82ab1c3def1c65b4639cb87b0904538b.pub\n-rw-r--r-- osboxes 12288 82ab1c3def1c65b4639cb87b0904538b.sec<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Cifrar el mensaje con la clave p\u00fablica<\/h4>\n\n\n\n<p>La l\u00f3gica que sigue la criptograf\u00eda post-cu\u00e1ntica es la misma que la tradicional. Usaremos la clave p\u00fablica para cifrar y la privada para descifrar. Para ello seleccionamos desde el men\u00fa principal la opci\u00f3n 1, \u201c<code>Encrypt\/Decrypt Data<\/code>\u201d.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>--- Encryption\/Decryption Mode ---\n\n 1) Generate key pair\n 2) Encrypt data\n 3) Decrypt Data\n\nEnter choice:2\n\n&lt;--- Task Started ---&gt;\n\nEnter Public key:82ab1c3def1c65b4639cb87b0904538b.pub\n\nEnter file:hello.txt\n\n&lt;--- Task Completed ---&gt;<\/code><\/pre>\n\n\n\n<p>Hemos seleccionado la opci\u00f3n de cifrar y hemos seguido los pasos proporcionando la informaci\u00f3n que nos solicita. Con esto, ya se ha generado de forma autom\u00e1tica el fichero \u201c<code>hello.txt.cry<\/code>\u201d. Si lo abrimos, veremos que contiene s\u00edmbolos y caracteres ilegibles.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Descifrar el mensaje con la clave privada<\/h4>\n\n\n\n<p>Para realizar la operaci\u00f3n contraria, desde el mismo men\u00fa, tendremos que seleccionar la opci\u00f3n 3, \u00ab<code>Decrypt Data<\/code>\u00ab.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Enter choice:3\n\n&lt;--- Task Started ---&gt;\n\nEnter Private key:82ab1c3def1c65b4639cb87b0904538b.sec\n\nEnter Encrypted file:hello.txt.cry\nEnter Password to unlock secret key:\nEnter Name of output file:hola.txt\n\n&lt;--- Task Completed ---&gt;<\/code><\/pre>\n\n\n\n<p>Podemos confirmar que el fichero original y que el nuevo fichero generado a partir del cifrado tienen el mismo contenido:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ cat hello.txt\nHello World\n$ cat hola.txt \nHello World<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Firma digital con criptograf\u00eda post-cu\u00e1ntica<\/h3>\n\n\n\n<p>Una firma digital es un mecanismo criptogr\u00e1fico que garantiza la <strong>autenticidad<\/strong>, <strong>integridad <\/strong>y <strong>no repudio<\/strong> de un mensaje o documento. Funciona mediante un par de claves: la privada (que solo el firmante conoce) y la p\u00fablica (que cualquiera puede usar para verificar la firma).<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Test: Todos los algoritmos no sirven para firmar<\/h4>\n\n\n\n<p>Ahora bien, no todas las claves privadas sirven para firmar. En el siguiente ejemplo he intentado firmar un archivo con una clave Kyber y, como era de esperar, he obtenido el siguiente error:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>--- Sign\/Verify Data ---\n\n 1) Generate key pair\n 2) Digitally Sign Data\n 3) Verify Digital Signature\n\nEnter choice:2\n\n&lt;--- Task Started ---&gt;\n\nEnter Private key:82ab1c3def1c65b4639cb87b0904538b.sec\n\nEnter file which will be signed:hello.txt\nEnter Password to unlock secret key:\nKyber1024\n\n&lt;--- Task Failed ---&gt;<\/code><\/pre>\n\n\n\n<p>Esto ocurre porque Kyber est\u00e1 dise\u00f1ado para cifrado e intercambio de claves, no para firmas digitales. En la criptograf\u00eda tradicional pasa algo parecido: algoritmos como RSA permiten tanto cifrar como firmar, aunque se recomienda no usar la misma clave para ambas funciones. En el caso de las curvas el\u00edpticas (ECC), directamente hay que elegir el algoritmo adecuado para cada tarea: ECDH para intercambio de claves y ECDSA o EdDSA para firmas.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Generar una pareja de claves para firmar con criptograf\u00eda post-cu\u00e1ntica<\/h4>\n\n\n\n<p>Tras comprobar que con Kyber no podemos firmar, vamos a dar el paso l\u00f3gico: generar un par de claves <strong>Dilithium<\/strong>, un esquema dise\u00f1ado espec\u00edficamente para firmas digitales. Desde el mismo men\u00fa de <code>pqcrypt <\/code>seleccionamos la opci\u00f3n de generar una nueva clave y elegimos Dilithium5 (la opci\u00f3n recomendada):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>--- Supported Algorithms ---\n 1) Dilithium5 &#091; Recommended ]\n 2) Falcon-1024\n 3) SPHINCS+-Haraka-256f-robust\n ...\nEnter choice:1\n\n&lt;--- Task Started ---&gt;\n\nEnter Password to protect secret key:\nDo you need ASCII armoured public key?(Y\/N):N\n\n&lt;--- Task Completed ---&gt;<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Firma del mensaje con la clave privada<\/h4>\n\n\n\n<p>Con la clave ya creada, podemos firmar nuestro fichero <code>hello.txt<\/code> introduciendo la clave privada correspondiente:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Enter Private key:20b477338f583c838b1c21162a8df413.ssec\nEnter file which will be signed:hello.txt\nEnter Password to unlock secret key:\nDo you need ascii armoured digital signature?(Y\/n):n\n\n&lt;--- Task Completed ---&gt;<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Comprobaci\u00f3n de la firma con la clave p\u00fablica<\/h4>\n\n\n\n<p>La firma se gener\u00f3 correctamente y qued\u00f3 guardada como <code>hello.txt.qsig<\/code>. Ahora, si compartimos el fichero con su firma, el receptor podr\u00eda verificar la firma usando nuestra clave p\u00fablica:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Enter Public key:20b477338f583c838b1c21162a8df413.spub\nEnter file which has to be verified:hello.txt\nEnter Digital Signature File Location:hello.txt.qsig\n\nGood Signature , Data signed on 2025-09-19 11:38:42.785343\n\nDigital Signature made using key with fingerprint:-\n  186ee88836e6abde77552448fd5fc63965e728a394490b0dc8834536cf24b119 \n  3cc829e227f7c1268aff29f40a1d6a29d976e6b70d4803a202948a921ed2d1fd<\/code><\/pre>\n\n\n\n<p>Como vemos, la firma es v\u00e1lida y nos confirma que el documento no ha sido modificado desde el momento en que se firm\u00f3.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Poniendo a prueba la integridad del mensaje<\/h4>\n\n\n\n<p>Para comprobar la robustez del sistema, editamos el archivo original a\u00f1adiendo una l\u00ednea m\u00e1s:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ echo \"modification\" &gt;&gt; hello.txt\n$ cat hello.txt\nHello World\nmodification<\/code><\/pre>\n\n\n\n<p>Si volvemos a verificar la firma, el resultado cambia:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Enter Public key:20b477338f583c838b1c21162a8df413.spub\nEnter file which has to be verified:hello.txt\nEnter Digital Signature File Location:hello.txt.qsig\n\n&lt;--- Task Completed ---&gt;<\/code><\/pre>\n\n\n\n<p>En este caso ya no se muestra el mensaje de <code>Good Signature<\/code>, lo que indica que el documento fue alterado y, por tanto, la firma ya no es v\u00e1lida. Este ejemplo demuestra claramente la funci\u00f3n principal de una <strong>firma digital<\/strong>: garantizar la <strong>integridad <\/strong>y <strong>autenticidad <\/strong>de la informaci\u00f3n.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Criptograf\u00eda h\u00edbrida<\/h3>\n\n\n\n<p>La criptograf\u00eda asim\u00e9trica tiene un inconveniente, y es que no puede cifrar grandes vol\u00famenes de informaci\u00f3n. Por el contrario, la criptograf\u00eda sim\u00e9trica, con algoritmos como AES o ChaCha20, s\u00ed es capaz de resolver este problema, sin embargo, si alguien intercepta la clave los datos quedan comprometidos.<\/p>\n\n\n\n<p>Para resolver estos problemas, la soluci\u00f3n est\u00e1 en combinar lo mejor de ambos mundos, la criptograf\u00eda h\u00edbrida, empleada en sistemas como <strong>PGP<\/strong>. Este enfoque consiste en cifrar los datos con una clave sim\u00e9trica aleatoria, y protegerla a su vez cifrando esa clave con un algoritmo asim\u00e9trico, como RSA, ECC o Kyber.<\/p>\n\n\n\n<p>Este enfoque sigue siendo v\u00e1lido para criptograf\u00eda post-cu\u00e1ntica, ya que algoritmos sim\u00e9tricos como AES siguen siendo seguros frente a ordenadores cu\u00e1nticos. La \u00fanica precauci\u00f3n es usar claves de 256 bits o m\u00e1s, ya que el ataque de <strong>Grover <\/strong>permite reducir a la mitad la seguridad efectiva de las claves sim\u00e9tricas. A diferencia de RSA o ECC, AES no se ve afectado por el algoritmo de Shor.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Generar una clave AES aleatoria<\/h4>\n\n\n\n<p>Este paso vamos a darlo con el framework de <strong>OpenSSL<\/strong>. Para ello, es necesario que tanto la clave como el <strong>vector de inicializaci\u00f3n<\/strong> (VI) est\u00e9n en formato hexadecimal:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ openssl rand -hex 32 &gt; aes.key\n$ openssl rand -hex 16 &gt; aes.iv<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Cifrar el mensaje con la clave AES<\/h4>\n\n\n\n<p>El siguiente paso es usar la clave privada con su vector de inicializaci\u00f3n para cifrar el mensaje <code>hello.txt<\/code>. El resultado de este cifrado se guarda como <code>hello.enc<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ openssl enc -aes-256-cbc -in hello.txt -out hello.enc -K $(cat aes.key) -iv $(cat aes.iv)<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Utilizar criptograf\u00eda post-cu\u00e1ntica para cifrar la clave privada<\/h4>\n\n\n\n<p>El siguiente paso es cifrar, tal y como hemos visto antes, la clave sim\u00e9trica <code>aes.key<\/code> con la clave p\u00fablica de Kyber. Los ficheros que enviar\u00edamos al destinatario ser\u00edan los siguientes:<\/p>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li><code>hello.enc<\/code> &#8211; fichero cifrado con AES<\/li>\n\n\n\n<li><code>aes.key.cry<\/code> &#8211; clave AES cifrada con Kyber<\/li>\n\n\n\n<li><code>aes.iv<\/code> &#8211; IV en claro (no es secreto)<\/li>\n<\/ol>\n\n\n\n<p>Para descifrar el mensaje, el receptor tendr\u00e1 que usar su clave privada para obtener la clave sim\u00e9trica AES, y utilizar esta clave para descifrar el mensaje <code>hello.enc<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Mejorando la criptograf\u00eda h\u00edbrida con la firma digital<\/h3>\n\n\n\n<p>Hasta ahora hemos visto c\u00f3mo cifrar un archivo con una clave sim\u00e9trica AES y c\u00f3mo proteger esa clave con un algoritmo post-cu\u00e1ntico como Kyber. Con este enfoque garantizamos la <strong>confidencialidad<\/strong> de la informaci\u00f3n. Sin embargo, todav\u00eda queda una cuesti\u00f3n importante por resolver: \u00bfc\u00f3mo puede el receptor estar seguro de que el mensaje no ha sido manipulado y que procede realmente del emisor?<\/p>\n\n\n\n<p>Aqu\u00ed es donde entra en juego la firma digital. Al a\u00f1adir una firma a nuestro esquema h\u00edbrido, conseguimos no solo cifrar el contenido, sino tambi\u00e9n validar su <strong>integridad<\/strong> y <strong>autenticidad<\/strong>. De este modo, aunque un atacante intercepte o modifique los datos, la firma fallar\u00e1 en la verificaci\u00f3n.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Firmar antes o despu\u00e9s de cifrar<\/h4>\n\n\n\n<p>Existen dos formas de combinar cifrado y firma digital:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Firmar antes de cifrar (sign-then-encrypt)<\/strong>: se genera la firma del archivo original y despu\u00e9s se cifra tanto el archivo como su firma. Esto es lo m\u00e1s com\u00fan en sistemas como PGP, ya que protege tambi\u00e9n la propia firma.<\/li>\n\n\n\n<li><strong>Firmar despu\u00e9s de cifrar (encrypt-then-sign)<\/strong>: primero se cifra el archivo y despu\u00e9s se firma el fichero resultante. La ventaja es que el receptor puede comprobar la validez de la firma incluso antes de descifrar.<\/li>\n<\/ul>\n\n\n\n<p>En ambos casos, la idea es la misma: la firma digital, generada con Dilithium u otro algoritmo post-cu\u00e1ntico, a\u00f1ade una capa de seguridad que el cifrado h\u00edbrido por s\u00ed solo no ofrece.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Ejemplo de flujo completo<\/h4>\n\n\n\n<p>Siguiendo nuestro ejemplo, el proceso quedar\u00eda as\u00ed:<\/p>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li>Generamos una clave AES y ciframos el archivo <code>hello.txt<\/code> \u2192 obtenemos <code>hello.enc<\/code>.<\/li>\n\n\n\n<li>Ciframos la clave AES con Kyber \u2192 obtenemos <code>aes.key.cry<\/code> y compartimos tambi\u00e9n el <code>aes.iv<\/code>.<\/li>\n\n\n\n<li>Firmamos el archivo original o bien el cifrado (seg\u00fan el enfoque elegido) con Dilithium \u2192 obtenemos <code>hello.txt.qsig<\/code> o <code>hello.enc.qsig<\/code>.<\/li>\n\n\n\n<li>El receptor descifra la clave AES con su clave privada Kyber, descifra el archivo con AES y, finalmente, verifica la firma con la clave p\u00fablica Dilithium.<\/li>\n<\/ol>\n\n\n\n<p>De este modo combinamos lo mejor de cada enfoque: <strong>confidencialidad<\/strong> gracias al cifrado h\u00edbrido y <strong>integridad, autenticidad y no repudio<\/strong> gracias a la firma digital. Este esquema es el que se utiliza en sistemas modernos de comunicaci\u00f3n segura y es, en esencia, la base sobre la que se construye la criptograf\u00eda post-cu\u00e1ntica aplicada.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Fin de la gu\u00eda<\/h2>\n\n\n\n<p>Con esto terminamos: has visto c\u00f3mo generar claves post-cu\u00e1nticas, cifrar y firmar ficheros con pqcrypt, y c\u00f3mo encajar ese trabajo en un esquema h\u00edbrido (Kyber + AES\/ChaCha20 + Dilithium) para lograr confidencialidad y autenticidad. Si te ha gustado, pru\u00e9balo en tu entorno y, si surge alguna duda, no dudes en dejar un comentario y lo revisamos juntos.<\/p>\n\n\n\n<p>Si te interesa la ciberseguridad, puedes continuar leyendo esta lecturas relacionada: <a href=\"https:\/\/jagumiel.xyz\/blog\/2025\/09\/01\/pentesting-vulnhub-basic-pentesting-1-escalada-persistencia\/\" target=\"_blank\" rel=\"noopener\">Pentesting (VulnHub): escalada y persistencia<\/a>.<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Gu\u00eda pr\u00e1ctica de criptograf\u00eda post-cu\u00e1ntica con PQcrypt: aprende a usar Kyber y Dilithium para cifrar, firmar y proteger datos frente a la computaci\u00f3n cu\u00e1ntica.<\/p>\n<p class=\"continue-reading-button\"> <a class=\"continue-reading-link\" href=\"https:\/\/jagumiel.xyz\/blog\/2025\/09\/22\/criptografia-post-cuantica-facil-con-python\/\">Continue reading<i class=\"crycon-right-dir\"><\/i><\/a><\/p>\n","protected":false},"author":1,"featured_media":736,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[93,37],"tags":[102,105,103,109,111,108,104,107,106,110],"class_list":["post-716","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ciberseguridad","category-linux","tag-ciberseguridad","tag-cifrado","tag-criptografia-post-cuantica","tag-dilithium","tag-grover","tag-kyber","tag-post-quantum","tag-pqcrypt","tag-seguridad","tag-shor"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/jagumiel.xyz\/blog\/wp-json\/wp\/v2\/posts\/716","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jagumiel.xyz\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jagumiel.xyz\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jagumiel.xyz\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jagumiel.xyz\/blog\/wp-json\/wp\/v2\/comments?post=716"}],"version-history":[{"count":24,"href":"https:\/\/jagumiel.xyz\/blog\/wp-json\/wp\/v2\/posts\/716\/revisions"}],"predecessor-version":[{"id":742,"href":"https:\/\/jagumiel.xyz\/blog\/wp-json\/wp\/v2\/posts\/716\/revisions\/742"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/jagumiel.xyz\/blog\/wp-json\/wp\/v2\/media\/736"}],"wp:attachment":[{"href":"https:\/\/jagumiel.xyz\/blog\/wp-json\/wp\/v2\/media?parent=716"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jagumiel.xyz\/blog\/wp-json\/wp\/v2\/categories?post=716"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jagumiel.xyz\/blog\/wp-json\/wp\/v2\/tags?post=716"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}