我想使用gson将加密的Profile对象存储在SharedPreferences
中。
这是我的代码:
public void saveProfile(Profile newProfile) {
try {
Log.i(C.TAG, newProfile.toString());
SharedPreferences.Editor editor = prefs.edit();
String profileJSONfied = new Gson().toJson(newProfile);
Log.i(C.TAG, profileJSONfied);
byte[] cleartext = profileJSONfied.getBytes(HTTP.UTF_8);
Log.i(C.TAG, cleartext.toString());
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, key);
String encrypedProfile = Base64.encodeToString(cipher.doFinal(cleartext), Base64.DEFAULT);
Log.i(C.TAG, encrypedProfile);
editor.putString(PROFILE, encrypedProfile);
editor.commit();
profile = newProfile;
} catch (Exception e) {
Log.i(C.TAG, e.getMessage());
}
}
public Profile loadProfile() {
try {
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, key);
Log.i(C.TAG, prefs.getString(PROFILE, null));
// byte[] plainTextProfileBytes = Base64.decode(cipher.doFinal(prefs.getString(PROFILE, null).getBytes(HTTP.UTF_8)), Base64.DEFAULT);
byte[] plainTextProfileBytes = Base64.decode(prefs.getString(PROFILE, null).getBytes(HTTP.UTF_8), Base64.DEFAULT);
Log.i(C.TAG, new String(plainTextProfileBytes, HTTP.UTF_8));
profile = new Gson().fromJson(new String(plainTextProfileBytes, HTTP.UTF_8), PROFILE_TYPE);
Log.i(C.TAG, profile.toString());
} catch (Exception e) {
Log.i(C.TAG, e.getMessage());
}
return profile;
}
这是一个输出示例(按Log的顺序排序):
saveProfile:
简介@ 4146a1d8
{“email”:“aaa”,“firstName”:“aaa”,“lastName”:“aaa”,“postal”:“aaa”等等......}
[B @ 414819b0
+ nLS7XhRoIFPBeC11 / h6mMz6hFfc8js03QJ8VwVZH + dPBeC11 / h6mJ448CLGPNzz + bU669XpAI8VXchYQJr7mgDwHpeoSrP4BMACydjKpC8Q9atbk9xz6HNqDpNOiqaa75hFM + r9pzm55 / E2E2tdjz4s5OzNNppAPzmtS69tZAZLPuYt1kvnJehHa6fDt2o5UCv6VukCwvVgt + UDcCqCKvF22Iv6vdMXWTcm
在这一点上,我认为一切都按预期进行。问题在于,破译操作
loadProfile :(后退流程)
+ nLS7XhRoIFPBeC11 / h6mMz6hFfc8js03QJ8VwVZH + dPBeC11 / h6mJ448CLGPNzz + bU669XpAI8VXchYQJr7mgDwHpeoSrP4BMACydjKpC8Q9atbk9xz6HNqDpNOiqaa75hFM + r9pzm55 / E2E2tdjz4s5OzNNppAPzmtS69tZAZLPuYt1kvnJehHa6fDt2o5UCv6VukCwvVgt + UDcCqCKvF22Iv6vdMXWTcm
rxQOzW; 4 | WYOz8" <:] X @Jʤ/ [ssjNE396k] GT;,6 @ 9 KmdK> -K%Gk中÷j9P + V`p ** v؋Y7&安培; -A
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 21
如果我而不是:
byte[] plainTextProfileBytes = Base64.decode(prefs.getString(PROFILE,null).getBytes(HTTP.UTF_8), Base64.DEFAULT);
我用:
byte[] plainTextProfileBytes = Base64.decode(cipher.doFinal(prefs.getString(PROFILE, null).getBytes(HTTP.UTF_8)), Base64.DEFAULT);
错误将是:
pad block corrupted
我在这里想念的是什么? 谢谢你的时间。
答案 0 :(得分:1)
所以,我找到了解决办法!
对于初学者我改变了一些代码。我用两种方法创建了一个myPBEkey类,加密和解密,都返回一个带有相应“opmode”的Cipher对象:
然后我将saveProfile和loadProfile方法代码更改为:
public void saveProfile(Profile newProfile) {
try {
SharedPreferences.Editor editor = prefs.edit();
String profileJSONfied = new Gson().toJson(newProfile);
byte[] encryptedProfile = pbeKey.encrypt().doFinal(profileJSONfied.getBytes(HTTP.UTF_8));
byte[] encryptedProfileBase64 = Base64.encode(encryptedProfile, Base64.DEFAULT);
editor.putString(PROFILE, new String(encryptedProfileBase64, HTTP.UTF_8));
editor.commit();
profile = newProfile;
} catch (Exception e) {
Log.i(C.TAG, e.getMessage());
}
}
public Profile loadProfile() {
if (profile == null) {
try {
byte[] decodedProfileBase64 = Base64.decode(prefs.getString(PROFILE, null), Base64.DEFAULT);
byte[] plainTextProfileBytes = pbeKey.decrypt().doFinal(decodedProfileBase64);
profile = new Gson().fromJson(new String(plainTextProfileBytes, HTTP.UTF_8), PROFILE_TYPE);
} catch (Exception e) {
Log.i(C.TAG, e.getMessage());
}
return profile;
我认为解决问题的原因是将加密/解密与Base64
编码/解码分开,所以首先我们加密然后编码加密的byte[]
并最终存储它。解密时也是如此,首先我们解码加密的base64配置文件,然后解密解码的byte[]
。瞧!
感谢您的时间,希望对您有所帮助。