2012-12-04 5 views
6

Der Code unten funktioniert zwar, aber wenn ich kontinuierlich w \ u00e4hle Würfe "Gegebene Endblock nicht richtig gepolstert" einige Male und andere auch. Ich fühle, dass ich irgendwo einen kleinen Fehler mache. Können Sie mir helfen, das Problem zu lösen?Using-Passwort-basierte Verschlüsselung in Android

Exception Stack:

Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded 
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811) 
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676) 
    at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:313) 
    at javax.crypto.Cipher.doFinal(Cipher.java:2086) 
    at MCrypt.decrypt(MCrypt.java:87) 
    at MCrypt.main(MCrypt.java:21) 

Und mein Code:

import java.security.SecureRandom; 
import java.security.spec.KeySpec; 

import javax.crypto.Cipher; 
import javax.crypto.SecretKey; 
import javax.crypto.SecretKeyFactory; 
import javax.crypto.spec.IvParameterSpec; 
import javax.crypto.spec.PBEKeySpec; 
import javax.crypto.spec.SecretKeySpec; 

public class MCrypt { 

    private int iterationCount = 10000; 
    private int saltLength = 8; // bytes; 64 bits 
    private int keyLength = 128; 

    public static void main(String[] args) throws Exception { 
     MCrypt mc = new MCrypt(); 
     String encryptedData = mc.encrypt("1234"); 
     MCrypt mc1 = new MCrypt(); 
     System.out.println(new String(mc1.decrypt(new String(encryptedData), 
       "1234"), "UTF-8")); 
    } 

    public MCrypt() { 
    } 

    public String encrypt(String text) throws Exception { 
     if (text == null || text.length() == 0) 
      throw new Exception("Empty string"); 

     byte[] encrypted = null; 

     SecureRandom random = new SecureRandom(); 
     byte[] salt = new byte[saltLength]; 
     random.nextBytes(salt); 

     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 

     byte[] iv = new byte[cipher.getBlockSize()]; 
     random.nextBytes(iv); 
     IvParameterSpec ivParams = new IvParameterSpec(iv); 

     KeySpec keySpec = new PBEKeySpec(text.toCharArray(), salt, 
       iterationCount, keyLength); 
     SecretKeyFactory keyFactory = SecretKeyFactory 
       .getInstance("PBKDF2WithHmacSHA1"); 
     byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded(); 
     SecretKey key = new SecretKeySpec(keyBytes, "AES"); 

     cipher.init(Cipher.ENCRYPT_MODE, key, ivParams); 

     encrypted = cipher.doFinal(text.getBytes("UTF-8")); 
     String encryptedStr = Base64.encodeBytes(encrypted); 

     StringBuffer strBuf = new StringBuffer(); 
     strBuf.append(new String(encryptedStr)); 
     strBuf.append("]"); 
     strBuf.append(new String(salt)); 
     strBuf.append("]"); 
     strBuf.append(new String(iv)); 

     return new String(Base64.encodeBytes(strBuf.toString().getBytes())); 
    } 

    public byte[] decrypt(String code, String pwd) throws Exception { 
     if (code == null || code.length() == 0) 
      throw new Exception("Empty string"); 

     String[] fields = new String(Base64.decode(code)).split("]"); 
     byte[] cipherBytes = Base64.decode(fields[0]); 
     byte[] salt = fields[1].getBytes(); 
     byte[] iv = fields[2].getBytes(); 

     KeySpec keySpec = new PBEKeySpec(pwd.toCharArray(), salt, 
       iterationCount, keyLength); 
     SecretKeyFactory keyFactory = SecretKeyFactory 
       .getInstance("PBKDF2WithHmacSHA1"); 
     byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded(); 
     SecretKey key = new SecretKeySpec(keyBytes, "AES"); 

     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     IvParameterSpec ivParams = new IvParameterSpec(iv); 

     byte[] decrypted = null; 
     cipher.init(Cipher.DECRYPT_MODE, key, ivParams); 
     decrypted = cipher.doFinal(cipherBytes); 

     return decrypted; 
    } 

} 
+1

Ihre Methoden machen keinen Sinn, die Verschlüsselungsmethode scheint den zu verschlüsselnden Text zu verwenden, um den Schlüssel auch abzuleiten. Wenn Ihre Verschlüsselungsmethode Zeichenfolgen verwendet und Zeichenfolgen zurückgibt, sollte dies auch Ihre Entschlüsselungsmethode sein. –

+0

Ich löste das Problem. StringBuffer strBuf = new StringBuffer(); \t \t strBuf.append (encryptedStr); \t \t strBuf.append ("]"); \t \t Zeichenfolge saltStr = Base64.encodeBytes (Salz); \t \t strBuf.append (SalzStr); \t \t strBuf.append ("]"); \t \t Zeichenfolge ivStr = Base64.encodeBytes (iv); \t \t strBuf.append (ivStr); – user1876402

+0

Ja das ist die Art, wie ich es möchte Ich wollte diese Methode "Verwenden von Passwort-basierten Verschlüsselung". daher das Verfahren. Wenn Sie etwas besseres vorschlagen könnten, würde ich mich freuen. – user1876402

Antwort

0

Schauen Sie sich das

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

import android.util.Base64; 
import android.util.Log; 

public class AesFileIo { 
// private static final String AES_ALGORITHM = "AES/CTR/NoPadding"; 
    private static final String AES_ALGORITHM = "AES/CBC/PKCS5Padding"; 
    private SecretKeySpec secretKeySpec; 
    private IvParameterSpec ivSpec; 

    public AesFileIo(byte[] aesKey, byte[] iv) { 
     ivSpec = new IvParameterSpec(iv); 
     secretKeySpec = new SecretKeySpec(aesKey, "AES"); 
    } 

    public String decrypt(String text) { 

     StringBuilder stringBuilder = new StringBuilder(); 
     try { 
      Cipher cipher = Cipher.getInstance(AES_ALGORITHM); 
      cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec); 
      byte[] decordedValue = Base64.decode(text,Base64.DEFAULT); 
      String decryptedValue = new String(cipher.doFinal(decordedValue),"UTF-8"); 
      Log.e("decrypted Value :",decryptedValue); 
      return decryptedValue; 
     } catch (Exception e) { 
      Log.e(this.getClass().toString(), e.getMessage(), e); 
     } 
     return stringBuilder.toString(); 
    } 

    public String encrypt(String text) { 
     String encryptedValue=null; 
     try { 
      Cipher cipher = Cipher.getInstance(AES_ALGORITHM); 
      cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec); 
      byte[] encValue = cipher.doFinal(text.getBytes()); 
      encryptedValue = Base64.encodeToString(encValue,Base64.DEFAULT); 
     } catch (Exception e) { 
      Log.e(this.getClass().toString(), e.getMessage(), e); 
     } 
     return encryptedValue; 
    } 
} 

Wie

0 verwenden,
public static byte[] iv = { '0', '0','0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0' }; 
    private static final byte[] keyValue = new byte[] { 'b', 'i', 'r', 'a', 'j', 'z', 'a', 'l', 'a', 'v', 'a', 'd', 'i', 'y', 'a', 'r' }; 
AesFileIo aes = new AesFileIo(keyValue, iv); 
String encrypetedText = aes.encrypt(str); 
String decryptedText = aes.decrypt(encrypetedText); 

System.out.println("EncrypetedText : " + encrypetedText); 
System.out.println("DecryptedText : " + decryptedText); 
+0

Dies ist wirklich eine unvollständige Lösung. Ich denke nicht, dass Sie einen festen iv-Vektor von 0 Werten übergeben sollten und die von Ihnen gelieferten Passwort-Bytes müssen 16 lang sein. – IcedDante

+1

@ IcedDante Bitte bearbeiten Sie die Antwort und machen Sie eine vollständige Lösung. –

Verwandte Themen