PyCryptoDome - ValueError: MAC check failed

38 views Asked by At

I'm trying to create an ECC cipher in my program... the encryption works perfectly but with the decryption process, it gives the following error:

ValueError: MAC check failed.

I've checked and the only issue I could find was the input that was in .lower() making the input of the base64 ciphertext give me an error.

After changing that it still doesn't work.

The functions clear_terminal() and title() are just prints or trivial.

def generar_ECC_keys():
    ECC_key = ECC.generate(curve="P-256")
    ECC_private_key = ECC_key.export_key(format="PEM")
    ECC_public_key = ECC_key.public_key().export_key(format="PEM")
    return ECC_key, ECC_private_key, ECC_public_key

def encriptar_ECC(plaintext, ECC_public_key, ECC_key):
    receptor_key = ECC.import_key(ECC_public_key)
    shared_key = ECC_key.d * receptor_key.pointQ
    key_derivada = SHA256.new(str(shared_key.x).encode()).digest()[:16]
    AES_cipher = AES.new(key_derivada, AES.MODE_EAX)
    ciphertext, tag = AES_cipher.encrypt_and_digest(pad(plaintext.encode(), AES.block_size))
    
    return ECC_key.public_key().export_key(format='PEM'), AES_cipher.nonce, tag, ciphertext

def display_datos_encriptados(ECC_public_key, ECC_private_key, nonce, tag, ciphertext):
    nonce_b64 = base64.b64encode(nonce).decode('utf-8')
    tag_b64 = base64.b64encode(tag).decode('utf-8')
    ciphertext_b64 = base64.b64encode(ciphertext).decode('utf-8')
    
    print("===== Guarda esta información para desencriptar el mensaje posteriormente =====\n")
    print(f"Llave pública ECC (PEM):\n{ECC_public_key}\n")
    print(f"Llave privada ECC (PEM):\n{ECC_private_key}\n")
    print(f"Nonce (Base64):\n{nonce_b64}\n")
    print(f"Tag (Base64):\n{tag_b64}\n")
    print(f"Texto encriptado (Base64):\n{ciphertext_b64}\n")
    print("=============================================================")

def desencriptar_ECC(ECC_public_key, nonce, tag, ciphertext, ECC_private_key):

    compartido = ECC_private_key.d * ECC_public_key.pointQ
    llave_derivada = SHA256.new(str(compartido.x).encode()).digest()[:16]
    
    AES_cipher = AES.new(llave_derivada, AES.MODE_EAX, nonce)
    plaintext = unpad(AES_cipher.decrypt_and_verify(ciphertext, tag), AES.block_size)
    
    return plaintext

def ECC_cipher():
    print("===== Cifrado ECC =====")                                     # Printea un menú por estética
    modo = input("Elige encriptar o desencriptar (E/D): ").upper()       # Pide un input de encriptar/desencriptar
    while modo not in "ED" or modo == "" or modo in " " or modo == "ED": # Mira que la respuesta al input sea válida
        print("Error")
        modo = input("Elige encriptar o desencriptar (E/D): ").upper()                       
    
    ECC_key, ECC_private_key, ECC_public_key = generar_ECC_keys()
    if modo == "E":
        plaintext = input("Introduce un texto: ") 
        while len(plaintext) < 1:                                            
            print("Error. Introduce un texto válido.")
            plaintext = input("Introduce un texto: ")
        ECC_public_key, nonce, tag, ciphertext = encriptar_ECC(plaintext, ECC_public_key, ECC_key)
        display_datos_encriptados(ECC_public_key, ECC_private_key, nonce, tag, ciphertext)

    else:
        ciphertext_b64 = input("Introduce el texto encriptado: ")
        while len(ciphertext_b64) < 1:                                            
            print("Error. Introduce un texto válido.")
            ciphertext_b64 = input("Introduce el texto encriptado: ")
        ECC_public_key_encoded = (input("Introduce la llave pública usada durante la encripción: "))
        ECC_private_key_encoded = (input("Introduce la llave privada usada durante la encripción: "))
        nonce_b64 = (input("Introduce el nonce usado durante la encripción: "))
        tag_b64 = (input("Introduce el tag usado durante la encripción: "))
        ECC_public_key = ECC.import_key(base64.b64decode(ECC_public_key_encoded))
        ECC_private_key = ECC.import_key(base64.b64decode(ECC_private_key_encoded))
        nonce = base64.b64decode(nonce_b64)
        tag = base64.b64decode(tag_b64)
        ciphertext = base64.b64decode(ciphertext_b64)
        decrypted_message = desencriptar_ECC(ECC_public_key, nonce, tag, ciphertext, ECC_private_key)
        print(f"\nEl texto desencriptado es: \n{decrypted_message.decode()}\n\nCifrado ECC\nLlave privada: \n\n{ECC_private_key}\n")
    input("Pulsa enter para continuar.")
    clear_terminal()
    title()
0

There are 0 answers