2010-10-17 18 views
20

Ho il seguente programma per la crittografia dei dati.Cifrare e decodificare con codifica AES e 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; 
    } 

} 

Qui sto ottenendo il seguente fuori posto con eccezione?

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

Qualcuno può spiegarmi la causa? Perché il suo unico dire quando decifrare quella lunghezza dovrebbe essere 16. Non converte in 16 come la crittografia con il metodo doFinal.

E come dice l'eccezione "come decifrare senza cifratura completa?"

+0

Avevi ragione tranne 2 punti. Ho menzionato in un'altra risposta .. –

risposta

44

l'ordine per cifrare:getBytes, cifrare, codificare, toString
l'ordine per decrypt:getBytes, decifrare, decodificare, toString

due problemi:

  1. Come qualcuno ha già menzionato, è necessario invertire l'ordine delle operazioni per d ecryption. Non lo stai facendo.
  2. encrypt fornisce 16 byte, codifica 24 byte, ma toString fornisce 106 byte. Qualcosa che ha a che fare con caratteri non validi che occupano spazio aggiuntivo.

Nota: Inoltre, non è necessario chiamare il numero generateKey() due volte.

Risolvere il problema n. 1 utilizzando l'ordine inverso per la decrittografia. ordine corretta:getBytes, decodificare, decifrare, toString
problema Fix # 2 sostituendo xxx.toString() con new String(xxx). Fatelo in entrambe le funzioni di criptazione e decrittografia.

tuo decifrare dovrebbe essere simile a questo:

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

Questo dovrebbe dare indietro "dude5"

+1

nella parte superiore della risposta si fornisce l'ordine di decrittografia come: getBytes, decrypt, decode, toString. Quindi in seguito fornisci l'ordine corretto come: getBytes, decodifica, decodifica, toString. Credo che il secondo ordine sia corretto. – Magnus

+2

Magnus, all'inizio della mia risposta, quando ho menzionato "Il tuo ordine ...", questo è l'ordine in cui OP stava eseguendo la sequenza. Il "tuo" si riferisce a OP. Quello non è il "mio" ordine. –

+2

È anche importante notare che si dovrebbe sempre usare un set di caratteri specifico quando si crea una stringa dal byte [] e viceversa: ad es. 'new String (byte," UTF-8 ")' e 'string.getBytes (" UTF-8 ")'. Ciò garantisce che se la crittografia e la decrittografia vengono eseguite su sistemi diversi con diversi set di sistema, ciò non determinerà un errore. –

0

Fondamentalmente, esiste un'asimmetria tra la funzione di crittografia e la funzione di decrittografia. Quando esegui la crittografia, esegui una codifica AES e quindi una codifica base64, quando decifri non devi prima annullare il passo di codifica base64.

Penso che ci sia qualcosa di sbagliato nella codifica base64 e nello [ non dovrebbe apparire in una stringa codificata in base64.

Guardando la documentazione per org.apache.commons.codec.binary.Base64 si dovrebbe essere in grado di fare questo su codificare:

String encryptedValue = Base64.encodeBase64String(encValue); 

e questo su decodifica:

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

non è un metodo come encodeBase64String charles – Harshana

+0

@Harshana: Cos'è questo, allora? http://commons.apache.org/codec/apidocs/org/apache/commons/codec/binary/Base64.html#encodeBase64String%28byte[]%29 –

3

La linea

String encryptedValue = encryptedByteValue.toString(); 

è la problema. Il tipo di encryptedByteValue è byte [] e la chiamata aString su di esso non è ciò che vuoi fare lì. Prova invece a

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

Quindi utilizzare Base64.decodeBase64(encryptedValue) in decrittografia. Devi farlo prima di provare a decrittografarlo. È necessario annullare le operazioni nell'ordine inverso del metodo di crittografia.

+0

è appena aggiunto lì per restituire una stringa dal metodo..anche in Base64 non esiste tale metodo encodeToString – Harshana

+0

Per quanto riguarda toString, chiamare quel metodo su una matrice non è quasi mai ciò che si vuole fare. Restituisce l'indirizzo in memoria dell'oggetto, non una rappresentazione String utile. Per quanto riguarda Base64, non stai usando questo? http://commons.apache.org/codec/apidocs/org/apache/commons/codec/binary/Base64.html Vedi il metodo qui: http://commons.apache.org/codec/apidocs/org/apache/commons/codec/binary/Base64.html#encodeToString%28byte[]%29 – laz

+0

ive metti commons-codec-1.2 e prova anche il jar 1.3, ma sembra che il metodo non sia noto allo schermo. – Harshana

2

Dove si ottiene una versione di Apache codec che ha codificaToString o encodeBase64String?

Ho scaricato 1.5 dal sito Apache e, mentre nella documentazione è indicato che questi metodi esistono, non vengono visualizzati quando si esegue il completamento del codice e creano un metodo sconosciuto quando li si fornisce.

sono stato in grado di fare:

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 

E poi la stringa che ho ottenuto è stato molto lungo, ma decifrati correttamente.

Non penso che questo sia il modo "giusto" per fare le cose, ma non riesco a trovare i metodi che la documentazione dice siano lì.

0

ho sostituisce linea nell'esempio:

String encryptedValue = encryptedByteValue.toString(); 

con successiva:

String encryptedValue = new String(encryptedByteValue); 

Tutto funziona bene!

+1

Dubito seriamente che questo risolva il padding Exception; più probabilmente stai utilizzando una JVM diversa. –

0

Che andava bene, è solo bisogno di

1) Utilizzare new String invece di toString() dal toString() non restituisce quello che vi serve qui (in entrambi i casi, la crittografia e la decrittografia)

2) è necessario prima decodificare poiché il valore è codificato in base64.

Mi sono imbattuto in questo thread ma ci sono voluti un po 'per scoprire il vero punto ... Sto postando il mio codice per il resto delle persone che si imbattono in questo problema.

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