工做中須要用python程序使用AES對java程序通過AES加密的文件進行解密,解密後的文件與源文件對比發現後面多了一些字符,查找資料發現原來java在對文件進行加密時,對不是16的整數倍數時會對文件進行補位,而python在解密時沒有將這些字符去掉。如下內容取自查找資料html
PyCrypto 是流行的 Python 加密/解密庫。可是其 AES 的 ECB 模式在加密解密時未提供適合的密文填充工具,所以有必要本身實現一個,下面是常見的 PKCS#5 / PKCS#7 填充模式的通常寫法:java
''' PKCS#5 padding is identical to PKCS#7 padding, except that it has only been defined for block ciphers that use a 64 bit (8 byte) block size. But in AES, there is no block of 8 bit, so PKCS#5 is PKCS#7. ''' BS = AES.block_size pad =lambda s: s +(BS - len(s)% BS)* chr(BS - len(s)% BS) unpad =lambda s : s[0:-ord(s[-1])]
在進行加密/解密前,只需使用 pad/unpad 進行填充/截斷便可。下面是具體實例:python
# -*- coding: utf-8 -*-fromCrypto.Cipherimport AES import os BS = AES.block_size pad =lambda s: s +(BS - len(s)% BS)* chr(BS - len(s)% BS) unpad =lambda s : s[0:-ord(s[-1])] key = os.urandom(16)# the length can be (16, 24, 32) text ='to be encrypted' cipher = AES.new(key) encrypted = cipher.encrypt(pad(text)).encode('hex')print encrypted # will be something like 'f456a6b0e54e35f2711a9fa078a76d16' decrypted = unpad(cipher.decrypt(encrypted.decode('hex')))print decrypted # will be 'to be encrypted'
提醒一點,PKCS#5 和 PKCS#7 惟一的區別就是前者規定了數據塊大小是 64 比特(8 字節),而 AES 中數據塊大小是 128 比特(16字節),所以在 AES 中, PKCS#5 和 PKCS#7 沒有區別。api
順便提一下,在 Java 中偶爾遇到以下方式獲取 AES 實例:oracle
Cipher cipher = javax.crypto.Cipher.getInstance("AES")
可是在文檔 Java™ Cryptography Architecture Standard Algorithm Name Documentation 以及Cipher Java doc 中並未直接說明這種方式所使用的模式以及填充方式。而AES默認的 ProviderAESCipher 中則有所說明,其使用的默認模式和填充方式正是 ECB 和 PKCS5Padding。今天寫一個 Python 工具須要與 Java 通信,我使用的 Java 庫正是使用上述方式構造 Cipher,因此進行了一番瞭解。dom
(轉自 http://likang.me/blog/2013/06/05/python-pycrypto-aes-ecb-pkcs-5/)ide