Sebagian besar pengembang aplikasi akan mengintegrasikan beberapa perpustakaan pihak ketiga ke dalam aplikasi mereka. Jika ingin mengakses layanan, seperti Dropbox atau YouTube, atau untuk penebangan macet. Jumlah perpustakaan dan layanan pihak ketiga sangat mengejutkan. Sebagian besar perpustakaan dan layanan diintegrasikan dengan entah bagaimana mengotentikasi dengan layanan, sebagian besar waktu, ini terjadi melalui kunci API. Untuk tujuan keamanan, layanan biasanya menghasilkan publik dan swasta, sering juga disebut sebagai kunci rahasia. Sayangnya, untuk terhubung ke layanan, kunci pribadi ini harus digunakan untuk otentikasi dan karenanya, mungkin menjadi bagian dari aplikasi. Tak perlu dikatakan, bahwa ini menghadapi masalah keamanan besar. Kunci API publik dan pribadi dapat diekstraksi dari APK dalam hitungan menit dan dapat dengan mudah diotomatisasi.
Dengan asumsi saya memiliki sesuatu yang mirip dengan ini, bagaimana saya bisa melindungi kunci rahasia:
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
}
Menurut Anda, apa cara terbaik dan paling aman untuk menyimpan kunci pribadi? Kebingungan, enkripsi, bagaimana menurut Anda?
sumber
Jawaban:
Karena itu, aplikasi Anda yang dikompilasi berisi string kunci, tetapi juga nama konstan APP_KEY dan APP_SECRET. Mengekstrak kunci dari kode yang mendokumentasikan diri sendiri itu sepele, misalnya dengan alat Android standar dx.
Anda dapat menerapkan ProGuard. Ini akan membuat string kunci tidak tersentuh, tetapi itu akan menghapus nama konstan. Itu juga akan mengganti nama kelas dan metode dengan nama pendek, tidak berarti, jika memungkinkan. Mengekstrak kunci kemudian membutuhkan waktu lebih lama, untuk mencari tahu string mana yang melayani tujuan mana.
Perhatikan bahwa pengaturan ProGuard seharusnya tidak sesulit yang Anda takutkan. Untuk memulainya, Anda hanya perlu mengaktifkan ProGuard, seperti yang didokumentasikan dalam project.properties. Jika ada masalah dengan perpustakaan pihak ketiga, Anda mungkin perlu menekan beberapa peringatan dan / atau mencegahnya dikaburkan, di proguard-project.txt. Contohnya:
Ini adalah pendekatan brute-force; Anda dapat memperbaiki konfigurasi tersebut setelah aplikasi yang diproses berfungsi.
Anda dapat mengaburkan string secara manual dalam kode Anda, misalnya dengan pengkodean Base64 atau lebih disukai dengan sesuatu yang lebih rumit; bahkan mungkin kode asli. Seorang peretas kemudian harus secara terbalik merekayasa encoding Anda atau secara dinamis mencegat decoding di tempat yang tepat.
Anda dapat menerapkan obfuscator komersial, seperti saudara khusus ProGuard, DexGuard . Selain itu dapat mengenkripsi / mengaburkan string dan kelas untuk Anda. Mengekstrak kunci kemudian membutuhkan lebih banyak waktu dan keahlian.
Anda mungkin dapat menjalankan sebagian aplikasi Anda di server Anda sendiri. Jika Anda dapat menyimpan kunci di sana, mereka aman.
Pada akhirnya, ini adalah trade-off ekonomi yang harus Anda buat: seberapa penting kunci, berapa banyak waktu atau perangkat lunak yang Anda mampu, seberapa canggih peretas yang tertarik pada kunci, berapa banyak waktu yang mereka inginkan belanjakan, berapa nilainya penundaan sebelum kunci diretas, pada skala apa peretas yang berhasil akan mendistribusikan kunci, dll. Informasi kecil seperti kunci lebih sulit untuk dilindungi daripada seluruh aplikasi. Pada dasarnya, tidak ada yang ada di sisi klien yang tidak bisa dipecahkan, tetapi Anda tentu dapat meningkatkannya.
(Saya adalah pengembang ProGuard dan DexGuard)
sumber
Beberapa ide, menurut saya hanya yang pertama memberikan jaminan:
Simpan rahasia Anda di beberapa server di internet, dan bila perlu ambil saja dan gunakan. Jika pengguna akan menggunakan dropbox maka tidak ada yang menghentikan Anda dari membuat permintaan ke situs Anda dan mendapatkan kunci rahasia Anda.
Masukkan rahasia Anda dalam kode jni, tambahkan beberapa kode variabel untuk membuat perpustakaan Anda lebih besar dan lebih sulit untuk didekompilasi. Anda juga dapat memisahkan string kunci menjadi beberapa bagian dan menyimpannya di berbagai tempat.
menggunakan obfuscator, juga memasukkan kode hash rahasia dan kemudian melepasnya ketika dibutuhkan untuk digunakan.
Masukkan kunci rahasia Anda sebagai piksel terakhir dari salah satu gambar Anda di aset. Kemudian ketika perlu membacanya di kode Anda. Mengacaukan kode Anda akan membantu menyembunyikan kode yang akan membacanya.
Jika Anda ingin melihat sekilas betapa mudahnya membaca kode apk Anda, lalu ambil APKAnalyser:
http://developer.sonymobile.com/knowledge-base/tool-guides/analyse-your-apks-with-apkanalyser/
sumber
Pendekatan lain adalah tidak memiliki rahasia pada perangkat di tempat pertama! Lihat Teknik Keamanan API Seluler (terutama bagian 3).
Menggunakan tradisi tipuan waktu yang dihormati, bagikan rahasia antara titik akhir API Anda dan layanan otentikasi aplikasi.
Ketika klien Anda ingin membuat panggilan API , ia meminta layanan auth app untuk mengautentikasi (menggunakan teknik pengesahan jarak jauh yang kuat), dan menerima token waktu terbatas (biasanya JWT ) yang ditandatangani oleh rahasia.
Token dikirim dengan setiap panggilan API di mana titik akhir dapat memverifikasi tanda tangannya sebelum bertindak atas permintaan.
Rahasia sebenarnya tidak pernah ada pada perangkat; pada kenyataannya, aplikasi tidak pernah tahu apakah itu valid atau tidak, itu menjorok permintaan otentikasi dan meneruskan token yang dihasilkan. Sebagai manfaat bagus dari tipuan, jika Anda ingin mengubah rahasia, Anda dapat melakukannya tanpa mengharuskan pengguna untuk memperbarui aplikasi yang diinstal.
Jadi, jika Anda ingin melindungi rahasia Anda, tidak memilikinya di aplikasi Anda di tempat pertama adalah cara yang cukup baik untuk pergi.
sumber
Cara tidak aman lama:
Ikuti 3 langkah sederhana untuk mengamankan API / Kunci rahasia ( Jawaban lama )
Kita dapat menggunakan Gradle untuk mengamankan kunci API atau kunci Rahasia.
1. gradle.properties (Properti proyek): Buat variabel dengan kunci.
2. build.gradle (Module: app): Setel variabel di build.gradle untuk mengaksesnya dalam aktivitas atau fragmen. Tambahkan kode di bawah ini ke buildTypes {}.
3. Akses di Aktivitas / Fragmen oleh BuildConfig aplikasi:
Perbarui:
Solusi di atas sangat membantu dalam proyek open source untuk melakukan lebih dari Git. (Terima kasih kepada David Rawson dan riyaz-ali untuk komentar Anda).
Sesuai komentar Matthew dan Pablo Cegarra cara di atas tidak aman dan Decompiler akan memungkinkan seseorang untuk melihat BuildConfig dengan kunci rahasia kami.
Solusi:
Kita dapat menggunakan NDK untuk Mengamankan Kunci API. Kita bisa menyimpan kunci di kelas C / C ++ asli dan mengaksesnya di kelas Java kita.
Ikuti blog ini untuk mengamankan kunci API menggunakan NDK.
Tindak lanjut tentang cara menyimpan token dengan aman di Android
sumber
gradle.properties
seharusnya tidak masuk ke Git jadi ini adalah cara untuk menjaga rahasia dari kode sumber yang berkomitmen, setidaknyaapk
(itu akan ditambahkan keBuildConfig
file yang dihasilkan ), meskipun ini jelas merupakan ide yang baik untuk mengelola kunci API yang berbeda (untuk misalnya dalam proyek open source)BuildConfig.java
File Anda akan memiliki kunci dalam bentuk teks biasa. Ini tidak lebih baik dari apa yang sudah dilakukan OP.bagi mereka yang tidak akan disembunyikan, kunci salah
ProGuard
satu kode. Ini adalah refactor dan beberapa obfuscator berbayar memasukkan beberapa operator bitwise untuk mendapatkan kembalijk433g34hg3
String. Anda dapat membuat 5 -15 menit lebih lama peretasan jika Anda bekerja 3 hari :)Cara terbaik adalah tetap seperti itu, imho.
Bahkan jika Anda menyimpan di sisi server (PC Anda) kuncinya dapat diretas dan dicetak. Mungkin ini yang paling lama? Bagaimanapun itu adalah masalah beberapa menit atau beberapa jam dalam kasus terbaik.
Pengguna normal tidak akan mendekompilasi kode Anda.
sumber
Salah satu solusi yang mungkin adalah menyandikan data di aplikasi Anda dan menggunakan decoding saat runtime (saat Anda ingin menggunakan data itu). Saya juga merekomendasikan untuk menggunakan progaurd untuk membuatnya sulit untuk membaca dan memahami kode sumber aplikasi Anda. misalnya saya meletakkan kunci yang dikodekan dalam aplikasi dan kemudian menggunakan metode decode di aplikasi saya untuk memecahkan kode kunci rahasia saya pada saat runtime:
Kode sumber yang didekompilasi dari aplikasi proguard adalah ini:
Setidaknya itu cukup rumit untukku. ini adalah cara yang saya lakukan ketika saya tidak punya pilihan selain menyimpan nilai dalam aplikasi saya. Tentu saja kita semua tahu Ini bukan cara terbaik tetapi ini bekerja untuk saya.
Versi terdekompilasi:
dan Anda dapat menemukan begitu banyak kelas enkripsi dengan sedikit pencarian di google.
sumber
Menambahkan ke solusi @Manohar Reddy, Firebase Database atau firebase RemoteConfig (dengan nilai default Null) dapat digunakan:
Apa yang berbeda dalam solusi ini?
sumber
Contoh ini memiliki sejumlah aspek berbeda. Saya akan menyebutkan beberapa poin yang saya pikir tidak secara eksplisit dibahas di tempat lain.
Melindungi rahasia dalam perjalanan
Hal pertama yang perlu diperhatikan adalah bahwa mengakses API dropbox menggunakan mekanisme autentikasi aplikasi mereka mengharuskan Anda untuk mengirimkan kunci dan rahasia Anda. Koneksi adalah HTTPS yang berarti bahwa Anda tidak dapat mencegat lalu lintas tanpa mengetahui sertifikat TLS. Ini untuk mencegah seseorang mencegat dan membaca paket-paket dalam perjalanan mereka dari perangkat seluler ke server. Untuk pengguna normal, ini adalah cara yang sangat baik untuk memastikan privasi lalu lintas mereka.
Apa yang tidak pandai, adalah mencegah orang jahat mengunduh aplikasi dan memeriksa lalu lintas. Sangat mudah untuk menggunakan proxy man-in-the-middle untuk semua lalu lintas masuk dan keluar dari perangkat seluler. Tidak diperlukan pembongkaran atau rekayasa balik kode untuk mengekstrak kunci aplikasi dan rahasia dalam hal ini karena sifat API Dropbox.
Anda dapat melakukan pinning yang memeriksa bahwa sertifikat TLS yang Anda terima dari server adalah yang Anda harapkan. Ini menambahkan cek ke klien dan membuatnya lebih sulit untuk mencegat lalu lintas. Ini akan membuat lebih sulit untuk memeriksa lalu lintas dalam penerbangan, tetapi pemeriksaan pinning terjadi pada klien, sehingga kemungkinan masih mungkin untuk menonaktifkan tes pinning. Itu memang membuatnya lebih sulit.
Melindungi rahasia saat istirahat
Sebagai langkah pertama, menggunakan sesuatu seperti proguard akan membantu memperjelas di mana rahasia disimpan. Anda juga dapat menggunakan NDK untuk menyimpan kunci dan rahasia dan mengirim permintaan secara langsung, yang akan sangat mengurangi jumlah orang dengan keterampilan yang sesuai untuk mengekstraksi informasi. Kebingungan lebih lanjut dapat dicapai dengan tidak menyimpan nilai-nilai secara langsung dalam memori untuk waktu yang lama, Anda dapat mengenkripsi dan mendekripsi mereka sebelum digunakan seperti yang disarankan oleh jawaban lain.
Opsi lebih lanjut
Jika Anda sekarang paranoid tentang menyimpan rahasia di mana saja di aplikasi Anda, dan Anda punya waktu dan uang untuk berinvestasi dalam solusi yang lebih komprehensif, maka Anda dapat mempertimbangkan menyimpan kredensial di server Anda (anggap Anda punya). Ini akan meningkatkan latensi panggilan apa pun ke API, karena harus berkomunikasi melalui server Anda, dan dapat meningkatkan biaya menjalankan layanan Anda karena peningkatan throughput data.
Anda kemudian harus memutuskan cara terbaik untuk berkomunikasi dengan server Anda untuk memastikan mereka terlindungi. Ini penting untuk mencegah semua masalah yang sama muncul lagi dengan API internal Anda. Aturan praktis terbaik yang bisa saya berikan adalah tidak mengirimkan rahasia apa pun secara langsung karena ancaman lelaki di tengah. Alih-alih, Anda dapat menandatangani lalu lintas menggunakan rahasia Anda dan memverifikasi integritas permintaan apa pun yang datang ke server Anda. Salah satu cara standar untuk melakukan ini adalah dengan menghitung HMAC dari pesan yang dikunci pada sebuah rahasia. Saya bekerja di sebuah perusahaan yang memiliki produk keamanan yang juga beroperasi di bidang ini yang mengapa hal semacam ini menarik minat saya. Sebenarnya, di sini ada artikel blog dari salah satu kolega saya yang membahas sebagian besar dari ini.
Berapa yang harus saya lakukan?
Dengan saran keamanan seperti ini, Anda perlu membuat keputusan biaya / manfaat tentang seberapa keras Anda ingin membuatnya agar bisa didobrak. Jika Anda bank yang melindungi jutaan pelanggan, anggaran Anda sama sekali berbeda dengan seseorang yang mendukung aplikasi di waktu luang. Sebenarnya tidak mungkin untuk mencegah seseorang merusak keamanan Anda, tetapi dalam praktiknya hanya sedikit orang yang membutuhkan semua lonceng dan peluit dan dengan beberapa tindakan pencegahan dasar Anda bisa menempuh jalan panjang.
sumber
Solusi paling aman adalah menyimpan kunci Anda di server dan merutekan semua permintaan yang membutuhkan kunci itu melalui server Anda. Dengan begitu kunci tidak pernah meninggalkan server Anda, jadi selama server Anda aman maka kunci Anda juga. Tentu saja ada biaya kinerja dengan solusi ini.
sumber
Jaga kerahasiaan
firebase database
dan dapatkan darinya saat aplikasi dimulai, Ini jauh lebih baik daripada memanggil layanan web.sumber
Apa pun yang Anda lakukan untuk mengamankan kunci rahasia Anda tidak akan menjadi solusi nyata. Jika pengembang dapat mendekompilasi aplikasi tidak ada cara untuk mengamankan kunci, menyembunyikan kunci hanya keamanan dengan ketidakjelasan dan begitu juga kode kebingungan. Masalah dengan pengamanan kunci rahasia adalah bahwa untuk mengamankannya Anda harus menggunakan kunci lain dan kunci itu juga harus diamankan. Pikirkan kunci yang disembunyikan di dalam kotak yang dikunci dengan kunci. Anda menempatkan kotak di dalam ruangan dan mengunci ruangan. Anda dibiarkan dengan kunci lain untuk mengamankan. Dan kunci itu masih akan dikodekan dalam aplikasi Anda.
Jadi, kecuali jika pengguna memasukkan PIN atau frasa, tidak ada cara untuk menyembunyikan kunci. Tetapi untuk melakukan itu Anda harus memiliki skema untuk mengelola PIN yang terjadi di luar jalur, yang berarti melalui saluran yang berbeda. Tentu tidak praktis untuk mengamankan kunci untuk layanan seperti Google API.
sumber
Posting lama, tapi masih cukup bagus. Saya pikir menyembunyikannya di perpustakaan .so akan menjadi besar, menggunakan NDK dan C ++ tentu saja. File .so dapat dilihat dalam hex editor, tetapi semoga berhasil mendekompilasi bahwa: P
sumber
Satu-satunya cara sebenarnya untuk merahasiakan ini adalah dengan menyimpannya di server Anda, dan minta aplikasi mengirim apa pun itu ke server, dan server berinteraksi dengan Dropbox. Dengan begitu Anda TIDAK PERNAH mendistribusikan kunci pribadi Anda dalam format apa pun.
sumber
Berdasarkan pengalaman pahit, dan setelah berkonsultasi dengan ahli IDA-Pro solusi terbaik adalah memindahkan bagian kunci dari kode ke dalam DLL / SharedObject, kemudian mengambilnya dari server dan memuat saat runtime.
Data sensitif harus disandikan karena sangat mudah untuk melakukan sesuatu seperti ini:
sumber