Apa pendekatan terbaik untuk menghasilkan kunci API baru?

92

Jadi dengan banyak layanan berbeda saat ini, Google API, Twitter API, Facebook API, dll.

Setiap layanan memiliki kunci API, seperti:

AIzaSyClzfrOzB818x55FASHvX4JuGQciR9lv7q

Semua kunci memiliki panjang yang berbeda-beda dan karakter yang dikandungnya, saya bertanya-tanya apa pendekatan terbaik untuk menghasilkan kunci API?

Saya tidak meminta bahasa tertentu, hanya pendekatan umum untuk membuat kunci, apakah itu enkripsi detail aplikasi pengguna, atau hash, atau hash dari string acak, dll. Haruskah kita khawatir tentang algoritme hash (MSD, SHA1, bcrypt) dll?

Sunting: Saya telah berbicara dengan beberapa teman (email / twitter) dan mereka merekomendasikan hanya menggunakan GUID dengan tanda hubung dilucuti.

Ini tampaknya sedikit hacky bagi saya, berharap mendapatkan lebih banyak ide.

Phill
sumber
Saya telah menjawab lebih detail di sini .. menghasilkan kunci dan menggunakannya sebagai auth hmac
Anshu Kumar

Jawaban:

59

Gunakan generator nomor acak yang dirancang untuk kriptografi. Kemudian base-64 menyandikan nomor tersebut.

Ini adalah contoh C #:

var key = new byte[32];
using (var generator = RandomNumberGenerator.Create())
    generator.GetBytes(key);
string apiKey = Convert.ToBase64String(key);
Edward Brey
sumber
2
Ini sangat tidak aman, penyerang yang memperoleh akses ke database Anda dapat memperoleh kunci tersebut. Akan lebih baik untuk menghasilkan kunci sebagai hash dari sesuatu yang unik untuk pengguna (seperti garam), dikombinasikan dengan rahasia server.
James Wierzba
14
Menyimpan kunci API yang dibuat secara acak memiliki karakteristik keamanan yang sama seperti menyimpan sandi berciri. Dalam banyak kasus, tidak masalah. Seperti yang Anda sarankan, adalah mungkin untuk menganggap nomor yang dibuat secara acak sebagai salt dan hashing dengan rahasia server; namun, dengan melakukan itu, Anda dikenakan overhead hash pada setiap validasi. Juga tidak ada cara untuk membuat rahasia server tidak valid tanpa membuat semua kunci API tidak valid.
Edward Brey
Solusi bagus, tetapi Anda memerlukan kata kunci var sebelum apiKey mungkin :) var apiKey = Convert.ToBase64String (key);
Dawid Ohia
@ John2 Benar. Saya telah membiarkannya terbuka, karena apiKeydapat dideklarasikan di tempat lain. Saya menambahkan tipe untuk kejelasan.
Edward Brey
4
@JamesWierzba jika yang diserang sudah ada di database Anda, maka mereka yang memiliki akses tidak aman ke API Anda mungkin yang paling tidak menjadi perhatian Anda ...
Jon Story
30

Kunci API harus memiliki properti yang:

  • mengidentifikasi secara unik pengguna API resmi - bagian "kunci" dari "kunci API"
  • mengotentikasi pengguna itu - tidak dapat ditebak / dipalsukan
  • dapat dicabut jika pengguna berperilaku buruk - biasanya mereka memasukkan ke dalam database yang dapat memiliki record yang dihapus.

Biasanya Anda akan memiliki ribuan atau jutaan kunci API, bukan miliaran, jadi mereka tidak perlu:

  • Simpan informasi tentang pengguna API dengan andal karena itu dapat disimpan di database Anda.

Karena itu, salah satu cara untuk menghasilkan kunci API adalah dengan mengambil dua informasi:

  1. nomor seri untuk menjamin keunikan
  2. bit acak yang cukup untuk mengeluarkan kunci

dan menandatanganinya menggunakan rahasia pribadi.

Penghitung menjamin bahwa mereka secara unik mengidentifikasi pengguna, dan penandatanganan mencegah pemalsuan. Pencabutan memerlukan pemeriksaan bahwa kunci tersebut masih valid dalam database sebelum melakukan apa pun yang memerlukan otorisasi kunci API.

Generator GUID yang baik adalah perkiraan yang cukup bagus dari penghitung tambahan jika Anda perlu menghasilkan kunci dari beberapa pusat data atau tidak memiliki cara terdistribusi yang baik untuk menetapkan nomor seri.


atau hash dari string acak

Hashing tidak mencegah pemalsuan. Penandatanganan adalah apa yang menjamin bahwa kunci tersebut berasal dari Anda.

Mike Samuel
sumber
3
Apakah langkah penandatanganan algoritme Anda diperlukan jika kunci API yang disajikan oleh klien diperiksa dengan database kunci API yang sudah terdaftar di server yang menyediakan API? Sepertinya penandatanganan akan menjadi berlebihan di sini jika server adalah yang menyediakan kunci.
sappenin
3
@enin, Ya. Jika Anda menyimpan kunci yang tidak dapat diubah di server, Anda tidak perlu mencegah pemalsuan. Seringkali permintaan API ditangani oleh salah satu dari peternakan mesin - yang server adalah salah satu dari banyak server. Pemeriksaan tanda tangan dapat dilakukan pada mesin apa pun tanpa bolak-balik ke database yang dapat menghindari kondisi balapan dalam beberapa kasus.
Mike Samuel
1
@MikeSamuel Jika kunci API ditandatangani dan Anda tidak melakukan perjalanan bolak-balik ke Database, lalu apa yang terjadi saat kunci dicabut tetapi masih digunakan untuk mengakses API?
Abhyudit Jain
@AbhyuditJain, Dalam sistem terdistribusi apa pun, Anda memerlukan urutan pesan yang konsisten (pembatalan terjadi-sebelum penggunaan kredensial yang dicabut berikutnya) atau cara lain untuk mengikat ambiguitas. Beberapa sistem tidak melakukan round-trip pada setiap permintaan - jika node menyimpan fakta bahwa kunci berada di database selama 10 menit, hanya ada 10 menit. jendela tempat penyerang dapat menyalahgunakan kredensial yang dicabut. Namun, kemungkinan kebingungan dapat terjadi: pengguna mencabut kredensial, lalu menguji bahwa kredensial tersebut dicabut, dan terkejut karena sesi non-sticky menyebabkan dua permintaan untuk pergi ke node yang berbeda.
Mike Samuel
5

Saya menggunakan UUID, diformat dalam huruf kecil tanpa tanda hubung.

Pembuatannya mudah karena sebagian besar bahasa memiliki bawaan.

Kunci API dapat disusupi, dalam hal ini pengguna mungkin ingin membatalkan kunci API mereka dan membuat yang baru, sehingga metode pembuatan kunci Anda harus dapat memenuhi persyaratan ini.

Adam Ralph
sumber
15
Jangan berasumsi bahwa UUID sulit ditebak; mereka tidak boleh digunakan sebagai kemampuan keamanan (UUID spec RFC4122 bagian 6 ). Kunci API membutuhkan nomor acak yang aman, tetapi UUID tidak dapat diabaikan dengan aman .
Edward Brey
3
@EdwardBrey bagaimana dengan UUID uuid = UUID.randomUUID();di Jawa? Apakah Anda mengatakan bahwa acak tidak cukup baik?
Mikro
8
@MicroR UUID acak aman hanya jika generator nomor acak yang digunakan untuk membuatnya aman secara kriptografis dan 128 bit sudah cukup. Meskipun UUID RFC tidak memerlukan pembuat nomor acak yang aman, implementasi tertentu dapat digunakan secara gratis. Dalam kasus randomUUID , dokumen API secara khusus menyatakan bahwa API menggunakan "pembuat nomor acak semu yang kuat secara kriptografis". Sehingga implementasi tertentu aman untuk kunci API 128-bit.
Edward Brey
4

Jika Anda menginginkan kunci API dengan hanya karakter alfanumerik, Anda dapat menggunakan varian dari pendekatan acak base64 , hanya menggunakan enkode base-62 saja. Encoder base-62 didasarkan pada ini .

public static string CreateApiKey()
{
    var bytes = new byte[256 / 8];
    using (var random = RandomNumberGenerator.Create())
        random.GetBytes(bytes);
    return ToBase62String(bytes);
}

static string ToBase62String(byte[] toConvert)
{
    const string alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    BigInteger dividend = new BigInteger(toConvert);
    var builder = new StringBuilder();
    while (dividend != 0) {
        dividend = BigInteger.DivRem(dividend, alphabet.Length, out BigInteger remainder);
        builder.Insert(0, alphabet[Math.Abs(((int)remainder))]);
    }
    return builder.ToString();
}
Edward Brey
sumber
1

Kunci API harus berupa nilai acak. Cukup acak sehingga tidak bisa diprediksi. Ini tidak boleh berisi detail pengguna atau akun apa pun. Menggunakan UUID adalah ide yang bagus, jika Anda yakin bahwa ID yang dibuat acak.

Versi Windows sebelumnya menghasilkan GUID yang dapat diprediksi, misalnya, tetapi ini adalah cerita lama.

Dave Van den Eynde
sumber
4
Windows 2000 beralih ke GUID menggunakan nomor acak . Namun, tidak ada jaminan bahwa angka acak tidak dapat diprediksi. Misalnya, jika penyerang membuat beberapa kunci API untuk dirinya sendiri, dimungkinkan untuk menentukan nomor acak di masa mendatang yang digunakan untuk membuat kunci API pengguna lain. Secara umum, jangan anggap UUID tidak dapat dipercaya secara aman .
Edward Brey