Tại sao sử dụng khóa API và bí mật?


93

Tôi đã xem qua nhiều API cung cấp cho người dùng cả khóa API và bí mật . Nhưng câu hỏi của tôi là: sự khác biệt giữa cả hai là gì?

Trong mắt tôi, một chìa khóa có thể là đủ. Giả sử tôi có một chìa khóa và chỉ tôi và máy chủ biết nó. Tôi tạo băm HMAC bằng khóa này và thực hiện lệnh gọi API. Trên máy chủ, chúng tôi tạo lại băm HMAC và so sánh nó với băm đã gửi. Nếu nó giống nhau, cuộc gọi đã được xác thực.

Vậy tại sao lại sử dụng hai chìa khóa?

Chỉnh sửa: hay khóa API đó được sử dụng để tra cứu bí mật API?


Câu trả lời:


46

Mật mã khóa bí mật dựa vào việc sử dụng cùng một khóa để mã hóa và sau đó giải mã một thông điệp. Như vậy, chỉ những người biết “bí mật” mới có thể đọc được tin nhắn.

Bảo mật RSA dựa trên 2 khóa phù hợp. Có một khóa công khai cho mỗi người dùng và mọi người có thể (nên) biết nó. Ngoài ra còn có một khóa riêng tư mà chỉ người dùng mới biết. Một tin nhắn được mã hóa bằng khóa công khai chỉ có thể được giải mã bằng khóa riêng và ngược lại.

Vì vậy, nếu tôi muốn gửi cho bạn một tin nhắn mà chỉ bạn mới có thể đọc, tôi sẽ lấy (từ mạng) khóa công khai của bạn, mã hóa tin nhắn bằng khóa đó và bạn là người duy nhất có thể giải mã nó.

Hoặc, nếu tôi muốn chứng minh với bạn rằng tôi đã gửi một tin nhắn, tôi có thể mã hóa tin nhắn bằng khóa cá nhân của mình, cho bạn biết (trong văn bản đang mở hoặc trong một tin nhắn khác) nó đã được mã hóa như thế nào. Sau đó, bạn có thể giải mã tin nhắn bằng khóa công khai của tôi, và nếu nó có thể đọc được, bạn biết nó đến từ tôi.

Hình thức mã hóa này khá chuyên sâu về máy tính, vì vậy những gì đôi khi được thực hiện là mã hóa "khóa bí mật" dùng một lần bằng công nghệ RSA, sau đó mã hóa phần còn lại của thư bằng khóa bí mật, sau đó mã hóa chữ ký của tôi theo cách thứ hai. Sau đó, bạn đảo ngược quá trình này để nếu tin nhắn và chữ ký có thể đọc được, bạn và chỉ bạn mới có thể đọc được và bạn được đảm bảo rằng tôi đã gửi tin nhắn.

HOẶC LÀ

bạn có thể truy cập liên kết này để giải thích chi tiết hơn.

Khóa API và Khóa bí mật hoạt động như thế nào?


9
Câu trả lời hay, nhưng khi tôi sử dụng khóa và bí mật API với Facebook hoặc Gmail, v.v., tôi không cần phải mã hóa hay băm bất cứ thứ gì. Trong những trường hợp đó, điểm bí mật và khóa API là gì?
Quintonn

2
Sử dụng Facebook làm ví dụ, có hai trường hợp bạn sẽ sử dụng app_secret. Cái đầu tiên không yêu cầu băm. Nó chủ yếu được sử dụng để ngăn chặn url chuyển hướng của bạn bị tấn công. Sau khi người dùng đăng nhập và cấp quyền truy cập ứng dụng của bạn nếu facebook gửi mã thông báo truy cập trực tiếp đến url chuyển hướng, bạn sẽ không có cách nào xác minh xem mã thông báo truy cập có phải từ Facebook hay không. Tôi có thể đăng mã thông báo truy cập của riêng tôi lên url chuyển hướng của bạn và thực hiện các hành động facebook sẽ đến từ api của bạn. Thay vào đó, facebook sẽ gửi một mã đến url chuyển hướng. Sau đó api trao đổi mã cho mã thông báo truy cập thực tế.
Ryan Thomas

