Ответ 1
Как всегда, лучший способ защитить ключ - не передавать его.
Тем не менее, мы обычно используем схему, где каждый "ключ API" имеет две части: несекретный ID (например, 1234) и секретный ключ (например, byte [64]).
- Если вы выдаете ключ API, храните его (соленое и хешированное) в вас сервисной базы данных.
- Если вы выдаете учетные записи пользователей (защищенные паролем), сохраните пароли (соленые и хешированные) в вашей базе данных
Теперь, когда пользователь первый обращается к вашему API, чтобы подключиться, попросите его
- Отправьте параметр "имя пользователя" ( "john.doe" не секрет)
- Отправьте параметр "APIkeyID" ( "1234", а не секрет)
и верните его
- соли из вашей базы данных (если один из параметров неверен, просто верните некоторую повторяемую соль - например. sha1 (имя пользователя + "notverysecret" ).
- Временная метка сервера
Потребитель должен хранить соль для продолжительности сеанса, чтобы поддерживать скорость и плавность, и он должен вычислять и сохранять временное смещение между клиентом и сервером.
Теперь потребитель должен вычислить соленые хэши ключа API и пароля. Таким образом, у потребителя есть точные хэши для пароля и ключа API, как то, что хранится в вашей базе данных, но без каких-либо секретов, когда-либо проходящих через провод.
Теперь, когда пользователь ниже обращается к вашему API, чтобы сделать реальную работу, ему
- Отправьте параметр "имя пользователя" ( "john.doe" не секрет)
- Отправьте параметр "APIkeyID" ( "1234", а не секрет)
- Отправьте параметр "RequestSalt" (байт [64], случайный, не секретный)
- Отправьте параметр "RequestTimestamp" (рассчитанный исходя из времени клиента и известного смещения)
- Отправьте параметр "RequestToken" (хэш (passwordhash + request_salt + request_timestamp + apikeyhash))
Сервер не должен принимать отметки времени больше, чем сказать 2 секунды в прошлом, чтобы сделать это безопасным против повторной атаки.
Теперь сервер может вычислить один и тот же хэш (passwordhash + request_salt + request_timestamp + apikeyhash) в качестве клиента, и убедитесь, что
- клиент знает ключ API,
- клиент знает правильный пароль