Intereting Posts
IllegalStateException с использованием библиотеки эффектов Ripple на устройствах Android M Как интегрировать шлюз оплаты ccavenue в моем приложении Android Пользовательский адаптер не отображает данные в ListView Использовать Chrome как средство рендеринга для веб-просмотра Android GestureDetector.SimpleOnGestureListener и GestureDetectorCompat не работают. Что случилось с моим кодом? Несколько аннотаций, найденных в этой строке: Модель памяти Dalvik такая же, как Java? Драйвер ADB для HTC Incredible Невозможно заставить Robotium работать в Android Studio CursorLoader – Две таблицы соединяют запрос? Как проверить домашнюю кнопку на панели действий с эспрессо? Undefined ссылка на 'typeinfo для тестирования :: Test' с Google Test на Android NDK Могу ли я изменить сертификат подписки на Android, сохраняя закрытый ключ Как поворачивать представления при изменении ориентации без повторной компоновки? Панель навигации переполненных элементов переполнения в анимации перехода

Общие предпочтения? Javax.crypto.BadPaddingException: блок pad поврежден только на некоторых устройствах

Я получаю некоторые ошибки с консоли google play, где некоторые пользователи (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) 

Приложение прекрасно работает на остальных устройствах (даже в некоторых связях 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); 

Если мы введем getInt из ObsucredSharedPreferences:

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

Итак, вместо получения нулевого значения из getString я получаю значение типа «ERKJFER89er» (я никогда не пишу этого значения в настройках, иначе он должен упасть на каждый телефон), поэтому, когда он пытается decryp значение, которое он ожидает, значение int и Он бросает javax.crypto.BadPaddingException: pad block corrupted Я не знаю, как обходить это или как это исправить, любая идея будет оценена

Код расшифровки:

 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); } } 

1 пользователь сказал, что сброс настроек не решает проблему, но выполняет сброс с заводских настроек с помощью кеша очистки и очистки данных.

Полный стек для пикселя google

 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) 

Solutions Collecting From Web of "Общие предпочтения? Javax.crypto.BadPaddingException: блок pad поврежден только на некоторых устройствах"

Я не могу сказать, что это гораздо больше, чем предположение, но я попробую.

Я видел, что другие используют по умолчанию значение null для SharedPreferences, но мне нравится использовать фактическое значение по умолчанию в виде строки. Исходя из этого, у меня было бы нечто подобное (предполагая, что метод encryt() используется с decrypt() ).

 @Override public int getInt(String key, int defValue) { final String v = delegate.getString(key, encrypt(String.valueOf(defValue)); return Integer.parseInt(decrypt(v)); } 

Если это не устраняет проблему, попробуйте ли вы использовать значение, отличное от нуля, как значение по умолчанию. Как насчет пустой строки? Некоторые символы Unicode, которые вы уверены, не могут быть реальным зашифрованным сохраненным значением? EDIT: Это вряд ли проблема. После просмотра документации параметр defValue для getString() является Nullable, что означает, что метод предназначен для обработки нулевого параметра изящно.

Надеюсь, что это помогает и удачи.

EDIT: Я пытался дублировать вашу проблему, но не мог. Я попробовал эмулированное устройство Nexus 5 и реальное устройство Nexus 5, используя API 23. getString() всегда возвращал null. На этом я использовал код. Я предполагаю, что это более или менее тот же код, на котором основывается ваш код.

Оставляя неиспользованные методы …

 public class ObscuredSharedPreferences implements SharedPreferences { private static final String TAG = "ObscuredSp"; protected static final String UTF8 = "utf-8"; private static final char[] SEKRIT = "abc".toCharArray() ; // INSERT A RANDOM PASSWORD HERE. protected SharedPreferences delegate; protected Context context; public ObscuredSharedPreferences(Context context, SharedPreferences delegate) { this.delegate = delegate; this.context = context; } @Override public int getInt(String key, int defValue) { final String v = delegate.getString(key, null); Log.d(TAG, "got int " + v); return v!=null ? Integer.parseInt(decrypt(v)) : defValue; } 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(Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID).getBytes(UTF8), 20)); return new String(pbeCipher.doFinal(bytes),UTF8); } catch( Exception e) { throw new RuntimeException(e); } } } 

В onCreate()

 private static final String MY_PREFS_FILE_NAME = "MyFile"; private static final String KEY_SP_MUSIC_VOLUME = "KeySpMusicVol"; final SharedPreferences prefs = new ObscuredSharedPreferences( this, this.getSharedPreferences(MY_PREFS_FILE_NAME, Context.MODE_PRIVATE)); int musicVolume; musicVolume = prefs.getInt(KEY_SP_MUSIC_VOLUME, 10); Log.d(TAG, "volume = " + musicVolume); 

Вы могли бы попытаться упростить свой код примерно так. Если это работает, а ваше – нет, это просто вопрос добавления и удаления кода, пока вы не определите, что вызывает проблему. (Я знаю, что это не обязательно так просто, как это звучит).

Другой вопрос, о чем нужно думать. Попробовали ли вы оба конфигурации отладки и выпуска? Вы удаляете приложение каждый раз, чтобы убедиться, что это действительно первый раз, когда приложение запущено? Является ли объем единственным преимуществом, с которым это происходит?

Я вернулся и перечитал ваш вопрос, и теперь я замечаю, что вы пишете проблемы, о которых сообщает Google Play. Это делает большой вопрос, можете ли вы дублировать это самостоятельно, чтобы вы могли попробовать разные вещи, чтобы определить основную причину?

Каков результат возврата decrypt(null) ? Кажется, что ваше приложение прочитало некоторые неверные данные, которые ранее были написаны неправильно.

Также я заметил, что некоторые устройства имеют различное поведение в пути к папке с данными и, вероятно, вызвали эту проблему.

Одним из возможных решений для вашей проблемы является регистрация контекста аварийной ситуации, включая данные, вызвавшие ошибку дешифрования. Вы можете попробовать некоторые услуги онлайн-журнала, такие как Fabric или Logentries. Или вы можете реализовать свой глобальный ExceptionHandler, сохранить данные и отправить данные вам, когда произошел сбой.

IMO, я предпочитаю сохранять все данные в String и анализировать их во время выполнения в случае изменения формата данных.

FYI. Вот моя реализация для предпочтения. Он поддерживает простые / закодированные / зашифрованные предпочтения, сохраненные в SharedPreference. Он также очень прост в распространении, чтобы поддерживать онлайн-настройки.

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