Подтвердить что ты не робот

Использование HMAC-SHA1 для проверки подлинности API - как безопасно хранить пароль клиента?

В RESTful API, который использует аутентификацию S3-style, клиент API подписывает запрос своим секретным ключом с использованием HMAC-SHA1, поэтому секретный ключ никогда не передается над проводом. Затем сервер аутентифицирует клиента, используя этот секретный ключ клиента, чтобы повторить сам процесс подписи и сравнить результат с сигнатурой, переданной клиентом.

Это все хорошо и хорошо, но это означает, что серверу требуется доступ к открытому ключу общего секретариата клиента. Это бросается в глаза всем советам против хранения пользовательских паролей в ясности внутри вашей базы данных. Хранение только соленого хэша пароля не является опцией, насколько я могу сказать, потому что тогда я не могу проверить подпись клиента.

Я должен подчеркнуть, что мой API RESTful и, следовательно, должен быть апатридом: я предпочел бы избежать шага входа до других вызовов API.

Одним из необязательных решений является шифрование всех паролей пользователей с использованием некоторого симметричного ключевого алгоритма. Тем не менее, сервер должен будет хранить ключ для этого шифрования где-то легко доступным, например. внутри исходного кода. Это лучше, чем ничего, но не оптимальное решение (как упоминал в своем ответе @Rook, он нарушает CWE-257).

Другим направлением для решения может быть что-то вокруг асимметричных подписей, но я не могу понять, как применить это к HMAC, и не могу найти статей по этому вопросу.

Я пропустил что-то очевидное здесь? Многие респектабельные провайдеры реализовали такую ​​схему аутентификации - они не могут все нарушать общие принципы безопасности, не так ли? Если нет, есть ли какие-либо рекомендации, которыми вы можете поделиться?

4b9b3361

Ответ 1

Это недостаток аутентификации стиля ответа с симметричным ключом - вы не ставите секрет на провод, но вы должны хранить секрет с обоих концов. (HMAC являются симметричными ключевыми системами).

Обратите внимание, что это не пароль - это общий секрет. Здесь принципиальное различие - пароль обычно выбирается пользователем, тогда как общий секрет генерируется случайным образом и предоставляется пользователю (в этом контексте они часто называются "ключами API" ).

Хранение паролей в обратимом формате плохо, потому что если ваша база данных скомпрометирована, тогда злоумышленники получили пароли, которые могли (и, вероятно, были) использованы в другом месте. С другой стороны, хранение секретной секретности - это не такая проблема - секрет, свойственный вашему сервису, поэтому все нападавшие получили возможность войти в вашу службу.

С другой стороны, возможно иметь асимметричную систему, которая не должна хранить секрет на стороне сервера. Основная идея заключается в том, что сервер знает открытый ключ клиента и текущий порядковый номер сообщения. При отправке запроса API клиент увеличивает порядковый номер сообщения и вычисляет подпись по порядковому номеру и параметрам запроса API, которые сервер может проверить с помощью открытого ключа. Сервер отклоняет сообщение, если он содержит старый порядковый номер сообщения, чтобы предотвратить повторные атаки.

Ответ 2

В идеале после входа пользователя в систему вы даете им Cryptographic Nonce, который используется в качестве секретного ключа HMAC K для жизни этого сеанса. Это безопасный подход, но не RESTful, потому что REST не имеет гражданства. Эта идея кода аутентификации сообщения, выданного для входа, технически является формой состояния.

Шифрование паролей и их сохранение в базе данных является нарушением CWE-257.

Ответ 3

Я не уверен, что здесь что-то не хватает, но один из них - использовать хешированный пароль как симметричный ключ.