web-dev-qa-db-fra.com

Chiffrer et déchiffrer avec les codages AES et Base64

J'ai le programme suivant pour le cryptage des données.

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;
    }

}

Ici, je reçois ce qui suit avec une exception?

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*..)

Quelqu'un peut-il m'expliquer la cause? Pourquoi son seul mot lors du déchiffrement de cette longueur devrait être 16. Ne convertit-il pas en 16 comme un chiffrement avec la méthode doFinal.

Et comme le dit l’exception " comment décrypter sans chiffrement renforcé?"

26
Harshana

Votre commande pour chiffrer: getBytes, chiffrer, coder, toString
Votre commande de déchiffrement (Wrong *): getBytes, déchiffrer, décoder, toString

Deux problèmes:

  1. Comme quelqu'un l'a déjà mentionné, vous devriez inverser l'ordre des opérations pour le déchiffrement. Tu ne fais pas ça.
  2. encrypt vous donne 16 octets, encodez 24 octets, mais toString donne 106 octets. Quelque chose à voir avec les caractères invalides prenant de la place supplémentaire.

Remarque: De plus, vous n'avez pas besoin d'appeler generateKey() deux fois.

Résoudre le problème n ° 1 en utilisant l'ordre inverse du déchiffrement.
Ordre correct pour déchiffrer: getBytes, décoder, déchiffrer, toString

Résoudre le problème n ° 2 en remplaçant xxx.toString() par new String(xxx). Faites cela dans les fonctions de chiffrement et de déchiffrement.

Votre déchiffrement devrait ressembler à ceci:

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

Cela devrait vous rendre "mec5"

54
Babu Srinivasan

La ligne

String encryptedValue = encryptedByteValue.toString();

c'est le problème. Le type de encryptedByteValue est byte [] et appeler toString sur ce n'est pas ce que vous voulez faire ici. Au lieu d'essayer

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

Ensuite, utilisez Base64.decodeBase64(encryptedValue) dans déchiffrer. Vous devez cependant le faire avant de tenter de décrypter. Vous devez annuler les opérations dans l'ordre inverse de la méthode de chiffrement.

3
laz

Où trouvez-vous une version du codec Apache contenant encodeToString ou encodeBase64String?

J'ai téléchargé la version 1.5 à partir du site Apache et bien que la documentation indique que ces méthodes existent, elles ne s'affichent pas lorsque vous complétez du code et créent une méthode inconnue lorsque vous les fournissez.

J'ai pu faire:

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

Et puis la chaîne que j'ai obtenue était très longue, MAIS elle a été décryptée correctement.

Je ne pense pas que ce soit la "bonne" façon de faire les choses, mais je ne trouve pas les méthodes décrites dans la documentation.

2
John Wooten

J'ai remplace la ligne dans l'exemple:

String encryptedValue = encryptedByteValue.toString();

avec le prochain:

String encryptedValue = new String(encryptedByteValue);

Tout fonctionne bien!

1
Alex

C'était bien, il fallait juste 

1) Utilisez new String au lieu de toString () car toString () ne renvoie pas ce dont vous avez besoin ici (dans les deux cas, chiffrement et déchiffrement).

2) vous devez d'abord décoder car la valeur est encodée en base64.

Je suis tombé sur ce fil de discussion, mais il m'a fallu un certain temps pour trouver le point réel. Je publie mon code pour le reste des personnes qui rencontrent ce problème.

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));
}
}
1
Danyal Sandeelo

Fondamentalement, il existe une asymétrie entre votre fonction de chiffrement et votre fonction de déchiffrement. Lorsque vous chiffrez, vous effectuez un chiffrement AES, puis un codage base64. Lorsque vous décryptez, vous n'annulez pas au préalable l'étape de codage base64.

Je pense qu'il y a quelque chose qui ne va pas avec votre encodage en base64, et [ ne devrait pas apparaître dans une chaîne encodée en base64.

En regardant la documentation pour org.Apache.commons.codec.binary.Base64, vous devriez pouvoir le faire sur encoder:

String encryptedValue = Base64.encodeBase64String(encValue);

et ceci sur décoder:

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