2010-09-30 51 views
0

[編輯:不要試圖理解整件事情,不要浪費時間來閱讀我的所有問題 - 只要記住解密工作到一定的位置......看我的回答解釋了爲什麼!]使用密碼和AES進行解密會得到208個解密字節,然後是垃圾

我得到了一個惱人的問題,在這裏我不知道如何解決的線索......

的系統加密的數據寫入到文件中,一些是序列化對象,其他文本(XML)文件。該基類,確實需要時解密初始化與AES加密密碼,準備一個鍵(從文件中讀取),並具有方式訪問數據:

一種方式來獲得一個InputStream:

public InputStream getInputStream(File pFile) throws IOException { 
    return 
    new CipherInputStream(
     new BufferedInputStream(new FileInputStream(pFile)), 
     getCipher(Cipher.DECRYPT_MODE) 
    ); 
} 

以及一種讀取對象的方法,該對象只是圍繞從此方法派生的InputStream包裝ObjectInputStream並使用ObjectInputStream.readObject()讀取對象。

現在。在軟件系統中,一切都以這種方式工作。 我想寫的是一個命令行工具來幫助解密文件以獲得支持。因此,我使用完全相同的方法來獲取我的密碼,甚至使用了相同的類和在那裏構建的InputStream。

但是:不管我做什麼:只有第一個208(!)字節被解密,其餘的都保持加密!

我試圖簡單地使用字節緩衝區將此InputStream中的數據「複製」到新的OutputStream中,但我也嘗試從數據中獲取一個String來查看調試器中發生了什麼。 =>效果總是相同的。直到208字節的這個「邊界」,我看到明文 - 接着是垃圾。

我不知道這裏會出現什麼問題!任何線索?

密碼被創建這樣的:

public Cipher getCipher(int opMode) throws IOException { 
    Cipher cipher = null; 

    try { 
     cipher = Cipher.getInstance("AES"); 
    } catch (NoSuchAlgorithmException e) { 
     throw new MdmFatalInternalErrorException("Getting instance of cipher failed. Should never happen. BUG ", e); 
    } catch (NoSuchPaddingException e) { 
     throw new MdmFatalInternalErrorException("Getting instance of cipher failed. Should never happen. BUG ", e); 
    } 
    try { 
     cipher.init(opMode, readKey()); 
    } catch (InvalidKeyException e) { 
     throw new MdmInvalidKeyException(); 
    } catch (ClassNotFoundException e) { 
     throw new MdmInvalidKeyException(); 
    } catch (NumberFormatException e) { 
     throw new MdmInvalidKeyException(); 
    } 
    return cipher; 
} 

所以,這裏的實際使用InputStream的軟件系統代碼:

String s = readStream(reader.getInputStream(file)); 

其中readStream是這樣實現的:

public String readStream(InputStream is) throws IOException { 
    BufferedReader reader = new BufferedReader(new InputStreamReader(is)); 

    StringBuffer sb = new StringBuffer(); 
    String line = null; 
    try { 
     while ((line = reader.readLine()) != null) { 
      sb.append(line).append('\n'); 
     } 
    } finally { 
     reader.close(); 
    } 

    return sb.toString(); 
} 

所有這些工作(在軟件內)! 但我嘗試以同樣的方式讀取失敗:字符串s包含208個解密字符,然後是垃圾!

XML文件的寫入完全是通過其他方式完成的,但這裏並不重要,因爲顯示的代碼在系統內工作,但不在我的簡單複製程序中!我在那裏使用完全相同的課程! 爲什麼地球上只有208個字符被解密?

謝謝!

編輯:現在很清楚,只獲得一定數量的字節解密的效果取決於操作系統和機器!在使用32位Java 1.6 Update 20的Windows操作系統上,它無法解密 - 在具有64位Java 1.6 Update 18的Linux機器上工作!

所以 - 這是挑戰:有人知道如何幹擾輸出?

+0

你不顯示,這是否從閱讀代碼InputStream也不寫。 – 2010-09-30 23:07:07

回答

0

這是一點點尷尬 - 但我留下這個(回答!)問題在這裏萬一有人遇到類似的問題!

我得到的xx字節正確解密後跟垃圾桶的原因很容易解釋 - 對我很恥辱!

我們在Linux系統上加密了XML文件。系統內部的解密工作正常;但是每當我嘗試在我的Windows機器上解密它們時,它都會像描述的那樣失敗。

爲什麼?因爲這些文件的擴展名是XML格式,所以我的WinScp FTP工具將帶有XML擴展名的文件視爲文本文件-並用CR LF(#13#10)替換每個LF(#10)!

因此,解密工作正常,直到第一個愚蠢的CR字符被擊中! :-(

所以,我們學習!永不放棄的二進制文件的文本文件的擴展名,除非你想麻煩 * *

1

AES是一個分組密碼,所以它必須加密一個精確大小的塊(16字節)。當你加密數據時,你必須確保它可以分成16個字節的塊;如果最後一個塊比這個塊短,你可以得到一個Exception或者你可以得到垃圾(因爲緩衝流的工作方式)。如果您不想因手動填充數據而煩惱,則可以將密碼設置爲使用PKCS5Padding。您不必調用Cipher.getInstance(「AES」),而必須使用Cipher.getInstance(「AES/ECB/PKCS5Padding」),並且您必須在兩邊執行此操作。另外,我建議使用CBC或CFB,這些模式需要一個初始化向量(鹽),但它比使用ECB更好,這與使用非模式相同,這意味着您只是獨立加密每個塊所以任何塊都可以單獨破解。如果您使用CBC或CFB然後破解您需要破解前一個塊的數據塊(CBC代表密碼塊鏈接)。

最後但並非最不重要...如果你想通過流加密數據中,可以使用流密碼RC4一樣,而不是分組密碼會更好。