it-swarm.com.de

Verschlüsseln und entschlüsseln Sie mit AES- und Base64-Kodierung

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 ausnahmsweise folgendes raus?

valueToEnc.getBytes().length 5
encValue length16
encryptedValue [[email protected]
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 man beim Entschlüsseln dieser Länge nur 16 sagen? Wird es nicht wie 16 mit der Methode doFinal verschlüsselt?.

Und wie die Ausnahme besagt " wie kann man ohne aufgefüllte Chiffre entschlüsseln?"

26
Harshana

Ihre Bestellung zum Verschlüsseln: getBytes, Verschlüsseln, Verschlüsseln, toString
Ihre Bestellung zum Entschlüsseln (Falsch *): getBytes, entschlüsseln, entschlüsseln, toString

Zwei Probleme:

  1. Wie bereits erwähnt, sollten Sie die Reihenfolge der Operationen zur Entschlüsselung umkehren. Das machst du nicht.
  2. verschlüsseln gibt 16 Bytes, 24 Bytes kodieren, aber toString 106 Bytes. Es hat etwas damit zu tun, dass ungültige Zeichen zusätzlichen Platz einnehmen.

Hinweis: Außerdem müssen Sie generateKey() nicht zweimal aufrufen.

Problem Nr. 1 beheben durch die umgekehrte Reihenfolge der Entschlüsselung.
Richtige Reihenfolge für die Entschlüsselung: getBytes, Dekodieren, Entschlüsseln, toString

Problem Nr. 2 beheben durch Ersetzen von xxx.toString() durch new String(xxx). Tun Sie dies sowohl in der Verschlüsselungs- als auch in der Entschlüsselungsfunktion.

Deine Entschlüsselung sollte so aussehen:

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

Das sollte dir "dude5" zurückgeben

54
Babu Srinivasan

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 möchten. Versuchen Sie es stattdessen

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

Verwenden Sie dann Base64.decodeBase64(encryptedValue) zum Entschlüsseln. Sie müssen dies jedoch tun, bevor Sie versuchen zu entschlüsseln. Sie müssen die Vorgänge in umgekehrter Reihenfolge der Verschlüsselungsmethode rückgängig machen.

3
laz

Woher bekommen Sie eine Version des Apache-Codecs mit encodeToString oder encodeBase64String?

Ich habe 1,5 von der Apache-Site heruntergeladen, und obwohl in der Dokumentation angegeben ist, dass diese Methoden vorhanden sind, werden sie nicht angezeigt, wenn Sie Code vervollständigen, und sie erstellen eine unbekannte Methode, wenn Sie sie bereitstellen.

Ich konnte machen:

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 Saite, die ich erhielt, sehr lang, ABER sie wurde richtig entschlüsselt.

Ich denke nicht, dass dies die "richtige" Vorgehensweise ist, aber ich kann nicht die Methoden finden, die laut Dokumentation in der Dokumentation vorhanden sind.

2
John Wooten

Ich habe Zeile in Beispiel ersetzt:

String encryptedValue = encryptedByteValue.toString();

mit dem nächsten:

String encryptedValue = new String(encryptedByteValue);

Alles funktioniert gut!

1
Alex

Das war in Ordnung, du musstest nur 

1) Verwenden Sie new String anstelle von toString (), da toString () nicht das zurückgibt, 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 kodiert wird.

Ich bin auf diesen Thread gestoßen, aber es hat etwas gedauert, bis ich den eigentlichen Punkt herausgefunden habe. Ich poste meinen Code für den Rest der Leute, die auf dieses Problem stoßen.

public abstract class EncryptionDecryption {
static  byte[]  key = "[email protected]#[email protected]#$%^&**&^%".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

Grundsätzlich besteht eine Asymmetrie zwischen Ihrer Verschlüsselungsfunktion und Ihrer Entschlüsselungsfunktion. Wenn Sie verschlüsseln, führen Sie eine AES-Verschlüsselung und dann eine base64-Verschlüsselung durch. Beim Entschlüsseln machen Sie zunächst den base64-Verschlüsselungsschritt nicht rückgängig.

Ich denke, mit Ihrer base64-Kodierung stimmt etwas nicht, und [ sollte nicht in einer mit Base64 kodierten Zeichenfolge erscheinen.

In der Dokumentation zu org.Apache.commons.codec.binary.Base64 sollten Sie dazu in der Lage sein, encod zu tun:

String encryptedValue = Base64.encodeBase64String(encValue);

und dies am dekodieren:

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