2016-05-16 64 views
0

我是Java密碼學的新手。我提供了以下PHP代碼來解密AES-256/CBC/ZeroBytePadding加密對象。如何解碼AES-256/CBC/ZeroBytePadding加密對象

function decrypt($key, $data) 
{ 
    if (!in_array(strlen($key), array(32, 48, 64))) 
{ 
    throw new Exception("Invalid key"); 
} 

$key_hex = pack('H*', $key); 

$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); 

$ciphertext = base64_decode($data); 

# retrieves the IV, iv_size should be created using mcrypt_get_iv_size() 
$iv_dec = substr($ciphertext, 0, $iv_size); 

# retrieves the cipher text (everything except the $iv_size in the front) 
$ciphertext_dec = substr($ciphertext, $iv_size); 

# may remove 00h valued characters from end of plain text 
$result = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key_hex, $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec); 

return $result; 
} 

我需要在java中做同樣的事情。經過大量的搜索我做了以下代碼:

public String decrypt(byte key[], String encrypted) 
      throws GeneralSecurityException { 
     if (key.length != 32 || key.length != 48 || key.length != 64) { 
      throw new IllegalArgumentException("Invalid key size."); 
     } 
    byte[] ciphertextBytes = Base64.decodeBase64(encrypted.getBytes()); 

    // Need to find the IV length here. I am using 16 here 

    IvParameterSpec iv = new IvParameterSpec(ciphertextBytes, 0, 16); 
    ciphertextBytes = Arrays.copyOfRange(ciphertextBytes, 16, 
      ciphertextBytes.length); 

    SecretKeySpec skeySpec = new SecretKeySpec(key, "AES"); 

    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); 
    cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); 
    byte[] original = cipher.doFinal(ciphertextBytes); 

    // remove zero bytes at the end 
    int lastLength = original.length; 
    for (int i = original.length - 1; i > original.length - 16; i--) { 
     if (original[i] == (byte) 0) { 
      lastLength--; 
     } else { 
      break; 
     } 
    } 

    return new String(original, 0, lastLength); 
} 

但我需要找到這裏的IV長度。在PHP中,他們使用: $ iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128,MCRYPT_MODE_CBC); 如何在java中實現它?有人可以幫我嗎?

我打電話的方法是這樣的:在CBC模式

public static void main(String args[]) { 
     String key =  "F5D4471791B79B6360C1EFF4A76250C1D7E5C23F5E4C3C43893B6CCAA796E307"; 
     String encrypted =  "F4N8SvpF1zgyMnQKwLlX\\/Dfgsj4kU58pg3kaSrt+AJt9D7\\/3vAfngegtytAdCUwwkQ2nxj8PVABRy0aaeBfsJN9n2Ltco6oPjdcmx8eOI"; 

    try { 
     String decrypted = decrypt(Hex.decodeHex(key.toCharArray()), encrypted); 
     System.out.println(decrypted); 
    } catch (GeneralSecurityException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

} 
+0

請不要編輯您的問題以包含答案。您可以發佈自己的問題的答案。完成之後,請將您的問題回滾至修訂4. –

+0

您問題中的答案使用的密鑰不是有效的十六進制編碼,因爲它包含0-9以外的字符,a-f,A-F。這段代碼應該會引發錯誤。 –

回答

2

一種IV爲AES(Rijndael算法-128)具有總是大小作爲塊,這是16個字節或128位相同。如果您繼續使用CBC模式,那麼您可以對該值進行硬編碼或使用Cipher#getBlockSize()

如果您想使用AES-256,則需要爲您的JRE/JDK(Link for Java 8)安裝Unlimited Strength策略文件。 AES-128可以不加修改地使用,但美國的出口限制要求你自己啓用更高的密鑰。

+0

感謝您的幫助。現在它給出了一個錯誤:無效的AES密鑰長度:64字節 – Ajit

+0

您沒有顯示那部分代碼。 –

+0

我已添加代碼。現在你能幫我嗎?我相信string.getByte()是所有問題的根源。 – Ajit

0

答案:在Artjom B的幫助下,我創建瞭解密AES-256/CBC/ZeroBytePadding加密字符串的代碼。我將這張貼發佈給需要幫助的其他人。

1.首先,您必須爲您的JDK版本下載Java加密擴展(JCE)無限強度管轄策略。

2.將zip文件解壓&把local_policy.jar &的US_export_policy.jar路徑/ JDK路徑/ JRE/lib/security中。這是必需的,因爲我的密鑰是64字節。 AES需要16/24/32字節的密鑰。

3.複製粘貼我的代碼&根據您的要求更改它:P。

import java.security.GeneralSecurityException; 
import java.util.Arrays; 
import javax.crypto.Cipher; 
import javax.crypto.spec.IvParameterSpec; 
import javax.crypto.spec.SecretKeySpec; 
import org.apache.commons.codec.DecoderException; 
import org.apache.commons.codec.binary.Hex; 
import org.apache.commons.codec.binary.Base64; 

public class Decryption { 

public static void main(String args[]) { 
//I have changed the original key. So mere copy pasting may not work. Put your key here. 
    String key = "FfDaaaaaaa444aaaa7aaEFF4A76efaaaaaE5C23F5E4C3adeaaaaaaCAA796E307"; 
    String encrypted = "8AQ8SvpF1zgyNyxKwLlX\\/cGzwLE5skU58pg3kaSrt+AJt9D7\\/3vaNRPZISIKMdCUwwkQ2nxj8PVABRy0aaeBfsJN9n2Ltco6oPjdcmx8eOI"; 
    String decrypted = ""; 
    try { 

     try { 
      decrypted = decrypt(Hex.decodeHex(key.toCharArray()), encrypted); 
     } catch (DecoderException e) { 
      e.printStackTrace(); 
     } 

     System.out.println(decrypted); 
    } catch (GeneralSecurityException e) { 
     e.printStackTrace(); 
    } 

} 

public static String decrypt(byte key[], String encrypted) 
     throws GeneralSecurityException { 
    /* 
    * if (key.length != 32 || key.length != 48 || key.length != 64) { throw 
    * new IllegalArgumentException("Invalid key size."); } 
    */ 
    byte[] ciphertextBytes = Base64.decodeBase64(encrypted.getBytes()); 

    IvParameterSpec iv = new IvParameterSpec(ciphertextBytes, 0, 16); 

    ciphertextBytes = Arrays.copyOfRange(ciphertextBytes, 16, 
      ciphertextBytes.length); 

    SecretKeySpec skeySpec = new SecretKeySpec(key, "AES"); 

    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); 
    cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); 
    byte[] original = cipher.doFinal(ciphertextBytes); 

    // Remove zero bytes at the end. 
    int lastLength = original.length; 
    for (int i = original.length - 1; i > original.length - 16; i--) { 
     if (original[i] == (byte) 0) { 
      lastLength--; 
     } else { 
      break; 
     } 
    } 

    return new String(original, 0, lastLength); 

} 

} 

感謝@Artjom B.您的幫助&專長:)。