En esta entrada se desarrolla una aplicación en Python para proveer servicios como integridad, confidencialidad y no repudio. Mediante el uso de la criptografía de llave simétrica, criptografía de llave asimétrica, funciones hash, firma digital, sobre digital y certificado digital.
La digitalización de la información se ha vuelto tendencia. Las transacciones en línea se vuelven cada vez más populares. Las empresas guardan los datos confidenciales de sus clientes en formato digital. Los hospitales guardan los expedientes clínicos de los clientes en formato digital. En todas las entidades la tendencia es no hacer papelería y migrar a la digitalización. En el mundo de la seguridad informática los hackers han desarrollado habilidades sofisticadas para acceder a estos datos confidenciales. Por otro lado, los profesionales destinados a proteger los datos al acceso no autorizado han desarrollado habilidades aún más sofisticadas para proporcionar mecanismos que garanticen algunas medidas de seguridad para proteger los datos en reposo, en tránsito y/o en uso.

Vamos a definir las palabras claves antes de pasar a código.
Tabla de contenidos
Criptografía
Criptografı́a tiene su raı́z de la lengua griega, proviene de las palabras (kryptós = recubierto, oculto) y (grafein = escribir) a las que agregando el sufijo -ía se le confiere el carácter de conocimiento o ciencia. Entonces, etimológicamente la criptografía es la ciencia que estudia la escritura oculta. Según la misma fuente, la criptografía también se puede definir como el estudio de diseñar cifradores.
Los cifradores se dividen en dos tipos, los de llave simétrica y los de llave pública. Los cifradores de llave simétrica usan la misma llave para cifrar y descifrar los datos mientras que los de llave pública usan llaves diferentes.
Funciones hash
Mientras que los cifradores se usan para proveer la confidencialidad de los datos, las funciones hash se usan para proveer la integridad. Básicamente el hash representa la huella digital del documento y así, cualquier modificación de los datos se puede saber porque esta firma es única.
Criptografía de llave simétrica
La criptografía de llave simétrica (SKC) consiste en la utilización de una sola llave tanto para el cifrado como el descifrado de un mensaje.
Criptografía de llave asimétrica
La criptografía de llave asimétrica o pública (PKC) consiste en el uso de una llave privada y una llave pública para el cifrado y el descifrado de un mensaje. En este tipo de criptografía, el módulo emisor cifra el mensaje con la llave pública del receptor y el receptor usa su llave privada para descifrar el mensaje.
Sobre digital
Un sobre digital es un método de envío de llave simétrica que usa la criptografía de llave asimétrica, se cifra el sobre con la llave pública del receptor y el receptor usa su llave privada para descifrar el sobre y recupera la llave simétrica. En la figura se ilustra el proceso de cifrado y de descifrado del sobre digital.

Firma digital
La firma digital es una forma de cifrar la huella digital de un mensaje, el emisor cifra la huella con su llave privada y el receptor usa la llave pública del emisor para verificar la firma. En la figura se ilustra el proceso de cifrado y de descifrado del sobre digital.

Las actividades del emisor y del receptor se presentan en las siguientes dos imágenes.


