13 sie 2025·7 min czytania

Lista kontrolna bezpiecznego przechowywania w Kotlin dla tokenów, kluczy i PII

Lista kontrolna bezpiecznego przechowywania w Kotlinie — jak wybrać między Android Keystore, EncryptedSharedPreferences i szyfrowaniem bazy danych dla tokenów, kluczy i PII.

Lista kontrolna bezpiecznego przechowywania w Kotlin dla tokenów, kluczy i PII

Co próbujesz chronić (prostymi słowami)

Bezpieczne przechowywanie w aplikacji biznesowej oznacza jedno: jeśli ktoś dostanie telefon (lub pliki twojej aplikacji), wciąż nie powinien móc odczytać ani ponownie użyć tego, co zapisałeś. Obejmuje to dane w spoczynku (na dysku) oraz wycieki sekretów przez kopie zapasowe, logi, raporty awarii czy narzędzia debugowania.

Prosty test myślowy: co mógłby zrobić obcy, gdyby otworzył folder ze storage twojej aplikacji? W wielu aplikacjach najcenniejsze nie są zdjęcia czy ustawienia, tylko krótkie ciągi znaków, które odblokowują dostęp.

Na urządzeniu często przechowuje się tokeny sesji (by użytkownicy pozostali zalogowani), tokeny odświeżania, klucze API, klucze szyfrujące, dane osobowe (PII) jak imiona i e-maile oraz cachowane rekordy biznesowe używane offline (zamówienia, bilety, notatki klientów).

Oto typowe rzeczy, które idą źle:

  • Zgubione lub skradzione urządzenie jest analizowane, a tokeny są skopiowane, by podszyć się pod użytkownika.
  • Malware lub „pomocnicza” aplikacja odczytuje lokalne pliki na zrootowanym urządzeniu lub przez triki z dostępnością.
  • Automatyczne kopie zapasowe przenoszą dane twojej aplikacji tam, gdzie nie planowałeś.
  • Buildy debugowe logują tokeny, zapisują je w raportach awarii lub wyłączają kontrole bezpieczeństwa.

Dlatego „po prostu zapisz to w SharedPreferences” nie jest okej dla czegokolwiek, co daje dostęp (tokeny) lub może zaszkodzić użytkownikom i firmie (PII). Zwykłe SharedPreferences to jak zapisanie sekretu na karteczce w aplikacji: wygodne, ale łatwe do odczytania, gdy ktoś ma okazję.

Najbardziej przydatny punkt startowy to nazwać każdy przechowywany element i zadać dwa pytania: czy to coś odblokowuje? i czy byłoby problemem, gdyby to się upubliczniło? Reszta (Keystore, zaszyfrowane preferencje, zaszyfrowana baza) wynika z odpowiedzi.

Sklasyfikuj dane: tokeny, klucze i PII

Bezpieczne przechowywanie staje się prostsze, gdy przestaniesz traktować wszystkie „wrażliwe dane” tak samo. Zacznij od wypisania, co aplikacja zapisuje i co by się stało, gdyby to wyciekło.

Tokeny to nie to samo co hasła. Access tokeny i refresh tokeny mają być przechowywane, aby użytkownik pozostał zalogowany, ale to wciąż wysokowartościowe sekrety. Haseł nie powinno się przechowywać w ogóle. Jeśli potrzebujesz logowania, zapisuj tylko to, co konieczne do utrzymania sesji (zwykle tokeny) i polegaj na serwerze przy weryfikacji hasła.

Klucze to inna kategoria. Klucze API, klucze podpisujące i klucze szyfrujące mogą odblokować całe systemy, nie tylko jedno konto użytkownika. Jeśli ktoś je wyciągnie z urządzenia, może zautomatyzować nadużycia na dużą skalę. Dobra zasada: jeśli wartość może być użyta poza aplikacją do podszywania się pod aplikację lub odszyfrowania danych, traktuj ją jako większe ryzyko niż token użytkownika.