2
Trong phần sau, trao đổi mã lấy mã thông báo truy cập thực tế, facebook hy vọng api của bạn xác minh danh tính của nó bằng chữ ký. Trong trường hợp này, họ không yêu cầu mật mã khóa công khai để ký, họ chỉ tin tưởng bạn giữ bí mật thực sự cho ứng dụng của bạn và sử dụng nó làm chữ ký của bạn. Điều này luôn luôn có vẻ ngớ ngẩn đối với tôi khi không tiếp tục và sử dụng một hàm một chiều để tạo chữ ký nhưng tôi cho rằng họ có những lý do như hiệu suất để giải quyết việc sử dụng trực tiếp bí mật ứng dụng.
Ryan Thomas

Trong trường hợp sử dụng thứ hai, bạn sử dụng băm mật mã. Sau khi bạn có access_token thực sự để bắt đầu tương tác với facebook, bạn có thể muốn bảo mật thêm để ngăn ứng dụng của bạn bị mạo danh. Trong bảng điều khiển ứng dụng Facebook, bạn có thể bật một tính năng yêu cầu mọi yêu cầu api facebook từ ứng dụng của bạn phải bao gồm chữ ký của bạn ngoài mã thông báo truy cập. Tôi chỉ đoán động cơ của họ nhưng tôi nghĩ tại thời điểm này, họ không muốn bạn liên tục gửi app_secret làm chữ ký cho mọi yêu cầu. Bạn gửi càng nhiều thì khả năng app_secret bị xâm phạm càng lớn.
Ryan Thomas

1
Tôi cho rằng vì bạn đã chọn tham gia vào tính năng bảo mật bổ sung này, bạn cũng đã đưa ra quyết định để cho phép Facebook tăng hiệu suất xác minh chữ ký của bạn bằng một lệnh gọi băm mật mã ở cuối của họ. Dù sao trong trường hợp này, bạn chuyển hai giá trị với các yêu cầu api Facebook của mình. Access_token và một giá trị có tên appsecret_proof dùng làm chữ ký của bạn. Bằng chứng bí mật của ứng dụng được tạo bằng cách băm mật mã của access_token bằng cách sử dụng app_secret làm khóa.
Ryan Thomas

55

Bạn cần hai chìa khóa riêng biệt, một chìa khóa cho họ biết bạn là ai và một chìa khóa còn lại chứng minh bạn là chính mình .

"Khóa" là ID người dùng của bạn và "bí mật" là mật khẩu của bạn. Họ chỉ sử dụng các thuật ngữ "khóa" và "bí mật" vì đó là cách họ đã triển khai nó.


1
Và điều gì sẽ xảy ra nếu bạn đang giao tiếp qua https? Vậy thì mục đích của việc mã hóa tin nhắn của bạn bằng một khóa bí mật nào đó là gì?
kamuniaft

6
Vấn đề là luôn giảm thiểu rủi ro. Nếu giao tiếp https bị xâm phạm, thì kẻ tấn công có thể đọc yêu cầu của bạn sẽ không thể giả mạo yêu cầu mới. Nếu API của bạn sắp xếp hạng hình ảnh về mèo, không có vấn đề gì lớn, nếu đó là API thanh toán, tốt hơn bạn nên có nhiều lớp bảo mật :)
Yall

Tôi cho rằng mục đích của nó là hai khóa riêng biệt, là vì những người dùng khác nhau của một ứng dụng khách có thể có những bí mật khác nhau, nếu không, nếu tất cả họ đều có cùng một bí mật thì việc có một khóa sẽ không hữu ích. Đúng?
Honey,

Tại sao các API này không sử dụng Bearer:xác thực cho điều đó? Bạn sẽ có một ID và một mật khẩu ở đó.
Stefan Haberl

7

Câu trả lời đơn giản, nếu tôi hiểu nó một cách chính xác ...

Nếu bạn sử dụng khóa API của mình để mã hóa, làm cách nào dịch vụ biết được ai đang liên hệ với họ? Họ sẽ giải mã thông điệp đó như thế nào?

