2017-07-04 3 views
0

私はJavaでデータファイルを暗号化し、Pythonで解読しようとしています。Pythonのjava解読でAES/CBC/PKCS5Paddingの暗号化が正しく行われない

復号化されたデータファイルは、常にこの

my normal content^@^@^@^@^@ 

remainslikeいくつかのパディングバイトを得たI実際にPythonコードでUNPADアクション(FUNC decrypt_file())

を行うと、私はUNPADのアクションを削除する場合私はこれを持っています:

my normal content^@^@^@^@^@^P^P^P^P^P^P^P^P^P^P^P^P^P^P^P^P 

だから、Javaの暗号化メソッドはTWICEを埋め尽くしたようです。

私はとても混乱しており、ここにはまっています。誰でも助けることができますか?どうもありがとう!

ここに私のコードです。あなただけのデフォルトモードを使用して試してみて、ENC/12月時にこの問題が発生した場合

(1)Javaのバージョン

import java.io.File; 
import javax.crypto.Cipher; 
import javax.crypto.spec.IvParameterSpec; 
import javax.crypto.spec.SecretKeySpec; 

public class AESUtil { 
    private static final String key = "wesurexZ5!Hcurfit"; 
    private static final String ivs = "zK2hzBvP%FRJ5%lD"; 
    public static byte[] encrypt(byte[] strInBytes) throws Exception { 
     SecretKeySpec skeySpec = getKey(key); 
     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     IvParameterSpec iv = new IvParameterSpec(ivs.getBytes("UTF-8")); 
     cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv); 
     return cipher.doFinal(strInBytes); 
    } 

    public static byte[] decrypt(byte[] strIn) throws Exception { 
     SecretKeySpec skeySpec = getKey(key); 
     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     IvParameterSpec iv = new IvParameterSpec(ivs.getBytes("UTF-8")); 
     cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); 
     byte[] decrypted = cipher.doFinal(strIn); 
     return decrypted; 
    } 

    private static SecretKeySpec getKey(String strKey) throws Exception { 
     byte[] arrBTmp = strKey.getBytes(); 
     byte[] arrB = new byte[16]; 
     for (int i = 0; i < arrBTmp.length && i < arrB.length; i++) { 
      arrB[i] = arrBTmp[i]; 
     } 
     SecretKeySpec skeySpec = new SecretKeySpec(arrB, "AES"); 
     return skeySpec; 
    } 
} 

(2)Pythonのバージョン

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 

import sys 

reload(sys) 
sys.setdefaultencoding("utf-8") 

from Crypto.Cipher import AES 


class AESTool(object): 

    def __init__(self, iv, key): 
     self.iv = iv.decode("utf8") 
     self.key = key 
     bs = AES.block_size 
     self.pad = lambda s: s + (bs - len(s) % bs) * chr(bs - len(s) % bs) 
     self.unpad = lambda s: s[0:-ord(s[-1])] 

    def encrypt(self, plain_text): 
     try: 
      encryptor = AES.new(self.key, AES.MODE_CBC, self.iv) 
      encrypted_text = encryptor.encrypt(self.pad(plain_text)) 
     except Exception as ex: 
      raise Exception(ex.message) 

     return encrypted_text 

    def decrypt(self, decrypted_text): 
     try: 
      decryptor = AES.new(self.key, AES.MODE_CBC, self.iv) 
      plain_text = decryptor.decrypt(decrypted_text) 
     except Exception as ex: 
      raise Exception(ex.message) 

     return self.unpad(plain_text) 

    def encrypt_file(self, from_full_path, to_full_path, chunksize=64*1024): 
     encryptor = AES.new(self.key, AES.MODE_CBC, self.iv) 
     try: 
      with open(from_full_path, 'rb') as infile: 
       with open(to_full_path, 'wb') as outfile: 
        while True: 
         chunk = infile.read(chunksize) 

         if len(chunk) == 0: 
          break 

         if len(chunk) < chunksize: 
          outfile.write(encryptor.encrypt(self.pad(chunk))) 
          break 

         outfile.write(encryptor.encrypt(chunk)) 
     except Exception as ex: 
      return -1 

     return 0 

    def decrypt_file(self, from_full_path, to_full_path, chunksize=64*1024): 
     decryptor = AES.new(self.key, AES.MODE_CBC, self.iv) 
     try: 
      with open(from_full_path, 'rb') as infile: 
       with open(to_full_path, 'wb') as outfile: 
        prev_chunk = None 
        while True: 
         chunk = infile.read(chunksize) 

         if len(chunk) == 0 and prev_chunk: 
          outfile.write(self.unpad(decryptor.decrypt(prev_chunk))) 
          break 

         if prev_chunk: 
          outfile.write(decryptor.decrypt(prev_chunk)) 

         if len(chunk) < chunksize: 
          outfile.write(self.unpad(decryptor.decrypt(chunk))) 
          break 

         prev_chunk = chunk 
     except Exception as ex: 
      return -1 

     return 0 
+1

IVは、暗号化ごとにランダムで異なる必要があります。 – zaph

+0

@zaph固定IVの再利用がセキュリティ上の問題を引き起こす可能性があることを知りました。しかし、どうすればこのような機能上の問題が生じるのでしょうか?私はそれを得ていない、あなたは私を埋めることができますか?どうもありがとうございました。 – RonnieTsang

+0

このコメントはOPのためのものではなく、将来の読者のためのもので、問題の固定IVはセキュリティが貧弱であることを指摘しています。 – zaph

答えて

-1

をあなたは知っていますか?それが事実なら、私たちは同じ問題を抱えているので、好奇心が強い。デフォルトでは、次のように指定しています。

Cipher cipher = Cipher.getInstance("AES"); 

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
+0

あなたの情報に感謝します。私は既定のモードが以前に同じ問題を抽出可能に持つことができるかどうかはわかりませんでした。しかし、確かに異なるプラットフォーム間で暗号化/復号化すると、不確実性のパディング関連の問題が発生する可能性があります。私はエースを使用するプラットフォームを横断する方法を模索しており、私は[aes-cross](https://github.com/keel/aes-cross)を見つけました。著者の結論は「プラットフォーム上でAES/CBC/PKCS5Paddingへの道を見つけるなら、既にクロスプラットフォームのAESソリューションを手に入れている」だから私のコードは – RonnieTsang

+0

の上に来るモードやパディングなどの暗号化属性を完全に指定するのが最善です。 – zaph

関連する問題