PII to wszystko, co może zidentyfikować osobę: email, telefon, adres, notatki klientów, dokumenty tożsamości, dane zdrowotne. Nawet pola, które wydają się niegroźne, stają się wrażliwe, gdy się je połączy.

Szybki system etykiet, który działa w praktyce:

  • Sekrety sesji: access token, refresh token, cookie sesji
  • Sekrety aplikacji: klucze API, klucze podpisywania, klucze szyfrujące (unikaj umieszczania ich na urządzeniach, jeśli to możliwe)
  • Dane użytkownika (PII): dane profilu, identyfikatory, dokumenty, dane medyczne lub finansowe
  • ID urządzenia i analityki: advertising ID, device ID, install ID (wciąż wrażliwe w wielu politykach)

Android Keystore: kiedy go używać

Android Keystore jest najlepszy, gdy musisz chronić sekrety, które nigdy nie powinny opuścić urządzenia w postaci jawnej. To sejf dla kluczy kryptograficznych, nie baza danych dla twoich danych.

Do czego się nadaje: generowanie i przechowywanie kluczy używanych do szyfrowania, odszyfrowywania, podpisywania lub weryfikowania. Zwykle szyfrujesz token lub dane offline gdzie indziej, a to klucz z Keystore je odblokowuje.

Klucze osadzone w sprzęcie: co to naprawdę znaczy

Na wielu urządzeniach klucze Keystore mogą być sprzętowo wspierane. To znaczy, że operacje na kluczu wykonują się w zabezpieczonym środowisku i materiał klucza nie da się wyekstrahować. Zmniejsza to ryzyko przy malware, które może czytać pliki aplikacji.

Hardware-backed nie jest gwarantowane na każdym urządzeniu, a zachowanie zależy od modelu i wersji Androida. Projektuj z myślą, że operacje na kluczu mogą zawodzić.

Bramki uwierzytelniania użytkownika

Keystore może wymagać obecności użytkownika przed użyciem klucza. Dzięki temu powiążesz dostęp z biometrią lub danymi uwierzytelniającymi urządzenia. Na przykład możesz zaszyfrować token eksportu i odszyfrować go dopiero po potwierdzeniu odcisku palca lub PIN.

Keystore dobrze sprawdza się, gdy chcesz klucza nie-do-wyeksportowania, chcesz zatwierdzeń biometrycznych lub urządzeniowych dla wrażliwych działań oraz gdy chcesz sekretów przypisanych do urządzenia, które nie powinny synchronizować się ani podróżować z kopią zapasową.

Planuj pułapki: klucze mogą zostać unieważnione po zmianach blokady ekranu, zmianach biometrii lub zdarzeniach bezpieczeństwa. Spodziewaj się błędów i zaimplementuj czysty plan awaryjny: wykrywaj nieważne klucze, wycieraj zaszyfrowane obiekty i pros użytkownika o ponowne logowanie.

EncryptedSharedPreferences: kiedy wystarczy

EncryptedSharedPreferences to dobry domyślny wybór dla niewielkiego zestawu sekretów w formie klucz–wartość. To „SharedPreferences, ale zaszyfrowane”, więc nikt nie może po prostu otworzyć pliku i odczytać wartości.

Pod spodem używa klucza głównego (master key) do szyfrowania i odszyfrowywania wartości. Ten klucz główny jest chroniony przez Android Keystore, więc aplikacja nie przechowuje surowego klucza szyfrowania w postaci jawnej.

Zazwyczaj wystarcza dla kilku małych elementów, które czytasz często, jak access i refresh tokeny, identyfikatory sesji, ID urządzenia, flagi środowiska czy drobne stany (np. czas ostatniej synchronizacji). Nadaje się też do małych fragmentów danych użytkownika, jeśli naprawdę musisz je przechowywać, ale nie powinno się z niego robić śmietnika dla PII.

