简体   繁体   English

文件解密失败:javax.crypto.BadPaddingException:填充块已损坏

[英]Decryption of file fails: javax.crypto.BadPaddingException: pad block corrupted

I've created a ZIP-File on my pc (I compressed it with the os x zipper in the finder) and after that I encrypted it with my java program: 我在我的电脑上创建了一个ZIP文件(我用finder中的os x压缩器压缩了它),然后用Java程序对其进行了加密:

public class ResourceEncrypter {

    static byte[] salt = { (byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c,
                               (byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99 };

    public static void main(String[] args) {
        new ResourceEncrypter().encryptAllFiles();
        System.out.println("Okay, done");
    }



    private byte[] getKey() {
        try {
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
            sr.setSeed(salt);
            kgen.init(128, sr); 
            SecretKey skey = kgen.generateKey();
            byte[] key = skey.getEncoded();
            return key;
        } catch(Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    private void encryptAllFiles() {
        try {
            byte[] key = getKey();

            //Take a list of files and encrypt each file...
            String srcFilesPath = System.getProperty("user.dir") + "/srcFiles";
            String encryptedSrcFilesPath = System.getProperty("user.dir") + "/encryptedSrcFiles";
            File[] listOfFiles = new File(srcFilesPath).listFiles();
            for(int i = 0; i < listOfFiles.length; ++i) {
                if(listOfFiles[i].getAbsolutePath().contains(".zip")) {
                    //Encrypt this file!
                    byte[] data = Files.readAllBytes(Paths.get(listOfFiles[i].getAbsolutePath()));
                    byte[] encryptedData = ResourceEncrypter.encrypt(key, data);

                    String filename = listOfFiles[i].getName();
                    System.out.println("Write result to " + encryptedSrcFilesPath + "/" + filename);
                    FileOutputStream output = new FileOutputStream(encryptedSrcFilesPath + "/" + filename);
                    output.write(encryptedData);
                    output.close();
                }
            }
        } catch(Exception e) {
            e.printStackTrace();
        }
    }



    private static byte[] encrypt(byte[] key, byte[] data) throws Exception {
        SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        byte[] encryptedData = cipher.doFinal(data);
        return encryptedData;
    }

So, this takes any zip file encrypts it and saves the result to another folder. 因此,这将使用任何zip文件对其进行加密并将结果保存到另一个文件夹。

Now, I got an android app and I put the encrypyted zip file into an asset folder main/assets/pic.zip.encrypted . 现在,我有了一个android应用程序,然后将加密的zip文件放入资产文件夹main/assets/pic.zip.encrypted

In my android app I do the following: 在我的android应用中,我执行以下操作:

public class MainActivity extends AppCompatActivity {

static byte[] salt = {  (byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c,
                                (byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99 };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        decryptZipFile();
    }


    private byte[] getKey() {
        try {
            //Create the key for the encryption/decryption
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
            sr.setSeed(salt);
            kgen.init(128, sr); // 192 and 256 bits may not be available
            SecretKey skey = kgen.generateKey();
            byte[] key = skey.getEncoded();
            return key;
        } catch(Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    private static byte[] decrypt(byte[] key, byte[] encryptedData) throws Exception {
        SecretKeySpec skeySpec = new SecretKeySpec(key,"AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);
        byte[] decrypted = cipher.doFinal(encryptedData);
        return decrypted;
    }


    public void decryptZipFile() {
        // First decrypt the zip file
        try {
            InputStream is = getResources().getAssets().open("pics.zip.encrypted");
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int count;
            while ((count = is.read(buffer)) != -1)
                baos.write(buffer, 0, count);
            byte[] encryptedData = baos.toByteArray();

            byte[] decryptedData = decrypt(getKey(), encryptedData);
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

When I now try to decrypt my zip file with this code I get the following error: 现在,当我尝试使用此代码解密zip文件时,出现以下错误:

09-23 18:41:21.117  30799-30799/demo.zip.app.zipapp W/System.err﹕ javax.crypto.BadPaddingException: pad block corrupted
09-23 18:41:21.117  30799-30799/demo.zip.app.zipapp W/System.err﹕ at com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(BaseBlockCipher.java:854)
09-23 18:41:21.117  30799-30799/demo.zip.app.zipapp W/System.err﹕ at javax.crypto.Cipher.doFinal(Cipher.java:1340)
09-23 18:41:21.117  30799-30799/demo.zip.app.zipapp W/System.err﹕ at demo.zip.app.zipapp.MainActivity.decrypt(MainActivity.java:63)

However, when I apply the same methods for decrypting on my PC it works fine. 但是,当我在PC上应用相同的方法进行解密时,效果很好。

What is happening here? 这是怎么回事

Okay, I found the solution. 好的,我找到了解决方案。

The problem is that SecureRandom and in particular the setSeed method works differently on Android than on normal Java. 问题在于, SecureRandom尤其是setSeed方法在Android上的工作方式与在普通Java上不同。

So, instead you should not construct a key from a salt key as I do above. 因此,相反,您不应该像我上面那样从盐键构造键。 Instead you should go to the PC and get the key from private byte[] getKey() as a Base64 string object. 相反,您应该转到PC并从private byte[] getKey()获取key作为Base64字符串对象。 Then the key looks something like this in my case: n9dReP+BPwHWGCLpDQe+MQ== and then copy an paste this into the android method which becomes this: 然后,在我的情况下,密钥看起来像这样: n9dReP+BPwHWGCLpDQe+MQ== ,然后将其粘贴到android方法中,从而变成:

private byte[] getKey() {
            byte[] key = Base64.decode(new String("n9dReP+BPwHWGCLpDQe+MQ==").getBytes(), 0);
            return key;
    }

That's it. 而已。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 错误:javax.crypto.BadPaddingException:解密时填充块损坏 - Error : javax.crypto.BadPaddingException: pad block corrupted while Decryption javax.crypto.BadPaddingException:pad块损坏 - javax.crypto.BadPaddingException: pad block corrupted Java Blowfish CBC 解密 javax.crypto.BadPaddingException:填充块已损坏 - Java Blowfish CBC Decryption javax.crypto.BadPaddingException: pad block corrupted AES128解密:javax.crypto.badpaddingexception pad块损坏 - AES128 Decryption :javax.crypto.badpaddingexception pad block corrupted Android javax.crypto.BadPaddingException:填充块已损坏 - Android javax.crypto.BadPaddingException: pad block corrupted javax.crypto.BadPaddingException:填充块损坏的异常 - javax.crypto.BadPaddingException: pad block corrupted exception javax.crypto.BadPaddingException:填充块有时损坏 - javax.crypto.BadPaddingException: pad block corrupted sometimes 函数解密引发javax.crypto.BadPaddingException:android中的类SimpleCrypto中的填充块已损坏 - function decrypt throws javax.crypto.BadPaddingException: pad block corrupted in class SimpleCrypto in android 解密图像时,给出javax.crypto.BadPaddingException:填充块损坏的Android - When Decrypting Image, gives javax.crypto.BadPaddingException: pad block corrupted Android javax.crypto.BadPaddingException:解密错误 - javax.crypto.BadPaddingException : Decryption error
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM