2016-05-16 349 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.您的帮助&专长:)。