Mengapa menggunakan kunci dan rahasia API?

93

Saya menemukan banyak API yang memberi pengguna kunci API dan rahasia . Tapi pertanyaan saya adalah: apa perbedaan keduanya?

Di mata saya, satu kunci sudah cukup. Katakanlah saya memiliki kunci dan hanya saya dan server yang mengetahuinya. Saya membuat hash HMAC dengan kunci ini dan melakukan panggilan API. Di server, kami membuat hash HMAC lagi dan membandingkannya dengan hash yang dikirim. Jika sama, panggilan diautentikasi.

Jadi mengapa menggunakan dua kunci?

Edit: atau apakah kunci API itu digunakan untuk mencari rahasia API?

EsTeGe
sumber

Jawaban:

46

Kriptografi kunci rahasia bergantung pada penggunaan kunci yang sama untuk menyandikan dan kemudian mendekode pesan. Jadi, hanya mereka yang mengetahui "rahasia" yang dapat membaca pesan tersebut.

Keamanan RSA didasarkan pada 2 kunci yang cocok. Ada kunci publik untuk setiap pengguna, dan semua orang bisa (harus) mengetahuinya. Ada juga kunci pribadi yang hanya diketahui oleh pengguna. Pesan yang dienkripsi oleh kunci publik hanya dapat didekripsi dengan kunci privat, dan sebaliknya.

Jadi, jika saya ingin mengirimi Anda pesan yang hanya dapat dibaca oleh Anda, saya mendapatkan (dari jaringan) kunci publik Anda, mengenkripsi pesan dengan kunci itu dan Anda adalah satu-satunya orang yang dapat mendekripsinya.

Atau, jika saya ingin membuktikan kepada Anda bahwa saya telah mengirim pesan, saya dapat mengenkripsi pesan tersebut dengan kunci pribadi saya, memberi tahu Anda (dalam teks terbuka atau dalam pesan lain) bagaimana pesan itu dienkripsi. Kemudian Anda dapat mendekripsi pesan dengan kunci publik saya, dan jika dapat dibaca, Anda tahu itu berasal dari saya.

Bentuk enkripsi ini cukup intensif di komputer, jadi yang terkadang dilakukan adalah mengenkripsi "kunci rahasia" satu kali dengan teknologi RSA, kemudian mengenkripsi sisa pesan dengan kunci rahasia, lalu mengenkripsi tanda tangan saya dengan cara kedua. Anda kemudian membalikkan proses ini jadi jika pesan dan tanda tangannya dapat dibaca, Anda dan hanya Anda yang dapat membacanya dan Anda yakin bahwa saya mengirim pesan tersebut.

ATAU

Anda dapat mengunjungi tautan ini untuk penjelasan lebih detail.

Bagaimana cara kerja Kunci API dan Kunci Rahasia?