Nie nadaje się do czegokolwiek dużego lub złożonego. Jeśli potrzebujesz list offline, wyszukiwania czy zapytań po polach (klienci, bilety, zamówienia), EncryptedSharedPreferences staje się powolne i nieporęczne. Wtedy chcesz zaszyfrowanej bazy danych.

Prosta zasada: jeśli potrafisz wypisać każdy przechowywany klucz na jednym ekranie, EncryptedSharedPreferences prawdopodobnie wystarczy. Jeśli potrzebujesz wierszy i zapytań, przejdź dalej.

Szyfrowanie bazy danych: kiedy jest potrzebne

Przetestuj scenariusz „zły dzień”
Zweryfikuj przechowywanie tokenów, wycieranie przy logout i odzyskiwanie po błędach kluczy w małym proof-of-concept.
Rozpocznij POC

Szyfrowanie bazy danych ma znaczenie, gdy przechowujesz więcej niż drobne ustawienie lub pojedynczy token. Jeśli aplikacja trzyma lokalnie dane biznesowe, załóż, że można je wyciągnąć z utraconego telefonu, chyba że je zabezpieczysz.

Baza danych ma sens, gdy potrzebujesz dostępu offline do rekordów, lokalnego cache dla wydajności, historii/audytu lub dłuższych notatek i załączników.

Dwa powszechne podejścia do szyfrowania

Pełne szyfrowanie bazy (często w stylu SQLCipher) szyfruje cały plik w spoczynku. Aplikacja otwiera go za pomocą klucza. Łatwo to rozumieć, bo nie musisz pamiętać, które kolumny są chronione.

Szyfrowanie na poziomie aplikacji (pól) szyfruje tylko określone pola przed zapisaniem, a odszyfrowuje je po odczycie. Może to działać, jeśli większość rekordów nie jest wrażliwa, albo jeśli chcesz zachować istniejącą strukturę bazy bez zmiany formatu pliku.

Kompromisy: poufność vs. wyszukiwanie i sortowanie

Pełne szyfrowanie ukrywa wszystko na dysku, ale gdy baza jest odblokowana, aplikacja może normalnie wykonywać zapytania.

Szyfrowanie pól chroni wybrane kolumny, ale tracisz proste wyszukiwanie i sortowanie po zaszyfrowanych wartościach. Sortowanie po zaszyfrowanym nazwisku nie działa przewidywalnie, a wyszukiwanie staje się albo „szukaj po odszyfrowaniu” (wolne), albo „przechowuj dodatkowe indeksy” (większa złożoność i potencjalne wycieki).

Podstawy zarządzania kluczami

Klucz bazy nie powinien być nigdy wbudowany ani wysyłany z aplikacją. Typowy wzorzec to wygenerowanie losowego klucza bazy danych (DEK), a następnie przechowywanie go opakowanego (zaszyfrowanego) przy użyciu klucza z Android Keystore. Przy wylogowaniu możesz usunąć opakowany klucz i traktować lokalną bazę jako jednorazową, albo go zachować, jeśli aplikacja musi działać offline między sesjami.

Jak wybrać: praktyczne porównanie

Zamień modele danych w prawdziwe aplikacje
Modeluj dane w PostgreSQL wizualnie, a następnie generuj działające API i klienty.
Zacznij budować

Nie wybierasz „najbezpieczniejszej” opcji w ogólności. Wybierasz najbezpieczniejszą opcję, która pasuje do sposobu użycia danych w twojej aplikacji.

Pytania, które naprawdę naprowadzają na właściwy wybór:

  • Jak często dane są czytane (przy każdym uruchomieniu czy rzadko)?
  • Ile danych to jest (kilka bajtów czy tysiące rekordów)?
  • Co się stanie, jeśli to wycieknie (drobna niedogodność, koszt, obowiązek prawny zgłoszenia)?
  • Czy potrzebujesz dostępu offline, wyszukiwania lub sortowania?
  • Czy masz wymagania zgodności (retencja, audyt, zasady szyfrowania)?

Praktyczne mapowanie:

  • Tokeny (OAuth access i refresh tokeny) zwykle nadają się do EncryptedSharedPreferences, bo są małe i często odczytywane.
  • Material kluczy powinien żyć w Android Keystore, gdy to możliwe, by zmniejszyć szansę na jego skopiowanie z urządzenia.
  • PII i offline’owe dane biznesowe zwykle potrzebują szyfrowania bazy danych, gdy przechowujesz więcej niż kilka pól lub potrzebujesz list i filtrowania offline.

Mieszane dane są normalne w aplikacjach biznesowych. Praktyczny wzorzec to wygenerowanie losowego klucza szyfrującego dane (DEK) dla bazy lub pliku, przechowywanie tylko opakowanego DEK używając klucza z Keystore i rotowanie go w razie potrzeby.

Jeśli nie jesteś pewien, wybierz prostszą bezpieczną drogę: przechowuj mniej. Unikaj offline’owego PII, chyba że naprawdę go potrzebujesz, i trzymaj klucze w Keystore.

Krok po kroku: implementacja bezpiecznego przechowywania w aplikacji Kotlin

Zacznij od spisania każdej wartości, którą planujesz zarejestrować na urządzeniu i dokładnego powodu, dla którego musi tam być. To najszybszy sposób, żeby uniknąć „na wszelki wypadek” zapisywania.

Zanim zaczniesz pisać kod, ustal reguły: jak długo każdy element powinien żyć, kiedy powinien być wymieniany i co oznacza „logout”. Access token może wygasać po 15 minutach, refresh token dłużej, a offline’owe PII może wymagać twardej reguły „usuń po 30 dniach”.

Implementacja, która pozostaje utrzymywalna:

  • Stwórz jeden wrapper „SecureStorage”, żeby reszta aplikacji nigdy bezpośrednio nie dotykała SharedPreferences, Keystore czy bazy.
  • Umieść każdy element we właściwym miejscu: tokeny w EncryptedSharedPreferences, klucze szyfrujące chronione przez Android Keystore, a większe zestawy offline w zaszyfrowanej bazie danych.
  • Świadomie obsługuj porażki. Jeśli bezpieczne przechowywanie zawiedzie, zamykaj dostęp. Nie cichaczem nie wracaj do przechowywania jawnego.
  • Dodaj diagnostykę bez wycieków: loguj typy zdarzeń i kody błędów, nigdy tokenów, kluczy ani danych użytkownika.
  • Podłącz ścieżki usuwania: logout, usunięcie konta i „wyczyść dane aplikacji” powinny przechodzić przez tę samą rutynę wycierania.

Następnie testuj nudne przypadki, które łamią bezpieczne przechowywanie w produkcji: przywracanie z kopii zapasowej, aktualizacja z poprzedniej wersji, zmiana ustawień blokady ekranu, migracja na nowe urządzenie. Upewnij się, że użytkownicy nie utkną w pętli, gdzie dane nie dają się odszyfrować, a aplikacja ciągle próbuje.

Na koniec spisz decyzje na jednej stronie, którą cały zespół może śledzić: co jest przechowywane, gdzie, okresy retencji i co robić, gdy odszyfrowanie zawiedzie.

Najczęstsze błędy, które łamią bezpieczne przechowywanie

Wprowadź przepływy bezpieczeństwa do logiki
Twórz reguły biznesowe za pomocą przeciągnij-i-upuść zamiast ręcznie obsługiwać każde skrajne zachowanie.
Buduj logikę

Większość porażek to nie wybór złej biblioteki. Dzieje się tak, gdy jedna mała skrótowa ścieżka potajemnie kopiuje sekrety tam, gdzie nie zamierzałeś.

Największy czerwony alarm to refresh token (lub długotrwały token sesji) zapisany w jawnej postaci gdziekolwiek: SharedPreferences, plik, „tymczasowy” cache lub kolumna lokalnej bazy. Jeśli ktoś dostanie kopię zapasową, zrzut zrootowanego urządzenia lub artefakty debugowe, ten token może przeżyć hasło.

Sekrety również wyciekają przez widoczność, a nie tylko przez przechowywanie. Logowanie pełnych nagłówków żądań, drukowanie tokenów podczas debugowania lub dołączanie „pomocnego” kontekstu do raportów awarii i analityki może ujawnić poświadczenia poza urządzeniem. Traktuj logi jako publiczne.

Obsługa kluczy to kolejna luka. Używanie jednego klucza do wszystkiego zwiększa promień szkód. Brak rotacji kluczy oznacza, że stare kompromisy pozostają ważne. Uwzględnij plan wersjonowania kluczy, rotacji i co się dzieje z dawnymi zaszyfrowanymi danymi.

Nie zapomnij o ścieżkach „poza sejfem”

Szyfrowanie nie zatrzyma kopii zapasowych chmurowych przed kopiowaniem lokalnych danych aplikacji. Nie zatrzyma zrzutów ekranu ani nagrań ekranu przechwytujących PII. Nie zatrzyma buildów debugowych z osłabionymi ustawieniami, ani funkcji eksportu (CSV/udostępnianie) przed wyciekiem wrażliwych pól. Schowek także może ujawnić kody jednorazowe lub numery kont.

Poza tym szyfrowanie nie naprawia autoryzacji. Jeśli aplikacja pokazuje PII po wylogowaniu, albo trzyma cache dostępne bez ponownego uwierzytelnienia, to błąd kontroli dostępu. Zamykaj UI, wycieraj wrażliwe cache przy logout i ponownie sprawdzaj uprawnienia przed pokazaniem chronionych danych.

Szczegóły operacyjne: cykl życia, logout i przypadki brzegowe

Bezpieczne przechowywanie to nie tylko miejsce, gdzie trzymasz sekrety. To też to, jak się zachowują w czasie: gdy aplikacja usypia, gdy użytkownik się wylogowuje i gdy urządzenie jest zablokowane.

Dla tokenów zaplanuj cały cykl życia. Access tokeny powinny być krótkotrwałe. Refresh tokeny traktuj jak hasła. Jeśli token wygasł, odśwież go cicho. Jeśli odświeżanie zawiedzie (unieważniony, zmienione hasło, urządzenie usunięte), przestań pętlować i wymuś czyste zalogowanie. Wspieraj także unieważnianie po stronie serwera. Lokalne przechowywanie nie uratuje, jeśli nigdy nie unieważnisz skradzionych poświadczeń.

Używaj biometrii do ponownego uwierzytelnienia, ale nie do wszystkiego. Wywołuj ją, gdy akcja naprawdę niesie ryzyko (przeglądanie PII, eksport danych, zmiana szczegółów wypłat, pokazanie jednorazowego klucza). Nie pytaj przy każdym otwarciu aplikacji.

Przy wylogowaniu bądź rygorystyczny i przewidywalny:

  • Najpierw wyczyść kopie w pamięci (tokeny w singletonach, interceptorach, ViewModelach).
  • Wytrzyj przechowywane tokeny i stan sesji (w tym refresh tokeny).
  • Usuń lub unieważnij lokalne klucze szyfrujące, jeśli twój projekt to wspiera.
  • Usuń offline’owe PII i cache odpowiedzi API.
  • Wyłącz zadania tła, które mogłyby ponownie pobrać dane.

Przypadki brzegowe mają znaczenie w aplikacjach biznesowych: wiele kont na jednym urządzeniu, profile pracy, backup/restore, transfer urządzenie→urządzenie i częściowe wylogowania (zmiana firmy/przestrzeni roboczej zamiast pełnego wylogowania). Testuj force stop, aktualizacje OS i zmiany zegara, bo dryft czasu może popsuć logikę wygasania.

Wykrywanie manipulacji to kompromis. Proste kontrole (buildy debugowalne, flagi emulatora, proste sygnały root, verdicty Play Integrity) mogą zmniejszyć przypadkowe nadużycia, ale zdeterminowany atakujący może je obejść. Traktuj sygnały manipulacji jako dane ryzyka: ogranicz dostęp offline, wymagaj re-autoryzacji i zanotuj zdarzenie.

Szybka checklista przed wypuszczeniem

Wysyłaj logowanie i sesje szybciej
Skorzystaj z gotowego uwierzytelniania, aby skupić się na zasadach bezpiecznego przechowywania i zachowaniu aplikacji.
Dodaj uwierzytelnianie

Użyj tego przed wydaniem. Celuje w miejsca, gdzie bezpieczne przechowywanie zawodzi w prawdziwych aplikacjach biznesowych.

  • Załóż, że urządzenie może być wrogie. Jeśli atakujący ma zrootowane urządzenie lub pełny obraz, czy może odczytać tokeny, klucze lub PII z plików aplikacji, preferencji, logów lub zrzutów ekranu? Jeśli odpowiedź brzmi „może”, przenieś sekrety pod ochronę Keystore i trzymaj payload zaszyfrowany.
  • Sprawdź kopie zapasowe i transfery urządzeń. Trzymaj wrażliwe pliki poza Android Auto Backup, chmurowymi kopiiami i transferami urządzeń. Jeśli utrata klucza podczas przywracania zepsuje odszyfrowanie, zaplanuj flow odzyskiwania (re-auth i ponowne pobranie danych zamiast prób odszyfrowania).
  • Szukaj przypadkowego textu jawnego na dysku. Szukaj plików tymczasowych, cache HTTP, raportów awarii, zdarzeń analitycznych i cache obrazów, które mogą zawierać PII lub tokeny. Sprawdź logowanie debugowe i dumpy JSON.
  • Wygasaj i rotuj. Access tokeny krótkotrwałe, refresh tokeny chronione, sesje po stronie serwera odwoływalne. Zdefiniuj rotację kluczy i co aplikacja robi, gdy token zostanie odrzucony (wyczyść, re-auth, spróbuj ponownie raz).
  • Zachowanie przy reinstalacji i zmianie urządzenia. Testuj odinstalowanie i ponowną instalację, a następnie otwarcie offline. Jeśli klucze Keystore znikają, aplikacja powinna bezpiecznie zawieść (wyczyścić zaszyfrowane dane, pokazać logowanie, unikać częściowych odczytów które psują stan).

Szybka walidacja to test „zły dzień”: użytkownik wylogowuje się, zmienia hasło, przywraca kopię zapasową na nowy telefon i otwiera aplikację na samolocie. Wynik powinien być przewidywalny: albo dane odszyfrowują się dla właściwego użytkownika, albo zostają wyczyszczone i pobrane ponownie po zalogowaniu.

Przykładowy scenariusz: aplikacja biznesowa przechowująca PII offline

Zbuduj aplikację zgodnie z checklistą
Buduj aplikację biznesową z backendem, webem i natywnymi klientami bez zaczynania od zera.
Wypróbuj AppMaster

Wyobraź sobie aplikację handlową do pracy w terenie w miejscach ze słabym zasięgiem. Przedstawiciele logują się rano, przeglądają przypisanych klientów offline, dodają notatki z wizyt i synchronizują później. To moment, gdy lista kontrolna przestaje być teorią i zaczyna zapobiegać rzeczywistym wyciekom.

Praktyczny podział:

  • Access token: krótkożyjący, przechowywany w EncryptedSharedPreferences.
  • Refresh token: chroniony mocniej i dostęp do niego bramkowany przez Android Keystore.
  • PII klientów (imiona, telefony, adresy): zapisane w zaszyfrowanej lokalnej bazie danych.
  • Notatki offline i załączniki: w zaszyfrowanej bazie danych, z dodatkową ostrożnością przy eksportach i udostępnianiu.

