ValueError: MAC check failed
ValueError: MAC check failed
我正在做一个超级小而简单的程序,它试图更多地了解这个模块,但是发生了一些非常奇怪的事情。
下面的代码returns:
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()
您忘记转移随机数了。 nonce 可以直接传输,也不需要在 AAD 中,因为 nonce 会自动针对 AEAD 密码(例如 GCM)进行验证。
来自文档:
nonce
(bytes) – the value of the fixed nonce. It must be unique for the combination message/key. If not present, the library creates a random nonce (16 bytes long for AES).
所以如果你想使用默认随机生成的16字节1,你需要检索和传输随机数。
但是,由于 GCM 对于 12 字节随机数更安全且性能更高,我宁愿自己生成一个(安全随机)12 字节随机数,并使用/传输它。该库似乎默认使用 16 字节的随机随机数,因为这是 AES 的块大小。这通常是个好主意,但不适用于 GCM。
当然,你不能简单地发送密钥,密钥应该事先建立。
我正在做一个超级小而简单的程序,它试图更多地了解这个模块,但是发生了一些非常奇怪的事情。
下面的代码returns:
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()
您忘记转移随机数了。 nonce 可以直接传输,也不需要在 AAD 中,因为 nonce 会自动针对 AEAD 密码(例如 GCM)进行验证。
来自文档:
nonce
(bytes) – the value of the fixed nonce. It must be unique for the combination message/key. If not present, the library creates a random nonce (16 bytes long for AES).
所以如果你想使用默认随机生成的16字节1,你需要检索和传输随机数。
但是,由于 GCM 对于 12 字节随机数更安全且性能更高,我宁愿自己生成一个(安全随机)12 字节随机数,并使用/传输它。该库似乎默认使用 16 字节的随机随机数,因为这是 AES 的块大小。这通常是个好主意,但不适用于 GCM。
当然,你不能简单地发送密钥,密钥应该事先建立。