SALMAN
sumber
9
Jawaban bagus, tetapi ketika saya menggunakan rahasia dan kunci API dengan Facebook atau Gmail dll, saya tidak perlu mengenkripsi atau mencirikan apa pun. Dalam kasus tersebut, apa gunanya rahasia dan kunci API?
Quintonn
2
Menggunakan Facebook sebagai contoh, ada dua skenario Anda akan menggunakan app_secret. Yang pertama tidak membutuhkan hashing. Ini terutama digunakan untuk mencegah url pengalihan Anda dibajak. Setelah pengguna masuk dan memberikan akses aplikasi Anda jika facebook mengirim token akses langsung ke url pengalihan, Anda tidak akan dapat memverifikasi apakah token akses itu berasal dari Facebook. Saya dapat memposting token akses saya sendiri ke url pengalihan Anda dan menjalankan tindakan facebook yang akan datang dari api Anda. Sebaliknya facebook mengirimkan kode ke url redirect. Api kemudian menukar kode untuk token akses yang sebenarnya.
Ryan Thomas
2
Selama bagian terakhir, menukar kode untuk token akses yang sebenarnya, facebook mengharapkan api Anda untuk memverifikasi identitasnya dengan tanda tangan. Dalam skenario ini, mereka tidak memerlukan kriptografi kunci publik untuk penandatanganan, mereka hanya mempercayai Anda untuk merahasiakan aplikasi Anda dan menggunakannya sebagai tanda tangan Anda. Ini selalu tampak konyol bagi saya untuk tidak melanjutkan dan menggunakan fungsi satu arah untuk menghasilkan tanda tangan tetapi saya kira mereka memiliki alasan seperti kinerja untuk menyelesaikan penggunaan langsung rahasia aplikasi.
Ryan Thomas
Dalam kasus penggunaan kedua, Anda menggunakan hashing kriptografi. Setelah Anda memiliki access_token yang sebenarnya untuk mulai berinteraksi dengan facebook, Anda mungkin menginginkan keamanan ekstra untuk mencegah aplikasi Anda ditiru. Di konsol aplikasi Facebook Anda dapat mengaktifkan fitur yang mengharuskan setiap permintaan api facebook dari aplikasi Anda untuk menyertakan tanda tangan Anda selain token akses. Saya hanya menebak-nebak motif mereka, tetapi saya pikir pada saat ini mereka tidak ingin Anda berulang kali mengirimkan app_secret sebagai tanda tangan pada setiap permintaan. Semakin banyak Anda mengirimnya, semakin besar peluang app_secret disusupi.
Ryan Thomas
1
Saya kira karena Anda telah memilih fitur keamanan ekstra ini, Anda juga telah membuat keputusan untuk memungkinkan overhead kinerja ekstra Facebook memverifikasi tanda tangan Anda dengan panggilan hash kriptografi di ujungnya. Bagaimanapun dalam skenario ini Anda meneruskan dua nilai dengan permintaan api Facebook Anda. Access_token dan nilai bernama appsecret_proof yang berfungsi sebagai tanda tangan Anda. Bukti rahasia aplikasi dihasilkan oleh hashing kriptografik dari access_token menggunakan app_secret sebagai kuncinya.
Ryan Thomas
55

Anda membutuhkan dua kunci terpisah, satu yang memberi tahu mereka siapa Anda, dan satu lagi yang membuktikan bahwa Anda adalah yang Anda katakan .

"Kunci" adalah ID pengguna Anda, dan "rahasia" adalah sandi Anda. Mereka hanya menggunakan istilah "kunci" dan "rahasia" karena begitulah cara mereka menerapkannya.

Marcus Adams
sumber
1
Dan bagaimana jika Anda berkomunikasi melalui https? Lalu apa gunanya mengenkripsi pesan Anda dengan beberapa kunci rahasia?
kamuniaft
6
Intinya adalah selalu mengurangi risiko. Jika komunikasi https terganggu, maka penyerang yang dapat membaca permintaan Anda tidak akan dapat memalsukan permintaan baru. Jika API Anda adalah untuk peringkat gambar kucing, bukan masalah besar, jika itu adalah API pembayaran Anda lebih baik memiliki beberapa lapisan keamanan :)
Yall
Saya kira tujuannya adalah dua kunci yang terpisah, adalah karena pengguna yang berbeda dari aplikasi klien tunggal dapat memiliki rahasia yang berbeda, sebaliknya jika mereka semua memiliki rahasia yang sama maka memiliki kunci tidak berguna. Baik?
Madu
Mengapa API ini tidak menggunakan Bearer:otentikasi untuk itu? Anda akan memiliki ID dan pwd di sana.
Stefan Haberl
7

Jawaban sederhana, jika saya memahaminya dengan benar ...

Jika Anda menggunakan kunci API Anda untuk enkripsi, bagaimana layanan tahu siapa yang menghubungi mereka? Bagaimana mereka akan mendekripsi pesan itu?

Anda menggunakan kunci API untuk menyatakan siapa Anda, inilah yang Anda kirimkan dalam teks biasa. Kunci RAHASIA tidak Anda kirim ke siapa pun. Anda cukup menggunakannya untuk enkripsi. Kemudian Anda mengirim pesan terenkripsi. Anda tidak mengirim kunci yang digunakan untuk enkripsi, itu akan menggagalkan tujuan.

kuno
sumber
Anda lakukan. Anda mengirim kunci api ke server. Jadi, ini berarti Anda memberikan nilai itu kepada siapa saja yang mungkin mengganggu komunikasi Anda dengan server.
ancajic
Hampir setiap API yang pernah saya lihat meminta Anda mengirim kunci dan rahasianya ke server. Koneksi ke server dienkripsi dengan tingkat keamanan yang sama secara teoritis. Tapi saya tidak pernah memberikannya kepada orang lain selain server.
sudo
Saya tidak pernah melihat pengiriman secretdalam bentuk teks biasa. Bisakah Anda memberi saya tautan? Apa yang saya lihat digunakan secretuntuk mengenkripsi beberapa data. Dan bersama dengan data yang dienkripsi, pengiriman apiKeysehingga server tahu cara mendekripsi data.
ancajic
twilio.com/docs/sms/tutorials/… dan nexmo.github.io/Quickstarts/sms/send adalah contoh yang saya lihat yang mendorong saya untuk mencari di StackOverflow.
sudo
Twilio tidak benar-benar menggunakan istilah ini. Tapi Nexmo pasti adalah ... tapi, setelah sekilas, sepertinya mereka hanya memanggil data secretdan apiKeydan apa yang mereka benar-benar lakukan adalah usernamedan password. Yang benar-benar berbeda ...
ancajic
3

Ada jawaban yang menjelaskan apa rahasia dan kunci (publik) itu. Ini adalah pasangan kunci publik-pribadi yang mereka beri nama yang membingungkan. Tetapi tidak ada yang mengatakan mengapa API membutuhkan keduanya, dan banyak API hanya memberi Anda satu rahasia! Saya juga belum pernah melihat dokumen API mana pun yang menjelaskan mengapa mereka memiliki dua kunci, jadi yang terbaik yang bisa saya lakukan adalah berspekulasi ...

Yang terbaik adalah meletakkan kunci publik Anda dalam permintaan Anda dan menandatangani permintaan secara lokal dengan kunci pribadi Anda; mengirim apa pun lagi seharusnya tidak diperlukan. Tetapi beberapa lolos hanya dengan memiliki rahasia dalam permintaan. Oke, API apa pun yang bagus akan menggunakan beberapa keamanan transportasi seperti TLS (biasanya melalui HTTPS). Tapi Anda masih mengekspos kunci pribadi Anda ke server seperti itu, meningkatkan risiko mereka entah bagaimana salah menanganinya (lihat: GitHub dan bug pencatatan kata sandi Twitter baru-baru ini ditemukan). Dan HTTPS secara teoritis sama amannya, tetapi selalu ada kekurangan implementasi di luar sana.

Tetapi banyak - sebenarnya kebanyakan - API meminta Anda mengirim kedua kunci dalam permintaan karena itu lebih mudah daripada membuat orang membuat tanda tangan mereka sendiri; tidak dapat memiliki contoh cURL murni sebaliknya! Dalam hal ini, tidak ada gunanya memisahkan mereka. Saya kira kunci terpisah hanya untuk jika mereka mengubah API nanti untuk memanfaatkannya. Atau beberapa memiliki pustaka klien yang mungkin melakukannya dengan cara yang lebih aman.

sudo
sumber
1

Satu hal yang tidak saya lihat disebutkan di sini, meskipun ini merupakan perpanjangan dari jawaban Marcus Adams, adalah bahwa Anda tidak boleh menggunakan satu pun informasi untuk mengidentifikasi dan mengautentikasi pengguna jika ada kemungkinan serangan waktu , yang dapat gunakan perbedaan waktu respons untuk menebak seberapa jauh perbandingan string.

