Najlepsza praktyka do przechowywania i ochrony prywatnych kluczy API w aplikacjach [zamknięte]


373

Większość twórców aplikacji zintegruje niektóre biblioteki stron trzecich ze swoimi aplikacjami. Jeśli ma to uzyskać dostęp do usługi, takiej jak Dropbox lub YouTube, lub do rejestrowania awarii. Liczba bibliotek i usług stron trzecich jest oszałamiająca. Większość tych bibliotek i usług jest zintegrowana poprzez uwierzytelnianie w usłudze, w większości przypadków odbywa się to za pomocą klucza API. Ze względów bezpieczeństwa usługi zwykle generują klucz publiczny i prywatny, często określany również jako klucz tajny. Niestety, aby połączyć się z usługami, ten klucz prywatny musi zostać użyty do uwierzytelnienia, a zatem prawdopodobnie jest częścią aplikacji. Nie trzeba dodawać, że ma to ogromny problem z bezpieczeństwem. Publiczne i prywatne klucze API można wyodrębnić z APK w ciągu kilku minut i można je łatwo zautomatyzować.

Zakładając, że mam coś podobnego do tego, w jaki sposób mogę chronić tajny klucz:

public class DropboxService  {

    private final static String APP_KEY = "jk433g34hg3";
    private final static String APP_SECRET = "987dwdqwdqw90";
    private final static AccessType ACCESS_TYPE = AccessType.DROPBOX;

    // SOME MORE CODE HERE

}

Jaki jest Twoim zdaniem najlepszy i najbezpieczniejszy sposób przechowywania klucza prywatnego? Zaciemnianie, szyfrowanie, co myślisz?



Miałem sklep w obrazie / png i dostałem klucz przez png jako BufferReader
Sumit

Myślę, że jest to uzasadniony problem i opublikowałem podobny problem na stronie github Firebase Android SDK: github.com/firebase/firebase-android-sdk/issues/1583 . Zobaczmy, czy zostanie to obsłużone.
grebulon

Odpowiedzi:


348
  1. W tej chwili skompilowana aplikacja zawiera ciągi kluczy, ale także stałe nazwy APP_KEY i APP_SECRET. Wydobywanie kluczy z takiego samodokumentującego się kodu jest banalne, na przykład w przypadku standardowego narzędzia Android dx.

  2. Możesz zastosować ProGuard. Pozostawi nietknięte ciągi klawiszy, ale usunie stałe nazwy. W miarę możliwości zmieni także nazwy klas i metod krótkimi, pozbawionymi znaczenia nazwami. Wyodrębnienie kluczy zajmuje trochę więcej czasu, aby dowiedzieć się, który ciąg znaków służy do którego celu.

    Pamiętaj, że konfiguracja ProGuard nie powinna być tak trudna, jak się obawiasz. Na początek wystarczy włączyć ProGuard, jak opisano w project.properties. Jeśli występują jakiekolwiek problemy z bibliotekami stron trzecich, być może będziesz musiał ukryć niektóre ostrzeżenia i / lub zapobiec ich zaciemnieniu, w proguard-project.txt. Na przykład:

    -dontwarn com.dropbox.**
    -keep class com.dropbox.** { *; }

    To podejście oparte na brutalnej sile; możesz sprecyzować taką konfigurację po uruchomieniu przetworzonej aplikacji.

  3. Możesz zaciemnić ciągi ręcznie w kodzie, na przykład przy użyciu kodowania Base64 lub najlepiej za pomocą czegoś bardziej skomplikowanego; może nawet natywny kod. Haker będzie musiał następnie statycznie poddać inżynierii wstecznej kodowanie lub dynamicznie przechwycić dekodowanie w odpowiednim miejscu.

  4. Możesz zastosować komercyjny zaciemniacz, taki jak wyspecjalizowany rodzeństwo DexGuard firmy ProGuard . Może dodatkowo zaszyfrować / zaciemnić ciągi i klasy. Wydobycie kluczy zajmuje jeszcze więcej czasu i wiedzy.

  5. Możliwe, że możesz uruchomić części aplikacji na własnym serwerze. Jeśli możesz zatrzymać klucze, są one bezpieczne.

