Najlepsze praktyki przechowywania i ochrony prywatnych kluczy API w aplikacjach [zamknięte]

Zamknięte . To pytanie jest oparte na opinii . Obecnie nie przyjmuje odpowiedzi.

Chcesz poprawić to pytanie? Zaktualizuj pytanie, aby mogło być odpowiedź z faktami i cytatami przez edytując ten post .

Zamknięte 1 rok temu .

Popraw to pytanie

Większość programistów aplikacji zintegruje niektóre biblioteki firm trzecich ze swoimi aplikacjami. Jeśli chodzi o dostęp do usługi, takiej jak Dropbox lub YouTube, lub rejestrowanie awarii. Liczba trzecia biblioteki i usługi partyjne są oszałamiające. Większość tych bibliotek i usług jest zintegrowana poprzez uwierzytelnianie z usługą, w większości przypadków dzieje się to za pomocą klucza API. Dla celów bezpieczeństwa, usługi zazwyczaj generują publiczny i prywatny, często określany również jako tajny, klucz. Niestety, aby połączyć się z usługami, ten klucz prywatny musi być użyty do uwierzytelnienia, a co za tym idzie, prawdopodobnie być częścią aplikacji. Nie trzeba dodawać, że stoi to w ogromnej problem z bezpieczeństwem. Publiczne i prywatne klucze API można wyodrębnić z plików APK w ciągu kilku minut i można je łatwo zautomatyzować.

Zakładając, że mam coś podobnego do tego, jak 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? Zaciemnienie, szyfrowanie, co o tym myślisz?

Author: Basic Coder, 2013-01-28

14 answers

  1. Tak jak jest, 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 za pomocą standardowego narzędzia Android dx.

  2. Możesz zastosować ProGuard. Pozostawi ciągi klawiszy nietknięte, ale usunie stałe nazwy. Zmieni również nazwy klas i metod z krótkimi, bezsensownymi nazwami, tam gdzie to możliwe. Wydobycie kluczy zajmuje więcej czas, aby dowiedzieć się, który ciąg służy do jakiego celu.

    pamiętaj, że konfiguracja ProGuard nie powinna być tak trudna, jak się obawiasz. Na początek wystarczy włączyć program ProGuard, zgodnie z dokumentacją w projekcie.właściwości. W przypadku jakichkolwiek problemów z bibliotekami innych firm, może być konieczne stłumienie niektórych ostrzeżeń i/lub uniemożliwienie ich zaciemniania w proguard-project.txt. Na przykład:

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

    jest to podejście brute-force; można udoskonalić takie konfiguracja po uruchomieniu przetworzonej aplikacji.

  3. Możesz zaciemniać łańcuchy znaków ręcznie w kodzie, na przykład za pomocą kodowania Base64 lub najlepiej za pomocą czegoś bardziej skomplikowanego; może nawet kodu natywnego. Haker będzie musiał statycznie odtworzyć kodowanie lub dynamicznie przechwycić dekodowanie we właściwym miejscu.

  4. Możesz zastosować komercyjny obfuscator, taki jak wyspecjalizowane rodzeństwo ProGuard DexGuard. Może dodatkowo Szyfruj / zaciemniaj łańcuchy i klasy. Wydobycie kluczy zajmuje wtedy jeszcze więcej czasu i wiedzy.

  5. Być może będziesz mógł uruchamiać części swojej aplikacji na własnym serwerze. Jeśli możesz trzymać tam klucze, są bezpieczne.

W końcu jest to ekonomiczny kompromis, który musisz zrobić: jak ważne są klucze, ile czasu lub oprogramowania możesz sobie pozwolić, jak wyrafinowani są hakerzy, którzy są zainteresowani kluczami, ile czasu czy będą chcieli wydać, ile warte jest opóźnienie przed zhakowaniem kluczy, na jaką skalę udani hakerzy rozpowszechniają klucze itp. Małe fragmenty informacji, takie jak klucze, są trudniejsze do ochrony niż całe aplikacje. Z natury rzeczy nic po stronie klienta nie jest nierozerwalne, ale z pewnością możesz podnieść poprzeczkę.

[[3]}(jestem twórcą ProGuard i DexGuard)
 372
Author: Eric Lafortune,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-28 22:01:22

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

  1. Zachowaj swoje sekrety na jakimś serwerze w Internecie, a w razie potrzeby po prostu je chwyć i użyj. Jeśli użytkownik ma zamiar korzystać z dropbox, nic nie stoi na przeszkodzie, aby złożyć wniosek do witryny i uzyskać tajny klucz.

  2. Umieść swoje sekrety w kodzie jni, dodaj zmienny kod, aby Twoje biblioteki były większe i trudniejsze do dekompilacji. Można również podzielić łańcuch klawiszy na kilka części i zachować je w różnych miejsca.

  3. Użyj obfuscator, również umieścić w kodzie hashed tajne i Później unhash go, gdy potrzebne do użycia.

  4. Umieść swój tajny klucz jako ostatnie piksele jednego z obrazów w zasobach. Następnie w razie potrzeby przeczytaj go w swoim kodzie. Zaciemnienie kodu powinno pomóc w ukryciu kodu, który go odczyta.

Jeśli chcesz mieć szybki przyjrzeć się, jak łatwo jest odczytać Ci kod apk, a następnie chwycić APKAnalyser: {]}

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

 82
Author: marcinj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-28 21:39:19

Innym podejściem jest nie mieć tajemnicy na urządzeniu w pierwszej kolejności! Zobacz techniki zabezpieczeń mobilnego API (szczególnie część 3).

Korzystając z uświęconej tradycją indirection, dziel się tajemnicą między punktem końcowym API a usługą uwierzytelniania aplikacji.

Gdy twój klient chce wykonać wywołanie API , prosi usługę App auth o jej uwierzytelnienie( przy użyciu silnych technik zdalnego atestowania) i otrzymuje ograniczony czas (Zwykle JWT ) token podpisany przez tajemnicę.

Token jest wysyłany z każdym wywołaniem API , gdzie 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, łączy żądania uwierzytelnienia i przekazuje token wynikowy. Jako miłą korzyść z indirection, jeśli kiedykolwiek chcesz zmienić sekret, możesz to zrobić bez konieczności aktualizowania swoich zainstalowane aplikacje.

Więc jeśli chcesz chronić swój sekret, nie posiadanie go w aplikacji w pierwszej kolejności jest całkiem dobrym sposobem.

 45
Author: Skip Hovsmith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-14 04:51:21

Stara niezabezpieczona Droga:

Aby zabezpieczyć API / tajny klucz, wykonaj 3 proste kroki (Old answer)

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

1. gradle.properties (właściwości projektu): Utwórz zmienną z kluczem.

GoolgeAPIKey = "Your API/Secret Key"

2. buduj.gradle (Module: app): ustawia zmienną w build.gradle, aby uzyskać do niego dostęp w aktywności lub fragmencie. Dodaj poniższy kod do buildTypes {}.

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

3. Dostęp do niego w aktywności / fragmencie przez app ' s BuildConfig:

BuildConfig.GoogleSecAPIKEY

Update:

Powyższe rozwiązanie jest pomocne w projekcie open source do commit 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 i Decompiler pozwoli komuś zobaczyć BuildConfig z naszymi tajnymi kluczami.

Rozwiązanie:

Możemy użyć NDK do zabezpieczenia kluczy API. Klucze możemy przechowywać w natywnej klasie C / C++ i uzyskać do nich dostęp na naszych zajęciach Java.

Proszę śledzić ten blog, aby zabezpieczyć klucze API za pomocą NDK.

Kontynuacja o tym, jak bezpiecznie przechowywać tokeny w Androidzie

 27
Author: SANAT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-15 08:22:50

Dodanie do @Manohar Reddy solution, Firebase Database lub firebase RemoteConfig (z wartością domyślną Null) może być użyte:

  1. Szyfruj swoje klucze
  2. przechowuj go w bazie firebase
  3. Pobierz go podczas uruchamiania aplikacji lub gdy jest to wymagane]}
  4. rozszyfruj klucze i użyj ich

Czym różni się to rozwiązanie?

  • brak wpisów dla firebase
  • dostęp do bazy firebase jest chroniony, więc tylko aplikacja z podpisanym certyfikatem ma uprawnienie do wykonywania wywołań API
  • szyfr / rozszyfrowanie, aby zapobiec przechwyceniu środkowego człowieka. Jednakże połączenia https do firebase
 16
Author: Ayman Al-Absi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-14 05:18:36

