Phương pháp tốt nhất để tạo khóa API


89

Vì vậy, với rất nhiều dịch vụ khác nhau hiện nay, API Google, API Twitter, API Facebook, v.v.

Mỗi dịch vụ có một khóa API, như:

AIzaSyClzfrOzB818x55FASHvX4JuGQciR9lv7q

Tất cả các khóa có độ dài và ký tự khác nhau, tôi đang tự hỏi cách tốt nhất để tạo khóa API là gì?

Tôi không yêu cầu một ngôn ngữ cụ thể, chỉ là cách tiếp cận chung để tạo khóa, nếu chúng là mã hóa các chi tiết của ứng dụng người dùng, hoặc một hàm băm, hoặc một hàm băm của một chuỗi ngẫu nhiên, v.v. Chúng ta có nên lo lắng về thuật toán băm không (MSD, SHA1, bcrypt), v.v.?

Chỉnh sửa: Tôi đã nói chuyện với một vài người bạn (email / twitter) và họ khuyên họ chỉ nên sử dụng GUID với các dấu gạch ngang được loại bỏ.

Tuy nhiên, điều này có vẻ hơi khó hiểu với tôi, hy vọng sẽ có thêm một số ý tưởng.


Tôi đã trả lời chi tiết hơn ở đây .. tạo khóa và sử dụng nó làm xác thực hmac
Anshu Kumar

Câu trả lời:


58

Sử dụng trình tạo số ngẫu nhiên được thiết kế cho mật mã. Sau đó, cơ số 64 mã hóa số.

Đây là một ví dụ C #:

var key = new byte[32];
using (var generator = RandomNumberGenerator.Create())
    generator.GetBytes(key);
string apiKey = Convert.ToBase64String(key);

2
Điều này không an toàn lắm, kẻ tấn công có quyền truy cập vào cơ sở dữ liệu của bạn có thể lấy được khóa. Sẽ tốt hơn nếu tạo khóa dưới dạng băm của một thứ gì đó duy nhất cho người dùng (như muối), kết hợp với bí mật máy chủ.
James Wierzba

13
Lưu trữ khóa API được tạo ngẫu nhiên có các đặc điểm bảo mật giống như lưu trữ mật khẩu băm. Trong hầu hết các trường hợp, nó ổn. Như bạn đề xuất, có thể coi số được tạo ngẫu nhiên là muối và băm nó bằng bí mật máy chủ; tuy nhiên, bằng cách làm như vậy, bạn phải chịu chi phí băm cho mỗi lần xác thực. Cũng không có cách nào để làm mất hiệu lực của bí mật máy chủ mà không làm mất hiệu lực của tất cả các khóa API.
Edward Brey

Giải pháp tốt, nhưng bạn cần từ khóa var trước apiKey :) var apiKey = Convert.ToBase64String (key);
Dawid Ohia

@ JohnM2 Đúng. Tôi đã để nó kết thúc mở, vì apiKeycó thể được khai báo ở nơi khác. Tôi đã thêm loại cho rõ ràng.
Edward Brey

4
@JamesWierzba nếu cuộc tấn công đã có trong cơ sở dữ liệu của bạn, thì họ có quyền truy cập không an toàn vào API của bạn có lẽ là điều bạn ít quan tâm nhất ...
Jon Story

29

Các khóa API cần phải có các thuộc tính:

  • xác định duy nhất một người dùng API được ủy quyền - phần "khóa" của "khóa API"
  • xác thực người dùng đó - không thể đoán / giả mạo
  • có thể bị thu hồi nếu người dùng hoạt động sai - thông thường họ nhập khóa vào cơ sở dữ liệu có thể xóa bản ghi.

Thông thường, bạn sẽ có hàng nghìn hoặc hàng triệu khóa API chứ không phải hàng tỷ, vì vậy chúng không cần phải:

  • Lưu trữ thông tin đáng tin cậy về người dùng API vì thông tin đó có thể được lưu trữ trong cơ sở dữ liệu của bạn.

Do đó, một cách để tạo khóa API là lấy hai phần thông tin:

  1. một số sê-ri để đảm bảo tính duy nhất
  2. đủ các bit ngẫu nhiên để tạo ra chìa khóa

và ký chúng bằng bí mật riêng tư.

Bộ đếm đảm bảo rằng họ nhận dạng duy nhất người dùng và việc ký tên ngăn chặn việc giả mạo. Khả năng thu hồi yêu cầu kiểm tra xem khóa có còn hợp lệ trong cơ sở dữ liệu hay không trước khi thực hiện bất kỳ điều gì yêu cầu ủy quyền khóa API.

Trình tạo GUID tốt là một xấp xỉ khá tốt của bộ đếm tăng dần nếu bạn cần tạo khóa từ nhiều trung tâm dữ liệu hoặc không có cách phân phối tốt để gán số sê-ri.


hoặc băm của một chuỗi ngẫu nhiên

Băm không ngăn được giả mạo. Việc ký tên là điều đảm bảo rằng chìa khóa đến từ bạn.


3
Bước ký thuật toán của bạn có cần thiết không nếu khóa API do máy khách trình bày được kiểm tra dựa trên cơ sở dữ liệu gồm các khóa API đã được đăng ký trên máy chủ cung cấp API? Có vẻ như việc ký sẽ là thừa ở đây nếu máy chủ là máy chủ cung cấp khóa.
sappenin

3
@sappenin, Có. Nếu bạn lưu trữ một khóa không thể truy cập trên máy chủ, thì bạn không cần phải ngăn chặn việc giả mạo. Thường yêu cầu API được xử lý bởi bất kỳ một trong một trang trại máy - các máy chủ là một trong nhiều máy chủ. Việc kiểm tra chữ ký có thể được thực hiện trên bất kỳ máy nào mà không cần đến cơ sở dữ liệu, điều này có thể tránh được các điều kiện về chủng tộc trong một số trường hợp.
Mike Samuel

1
@MikeSamuel nếu khóa API đã được ký và bạn không thực hiện một vòng đến Cơ sở dữ liệu thì điều gì sẽ xảy ra khi khóa bị thu hồi nhưng vẫn được sử dụng để truy cập API?
Abhyudit Jain

@AbhyuditJain, Trong bất kỳ hệ thống phân tán nào, bạn cần một thứ tự thông báo nhất quán (thu hồi xảy ra trước khi sử dụng tiếp theo thông tin đăng nhập đã thu hồi) hoặc các cách khác để ràng buộc sự mơ hồ. Một số hệ thống không quay vòng theo mọi yêu cầu - nếu một nút lưu trữ thông tin rằng một khóa đã nằm trong cơ sở dữ liệu trong 10 phút, thì chỉ có 10 phút. cửa sổ mà kẻ tấn công có thể lạm dụng thông tin đăng nhập đã thu hồi. Tuy nhiên, có thể xảy ra nhầm lẫn: người dùng thu hồi thông tin xác thực, sau đó kiểm tra xem nó có bị thu hồi hay không và ngạc nhiên vì các phiên không dính khiến hai yêu cầu chuyển đến các nút khác nhau.
Mike Samuel

5

Tôi sử dụng UUID, được định dạng bằng chữ thường không có dấu gạch ngang.

Việc tạo ra rất dễ dàng vì hầu hết các ngôn ngữ đều có nó được tích hợp sẵn.

Các khóa API có thể bị xâm phạm, trong trường hợp đó, người dùng có thể muốn hủy khóa API của họ và tạo một khóa mới, vì vậy phương pháp tạo khóa của bạn phải có thể đáp ứng yêu cầu này.


15
Đừng cho rằng UUID khó đoán; chúng không nên được sử dụng làm khả năng bảo mật (UUID spec RFC4122 phần 6 ). Khóa API cần một số ngẫu nhiên an toàn, nhưng UUID không phải là không thể nhận biết được một cách an toàn .
Edward Brey

3
@EdwardBrey thì sao UUID uuid = UUID.randomUUID();trong Java? Bạn đang nói rằng ngẫu nhiên là không đủ tốt?
Vi

8
@MicroR Một UUID ngẫu nhiên chỉ được bảo mật nếu trình tạo số ngẫu nhiên được sử dụng để tạo ra nó an toàn về mặt mật mã và đủ 128 bit. Mặc dù UUID RFC không yêu cầu trình tạo số ngẫu nhiên an toàn, nhưng việc triển khai nhất định được sử dụng miễn phí. Trong trường hợp của randomUUID , tài liệu API chỉ rõ rằng nó sử dụng "trình tạo số ngẫu nhiên giả mạnh về mặt mật mã". Vì vậy, triển khai cụ thể đó được an toàn cho khóa API 128 bit.
Edward Brey

4

Nếu bạn muốn một khóa API chỉ có các ký tự chữ và số, bạn có thể sử dụng một biến thể của cách tiếp cận ngẫu nhiên cơ sở64 , chỉ sử dụng mã hóa cơ sở 62 để thay thế. Bộ mã hóa base-62 dựa trên điều này .

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();
}

1

Khóa API phải là một số giá trị ngẫu nhiên. Ngẫu nhiên đến mức không thể đoán trước được. Nó không được chứa bất kỳ chi tiết nào về người dùng hoặc tài khoản mà nó dành cho. Sử dụng UUID là một ý tưởng hay, nếu bạn chắc chắn rằng các ID được tạo là ngẫu nhiên.

Ví dụ, các phiên bản trước của Windows đã tạo ra các GUID có thể dự đoán được, nhưng đây là một câu chuyện cũ.


4
Windows 2000 chuyển sang GUID sử dụng số ngẫu nhiên . Tuy nhiên, không có gì đảm bảo rằng những con số ngẫu nhiên không thể dự đoán được. Ví dụ: nếu kẻ tấn công tạo một số khóa API cho chính mình, có thể xác định một số ngẫu nhiên trong tương lai được sử dụng để tạo khóa API của người dùng khác. Nói chung, đừng coi UUID là không thể đoán được một cách an toàn .
Edward Brey
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.