Bạn sử dụng khóa API để cho biết bạn là ai, đây là những gì bạn đang gửi dưới dạng văn bản thuần túy. Chìa khóa BÍ MẬT bạn không gửi cho bất kỳ ai. Bạn chỉ cần sử dụng nó để mã hóa. Sau đó, bạn gửi tin nhắn được mã hóa. Bạn không gửi khóa đã được sử dụng để mã hóa, điều đó sẽ không đạt được mục đích.


Bạn làm. Bạn gửi khóa api đến máy chủ. Vì vậy, điều này có nghĩa là bạn đang trao giá trị đó cho bất kỳ ai có thể đang chặn giao tiếp của bạn với máy chủ.
ancajic

Hầu hết mọi API tôi đã thấy đều có bạn gửi cả khóa và bí mật đến máy chủ. Kết nối đến máy chủ được mã hóa với mức độ bảo mật về mặt lý thuyết. Nhưng tôi không bao giờ cho bất kỳ ai khác ngoài máy chủ.
sudo

Tôi chưa bao giờ thấy gửi secretbằng văn bản thuần túy. Bạn có thể cho tôi một liên kết? Những gì tôi thấy đang sử dụng secretđể mã hóa một số dữ liệu. Và cùng với dữ liệu được mã hóa, gửi apiKeyđể máy chủ biết cách giải mã dữ liệu.
ancajic

twilio.com/docs/sms/tutorials/…nexmo.github.io/Quickstarts/sms/send là các ví dụ tôi thấy đã nhắc tôi tìm kiếm trên StackOverflow.
sudo

Twilio không chính xác sử dụng các thuật ngữ này. Nhưng Nexmo chắc chắn là ... Nhưng, sau khi lướt qua, nó có vẻ như họ chỉ gọi dữ liệu secretapiKeyvà những gì họ thực sự làm là usernamepassword. Đó là điều hoàn toàn khác ...
ancajic

3

Có câu trả lời giải thích khóa bí mật và khóa (công khai) là gì. Đó là một cặp khóa công khai-riêng tư mà họ đặt tên khó hiểu. Nhưng không ai nói tại sao các API yêu cầu cả hai và nhiều API chỉ cung cấp cho bạn một bí mật! Tôi cũng chưa bao giờ thấy bất kỳ tài liệu nào của API giải thích lý do tại sao chúng có hai khóa, vì vậy tốt nhất tôi có thể làm là suy đoán ...

Tốt nhất là chỉ đặt khóa công khai của bạn trong yêu cầu của bạn và ký yêu cầu cục bộ bằng khóa riêng của bạn; không cần gửi thêm gì nữa. Nhưng một số thoát khỏi chỉ cần có bí mật trong yêu cầu. Ok, bất kỳ API tốt nào cũng sẽ sử dụng một số bảo mật truyền tải như TLS (thường qua HTTPS). Nhưng bạn vẫn để lộ khóa riêng tư của mình cho máy chủ theo cách đó, làm tăng nguy cơ họ xử lý sai bằng cách nào đó (xem: Lỗi ghi mật khẩu của GitHub và Twitter được phát hiện gần đây). Và về mặt lý thuyết, HTTPS cũng an toàn như vậy, nhưng vẫn luôn tồn tại những sai sót khi triển khai.

Nhưng nhiều người - thực tế là có vẻ như hầu hết - các API cho phép bạn gửi cả hai khóa trong các yêu cầu vì điều đó dễ dàng hơn so với việc khiến mọi người tự tạo chữ ký; không thể có các ví dụ cURL thuần túy nếu không! Trong trường hợp đó, thật vô nghĩa nếu chúng tách rời nhau. Tôi đoán các khóa riêng biệt chỉ dành cho trường hợp sau này họ thay đổi API để tận dụng chúng. Hoặc một số có thư viện máy khách có thể làm điều đó theo cách an toàn hơn.


1

Một điều mà tôi không thấy được đề cập ở đây, mặc dù nó là phần mở rộng cho câu trả lời của Marcus Adams, đó là bạn không nên sử dụng một phần thông tin để vừa xác định vừa xác thực người dùng nếu có khả năng xảy ra các cuộc tấn công định thời , điều này có thể sử dụng sự khác biệt về thời gian phản hồi để đoán xem so sánh chuỗi đã đi được bao xa.

Nếu bạn đang sử dụng một hệ thống sử dụng "khóa" để tra cứu người dùng hoặc thông tin đăng nhập, thì phần thông tin đó có thể được đoán dần dần theo thời gian bằng cách gửi hàng nghìn yêu cầu và kiểm tra thời gian cơ sở dữ liệu của bạn có thể tìm thấy (hay không tìm) một bản ghi. Điều này đặc biệt đúng nếu "khóa" được lưu trữ trong văn bản rõ ràng thay vì băm một chiều của khóa. Bạn muốn lưu trữ các khóa của người dùng ở dạng văn bản rõ ràng hoặc được mã hóa đối xứng nếu bạn cần có thể hiển thị lại khóa cho người dùng.

Bằng cách có phần thông tin thứ hai hoặc "bí mật", trước tiên bạn có thể tra cứu người dùng hoặc thông tin đăng nhập bằng cách sử dụng "khóa", có thể dễ bị tấn công thời gian, sau đó sử dụng chức năng so sánh an toàn về thời gian để kiểm tra giá trị của bí mật".

Đây là cách triển khai hàm đó của Python:

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

Và nó được hiển thị trong hmaclib (và có thể là những người khác):

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


Một điều cần lưu ý ở đây là tôi không nghĩ rằng kiểu tấn công này sẽ hoạt động trên các giá trị được băm hoặc mã hóa trước khi tra cứu, bởi vì các giá trị được so sánh thay đổi ngẫu nhiên mỗi khi một ký tự trong chuỗi đầu vào thay đổi. Tôi tìm thấy một lời giải thích tốt về điều này ở đây .

Các giải pháp để lưu trữ khóa API sau đó sẽ là:

  1. Sử dụng khóa và bí mật riêng biệt, sử dụng khóa để tra cứu hồ sơ và sử dụng so sánh an toàn về thời gian để kiểm tra bí mật. Điều này cho phép bạn hiển thị lại chìa khóa và bí mật cho người dùng.
  2. Sử dụng khóa và bí mật riêng biệt, sử dụng mã hóa đối xứng, xác định đối với bí mật và thực hiện so sánh thông thường các bí mật được mã hóa. Điều này cho phép bạn hiển thị lại khóa và bí mật cho người dùng, đồng thời có thể giúp bạn không phải thực hiện so sánh an toàn về thời gian.
  3. Sử dụng một khóa và bí mật riêng biệt, hiển thị bí mật, băm và lưu trữ, sau đó thực hiện so sánh bình thường với bí mật đã băm. Điều này loại bỏ sự cần thiết phải sử dụng mã hóa hai chiều và có thêm lợi ích là giữ bí mật của bạn an toàn nếu hệ thống bị xâm phạm. Nó có nhược điểm là bạn không thể hiển thị lại bí mật cho người dùng.
  4. Sử dụng một khóa duy nhất , hiển thị nó cho người dùng một lần, băm nó, sau đó thực hiện tra cứu bình thường đối với khóa được băm hoặc mã hóa. Điều này sử dụng một phím duy nhất, nhưng nó không thể hiển thị lại cho người dùng. Có lợi ích trong việc giữ khóa an toàn nếu hệ thống bị xâm phạm.
  5. Sử dụng một khóa duy nhất , hiển thị nó cho người dùng một lần, mã hóa nó và thực hiện tra cứu thông thường về bí mật được mã hóa. Có thể được hiển thị lại cho người dùng, nhưng phải trả giá là có các khóa dễ bị tổn thương nếu hệ thống của họ bị xâm phạm.

Trong số này, tôi nghĩ rằng 3 là sự cân bằng tốt nhất về bảo mật và tiện lợi. Tôi đã thấy điều này được triển khai trên nhiều trang web khi nhận được chìa khóa.

Ngoài ra, tôi mời bất kỳ chuyên gia bảo mật thực tế nào phê bình câu trả lời này. Tôi chỉ muốn đưa điều này ra khỏi đó như một điểm thảo luận khác.

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.