2012-08-30 87 views
1

我有一個奇怪的問題......沒有什麼解密加密後我

立足我的解決方案上Decrypting a hardcoded file as byte[]

所以,我寫了一個小的Cypher類幫忙的crypting /解密......它用來模擬某個地方的硬編碼密鑰,並在另一個地方存儲另一個預密鑰。但這有點不相關atm。

的crypting過程是這樣的:

  • 檢索硬編碼的字節數組
  • 使用它來解密KEY2
  • 使用KEY2解密數據
  • 使用KEY1進一步解密數據
  • 已解密的數據

我是sto將加密的數據作爲一個十六進制的字符串進行響鈴,使用這兩個函數進入那裏

private static String byteArrayToHexString(byte[] b) 
{ 
    StringBuffer sb = new StringBuffer(b.length * 2); 
    for (int i = 0; i < b.length; i++) 
    { 
     int v = b[i] & 0xff; 
     if (v < 16) 
     { 
      sb.append('0'); 
     } 
     sb.append(Integer.toHexString(v)); 
    } 
    return sb.toString().toUpperCase(); 
} 

private static byte[] hexStringToByteArray(String s) 
{ 
    byte[] b = new byte[s.length()/2]; 
    for (int i = 0; i < b.length; i++) 
    { 
     int index = i * 2; 
     int v = Integer.parseInt(s.substring(index, index + 2), 16); //THIS LINE 
     b[i] = (byte) v; 
    } 
    return b; 
} 

完美地工作;事實上它工作得很好,我在我的真實項目中實現了它。由於我沒有徹底測試,該項目未能運行。

發現它隱藏/解密幾乎所有的文件,除了一個 - 其中一個不想解密。

但是我確定了這個問題 - 這行引發了一個IllegalNumberFormat異常;在某些時候,我也熟悉了http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6259307。如果有人介紹一種方法來繞過一個長度爲2的字符串被轉換爲四個字節,並拋出一個IllegalNumberFormatException,那麼我會和可以恢復到這種方法。因此,我認爲,由於我無法解碼文件(顯然無法在這裏分享給大家試用),所以我需要對它進行一定的轉換,以使其更安全。輸入Base64Coder類,編碼爲base64字符串...

這似乎引發了一個新問題 - 填充得到了提高。

問題很簡單 - 我做錯了什麼?我需要符合這些數據,它必須能夠正確和平等地進行加密/解密。我想就最輕量級的解決方案提供最少複製/粘貼的建議......僞代碼在這裏不會成功。

這裏是我現在正在做的事情....

public static char[] encrypt2(byte[] value) throws GeneralSecurityException, IOException 
{ 
    SecretKeySpec key1 = getSecretKeySpec(true); 
    System.err.println("encrypt():\t" + key1.toString()); 
    Cipher cipher = Cipher.getInstance(CRYPTOSYS); 
    cipher.init(Cipher.ENCRYPT_MODE, key1, cipher.getParameters()); 
    byte[] encrypted = cipher.doFinal(value); 

    SecretKeySpec key2 = getSecretKeySpec(false); 
    cipher = Cipher.getInstance(CRYPTOSYS); 
    cipher.init(Cipher.ENCRYPT_MODE, key2, cipher.getParameters()); 
    byte[] encrypted2 = cipher.doFinal(encrypted); 

    return Base64Coder.encode(encrypted2); 
} 

public static byte[] decrypt2(char[] message) throws GeneralSecurityException, IOException 
{ 
    SecretKeySpec key1 = getSecretKeySpec(false); 
    System.err.println("decrypt():\t" + key1.toString()); 
    Cipher cipher = Cipher.getInstance(CRYPTOSYS); 
    cipher.init(Cipher.DECRYPT_MODE, key1); 
    byte[] decrypted = cipher.doFinal(Base64Coder.decode(message)); 

    SecretKeySpec key2 = getSecretKeySpec(true); 
    cipher = Cipher.getInstance(CRYPTOSYS); 
    cipher.init(Cipher.DECRYPT_MODE, key2); 
    byte[] decrypted2 = cipher.doFinal(decrypted); 

    return decrypted2; 
} 

注意鍵用於測試目的目前完全暴露(硬編碼)。

這裏是我的測試用例

