Criptografía en Python - RSA
¿Qué es RSA?
criptográfico de clave pública desarrollado en 1979, siendo el primer y el más
utilizado algoritmo de esta índole registrado hasta la fecha. Es capaz incluso
de cifrar y firmar digitalmente.
receptor para cifrar los datos a enviar, a posteriori, el receptor deberá usar
su clave privada para descifrarlos. Una cosa peculiar es que para el caso de
firmar los datos, el emisor usa su propia clave privada para firmarlos y luego
el receptor usar la clave pública del emisor para verificarlos.
La Librería pycryptodome
también se le conoce por la cantidad excesivas (aunque útiles) de librerías,
módulos y demás. pycryptodome es una librería que utiliza primitivas
criptográficas de bajo-nivel, está escrita mayormente en python, pero para
uso crítico (como el rendimiento) se utilizan algunas extensiones escritas
en C.
sí, las siguientes mejoras:
- Modos de cifrado autenticados (GCM, CCM, EAX, SIV, OCB)
- AES acelerado en plataformas Intel a través de AES-NI
- Soporte de primera clase para PyPy
- Criptografía de curvas elípticas (solo curvas NIST P-256, P-384 y P-521)
-
API mejor y más compacta (atributos nonce y
iv para cifrados, generación automática de nonces e IVs
aleatorios, modo de cifrado CTR simplificado y más) -
SHA-3 (incluidos los XOF SHAKE), algoritmos hash SHA-512 y BLAKE2
truncados - Cifrados de flujo Salsa20 y ChaCha20/XChaCha20
- Poly1305 MAC
- Cifrados autenticados ChaCha20-Poly1305 y XChaCha20-Poly1305
- funciones de derivación scrypt, bcrypt y HKDF
- Deterministic (EC)DSA
- Contenedores de claves PKCS-8 protegidos con contraseña
- Esquema de intercambio secreto de Shamir
-
Los números aleatorios consiguen originados directamente del sistema
operativo (y no de un CSPRNG [Generador de Números Criptográficamente
Seguros, en español] en el espacio de usuario) -
Proceso de instalación simplificado, que incluye un mejor soporte para
Windows -
Generación de claves RSA y DSA más limpia (basada en gran medida en FIPS
186-4) - Limpieza importante y simplificación de la base de código
Instalación de pycryptodome
simple comando:
python3 -m pip install pycryptodome
También es recomendable no tener instalado pycrypto, que como se
mencionó pycryptodome, es una bifurcación mucho mejor de él. En
caso de tenerlo instalado, igualmente con un simple comando se debería
desinstalar:
python3 -m pip uninstall pycrypto
OJO: Todo el tutorial estará hecho para la versión 3 y se debe
tener instalado el paquete python-dev y
build-essential para su versión de python correspondiente, use su
gestor de paquetes en caso de no tenerlo instalado. Como generalmente se
usan distribuciones basadas en Debian o Arch Linux, aquí unos simples
comandos orientativos:
# Debian
sudo apt-get install build-essential python3-dev
# Arch Linux
sudo pacman -S base-devel
# General
python3 -m pip install pycryptodome
Generando el par de claves
Una vez hemos aprendido los conceptos básicos, además de instalar lo
correspondiente, ahora pasemos a la práctica. En este caso primero vamos a
generar el par de claves, que como ya saben, serían la clave pública y la
clave privada. Empecemos:
import sys
from Crypto.PublicKey import RSA # Importamos el módulo RSA
# El usuario (o sea nosotros) tiene que pasar un número mayor
# o igual 1024 y usando el objeto 'int' convertirmos un string
# a un entero.
bit_size = int(sys.argv[1])
key_format = sys.argv[2]
# Generamos el par de claves. Dependiendo del tamaño y el
# procesamiento de nuestro computador es lo que podrá tardar
.
keys = RSA.generate(bit_size)
print("Clave Pública:")
# Exportamos la clave pública y la imprimimos. Colocamos como
# argumento 'nn' en el parámetro 'end' de la función 'print'
# para imprimir dos saltos de líneas y se vea más legible.
#
# 'key_format' se explicará en unos instantes
#
# Usamos el método '.decode(...)' porque al exportarlos estarán
# en 'bytes' y es mejor (para volverlo legible) tenerlo en 'utf-8'.
print(keys.publickey().export_key(key_format).decode(), end='nn')
print("Clave Privada:")
# Hacemos prácticamente lo mismo que lo anterior, pero a diferencia
# de la exportación de la clave pública, no se necesita explicitar
# ningún método.
print(keys.export_key(key_format).decode())
pasemos a ejecutar el script para verlo detenidamente.
2048, 1024 ya se considera inseguro, tampoco hay que abusar del tamaño, yo
recomiendo 2048 o 3072 bits, aunque la siguiente tabla enumera el tamaño
de algunos algoritmos para mantener una seguridad mayor a 2030:
(el predeterminado) que es la codificación basada en texto (útil si se
quiere compartir por algún servicio como correo electrónico); OpenSSH,
también es una codificación textual que sigue la especificación OpenSSH;
por último, DER, codificación binaria.
inválido para 'utf-8', pero simplemente quitando el método
'.decode(...)' de la línea 13 y 17, permitiría mostrar los datos:
Cifrado con RSA
pycryptodome nos permite cifrar y descifrar datos, como se podrá ver a
continuación:
import sys
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
bit_size = int(sys.argv[1])
key_format = sys.argv[2]
# El usuario (o sea nosotros) pasaremos un texto
# arbitrario para después cifrarlo y descifrarlo.
text2cipher = sys.argv[3]
keys = RSA.generate(bit_size)
# Importamos la clave pública para cifrar los datos
cipher_rsa = PKCS1_OAEP.new(keys.publickey())
# Importamos la clave privada para descifrar los datos
decipher_rsa = PKCS1_OAEP.new(keys)
# Ciframos los datos.
#
# Se deben codificar los datos a 'utf-8', por eso está
# presente el método '.encode(...)'
enc_data = cipher_rsa.encrypt(text2cipher.encode())
# Desciframos los datos
dec_data = decipher_rsa.decrypt(enc_data)
print("Encriptado:")
print(enc_data, end='nn')
print("Desencriptado:")
print(dec_data)
Lecturas recomendadas
- https://pycryptodome.readthedocs.io
- https://es.wikipedia.org/wiki/RSA
- https://es.qwe.wiki/wiki/Key_size
Deja una respuesta