2016-11-06 25 views
0

我正在开发一个项目,在其中进行加密,该项目使用AES拾取密钥和密码算法,然后执行base64。在将base64解密回AES和AES并返回到字符串时,会发生问题。下面的错误和代码javax.crypto.IllegalBlockSizeException:使用填充密码进行解密时,输入长度必须是16的倍数

import java.io.UnsupportedEncodingException; 
import java.security.InvalidKeyException; 
import java.security.NoSuchAlgorithmException; 
import java.util.Base64; 

import javax.crypto.*; 
import javax.crypto.spec.*; 

public class Criptografia { 
    byte[] chave = "chave de 16bytes".getBytes(); 

    public String encriptaAES(String chaveCriptografada) 
      throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException { 
     try { 

      Cipher cipher = Cipher.getInstance("AES"); 
      byte[] mensagem = chaveCriptografada.getBytes(); 
      cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(chave, "AES")); 
      chaveCriptografada = cipher.doFinal(mensagem).toString(); 



      chaveCriptografada =Base64.getUrlEncoder().encodeToString(chaveCriptografada.getBytes("utf-8")); 


     } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { 

      e.printStackTrace(); 
     } 

     return chaveCriptografada; 

    } 


    public String descriptografaAES(String chaveCriptografada) throws NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException{ 
     Cipher cipher = Cipher.getInstance("AES"); 

     byte[] base64decodedBytes = Base64.getUrlDecoder().decode(chaveCriptografada); 

     chaveCriptografada= base64decodedBytes.toString(); 


     try { 
      cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(this.chave, "AES")); 
      byte[] decrypted = cipher.doFinal(chaveCriptografada.getBytes("UTF-8")); 
      chaveCriptografada=decrypted.toString(); 

     } catch (InvalidKeyException e) { 

      e.printStackTrace(); 
     } 



     return chaveCriptografada; 


    } 

} 

Exception in thread "main" javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher 
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:922) 
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:833) 
    at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446) 
    at javax.crypto.Cipher.doFinal(Cipher.java:2165) 
    at Criptografia.descriptografaAES(Criptografia.java:47) 
    at Run.main(Run.java:15) 

回答

0

我分享你我珍贵的加密类我的英语朋友。

