Шифрование и дешифрование с помощью AES и Base64 кодирования



У меня есть следующая программа для шифрования данных.



import java.security.Key;

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

import org.apache.commons.codec.binary.Base64;

public class Test {

private static final String ALGORITHM = "AES";
private static final byte[] keyValue = "ADBSJHJS12547896".getBytes();

public static void main(String args[]) throws Exception {
String encriptValue = encrypt("dude5");
decrypt(encriptValue);

}

/**
* @param args
* @throws Exception
*/

public static String encrypt(String valueToEnc) throws Exception {

Key key = generateKey();
Cipher c = Cipher.getInstance(ALGORITHM);
c.init(Cipher.ENCRYPT_MODE, key);

System.out.println("valueToEnc.getBytes().length "+valueToEnc.getBytes().length);
byte[] encValue = c.doFinal(valueToEnc.getBytes());
System.out.println("encValue length" + encValue.length);
byte[] encryptedByteValue = new Base64().encode(encValue);
String encryptedValue = encryptedByteValue.toString();
System.out.println("encryptedValue " + encryptedValue);

return encryptedValue;
}

public static String decrypt(String encryptedValue) throws Exception {
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGORITHM);
c.init(Cipher.DECRYPT_MODE, key);

byte[] enctVal = c.doFinal(encryptedValue.getBytes());
System.out.println("enctVal length " + enctVal.length);

byte[] decordedValue = new Base64().decode(enctVal);

return decordedValue.toString();
}

private static Key generateKey() throws Exception {
Key key = new SecretKeySpec(keyValue, ALGORITHM);
return key;
}

}


Здесь я получаю следующий выход, поставленный с исключением?



valueToEnc.getBytes().length 5
encValue length16
encryptedValue [B@aa9835
Exception in thread "main" javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)


Может ли кто-нибудь объяснить мне причину? Почему его единственное высказывание при расшифровке, что длина должна быть 16. Не преобразуется ли он в 16, как шифрование с помощью метода doFinal.

И как говорит исключение " Как расшифровать без подкладки шифра?"

733   6  

6 ответов:

Ваш заказ на шифрование: getBytes, encrypt, encode, toString
Ваш заказ на расшифровку: getBytes, decrypt, decode, toString

Две проблемы:

  1. как кто-то уже упоминал, вы должны изменить порядок операций для расшифровки. Вы этого не сделаете.
  2. шифрование дает 16 байт, кодирование 24 байта, но toString дает 106 байт. Что-то связанное с недействительными символами, занимающими дополнительные пространство.
Примечание: кроме того, вам не нужно звонить generateKey() дважды.

Исправьте проблему №1, используя обратный порядок для расшифровки. Правильный порядок: getBytes, decode, decrypt, toString
Исправьте проблему №2, заменив xxx.toString() на new String(xxx). Сделайте это в обеих функциях шифрования и дешифрования.

Ваша расшифровка должна выглядеть следующим образом:

c.init(Cipher.DECRYPT_MODE, key)
val decodedValue = new Base64().decode(encryptedValue.getBytes())
val decryptedVal = c.doFinal(decodedValue)
return new String(decryptedVal)

Это должно вернуть вам "dude5"

Линия

String encryptedValue = encryptedByteValue.toString();

- вот в чем проблема. Тип encryptedByteValue-byte [], и вызов toString на нем-это не то, что вы хотите сделать там. Вместо этого попробуйте

String encryptedValue = Base64.getEncoder().encodeToString(encValue);

Затем используйте Base64.decodeBase64(encryptedValue) для расшифровки. Однако вы должны сделать это до того, как попытаетесь расшифровать. Вы должны отменить операции в обратном порядке метода шифрования.

Где вы получаете версию Apache codec, которая имеет encodeToString или encodeBase64String?

Я скачал 1.5 с сайта apache, и хотя в документации говорится, что эти методы существуют, они не появляются, когда вы выполняете завершение кода, и они создают неизвестный метод, когда вы их предоставляете.

Я смог сделать:

byte raw[] = md.digest(); //step 4
byte hashBytes[] = Base64.encodeBase64(raw); //step 5
StringBuffer buffer = new StringBuffer();
for( int i=0; i<hashBytes.length; i++ )
    buffer.append(hashBytes[i]);
return buffer.toString(); //step 6

И затем строка, которую я получил, была очень длинной, но она расшифровывалась правильно.

Я не думаю, что это "правильный" способ делайте что-то, но не можете найти методы, о которых говорится в документации.

Это было нормально, тебе просто нужно было

1) Используйте новую строку вместо toString (), так как toString() не возвращает то, что вам нужно (в обоих случаях шифрование и расшифровка)

2) вам нужно сначала декодировать, так как значение кодируется в base64.

Я наткнулся на эту нить, но потребовалось некоторое время, чтобы выяснить фактическую точку..Я публикую свой код для остальных людей, которые сталкиваются с этой проблемой.

public abstract class EncryptionDecryption {
static  byte[]  key = "!@#$!@#$%^&**&^%".getBytes();
final static String algorithm="AES";

public static String encrypt(String data){

    byte[] dataToSend = data.getBytes();
    Cipher c = null;
    try {
        c = Cipher.getInstance(algorithm);
    } catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    SecretKeySpec k =  new SecretKeySpec(key, algorithm);
    try {
        c.init(Cipher.ENCRYPT_MODE, k);
    } catch (InvalidKeyException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    byte[] encryptedData = "".getBytes();
    try {
        encryptedData = c.doFinal(dataToSend);
    } catch (IllegalBlockSizeException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (BadPaddingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    byte[] encryptedByteValue =    new Base64().encode(encryptedData);
    return  new String(encryptedByteValue);//.toString();
}

public static String decrypt(String data){

    byte[] encryptedData  = new Base64().decode(data);
    Cipher c = null;
    try {
        c = Cipher.getInstance(algorithm);
    } catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    SecretKeySpec k =
            new SecretKeySpec(key, algorithm);
    try {
        c.init(Cipher.DECRYPT_MODE, k);
    } catch (InvalidKeyException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    byte[] decrypted = null;
    try {
        decrypted = c.doFinal(encryptedData);
    } catch (IllegalBlockSizeException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (BadPaddingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return new String(decrypted);
}

public static void main(String[] args){
    String password=EncryptionDecryption.encrypt("password123");
    System.out.println(password);
    System.out.println(EncryptionDecryption.decrypt(password));
}
}

По сути, существует асимметрия между функцией шифрования и функцией дешифрования. Когда вы шифруете, вы выполняете шифрование AES, а затем кодирование base64, когда вы расшифровываете, вы сначала не отменяете шаг кодирования base64.

Я думаю, что что-то не так с вашей кодировкой base64, а также [ не должно появляться в строке с кодировкой base64.

Глядя на документацию для org.apache.commons.codec.binary.Base64 Вы должны быть в состоянии сделать это на encode:

String encryptedValue = Base64.encodeBase64String(encValue);

И это на расшифровать:

byte[] encValue = Base64.decodeBase64(encryptedValue);

У меня есть замена строки в Примере:

String encryptedValue = encryptedByteValue.toString();

Со следующим:

String encryptedValue = new String(encryptedByteValue);

Все работает отлично!

Comments

    Ничего не найдено.