Frage Verschlüsseln und Entschlüsseln mit AES- und Base64-Verschlüsselung


Ich habe folgendes Programm zum Verschlüsseln von Daten.

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

}

Hier bekomme ich folgendes heraus mit Ausnahme?

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

Kann mir jemand die Ursache erklären? Warum sollte es beim Entschlüsseln dieser Länge nur 16 sein? Konvertiert es nicht in 16, wie das Verschlüsseln mit der DoFinal-Methode?

Und wie die Ausnahme sagt "wie entschlüsselt man ohne gepolsterte Chiffre? "


22
2017-10-17 18:25


Ursprung


Antworten:


Ihre Bestellung zum Verschlüsseln:  getBytes, verschlüsseln, encodieren, toString
Ihre Bestellung zum Entschlüsseln:  getBytes, entschlüsseln, dekodieren, toString

Zwei Probleme:

  1. Wie bereits erwähnt, sollten Sie die Reihenfolge der Operationen für die Entschlüsselung umkehren. Du machst das nicht.
  2. encrypt gibt Ihnen 16 Bytes, codiert 24 Bytes, aber toString ergibt 106 Bytes. Etwas mit ungültigen Zeichen, die zusätzlichen Platz einnehmen.

Hinweis: Sie müssen auch nicht anrufen generateKey() zweimal.

Beheben Sie Problem Nr. 1, indem Sie die umgekehrte Reihenfolge für die Entschlüsselung verwenden. Korrekten Reihenfolge:  getBytes, entschlüsseln, entschlüsseln, toString
Beheben Sie Problem # 2, indem Sie ersetzen xxx.toString() mit new String(xxx). Tun Sie dies sowohl in den Verschlüsselungs- als auch in den Entschlüsselungsfunktionen.

Ihre Entschlüsselung sollte folgendermaßen aussehen:

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

Dies sollte dir "dude5" zurückgeben


46
2018-04-22 22:13



Die Linie

String encryptedValue = encryptedByteValue.toString();

ist das Problem. Der Typ von encryptedByteValue ist Byte [] und der Aufruf von toString ist nicht das, was Sie dort tun wollen. Stattdessen versuche es

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

Dann benutze Base64.decodeBase64(encryptedValue) entschlüsseln. Sie müssen dies jedoch vor dem Entschlüsselungsversuch tun. Sie müssen die Operationen in umgekehrter Reihenfolge der Verschlüsselungsmethode rückgängig machen.


3
2017-10-17 19:03



Wo bekommst du eine Version von Apache Codec, die encodeToString oder encodeBase64String hat?

Ich habe 1.5 von der Apache-Site heruntergeladen und während in der Dokumentation steht, dass diese Methoden existieren, werden sie nicht angezeigt, wenn Sie Code-Vervollständigung durchführen und sie eine unbekannte Methode erstellen, wenn Sie sie bereitstellen.

Ich konnte Folgendes tun:

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

Und dann war die Zeichenfolge, die ich erhielt, sehr lang, ABER es entschlüsselte richtig.

Ich denke nicht, dass dies der "richtige" Weg ist, Dinge zu tun, aber ich finde nicht die Methoden, die in der Dokumentation stehen.


2
2018-04-18 15:46



Grundsätzlich besteht eine Asymmetrie zwischen Ihrer Verschlüsselungsfunktion und Ihrer Entschlüsselungsfunktion. Wenn Sie eine AES-Verschlüsselung und dann eine Base64-Codierung ausführen, müssen Sie beim Entschlüsseln nicht zuerst den Base64-Verschlüsselungsschritt rückgängig machen.

Ich denke, dass etwas mit der base64-Codierung nicht stimmt [ sollte nicht in einer Base64-codierten Zeichenfolge angezeigt werden.

Schauen Sie sich die Dokumentation an org.apache.commons.codec.binary.Base64 Sie sollten dies beim Enkodieren tun können:

String encryptedValue = Base64.encodeBase64String(encValue);

und das beim Dekodieren:

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

0
2017-10-17 18:53



Ich habe die Zeile im Beispiel ersetzt:

String encryptedValue = encryptedByteValue.toString();

mit dem nächsten:

String encryptedValue = new String(encryptedByteValue);

Alles funktioniert gut!


0
2018-04-16 15:17



Das war in Ordnung, du musstest es nur tun

1) Verwenden Sie einen neuen String anstelle von toString (), da toString () nicht das liefert, was Sie hier benötigen (in beiden Fällen, Verschlüsselung und Entschlüsselung)

2) Sie müssen zuerst dekodieren, da der Wert in base64 codiert ist.

Ich bin auf diesen Thread gestoßen, aber es hat einige Zeit gedauert, um den eigentlichen Punkt herauszufinden. Ich poste meinen Code für den Rest der Leute, die auf dieses Problem stoßen.

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

0
2018-03-24 15:17