跳过elif语句?

编程入门 行业动态 更新时间:2024-10-28 01:16:45
本文介绍了跳过elif语句?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我正在尝试使用pycryptodome创建简单的加密/解密,但不断出现以下错误:

Am trying to create a simple encryption/decryption using pycryptodome but keeping getting the following error:

ValueError: Error 3 while encrypting in CBC mode

经过一些挖掘,我发现如果没有足够的数据可以得到此错误加密,因为实际上没有填充。问题是我添加了填充功能。调试后,似乎我的代码从字面上完全跳过了填充部分并导致了此错误。我在做什么错?

after some digging I saw that you get this error if there is not enough data to encrypt, as in there is no padding in effect. The thing is that I've added a padding function. After debugging it seems as if my code literally skips the padding part completely and causes this error. What am I doing wrong?

import os, random from Crypto.Cipher import AES from Crypto.Hash import SHA256 def encrypt(key, filename): chunksize = 64*1024 outputfile = filename + "(encrypted)" filesize = str(os.path.getsize(filename)).zfill(16) IV ='' for i in range(16): IV += chr(random.randint(0, 0xFF)) encryptor = AES.new(key, AES.MODE_CBC, IV.encode("latin-1")) with open(filename, 'rb') as infile: with open(outputfile, 'wb') as outfile: outfile.write(filesize.encode("latin-1")) outfile.write(IV.encode("latin-1")) while True: chunk = infile.read(chunksize) print(len(chunk)) if len(chunk) == 0: break elif len(chunk) % 16 != 0: chunk += ' ' * (16 - (len(chunk) % 16)) outfile.write(encryptor.encrypt(chunk)) def decrypt(key, filename): chunksize = 64 *1024 outputfile = filename[:11] with open(filename, 'rb') as infile: filesize = int(infile.read(16)) IV = infile.read(16) decryptor = AES.new(key, AES.MODE_CBC, IV.encode("latin-1")) with open(outputfile, 'wb') as outfile: while True: chunk = infile.read(chunksize) if len(chunk) == 0: break outfile.write(decryptor.decrypt(chunk)) outfile.truncate(filesize) def getkey (password): hasher = SHA256.new(password.encode("latin-1")) return hasher.digest() def main(): choice = input ("do you want to [E]ncrypt of [D]ecrypt?") if choice == 'E': filename = input("File to encrypt >") password = input("Password >") encrypt(getkey(password), filename) print("Encryption done!") elif choice == 'D': filename = input("File to Decrypt >") password = input("Password >") decrypt(getkey(password), filename) print("Decryption done!") else: print("No option selected") if __name__ == '__main__': main()

*我正在使用python 3.6

*I am using python 3.6

编辑:此处是我运行代码时完整的控制台输出:

Here are the full console output when I run the code:

C:\Users\itayg\AppData\Local\Programs\Python\Python36\python.exe "C:\Program Files\JetBrains\PyCharm Community Edition 2017.1.2\helpers\pydev\pydevd.py" --multiproc --qt-support --client 127.0.0.1 --port 21111 --file C:/Users/itayg/PycharmProjects/PyCrypto/encrypt.py Connected to pydev debugger (build 171.4249.47) pydev debugger: process 12876 is connecting do you want to [E]ncrypt of [D]ecrypt?E File to encrypt >grades.jpg Password >123 65536 49373 Traceback (most recent call last): File "C:\Program Files\JetBrains\PyCharm Community Edition 2017.1.2\helpers\pydev\pydevd.py", line 1585, in <module> globals = debugger.run(setup['file'], None, None, is_module) File "C:\Program Files\JetBrains\PyCharm Community Edition 2017.1.2\helpers\pydev\pydevd.py", line 1015, in run pydev_imports.execfile(file, globals, locals) # execute the script File "C:\Program Files\JetBrains\PyCharm Community Edition 2017.1.2\helpers\pydev\_pydev_imps\_pydev_execfile.py", line 18, in execfile exec(compile(contents+"\n", file, 'exec'), glob, loc) File "C:/Users/itayg/PycharmProjects/PyCrypto/encrypt.py", line 66, in <module> main() File "C:/Users/itayg/PycharmProjects/PyCrypto/encrypt.py", line 55, in main encrypt(getkey(password), filename) File "C:/Users/itayg/PycharmProjects/PyCrypto/encrypt.py", line 29, in encrypt outfile.write(encryptor.encrypt(chunk)) File "C:\Users\itayg\AppData\Local\Programs\Python\Python36\lib\site-packages\pycryptodome-3.4.6-py3.6-win-amd64.egg\Crypto\Cipher\_mode_cbc.py", line 167, in encrypt raise ValueError("Error %d while encrypting in CBC mode" % result) ValueError: Error 3 while encrypting in CBC mode

推荐答案

