【问题标题】:ValueError: MAC check failedValueError:MAC 检查失败
【发布时间】:2019-12-28 19:35:12
【问题描述】:

我正在做一个超级小而简单的程序,它试图更多地理解这个模块,但是发生了一些非常奇怪的事情。

下面的代码返回:

Traceback (most recent call last):
File ".\crypto.py", line 100, in <module> init = Emisor()
File ".\crypto.py", line 15, in __init__ self.encrypt()
File ".\crypto.py", line 71, in encrypt Receptor(cipher_text,tag_mac,self.key)
File ".\crypto.py", line 84, in __init__ self.decrypt(self.cipher_text,self.tag_mac,self.key)
File ".\crypto.py", line 93, in decrypt plain_text = cipher.decrypt_and_verify(cipher_text,tag_mac)
File "C:\Users\EQUIPO\AppData\Local\Programs\Python\Python37-32\lib\site-packages\Crypto\Cipher\_mode_gcm.py", line 569, in decrypt_and_verify self.verify(received_mac_tag)
File "C:\Users\EQUIPO\AppData\Local\Programs\Python\Python37-32\lib\site-packages\Crypto\Cipher\_mode_gcm.py", line 510, in verify raise ValueError("MAC check failed")
ValueError: MAC check failed

我已经阅读了许多 pdf、文档、视频、博客等。但我找不到解决方案。

PDTA:那是“nonce”,也就是“header”,有一个名为update()的方法,我应该把header放在哪里,我对那个和nonce有点迷茫。

from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes

class Transmitter():

    def __init__(self):

        self.random_password = None
        self.message_plain = True
        self.key = None

        self.password_option()
        self.text_option()
        self.encrypt()



    def password_option(self):

        while ( self.random_password == None ):

            random = input("\nDo you want to generate a random symmetric key? (y/n)\n\n>>> ").strip().lower()

            if random == "y":
                self.random_password = True
                self.random()

            elif random == "n":
                self.random_password = False
                self.random()

            else:
                pass

    def text_option(self):

        if self.message_plain:

            question = input("\nHow will you enter your message?\n\n[1] file\n\n[2] directly in the program\n\n>>> ").strip()

            if question == "1":
                path = input(r"\nEnter the file path\n\n>>> ").strip()
                name = path.split("\\")[-1]
                self.message_plain = open(name,mode = "rb")

            elif question == "2":
                self.message_plain = input("\nEnter your message\n\n>>> ").strip()
                self.message_plain = self.message_plain.encode("utf-8")


    def random(self):

        if self.random_password:
            self.key = get_random_bytes(16)

        else:
            self.key = input("\nEnter your password\n\n>>> ").strip()


    def encrypt(self):

        cipher = AES.new(self.key,AES.MODE_GCM)

        cipher.update(b"header")

        cipher_text,tag_mac = cipher.encrypt_and_digest(self.message_plain)

        Receiver(cipher_text,tag_mac,self.key)



class Receiver():

    def __init__(self,cipher_text,tag_mac,key):

        self.cipher_text = cipher_text
        self.tag_mac = tag_mac
        self.key = key

        self.decrypt(self.cipher_text,self.tag_mac,self.key)

    def decrypt(self,cipher_text,tag_mac,key):

        #try:

        # nonce = aes_cipher.nonce
        cipher = AES.new(key,AES.MODE_GCM)
        cipher.update(b"header")
        plain_text = cipher.decrypt_and_verify(cipher_text,tag_mac)

        #except ValueError:
        #   print("\nAn error has occurred.")

if __name__ == '__main__':

    init = Transmitter()

【问题讨论】:

  • 您在一篇文章中提出了非常不同的问题,请将它们分开
  • 您的主要问题似乎是基本的代码故障排除问题。您需要包含完整的错误(包括跟踪)。我们不会运行人们在这里发布的随机代码。
  • 这看起来更像是一个编程问题而不是安全问题。
  • 对不起,我已经放了完整的错误,至于嵌套的多个问题(实际上是3个)我这样做是因为要发布每个问题,我必须等待40分钟。我也很抱歉。
  • 请将屏幕截图替换为错误的复制/粘贴。一个原因是得到完整的错误(你切断了一堆)

标签: encryption python pycrypto


【解决方案1】:

您忘记转移随机数。随机数可以直接传输,也不需要在 AAD 中,因为随机数会自动针对 AEAD 密码(例如 GCM)进行验证。

来自文档:

nonce(字节)——固定随机数的值。对于组合消息/密钥,它必须是唯一的。 如果不存在,库会创建一个随机 nonce(AES 长 16 个字节)。

因此,如果要使用默认随机生成的 16 字节一,则需要检索和传输 nonce。

但是,由于 GCM 对于 12 字节随机数更安全且性能更高,我宁愿自己生成一个(安全随机)12 字节随机数,并使用/传输它。该库似乎默认为 16 字节的随机 nonce,因为这是 AES 的块大小。这通常是个好主意,但不适用于 GCM。

当然,你不应该简单地发送密钥,密钥应该事先建立。

【讨论】:

  • 事先?我认为对称加密就是这样发送密钥的,为了安全,我们也应该使用非对称加密,这种方法称为混合密码学。那么你如何事先做到这一点?什么不应该这样发送?
  • 没有收缩。我的意思是在加密或解密发生之前需要建立它。但是,目前我没有看到任何提及混合密码学或 DH,或 ECIES 或任何其他建立密钥的方式,所以我认为我应该提及它。您可以并且需要清楚地发送任何内容:AAD、nonce、身份验证标签,但不是密钥,这就是我要说的。也许“事先”可以被删除,我不知道,但我认为我们在同一页上:)
  • 收缩 -> 矛盾,愚蠢的拼写错误
猜你喜欢
  • 2021-05-29
  • 2021-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-25
  • 2016-05-31
  • 2017-07-31
  • 1970-01-01
相关资源
最近更新 更多