简体   繁体   中英

How to encrypt a message and sign it using PyCryptodome Python?

I am currently learning the Public Key Infrastructure implementation in Python using the PyCryptodome library, but I was having a hard time undestanding how exactly a digital signature is to be send with a message. I was trying to sign and verify the message projecting this process on a client-server interaction; however, at the signature verification step, my program exits, since the signature is not verified. I've read the documentation , in case you are wondering, yet, I am stuck. What am I doing wrong here?

So this is the last code I've written:

from Crypto.Cipher import AES, PKCS1_OAEP # needed for encrypting messages(AES)/public_key(PKCS1_OAEP) sent over the network
from Crypto.Hash import SHA256 # needed for digital signining
from Crypto.PublicKey import RSA # Needed for generating RSA private/public key pair
from Crypto.Random import get_random_bytes # Need for the AES key generation
from Crypto.Signature import pkcs1_15 # Digital signing alg
from Crypto.Util.Padding import pad, unpad

def sign_msg(msg:bytes, priv_key):
    hashed_msg = SHA256.new(msg)
    signed_msg = pkcs1_15.new(priv_key).sign(hashed_msg)
    return signed_msg

def verify_msg(msg:bytes, pub_key):
    hashed_msg = SHA256.new(msg)
    try:
        pkcs1_15.new(pub_key).verify(hashed_msg, )
    except (ValueError, TypeError):
        return False
    return True

shared_key = get_random_bytes(16)
shared_iv = get_random_bytes(16)

client_privkey = RSA.import_key(open('client_side/private_key.pem').read())
client_pubkey = RSA.import_key(open('client_side/public_key.pem').read())
msg_to_sign = input("Message to sign: ")
enc_msg = AES.new(shared_key, AES.MODE_CBC, shared_iv).encrypt(pad(msg_to_sign.encode('utf-8'), 16))
print("Encrypted message:")
print(enc_msg)
singed_msg = sign_msg(enc_msg, client_privkey)
print("Signed Message: ")
print(singed_msg)

#----------------------------------------------------------------------------------------#
### Then we send it to the server, server receives the message, and starts processing it

server_pubkey = RSA.import_key(open('server_side/public_key.pem').read())
server_privkey = RSA.import_key(open('server_side/private_key.pem').read())

print("Received Message: ")
print(singed_msg)

if verify_msg(singed_msg, client_pubkey):
    print("Message VERIFIED!")
    dec_msg = AES.new(shared_key, AES.MODE_CBC, shared_iv).decrypt(unpad(singed_msg, 16))
    print("Decrypted msg: ")
    print(dec_msg)
else:
    print("Message not verified..")
    

After some extra hours of research on digital signatures, I was able to figure this thing out. Essentially, my mistake was that I used to think that we can somehow derive an original message from the digital signature of it, which is utterly wrong. As a matter of fact, we send digital signatures in plain along with the symmetrically encrypted message . Like this: {"digital_signature": "-sdadasDSa=sDAdad/addaqwe1nsudad", "data": "dajdasnidj9q1haSHDdsjiadad"}

Important note (at least, it was for me): digital signature size will be ofa size of a used hashing algorithm for signing the message.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM