2016-10-25 42 views
7

Dostaję jakieś błędy z Google Play, gdzie niektórzy użytkownicy konsoli (Pixel XL, Nexus 5 i Xperia Z3 +) są corazWspólne preferencje? javax.crypto.BadPaddingException: blok konsola uszkodzony tylko w niektórych urządzeniach

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) 

Aplikacja działa dobrze w pozostałych urządzeniach (nawet w niektórych Nexus 5 działa dobrze)

Problem pojawia się, gdy po raz pierwszy użytkownik otwiera aplikację, Próbuje załadować głośność muzyki z udostępnionych preferencji. Ponieważ nigdy nie weszli w menu opcji, aby zmienić wartość domyślną, powinien on uzyskać wartość domyślną:

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

Jeśli wchodzimy w getInt z ObsucredSharedPreferences:

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

Więc zamiast się wartość null od getString Otrzymuję wartość taką jak "ERKJFER89er" (nigdy nie piszę tej wartości w preferencjach, w przeciwnym razie powinna ona rozbić się na każdym telefonie), więc kiedy spróbuje odszyfrować wartość, to oczekuje wartości int i rzuca javax.crypto.BadPaddingException: pad block corrupted I don ' t know how to obejść lub jak to naprawić, każdy pomysł będzie apreciate

Kodeks Deszyfruj:

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 użytkownik powiedzieć, że zrobić reset fabryczny nie rozwiązuje problemu, ale czy zresetować fabryki z wytrzeć cache i wytrzeć dane rozwiązać go

Pełna stosu dla strace google pixel

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) 
+1

Napotkałem ten sam problem wcześniej. Zmiana trybu szyfrowania rozwiązała problem. –

+0

ja też mam ten sam problem, czy jest jakaś inna opcja niż zmiana trybu szyfrowania? –

+0

jeden z moich kolegów również miał ten sam problem – M14

Odpowiedz

1

Jaki jest wynik zwrotu decrypt(null)? Wygląda na to, że Twoja aplikacja odczytała niepoprawne dane, które zostały wcześniej napisane niepoprawnie.

Zauważyłem również, że niektóre urządzenia mają inne zachowanie na ścieżce folderu danych i prawdopodobnie spowodowały ten problem.

Jednym z możliwych rozwiązań problemu jest zarejestrowanie kontekstu awarii szczegółów, w tym danych, które spowodowały błąd odszyfrowywania. Możesz wypróbować usługę logowania online, taką jak Fabric lub Logentries. Możesz też zaimplementować globalny ExceptionHandler, zapisać dane i przesłać dane do Ciebie, gdy dojdzie do awarii.

IMO, wolę zapisywać wszystkie dane w łańcuchu i analizować je w czasie wykonywania w przypadku zmiany formatu danych.

FYI. Oto moja implementacja preferencji. Obsługuje proste/kodowane/szyfrowane preferencje zapisane w SharedPreference. Bardzo łatwo można również rozszerzyć obsługę preferencji online.

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

+0

Tak, dane są nieprawidłowe, ale problem polega na tym, że aplikacja nie zapisuje danych wcześniej, Ten problem występuje w niektórych urządzeniach PIERWSZY, gdy aplikacja spróbuje odczytać preferencje, zamiast podać wartość domyślną, Daje losowy ciąg, ale ten ciąg nigdy nie został napisany przed – D4rWiNS

+0

Mam szczegółowy opis awarii, mogę go dołączyć – D4rWiNS

+0

Możesz również spróbować wykryć, czy jest to pierwsze wykonanie, a następnie zapisać domyślne ustawienia. To nie jest najlepsza opcja, ale powinna działać. – juanlugm

2

Nie mogę powiedzieć, że to o wiele więcej niż przypuszczeniem ale dam mu szansę.

Widziałem, jak inni używają wartości domyślnej null dla SharedPreferences, ale lubię używać rzeczywistej wartości domyślnej jako ciąg. Na tej podstawie chciałbym mieć coś podobnego (zakładając, że istnieje metoda , którą można zastosować z decrypt()).

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

Jeśli to nie rozwiąże problemu, czy próbowałeś użyć wartości innej niż null jako wartości domyślnej. A może pusty ciąg? Niektóre znaki Unicode, które na pewno nie mogą być prawdziwą zaszyfrowaną wartością przechowywaną? EDYCJA: Jest to mało prawdopodobne. Po zapoznaniu się z dokumentacją parametr defValue dla getString() ma wartość Nullable, co oznacza, że ​​metoda jest zaprojektowana tak, aby z wdziękiem obsługiwała parametr zerowy.

Mam nadzieję, że to pomoże i powodzenia.

EDYCJA: Próbowałem zduplikować twój problem, ale nie mogłem. Próbowałem urządzenia emulowanego Nexus 5 i urządzenia rzeczywistego Nexus 5, które używają zawsze interfejsu API 23. getString(). Użyłem kodu opartego na this. Wyobrażam sobie, że jest mniej więcej taki sam, na którym opiera się twój kod.

Pomijając niewykorzystane metod ...

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

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

można spróbować uproszczenie kodu do czegoś takiego. Jeśli to działa, a twoje nie, jest to tylko kwestia dodania kodu, dopóki nie określisz, co powoduje problem. (Wiem, że to niekoniecznie tak łatwe, jak to brzmi).

Inne pytanie, o czym warto pomyśleć. Czy wypróbowane konfiguracje kompilacji debugowania i wydania? Czy odinstalowujesz aplikację za każdym razem, aby upewnić się, że jest to naprawdę pierwsza aplikacja? Czy głośność jest jedyną preferowaną opcją?

Wróciłem i ponownie przeczytałem twoje pytanie. & Zauważyłem, że piszesz, że problemy są zgłaszane przez Google Play. To sprawia, że ​​najważniejsze pytanie, czy możesz powielić to samodzielnie, tak, że możesz wypróbować różne rzeczy, aby określić przyczynę?

+0

Spróbuję zmienić na inną domyślną wartość, jednak problem polega na tym, że zamiast zwraca wartość pustą, zwraca losowy ciąg – D4rWiNS

+0

Większość błędów pochodzi z raportu Google Play lub raportu awarii Firebase, jednak sześć miesięcy temu ten sam błąd był na moim Nexusie 5, próbowałem wielu rzeczy, ale tylko formatowałem z pamięcią podręczną wycierania załatw sobie sprawę – D4rWiNS

+0

Jeśli chcesz podać nazwę aplikacji, postaram się ją pobrać, aby sprawdzić, czy działa ona na moim Nexusie 5. Jakie masz API? – Gary99