有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何解码AES256/CBC/ZeroBytep添加加密对象

我对Java加密技术相当陌生。我提供了以下PHP代码来解密AES-256/CBC/ZeroByTep加密对象

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

但我需要在这里找到静脉长度。在PHP中,他们使用以下方法进行此操作: $iv_size=mcrypt_get_iv_size(mcrypt_RIJNDAEL_128,mcrypt_MODE_CBC); 如何在java中实现它?有人能帮我吗

我这样调用该方法:

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

}

共 (2) 个答案

  1. # 1 楼答案

    回答:在Artjom B的帮助下,我创建了一个代码,用于解密AES-256/CBC/ZeroByTep加密字符串。我为其他需要帮助的人发布这篇文章

    1首先,您必须为您的JDK版本下载Java加密扩展(JCE)无限强度权限策略

    2解压缩zip文件&;把当地的政策。jar&;美国的出口政策。jar位于/jdkpath/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.的帮助&;专业知识:)

  2. # 2 楼答案

    CBC模式下AES的IV(Rijndael-128)始终与块大小相同,即16字节或128位。如果继续使用CBC模式,则可以硬编码该值或使用Cipher#getBlockSize()

    如果要使用AES-256,则需要为JRE/JDK(Link for Java 8)安装无限强度策略文件。AES-128无需修改即可使用,但美国的出口限制要求您自己启用更高的密钥大小