2016-08-20 241 views
-1

我正在編寫我的學校項目的程序,並且上面有一個問題。 這裏是我的代碼:ValueError:AES密鑰長度必須爲16,24或32字節PyCrypto 2.7a1

def aes(): 
    #aes 
    os.system('cls') 
    print('1. Encrypt') 
    print('2. Decrypt') 

    c = input('Your choice:') 

    if int(c) == 1: 
     #cipher 
     os.system('cls') 
     print("Let's encrypt, alright") 
     print('Input a text to be encrypted') 
     text = input() 

     f = open('plaintext.txt', 'w') 
     f.write(text) 
     f.close() 

     BLOCK_SIZE = 32 
     PADDING = '{' 
     pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING 
     EncodeAES = lambda c, s: base64.b64encode(c.encrypt(pad(s))) 
     secret = os.urandom(BLOCK_SIZE) 

     f = open('aeskey.txt', 'w') 
     f.write(str(secret)) 
     f.close() 

     f = open('plaintext.txt', 'r') 
     privateInfo = f.read() 
     f.close() 

     cipher = AES.new(secret) 

     encoded = EncodeAES(cipher, privateInfo) 

     f = open('plaintext.txt', 'w') 
     f.write(str(encoded)) 
     f.close() 
     print(str(encoded)) 

    if int(c) == 2: 
     os.system('cls') 
     print("Let's decrypt, alright") 

     f = open('plaintext.txt','r') 
     encryptedString = f.read() 
     f.close() 

     PADDING = '{' 
     DecodeAES = lambda c, e: c.decrypt(base64.b64decode(e)).rstrip(PADDING) 
     encryption = encryptedString 

     f = open('aeskey.txt', 'r') 
     key = f.read() 
     f.close() 

     cipher = AES.new(key) 
     decoded = DecodeAES(cipher, encryption) 

     f = open('plaintext.txt', 'w') 
     f.write(decoded) 
     f.close() 

     print(decoded) 

完整的錯誤文本:

Traceback (most recent call last): File "C:/Users/vital/Desktop/Prog/Python/Enc_dec/Enc_dec.py", line 341, in aes() 
File "C:/Users/vital/Desktop/Prog/Python/Enc_dec/Enc_dec.py", line 180, in aes cipher = AES.new(key) 
File "C:\Users\vital\AppData\Local\Programs\Python\Python35-32\lib\site-packages\Crypto\Cipher\AES.py", line 179, in new return AESCipher(key, *args, **kwargs) 
File "C:\Users\vital\AppData\Local\Programs\Python\Python35-32\lib\site-packages\Crypto\Cipher\AES.py", line 114, in init blockalgo.BlockAlgo.init(self, _AES, key, *args, **kwargs) 
File "C:\Users\vital\AppData\Local\Programs\Python\Python35-32\lib\site-packages\Crypto\Cipher\blockalgo.py", line 401, in init self._cipher = factory.new(key, *args, **kwargs) 
ValueError: AES key must be either 16, 24, or 32 bytes long 

Process finished with exit code 1 

我在做什麼錯?

+0

它是3.5,這是pycrypto的版本2.7a1 – Tukanoid

回答

3

錯誤非常明顯。關鍵必須是這個尺寸。 os.urandom將返回正確的密鑰。但是,這個密鑰是字節(二進制字符串值)。此外,通過使用str(secret),將repr(secret)的值寫入文件而不是secret

更令人困惑的是,AES.new允許您將密鑰作爲Unicode傳遞!但是,假設密鑰是ASCII字節1234123412341234。現在,

f.write(str(secret)) 

會將b'1234123412341234'寫入文本文件!它現在包含那些16字節+ b和兩個'引用字符,而不是16字節;總共19個字節。

或者,如果你從os.urandom採取隨機二進制字符串,

>>> os.urandom(16) 
b'\xd7\x82K^\x7fe[\x9e\x96\xcb9\xbf\xa0\xd9s\xcb' 

現在,而不是寫16個字節D782,..等等,現在寫道,串到文件中。而且由於解密嘗試使用

"b'\\xd7\\x82K^\\x7fe[\\x9e\\x96\\xcb9\\xbf\\xa0\\xd9s\\xcb'" 

作爲解密密鑰,其中,當編碼爲UTF-8導致

b"b'\\xd7\\x82K^\\x7fe[\\x9e\\x96\\xcb9\\xbf\\xa0\\xd9s\\xcb'" 

這是一個49字節長bytes值發生錯誤。


您有2個不錯的選擇。要麼繼續將密鑰寫入文本文件,而要將其轉換爲十六進制,或將密鑰寫入二進制文件;那麼文件應該是字節中的密鑰長度。我打算在這裏後者:

因此用於存儲密鑰,使用

with open('aeskey.bin', 'wb') as keyfile: 
     keyfile.write(secret) 

with open('aeskey.bin', 'rb') as keyfile: 
     key = keyfile.read() 

同自然適用於密文(即加密二進制),您必須在二進制文件中寫入和讀取它:

with open('ciphertext.bin', 'wb') as f: 
     f.write(encoded) 

with open('ciphertext.bin', 'rb') as f: 
     encryptedString = f.read() 

如果你想爲base64編碼,千萬注意base64.b64encode/decodebytes -in/bytes退房手續。

順便說一句,plaintext是原始的,未加密的文本;加密的文本被稱爲ciphertext。 AES是一種密碼,可以將明文加密爲密文,並使用密鑰將密文解密爲明文。

儘管被稱爲「文本」,但它們都不是文本數據本身,正如Python所理解的那樣,但它們是二進制數據,應該表示爲bytes

+0

遺憾,但現在我有新的錯誤: ValueError異常:輸入的字符串必須是線16的長度 – Tukanoid

+0

多: 解碼= DecodeAES(密碼,加密) DecodeAES = lambda c,e:c.decrypt(base64.b64decode(e))。rstrip(PADDING) – Tukanoid

+1

@ВиталикЛукьянов同樣適用於您的密文!以二進制格式打開密文文件,並向其寫入二進制文件。它不是「明文」,也許不應該寫入名爲「plaintext.txt」的文件。 –

相關問題