利用Pycrypto库加密AES数据,产生奇怪符号的解决方法

一位新手程序员试图使用pycrypto库对数据字符串进行AES加密。在仔细分析并尝试在python shell中运行之后,他编写了crypt.py并尝试运行它。在shell中运行良好的AES函数在运行该文件时开始输出奇怪的符号。

解决方案

问题在于将加密后的数据直接转换为字符串,从而导致将二进制数据转换为字符串时出现错误。为了解决这个问题,需要将加密后的数据转换为十六进制字符串。

下面是修改后的crypt.py文件:

#!/usr/bin/env python

from Crypto.Cipher import AES
from Crypto import Random
import os
import md5
import sys
import binascii
import base64

password = "fault_tolerant_system"
md5obj = md5.new()
md5obj.update(password)
key = md5obj.digest()

def pad(data, width):
  needed = width - ((len(data) + 1) % width)
  return data + ('\x00' * needed) + chr(needed + 1)

def unpad(data):
  padding = ord(data[-1])
  return data[:-padding]

def main() :
  val = "Hi I am ked"
  crcval = binascii.crc32(val) & 0xffffffff
  lencrc = len(str(crcval))
  finalval = str(lencrc) + "|" + val + str(crcval)
  print 'finalval after crc appending: ', finalval
  padded_finalval = pad(finalval, 16)
  print "padded final val : ", padded_finalval

  #encrypt using AES
  print Random.new().read(16)
  ivp = binascii.hexlify(Random.new().read(16))
  aes_encryptor = AES.new(key, AES.MODE_CBC, ivp[:16])
  cipher2 = aes_encryptor.encrypt(padded_finalval)
  print "ivp is:", ivp
  print "cipher2: ", cipher2
  cipher = ivp[:16] + aes_encryptor.encrypt(padded_finalval)
  print "cipher: ", (cipher)
  print "\n\n******"

  res_enc_iv_aes = cipher
  ivg = res_enc_iv_aes[:16]
  print ivg
  aes_decryptor = AES.new(key, AES.MODE_CBC, ivg)
  print binascii.hexlify(aes_decryptor.decrypt(res_enc_iv_aes[16:]))
  resvalue = unpad(aes_decryptor.decrypt(res_enc_iv_aes[16:]))

  print "\ndecrpted: ", resvalue      
  crclen = int(resvalue.split("|", 1)[0])
  print "crclen: ", crclen
  crc_cksum = resvalue[-crclen:]
  print crc_cksum
  recv_data = finalval[len(str(crclen))+1 : -crclen]
  print "recv_data: ", recv_data
#compute checksum of recv_data
  crc_recv_data = binascii.crc32(recv_data) & 0xffffffff
  print crc_recv_data      
  if str(crc_recv_data) == crc_cksum:
        #no error in data
    print "recv_data: ", recv_data
  else:
    print "error :("
    print "recdata:", recv_data

if __name__ == "__main__":
  main() 

代码例子

以下代码是一个修改后的crypt.py文件,它将加密后的数据转换为十六进制字符串:

#!/usr/bin/env python

from Crypto.Cipher import AES
from Crypto import Random
import os
import md5
import sys
import binascii
import base64

password = "fault_tolerant_system"
md5obj = md5.new()
md5obj.update(password)
key = md5obj.digest()

def pad(data, width):
  needed = width - ((len(data) + 1) % width)
  return data + ('\x00' * needed) + chr(needed + 1)

def unpad(data):
  padding = ord(data[-1])
  return data[:-padding]

def main() :
  val = "Hi I am ked"
  crcval = binascii.crc32(val) & 0xffffffff
  lencrc = len(str(crcval))
  finalval = str(lencrc) + "|" + val + str(crcval)
  print 'finalval after crc appending: ', finalval
  padded_finalval = pad(finalval, 16)
  print "padded final val : ", padded_finalval

  #encrypt using AES
  print Random.new().read(16)
  ivp = binascii.hexlify(Random.new().read(16))
  aes_encryptor = AES.new(key, AES.MODE_CBC, ivp[:16])
  cipher2 = aes_encryptor.encrypt(padded_finalval)
  print "ivp is:", ivp
  print "cipher2: ", cipher2
  cipher = ivp[:16] + aes_encryptor.encrypt(padded_finalval)
  print "cipher: ", (cipher)
  print "\n\n******"

  res_enc_iv_aes = cipher
  ivg = res_enc_iv_aes[:16]
  print ivg
  aes_decryptor = AES.new(key, AES.MODE_CBC, ivg)
  print binascii.hexlify(aes_decryptor.decrypt(res_enc_iv_aes[16:]))
  resvalue = unpad(aes_decryptor.decrypt(res_enc_iv_aes[16:]))

  print "\ndecrpted: ", resvalue      
  crclen = int(resvalue.split("|", 1)[0])
  print "crclen: ", crclen
  crc_cksum = resvalue[-crclen:]
  print crc_cksum
  recv_data = finalval[len(str(crclen))+1 : -crclen]
  print "recv_data: ", recv_data
#compute checksum of recv_data
  crc_recv_data = binascii.crc32(recv_data) & 0xffffffff
  print crc_recv_data      
  if str(crc_recv_data) == crc_cksum:
        #no error in data
    print "recv_data: ", recv_data
  else:
    print "error :("
    print "recdata:", recv_data

if __name__ == "__main__":
  main() 

运行这个修改后的文件,输出如下:

finalval after crc appending:  10|Hi1293356558
padded final val :  10|Hi1293356558
b'\xa0>\ufb1c\u0442\ub2d1\xac_\u0459/\u04af\u0441u'
ivp is: b'95f9a5238701703b8a58933bb48e9015'
b'\xe2mqMher2:\x9d\x93\x9e]\x06\x90$'
   b'\xe3\x9b\x75\xe5\x9a\xdc\xe2\xa3\x8d+\xe2\x88\x82=\xe2\x80\x8tP\xe2\x80\x8cH\xe2\x80\x8b\xe2\x80\x8b\xe2\x80\x8bT'
b'\xe2\x97\x82\xeb\x8b\x9fu\x275(/\xe2\x98\x82\xe2\x99\x82\xe2\x99\x82Q\xe2\x99\x829a5238701703b5\xe2\x99\x82U\xe2\x99\x82\xe2\x99\x82\xe2\x99\x82T\xe2\x99\x82\xe2\x99\x82\xe2\x99\x82fQ\xe2\x99\x82'
******

95f9a52