Primero vamos a crear el certificado con el siguiente código.
import datetime
from cryptography import x509
from cryptography.x509.oid import NameOID
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.serialization import load_pem_public_key
from cryptography.hazmat.primitives.asymmetric import padding
class Certificate():
def __init__(self,private_key,public_key):
subject = issuer = x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"nombre_del_país"),
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"provincia"),
x509.NameAttribute(NameOID.LOCALITY_NAME, u"Ciudad"),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"Organización"),
x509.NameAttribute(NameOID.COMMON_NAME, u"correo")])
self.cert = x509.CertificateBuilder().subject_name(subject).issuer_name(issuer
).public_key(public_key
).serial_number(x509.random_serial_number()
).not_valid_before(datetime.datetime.utcnow()
).not_valid_after(datetime.datetime.utcnow() + datetime.timedelta(days=100)
).add_extension(x509.SubjectAlternativeName([x509.DNSName(u"localhost")]),critical=False
).sign(private_key, hashes.SHA256(), default_backend())
def getCertificate(self):
return self.cert
def validateCertificate(self, cert, public_key):
try:
public_key.verify(cert.signature,cert.tbs_certificate_bytes,padding.PKCS1v15(),cert.signature_hash_algorithm)
except:
return False
else:
return True
El algoritmo de AES.
from Crypto import Random
from Crypto.Cipher import AES
###KDF###
from Crypto.Protocol.KDF import PBKDF2
from Crypto.Hash import SHA512
from Crypto.Random import get_random_bytes
###KDF###
from time import time
from os import listdir
import hashlib
import os
class AES_Cipher:
ruta=None
def __init__(self,ruta):
super().__init__()
self.ruta=ruta
def pad(self,s):
return s + b"\1" * (AES.block_size - len(s) % AES.block_size)
def cifrar(self,message, key):
message = self.pad(message)
iv = Random.new().read(AES.block_size)
cipher = AES.new(key, AES.MODE_CBC, iv)
return iv + cipher.encrypt(message)
def descifrar(self,ciphertext, key):
iv = ciphertext[:AES.block_size]
cipher = AES.new(key, AES.MODE_CBC, iv)
texto_plano = cipher.decrypt(ciphertext[AES.block_size:])
return texto_plano.rstrip(b"\1")
def cifrar_archivo(self,archivo, key):
print("Procesando cifrado...")
with open("ruta_del_archivo", 'rb') as an:
ahora = time()
texto_plano = an.read()
enc = self.cifrar(texto_plano, key)
with open("ruta_del_archivo"+'.aes', 'wb') as an:
an.write(enc)
def decifrar_archivo(self,archivo, key):
print("Procesando decifrado...")
with open("ruta_del_archivo_cifrado"+'.aes', 'rb') as ac:
texto_cifrado = ac.read()
dec = self.descifrar(texto_cifrado, key)
with open("ruta_para_guardar_el_archivo_descifrado", 'wb') as acz:
acz.write(dec)
Algoritmo RSA.
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives.asymmetric import utils
class RSA_Cipher:
#Crifrando
def cifrado(self, public_key, message):
ciphertext = public_key.encrypt(
message,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA512()),
algorithm=hashes.SHA512(),
label=None
)
)
return ciphertext
#Descifrando
def descifrado(self, private_key, ciphertext):
plaintext = private_key.decrypt(
ciphertext,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA512()),
algorithm=hashes.SHA512(),
label=None
)
)
La clase principal.
#from Crypto.Cipher import PKCS1_OAEP
#from Crypto.PublicKey import RSA
from Crypto.Hash import SHA256
#from Crypto.Signature import PKCS1_v1_5
from AES_Cipher import * //Importar el primer archivo
from RSA_Cipher import * //Importar el segundo archivo
import Crypto
from os import listdir
from Certificate import *
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives.asymmetric import utils
ruta = "Ruta del archivo"
from shutil import rmtree
firma=[]
longitud=3072
def generar_llaves(longitud):
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=longitud,
backend=default_backend())
public_key = private_key.public_key()
return [private_key, public_key]
#Firmar archivos
def firmar_archivos(private_key,archivo):
global acum_tiempof
global acum_tamaf
print("Firmando el archivo, favor de esperar...")
chosen_hash = hashes.SHA512()
hasher = hashes.Hash(chosen_hash, default_backend())
with open("Ruta del archivo", "rb") as f:
ahora = time()
for bloque in iter(lambda: f.read(4096), b""):
hasher.update(bloque)
digest = hasher.finalize()
signature = private_key.sign(
digest,
padding.PSS(
mgf=padding.MGF1(hashes.SHA512()),
salt_length=padding.PSS.MAX_LENGTH
),
utils.Prehashed(chosen_hash))
return signature
#Vericar firma
def verificar_firma(public_key, archivo, signature):
print("Archivo: ",archivo)
print("Verificando la firma del archivo, favor de esperar...")
global acum_tiempovf
global acum_tamavf
chosen_hash = hashes.SHA512()
hasher = hashes.Hash(chosen_hash, default_backend())
with open(archivo, "rb") as f:
ahora = time()
for bloque in iter(lambda: f.read(4096), b""):
hasher.update(bloque)
digest = hasher.finalize()
try:
public_key.verify(
signature,
digest,
padding.PSS(
mgf=padding.MGF1(hashes.SHA512()),
salt_length=padding.PSS.MAX_LENGTH
),
utils.Prehashed(chosen_hash)
)
except Exception as e:
print("La firma no es correcta")
else:
print("La firma es correcta")
def getData(ruta):
archivos = listdir(ruta)
#print(archivos)
if '.DS_Store' in archivos:
archivos.remove('.DS_Store')
return archivos
if __name__ == "__main__":
#Seguridad de la llave PKC
longitud = 15360
archivos = getData("Ruta del archivo")
print("Generando la llave simétrica, favor de esperar...")
password = b'contraseña secreta'
salt = get_random_bytes(16)
key_simetrica = PBKDF2(password, salt, 32, count=100000)
print("¡Llave generada con éxito!")
aes_c = AES_Cipher(ruta)
for archivo in archivos:
tasa_cifrado = aes_c.cifrar_archivo(archivo, key_simetrica)
print("Generando las llaves de Alice, favor de esperar...")
alice_kpriv, alice_kpub = generar_llaves(longitud)
print("Generando el sobre digital, favor de esperar...")
rsa_c = RSA_Cipher()
sobre = rsa_c.cifrado(alice_kpub, key_simetrica)
print("Gerando las llaves de Bob, favor de esperar...")
bob_kpriv, bob_kpub = generar_llaves(longitud)
print("Creando el certificado digital, favor de esperar...")
cert = Certificate(bob_kpriv,bob_kpub)
bob_cert = cert.getCertificate()
firmas=[]
for archivo in archivos:
firma = firmar_archivos(bob_kpriv,archivo)
firmas.append(firma)
print("Cantidad de documentos firmados: ",len(firmas))
print("Abriendo el sobre digital, favor de esperar...")
key_simetrica_des = rsa_c.descifrado(alice_kpriv,sobre)
print("Verificando el certificado, favor de esperar...")
check_cert = cert.validateCertificate(bob_cert,bob_kpub)
print("Certificado válido: ",check_cert)
for archivo in archivos:
tasa_descifrado=aes_c.decifrar_archivo(archivo, key_simetrica)
for i in range(len(archivos)):
firma = firmas[i]
archivo = archivos[i]
verificar_firma(bob_kpub, "Ruta del archivo a descifrar", firma)
Para correr la aplicación corre el archivo principal. Cualquier duda deja un comentario. ¡No olvides mostrar tu apoyo dejando un “Me gusta”!
Acerca del autor
Saintus Zephir
Ingeniero en Sistemas Computacionales y estudiante de Maestría en Ciencias en Ingeniería y Tecnologías Computacionales en el Centro de Investigación y de Estudios Avanzados del IPN (CINVESTAV-IPN).
Lo probé y me funcionó, gracias me sirvió mucho :v
Hello! finger nail fungus treatment
fluid retention treatment
counseling and treatment center of utah
what is the best treatment for pid
crate and barrel window treatments
febrile neutropenia treatment
what is the treatment for osteoporosis
hodgkin’s lymphoma treatment success rates
treatment for the bends
what happens when you give a narcissist the silent treatment
dry flaky scalp treatment
roanoke comprehensive treatment center
acne treatment for african american skin
varicose veins natural treatment
residential treatment centers for depression
bipolar disorder treatment without medication
advantage treatment spray for cats
wart treatment for kids
lucida treatment center
pain treatment for dogs
cancer treatment anchorage ak
Hello! treatment for bowel incontinence in elderly helpful resources stromectol 3mg
Hello! ayurvedic treatment for arthritis
Hello! ingrown hair on scalp treatment address here
Hello! pcn treatment source web page
Hello! naturopathic treatment lyme disease click through the next web site
Hello! dental treatment for sleep apnea pop over here