Teraz dodaj dwie funkcje i ryzyko się zmienia.

Jeśli dodasz „zapamiętaj mnie”, refresh token staje się głównymi drzwiami do konta. Traktuj go jak hasło. W zależności od użytkowników możesz wymagać odblokowania urządzenia (PIN/wzór/biometria) przed jego odszyfrowaniem.

Jeśli dodasz tryb offline, przestajesz chronić tylko sesję. Chronisz pełną listę klientów, która sama w sobie jest wartościowa. To zwykle pcha w stronę szyfrowanej bazy danych plus jasnych reguł logout: wyczyść lokalne PII, zachowaj tylko to, co potrzebne do następnego logowania, i anuluj synchronizację w tle.

Testuj na prawdziwych urządzeniach, nie tylko na emulatorach. Przynajmniej weryfikuj zachowanie blokady/odblokowania, reinstalacji, backup/restore i separacji profili pracy/użytkowników.

Następne kroki: zmień to w powtarzalny nawyk zespołu

Bezpieczne przechowywanie działa tylko wtedy, gdy stanie się nawykiem. Napisz krótką politykę przechowywania, której zespół będzie przestrzegać: co gdzie idzie (Keystore, EncryptedSharedPreferences, zaszyfrowana baza), co nigdy nie jest przechowywane i co trzeba wyczyścić przy logout.

Włącz to do codziennej pracy: definition of done, przegląd kodu i checklisty przed wydaniem.

Lekka lista kontrolna dla recenzenta:

  • Każdy przechowywany element jest oznaczony (token, materiał klucza lub PII).
  • Wybór miejsca przechowywania jest uzasadniony w komentarzach w kodzie.
  • Wylogowanie i zmiana konta usuwają właściwe dane (i tylko je).
  • Błędy i logi nigdy nie drukują sekretów ani pełnego PII.
  • Ktoś odpowiada za politykę i ją aktualizuje.

Jeśli twój zespół używa AppMaster (appmaster.io) do budowy aplikacji biznesowych i eksportuje źródła Kotlin dla klienta Android, trzymaj ten sam wzorzec SecureStorage, aby kod generowany i customowy stosował spójną politykę.

Zacznij od małego proof-of-concept

Zbuduj mały POC, który przechowuje jeden token auth i jedną rekord PII (np. numer telefonu klienta potrzebny offline). Następnie testuj świeżą instalację, aktualizację, wylogowanie, zmiany blokady ekranu i wyczyszczenie danych aplikacji. Rozszerzaj tylko wtedy, gdy zachowanie wycierania jest prawidłowe i powtarzalne.

FAQ

Jaki jest najprostszy „bezpieczny domyślny” sposób przechowywania tokenów i danych użytkownika w aplikacji Kotlin?

Zacznij od spisania dokładnie tego, co przechowujesz i dlaczego. Małe tajne dane sesji, takie jak access i refresh tokeny, włóż do EncryptedSharedPreferences, material kryptograficzny trzymaj w Android Keystore, a do offline’owych rekordów biznesowych i PII używaj zaszyfrowanej bazy danych, gdy masz więcej niż kilka pól lub potrzebujesz zapytań.

Dlaczego zwykłe SharedPreferences nie nadaje się do tokenów lub PII?

Zwykłe SharedPreferences zapisuje wartości w pliku, który często można odczytać z kopii zapasowych, przez dostęp do plików na zrootowanym urządzeniu lub z artefaktów debugowych. Jeśli wartość to token lub PII, traktowanie jej jak zwykłe ustawienie ułatwia skopiowanie i ponowne użycie poza aplikacją.

Kiedy powinienem użyć Android Keystore zamiast samodzielnego szyfrowania pliku?