Jika Anda menggunakan sistem yang menggunakan "kunci" untuk mencari pengguna atau kredensial, informasi tersebut dapat ditebak secara bertahap dari waktu ke waktu dengan mengirimkan ribuan permintaan dan memeriksa waktu yang diperlukan database Anda untuk menemukan (atau tidak temukan) sebuah catatan. Hal ini terutama berlaku jika "kunci" disimpan dalam teks biasa, bukan dalam hash kunci satu arah. Anda ingin menyimpan kunci pengguna dalam teks biasa atau dienkripsi secara simetris jika Anda perlu menampilkan kembali kunci tersebut kepada pengguna.

Dengan memiliki informasi kedua, atau "rahasia", pertama-tama Anda dapat mencari pengguna atau kredensial menggunakan "kunci", yang mungkin rentan terhadap serangan waktu, kemudian menggunakan fungsi perbandingan aman waktu untuk memeriksa nilai rahasia".

Berikut adalah implementasi Python untuk fungsi itu:

https://github.com/python/cpython/blob/cd8295ff758891f21084a6a5ad3403d35dda38f7/Modules/_operator.c#L727

Dan itu diekspos di hmaclib (dan mungkin lainnya):

https://docs.python.org/3/library/hmac.html#hmac.compare_digest


Satu hal yang perlu diperhatikan di sini adalah saya tidak berpikir bahwa serangan semacam ini akan bekerja pada nilai yang di-hash atau dienkripsi sebelum pencarian, karena nilai yang dibandingkan berubah secara acak setiap kali karakter dalam string input berubah. Saya menemukan penjelasan yang bagus tentang ini di sini .

Solusi untuk menyimpan kunci API selanjutnya adalah:

  1. Gunakan kunci dan rahasia terpisah, gunakan kunci tersebut untuk mencari catatan, dan gunakan perbandingan waktu-aman untuk memeriksa rahasia. Ini memungkinkan Anda untuk menunjukkan kunci dan rahasia kepada pengguna lagi.
  2. Gunakan kunci dan rahasia terpisah, gunakan enkripsi simetris dan deterministik pada rahasia, dan lakukan perbandingan normal rahasia terenkripsi. Hal ini memungkinkan Anda untuk menampilkan kembali kunci dan rahasia tersebut kepada pengguna, dan dapat menyelamatkan Anda dari keharusan menerapkan perbandingan yang tepat waktu.
  3. Gunakan kunci dan rahasia terpisah, tampilkan rahasia, hash dan simpan, kemudian lakukan perbandingan normal dari rahasia yang di-hash. Ini menghilangkan keharusan untuk menggunakan enkripsi dua arah, dan memiliki manfaat tambahan untuk menjaga keamanan rahasia Anda jika sistem disusupi. Ada sisi negatifnya bahwa Anda tidak dapat menunjukkan rahasia itu lagi kepada pengguna.
  4. Gunakan kunci tunggal , tunjukkan kepada pengguna sekali, lakukan hash, lalu lakukan pencarian normal untuk kunci yang di-hash atau dienkripsi. Ini menggunakan kunci tunggal, tetapi tidak dapat ditampilkan lagi kepada pengguna. Memiliki manfaat untuk menjaga keamanan kunci jika sistem dikompromikan.
  5. Gunakan satu kunci , tunjukkan satu kali kepada pengguna, enkripsi, dan lakukan pencarian normal rahasia terenkripsi. Dapat ditampilkan kepada pengguna lagi, tetapi dengan mengorbankan kunci yang rentan jika sistem mereka disusupi.

Dari jumlah tersebut, saya pikir 3 adalah keseimbangan terbaik antara keamanan dan kenyamanan. Saya telah melihat ini diterapkan di banyak situs web ketika mendapatkan kunci yang dikeluarkan.

Juga, saya mengundang pakar keamanan yang sebenarnya untuk mengkritik jawaban ini. Saya hanya ingin mengeluarkan ini sebagai poin diskusi lain.

kbuilds
sumber