代码之家  ›  专栏  ›  技术社区  ›  mypython

pycrypto加密/解密,解密时丢失部分加密字符串

  •  0
  • mypython  · 技术社区  · 7 年前

    我正在尝试用python中的pycrypto加密/解密。在大多数情况下,工作都很顺利,但我在解密数据时遇到了一个奇怪的问题。我尝试对一些JPG进行加密/解密以进行测试,尽管它们加密/解密没有问题,但解密的文件无法打开/已损坏。为了找到问题,我保存了一个文本文件,其中有一个类似于“测试此文件的完整性布拉布拉布拉布拉”的随机句子,它只有在“…完整性布拉布拉布拉”之后才能正确解密,完整性之前的所有内容仍然是乱码。我对AES不太熟悉,但我假设这是一个编码/解码或填充错误。

    这是我的代码:

    #encryption
    iv = Random.new().read( AES.block_size)
    
    filePath = input("Path to file for encryption: ")
    selFile = open(filePath, 'rb')
    getBytes = bytes(selFile.read())
    
    encPW = input("Enter password: ")
    hashpw = hashlib.sha256(encPW.encode('UTF-8').digest())
    
    destination = input("Destination path for encrypted file: ")
    
    aes = AES.new(hashpw, AES.Mode_CFB, iv)
    encFile = base65.b64encode(aes.encrypt(getBytes))
    
    writetofile = open(destination, 'wb')
    writetofile.write(encFile)
    writetofile.close()
    print("Encryption successful")
    
    #Decryption
    iv = Random.new().read( AES.block_size)
    
    filePath = input("Path to file for decryption: ")
    selFile = open(filePath, 'rb')
    getBytes = bytes(selFile.read())
    
    decPW = input("Enter password: ")
    hashdecpw = hashlib.sha256(encPW.encode('UTF-8').digest())
    
    destination = input("Destination path for decrypted file: ")
    
    aes = AES.new(hashdecpw, AES.Mode_CFB, iv)
    decFile = aes.decrypt(getBytes)
    
    writetofile = open(destination, 'wb')
    writetofile.write(decFile)
    writetofile.close()
    print("Decryption successful")
    

    你知道是什么导致第一个字符丢失,阻止我正确加密/解密文件吗?

    2 回复  |  直到 7 年前
        1
  •  1
  •   Artjom B.    7 年前

    您至少有三个问题:

    • 你可能是说 hashlib.sha256(encPW.encode('UTF-8')).digest() hashlib.sha256(encPW.encode('UTF-8').digest()) (右括号位置错误)

    • 在将密文写入文件之前,您正在使用Base64对其进行编码。在解密之前,从文件中读回后,您忘记对其进行解码。例如:

      getBytes = base64.b64decode(bytes(selFile.read()))
      
    • 这是一个大问题:在解密期间,您需要与加密时使用的完全相同的IV。IV不是秘密的,但对于使用相同密钥进行的每一次加密,它都必须是唯一的。通常,IV写在密文前面,然后读回进行解密。

      #encryption
      encFile = base64.b64encode(iv + aes.encrypt(getBytes))
      
      #decryption
      getBytes = base64.b64decode(bytes(selFile.read()))
      iv = getBytes[:16]
      aes = AES.new(hashdecpw, AES.Mode_CFB, iv)
      decFile = aes.decrypt(getBytes[16:])
      
        2
  •  1
  •   Artjom B.    7 年前

    你正在生成一个新的IV,分别用于加密和解密,这就产生了这样的问题。以下是我的建议:

    def encrypt(inpath, outpath, password):
        iv = Random.new().read(AES.block_size)
        with open(inpath, "rb") as f:
            contents = f.read()
        # A context manager automatically calls f.close()
        key = pbkdf2.crypt(password, "")
        # See notes
    
        aes = AES.new(key, AES.Mode_CFB, iv)
        encrypted = aes.encrypt(contents)
        with open(outpath, "wb") as f:
            f.write(iv + b":")
            f.write(encrypted)
        print("Encryption successful")
    
    
    def decrypt(inpath, outpath, password):
        with open(inpath, "rb") as f:
            contents = f.read()
    
        iv, encrypted = contents.split(b":")
        key = pbkdf2.crypt(password, "")
        aes = AES.new(key, AES.Mode_CFB, iv)
    
        decrypted = aes.decrypt(contents)
        with open(outpath, "wb") as f:
            f.write(decrypted)
        print("Decryption successful")
    

    一些注意事项:

    • IV并不意味着是秘密的,因此它可以随机生成一次,然后写入一个文件,以便稍后用于解密(如本例所示)

    • 哈希算法不足以派生密钥,这就是为什么有称为密钥派生算法的特殊工具(如python中的PBKDF2)。用那些代替!