W końcu musisz dokonać ekonomicznego kompromisu: jak ważne są klucze, ile czasu lub oprogramowania możesz sobie pozwolić, jak wyrafinowani są hakerzy zainteresowani kluczami, ile czasu będą chcieli wydać, ile warte jest opóźnienie przed zhakowaniem kluczy, na jaką skalę hakerzy z powodzeniem rozprowadzą klucze itp. Małe fragmenty informacji, takie jak klucze, są trudniejsze do ochrony niż całe aplikacje. Zasadniczo nic po stronie klienta nie jest nie do złamania, ale z pewnością możesz podnieść poprzeczkę.

(Jestem programistą ProGuard i DexGuard)


2
@EricLafortune nie ma znaczenia, czy ciąg klucza prywatnego jest przechowywany w klasie Java, czy w pliku XML zasobu String?
Alan

1
@EricLafortune Czy można teraz używać systemu Android Keystore do bezpiecznego przechowywania kluczy? ( developer.android.com/training/articles/keystore.html )
David Thomas

1
@DavidThomas: Czy próbowałeś użyć magazynu kluczy. Chcę zaciemnić klucz API napisany w klasie Java. Proszę odpowiedzieć
Sagar Trehan

1
Czy Android KeyStore jest do tego przydatny? ( developer.android.com/training/articles/… )
Weishi Zeng

1
Nie rozumiem # 5. Czy nie ma takich samych problemów, jak problem pierwotny?
pete

80

Kilka pomysłów, moim zdaniem tylko pierwszy daje pewną gwarancję:

  1. Zachowaj swoje sekrety na jakimś serwerze w Internecie, a kiedy zajdzie taka potrzeba, po prostu je złap i użyj. Jeśli użytkownik ma zamiar użyć Dropbox, nic nie powstrzyma Cię przed wysłaniem żądania do Twojej witryny i zdobyciem tajnego klucza.

  2. Umieść swoje sekrety w kodzie jni, dodaj zmienny kod, aby Twoje biblioteki były większe i trudniejsze do dekompilacji. Możesz także podzielić ciąg kluczy na kilka części i przechowywać je w różnych miejscach.

  3. użyj obfuscatora, również wprowadź tajny kod, a później go odblokuj, gdy będzie to konieczne.

  4. Umieść swój tajny klucz jako ostatnie piksele jednego ze swoich obrazów w zasobach. W razie potrzeby przeczytaj go w kodzie. Ukrywanie kodu powinno pomóc ukryć kod, który będzie go czytał.

Jeśli chcesz szybko sprawdzić, jak łatwo można odczytać kod apk, pobierz APKAnalyser:

http://developer.sonymobile.com/knowledge-base/tool-guides/analyse-your-apks-with-apkanalyser/


46
jeśli użytkownik może zdekompilować aplikację, prawdopodobnie może ustalić żądanie wysłane na własny serwer i po prostu wykonać je, aby uzyskać tajność. Nie ma tu srebrnej kuli, ale zrób kilka kroków i założę się, że wszystko będzie dobrze! Jeśli Twoja aplikacja jest bardzo popularna, ale może nie ... Świetne pomysły!
Matt Wolfe

3
tak, numer 1 nie daje gwarancji.
marcinj

42
Bardzo podoba mi się pomysł ukrywania kluczy w obrazach. +1
Igor Čordaš

1
@ MarcinJędrzejewski Czy chcesz wyjaśnić więcej (najlepiej z przykładowym lub wyciętym kodem) na temat czwartego rozwiązania? Dziękuję Ci.
Dr.jacky 16.04.16

2
@ Mr.Hyde nazywa się to steganografią, jest zbyt skomplikowane, aby dać przykładowy kod tutaj, możesz znaleźć przykłady w google. Znalazłem tutaj: dreamincode.net/forums/topic/27950-steganography . Pomysł jest świetny, ale ponieważ kod apk można zdekompilować, psuje to jego piękno.
marcinj 21.04.16

