对称加密解密问题

时间:2015-03-09 10:44:44

标签: java encryption aes

我试图用java加密和解密命令行的程序。到目前为止我可以正确加密但是当我尝试解密加密的消息时,我得到了填充错误。程序的代码是

    package cat.copernic.simetriccd;


import java.security.MessageDigest;
import java.util.Arrays;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

class symetric{

    public static String byteArrayToHexString(byte[] b){ 
        StringBuilder sb = new StringBuilder(b.length * 2); 
        for(int i = 0; i < b.length; i++){ 
            int v = b[i] & 0xff; if(v < 16){ 
                sb.append("0"); 
            } 
            sb.append(Integer.toHexString(v)); 
        } return sb.toString(); 
    }

    static SecretKey genKey(String text) {    
        SecretKey sKey = null;  
        int keySize = 256;      
        try {
            byte[] data = text.getBytes("UTF-8");
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            byte[] hash = md.digest(data);
            byte[] key = Arrays.copyOf(hash, keySize/8);
            sKey = new SecretKeySpec(key, "AES");      
        } catch (Exception ex) {
            System.err.println("Error generant la clau:" + ex);  
        }

        return sKey;   
    }

    static String encryptData(String password, byte[] data) {
        byte[] encryptedData = null;    
        try {
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, genKey(password));
            encryptedData =  cipher.doFinal(data);
        } catch (Exception  ex) {  
            System.err.println("Error xifrant les dades: " + ex);          
        } 

        return byteArrayToHexString(encryptedData);
    }

    static String decryptData(String password, byte[] data) {
        byte[] decryptedData = null;    
        try {
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, genKey(password));
            decryptedData =  cipher.doFinal(data);
        } catch (Exception  ex) {  
            System.err.println("Error desxifrant les dades: " + ex);          
        } 
        return decryptedData.toString();
    }

}



public class Main { 

    public static void main(String[] args) {

        //controlar numero de parametros que se pasan
        if(args.length <= 1 || args.length > 3 || args.length == 2){
            System.out.println("java Main -mode=encrypt|decrypt <message> <key>");
            return;
        }

        //sacamos los valores de los argumentos
        String mode = args[0].split("=")[1].toLowerCase();
        byte[] mensage = args[1].getBytes();
        String key = args[2];

        if(mode.equals("encrypt") || mode.equals("decrypt")){
            switch (mode) {
            case "encrypt":
                //System.out.println("encrypt");
                System.out.println(symetric.encryptData(key, mensage));
                break;

            case "decrypt":
                //System.out.println("decrypt");
                System.out.println(symetric.decryptData(key, mensage));
                break;

            default:
                break;
            }
        }else {
            System.out.println("Solo coje valores encrypt/ENCRYPT o decrypt/DECRYPT");
        }
    }
}

消息错误是

    Error desxifrant les dades: javax.crypto.BadPaddingException: Given final block not properly padded
Exception in thread "main" java.lang.NullPointerException
    at cat.copernic.simetriccd.symetric.decryptData(Main.java:61)
    at cat.copernic.simetriccd.Main.main(Main.java:92)

我很确定错误是在这里生成的,但不知道如何解决它...任何想法?感谢

cipher.init(Cipher.DECRYPT_MODE, genKey(password));
            decryptedData =  cipher.doFinal(data);

2 个答案:

答案 0 :(得分:1)

您需要在解密之前将十六进制编码的String转换回字节。建议使用this functiondecryptedData.toString()也不会有效。尝试将字节编码为“UTF-8”字符串,如下所示:

new String(decryptedData, "UTF-8");

答案 1 :(得分:0)

最后,感谢帮助该练习的人们解决方案:

package cat.copernic.simetriccd;


import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;


class symetric{

    public static String byteArrayToHexString(byte[] b){ 
        return DatatypeConverter.printHexBinary(b);
    }   

    public static byte[] hexToByteArray(String b){
        return DatatypeConverter.parseHexBinary(b);
    }

    static SecretKey genKey(String text) {    
        SecretKey sKey = null;  
        int keySize = 256;      
        try {
            byte[] data = text.getBytes("UTF-8");
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            byte[] hash = md.digest(data);
            byte[] key = Arrays.copyOf(hash, keySize/8);
            sKey = new SecretKeySpec(key, "AES"); 
        } catch (Exception ex) {
            System.err.println("Error generant la clau");  
        }

        return sKey;   
    }

    static String encryptData(String password, String data) {
        byte[] encryptedData = null;    
        try {
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, genKey(password));
            encryptedData =  cipher.doFinal(data.getBytes());
        } catch (Exception  ex) {  
            System.err.println("Error xifrant les dades");          
        } 

        return byteArrayToHexString(encryptedData);
    }

    static String decryptData(String password, String data) throws UnsupportedEncodingException {
        byte[] decryptedData = null;    
        try {
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, genKey(password));
            decryptedData =  cipher.doFinal(hexToByteArray(data));
        } catch (Exception  ex) {  
            System.err.println("Error desxifrant les dades");          
        } 

        return new String(decryptedData, "UTF-8");
    }

}

public class Main { 

    public static void main(String[] args) throws UnsupportedEncodingException {

        //controlar numero de parametros que se pasan
        if(args.length <= 1 || args.length > 3 || args.length == 2){
            System.out.println("java Main -mode=encrypt|decrypt <message> <key>");
            return;
        }

        try {

            //sacamos los valores de los argumentos
            String mode = args[0].split("=")[1].toLowerCase();
            String mensage = args[1];
            String key = args[2];

            if(mode.equals("encrypt") || mode.equals("decrypt")){
                switch (mode) {
                case "encrypt":
                    //System.out.println("encrypt");
                    System.out.println("mensaje encriptado= " + symetric.encryptData(key, mensage));
                    break;

                case "decrypt":
                    //System.out.println("decrypt");
                    System.out.println("mensaje desencriptado= " + symetric.decryptData(key, mensage));
                    break;

                default:
                    break;
                }
            }else {
                System.out.println("Solo coje valores encrypt/ENCRYPT o decrypt/DECRYPT");
            }

        } catch (Exception e) {
            System.out.println("Error en la definicion de los atributos");
        }
    }
}