python - installing - Firma y verificación de datos usando pycrypto(RSA)
pycrypto python 3.7 windows (3)
A continuación se muestra la clase de ayuda que creé para realizar todas las funciones RSA necesarias (cifrado, descifrado, firma, verificación de firmas y generación de nuevas claves)
rsa.py
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA512, SHA384, SHA256, SHA, MD5
from Crypto import Random
from base64 import b64encode, b64decode
hash = "SHA-256"
def newkeys(keysize):
random_generator = Random.new().read
key = RSA.generate(keysize, random_generator)
private, public = key, key.publickey()
return public, private
def importKey(externKey):
return RSA.importKey(externKey)
def getpublickey(priv_key):
return priv_key.publickey()
def encrypt(message, pub_key):
#RSA encryption protocol according to PKCS#1 OAEP
cipher = PKCS1_OAEP.new(pub_key)
return cipher.encrypt(message)
def decrypt(ciphertext, priv_key):
#RSA encryption protocol according to PKCS#1 OAEP
cipher = PKCS1_OAEP.new(priv_key)
return cipher.decrypt(ciphertext)
def sign(message, priv_key, hashAlg="SHA-256"):
global hash
hash = hashAlg
signer = PKCS1_v1_5.new(priv_key)
if (hash == "SHA-512"):
digest = SHA512.new()
elif (hash == "SHA-384"):
digest = SHA384.new()
elif (hash == "SHA-256"):
digest = SHA256.new()
elif (hash == "SHA-1"):
digest = SHA.new()
else:
digest = MD5.new()
digest.update(message)
return signer.sign(digest)
def verify(message, signature, pub_key):
signer = PKCS1_v1_5.new(pub_key)
if (hash == "SHA-512"):
digest = SHA512.new()
elif (hash == "SHA-384"):
digest = SHA384.new()
elif (hash == "SHA-256"):
digest = SHA256.new()
elif (hash == "SHA-1"):
digest = SHA.new()
else:
digest = MD5.new()
digest.update(message)
return signer.verify(digest, signature)
Uso de la muestra
import rsa
from base64 import b64encode, b64decode
msg1 = "Hello Tony, I am Jarvis!"
msg2 = "Hello Toni, I am Jarvis!"
keysize = 2048
(public, private) = rsa.newkeys(keysize)
encrypted = b64encode(rsa.encrypt(msg1, public))
decrypted = rsa.decrypt(b64decode(encrypted), private)
signature = b64encode(rsa.sign(msg1, private, "SHA-512"))
verify = rsa.verify(msg1, b64decode(signature), public)
print(private.exportKey(''PEM''))
print(public.exportKey(''PEM''))
print("Encrypted: " + encrypted)
print("Decrypted: ''%s''" % decrypted)
print("Signature: " + signature)
print("Verify: %s" % verify)
rsa.verify(msg2, b64decode(signature), public)
Estoy tratando de familiarizarme con el módulo de pycrypto, pero la falta de documentación clara dificulta las cosas.
Para empezar, me gustaría entender cómo firmar y verificar datos. ¿Podría alguien dar un ejemplo de cómo se escribiría esto?
Esta es una versión completa del ejemplo en la documentación:
import Crypto.Hash.MD5 as MD5
import Crypto.PublicKey.RSA as RSA
import Crypto.PublicKey.DSA as DSA
import Crypto.PublicKey.ElGamal as ElGamal
import Crypto.Util.number as CUN
import os
plaintext = ''The rain in Spain falls mainly on the Plain''
# Here is a hash of the message
hash = MD5.new(plaintext).digest()
print(repr(hash))
# ''/xb1./J/xa883/x974/xa4/xac/x1e/x1b!/xc8/x11''
for alg in (RSA, DSA, ElGamal):
# Generates a fresh public/private key pair
key = alg.generate(384, os.urandom)
if alg == DSA:
K = CUN.getRandomNumber(128, os.urandom)
elif alg == ElGamal:
K = CUN.getPrime(128, os.urandom)
while CUN.GCD(K, key.p - 1) != 1:
print(''K not relatively prime with {n}''.format(n=key.p - 1))
K = CUN.getPrime(128, os.urandom)
# print(''GCD({K},{n})=1''.format(K=K,n=key.p-1))
else:
K = ''''
# You sign the hash
signature = key.sign(hash, K)
print(len(signature), alg.__name__)
# (1, ''Crypto.PublicKey.RSA'')
# (2, ''Crypto.PublicKey.DSA'')
# (2, ''Crypto.PublicKey.ElGamal'')
# You share pubkey with Friend
pubkey = key.publickey()
# You send message (plaintext) and signature to Friend.
# Friend knows how to compute hash.
# Friend verifies the message came from you this way:
assert pubkey.verify(hash, signature)
# A different hash should not pass the test.
assert not pubkey.verify(hash[:-1], signature)
Según la documentación en:
https://www.dlitz.net/software/pycrypto/api/current/Crypto.PublicKey.RSA._RSAobj-class.html
no debe usar la función Crypto.PublicKey.RSA.sign de PyCrypto en código real:
Atención: esta función realiza el descifrado RSA simple y primitivo (libro de texto). En aplicaciones reales, siempre debe usar el relleno criptográfico adecuado, y no debe firmar directamente los datos con este método. De lo contrario, se pueden producir vulnerabilidades de seguridad. Se recomienda utilizar los módulos Crypto.Signature.PKCS1_PSS o Crypto.Signature.PKCS1_v1_5 en su lugar.
Terminé usando el módulo RSA que implementa PKCS1_v1_5. La documentación para la firma fue bastante sencilla. Otros han recomendado usar M2Crypto .