33

Innym podejściem jest przede wszystkim nie mieć tajemnicy na urządzeniu! Zobacz techniki bezpieczeństwa Mobile API (szczególnie część 3).

Korzystając z uświęconej tradycji pośrednictwa, udostępnij tajemnicę między punktem końcowym interfejsu API a usługą uwierzytelniania aplikacji.

Gdy klient chce nawiązać połączenie API , prosi usługę uwierzytelniania aplikacji o jego uwierzytelnienie (przy użyciu silnych technik zdalnej atestacji) i otrzymuje ograniczony czasowo (zwykle JWT ) token podpisany przez klucz tajny.

Token jest wysyłany przy każdym wywołaniu interfejsu API, w którym punkt końcowy może zweryfikować swój podpis przed podjęciem działania na żądanie.

Rzeczywisty sekret nigdy nie jest obecny na urządzeniu; w rzeczywistości aplikacja nigdy nie ma pojęcia, czy jest poprawna, czy nie, blokuje żądania uwierzytelnienia i przekazuje otrzymany token. Jako miła korzyść z pośrednictwa, jeśli kiedykolwiek chcesz zmienić sekret, możesz to zrobić bez konieczności aktualizowania zainstalowanych aplikacji przez użytkowników.

Więc jeśli chcesz chronić swój sekret, nie posiadanie go w aplikacji to całkiem dobry sposób.


5
To powinna być zaakceptowana odpowiedź.
ortonomy

3
Problem występuje nadal, gdy chcesz uzyskać dostęp do usługi uwierzytelniania. Da ci identyfikator klienta i sekret klienta. Gdzie powinniśmy je ocalić?
Ashi

nie rozwiązuje prywatnego API, w którym musisz najpierw uwierzytelnić się w interfejsie API, aby go użyć. skąd masz dane uwierzytelniające dla wszystkich użytkowników aplikacji?
Kibotu

25

Stary niezabezpieczony sposób:

Wykonaj 3 proste kroki, aby zabezpieczyć interfejs API / tajny klucz ( stara odpowiedź )

Możemy użyć Gradle do zabezpieczenia klucza API lub tajnego klucza.

1. gradle.properties (właściwości projektu): Utwórz zmienną za pomocą klucza.

GoolgeAPIKey = "Your API/Secret Key"

2. build.gradle (Module: app): Ustaw zmienną w build.gradle, aby uzyskać do niej dostęp w działaniu lub fragmencie. Dodaj poniższy kod do buildTypes {}.

buildTypes.each {
    it.buildConfigField 'String', 'GoogleSecAPIKEY', GoolgeAPIKey
}

3. Uzyskaj do niego dostęp w Activity / Fragment przez BuildConfig aplikacji:

BuildConfig.GoogleSecAPIKEY

Aktualizacja :

Powyższe rozwiązanie jest przydatne w projekcie open source do zatwierdzenia przez Git. (Podziękowania dla Davida Rawsona i riyaz-ali za komentarz).

Zgodnie z komentarzami Matthew i Pablo Cegarra powyższy sposób nie jest bezpieczny, a Dekompilator pozwoli komuś zobaczyć BuildConfig za pomocą naszych tajnych kluczy.

Rozwiązanie :

Możemy użyć NDK do zabezpieczenia kluczy API. Możemy przechowywać klucze w natywnej klasie C / C ++ i uzyskiwać do nich dostęp w naszych klasach Java.

Śledź tego bloga, aby zabezpieczyć klucze API za pomocą NDK.

Dalsze informacje na temat bezpiecznego przechowywania tokenów w systemie Android


4
przechowywanie klucza w pliku stopni jest bezpieczne?
Google

4
@Google gradle.propertiesnie należy rejestrować w Git, więc jest to sposób na zachowanie tajemnicy poza popełnionym kodem źródłowym, przynajmniej
David Rawson

