[英]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.