2013-06-21 9 views
13

sto ottenendo un errore di decrittografia in classe Java:javax.crypto.IllegalBlockSizeException: lunghezza di ingresso deve essere multiplo di 16, quando decifrare con imbottitura cifra

javax.crypto.IllegalBlockSizeException : 
    Input length must be multiple of 16 when decrypting with padded cipher. 

Cosa posso fare per risolvere questo problema?

UPDATE:

Ho dimenticato di dire che funzioni una volta e quando la seconda volta nel tentativo di eseguire di nuovo il suo gettando l'errore sopra citato.

package com.tb.module.service; 
import java.security.Key; 
import java.security.spec.InvalidKeySpecException; 

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

import sun.misc.*; 

/** 
* This class is used for encrypt and decrypt the password field. 
* 
*/ 
public class PswdEnc { 

    private static final String ALGO = "AES"; 
    private static final byte[] keyValue = new byte[] { 'T', 'h', 'e', 'B', 'e', 's', 't','S', 'e', 'c', 'r','e', 't', 'K', 'e', 'y' }; 

    public static String encrypt(String Data) throws Exception { 
     Key key = generateKey(); 
     Cipher c = Cipher.getInstance(ALGO); 
     c.init(Cipher.ENCRYPT_MODE, key); 
     byte[] encVal = c.doFinal(Data.getBytes()); 
     String encryptedValue = new BASE64Encoder().encode(encVal); 
     return encryptedValue; 
    } 

    public static String decrypt(String encryptedData) throws Exception { 
     Key key = generateKey(); 
     Cipher c = Cipher.getInstance(ALGO); 
     c.init(Cipher.DECRYPT_MODE, key); 
     byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData); 
     byte[] decValue = c.doFinal(decordedValue); 
     String decryptedValue = new String(decValue); 
     return decryptedValue; 
    } 


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

} 
+0

Qualsiasi cosa decifri è la dimensione sbagliata. Deve essere un multiplo della dimensione del blocco (16), altrimenti non può essere decodificato. Come stai ottenendo i tuoi dati decrittografati? – thegrinner

+0

in realtà sto crittografando la password prima di salvarla in sql db. quindi durante il recupero sto cercando di decrittografarlo. – baburao113

+0

Sei sicuro che i dati che stai salvando e i dati che stai leggendo abbiano la stessa lunghezza? – thegrinner

risposta

2

Alcuni commenti:

import sun.misc.*; Non fanno questo. Non è standard e non è garantito che sia lo stesso tra le implementazioni. Ci sono altre librerie con la conversione Base64 disponibile.

byte[] encVal = c.doFinal(Data.getBytes()); Si sta facendo affidamento sulla codifica dei caratteri di default qui. Specifica sempre la codifica dei caratteri che stai utilizzando: byte[] encVal = c.doFinal(Data.getBytes("UTF-8")); I valori predefiniti potrebbero essere diversi in luoghi diversi.

Come sottolineato da @thegrinner, è necessario controllare esplicitamente la lunghezza degli array di byte. Se esiste una discrepanza, confrontarli byte per byte per vedere dove si sta insinuando la differenza.

+0

* Ci sono altre librerie con la conversione Base64 disponibile *> Da Java 6, prova 'DatatypeConverter'. –

57

L'algoritmo che si sta utilizzando, "AES", è una scorciatoia per "AES/ECB/NoPadding". Ciò significa che stai utilizzando lo AES algorithm con una chiave a 128 bit e block size, con lo ECBmode of operation e no padding.

In altre parole: è possibile crittografare i dati solo in blocchi di 128 bit o 16 byte. Ecco perché ricevi questa eccezione IllegalBlockSizeException.

Se si desidera crittografare i dati in dimensioni non multiple di 16 byte, è necessario utilizzare un tipo di riempimento o un flusso di crittografia. Ad esempio, è possibile utilizzare CBC mode (una modalità di funzionamento che trasforma efficacemente un codice di blocco in uno stream cipher) specificando "AES/CBC/NoPadding" come algoritmo o riempimento PKCS5 specificando "AES/ECB/PKCS5", che aggiungi automaticamente alcuni byte alla fine dei tuoi dati in un formato molto specifico per rendere le dimensioni del multiplo di 16 byte, e in un modo che l'algoritmo di decodifica comprenderà che deve ignorare alcuni dati.

