2012-09-28 17 views
9

पढ़ता है मैं एईएस का उपयोग कर फ़ाइलों को एन्क्रिप्ट करने के लिए सिफर इनपुटपुट और सिफर आउटपुटस्ट्रीम का उपयोग कर रहा हूं।सिफर इनपुटस्ट्रीम केवल 16 बाइट्स (एईएस/जावा)

encrypt(...) ठीक काम कर रहा है, लेकिन मेरा decrypt(...) फ़ंक्शन केवल मेरी फ़ाइलों के पहले 16 बाइट्स को डिक्रिप्ट करता है।

public class AESFiles { 

    private byte[] getKeyBytes(final byte[] key) throws Exception { 
     byte[] keyBytes = new byte[16]; 
     System.arraycopy(key, 0, keyBytes, 0, Math.min(key.length, keyBytes.length)); 
     return keyBytes; 
    } 

    public Cipher getCipherEncrypt(final byte[] key) throws Exception { 
     byte[] keyBytes = getKeyBytes(key); 
     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES"); 
     IvParameterSpec ivParameterSpec = new IvParameterSpec(keyBytes); 
     cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); 
     return cipher; 
    } 

    public Cipher getCipherDecrypt(byte[] key) throws Exception { 
     byte[] keyBytes = getKeyBytes(key); 
     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES"); 
     IvParameterSpec ivParameterSpec = new IvParameterSpec(keyBytes); 
     cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); 
     return cipher; 
    } 

    public void encrypt(File inputFile, File outputFile, byte[] key) throws Exception { 
     Cipher cipher = getCipherEncrypt(key); 
     FileOutputStream fos = null; 
     CipherOutputStream cos = null; 
     FileInputStream fis = null; 
     try { 
      fis = new FileInputStream(inputFile); 
      fos = new FileOutputStream(outputFile); 
      cos = new CipherOutputStream(fos, cipher); 
      byte[] data = new byte[1024]; 
      int read = fis.read(data); 
      while (read != -1) { 
       cos.write(data, 0, read); 
       read = fis.read(data); 
       System.out.println(new String(data, "UTF-8").trim()); 
      } 
      cos.flush(); 
     } finally { 
      fos.close(); 
      cos.close(); 
      fis.close(); 
     } 
    } 

    public void decrypt(File inputFile, File outputFile, byte[] key) throws Exception { 
     Cipher cipher = getCipherDecrypt(key); 
     FileOutputStream fos = null; 
     CipherInputStream cis = null; 
     FileInputStream fis = null; 
     try { 
      fis = new FileInputStream(inputFile); 
      cis = new CipherInputStream(fis, cipher); 
      fos = new FileOutputStream(outputFile); 
      byte[] data = new byte[1024]; 
      int read = cis.read(data); 
      while (read != -1) { 
       fos.write(data, 0, read); 
       read = cis.read(data); 
       System.out.println(new String(data, "UTF-8").trim()); 
      } 
     } finally { 
      fos.close(); 
      cis.close(); 
      fis.close(); 
     } 
    } 

    public static void main(String args[]) throws Exception { 
     byte[] key = "mykey".getBytes("UTF-8"); 
     new AESFiles().encrypt(new File("C:\\Tests\\secure.txt"), new File("C:\\Tests\\secure.txt.aes"), key); 
     new AESFiles().decrypt(new File("C:\\Tests\\secure.txt.aes"), new File("C:\\Tests\\secure.txt.1"), key); 
    } 
} 

तो मेरे सवाल, क्यों decrypt समारोह केवल पहले 16 बाइट्स पढ़ा जाता है:

यहाँ मेरी कक्षा है?

+0

आप कैसे जानते हैं कि यह केवल 16 बाइट्स को डिक्रिप्ट करता है? क्या आप अपना अपवाद दिखाने के लिए अपनी पोस्ट संपादित कर सकते हैं? – Gray

+0

मुझे कोई अपवाद नहीं मिल रहा है। फ़ाइल "secure.txt.1" (डिक्रिप्ट की गई फ़ाइलों) के आकार में केवल 16 बाइट हैं, जबकि स्रोत में 41 बाइट हैं। – Joshua

+0

ध्यान दें कि 'CipherInputStream' का उपयोग करना बहुत मुश्किल है क्योंकि यह कालीन के नीचे अपवादों को मिटा देता है (यह एक कहानियां है जिसका अर्थ है कि यह उन्हें छुपाता है)। मैं इसे खुद का उपयोग नहीं करता। –

उत्तर

12

यह बहुत सूक्ष्म है। आपकी समस्या यह है कि आप अपने से पहले cos बंद कर रहे हैं। अपने encrypt(...) विधि में आप कर रहे हैं:

} finally { 
    fos.close(); 
    cos.close(); 
    fis.close(); 
} 

कि CipherOutputStream तो एन्क्रिप्टेड उत्पादन के अंतिम गद्देदार ब्लॉक कभी नहीं आउटपुट फ़ाइल के लिए लिखा जाता है के नीचे से FileOutputStream बाहर बंद कर देता है।cos के बाद fosबंद करें तो आपके कोड को ठीक काम करना चाहिए।

वास्तव में, आप की तरह कुछ कर रही पर विचार करना चाहिए:

FileOutputStream fos = null; 
    CipherOutputStream cos = null; 
    FileInputStream fis = null; 
    try { 
     fis = new FileInputStream(inputFile); 
     fos = new FileOutputStream(outputFile); 
     cos = new CipherOutputStream(fos, cipher); 
     // once cos wraps the fos, you should set it to null 
     fos = null; 
     ... 
    } finally { 
     if (cos != null) { 
      cos.close(); 
     } 
     if (fos != null) { 
      fos.close(); 
     } 
     if (fis != null) { 
      fis.close(); 
     } 
    } 

FYI करें: org.apache.commons.io.IOUtils एक महान closeQuietly(...) तरीका है जिसके null चेकों संभालती है और आप के लिए अपवाद पकड़ता है।

+0

वाह! बहुत बहुत धन्यवाद!!! – Joshua

+0

बहुत अच्छा समाधान .. –

+1

अब तक इसे संसाधनों के साथ प्रयास करके संभाला जा सकता है। ध्यान दें कि आप 'try' कथन में कई धाराएं निर्दिष्ट कर सकते हैं, जो स्वचालित रूप से बंद हो जाएंगे - और निश्चित रूप से - दाएं (विपरीत) क्रम में। –

संबंधित मुद्दे