使用加密密钥解密文本

时间:2014-08-30 21:57:28

标签: java aes padding

我写了一个用AES加密字符串的类:

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.*;
import javax.xml.bind.DatatypeConverter;
import org.bouncycastle.util.encoders.Hex;

public class CipherAES {

    public static void brutToHexa(byte[] t) {
        byte[] tab = Hex.encode(t);
        System.out.print("secret key : ");
        for (int i = 0; i < tab.length; i++) {
            System.out.print((char) tab[i] + "");
        }
        System.out.println();
    }

    public static byte[] encrypter(final String message, SecretKey cle)
            throws NoSuchAlgorithmException, NoSuchPaddingException,
            InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, cle);
        byte[] donnees = message.getBytes();

        return cipher.doFinal(donnees);
    }

    public static String decrypter(final byte[] donnees, SecretKey cle)
            throws NoSuchAlgorithmException, NoSuchPaddingException,
            InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, cle);

        return new String(cipher.doFinal(donnees));
    }

    public static void main(String[] args) {

        final String message = "Java is the best";

        KeyGenerator keyGen;
        try {
            keyGen = KeyGenerator.getInstance("AES");
            SecretKey cle = keyGen.generateKey();
            brutToHexa(cle.getEncoded());

            byte[] enc = encrypter(message, cle);
            System.out.print("encrypted text : ");
            System.out.println(DatatypeConverter.printBase64Binary(enc));

            String dec = decrypter(enc, cle);
            System.out.println("decrypted text : " + dec);

        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException |
                IllegalBlockSizeException | BadPaddingException e) {
            e.printStackTrace();
        }
    }
}

我以HEX格式显示密钥,并使用Base64编码加密文本。 为了跑,我得到:

secret key : dfaa3b49adbc546d4437107b6a666cb1
encrypted text : iwEjj0Gahfzgq4BWrdY9odNX9PqvHgppz9YZ3mddQq8=
decrypted text : Java is the best

这里是类解密:

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;

public class DecryptCipherAES {

    public static void main(String[] args) {
        try {
            byte[] key = ("dfaa3b49adbc546d4437107b6a666cb1").getBytes();
            SecretKey secretKey = new SecretKeySpec(key, "AES");

            String base64String = "iwEjj0Gahfzgq4BWrdY9odNX9PqvHgppz9YZ3mddQq8=";
            byte[] enc = org.apache.commons.codec.binary.Base64.decodeBase64(base64String.getBytes());

            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            String dec = new String(cipher.doFinal(enc));
            System.out.println("texte decrypte : " + dec);

        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
            e.printStackTrace();
        }
    }
}

运行时,我得到以下异常: javax.crypto.BadPaddingException:给定最终块未正确填充

2 个答案:

答案 0 :(得分:0)

核心问题是您假设使用String#getBytes会将基于十六进制的String正确转换为字节数组。

您需要手动将十六进制String值转换为byte数组。考虑一下,您将byte数组转换为String格式,需要将其转换回来。

这基本上就是您的代码,但我带了您的DecryptCipherAES并加入decryptWith方法。

该示例将密钥和消息转换为十六进制String,然后将其传递给decryptWith,然后将其转换回byte数组(通过取消它)。

同样,你也可以使用base64编码,但你仍然需要在另一端解码它

import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.management.openmbean.InvalidKeyException;
import javax.xml.bind.DatatypeConverter;

public class Test11 {

    public static String brutToHexa(byte[] t) {
        StringBuilder sb = new StringBuilder(t.length * 2);
        for (int i = 0; i < t.length; i++) {

            int v = t[i] & 0xff;
            if (v < 16) {

                sb.append('0');

            }

            sb.append(Integer.toHexString(v));//.append("-");

        }

        return sb.toString();
    }

    public static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                            + Character.digit(s.charAt(i + 1), 16));
        }
        return data;
    }

    public static byte[] encrypter(final String message, SecretKey cle)
                    throws NoSuchAlgorithmException, NoSuchPaddingException,
                    InvalidKeyException, IllegalBlockSizeException, BadPaddingException, java.security.InvalidKeyException {
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, cle);
        byte[] donnees = message.getBytes();

        return cipher.doFinal(donnees);
    }

    public static String decrypter(final byte[] donnees, SecretKey cle)
                    throws NoSuchAlgorithmException, NoSuchPaddingException,
                    InvalidKeyException, IllegalBlockSizeException, BadPaddingException, java.security.InvalidKeyException {
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, cle);

        return new String(cipher.doFinal(donnees));
    }

    public static void main(String[] args) throws java.security.InvalidKeyException {

        final String message = "Java is the best";

        KeyGenerator keyGen;
        try {
            keyGen = KeyGenerator.getInstance("AES");
            SecretKey cle = keyGen.generateKey();

            String hexKey = brutToHexa(cle.getEncoded());

            byte[] enc = encrypter(message, cle);
            System.out.print("encrypted text : ");
            System.out.println(DatatypeConverter.printBase64Binary(enc));

            String dec = decrypter(enc, cle);
            System.out.println("decrypted text : " + dec);

            decryptWith(hexKey, brutToHexa(enc));

        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException |
                        IllegalBlockSizeException | BadPaddingException e) {
            e.printStackTrace();
        }
    }

    public static void decryptWith(String hexKey, String hexMessage) throws java.security.InvalidKeyException {
        try {

            byte[] byteKey = hexStringToByteArray(hexKey);
            SecretKey secretKey = new SecretKeySpec(byteKey, "AES");

            byte[] message = hexStringToByteArray(hexMessage);

            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            String dec = new String(cipher.doFinal(message));
            System.out.println("texte decrypte : " + dec);

        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
            e.printStackTrace();
        }
    }
}

现在打印......

encrypted text : jq1S6WI0XsW6jmPQmCoZheVKEUZj5zOJZoR13jNdbYE=
decrypted text : Java is the best
texte decrypte : Java is the best

答案 1 :(得分:0)

问题在于将字符串转换为十六进制,我使用了这种方法并且它可以工作:

public static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i + 1), 16));
        }
        return data;
    }