In ogni caso, suggerisco caldamente di interrompere subito ciò che state facendo e di studiare alcuni materiali introduttivi sulla crittografia. Ad esempio, controlla Crypto I on Coursera. Dovresti capire molto bene le implicazioni di scegliere una modalità o un'altra, quali sono i loro punti di forza e, soprattutto, le loro debolezze. Senza questa conoscenza, è molto facile costruire sistemi che sono molto facili da rompere.


Aggiornamento: in base ai vostri commenti sulla questione, non mai crittografare le password, quando la loro memorizzazione in un database !!!!! Non dovresti mai farlo mai. È necessario HASH le password, correttamente salate, che è completamente diverso dalla crittografia. Davvero, per favore, non fare quello che stai cercando di fare ... Codificando le password, possono essere decifrate. Ciò significa che tu, come gestore del database e chi conosce la chiave segreta, sarai in grado di leggere ogni password memorizzata nel tuo database.O lo sapevi e stai facendo qualcosa di molto, molto male, o non lo sapevi, e dovresti rimanere scioccato e fermarlo.

+0

Non ero a conoscenza del fatto che non dovrei crittografare la password e archiviarla nel database. Grazie per le informazioni. – baburao113

+0

@ baburao113 quindi dovresti davvero accettare la risposta –

+6

+1 per raccomandare l'hashing sulla crittografia –

2

Per risolvere il problema poche modifiche che devi fare nel tuo codice basta rendere il tipo di ritorno di encrypt() API della tua classe è byte [] array e in decrypt() API del tuo passaggio classe byte [] array così facendo questo è possibile risolvere più lunghezze in ingresso di 16 eccezioni.

prega di fare riferimento qui sotto il codice di lavoro:

public static byte[] encrypt(String value) { 
     byte[] encrypted = null; 
     try { 

      byte[] raw = new byte[]{'T', 'h', 'i', 's', 'I', 's', 'A', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y'}; 
      Key skeySpec = new SecretKeySpec(raw, "AES"); 
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
      byte[] iv = new byte[cipher.getBlockSize()]; 

      IvParameterSpec ivParams = new IvParameterSpec(iv); 
      cipher.init(Cipher.ENCRYPT_MODE, skeySpec,ivParams); 
      encrypted = cipher.doFinal(value.getBytes()); 
      System.out.println("encrypted string:" + encrypted.length); 

     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
     return encrypted; 
    } 

    public static byte[] decrypt(byte[] encrypted) { 
     byte[] original = null; 
     Cipher cipher = null; 
     try { 
      byte[] raw = new byte[]{'T', 'h', 'i', 's', 'I', 's', 'A', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y'}; 
      Key key = new SecretKeySpec(raw, "AES"); 
      cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
      //the block size (in bytes), or 0 if the underlying algorithm is not a block cipher 
      byte[] ivByte = new byte[cipher.getBlockSize()]; 
      //This class specifies an initialization vector (IV). Examples which use 
      //IVs are ciphers in feedback mode, e.g., DES in CBC mode and RSA ciphers with OAEP encoding operation. 
      IvParameterSpec ivParamsSpec = new IvParameterSpec(ivByte); 
      cipher.init(Cipher.DECRYPT_MODE, key, ivParamsSpec); 
      original= cipher.doFinal(encrypted); 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
     return original; 
    } 
0

Bene che è a causa della

si è solo in grado di crittografare i dati in blocchi di 128 bit o 16 byte. Ecco perché ricevi questa eccezione IllegalBlockSizeException. e l'unico modo è quello di crittografare i dati direttamente nella stringa.

guarda questo. Prova e sarai in grado di risolvere questo

public static String decrypt(String encryptedData) throws Exception { 

    Key key = generateKey(); 
    Cipher c = Cipher.getInstance(ALGO); 
    c.init(Cipher.DECRYPT_MODE, key); 
    String decordedValue = new BASE64Decoder().decodeBuffer(encryptedData).toString().trim(); 
    System.out.println("This is Data to be Decrypted" + decordedValue); 
    return decordedValue; 
} 

speranza che ti aiuterà.

Problemi correlati