Użyj Android Keystore do generowania i przechowywania kluczy kryptograficznych, które nie powinny być wyeksportowane. Zwykle używasz tych kluczy do zaszyfrowania innych danych (tokenów, kluczy bazy danych, plików) i możesz wymagać uwierzytelnienia użytkownika (biometria lub dane urządzenia) przed użyciem klucza.

Czego właściwie chroni mnie „hardware-backed” Keystore?

Oznacza to, że operacje na kluczu mogą być wykonywane w sprzętowym środowisku chronionym, więc materiał klucza trudniej wyekstrahować, nawet jeśli atakujący ma dostęp do plików aplikacji. Nie zakładaj jednak, że jest dostępne na każdym urządzeniu ani że zawsze działa identycznie; projektuj obsługę błędów i scenariusze odzyskiwania.

Czy EncryptedSharedPreferences wystarczy dla większości aplikacji?

Zwykle wystarcza dla niewielkiego zestawu sekretów w formie klucz–wartość, jak access/refresh tokeny, identyfikatory sesji czy drobne stany. Nie nadaje się do dużych struktur danych ani offline’owych rekordów, które wymagają wyszukiwania i filtrowania — wtedy lepsza jest zaszyfrowana baza danych.

Kiedy potrzebuję szyfrowania bazy danych zamiast zaszyfrowanych preferencji?

Wybierz zaszyfrowaną bazę gdy przechowujesz offline’owe dane biznesowe lub PII na większą skalę, potrzebujesz zapytań/wyszukiwania/sortowania albo historii do użytku offline. Chroni przed tym, że zgubiony telefon ujawni listy klientów lub notatki, pozostawiając jednocześnie możliwość pracy offline przy jasnej strategii klucza.

Czy lepiej szyfrować całą bazę czy tylko konkretne pola?

Pełne szyfrowanie bazy chroni cały plik w spoczynku i jest łatwiejsze do przemyślenia, bo nie musisz śledzić, które kolumny są wrażliwe. Szyfrowanie pól może działać dla kilku kolumn, ale utrudnia wyszukiwanie i sortowanie oraz łatwo przez przypadek ujawnić dane przez indeksy lub pola pochodne.

Jaki jest praktyczny sposób zarządzania kluczami bez hardkodowania czegokolwiek?

Wygeneruj losowy klucz bazy danych, a następnie przechowuj go tylko w postaci opakowanej (zaszyfrowanej) przy użyciu klucza z Android Keystore. Nigdy nie umieszczaj kluczy na stałe w aplikacji i zaplanuj, co się dzieje przy wylogowaniu lub unieważnieniu klucza (często: usuń opakowany klucz i traktuj lokalne dane jako jednorazowe).

Co powinna robić aplikacja, gdy klucze Keystore zostaną unieważnione i deszyfrowanie zawiedzie?

Klucze mogą zostać unieważnione przez zmianę blokady ekranu, zmianę biometrii, zdarzenia bezpieczeństwa systemu albo scenariusze przywracania/migracji. Obsłuż to jawnie: wykrywaj błędy deszyfrowania, bezpiecznie wycieraj zaszyfrowane bazy/obiekty i pros użytkownika o ponowne zalogowanie zamiast pętli lub wracania do przechowywania w postaci jawnej.

Jakie są najczęstsze błędy, które nadal wyciekają sekrety, nawet jeśli używam szyfrowania?

Większość wycieków ma miejsce „poza sejfem”: logi, raporty awarii, zdarzenia analityczne, wydruki debugowe, cache HTTP, zrzuty ekranu, schowek i ścieżki backupu/restore. Traktuj logi jak publiczne, nigdy nie zapisuj tokenów ani pełnego PII, wyłącz przypadkowe funkcje eksportu i spraw, by wylogowanie czyściło zarówno dane na dysku, jak i kopie w pamięci.

Łatwy do uruchomienia
Stworzyć coś niesamowitego

Eksperymentuj z AppMaster z darmowym planem.
Kiedy będziesz gotowy, możesz wybrać odpowiednią subskrypcję.

Rozpocznij