notifications Notificaciones

Marcar todas como leídas

Ver más

lightbulb_outline

316 veces ha sido leído este artículo

Criptografia de llave publica y llave privada con Python

Lo lees en 3 Min.

La criptografía asimétrica, tambíen conocida como criptografia de clave pública, es un método criptografico donde a partir de dos llaves, (una llave publica y una llave privada) es posible el envío de mensajes de una forma segura.

La llave pública la podremos compartir con todo el mundo y será a partir de esta que se cifre el mensaje. Por otro lado la llave privada debe permanecer en un lugar seguro, y sólo debe conocerla el dueño de esta. Con la llave privada seremos capaces de descifrar el mensaje.

Uno de los algoritmos más utilizados al momento de trabajar con criptografía asimétrica es el algoritmo RSA, algoritmo que aprovecha el poder de los números primos para mantener nuestros secretos asalvo 😼. En esta ocasión aprenderemos a enviar y recibir mensajes de forma cifrada utilizando el algoritmo RSA y lenguaje de programación Python.

LLaves

Lo primero que debemos hacer es generar nuestro par de llaves, para ello nos podemos apoyar de la librería Crypto.

pip install crypto

Lo más importante al momento de generar nuestro par de llaves es encontrar una fuente segura de entropía o aleatoriedad.

Algo que aprendí en una clase de seguridad informática es que nunca utilices tu propio algoritmo para generar un número random o uses un generador simple (como lo puede ser la librería random de python). Siempre utiliza un generador pseudoaleatorio criptográficamente seguro (CSPRNG) .

import Crypto
from Crypto.PublicKey import RSA

random_generator = Crypto.Random.new().read

private_key = RSA.generate(1024, random_generator)
public_key = private_key.publickey()

Si nosotros imprimimos en consola cualquiera de nuestras dos llaves obtendremos un resultado como el siguiente.

<_RSAobj @0x107e5e0f0 n(1024),e,d,p,q,u,private>

La llaves ya están generadas, ya las podemos utilizar, sin embargo, nosotros no podemos presentar esto a un cliente, así que lo que haremos será decodificar nuestro par de llaves de tal forma que tengamos como resultado final algo que un ser humano pueda entender.

Para decodifocar las llaves nos apoyaremos de la librería binascii. Esta librería nos permite convertir de binario a ASCII.

Si tu así lo deseas puedes omitir estos pasos y seguir trabajando con los objetos RSA.

import binascii

private_key = private_key.exportKey(format='DER')
public_key = public_key.exportKey(format='DER')

private_key = binascii.hexlify(private_key).decode('utf8')
public_key = binascii.hexlify(public_key).decode('utf8')

Es importante mencionar que las llaves se encuentran almacenadas en las mismas variables, es decir, los valores anteriores se perderán. 🔑 una muy buena idea sería almacenar cada uno de los nuevos valores en variables difentes.

Ahora sí, si imprimimos nuestras llaves obtendrá un resultado un poco más amigable para un ser humano.

Ejemplo llave pública.

30819f300d06092a864886f70d010101050003818d0030818902818100f023ea29f841a2e007c3549962fdce6819b70165d4fd270ca03e518530bbf9883fea42898da676f978b420f716e2bea7d5f14e0dd35807de38d717187a511b702fe55574fe103bd1fd9f13f3e1927c1200a197c914216c711f8c34577b8b6218c0488a3a1bc2b40fd78d4aedb103fa83246d75d223c9787ba0dd7ab943a613f70203010001

La llave pública debe poseer una longitud menor que la llave privada.

Mensaje cifrado

Una vez tengamos nuestro par de llaves ya podremos cifrar los mensajes.

En caso tú hayas decodificado las llaves del objeto RSA a binario y posteriormente ASCII (lo que hicimos arriba) será necesario volver a obtener los objetos originales, no te preocupes, es una tarea muy sencilla.

De ASCCI a llave privada.

private_key = RSA.importKey(binascii.unhexlify(private_key))
public_key = private_key.publickey()

De ASCCI a llave pública.

public_key = RSA.importKey(binascii.unhexlify(public_key))

Encriptado.

from Crypto.Cipher import PKCS1_OAEP

message = 'Hola mundo, soy un mensaje en texto plano, todo el mundo puede leerme.'
message = message.encode()

cipher = PKCS1_OAEP.new(public_key)
encrypted_message  = cipher.encrypt(message)

Desencriptado.

cipher = PKCS1_OAEP.new(private_key)
message = cipher.decrypt(encrypted_message)

En esta ocasión nos apoyamos del modulo PKCS1_OAEP para el envío y recepción de mensaje cifrados.

Firma

Lo interesante del cifrado asimétrico es que no solo nos permite el envío de mensajes de forma segura, si no que tambíen podemos realizar firmas digitales, esto con la finalidad de validar la autenticidad de un recurso.

Vamos a realizar la firma utilizando nuestra llave privada y validaremos dichafirma a través de la llave pública.

from Crypto.Hash import SHA256
from Crypto.Signature import PKCS1_v1_5

signer = PKCS1_v1_5.new(private_key)

resource = 'Texto plano!'
resource = resource.encode()

sha = SHA256.new()
sha.update(resource)

signature = signer.sign(sha)

En este ejemplo utilizamos el algoritmo SHA-256 para generar el hash, sin embargo, si así lo deseas puedes utilizar el algoritmo que necesites.

  • SHA512
  • SHA384
  • SHA256
  • SHA
  • MD5

Verificar firma.

signer = PKCS1_v1_5.new(public_key)

sha = SHA256.new()
sha.update(resource) #Recurso

result = signer.verify(sha, signature)

El método verify nos retornará un valor booleano. El valor será verdadero si y sólo si es posible autenticar la firma.

El algoritmo que hayamos utilizado para generar el hash y firmar el recurso será el mismo algoritmo que usaremos para validar la firma digital.

Recomendaciones

¿Con qué lenguaje de programación comenzar?

Lo lees en 3 Min.

Si quieres aprender a programar una pregunta que muy probablemente te estés haciendo es : ¿Con qu...

 

WSGI python

Lo lees en 2 Min.

Si eres un desarrollador Python y quieres comenzar a crear tus propios proyectos web, déjame dec...

 

5 lenguajes de programación para aprender a programar

Lo lees en 3 Min.

En esta ocasión citaremos 5 lenguajes de programación, los cuales considero yo, son una excelente...

 

Cursos Gratuitos 2018

Lo lees en 6 Min.

Desde nuestros inicios en 2011, hemos mantenido un compromiso para ofrecer cursos gratuitos, inde...

 

Comunidad