简体   繁体   English

如何解码AES-256 / CBC / ZeroBytePadding加密对象

[英]How to decode a AES-256 / CBC / ZeroBytePadding encrypted object

I am pretty new in Java Cryptography.I have provided with the following PHP code to decrypt a AES-256 / CBC / ZeroBytePadding encrypted object. 我是Java密码学的新手,我提供了以下PHP代码来解密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;
}

I need to do the same in java. 我需要在Java中执行相同的操作。 After lots of searching I have made the following code: 经过大量搜索,我编写了以下代码:

 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);
}

But I need to find the IV length here. 但是我需要在这里找到IV长度。 In PHP they are doing this using: $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); 在PHP中,他们使用以下方法执行此操作:$ iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128,MCRYPT_MODE_CBC); How to implement it in java? 如何在Java中实现它? Can anybody help me please? 有人可以帮我吗?

I am calling the method like this: 我正在这样调用方法:

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();
    }

}

An IV for AES (Rijndael-128) in CBC mode has always the same size as the block, which is 16 bytes or 128 bits. 在CBC模式下,用于AES的IV(Rijndael-128)始终与块大小相同,为16字节或128位。 If you keep using CBC mode, then you can hardcode that value or use Cipher#getBlockSize() . 如果继续使用CBC模式,则可以对该值进行硬编码或使用Cipher#getBlockSize()

If you want to use AES-256, then you need to install the Unlimited Strength policy files for your JRE/JDK ( Link for Java 8 ). 如果要使用AES-256,则需要为JRE / JDK( Java 8的链接 )安装Unlimited Strength策略文件。 AES-128 can be used without modification, but the US export restrictions require that you enable the higher key sizes yourself. 可以直接使用AES-128,但美国出口限制要求您自己启用更大的密钥。

Answer: With the help of Artjom B. I have created the code that will decrypt the AES-256 / CBC / ZeroBytePadding encrypted string. 答:在Artjom B的帮助下,我创建了将解密AES-256 / CBC / ZeroBytePadding加密字符串的代码。 I am posting this for others who need the help. 我将其发布给需要帮助的其他人。

1. Firstly you have to download Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy for your JDK version. 1.首先,您必须为您的JDK版本下载Java密码学扩展(JCE)无限强度管辖权策略。

2. Extract the zip file & put the local_policy.jar & US_export_policy.jar in the path /JDK Path/jre/lib/security. 2.解压缩zip文件,并将local_policy.jar和US_export_policy.jar放在/ JDK路径/ jre / lib / security路径中。 This is required as my key is 64 byte. 这是必需的,因为我的密钥是64字节。 AES requires 16/24/32 bytes of key. AES需要16/24/32字节的密钥。

3. Copy paste my code & change it as per your requirement :P. 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); 

}

}

Thanks @Artjom B. for your help & expertise :). 感谢@Artjom B.的帮助和专业知识:)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM