如何解决此代码中的“javax.crypto.IllegalBlockSizeException:解密中的最后一个块不完整”

时间:2013-07-10 12:37:13

标签: java android

我阅读了很多解释如何解决此类异常的内容,但我仍然无法解决此问题。

我的目标是:   1.使用SecretKey加密字符串数据并将其存储到SQLite数据库中。   2.从SQLite数据库中读取数据并使用相同的SecretKey对其进行解密。

这是我的类加密和解密android应用程序中的数据(目标1和2的实现)。此代码提供异常 - javax.crypto.IllegalBlockSizeException:解密时最后一个块不完整

我该如何解决这个错误?任何消化都将受到赞赏..谢谢

      public class Cryptography {

    private String encryptedFileName = "Enc_File2.txt";
    private static String algorithm = "AES";
    private static final int outputKeyLength = 256;
    static SecretKey yourKey = null;

    SQLiteDatabase database;
    DBHelper helper;
    Context context;

    //saveFile("Hello From CoderzHeaven testing :: Gaurav Wable");
    //decodeFile();

    public Cryptography (Context context) {
        this.context = context;
        helper = new DBHelper(context);
        database = helper.getWritableDatabase();
    }


    public String encryptString(String data) {
        char[] p = { 'p', 'a', 's', 's' };
        //SecretKey yourKey = null;
        byte[] keyBytes = null;
        byte[] filesBytes = null;
        try {
            if(this.yourKey == null) {
                Log.d("key", "instance null");
                Cursor cursor = database.query("assmain", new String[]{"keyAvailability"}, null, null, null, null, null);
                cursor.moveToFirst();
                if(cursor.getInt(cursor.getColumnIndex("keyAvailability")) == 1) {
                    Log.d("key", "exists in DB");
                    keyBytes = cursor.getBlob(cursor.getColumnIndex("key"));
                    cursor.close();
                    filesBytes = encodeFile(keyBytes, data.getBytes());
                } else {
                    Log.d("key", "generating");
                    this.yourKey = generateKey(p, generateSalt().toString().getBytes()); 
                    filesBytes = encodeFile(this.yourKey, data.getBytes());
                }
            } else {
                Log.d("key", "instance exists");
                //yourKey = this.yourKey;
                filesBytes = encodeFile(yourKey, data.getBytes());
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return new String(filesBytes);
    }

    public String decryptString(String data) {
        String str = null;
        byte[] decodedData = null;
        try {
            Log.d("To decrypt", data);
            if(this.yourKey == null) {
                Log.d("key", "null");
                Cursor cursor = database.query("assmain", new String[]{"keyAvailability"}, null, null, null, null, null);
                cursor.moveToFirst();
                if(cursor.getInt(cursor.getColumnIndex("keyAvailability")) == 1) {
                    Log.d("key", "exists in DB");
                    byte[] keyBytes = cursor.getBlob(cursor.getColumnIndex("key"));
                    cursor.close();
                    decodedData = decodeFile(keyBytes, data.getBytes());
                } else {
                    Log.d("key", "Unavailable");
                    Toast.makeText(context, "Key Unavailable", Toast.LENGTH_SHORT).show();
                }
            } else {
                Log.d("key", "instance exists");
                decodedData = decodeFile(this.yourKey, data.getBytes());
            }
            decodedData = decodeFile(yourKey, data.getBytes());
            str = new String(decodedData);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return str;
    }

    public static SecretKey generateKey(char[] passphraseOrPin, byte[] salt)
            throws NoSuchAlgorithmException, InvalidKeySpecException {
        // Number of PBKDF2 hardening rounds to use. Larger values increase
        // computation time. You should select a value that causes computation
        // to take >100ms.
        final int iterations = 1000;

        // Generate a 256-bit key
        //final int outputKeyLength = 256;

        SecretKeyFactory secretKeyFactory = SecretKeyFactory
                .getInstance("PBKDF2WithHmacSHA1");
        KeySpec keySpec = new PBEKeySpec(passphraseOrPin, salt, iterations,
                outputKeyLength);
        yourKey = secretKeyFactory.generateSecret(keySpec);
        return yourKey;
    }

    public static SecretKey generateSalt() throws NoSuchAlgorithmException {
        // Generate a 256-bit key
        //final int outputKeyLength = 256;

        SecureRandom secureRandom = new SecureRandom();
        // Do *not* seed secureRandom! Automatically seeded from system entropy.
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        keyGenerator.init(outputKeyLength, secureRandom);
        SecretKey key = keyGenerator.generateKey();
        return key;
    }

    public static byte[] encodeFile(SecretKey yourKey, byte[] fileData)
            throws Exception {
        byte[] data = yourKey.getEncoded();
        SecretKeySpec skeySpec = new SecretKeySpec(data, 0, data.length,
                algorithm);
        Cipher cipher = Cipher.getInstance(algorithm);
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);

        byte[] encrypted = cipher.doFinal(fileData);

        return encrypted;
    }

    public static byte[] encodeFile(byte[] data, byte[] fileData)
            throws Exception {
        //byte[] data = yourKey.getEncoded();
        SecretKeySpec skeySpec = new SecretKeySpec(data, 0, data.length,
                algorithm);
        Cipher cipher = Cipher.getInstance(algorithm);
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);

        byte[] encrypted = cipher.doFinal(fileData);

        return encrypted;
    }

    public static byte[] decodeFile(SecretKey yourKey, byte[] fileData)
            throws Exception {
        byte[] data = yourKey.getEncoded();
        SecretKeySpec skeySpec = new SecretKeySpec(data, 0, data.length,
                algorithm);
        //Cipher cipher = Cipher.getInstance(algorithm);
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);

        byte[] decrypted = cipher.doFinal(fileData);

        return decrypted;
    }

    public static byte[] decodeFile(byte[] data, byte[] fileData)
            throws Exception {
        //byte[] data = yourKey.getEncoded();
        SecretKeySpec skeySpec = new SecretKeySpec(data, 0, data.length,
                algorithm);
        Cipher cipher = Cipher.getInstance(algorithm);
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);

        byte[] decrypted = cipher.doFinal(fileData);

        return decrypted;
    }
    }

这是错误代码段

07-01 14:50:48.230: W/System.err(11715): javax.crypto.IllegalBlockSizeException: last block incomplete in decryption
07-01 14:50:48.230: W/System.err(11715):    at com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(BaseBlockCipher.java:705)
07-01 14:50:48.230: W/System.err(11715):    at javax.crypto.Cipher.doFinal(Cipher.java:1111)
07-01 14:50:48.230: W/System.err(11715):    at com.cdac.authenticationl3.Cryptography.decodeFile(Cryptography.java:170)
07-01 14:50:48.230: W/System.err(11715):    at com.cdac.authenticationl3.Cryptography.decryptString(Cryptography.java:95)

1 个答案:

答案 0 :(得分:0)

您正在使用AES / ECB / PKCS5Padding来解密文件,但在加密文件时却没有。 添加AES / ECB / PKCS5Padding也用于加密过程。所以它应该是

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

希望这有帮助