4
Nie uniemożliwia apkto dołączenia klucza API do wynikowego (zostanie dodany do wygenerowanego BuildConfigpliku), chociaż zdecydowanie jest to dobry pomysł na zarządzanie różnymi kluczami API (na przykład w projekcie open source)
riyaz-ali

5
Użycie dekompilatora Java pozwoli komuś wyświetlić plik BuildConfig i „GoogleSecAPIKEY”
Matthew

3
Twój BuildConfig.javaplik będzie miał klucz w postaci zwykłego tekstu. Nie jest to lepsze niż to, co już robi PO.
lodowiec

16

Klucz App-Secret powinien pozostać prywatny - ale po wydaniu aplikacji mogą zostać cofnięci przez niektórych facetów.

dla tych facetów to się nie ukryje, zablokuj albo ProGuardkod. Jest to refaktor, a niektóre płatne zaciemnienia wstawiają kilka bitowych operatorów, aby odzyskać jk433g34hg3 ciąg. Możesz przerwać hakowanie o 5-15 minut, jeśli pracujesz 3 dni :)

Najlepszym sposobem jest zachować go takim, jaki jest, imho.

Nawet jeśli przechowujesz po stronie serwera (komputer), klucz można zhakować i wydrukować. Może to trwa najdłużej? W każdym razie jest to kwestia kilku minut lub kilku godzin w najlepszym przypadku.

Normalny użytkownik nie zdekompiluje twojego kodu.


