GPG - Cifrado y Firma Digital
Cifrado simétrico y asimétrico con GPG: generación de claves, encriptación, desencriptación y conceptos de RSA.
GPG
Theory
gpg is the OpenPGP (Pretty Good Privacy) part of the GNU Privacy Guard (GnuPG). It is a tool to provide digital encryption and signing services using the OpenPGP standard. gpg features complete key management and all the bells and whistles you would expect from a full OpenPGP implementation.
The gpg utility has a lot of options, but fortunately for us, encrypting and decrypting are easy to do and only require that you know three options for quick use: Create or encrypt (-c), decrypt (-d), and extract and decrypt (no option).
Practical: Working with GnuPG
1. Preparar un entorno seguro (opcional pero recomendado)
Para aprender y experimentar sin afectar tu configuración principal:
mkdir -p ~/gpg-lab
chmod 700 ~/gpg-lab
export GNUPGHOME=~/gpg-lab
Todo comando de gpg en esta terminal usará ~/gpg-lab como directorio base.
2. Encrypt a file (Symmetric Encryption)
Para cifrado simétrico (con contraseña):
echo "This is an encryption test" > file1.txt
gpg -c file1.txt
-cindica cifrado simétrico (solo se usa una contraseña).- Se te pedirá una passphrase para proteger el archivo.
- El archivo resultante será
file1.txt.gpg.
Puedes verificar el tipo de archivo:
file file1.txt.gpg
Puedes renombrar el archivo sin afectar su contenido:
mv file1.txt.gpg testfile01.doc
file testfile01.doc
Nota: Aunque cambies la extensión, GPG sigue reconociendo el archivo como PGP cifrado.
3. Decrypt a file (Symmetric Decryption)
Para recuperar el contenido original:
gpg -d testfile01.doc > recovered.txt
-do--decryptextrae el contenido.- Te pedirá la passphrase si el
gpg-agentno la tiene en caché. - Verifica el archivo recuperado:
cat recovered.txt
Concepto clave:
gpg-agentguarda la contraseña temporalmente en memoria. Si no quieres que la cachee, mata el agente antes de descifrar:
gpgconf --kill gpg-agent
Conceptos clave:
- El cifrado simétrico usa una contraseña compartida.
- El cifrado asimétrico usa clave pública para cifrar y clave privada para descifrar.
- Puedes combinar ambos métodos: cifrar un archivo con una clave pública y proteger la clave privada con passphrase.
1. file1.txt.gpg
- Es el archivo cifrado generado por GPG.
- Contiene los datos originales de
file1.txt, pero cifrados. - Si se usó
-c, está protegido con contraseña simétrica; si se usó cifrado con clave pública, está protegido con la clave pública del destinatario. - No es legible directamente; necesita
gpg -do la clave correcta para descifrarlo.
2. private-keys-v1.d/
- Es un directorio que almacena tus claves privadas en GPG.
- Cada clave privada está en un archivo separado, usualmente en un formato seguro (cifrado con tu passphrase).
- Solo el propietario del directorio debe tener acceso (permisos
700o más restrictivos). - Nunca se debe compartir fuera de entornos seguros.
3. pubring.kbx
- Es el keyring de claves públicas.
- Contiene todas las claves públicas que has importado o generado, usadas para cifrar datos o verificar firmas.
- Formato moderno
.kbx(KeyBox) reemplaza al antiguopubring.gpg. - Puedes exportar estas claves para compartirlas con otros.
4. random_seed
- Es un archivo que guarda datos de entropía aleatoria usados por GPG.
- GPG lo utiliza para mejorar la generación de claves y cifrados simétricos.
- Se actualiza automáticamente al generar claves o cifrar/descifrar.
- Es un archivo interno; no se modifica directamente.
4. Asymmetric Encryption (Cifrado con clave pública/privada)
1. Generar un par de claves (pública/privada)
gpg --full-generate-key
- Tipo de clave: RSA y RSA (opción 1)
- Tamaño: 4096 bits (recomendado)
- Validez: según tu criterio
- Nombre, correo y comentario opcional
- Passphrase: protege tu clave privada
Esto generará tu clave privada y la clave pública correspondiente, que quedan almacenadas en
~/.gnupg/private-keys-v1.d/y~/.gnupg/pubring.kbx.
2. Exportar la clave pública
Para enviar a un destinatario o usar para cifrar:
gpg --export -a "Nombre del Usuario" > mypublickey.asc
-aexporta en formato ASCII (legible).- El archivo
mypublickey.ascpuede compartirse libremente.
3. Cifrar un archivo con la clave pública
echo "Este es un mensaje secreto" > message.txt
gpg --encrypt --recipient "Nombre del Usuario" message.txt
gpg --import mypublickey.asc
gpg --list-keys
/home/haise/gpg-lab/pubring.kbx
-------------------------------
pub rsa4096 2025-08-29 [SC] [expires: 2025-08-31]
2B4D6CEFE2B5AF96B064D893E903090BE0D3E713
uid [ultimate] test (test) <test@test.test>
sub rsa4096 2025-08-29 [E] [expires: 2025-08-31]
gpg --encrypt --recipient "test (test) <test@test.test>" message.txt
- Se genera un archivo
message.txt.gpg. - Solo el propietario de la clave privada correspondiente puede descifrarlo.
4. Descifrar con la clave privada
Si recibes message.txt.gpg:
gpg --decrypt message.txt.gpg > decrypted.txt
- Te pedirá la passphrase de la clave privada si no está en caché.
- El contenido original queda en
decrypted.txt.
Conceptos clave
- Cifrado asimétrico: usa clave pública para cifrar y clave privada para descifrar.
- Seguridad: la clave privada nunca debe compartirse.
- Compatibilidad: puedes cifrar para varios destinatarios usando varias opciones
--recipient.
Resumen corto de criptografía
Existen dos grandes familias de criptografía: la de llave privada y la de llave pública. Históricamente, la criptografía de llave privada (simétrica) apareció primero; el criptosistema de llave pública (asimétrica) llegó después como respuesta al problema de tener que compartir una clave secreta de forma segura entre dos partes.
Criptografía clásica
Los cifrados clásicos por carácter (o monoalfabéticos) reemplazan cada letra del alfabeto por otra letra. Dos ejemplos típicos son el shift cipher y los affine ciphers. Su debilidad principal es que son vulnerables al análisis de frecuencia de letras en el texto cifrado, ya que ciertas letras aparecen con más frecuencia que otras en cualquier idioma. Una forma de mitigar esto es agrupar y reemplazar bloques de letras en lugar de letras individuales, dando lugar a los llamados block ciphers.
Criptografía de llave pública
En este modelo, cada persona tiene una clave para cifrar (pública) y otra distinta para descifrar (privada). El destinatario ("recipient") comparte su clave pública abiertamente, pero guarda su clave privada en secreto.
RSA
RSA es el algoritmo de llave pública más utilizado. Cifra mensajes mediante exponenciación modular, donde el módulo es el producto de dos números primos grandes.
Para cifrar un mensaje basta con conocer el módulo y el exponente público ; no hace falta conocer los dos primos que forman . Para descifrar, en cambio, sí se necesitan esos dos primos, ya que son la base para calcular el exponente privado . Esta asimetría —fácil de cifrar con datos públicos, imposible de descifrar sin los primos— es lo que hace seguro al sistema.
En los ejemplos didácticos se usan primos y pequeños para que los cálculos sean manejables a mano; en la práctica real, cada primo tiene 300 dígitos o más.
En el sistema RSA, cada persona tiene una clave de cifrado , donde es el módulo (resultado de multiplicar los dos primos grandes) y es un exponente relativamente primo a . Con primos de unos 300 dígitos cada uno, termina teniendo alrededor de 600 dígitos, un tamaño en el que factorizarlo de vuelta en y resulta computacionalmente inviable incluso para una computadora potente.
Proceso de encriptación:
- El mensaje en texto plano se traduce a una secuencia de enteros de dos dígitos: A = 01, B = 02, y así sucesivamente, hasta obtener una secuencia .
- Estos números se concatenan en una sola cadena de dígitos.
- La cadena se divide en bloques de igual longitud, de dígitos cada uno (donde es el mayor número par de dígitos que garantiza que el bloque, convertido a número, siga siendo menor que ). Si el último bloque queda incompleto, se rellena con letras ficticias, típicamente X, para completar la longitud.
- Cada bloque se transforma en un bloque de texto cifrado aplicando:
¿Por qué se usa el exponente e?
En RSA, la clave pública es el par . El exponente es el valor usado en la exponenciación modular al cifrar:
Su rol es ser parte de la función de encriptación: transforma el mensaje en el texto cifrado . Para que el esquema funcione, debe elegirse de modo que tenga un inverso multiplicativo respecto a , es decir:
donde es la función totiente de Euler. Ese inverso multiplicativo es , el exponente privado, y satisface:
En otras palabras: permite encriptar, y gracias a esta relación matemática, permite desencriptar.
En la práctica se suele escoger un pequeño y fijo (como 65537), porque acelera la operación de encriptación, siempre que cumpla la condición de ser coprimo con .
¿Por qué aparece (p-1)(q-1)?
La fórmula proviene de la función totiente de Euler, que cuenta cuántos enteros menores que son coprimos con .
Para un número primo , todos los números menores que son coprimos con , así que . Como con y primos distintos, la propiedad multiplicativa del totiente da:
Este valor se usa porque es la base para aplicar el teorema de Euler, que garantiza que:
Este resultado es justamente lo que hace posible que cifrar y descifrar sean operaciones inversas entre sí.
Resumen del proceso de RSA
Generación de claves:
- Escoger dos primos grandes .
- Calcular .
- Calcular .
- Elegir tal que y .
- Calcular como el inverso modular de .
- La clave pública es ; la clave privada es .
Encriptación (con la clave pública):
Desencriptación (con la clave privada):
Esto funciona porque , lo que garantiza que descifrar recupera exactamente el mensaje original.
Ejemplo rápido (mini-RSA, inseguro en la práctica)
Escogemos , . Entonces:
- Escogemos (coprimo con 60)
- Calculamos como el inverso de 7 mod 60: , porque
- Clave pública: ; clave privada:
- Mensaje:
Encriptación:
Desencriptación:
Conexión con los bloques de 2N dígitos
Los mensajes (letras) se convierten en números y luego se agrupan en bloques de longitud calculada de forma que el bloque, convertido a número, siempre sea menor que . De lo contrario, la operación modular se rompe: si un bloque representa un número mayor o igual a , la reducción módulo ya no distingue ese valor de otros equivalentes, y se pierde información del mensaje original. Por eso se calcula ese límite de "2N dígitos" antes de cifrar.
Explicación detallada del proceso de RSA (cifrado)
1. Traducción del mensaje a números
Cada letra se representa con 2 dígitos: A = 00, B = 01, ..., J = 09, K = 10, ..., Z = 25. Esto garantiza que todas las letras tengan la misma longitud.
Ejemplo: "STOP" → S = 18, T = 19, O = 14, P = 15 → 1819 1415
2. Agrupación en bloques
El mensaje traducido a números se concatena en una cadena de dígitos, que luego se divide en bloques de dígitos. Ese es el número par de dígitos más grande tal que un bloque compuesto solo por "25" repetidos (el valor máximo posible de una letra) siga siendo menor que .
En el ejemplo, . El número 2525 (4 dígitos) es menor que 2537, pero 252525 (6 dígitos) ya es mayor. Por lo tanto, los bloques deben tener 4 dígitos: "STOP" → 1819 1415
3. Encriptación de cada bloque
Cada bloque se encripta con:
Con clave pública y bloques , :
Resultado cifrado: 2081 2182
Explicación de RSA - Desencriptación
1. Clave de desencriptación
Para descifrar se necesita el exponente , el inverso modular de respecto a .
Con , :
- satisface , así que
2. Proceso de desencriptación
Para cada bloque se aplica:
Esto funciona porque , lo que asegura que la potencia deshace exactamente la operación de cifrado . Esto se demuestra formalmente con el teorema de Euler y, en implementaciones reales, se acelera con el teorema chino del resto (CRT).
3. Ejemplo de desencriptación
Mensaje recibido: 0981 0461, con clave .
Reconstrucción del mensaje:
- 0704 → 07 04 → H, E → "HE"
- 1115 → 11 15 → L, P → "LP"
- Mensaje final: HELP
Resumen conceptual
- Encriptación: letras → números → bloques → .
- Desencriptación: bloques cifrados → → números → letras.
- El sistema funciona porque y son inversos modulares respecto a , el teorema de Euler garantiza la reversibilidad, y el teorema chino del resto asegura que la congruencia se cumple simultáneamente en y en .
El módulo n
En RSA, el módulo se define como:
donde y son dos números primos grandes, elegidos al inicio del proceso de generación de claves.
Rol del módulo n:
- Tamaño del espacio de mensajes. El mensaje, convertido en un número entero , debe ser menor que . Por eso, al convertir texto a números, se divide en bloques que no excedan el valor de .
- Base de las operaciones modulares. Tanto el cifrado como el descifrado se hacen "módulo ", lo que asegura que los resultados siempre estén en el rango de 0 a .
- Seguridad. La seguridad de RSA descansa en la dificultad de factorizar en sus dos factores primos y . Aunque es público, obtener y es computacionalmente inviable cuando tienen cientos o miles de bits. Si un atacante lograra factorizar , podría calcular y de ahí obtener el exponente secreto .
Ejemplo práctico:
Con , :
La clave pública es y la clave privada es . El módulo es el valor común en ambas claves: es público y se usa tanto para cifrar como para descifrar. Lo que permanece secreto no es , sino su factorización en y .
En resumen: el módulo en RSA es el producto de dos primos grandes, determina el rango numérico en el que trabajan los mensajes cifrados, y es la base de la seguridad del sistema: su factorización es el problema matemático difícil que lo protege.