Tajny klucz aplikacji powinien być przechowywany w tajemnicy - ale po zwolnieniu aplikacji niektórzy mogą je odwrócić.

Dla tych facetów to nie ukryje, zablokować albo ProGuard kod. Jest to refaktor, a niektóre płatne obfuscatory wstawiają kilka bitowych operatorów, aby odzyskać jk433g34hg3 Sznurek. Możesz zrobić 5 -15 min dłużej hacking jeśli pracujesz 3 dni:)

Najlepszy sposób to zachować to tak jak jest, imho.

Nawet jeśli przechowujesz po stronie serwera (komputera ) 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.

Zwykły użytkownik nie zdekompiluje Twojego kodu.

 15
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-28 21:03:53

Jednym z możliwych rozwiązań jest zakodowanie danych w aplikacji i użycie dekodowania w czasie wykonywania (jeśli chcesz użyć tych danych). Polecam również użyć progaurd, aby utrudnić czytanie i zrozumienie dekompilowanego kodu źródłowego aplikacji . na przykład umieściłem zakodowany klucz w aplikacji, a następnie użyłem metody dekodowania w mojej aplikacji do dekodowania tajnych kluczy 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=="));
}

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

 public String c()
 {
    return com.myrpoject.mypackage.g.h.a(com.myrpoject.mypackage.g.h.a("Ylhsd1lYTnpkMjl5WkE9PQ=="));
  }