package Encriptacion; 
import javax.crypto.*; 
import java.io.*; 
import java.nio.*; 
import java.nio.channels.*; 
import javax.crypto.spec.*; 
public class EncriptadorAES { 
    private SecretKey CLAVESECRETA=null; 
    private final int AES_KEYLENGTH = 128; 
    private IvParameterSpec IV=null; 
    public EncriptadorAES() throws Exception{ 
     //generarIV(); 
     if(new File("initvectoraes.iv").exists()){ 
      this.IV=new IvParameterSpec(obtenerIV()); 
     } 
    } 
    public void setCLAVESECRETA(String clave){ 
     this.CLAVESECRETA=generarClaveSecreta(clave); 
    } 
    public void guardarClave(String clave,String ruta)throws Exception{ 
     try{ 
      byte[]bytesClave=generarClaveSecreta(clave).getEncoded(); 
      FileChannel canalSalida=new RandomAccessFile(new File(ruta), "rw").getChannel(); 
      ByteBuffer bufferSalida=ByteBuffer.wrap(bytesClave); 
      canalSalida.write(bufferSalida); 
      canalSalida.close(); 
     }catch(Exception ex){ 
      throw new Exception("No se pudo guardar la clave\n"+ex); 
     } 
    } 
    public SecretKey cargarClave(String ruta)throws Exception{ 
     try{ 
      File archivo=new File(ruta); 
      byte[]bytesClave=new byte[(int)archivo.length()]; 
      FileChannel canalEntrada=new RandomAccessFile(archivo, "r").getChannel(); 
      ByteBuffer bufferEntrada=ByteBuffer.allocate(bytesClave.length); 
      canalEntrada.read(bufferEntrada); 
      bufferEntrada.flip(); 
      bufferEntrada.get(bytesClave); 
      canalEntrada.close(); 
      return new SecretKeySpec(bytesClave, "AES"); 
     }catch(Exception ex){ 
      throw new Exception("No se pudo cargar la clave secreta\n"+ex); 
     } 
    } 
    public void encriptarArchivo(String ruta,SecretKey clave) throws Exception{ 
     File archivo=null; 
     try { 
      archivo=new File(ruta); 
      if(archivo.isFile()&&archivo.exists()&&archivo.length()<=700248752){ 
       //LECTURA 
       byte[] bytesArchivo=new byte[(int)archivo.length()]; 
       int tamañoBloque=AES_KEYLENGTH/8; 
       int numBloques=((int)archivo.length()%tamañoBloque==0)?(int)archivo.length()/tamañoBloque:((int)archivo.length()/tamañoBloque)+1; 
       int tamañoEncriptado=((bytesArchivo.length/tamañoBloque)+1)*tamañoBloque; 
       FileChannel canalEntrada=new RandomAccessFile(archivo, "r").getChannel(); 
       ByteBuffer bufferEntrada=ByteBuffer.allocate((int)archivo.length()); 
       canalEntrada.read(bufferEntrada); 
       bufferEntrada.flip(); 
       bufferEntrada.get(bytesArchivo); 
       canalEntrada.close(); 
       //CIFRADO clave simétrica 
       ByteBuffer bufferSalida=ByteBuffer.allocate(tamañoEncriptado); 
       Cipher cifradorAES = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
       cifradorAES.init(Cipher.ENCRYPT_MODE, clave,this.IV); 
       bufferSalida.put(cifradorAES.doFinal(bytesArchivo)); 
       bufferSalida.flip(); 
       //ESCRITURA 
       if(archivo.delete()){ 
        FileChannel canalSalida=new RandomAccessFile(archivo,"rw").getChannel(); 
        canalSalida.write(bufferSalida); 
        canalSalida.close(); 
       }else throw new Exception("No se pudo borrar el archivo "+archivo.getName()+", si lo tiene abierto, ciérrelo."); 
      }else{ 
       if(!archivo.exists())throw new Exception("El archivo "+archivo.getName()+" no existe"); 
       if(!archivo.isFile())throw new Exception("No puede encriptar un directorio, trate\nde comprimirlo antes para luego encriptar los archivos"); 
       if(archivo.length()>700248752)throw new Exception("No se puede encriptar el archivo "+archivo.getName()+" porque ha superado el tamaño máximo\nde capacidad de memoria del JVM"); 
      } 
     } 
     catch (Exception ex){ 
      throw new Exception("Hubo un error al encriptar el archivo\n"+ archivo.getName() +"\n"+ex); 
     } 
    } 
    public void desencriptarArchivo(String ruta,SecretKey clave)throws Exception{ 
     File archivoEncriptado=null; 
     try{ 
      archivoEncriptado=new File(ruta); 
      if(archivoEncriptado.exists()){ 
       //LECTURA 
       byte[]bytesArchivoEncriptado=new byte[(int)archivoEncriptado.length()]; 
       int tamañoBloque=AES_KEYLENGTH/8; 
       int numBloques=((int)archivoEncriptado.length()%tamañoBloque==0)?(int)archivoEncriptado.length()/tamañoBloque:((int)archivoEncriptado.length()/tamañoBloque)+1; 
       FileChannel canalEntrada=new RandomAccessFile(archivoEncriptado, "r").getChannel(); 
       ByteBuffer bufferEntrada=ByteBuffer.allocate((int)archivoEncriptado.length()); 
       canalEntrada.read(bufferEntrada); 
       bufferEntrada.flip(); 
       bufferEntrada.get(bytesArchivoEncriptado); 
       canalEntrada.close(); 
       //DESCRIFRADO 
       ByteBuffer bufferSalida=ByteBuffer.allocate((int)archivoEncriptado.length()); 
       if(comprobarKeys(clave)){ 
        Cipher descifradorAES = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
        descifradorAES.init(Cipher.DECRYPT_MODE,clave,this.IV); 
        bufferSalida.put(descifradorAES.doFinal(bytesArchivoEncriptado)); 
        bufferSalida.flip(); 
       } 
       else{ 
        System.gc(); 
        throw new Exception("La clave ingresada es incorrecta"); 
       } 
       //ESCRITURA    
       if(archivoEncriptado.delete()){ 
        FileChannel canalSalida=new RandomAccessFile(ruta, "rw").getChannel(); 
        canalSalida.write(bufferSalida); 
        canalSalida.close(); 
       }else throw new Exception("No se pudo eliminar el archivo "+archivoEncriptado.getName()+", si lo tiene abierto, ciérrelo."); 
      }else{ 
       if(!archivoEncriptado.exists())throw new Exception("El archivo "+archivoEncriptado.getName()+" no existe"); 
      } 
     } 
     catch (Exception ex){ 
      System.gc(); 
      throw new Exception("Hubo un error al desencriptar\n"+archivoEncriptado.getName()+":\n"+ex.getMessage()); 
     } 
    }  
    public SecretKey generarClaveSecreta(String clave){ 
     byte[]key=rellenarBytesClave(clave); 
     SecretKey claveGenerada=new SecretKeySpec(key, "AES"); 
     return claveGenerada; 
    } 
    private byte[] rellenarBytesClave(String clave){ 
     byte[]key=clave.getBytes(); 
     while(key.length!=AES_KEYLENGTH/8){ 
      if(key.length<AES_KEYLENGTH/8){ 
       clave+="0"; 
       key=clave.getBytes(); 
      } 
      if(key.length>AES_KEYLENGTH/8){ 
       clave=clave.substring(0,AES_KEYLENGTH/8); 
       key=clave.getBytes(); 
      } 
     } 
     return key; 
    } 
    private boolean comprobarKeys(SecretKey clave){ 
     return this.CLAVESECRETA.equals(clave); 
    } 
    public void generarIV() throws Exception{ 
     try{ 
      byte[]VECTOR={1,6,1,2,1,9,9,7,7,9,9,1,2,1,6,1}; 
      FileChannel canalsalida=new RandomAccessFile(new File("initvectoraes.iv"), "rw").getChannel(); 
      MappedByteBuffer buffersalida=canalsalida.map(FileChannel.MapMode.READ_WRITE, 0, 16); 
      buffersalida.put(VECTOR); 
      buffersalida.force(); 
      canalsalida.close(); 
     }catch(Exception ex){ 
      throw new Exception("Error al generar el Vector de Inicialización de AES\n"+ex.getMessage()); 
     } 
    } 
    private byte[]obtenerIV()throws Exception{ 
     byte[]vectorcargado=null; 
     try{ 
      FileChannel canalentrada=new RandomAccessFile(new File("initvectoraes.iv"), "r").getChannel(); 
      MappedByteBuffer bufferentrada=canalentrada.map(FileChannel.MapMode.READ_ONLY, 0, 16); 
      vectorcargado=new byte[16]; 
      bufferentrada.get(vectorcargado); 
      bufferentrada.load(); 
      canalentrada.close(); 
     } 
     catch(Exception ex){ 
      throw new Exception("Error al obtener el Vector de Inicialización de AES\n"+ex.getMessage()); 
     } 
     return vectorcargado; 
    } 
} 

