2012-12-17 85 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填充解码数据。