好,让我们解决一些代码错误的问题。首先最明显的一个-您的填充将在Python 3.5+上中断(并且用户的菜单将在2.x上中断),因为 infile.read()会给您 bytes 数组,因此尝试添加由 chunk + =''*(16-(len(chunk)%16))会导致错误。首先需要将空白填充转换为 bytes 数组: chunk + = b''*(16-(len(chunk)%16) )

Ok, let's fix a few things that are wrong with your code. First the most obvious one - your padding would break on Python 3.5+ (and your user 'menu' would break on 2.x) because infile.read() would give you bytes array so trying to add a string formed by chunk += ' ' * (16 - (len(chunk) % 16)) would result in an error. You would need to convert your whitespace pad to bytes array first: chunk += b' ' * (16 - (len(chunk) % 16))

但是这样的空格填充是个坏主意-当您以后解密文件时,如何知道多少(如果有) ,您添加的填充?您需要将其存储在某个位置,然后通过 filesize 值在标头中进行操作,告诉潜在的攻击者您的文件有多大,以及添加了多少空白您可能会遭受oracle填充攻击(下面的代码有可能,因此在不添加适当的MAC的情况下不要使用它来传递消息)。

But whitespace padding like this is a bad idea - when you're later decrypting your file how will you know how much, if any, padding you've added? You need to store this somewhere - and you do in the 'header' via the filesize value, telling a potential attacker how exactly big is your file and how much padding was added opening you to a padding oracle attack (which is possible with the bellow code so do not use it for passing messages without adding a proper MAC to it).

您可以使用的强大填充方案-我个人更喜欢 PKCS#7 只需填充不均匀的块或添加 n 个字节值为 n 的全新块-这样,解密后,您可以从块中选择最后一个字节,并确切知道要填充多少个字节,以便剥离它们。因此,将您的加密部分替换为:

There are plenty of robust padding schemes that you can use - I personally prefer PKCS#7 which is simply padding your uneven block or adding a whole new block with n number of bytes with the value of n - that way, after decryption, you can pick the last byte from your block and know exactly how many bytes were padded so you can strip them. So, replace your encryption portion with:

def encrypt(key, filename): outputfile = filename + "(encrypted)" chunksize = 1024 * AES.block_size # use the cipher's defined block size as a multiplier IV = bytes([random.randint(0, 0xFF) for _ in range(AES.block_size)]) # bytes immediately encryptor = AES.new(key, AES.MODE_CBC, IV) with open(filename, 'rb') as infile: with open(outputfile, 'wb') as outfile: outfile.write(IV) # write the IV padded = False while not padded: # loop until the last block is padded chunk = infile.read(chunksize) chunk_len = len(chunk) # if no more data or the data is shorter than the required block size if chunk_len == 0 or chunk_len % AES.block_size != 0: padding = AES.block_size - (chunk_len % AES.block_size) chunk += bytes([padding]) * padding # on Python 2.x replace with: chunk += chr(padding_len) * padding_len padded = True outfile.write(encryptor.encrypt(chunk))

我还更改了 chunksize 以匹配您正在使用的块大小( AES.block_size 的倍数)-碰巧64是16的倍数,但是您应该注意那些东西。

I've also changed your chunksize to match the block size you're using (multiples of AES.block_size) - it just happens that 64 is a multiple of 16 but you should pay attention to those things.

现在我们已经对加密进行了整理,解密就是所有这些,但要反向执行-解密所有块,读取最后一个块的最后一个字节并删除 n 个字节,从后面匹配最后一个字节的值:

Now that we have the encryption sorted out, the decryption is all this but in reversal - decrypt all blocks, read the last byte of the last block and remove n amount of bytes from behind matching the value of the last byte:

def decrypt(key, filename): outputfile = filename[:-11] + "(decrypted)" chunksize = 1024 * AES.block_size # use the cipher's defined block size as a multiplier with open(filename, 'rb') as infile: IV = infile.read(AES.block_size) decryptor = AES.new(key, AES.MODE_CBC, IV) with open(outputfile, 'wb') as outfile: old_chunk = b'' # stores last chunk, needed for reading data with a delay stripped = False while not stripped: # delayed loop until the last block is stripped chunk = decryptor.decrypt(infile.read(chunksize)) # decrypt as we read if len(chunk) == 0: # no more data padding = old_chunk[-1] # pick the padding value from the last byte if old_chunk[-padding:] != bytes([padding]) * padding: raise ValueError("Invalid padding...") old_chunk = old_chunk[:-padding] # strip the padding stripped = True outfile.write(old_chunk) # write down the 'last' chunk old_chunk = chunk # set the new chunk for checking in the next loop

更多推荐

跳过elif语句?

本文发布于:2023-11-24 10:11:46,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1624788.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:跳过   语句   elif

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!