pycryptodome:MAC检查失败(使用decrypt_and_verify)

时间:2018-06-02 00:13:12

标签: python-3.x cryptography aes aes-gcm pycryptodome

我正在使用Python 3.6中的Pycryptodome进行加密程序我正在尝试加密文件,然后对其进行解密并验证MAC标记。当我验证它时,会抛出错误

import os
from Crypto.Cipher import AES

bib Cryptodome导入

aad = b'any thing'
nonce = b'\xde\xe2G\xca\xe8Lq9\xeb\x8b\x84\xe7'
key = b'\xde\xe9\xad\xe9\x14_\x07\x1aq7C\\\xd7\x9c\xae\xfcJ\x1c%\xec\xe6C\xbe\xf0eO\xfaJ1\x08\x0c\xae'

我将nonce和key设置为常量只是为了先启动它。那么我将对每个文件使用唯一的nonce = get_random_bytes(12)。

def encrypt(filename):
    chunksize = 64 * 1024
    outputFile = "(encrypted)" + filename
    filesize = str(os.path.getsize(filename))
    cipher = AES.new(key, AES.MODE_GCM, nonce)
    cipher.update(aad)
    with open(filename, 'rb') as infile:
        with open(outputFile, 'wb') as outfile:
            outfile.write(filesize.encode('utf-8'))

            while True:
                chunk = infile.read(chunksize)

                if len(chunk) == 0:
                    break
                elif len(chunk) % 16 != 0:
                    chunk += ' '.encode('utf-8') * (16 - (len(chunk) % 16))
                ciphertext,sender_tag = cipher.encrypt_and_digest(chunk)

                print (sender_tag)
                outfile.write(ciphertext)

解密部分使用decrypt_and_verify所以无需担心哪个先来解密或验证

def decrypt(filename,received_tag):
    chunksize = 64 * 1024

    outputFile = "(clear)"+ filename
    cipher = AES.new(key, AES.MODE_GCM, nonce)
    cipher.update(aad)
    with open(filename, 'rb') as infile: 
        with open(outputFile, 'wb') as outfile:
            while True:
                chunk = infile.read(chunksize)
                if len(chunk) == 0:
                    break
                clearmessage = cipher.decrypt_and_verify(chunk, b'received_tag')
                outfile.write(clearmessage)
            outfile.truncate()

def Main():
    choice = input("Would you like to (E)ncrypt or (D)ecrypt?: ")
    if choice == 'E':
        filename = input("File to encrypt: ")
        #password = input("Password: ")
        encrypt(filename)
        print ("Done.")
    elif choice == 'D':
        filename = input("File to decrypt: ")
    #password = input("Password: ")
        received_tag = input("enter received tag:")
        decrypt(filename,received_tag)
        print ("Done.")
    else:
        print ("No Option selected, closing...")

if __name__ == '__main__':
    Main()

这就是错误:

raise ValueError("MAC check failed")
ValueError: MAC check failed

我不知道我搞砸了哪里。顺便说一句,我得到一个类似于b'\ x1c \ xd1 \ xd8 \ x1a6 \ x07 \ xf3G \ x8c_s \ x94的标签“*(b'

更新: 我确实纠正了代码sender_tag中的错误,ciphertext = cipher.encrypt_and_digest(chunk)insted of ciphertext,sender_tag = cipher.encrypt_and_digest(chunk)但仍然问题仍然存在

1 个答案:

答案 0 :(得分:1)

相当多的事情看起来很狡猾:

  • 您编写文件大小,但之后您又无法读回来。实际上,我根本不认为你应该写它。
  • 在加密之前将块填充到16字节边界,但GCM不需要它。
  • 不应该修复,而是每次加密随机。
  • 随机数和MAC标记通常与密文一起存储(因此密文长于明文)。
  • 通过独立地编写块,您可以让攻击者删除,复制和重新排序传输中的块。