共享偏好?javax.crypto.BadPaddingException:pad块仅在某些设备中损坏

D4r*_*iNS 6 android sharedpreferences sony-xperia nexus-5

我从谷歌播放控制台收到一些错误,其中一些用户(Pixel XL,nexus 5和Xperia Z3 +)正在获得

Caused by: java.lang.RuntimeException: javax.crypto.BadPaddingException: pad block corrupted
at com.darwins.custom.ObscuredSharedPreferences.decrypt(ObscuredSharedPreferences.java:193)
at com.darwins.custom.ObscuredSharedPreferences.getInt(ObscuredSharedPreferences.java:134)
Run Code Online (Sandbox Code Playgroud)

该应用程序在其余设备上工作正常(即使在一些nexus 5工作正常)

当用户第一次打开应用程序时,问题出现了,它尝试从共享首选项加载音乐卷.由于他们从未在选项菜单中输入以更改默认值,因此应获取默认值:

if(sp      == null) sp = new ObscuredSharedPreferences(ctx, ctx.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE));
if(musicVolume == -1) musicVolume = sp.getInt(KEY_SP_MUSIC_VOLUME,10);
Run Code Online (Sandbox Code Playgroud)

如果我们从ObsucredSharedPreferences输入getInt:

@Override
public int getInt(String key, int defValue) {
    final String v = delegate.getString(key, null);
    return v!=null ? Integer.parseInt(decrypt(v)) : defValue;
}
Run Code Online (Sandbox Code Playgroud)

因此,getString我没有得到null值,而是得到像"ERKJFER89er"这样的值(我从不在首选项中写入该值,否则它应该在每个手机上崩溃)所以当它试图解密该值时,它期望一个int值,它抛出一个javax.crypto.BadPaddingException: pad block corrupted我不知道如何解决这个或如何解决这个问题,任何想法将是apreciate

解密代码:

protected String decrypt(String value){
    try {
        final byte[] bytes = value!=null ? Base64.decode(value,Base64.DEFAULT) : new byte[0];
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
        SecretKey key = keyFactory.generateSecret(new PBEKeySpec(SEKRIT));
        Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
        pbeCipher.init(Cipher.DECRYPT_MODE, key, new PBEParameterSpec( Secure.getString(context.getContentResolver(), Secure.ANDROID_ID).getBytes(UTF8), 20));
        return new String(pbeCipher.doFinal(bytes),UTF8);

    } catch( Exception e) {
        throw new RuntimeException(e);
    }
}
Run Code Online (Sandbox Code Playgroud)

1位用户说出厂恢复不能解决问题但是使用擦除缓存进行恢复出厂设置并擦除数据解决问题

谷歌像素的完整堆栈strace

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.suduck.upgradethegame/com.darwins.cubegame.WelcomeActivity}: java.lang.RuntimeException: javax.crypto.BadPaddingException: pad block corrupted
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
Caused by: java.lang.RuntimeException: javax.crypto.BadPaddingException: pad block corrupted
at com.darwins.custom.ObscuredSharedPreferences.decrypt(ObscuredSharedPreferences.java:193)
at com.darwins.custom.ObscuredSharedPreferences.getInt(ObscuredSharedPreferences.java:134)
at com.darwins.clases.Logro.<init>(Logro.java:41)
at com.darwins.clases.LogrosManager.iniciar(LogrosManager.java:64)
at com.darwins.clases.LogrosManager.<init>(LogrosManager.java:48)
at com.darwins.motor.CEngine.Inicializar(CEngine.java:141)
at com.darwins.superclases.CActividad.onCreate(CActividad.java:47)
at com.darwins.cubegame.WelcomeActivity.onCreate(WelcomeActivity.java:32)
at android.app.Activity.performCreate(Activity.java:6679)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618)
... 9 more
Caused by: javax.crypto.BadPaddingException: pad block corrupted
at com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher$BufferedGenericBlockCipher.doFinal(BaseBlockCipher.java:1267)
at com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(BaseBlockCipher.java:1100)
at javax.crypto.Cipher.doFinal(Cipher.java:2056)
at com.darwins.custom.ObscuredSharedPreferences.decrypt(ObscuredSharedPreferences.java:190)
Run Code Online (Sandbox Code Playgroud)

Sim*_*Liu 1

的返回结果是什么decrypt(null)?您的应用程序似乎读取了一些之前写入不正确的数据。

我还注意到某些设备在数据文件夹路径上有不同的行为,可能导致此问题。

针对您的问题的一种可能的解决方案是记录详细的崩溃上下文,包括导致解密错误的数据。您可以尝试一些在线日志服务,例如 Fabric 或 Logentries。或者您可以实现全局异常处理程序,保存数据并在崩溃发生时将数据发送给您。

IMO,我更喜欢将所有数据保存在字符串中,并在运行时解析它们,以防数据格式发生变化。

供参考。这是我的偏好实现。它支持保存在 SharedPreference 中的纯/编码/加密首选项。它也很容易扩展以支持在线偏好。

https://github.com/passos/SimplePreferences/blob/master/library/src/main/java/com/ioenv/preferences/