Firma digital con cryptography
Veamos como proteger la información para asegurarnos de que el autor es quien dice ser. Antiguamente se usaban las firmas con pluma. Cada persona tenía una firma reconocible y difícil de copiar.
Actualmente tenemos la firma digital donde la integridad de la información está asegurada por la criptografía. La firma digital es un sistema criptográfico donde existen dos claves relacionadas matemáticamente:
- Una pública 🗝️ accesible por cualquiera. Permite verificar una firma.
- Otra privada 🔑 que debe mantenerse en secreto. Permite crear una firma.
Con la firma digital podemos verificar el origen o integridad de un mensaje. Si firmas un mensaje con tu clave privada, cualquiera podrá verificar su autenticidad con tu clave pública.
Veamos un ejemplo donde firmamos un mensaje con tu clave privada. La clave privada es el equivalente a la pluma y a tu firma, algo que sólo tú puedes crear. Empezamos importando los módulos que necesitamos.
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives import hashes
from cryptography.exceptions import InvalidSignature
Podemos crear una clave privada de la siguiente manera. La clave pública deriva de la privada.
privada = ec.generate_private_key(ec.SECP256R1())
publica = privada.public_key()
Puedes ver la privada así. En aplicaciones reales no debes enseñar esta clave a nadie, o se podrían hacer pasar por ti.
pem = privada.private_bytes(
serialization.Encoding.PEM,
serialization.PrivateFormat.PKCS8,
serialization.NoEncryption())
Podemos firmar un mensaje utilizando sign
. Esto es algo muy usado en transacciones blockchain. Esta firma permite reconocer que el creador de ese mensaje es quien tiene la clave privada. Haciendo esto es como si autorizaras esta transacción.
firma = privada.sign(
b"Envia 1 Euro al IBAN 123",
ec.ECDSA(hashes.SHA256()))
Ahora, un tercero podría verificar que el mensaje fue efectivamente creado por el conocedor de privada
. Para esto sólo se necesita publica
. Podemos verificar que el mensaje no ha sido alterado.
try:
publica.verify(
firma,
b"Envia 1 Euro al IBAN 123",
ec.ECDSA(hashes.SHA256()))
print("Verificacion OK")
except InvalidSignature:
print("Verificacion NOK")
# Verificacion OK
Ahora pongamos que alguien intercepta la comunicación y realiza lo siguiente:
- 😈 Cambia el mensaje de
1 euro
. - 💶 Cambia la cantidad por
100 euros
. - 🏦 Cambia la cuenta por
456
.
Si ahora intentamos verificar la firma con verify
obtendremos un error InvalidSignature
. Nos hemos protegido de un atacante modificando el mensaje.
try:
publica.verify(
firma,
b"Envia 100 Euros al IBAN 456",
ec.ECDSA(hashes.SHA256()))
print("Verificacion OK")
except InvalidSignature:
print("Verificacion NOK")
# Verificacion NOK
En pocas palabras, la firma digital permite evitar que alguien suplante tu identidad y diga cosas que tú no has dicho. Eso sí, siempre y cuando la clave privada solo la conozcas tú.
✏️ Ejercicios:
- Intenta usar otra clave pública distinta para verificar la firma con
verify
y explica lo que sucede.