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 hmac
lib (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:
- 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.
- 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.
- 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.
- 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.
- 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.