public static void main(String... args) throws Exception 
{ 
    //  byte[] data = "hello".getBytes(); 
    File PEM = new File(PATH_TO_FILES + SOURCE_PEM); 
    File DER = new File(PATH_TO_FILES + SOURCE_DER); 
    File cryptoPEM = new File(PATH_TO_FILES + "cryptopem"); 
    File cryptoDER = new File(PATH_TO_FILES + "cryptoder"); 

    byte[] cryptokey = encryptA(ASSET_KEY); 
    System.out.println(new String(cryptokey)); 

    //pem key 
    System.out.println("PEM"); 
    byte[] data = getBytesFromFile(PEM); 
    char[] crypted = encrypt2(data); 
    //  FileOutputStream fos = new FileOutputStream(cryptoPEM); 
    FileWriter fw = new FileWriter(cryptoPEM); 
    fw.write(crypted); 
    fw.flush(); 

    //der key 
    System.out.println("DER"); 
    data = getBytesFromFile(DER); 
    crypted = encrypt2(data); 
    fw = new FileWriter(cryptoDER); 
    fw.write(crypted); 
    fw.flush(); 

    //opentext 
    System.out.println("checking PEM..."); 
    crypted = Base64Coder.encode(getBytesFromFile(cryptoPEM)); 
    byte[] decrypted = decrypt2(crypted, false); 
    byte[] decryptedData = decrypted; 

    if (!Arrays.equals(getBytesFromFile(PEM), decryptedData)) { throw new Exception("PEM Data was not decrypted successfully"); } 

    System.out.println("checking DER..."); 
    crypted = Base64Coder.encode(getBytesFromFile(cryptoDER)); 
    decrypted = decrypt2(crypted, false); 
    decryptedData = decrypted; 

    if (!Arrays.equals(getBytesFromFile(DER), decryptedData)) { throw new Exception("DER Data was not decrypted successfully"); } 
} 

現在我得到一個InvalidBlockSizeException ....請,有人流下了這方面的一些情況,我只是希望這個工作......

將「key2」替換爲稍後在「AES/CBC/PKCS5Padding」中使用的IV是我現在正在考慮的選項。基本上除了第二步加密之外,沒有什麼會改變。從理論上講,我會保持相同 - 除非有更好的解決方案。

當時我想指出的是,這是一個程序員的問題,而不是一個IT安全問題的學生適當的這樣的代碼非常看重比覆蓋不大可能邊緣的情況下理論上的響應更加結束。

編輯: 好吧,我不能給你導致IllegalNumberFormatException的數字,因爲我今天早上丟失了代碼。我似乎無法複製這個問題,所以我猜想這個部分是沒有用的。

下面是從樣品測試輸出:

encrypt(): [email protected] 
[email protected]��_׵G�j��!�c;D�i�lR?z�j\ 
PEM 
encrypt(): [email protected] 
DER 
encrypt(): [email protected] 
checking PEM... 
decrypt(): [email protected] 
Exception in thread "main" javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher 

這意味着Base64是有點搞亂起來......

+0

什麼是輸入到'Integer.parseInt()'的輸入值,它引發異常?這本身不應包含任何祕密信息,但對幫助您非常有用。 –

+0

是的,我不難發現那條信息。 它遇到的標記線在某些時候(正如你所看到的,它應該採取兩個十六進制字母),直到它擊中這些字節(兩個字母) - 0 *與字節[47,-61,-67,-65 ]當我再次捕捉到他們時,我會更新我的答案,就像我說的 - 我可以恢復。 – Shark

+0

你有沒有嘗試過Byte.parseByte(stringRepresentationOfByte,16)而不是Integer.parseInt(...)? – Buhb

回答

0

今天上午審查代碼和調整一點點我得到它的工作之後。

public static byte[] encrypt2(byte[] value) throws GeneralSecurityException, IOException 
{ 
    SecretKeySpec key1 = getSecretKeySpec(true); 
    System.err.println("encrypt():\t" + key1.toString()); 
    Cipher cipher = Cipher.getInstance("AES"); 
    cipher.init(Cipher.ENCRYPT_MODE, key1, cipher.getParameters()); 
    byte[] encrypted = cipher.doFinal(value); 

    SecretKeySpec key2 = getSecretKeySpec(false); 
    System.err.println("encrypt():\t" + key2.toString()); 
    cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
    cipher.init(Cipher.ENCRYPT_MODE, key2, new IvParameterSpec(getIV())); 
    byte[] encrypted2 = cipher.doFinal(encrypted); 

    return encrypted2;//Base64Coder.encode(encrypted2); 
} 

public static byte[] decrypt2(byte[] message, boolean A) throws GeneralSecurityException, IOException 
{ 
    SecretKeySpec key1 = getSecretKeySpec(false); 
    System.err.println("decrypt():\t" + key1.toString()); 
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
    cipher.init(Cipher.DECRYPT_MODE, key1, new IvParameterSpec(getIV())); 
    byte[] decrypted = cipher.doFinal(message); 

    SecretKeySpec key2 = getSecretKeySpec(true); 
    System.err.println("decrypt():\t" + key2.toString()); 
    cipher = Cipher.getInstance("AES"); 
    cipher.init(Cipher.DECRYPT_MODE, key2); 
    byte[] decrypted2 = cipher.doFinal(decrypted); 

    return decrypted2; 
} 
1

我認爲這個問題是在這裏:

//opentext 
System.out.println("checking PEM..."); 
crypted = Base64Coder.encode(getBytesFromFile(cryptoPEM)); 

以前,你寫的char []的文件,但現在你從文件讀取的一個的byte [] d在base64中重新編碼。該文件的內容應該已經base64編碼!

你需要一個叫做getCharsFromFile新的函數,返回的char []或字符串,並通過直接向decrypt2。

+0

當我使用一個讀取char []的FileReader時,我得到一個填充異常。 – Shark

相關問題