RESTful API, хранение паролей и взрыв мозга

psm-home

Популярный ныне RESTful подход к созданию API предполагает, что сервер не должен хранить состояние для клиента (должен быть stateless). (1)
Считается общеизвестным, что пароли на серверной стороне должны храниться в виде соль+хэш, причем хэш должен быть "ресурсоемким", а-ля bcrypt/scrypt/PBKDF2, чтобы украв хэши нельзя было подобрать пароли за разумное время. (2)
Я правильно понимаю, что (1) и (2) противоречат друг другу?
Подход (1) предполагает что-то вроде BASIC аутентификации, когда мы получаем пароль с каждым запросом и для каждого запроса долго и упорно вычисляем хэш (2 чтоб аутентифицировать запрос. Получается что сервер зря греет воздух и тупит (ко времени работы самого метода API добавляется время проверки пароля).
Большое количество современных сервисов, имеющих публичное RESTful API, используют BASIC аутентификацию.
Я правильно понимаю, что они все положили с прибором на стойкость хэша пароля и вместо благословенного bcrypt используют что-то вроде MD5/SHA?

artimon

А мне казалось, что все использую токены (OAuth и т.п).

psm-home

Да, может быть у меня плохая выборка и все используют токены. Но это в общем тоже самое что сессии, и уже не совсем stateless.

artimon

А что ты понимаешь под сессией?

psm-home

web page

zorin29

Считается общеизвестным, что пароли на серверной стороне должны храниться в виде соль+хэш, причем хэш должен быть "ресурсоемким", а-ля bcrypt/scrypt/PBKDF2, чтобы украв хэши нельзя было подобрать пароли за разумное время.
Мне требование ресурсоемкости не представляется обязательным. Расскажи подробнее, плз, как за разумное время подобрать пароли по SHA-1?

artimon

Ну при таком подходе любой способ залогинить человека это сессия. Но вообще стейтлесс/стейтфул от этого никак не зависят.

psm-home

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

psm-home

Расскажи подробнее, плз, как за разумное время подобрать пароли по SHA-1
Попробовать перебор по словарю + полный перебор для какого-то ограниченного класса символов. В интернетах встречаются утверждения о скорости перебора 500 миллиардов хэшей/сек. По-моему что-то вполне можно так подобрать. Для "медленных" хэшей типа scrypt можно подобрать параметры так, чтобы на типичном железе вычисление хэша 1 раз занимало время ~1 сек.
Вот что NIST например пишет в документе , где рекомендует PBKDF:
The main idea of a PBKDF is to slow dictionary or brute force attacks on the passwords
by increasing the time needed to test each password. An attacker with a list of likely
passwords can evaluate the PBKDF using the known iteration counter and the salt. Since
an attacker has to spend a significant amount of computing time for each try, it becomes
harder to apply the dictionary or brute force attacks.

zorin29

В 500 миллиардов хешей в секунду мне не верится что-то, если идет речь про одну машину десктоп-класса.
В любом случае, если в качестве соли выбирать, скажем, произвольное слово длины 20 из алфавита в 30 символов (30^20 то угадать соль даже при указанной скорости можно за 22 миллиарда лет.

artimon

Соль очевидно есть вместе с базой хешей

zorin29

Тогда понятно. Ну это тогда угроза другого рода, чем я себе представлял.

psm-home

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

zorin29

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

rosali

> Тогда какой в ней смысл?
Смысл в том, чтобы ты вынужден был действительно перебирать пароли и хешировать их, а не просто лукапиться по предвычисленному индексу хешей от всех популярных паролей.

zorin29

Угу, это разница в парадигмах у нас.
Я представлял себе "стандартный" способ - это хранить SHA1(password+salt) в базе, а salt держать в большом секрете вне базы.
Другой способ, о котором мне все говорят, это хранить salt и ExpensiveHash(password+salt) в базе. В этом случае да, без salt теряется смысл, потому что все ExpensiveHash-ы можно вычислить заранее.
Соответственно, я себе вообразил вариант с хранением salt и SHA1(password+salt и не увидел в нем смысла.

esorokin

Я правильно понимаю, что (1) и (2) противоречат друг другу?
Ммм... Нет, не противоречат. Как уже заметили, это вопросы ортогональные. В качестве варианта, можно использовать сколь угодно сложный хеш на стороне сервера, но при аутентификации выдавать клиенту вместо session token подписанную печеньку с userid/датой протухания/чем угодно. В такой позе данные сессии хранятся у клиента, но клиент (или злоумышленник) не может их подделать не имея приватного ключа подпись которым сервер ожидает увидеть.
Оставить комментарий
Имя или ник:
Комментарий: