【发布时间】:2016-08-09 04:54:24
【问题描述】:
所以我遇到了从基于字符串的密码生成密钥的问题。加密步骤工作正常,解密步骤工作直到底部列出的错误,使解密的文件损坏。我使用以下函数来执行加密/解密:
public static boolean decryptFileFromUri(Context context, Uri file, String keyphrase) {
try {
File f = new File(getRealPathFromURI(context, file));
FileInputStream fis = new FileInputStream(f);
File ef = new File(f.toString().replace(".epf", ""));
FileOutputStream fos = new FileOutputStream(ef);
Log.d("HIDEMYPICS","Decrypting: " + f.toString());
byte[] rawKey = getRawKey(keyphrase.getBytes("UTF8"));
/*KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(rawKey);
kgen.init(128, sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
byte[] key = skey.getEncoded();*/
SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
// Wrap the output stream
CipherOutputStream cos = new CipherOutputStream(fos, cipher);
// Write bytes
int b;
byte[] d = new byte[8];
while ((b = fis.read(d)) != -1) {
cos.write(d, 0, b);
}
// Flush and close streams.
cos.flush();
cos.close();
fis.close();
Log.d("HIDEMYPICS","Decrypted to: " + ef.toString());
return true;
} catch (IOException e){
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return false;
}
public static boolean encryptFileFromUri(Context context, Uri file, String keyphrase) {
try {
File f = new File(getRealPathFromURI(context, file));
FileInputStream fis = new FileInputStream(f);
File ef = new File(f.toString() + ".epf");
FileOutputStream fos = new FileOutputStream(ef);
Log.d("HIDEMYPICS","Encrypting: " + f.toString());
byte[] rawKey = getRawKey(keyphrase.getBytes("UTF8"));
/*KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(rawKey);
kgen.init(128, sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
byte[] key = skey.getEncoded();*/
SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
// Wrap the output stream
CipherOutputStream cos = new CipherOutputStream(fos, cipher);
// Write bytes
int b;
byte[] d = new byte[8];
while ((b = fis.read(d)) != -1) {
cos.write(d, 0, b);
}
// Flush and close streams.
cos.flush();
cos.close();
fis.close();
Log.d("HIDEMYPICS","Encrypted to: " + ef.toString());
return true;
} catch (IOException e){
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return false;
}
这是生成原始密钥的函数:
private static byte[] getRawKey(byte[] seed) throws NoSuchAlgorithmException {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(seed);
kgen.init(128, sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
String result = "";
for(int index = 0; index < raw.length; index++) {
result += Integer.toHexString(raw[index]);
// maybe you have to convert your byte to int before this can be done
// (cannot check reight now)
}
Log.d("HIDEMYPICS","Passphrase: " + new String(seed).toString() + " Key: " + result );
return raw;
}
对于上述密钥的十六进制转储,“test”输入字符串的输出如下:
加密:
04-17 09:01:25.088 18341-18341/com.dcheeseman.hidemypics D/HIDEMYPICS: Encrypting: /storage/emulated/0/Download/bailout_5128280_GIFSoup.com-1.gif
04-17 09:01:25.088 18341-18341/com.dcheeseman.hidemypics D/HIDEMYPICS: Passphrase: test Key: ffffff85affffffe21023ffffffb7ffffffe8ffffffc8214031fffffffa5b29ffffff9affffff80
解密:
04-17 09:01:43.808 18341-18341/com.dcheeseman.hidemypics D/HIDEMYPICS: Decrypting: /storage/emulated/0/Download/bailout_5128280_GIFSoup.com-1.gif.epf
04-17 09:01:43.808 18341-18341/com.dcheeseman.hidemypics D/HIDEMYPICS: Passphrase: test Key: ffffff8331ffffffe2ffffff87ffffffe242dffffffa61cffffffc7ffffffb4ffffffa1d74ffffff9affffff9b
解密和加密都以“test”作为密码,但该函数返回 2 个不同的密钥,这就是为什么我认为我收到了 bad-decrypt 错误,其完整跟踪如下所示:
04-17 09:33:24.158 823-823/com.dcheeseman.hidemypics W/System.err: java.io.IOException: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
04-17 09:33:24.158 823-823/com.dcheeseman.hidemypics W/System.err: at javax.crypto.CipherOutputStream.close(CipherOutputStream.java:136)
04-17 09:33:24.158 823-823/com.dcheeseman.hidemypics W/System.err: at com.dcheeseman.hidemypics.AESUtils.decryptFileFromUri(AESUtils.java:102)
04-17 09:33:24.158 823-823/com.dcheeseman.hidemypics W/System.err: at com.dcheeseman.hidemypics.HideMyPics.onActivityResult(HideMyPics.java:35)
04-17 09:33:24.158 823-823/com.dcheeseman.hidemypics W/System.err: at android.app.Activity.dispatchActivityResult(Activity.java:6808)
04-17 09:33:24.158 823-823/com.dcheeseman.hidemypics W/System.err: at android.app.ActivityThread.deliverResults(ActivityThread.java:4698)
04-17 09:33:24.158 823-823/com.dcheeseman.hidemypics W/System.err: at android.app.ActivityThread.handleSendResult(ActivityThread.java:4745)
04-17 09:33:24.158 823-823/com.dcheeseman.hidemypics W/System.err: at android.app.ActivityThread.access$1500(ActivityThread.java:197)
04-17 09:33:24.158 823-823/com.dcheeseman.hidemypics W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1730)
04-17 09:33:24.158 823-823/com.dcheeseman.hidemypics W/System.err: at android.os.Handler.dispatchMessage(Handler.java:102)
04-17 09:33:24.158 823-823/com.dcheeseman.hidemypics W/System.err: at android.os.Looper.loop(Looper.java:145)
04-17 09:33:24.158 823-823/com.dcheeseman.hidemypics W/System.err: at android.app.ActivityThread.main(ActivityThread.java:6872)
04-17 09:33:24.158 823-823/com.dcheeseman.hidemypics W/System.err: at java.lang.reflect.Method.invoke(Native Method)
04-17 09:33:24.158 823-823/com.dcheeseman.hidemypics W/System.err: at java.lang.reflect.Method.invoke(Method.java:372)
04-17 09:33:24.158 823-823/com.dcheeseman.hidemypics W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
04-17 09:33:24.158 823-823/com.dcheeseman.hidemypics W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)
提前感谢您对此问题的任何帮助!
【问题讨论】:
-
从问题中删除未使用的代码。
-
您声明:“2 个不同的密钥”,密钥必须相同,因此要调试的区域是密钥派生
getRawKey。还要检查 IV 是如何创建并传递给解密的,您需要研究库文档。
标签: android encryption passwords encryption-symmetric