1
Cóż - nie odpowiedź, którą chciałem uzyskać =) ... Myślałem, że możesz osiągnąć świetne bezpieczeństwo :(
Podstawowy koder

przepraszam, że nie jest tak, jak chciałeś genialne, ultra bezpieczne rozwiązanie, ale dla tych, którzy mogą korzystać z kompilatora, dekompilatora nie ma bezpiecznego kodu Java: nawet kod natywny można przeglądać za pomocą przeglądarki hexa i rozpakowywać. Przynajmniej warto spróbować ...

1
Proguard nie zaciemni jednak rzeczywistego klucza ...? Najlepszą rzeczą do zrobienia jest prosta procedura szyfrowania / deszyfrowania, która ukryje zaciemnianie.
Doomsknight

3
jest to „widoczne” procedura deszyfrowania, łatwo jest zrobić odwrotność i masz oryginalny ciąg

14

Jednym z możliwych rozwiązań jest zakodowanie danych w aplikacji i użycie dekodowania w czasie wykonywania (gdy chcesz użyć tych danych). Polecam również użyć progaurd, aby utrudnić odczytanie i zrozumienie zdekompilowanego kodu źródłowego twojej aplikacji. na przykład umieściłem zakodowany klucz w aplikacji, a następnie użyłem metody dekodowania w mojej aplikacji, aby zdekodować moje tajne klucze w czasie wykonywania:

// "the real string is: "mypassword" "; 
//encoded 2 times with an algorithm or you can encode with other algorithms too
public String getClientSecret() {
    return Utils.decode(Utils
            .decode("Ylhsd1lYTnpkMjl5WkE9PQ=="));
}

Zdekompilowany kod źródłowy zaawansowanej aplikacji jest następujący:

 public String c()
 {
    return com.myrpoject.mypackage.g.h.a(com.myrpoject.mypackage.g.h.a("Ylhsd1lYTnpkMjl5WkE9PQ=="));
  }

Przynajmniej jest to dla mnie wystarczająco skomplikowane. tak właśnie robię, gdy nie mam wyboru, ale przechowuję wartość w mojej aplikacji. Oczywiście wszyscy wiemy, że to nie jest najlepszy sposób, ale dla mnie działa.

/**
 * @param input
 * @return decoded string
 */
public static String decode(String input) {
    // Receiving side
    String text = "";
    try {
        byte[] data = Decoder.decode(input);
        text = new String(data, "UTF-8");
        return text;
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    return "Error";
}

Wersja zdekompilowana:

 public static String a(String paramString)
  {
    try
    {
      str = new String(a.a(paramString), "UTF-8");
      return str;
    }
    catch (UnsupportedEncodingException localUnsupportedEncodingException)
    {
      while (true)
      {
        localUnsupportedEncodingException.printStackTrace();
        String str = "Error";
      }
    }
  }

i możesz znaleźć tak wiele klas szyfrujących za pomocą małego wyszukiwania w Google.


13

Dodając do rozwiązania @Manohar Reddy, bazy danych Firebase lub FireCase RemoteConfig (z wartością domyślną Null) można użyć:

  1. Zaszyfruj klucze
  2. Przechowuj w bazie danych Firebase
  3. Zdobądź go podczas uruchamiania aplikacji lub w razie potrzeby
  4. rozszyfruj klucze i użyj go

Co różni się w tym rozwiązaniu?

  • brak referencji dla bazy ogniowej
  • dostęp do bazy ogniowej jest chroniony, więc tylko aplikacja z podpisanym certyfikatem ma uprawnienia do wykonywania połączeń API
  • szyfrowanie / deszyfrowanie, aby zapobiec przechwytywaniu przez środkowego człowieka. Jednak połączenia już https do bazy ogniowej

z całym szacunkiem dla tego rozwiązania, wciąż jesteśmy pierwszym kwadratem. Zamiast używania poświadczeń sugerujesz użycie certyfikatu. Ktokolwiek może ukraść twoje dane uwierzytelniające, może ukraść podpisany certyfikat.
Ashi

Jednak jedną z zalet proponowanego rozwiązania jest dodanie jeszcze jednej komplikacji przed hakerem.
Ashi

11

Ten przykład ma wiele różnych aspektów. Wspomnę o kilku kwestiach, które moim zdaniem nie zostały wyraźnie omówione w innym miejscu.

Ochrona tajemnicy podczas transportu

Pierwszą rzeczą, na którą należy zwrócić uwagę, jest dostęp do interfejsu API Dropbox przy użyciu uwierzytelniania aplikacji mechanizmu wymaga przesłania klucza i tajnego klucza. Połączenie to HTTPS, co oznacza, że ​​nie można przechwycić ruchu bez znajomości certyfikatu TLS. Zapobiega to przechwyceniu i odczytaniu pakietów przez osobę podróżującą z urządzenia mobilnego na serwer. Dla zwykłych użytkowników jest to naprawdę dobry sposób na zapewnienie prywatności ich ruchu.

To, co nie jest dobre, polega na zapobieganiu pobieraniu aplikacji i sprawdzaniu ruchu przez złośliwą osobę. Naprawdę łatwo jest korzystać z pośredniczącego proxy dla całego ruchu do i z urządzenia mobilnego. W tym przypadku nie wymaga demontażu ani inżynierii wstecznej kodu, aby wyodrębnić klucz aplikacji i klucz tajny ze względu na charakter interfejsu API Dropbox.

Możesz wykonać przypinanie, które sprawdza, czy certyfikat TLS otrzymany z serwera jest tym, którego oczekujesz. To dodaje kontrolę do klienta i utrudnia przechwytywanie ruchu. Utrudniłoby to kontrolę ruchu w locie, ale kontrola pinowania ma miejsce u klienta, więc prawdopodobnie nadal można wyłączyć test pinowania. Utrudnia to jednak.

Ochrona sekretu w spoczynku

Pierwszym krokiem jest użycie czegoś takiego jak proguard , który sprawi, że będzie mniej oczywiste, gdzie kryją się jakieś tajemnice. Możesz także użyć NDK do przechowywania klucza i tajemnicy oraz bezpośredniego wysyłania wniosków, co znacznie zmniejszy liczbę osób posiadających odpowiednie umiejętności do wydobywania informacji. Dalsze zaciemnianie można osiągnąć, nie przechowując wartości bezpośrednio w pamięci przez dłuższy czas, możesz je zaszyfrować i odszyfrować tuż przed użyciem, jak sugeruje inna odpowiedź.

Bardziej zaawansowane opcje

Jeśli masz teraz obsesję na punkcie umieszczenia sekretu w dowolnym miejscu w swojej aplikacji i masz czas i pieniądze na inwestowanie w bardziej kompleksowe rozwiązania, możesz rozważyć przechowywanie poświadczeń na swoich serwerach (zakładając, że je masz). Zwiększy to opóźnienie wszelkich wywołań interfejsu API, ponieważ będzie on musiał komunikować się za pośrednictwem serwera, i może zwiększyć koszty prowadzenia usługi z powodu zwiększonej przepustowości danych.

Następnie musisz zdecydować, jak najlepiej komunikować się z serwerami, aby zapewnić ich ochronę. Jest to ważne, aby zapobiec ponownemu pojawieniu się tych samych problemów z wewnętrznym interfejsem API. Najlepszą ogólną zasadą, jaką mogę podać, to nie przekazywać żadnych tajemnic bezpośrednio z powodu zagrożenia „człowiek w środku”. Zamiast tego możesz podpisać ruch przy użyciu swojego tajnego klucza i zweryfikować integralność wszelkich żądań przychodzących na twój serwer. Jednym ze standardowych sposobów jest obliczenie HMAC wiadomości wpisanej w tajny klucz. Pracuję w firmie, która ma produkt zabezpieczający, który również działa w tej dziedzinie, dlatego takie rzeczy mnie interesują. W rzeczywistości, oto artykuł na blogu jednego z moich kolegów, który omawia większość tego.

Ile powinienem zrobić?

W przypadku takich porad dotyczących bezpieczeństwa musisz podjąć decyzję dotyczącą kosztów / korzyści dotyczącą tego, jak bardzo chcesz zmusić kogoś do włamania. Jeśli jesteś bankiem chroniącym miliony klientów, twój budżet jest zupełnie inny niż ktoś, kto wspiera aplikację w ich wolny czas. Jest praktycznie niemożliwe, aby uniemożliwić komuś złamanie twojego bezpieczeństwa, ale w praktyce niewiele osób potrzebuje wszystkich dzwonków i gwizdków, a przy pewnych podstawowych środkach ostrożności można uzyskać długą drogę.


1
Po prostu skopiuj i wklej to stąd: hackernoon.com/mobile-api-security-techniques-682a5da4fe10 bez podania źródła.
ortonomy

1
@ortonomy Zgadzam się, że powinien był zacytować artykuł, który podlinkowałeś, ale mógł go zapomnieć, ponieważ oba pracują w tym samym miejscu ...
Exadra37

2
Również artykuł Skip i post na blogu, na którym są oparte, ukazał się tydzień po mojej odpowiedzi.
ThePragmatist

8

Najbezpieczniejszym rozwiązaniem jest przechowywanie kluczy na serwerze i kierowanie wszystkich żądań wymagających tego klucza przez serwer. W ten sposób klucz nigdy nie opuszcza twojego serwera, więc tak długo, jak długo twój serwer jest bezpieczny, tak i twój klucz. Oczywiście z tym rozwiązaniem wiąże się koszt wydajności.


32
Problem polega na tym - aby dotrzeć do tego serwera, który zawiera wszystkie skrypty, powinienem użyć innego tajnego klucza - zastanawiam się, gdzie to zatrzymam? ;) To, co próbuję powiedzieć, to - To też nie jest najlepsze rozwiązanie (nie sądzę, że jest tutaj idealne rozwiązanie)
Mercury

To nieprawda, twój serwer jest całkowicie pod twoją kontrolą. To, czego wymaga, zależy wyłącznie od Ciebie.
Bernard Igiri

5
Czy możesz wyjaśnić tutaj, w jaki sposób klient może szyfrować dane, które chce wysłać na serwer, gdy klucze znajdują się po stronie serwera? a jeśli twoja odpowiedź brzmi - serwer wysyła klucze do klienta - to też musi być zabezpieczone! więc znowu nie ma magicznego rozwiązania! nie widzisz ?!
Merkury

2
@BernardIgiri, a potem znowu wracamy do kwadratu 1. Załóżmy, że telefon tworzy losowy login, a serwer akceptuje go i wysyła PIN (to tak zwany prywatny serwer, o którym mówimy). Wtedy osoba, która dezasembluje twoją aplikację, widzi, że wszystko, czego potrzeba, aby uzyskać dostęp do twojego prywatnego serwera, to tylko losowe logowanie, które sam może stworzyć. Powiedz mi, co powstrzymuje go przed utworzeniem i dostępem do twojego serwera? W rzeczywistości, jaka jest różnica między Twoim rozwiązaniem a faktycznym przechowywaniem loginu lub klucza API na głównym serwerze (którego poświadczenia chcieliśmy przechowywać na naszym prywatnym serwerze)
Ken

3
@ken Losowy numer jest uwierzytelniany na podstawie numeru telefonu i fizycznego dostępu do jego wiadomości tekstowych. Jeśli ktoś Cię zdradza, masz jego informacje. Jeśli to nie wystarczy, wymuś utworzenie pełnego konta użytkownika i hasła. Jeśli to nie wystarczy, weź kartę kredytową. Jeśli to nie wystarczy, niech zadzwonią. Jeśli to nie wystarczy, spotkaj się z nimi twarzą w twarz. Jak bezpieczny / niewygodny chcesz być?
Bernard Igiri,

7

Zachowaj tajemnicę firebase databasei wyjdź z niej, gdy aplikacja się uruchomi. Jest to o wiele lepsze niż wywoływanie usługi internetowej.


13
ale co z poświadczeniami do bazy ogniowej?
the_joric

2
Niestety baza danych Firebase nie działa w Chinach.
Konjengbam,

9
nie ma sensu, atakujący mogą zobaczyć twoje szczegóły bazy
ogniowej

3
Myślę, że to najlepsze rozwiązanie, ponieważ firebase Apps używa SHA1, aby umożliwić dostęp do serwera. Dekompilacja kodu nie pomoże w wywołaniu bazy ogniowej, ponieważ nowa aplikacja hakera powinna używać dokładnego stempla aplikacji, aby uzyskać dostęp do bazy ogniowej. Przechowywany klucz należy również zaszyfrować przed zapisaniem w bazie danych DB i odszyfrować po otrzymaniu, aby uniknąć przechwycenia przez środkowego człowieka.
Ayman Al-Absi

Kiedy dostajesz sekret z bazy danych firebase przez sieć, w jaki sposób jest to bardziej bezpieczne niż uzyskiwanie tego samego sekretu z innej usługi internetowej za pośrednictwem bezpiecznego kanału (https)? Możesz wytłumaczyć?
Csaba Toth,

6

Cokolwiek zrobisz, aby zabezpieczyć swoje tajne klucze, nie będzie prawdziwym rozwiązaniem. Jeśli programista może zdekompilować aplikację, nie ma sposobu, aby zabezpieczyć klucz, ukrycie klucza to po prostu bezpieczeństwo przez zaciemnienie, podobnie jak zaciemnienie kodu. Problem z zabezpieczeniem tajnego klucza polega na tym, że aby go zabezpieczyć, musisz użyć innego klucza i ten klucz również musi być zabezpieczony. Pomyśl o kluczu ukrytym w pudełku zamkniętym kluczem. Umieszczasz pudełko w pokoju i zamykasz pokój. Pozostaje ci kolejny klucz do zabezpieczenia. I ten klucz będzie nadal zakodowany na stałe w twojej aplikacji.

Więc dopóki użytkownik nie wprowadzi kodu PIN lub frazy, nie ma sposobu, aby ukryć klucz. Ale aby to zrobić, musiałbyś mieć schemat zarządzania PIN-ami występującymi poza pasmem, co oznacza przez inny kanał. Z pewnością nie jest praktyczne do zabezpieczania kluczy do usług takich jak interfejsy API Google.


5

Wiekowy post, ale wciąż wystarczająco dobry. Myślę, że ukrywanie go w bibliotece .so byłoby świetne, oczywiście przy użyciu NDK i C ++. Pliki .so można wyświetlać w edytorze szesnastkowym, ale powodzenia przy dekompilacji: P


9
Użytkownicy mogą łatwo wywoływać funkcje do biblioteki współdzielonej i uzyskiwać wszystko, co się tam ukrywa. Nie trzeba go rozpakowywać.
david72

5
Według androidauthority.com/… obecnie nie ma bezpiecznego sposobu na zrobienie tego w Androidzie .
david72

1
@AhmedAwad Nie rozumiem, dlaczego ma to 3 pozytywne oceny. każdy może łatwo zdekompilować aplikację i zobaczyć, jak nazywa się punkt wejścia
ndk

1
Ta odpowiedź jest prawie jedną z najlepszych opcji, ale autor powinien wspomnieć, że bardzo ważne jest, aby dołączyć wywołanie (w bibliotece NDK), aby sprawdzić, czy suma kontrolna pasuje do Twojego APK, ponieważ w przeciwnym razie ktoś może wywołać bibliotekę NDK poza Twoja aplikacja
Stoycho Andreev,

@Sniper, byłoby świetnie, z wyjątkiem tego, że ma duży problem. Skąd wiesz, który plik „wywołuje” metodę natywną? Jeśli na sztywno kodujesz nazwę apka do sprawdzenia, świetnie, ale co, jeśli sprawię, że mój „hack” apk będzie tym samym folderem co „dobry” apk? Sprawdzi, czy „dobra” aplikacja ma dobrą sumę kontrolną i pozwoli mi wykonać tę natywną metodę. O ile nie ma sposobu na poznanie pliku wywołującego od strony JNI / C ++, to nie ma sensu jak inne opcje.
SocketByte

5

Jedynym prawdziwym sposobem na zachowanie tych prywatności jest zachowanie ich na serwerze, a aplikacja wysyła wszystko na serwer, a serwer wchodzi w interakcję z Dropbox. W ten sposób NIGDY nie dystrybuujesz swojego klucza prywatnego w jakimkolwiek formacie.


11
Ale w jaki sposób uniemożliwisz reszcie świata dzwonienie do serwera?
user2966445

Jeśli przez „serwer” rozumiesz swój serwer internetowy, na którym znajdują się dane uwierzytelniające - możesz użyć dowolnej metody. proste uwierzytelnianie przy użyciu nazwy użytkownika / hasła, autoryzacji, active directory itp. Naprawdę zależy od twojej aplikacji.
Nick

Może czegoś mi brakuje, ale czy to nie wymaga przechowywania poświadczeń w aplikacji?
user2966445

3
Racja, ale powiedziałeś, że aplikacja najpierw uwierzytelni się na serwerze. Czy to nie oznacza przechowywania innego zestawu poświadczeń w aplikacji? Rozumiem, że serwer obsługiwałby rzeczywiste wywołania dropbox.
user2966445

4
Może to oznaczać, ale jest to zupełnie osobna autoryzacja. Ale nie musisz. Przypadek użycia, o którym mówię, polega na tym, że użytkownik aplikacji miałby login do aplikacji, powiedzmy za pomocą Facebooka lub Twittera. Nie przechowujesz ich poświadczeń w swojej aplikacji, nawet ich nie znasz. Ten proces autoryzacji umożliwia im dostęp do serwera interfejsu API, który ma poświadczenia do skrzynki odbiorczej, ale żadna aplikacja ani użytkownik nie ma do nich bezpośredniego dostępu.
Nick

0

W oparciu o gorzkie doświadczenia i po konsultacji z ekspertem IDA-Pro najlepszym rozwiązaniem jest przeniesienie kluczowej części kodu do DLL / SharedObject, a następnie pobranie go z serwera i załadowanie w czasie wykonywania.

Wrażliwe dane muszą zostać zakodowane, ponieważ bardzo łatwo jest zrobić coś takiego:

$ strings libsecretlib.so | grep My
  My_S3cr3t_P@$$W0rD

3
A gdzie przechowujesz dane uwierzytelniające dla tego serwera?
ZX9,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.