我正在开展一个我正在进行加密的项目,该项目使用AES选择密钥和密码学家,然后再执行base64。在将base64解密回AES和AES并返回String时发生问题。低于错误和代码
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 :(得分: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));
}