2012-12-17 126 views
1

我試圖在Python中實現以下內容: openssl enc -e -aes-256-cbc -base64 -k「密碼密碼」-in plaintext.txt -out ciphertext.txt在Python中實現OpenSSL AES加密

OpenSSL的ENC -d -AES-256-CBC -base64 -k 「祕密口令」 -in ciphertext.txt退房手續verification.txt

我已經嘗試了幾種不同的模塊,PyCrypto,M2Crypto等,但可以似乎沒有得到將密碼更改爲正確大小的密鑰並正確編碼所有內容的正確組合。我發現了https://github.com/nvie/SimpleAES,但基本上在命令行上運行OpenSSL,我寧願避免。

回答

5

可以通過標準的base64模塊輕鬆處理基礎64編碼和解碼。

PyCrypto和M2Crypto均支持CBC模式下的AES-256解密和加密。

唯一的非標準(也是最困難的)部分是從密碼派生出IV和密鑰。 OpenSSL通過它自己的EVP_BytesToKey函數來完成它,該函數被描述爲in this man page

Python的當量是:

def EVP_BytesToKey(password, salt, key_len, iv_len): 
    """ 
    Derive the key and the IV from the given password and salt. 
    """ 
    from hashlib import md5 
    dtot = md5(password + salt).digest() 
    d = [ dtot ] 
    while len(dtot)<(iv_len+key_len): 
     d.append(md5(d[-1] + password + salt).digest()) 
     dtot += d[-1] 
    return dtot[:key_len], dtot[key_len:key_len+iv_len] 

key_len哪裏是32和iv_len是16 AES-256。該函數返回可用於解密有效負載的密鑰和IV。

OpenSSL提供並期望鹽在加密有效負載的前8個字節中。

最後,CBC模式下的AES只能處理與16字節邊界對齊的數據。使用的默認填充是PKCS#7。因此

用於加密的步驟如下:

  1. 生成8個字節的隨機數據作爲鹽。
  2. 使用步驟1中的鹽從密碼中導出AES密鑰和IV。
  3. 使用PKCS#7填充輸入數據。
  4. 加密使用AES-256在CBC模式下與該鍵並從步驟2以Base64的IV
  5. 編碼和輸出從第1步
  6. 編碼在Base64和輸出加密的從步驟數據中的鹽的填充4.

從解密的步驟是相反的:

  1. 解碼從Base64的所述輸入數據爲二進制字符串。
  2. 將解碼數據的前8個字節視爲鹽。使用鹽從步驟1
  3. 解密
  4. 派生AES密鑰和IV從密碼的剩餘使用AES密鑰和從步驟3
  5. 的IV驗證並從結果中刪除PKCS#7填充解碼數據。