编辑 这个代码不解决这个问题,但我认为这可能以某种方式帮助

byte[] chave = "chave de 16bytes".getBytes(); 
IvParameterSpec IV = new IvParameterSpec(new byte[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}); 
String TEST = "TEST"; 

    public String encriptaAES(String chaveCriptografada) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException, InvalidAlgorithmParameterException { 
     try { 
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
      System.out.println("MENSAJE: "+chaveCriptografada); 
      byte[] mensagem = chaveCriptografada.getBytes(); 
      cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(chave, "AES"), this.IV); 
      chaveCriptografada = new String(cipher.doFinal(mensagem)); 
      System.out.println("Mensaje encriptado: "+chaveCriptografada); 

      chaveCriptografada = DatatypeConverter.printBase64Binary(chaveCriptografada.getBytes()); 
      this.TEST = DatatypeConverter.printBase64Binary(TEST.getBytes()); 
      System.out.println("TEST: "+TEST); 
     } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { 
      e.printStackTrace(); 
     } 
     return chaveCriptografada; 

    } 

    public String descriptografaAES(String chaveCriptografada) throws NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException, InvalidAlgorithmParameterException { 
     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 

     System.out.println("Mensaje Encriptado CON BASE 64: "+chaveCriptografada); 
     byte[] base64decodedBytes = DatatypeConverter.parseBase64Binary(chaveCriptografada); 
     this.DATA=new String(DatatypeConverter.parseBase64Binary(this.DATA)); 
     System.out.println("TEST: "+TEST); 
     System.out.println("Mensaje Encriptado: "+new String(base64decodedBytes)); 
     try { 
      cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(this.chave, "AES") , this.IV); 
      byte[] decrypted = cipher.doFinal(base64decodedBytes); 
      chaveCriptografada = new String(decrypted); 
     } catch (InvalidKeyException e) { 
      e.printStackTrace(); 
     } 
     return chaveCriptografada; 
    } 
    public static void main(String[] args) throws Exception{ 
     AESCipher cipher = new AESCipher(); 
     String mensajeEncriptado = cipher.encriptaAES("mensaje"); 
     System.out.println("Mensaje encriptado CON BASE 64: "+mensajeEncriptado); 
     System.out.println("Mensaje desencriptado: "+cipher.descriptografaAES(mensajeEncriptado)); 
    } 
+0

感谢,但仍不能解决只是看你的课,我的问题是当我返回base64时也是如此。 –

+0

哇我一直试图在很多方面,我只是在这一点上非常困难。如果您最终解决了问题,请通知我。 –

+0

我可以看看这个例子http://howtodoinjava.com/security/java-aes-encryption-example/,希望它也可以帮助你。 –

相关问题