Przynajmniej dla mnie to wystarczająco skomplikowane. to jest tak robię, gdy nie mam wyboru, ale przechowuję wartość w mojej aplikacji. Oczywiście wszyscy wiemy, że to nie jest najlepszy sposób, ale to działa dla mnie.
/**
 * @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 dekompilowana:

 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 z małym wyszukiwaniem w google.

 15
Author: Milad Faridnia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-10 09:03:10

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

Protecting the secret in transit

Pierwszą rzeczą, na którą należy zwrócić uwagę, jest to, że dostęp do API dropbox przy użyciu mechanizmu uwierzytelniania aplikacji wymaga przesłania klucza i tajemnicy. Połączenie jest HTTPS, co oznacza, że nie można przechwycić ruchu bez znajomości certyfikatu TLS. To jest do zapobiegaj przechwytywaniu i odczytywaniu pakietów podczas podróży 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, w czym nie jest dobry, to zapobieganie złośliwej osobie pobierającej aplikację i kontrolującej ruch. Korzystanie z proxy man-in-the-middle jest naprawdę łatwe dla całego ruchu do iz urządzenia mobilnego. Nie wymagałoby to demontażu ani inżynierii wstecznej kodu, aby wyodrębnić klucz aplikacji i tajemnica w tym przypadku ze względu na charakter interfejsu API Dropbox.

Możesz wykonać przypinanie , które sprawdza, czy certyfikat TLS, który otrzymujesz od serwera, jest tym, którego oczekujesz. To dodaje czek do klienta i utrudnia przechwycenie ruchu. Utrudni to kontrolę ruchu w locie, ale kontrola przypinania odbywa się w kliencie, więc prawdopodobnie nadal będzie możliwe wyłączenie testu przypinania. To sprawia, że trudniej chociaż.

Ochrona tajemnicy w spoczynku

Jako pierwszy krok, użycie czegoś w rodzaju proguard pomoże uczynić to mniej oczywistym, gdzie trzymane są jakiekolwiek tajemnice. Możesz również użyć NDK do przechowywania klucza i tajemnicy oraz wysyłania żądań bezpośrednio, co znacznie zmniejszyłoby liczbę osób posiadających odpowiednie umiejętności wydobywania informacji. Dalsze zaciemnianie można uzyskać, nie przechowując wartości bezpośrednio w pamięci przez Dowolny czas, można zaszyfrować je i odszyfrować je tuż przed użyciem, zgodnie z sugestią innej odpowiedzi.

Bardziej zaawansowane opcje

Jeśli masz teraz paranoję na temat umieszczania tajemnicy w dowolnym miejscu w swojej aplikacji i masz czas i pieniądze, aby zainwestować w bardziej kompleksowe rozwiązania, możesz rozważyć przechowywanie poświadczeń na swoich serwerach(zakładając, że je masz). Zwiększyłoby to opóźnienie wszelkich wywołań do API, ponieważ będzie on musiał komunikować się za pośrednictwem serwera i może zwiększyć koszty uruchamianie usługi ze względu na zwiększoną przepustowość danych.

Następnie musisz zdecydować, jak najlepiej komunikować się z serwerami, aby zapewnić ich ochronę. Jest to ważne, aby zapobiec ponownemu wystąpieniu tych samych problemów z wewnętrznym interfejsem API. Najlepszą zasadą, jaką mogę dać, jest nie przekazywać żadnych tajemnic bezpośrednio z powodu zagrożenia "człowiek w środku". Zamiast tego możesz podpisać ruch za pomocą swojej tajemnicy i zweryfikować integralność wszelkich żądań, które przychodzą na twój serwer. Jeden standardowym sposobem jest obliczenie HMAC wiadomości z kluczem tajnym. Pracuję w firmie, która ma produkt zabezpieczający, który działa również w tej dziedzinie, dlatego tego rodzaju rzeczy mnie interesują. W rzeczywistości, oto blog artykuł jednego z moich kolegów, który omawia większość tego.

Ile powinienem zrobić?

Z takimi poradami bezpieczeństwa musisz podjąć decyzję o kosztach/korzyściach o tym, jak ciężko chcesz, aby ktoś się włamał. Jeśli jesteś bankiem chroniącym miliony klientów, twój budżet jest zupełnie inny niż ktoś, kto obsługuje aplikację w wolnym czasie. Jest to praktycznie niemożliwe, aby zapobiec komuś przed złamaniem bezpieczeństwa, ale w praktyce niewiele osób potrzebuje wszystkich dzwonów i gwizdków, a niektóre podstawowe środki ostrożności można uzyskać długą drogę.

 11
Author: ThePragmatist,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-17 13:32:11

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 opuści twojego serwera, więc tak długo, jak Twój serwer jest bezpieczny, tak samo jest z Twoim kluczem. Oczywiście jest koszt wydajności z tego rozwiązania.

 8
Author: Bernard Igiri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-24 15:41:13

Keep The secret in firebase database i uzyskaj z niego po uruchomieniu aplikacji , Jest to o wiele lepsze niż wywołanie usługi internetowej .

 7
Author: Manohar Reddy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-06 13:11:25

Cokolwiek zrobisz, aby zabezpieczyć swoje tajne klucze, nie będzie prawdziwym rozwiązaniem. Jeśli programista może dekompilować aplikację, nie ma sposobu na zabezpieczenie klucza, ukrywanie klucza jest tylko zabezpieczeniem 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 musi być również zabezpieczony. Pomyśl o kluczu ukrytym w pudełku, które jest zamknięte kluczem. Umieszczasz pudełko w pokoju i zamykasz pokój. Zostajesz z kolejny klucz do zabezpieczenia. I ten klucz nadal będzie zakodowany na twardo w Twojej aplikacji.

Więc dopóki użytkownik nie wprowadzi kodu PIN lub frazy, nie ma możliwości ukrycia klucza. Aby to zrobić, musisz mieć schemat zarządzania pinami, który odbywa się poza pasmem, co oznacza, że za pośrednictwem innego kanału. Z pewnością nie jest to praktyczne zabezpieczenie kluczy dla usług takich jak Google API.

 6
Author: user1611728,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-15 16:27:44

Stary post, ale nadal wystarczająco dobry. Myślę, że ukrycie go w bibliotece .so byłoby świetne, oczywiście używając NDK i C++. . więc pliki można przeglądać w edytorze hex, ale powodzenia w dekompilacji tego :P

 5
Author: Ahmed Awad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-30 15:51:53

Jedynym prawdziwym sposobem na zachowanie prywatności jest przechowywanie ich na serwerze, a aplikacja wysyła cokolwiek to jest na serwer, a serwer wchodzi w interakcję z Dropbox. W ten sposób nigdy nie rozpowszechniasz klucza prywatnego w żadnym formacie.

 5
Author: Nick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-07 18:55:33

Bazując na gorzkim doświadczeniu 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.

Poufne dane muszą być zakodowane, ponieważ bardzo łatwo jest zrobić coś takiego:

$ strings libsecretlib.so | grep My
  My_S3cr3t_P@$$W0rD
 0
Author: RonTLV,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-27 11:00:34