Замедление хеширования паролей. Зачем?

    Доброго времени суток, хабрапараноик! Сегодня мы поговорим о немного необычном способе повышения безопасности, а именно замедлении хеширования паролей. Казалось бы, когда всё вокруг стараются оптимизировать, зачем что то замедлять?
    Хотя бы затем, что даже в самой супер-пупер защищенной системе самым слабым звеном остается человек. А именно, его пароль.

    Вы пытались когда нибудь взломать зашифрованный rar архив? И сколько паролей в секунду оно перебирало? 50-100-200? Даже на хорошем GPU, при использовании небезызвестного cRARk, скорость перебора всего около 2400 вариантов/сек. И это-то по сравнению с десятками (сотнями) миллионов паролей/сек для zip/md5/SHA1.

    Под катом моя вольная интерпретация этого процесса.


    Смысл всего действа сводится к следующему:
    • Ключом шифрования важной является не пароль, а (медленный) хэш от него
    • Юзеру ничего не стоит подождать секунду\пол секунды пока пароль прохешируется
    • А вот homo brutforsus придется запастись терпением

    Да, чуть не забыл про всеми любимые rainbow tables, которые довольно успешно генерятся даже для систем, использующих сахар соль. Их генерация тоже станет если не бесполезной, то очень трудозатратной.

    Я не говорю, что системы с солью плохие, просто их можно еще усилить.

    И так, есть соль, есть пароль. Что дальше?

    А дальше все довольно просто:
    1. Конкатенируем соль и пароль
    2. Хэшируем, запоминаем результат
    3. while (много много раз) do{
    4. сгенерировать раундовую соль
    5. Сконкатенировать её и хэш
    6. Прохэшировать, запомнить результат}

    В Winrar (спасибо ему, кстати, за вдохновение), если мне не изменяет память, раундовой солью является номер итерации. Я же пошел немножко дальше.

    Итак, код. Всё написано на java с использованием библиотеки BouncyCastle, но вдумчивому хабрапараноику не составит сложности перенести это (и может быть добавить своё) на любой язык программирования, полный по тьюрингу. К тому же BouncyCastle есть и для C#.

    1. Я использую 2 алгоритма хеширования (SHA-256 и SHA-512), поэтому для начала небольшой интерфейсик, который поможет нам всё это дело более-менее универсализировать.
    public interface IDigest
    {
        public byte[] process(byte[] data);
        
        public int getSize();
    }




    2. Пример реализации этого интерфейса для алгоритма SHA-256 (используется класс SHA256Digest из библиотеки BouncyCastle):
    public class SHA256 implements IDigest
    {

        private SHA256Digest m_SHA256 = new SHA256Digest();

        @Override
        public byte[] process(byte[] data)
        {
            m_SHA256.reset();
            m_SHA256.update(data, 0, data.length);
            byte[] result = new byte[m_SHA256.getDigestSize()];
            m_SHA256.doFinal(result, 0);
            return result;
        }

        @Override
        public int getSize()
        {
            return m_SHA256.getDigestSize();
        }
    }




    3. Самая вкуснятина. Её я объясню подробно.
    public class SlowHasher
    {
        private final static int BITS_IN_BYTE = 8;
        
        private static final int[] s_primeIndices = new int[] { 7, 11, 17, 23, 31, 41, 47, 53, 61 };

        /**
         * this method hashes password 0x50000 times adding round salt each round
         *
         * param digest
         * param password
         * return
         */
        public byte[] calculateSlowHash(IDigest digest, String password, byte[] salt)
        {
            int roundSaltSize = digest.getSize() / BITS_IN_BYTE;
            byte[] bPasswd = password.getBytes();
            byte[] toHash = new byte[bPasswd.length + salt.length];

            /*
             * composing array of bytes that will be hashed
             */
            System.arraycopy(salt, 0, toHash, 0, salt.length);
            System.arraycopy(bPasswd, 0, toHash, salt.length, bPasswd.length);

            byte[] res = digest.process(toHash);
            byte[] temp = new byte[res.length + roundSaltSize];

            for (int i = 0; i < 0x50000; i++)
            {
                System.arraycopy(res, 0, temp, 0, res.length);

                /***
                 * calculating salt
                 */
                for (int j = 0; j < roundSaltSize; j++)
                {
                    int btmp = res[s_primeIndices[j]] & 0xFF;
                    for (int k = 1; k < BITS_IN_BYTE; k++)
                    {
                        btmp = ror((btmp + (res[ror(btmp, k) % res.length] & 0xFF)) % 256, BITS_IN_BYTE-k);
                    }
                    temp[res.length + j] = (byte)btmp;
                }
                res = digest.process(temp);
            }
            return res;
        }

        /**
         * rotate bits right treating input as byte
         * param value 0 <= value <=255
         * param n number of bits to shift
         * return
         */
        public static int ror(int value, int n)
        {
            return ((value >> (n % BITS_IN_BYTE)) | ((value << (8 — (n % BITS_IN_BYTE))) & 0xFF));
        }
    }


    Людям не знакомым с java скажу сразу, что не стоит пугаться многочисленных вставок & 0xFF. Это всего лишь конвертация signed byte в unsigned путем преобразования его в int и применения такой вот битовой маски. А всё потому, что в java нет unsigned типов! Совсем! Ну да ладно, это не смертельно.

    Вся красивость тут заключается в формировании раундовой соли, поэтому основное внимание будет уделяться ей.

    Немного о переменных:
    • res — массив из 32 байт для SHA-256 или 64 байт для SHA-512. В нем хранится результат хеширования
    • roundSaltSize — размер раундовой соли. 4 байта для SHA-256 и 8 байт для SHA-512
    • temp — массив из элементов размера массива res плюс размер раундовой соли roundSaltSize
    • s_primeIndices — массив индексов элементов в массиве res, начиная с которых мы будем вычислять соответствующий байт раундовой соли. То есть, начинать вычисления первого байта раундовой соли для SHA-256 мы будем с res[7], второго с res[11] и т.д. Для SHA-512 будут задействованы все индексы
    • btemp — байт, который после серии хитрых преобразований станет на своё место в раундовой соли

    Еще одна ремарка прежде чем мы перейдем к разъяснениям формирования алгоритма раундовой соли. Весь алгоритм не является результатом каких либо научных исследований и тестов. Он создан для формирования значения, которое было бы зависимо от некоторых байтов результирующего хэша и помогло бы его замедлить и усложнить. Ну а теперь описание:

    1. В начале в массив toHash собираются основная соль и пароль
    2. Массив toHash хешируется и результат запоминается в массиве res. Всё, про основную соль и пароль забыли
    3. Запускаем длинный цикл в 0x50000 итераций
    4. Далее работаем с массивом temp, в который копируем массив res. В конце массива temp еще остается 4 или 8 байт для соли. Нам предстоит их заполнить
    5. Для каждого из байтов раундовой соли:
    6. Запоминаем в btmp элемент, который находится по одному из индексов (7, 11, 17… ) в зависимости от номера текущего байта (j)
    7. Затем 7(k) раз делаем следующее:
    8. Берем остаток от деления btmp, у которого биты сдвинуты вправо на k позиций, на длину массива res
    9. предыдущее число используем как индекс для массива res, вытаскиваем число по этому индексу
    10. btmp присваиваем это число, сложенное с btmp по модулю 256 и прокрученное вправо на 8-k бит
    11. Помещаем btmp на своё место после хэша в массиве temp
    12. Хэшируем temp

    Вызов этого метода выглядит следующим образом:

    byte[] salt = new byte[16];
    new SecureRandom().nextBytes(salt); // generate random 16byte salt
    byte[] hashedPassword = new SlowHasher().calculateSlowHash(new SHA256(), password, salt);




    В результате получится хэш(хэш(хэш+ранудовая соль)+раундовая соль)… который можно использовать как 256 битный ключ шифрования важной информации для AES-256, например.

    На моей машине (C2D 2.6) на генерацию одного хэша приходится около 0.25 секунды, что я считаю приемлемым для использования. в своих проектах. Можно увеличить число раундов и тогда время соответственно вырастет.

    Если уважаемой публике будет интересно, то я могу рассказать и о других прикладных аспектах работы с библиотекой BouncyCastle как то симметричное\ассиметричное шифрование, генерация сертификатов и т.д.

    UPD:
    В комментах указали ссылку на доку, в которой такого рода схема принимает еще больший размах

    Similar posts

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 107

      –15
      Допустим, надо сменить всем пароли на высоконагруженном сайте. Или сохранить его с другой солью.

      Админы будут в ярости
        0
        В основном это используется на клиентских машинах для шифрования различной инфы (архивы\документы и.т.д)
          +13
          И часто вы практикуете массовую смену паролей?
            –4
            Я – нет.
              0
              А кто тогда практикует?
                –3
                Ну, я видел проекты, в которых сначала пароли вообще в открытом виде хранились (~4 000 000). Пересчет занял день, вроде.
                  0
                  Это ужасно!
                    –2
                    Кто спорит?
                      0
                      Вопрос в другом, каким макаром неправильный подход к хранению паролей является виной алгоритма хеширования?
                        –5
                        В том, что долгое массовое хеширование выльется в ад. Уверен, такая ситуация может возникнуть.
            +5
            а не получится — вы же умный мальчик не храните пароли в открытом виде, а пользователи одновременно все не смогут сменить пароль.
              +6
              Как это — сохранить пароль с другой солью? Без участия пользователя, знающего пароль, это должно быть невозможно, как вы понимаете. Иначе зачем вообще тогда соль?
                0
                Понял позже.
              –11
              Гм… может, просто sleep($period) воткнуть, где $period — величина замедления (может быть передана в хеширующий метод)? Например, для разовой смены паролей у всех юзеров данный параметр можно выставить в 0, дабы не тормозить зря систему.

              Навряд ли многократное хеширование так уж усилит криптостойкость, получается основная задача — усложнить брутфорс…
                +17
                Вы не поняли сути — создаётся не медленный код, а медленный алгоритм, который при любой реализации будет медленным.
                  –9
                  Объясните, пожалуйста, разницу :) Пока мне видится, что «при любой реализации будет медленным» это скорее минус, чем плюс.
                    +2
                    Плюс в том, что при подборе он тоже будет медленным.
                      –10
                      А что, при переборе паролей мой вариант ( sleep() ) почему-то не сработает? :)
                        +6
                        Потому, что подбирать будут не этим кодом со sleep-ом, а совершенно другим кодом, реализующим данный алгоритм. О чём выше и сказали, или до сих пор не понимаете разницу?)
                          –1
                          Ну хрен с ним, с алгоритмом — пускай он известен. А как можно соль узнать, чтобы реализовать хеширование по-своему?
                            +10
                            Т.е. все все знают, просто коммент написать лень — легче плюнуть, так? Замечательное решение.

                            Я спрашиваю не чтобы поспорить, а чтобы разобраться в предложенной схеме, а в ответ — типичный для Хабра средний палец. Мдя
                              +13
                              вас картинка приманила в топик?
                                –6
                                Вы только что честно заработали минус. Я задал конкретный вопрос по теме топика. Вы на него не ответили, стеб не осилил.
                                  0
                                  вам выше всё объяснили, а вы продолжаете слоупочить. Теперь еще и обижаетесь. Может лучше фишки будете читать, там народ попроще :)
                                    +3
                                    Если я продолжаю спрашивать, значит не все мне понятно. Вопросы вроде как задаю достаточно конкретные. В чем проблема? Хочется поострить?
                                    Вы лично ничего по теме топика не написали, только зачем-то г** подбрасываете. Ведь очень интересно смотреть на других свысока, правда?

                                    ЗЫ. На Фишки не хожу, да и не надо — Хабр к ним потихоньку приходит.
                                      0
                                      Народ обижается, что вы не хотите почитать / изучить теорию типа www.intuit.ru/department/security/networksec/
                                      А хотите получить всё «разжеванное на блюдечке».
                                        –2
                                        Я знаком со многими общими понятиями из этой теории, спасибо. И вопросы задаю, как мне кажется, не откровенно тупые (разубедите меня, но аргументами, а не минусами).
                                        Ниже есть комментарии с нормальными ответами. Почему-то люди не гнушаются снизойти до разговора с непонимающими, вот за это я все еще люблю Хабр.
                                          +2
                                          Предположим у тебя есть сайт. Злоумышленник решил его взломать. Он раздобыл алгоритм шифрования, который ты используешь и хеш пароля админа. Алгоритм прост: md5($passw); Злоумышленник воспользуется брутфорсом пароля по твоему алгоритму, и найдет его максимум часа за два.

                                          А теперь предположим, что алгоритм шифрования такой:
                                          $hash = '';
                                          for($i = 0; $i < 10000; $i++){
                                          $hash .= sha1($passw).md5($passw);

                                          if(!($i%10)){
                                          $hash = md5(sin((int) $hash).$hash);
                                          }
                                          }

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

                                              А если речь идет об архиваторе, то дизассемблировать — и вперед, тут все ясно.
                                                –1
                                                Представьте, что у вас есть алгоритм с вставками sleep, которые замедляют его работу, алгоритм открыт и известен, злоумышленник крадет базу хешей, берет алгоритм, удаляет из него все замедляторы и вуаля, алгоритм становится быстрый. А здесь же имея алгоритм и даже соль все равно придется прогонять 50000 итераций для каждого варианта пароля, что замедлит время подбора во сколько тысяч раз? Как ни крутись, а упростить алгоритм и следовательно сократить время его выполнения не получится.
                                                  0
                                                  топику год ) расслабьтесь
                                                0
                                                Злоумышленник воспользуется брутфорсом пароля по твоему алгоритму, и найдет его максимум часа за два.

                                                Интересное утверждение, а если у меня пароль длиной в 40 символов, он тоже за 2 часа забрутит его? ;)
                                                  0
                                                  больше интересен момент добычи хеша пароля одмина =) Очевидно, что в куке он не хранится, а хранится, допустим, в базе. Как кулхацкер выцепит хэш из бд?

                                                  Получается, что, чтобы взломать сайт, нужно сначала взломать сервер ;)
                                                    +2
                                                    sql injection.
                                                      0
                                                      sql injection для чтения инфы? что-то новое :)
                                                      –2
                                                      sql-инъекции пока никто не отменял
                                                      +2
                                                      Длина пароля значения не имеет, если у злоумышленника есть хеш — ему достаточно найти любой пароль имеющий тот же хеш, а будет он вашим или вдруг какая коллизия — без разницы.
                                                        0
                                                        Вы про коллизии? только и займет это O(2^64), O(2^80)… (подставить нужное) времени. а короткие пароли ломаются посимвольно за O(x^N), где N — длина пароля.
                                      0
                                      Брутфорсом или дизассемблированием.
                                        –1
                                        Но ведь брутфорс соли (я так понимаю, тут по-любому будет использован алгоритм сервера) будет получать задержки?

                                        PS. Можно перейти в личку, чтобы не замусоривать данный топик
                                          0
                                          С какой стати брутфорс будет использовать алгоритм сервера? Я сливаю себе базу данных сервера с паролями и брутфорсю на своем домашнем Cray. Теперь понятно?
                                            0
                                            Ого! Доступ к БД сервера? Это что-то новое. А зачем тогда брутфорс, если можно тогда прямо в БД что-то править?

                                            Вообще-то я имел в виду случаи, когда у злоумышленника нет доступа к внутренностям сайта (это ведь самый распространенный вариант?).
                                              +4
                                              Давайте определимся. Это алгоритм не предназначен для препятсвия подбору паролей на сайт, там sleep как раз подойдет. А это алгоритм для того чтобы замедлить подбор пароля к шифрованному документу (например rar-архиву). Злоумышленнику известен алгоритм хеширования, так как он имеет доступ к бинарникам архиватора и может их дизассемблировать.
                                                +1
                                                Да, спасибо. Внизу уже тоже указали на такие случаи. Я рассматривал алгоритм со своей колокольни.

                                                Спасибо за конструктив, приятно что-то полезное из статей извлекать.
                                                  0
                                                  не подойдет sleep на сайтах. там можно в 1000 потоков запустить подбор пароля. подойдет разве что добавление в базу последнего обращения. например, если логинились к пользователю в 1234567890 юникс-секунд, то след раз можно логинится только в 1234567895 секунд, иначе выдаст ошибку
                                                    0
                                                    Это само собой, не хотелось разжевывать. Счетчики на аккаунты, на IP. Но sleep никуда не девается, он как замедляет атаку с серии IP на один аккаунт.
                                      +6
                                      Потому что при подборе при помощи средств (к сожалению не знаю какие они для джавы) вытащит код, который генерит хеш, уберёт оттуда все слипы и получит существенно более быструю реализацию.
                                      Или, если алгоритм известен то просто напишет его сам, без слипов.
                                      После чего будет брутфорсить в своё удовольствие.

                                      С медленным же алгоритмом скорее всего не получится придумать ничего более умного чем просто медленно его выполнять.
                                      Такие дела.
                                        +4
                                        Простым языком:

                                        Вариант топикстартера — для подбора пароля надо выкопать яму глубиной 3 метра и после этого можно что-то сделать.
                                        Твой вариант — копнуть раз, подождать пол дня, копнуть еще раз и после этого работать с ключом.

                                        Вся беда в том, что злоумышленнику в первом варианте придется для каждого ключа копать яму в 3 метра, а в твоем он копнет 2 раза и не будет ждать под дня между копками лопатой.
                                          –2
                                          Ну, я предполагаю, что у злоумышленника нет своей лопаты, и он нанимает человека у владельца пароля :) Это все к тому, что у механизма шифрования имеются секретные части (соль, алгоритм хеширования и т.д.), к которым вроде как доступа у простого пользователя нет.

                                          Или я коренным образом в чем-то ошибаюсь?
                                            +2
                                            мы не рассматриваем ситуацию когда надо еще что то достать (соль, кстати, ни разу не секретная часть)
                                            Мы рассматриваем ситуацию когда у нас уже всё есть кроме пароля
                                              +1
                                              Просто удар по почкам :) Я всегда полагал соль секретной частью… Это все меняет, хотя вопросы еще остаются, спасибо!
                                                0
                                                генерируем хеш (соль+пароль). Соль хранится отдельно. Чтобы проверить верен ли пароль, мы обязаны провторить процесс как хеш(соль+проверяемый пароль) и если они совпадут то ок.
                                                Отсюда вывод — соль хранится отдельно и ни от кого не прячется
                                              +2
                                              В критографии считается алгоритм полностью известным злоумышленнику. Соль в том числе является не секретной частью алгоритма.
                                  –1
                                  Подскажите, почему нельзя просто увеличить значение FAIL_DELAY?
                                    0
                                    Потому что по заранее известному алгоритму злоумышленник может подбирать пароль на своей машине.
                                      0
                                      Если я не ошибаюсь, для PAM нету разницы, с какой машины в пытаетесь осуществить подбор пароля — локальной или удаленной.
                                        +2
                                        Речь идет о подборе пароля не прибегая к стандартным интефейсам проверки.
                                        Например, подбор пароля к архиву.
                                          +1
                                          До тех пор, пока нет хэша. Если хэш есть, то для его брутфорса уже не нужен целевой сервак.
                                          А в топике автор как раз и приводит алгоритм, который даже при его знании и владении хэшем не позволит быстро его подобрать.
                                      0
                                      >в java нет unsigned типов! Совсем!
                                      А char?
                                        +1
                                        Char — строковый тип. С таким же успехом string можно назвать универсальным типом данных произвольной длинны с произвольной точностью.
                                          0
                                          Я имел в виду типы для работы с числами. Про двухбайтовый char в курсе.
                                            0
                                            byte?!?!
                                              +1
                                              только signed
                                          +2
                                          похожая идея используется в unix md5, где стандартный md5 вызывается 1000 раз
                                            0
                                            А еще наверное можно отсрочить момент понимания, что пароль не валиден? Например, он может «подойти», но на выходе будет кашица, которую идентифицировать автоматически будет «сложно».
                                              0
                                              И как мне понять, что мой бинарник не запускается из-за неправильного пароля, а не из-за того что он битый еще до архивирования?
                                                0
                                                Говоря о шифровании, можно не добавлять к исходному сообщению никаких специальных данных (Padding), по которым можно узнать зашифрованы данные или нет. Тогда если данные, например, пожаты хорошим алгоритмом (без сигнатур, опять же) или обфусцированы как в скайпе, то на выходе даже с верным паролем данные не будут отличимы от случайных.
                                                +3
                                                В то время как космические корабли бороздят просторы вселенной, на некоторых сайтах по-прежнему используется MD5 пароля в чистом виде, без всякой соли, что позволяет весело и радостно пользоваться радужными таблицами.
                                                  0
                                                  А где там используется md5 от пароля в чистом виде? В куках на основном домене уже давным давно хранится псевдосессия, зависящая от IP и пароля, в куках на login.vk.com хранится парольный хеш, однако совсем не md5 от пароля в чистом виде. Или речь про еще какое-то использование?
                                                  +1
                                                  Кажется, именно так хешируется пароль в некоторых *nix системах.

                                                  А ещё, я тоже писал об этом в своём блоге почти год назад. Всё-таки, хорошие идеи достаточно часто приходят в голову разным людям)
                                                  Там даже небольшая дискуссия в комментариях развернулась.

                                                  Цитата оттуда:
                                                  Перебор 1000 паролей на компьютере средней мощности должен занимать больше 1 секунды.

                                                  У вас, даже лучше получилось. К слову, всё, за исключением модуля, описанное в моём посте — успешно используется на реальном проекте.
                                                    +1
                                                    Чем результат принципиально отличается от результата использования более длинной соли? Я так понимаю что ничем, кроме того что будет дико грузить процессор на сервере при каждой проверке пароля.
                                                    Вывод — на серверных приложения такие решения неприемлимы.
                                                      –2
                                                      А что за число 0x20000? Никогда не видел.
                                                        0
                                                        0x означает, что используется 16ричная кодировка
                                                          0
                                                          Ларчик просто открывался. Спасибо (:
                                                        +1
                                                        Судя по комментариям, слово «медленный» многих запутало. :)

                                                        А идея здравая на самом деле.
                                                          +4
                                                          как бы только это шаманство не увеличило число коллизий настолько, чтобы подобрать пароль стало даже проще х)
                                                            0
                                                            для успокоения души можно провести тесты генерируемой соли на случайность )
                                                              +1
                                                              а толку? соль и так хранится в открытом виде. а коллизии от секретного ключа при заданной соли будут только увеличиваться
                                                                0
                                                                на самом деле первый дельный комментарий к топику ) Я пока не знаю что ответить, надо почитать литературу
                                                            +1
                                                            Действительно, зачем? Если от брутфорса перехваченных данных — Just use SASL. Если от брута сграбленой базы — от rainbow спасет салт, который и так есть. От онлайн брута — задержки собственно в процессе инициализации. Вообще, строго говоря, не совсем ясно как будут меняться коллизионные свойства результирующего хеша от вводимых вами дополнительных шагов. А вообще, как по мне, самое слабое звено — канал связи :] Я бы предпочел отдельную инфраструктуру аутентификации с паролями в открытом виде + SASL этой схеме. Впрочем каждой задаче своё решение.
                                                              0
                                                              кому надо могут сгенерить таблицы и для определенного saltа, если подбирается лишь определенный пароль. Я правда не знаю будет ли это быстрее чем голый брут
                                                                0
                                                                Конечно нет. Это и есть — голый брут :] Просто rainbow — это брут оптом, где кто-то уже делал эту работу.

                                                                По моему мнению, тут решается не та проблема. Надо защищать канал связи и доступ к данным аутентификации, способ аутентификации, а не сами данные.
                                                              –1
                                                              Кто объяснит почему все используют md5 ( pass + salt )?
                                                              Почему не завести в бд поле, в котором будет жить то что находится в куке у конкретного пользователя? При генерации этого значения можно использовать, например: md5( рэндом + пароль + положение луны на небе ).
                                                                0
                                                                А если сессий несколько? Обычно хранят ключевую информацию. Хранить каждый сессионный ключ чревато ДоСом. Использовать всегда один сессионный ключ… Ну можно конечно, но тогда кража сессионного ключа автоматически позволяет получать доступ к аккаунту на все его время жизни. Причем не совсем прозрачно, сколько это время жизни будет составлять. Впрочем, как показывает практика, этот аспект никого не парит. Так что может быть и можно (% Но в любом случае, нужно хранить мастер ключ где-нибудь, на случай новой сессии. Если хранить эти данные в той же базе, то ничего по сути не меняется.

                                                                Вообще, хранение данных аутентификации не на отдельном логическом юните имхо — безответственное решение
                                                                  0
                                                                  А не, я туплю. Я не о той задаче мысли привёл. Я про кражу куки и брутфорс её написал.
                                                                0
                                                                в маршрутизаторах Cisco уже более 8ми лет используется тысячекратный хеш. так что идея весьма не нова.
                                                                  +3
                                                                  Проблема тысячекратного применения хэширования, например, в том, что каждый шаг уменьшает возможное пространство значений (в лучшем случае — оставляет той же размерности), исходя из этого может получиться более простым подбор коллизии. Ведь злоумышленнику, по сути, не так важен сам пароль, как то, что хэш от результата брутфорса совпадает с хэшем оригинального пароля.
                                                                    0
                                                                    всякие пермутации призваны усложнить как раз таки их поиск… Хотя с удовольствием почитаю о безитеративном замедлении
                                                                      +1
                                                                      Это не совсем так.

                                                                      Не суть ясно, уменьшается ли возможное пространство значений.

                                                                      Злоумышленнику нужно подобрать то, что будучи поданным на вход ф-ии аутентификации в результате имеет то же значение, что и значение, с которым будет производиться сравнение. Если туда подается пароль, а внутри модуля аутентификации сравниваются значения вот иэтих 100500 проходов, то, как не крути, все равно придется искать коллизию (атака экзистенциальной подделки). Скорее всего сложность этой атаки будет такой же, как и в случае одного хеширования (Если нет фильтра входных данных, если он есть, то не каждый результат подойдет).
                                                                        +1
                                                                        Ну увеличиваться оно явно не будет, в силу того, что хэш — это отображение. Уменьшаться может запросто: пусть у нас пароль — это число от 0 до 2^32 — 1 и дурацкая хэширующая функция — правый сдвиг. Тогда после первого применения хэша у нас пространство значений сократится вдвое (и значения 0 и 1, например, будут давать одинаковый хэш — 0). И так далее, после 32 применений хэша в любом случае получится у нас 0.
                                                                        Вы, конечно, возразите мне, что хэш придумывают не такой разрушительный обычно, а умный и со всякими классными штуками. Но, опять же, есть ещё одна проблема. Если у нас есть функция, применённая несколько раз последовательно, то у неё может быть и какой-нибудь плохой эффект от циклического применения, который с удовольствием могут найти и использовать криптоаналитики. Грубо говоря, отчасти на этом построена циклическая атака на RSA. Конечно, можно подбирать хорошо функции и соль, чтобы избегать уязвимостей, но это уже более глубокая алхимия.
                                                                          0
                                                                          Вы всё правильно говорите, но стандартизированные криптографические хеш функции обычно рассчитаны для такого использования (всякие PRNG/MGF/KDF преобразования) [если интересно, можно поплясать по ссылкам от требований NIST SHA-3, раздел 2.2.1]. Вообще, конечно, имхо в данной ситуации это решение какое то леваковое, и «лечит симптомы, а не проблему» :)
                                                                            0
                                                                            Можете кинуть такой ссылкой? Чет я по SHA-3 requirements никак не найду доку в которой был бы пункт 2.2.1 )
                                                                            0
                                                                            Для SHA будет строго уменьшаться,

                                                                              0
                                                                              прошу прощения, ссылка сорвалась, а вот и она.

                                                                              то есть, в нашем-то как раз случае, эта проблема существенна.
                                                                                0
                                                                                В случае ТС SHA-1 1) не используется 2) нельзя сказать что случай ТС эквивалентен увеличению раундов ф-ии. То что в случае ТС получается нужно (если это действительно кому то нужно) исследовать отдельно :]
                                                                                  0
                                                                                  В случае SHA используется не в прямом виде циклическое хеширование.
                                                                                  people.redhat.com/drepper/SHA-crypt.txt
                                                                            0
                                                                            А что скажете о применении гигантской соли? Прегенерённого случайного файла, где функцией от пароля пользователя мы определяем смещение, по которому считываем, скажем 500Mb и используем как соль: на моей машине md5 от 500 Mb считается почти секунду.
                                                                              0
                                                                              И эту гигантскую соль тоже придется где-то хранить.

                                                                              У Вас, кстати, видимо очень быстрый винчестер, у меня за секунду даже 100 мегабайт не считается.
                                                                                0
                                                                                Ну я считаю, что эти 500 Mb уже в файловом кеше лежат.
                                                                            –1
                                                                            Гм? Поделить базу для брута на несколько частей и запустить брут с нескольких хостов? — Будет быстрее
                                                                              0
                                                                              При первом прочтении, я был похож на создание с картинки =) Потом всосал мысль и понял )
                                                                                –2
                                                                                Какой разврат.

                                                                                0. Где хоть какие-нибудь гарантии, что вместе с усложнением алгоритма хеширования, Вы не увеличите теоретическую вероятность коллизии в пропорциональное (а то и худшее) число раз?

                                                                                Ну и очевидные ошибки:
                                                                                1. в RAR успех расшифровки определяется сравнением полученных CRC расшифрованного блока, а он не маленький. Отсюда и скорость такая низкая, а не из-за раундовых солей.

                                                                                2. Радужные таблицы как раз-таки не эффективны после введения соли. Ключевой момент, почему они еще хоть как-то могут быть применимы — небольшая длина соли. Если сделать соль пропорциональной разрядности хеш-значения, то радужные таблицы полностью теряют смысл; их генерация для каждого конкретного случая занимает существенно большее время, чем прямой перебор (да еще и не будет обладать 100% шансами на успех).

                                                                                Если же мы надемся на произвольную коллизию, то при фиксированной соли равной по разрядности хеш-значению мы с большущей (назовем ее «100%», лень считать) вероятностью получим коллизию, не содержащую эту соль в качестве части пароля, и такой пароль не примет система:

                                                                                f(pass. ababababab) = hash = f(test. cdcdcdcdcd)

                                                                                3. Пропорционально вы уменьшите количество одновременно обрабатываемых авторизаций на предполагаемом сервере, может быть в 10 раз — это не существенно, но в 100000 — серьезная проблема. Для локальных решений это имеет смысл, но для сетевых — абсурд.
                                                                                  0
                                                                                  не содержащую эту соль в качестве части пароля, и такой пароль не примет система

                                                                                  соль не часть пароля.

                                                                                  их генерация для каждого конкретного случая занимает существенно большее время, чем прямой перебор

                                                                                  Генерация таблиц равна по времени полному перебору. Просто в случае соли на генерить для каждой соли опять полностью весь доступный парольный диапазон. Ничто не мешает сделать заранее радужные таблицы для солей заранее. Да растет объем для хранения, но в наше время не это проблема. Возможно и существует у тех кому надо.
                                                                                    0
                                                                                    Придется проводить очередной ликбез.

                                                                                    Генерация таблиц равна по времени полному перебору.

                                                                                    Это ерунда.
                                                                                    Таблица строится по некоторому диапазону строк X (например = {a..z}^8). И если прямой перебор проверяет каждую строку из X и имеет 100% шанс подобрать пароль для любого хеша, полученного из строки из X (что очевидно), то для радужной таблицы вероятность успешного подбора по нелинейному закону зависит от размера таблицы. И для получения где-то 75% успеха придется применить функцию хеширования по крайней мере в 2 раза больше раз, чем для полного прямого перебора. Для 99.9% покрытия объем вычислений на порядки привышает сложность прямого перебора для аналогичного промежутка. чуть подробнее.

                                                                                    но в наше время не это проблема

                                                                                    Вы считаете, что соль это отдельный параметр алгоритма, а не часть пароля, ладно, исходим из этого… тогда тезис представляет собой абсурд. Пусть мы умеем строить таблицу для конкретной соли, позволяющую восстановить любой пароль с 100% вероятностью (!) и такая таблица будет занимать всего 1 мегабайт (!)… но, вообще говоря входных параметров — различных солей число бесконечное. У кого-то существует бесконечное дисковое хранилище? Мне надо, но у меня нет.

                                                                                    Так вот, к чему это я. Соль — часть пароля.
                                                                                    хеш = MD5( пароль + соль ),
                                                                                    и для построения таблиц возможные соли включаются в диапазон паролей, затем, при подборе пароля по таблице проводится его декомпозиция на часть-соль и часть-пароль-пользователя. Но из-за коллизий (а мы собственно на них и надеемся) часть-соль может не соответствовать (и не будет!) нашей фиксированной соли, для которой мы пытаемся восстановить юзер-пароль по хешу.

                                                                                    А мораль такая, введение соли действительно делает применение таблиц полностью бессмысленным.
                                                                                      0
                                                                                      Так вот, к чему это я. Соль — часть пароля.

                                                                                      Пароль это то что вводится пользователем. Соль либо является константой в алгоритме, либо генерится случайно при установке/смене пароля и тогда хранится вместе с хэшем.
                                                                                      В случае использования соли при хэшировании пароля, если мы будем устраивать тотальный перебор нам нужно перебрать ровно столько же паролей, сколько и в системе без использования соль. В любом случае это прорва времени.
                                                                                      Внезапно, нам удалось получить доступ к хэшам паролей. Времени на полный перебор у нас мало, но мы-то заранее подготовились. Для того чтобы ускорить процесс мы на досуге строим радужную таблицу для всех возможных паролей, например { MD5('war'), MD5('god'), MD5('sex')}. И теперь нам достаточно проверить какому из хэшей соотвествует наш хэш и спокойно получить доступ. Вариант оценки размера радужных таблиц для разных алфавитов уже был на хабре.
                                                                                      Но оказалось, что создатели системы продвинутые люди и использовали соль при хэшировании пароля. Для каждого конкретного пользователя, соль либо известна и хранится вместе с хэшем, либо ее можно получить из алгоритма зная имя пользователя. И перед нами стоит опять затратная по времени задача перебрать все пароли, но уже с прибавлением этой соли {MD5(salt+'war'),MD5(salt+'god'),MD5(salt+'sex')}. Очевидно, что время и количество вариантов для тотального перебора не изменилось. Но вот наша старая таблица уже не дает нам возможности сэкономить время.
                                                                                      Ничто не мешает нам заранее сделать такие таблицы для солей. Диапазон их допустим 0x00 — 0xFFFF и мы просто штампуем таблицы {MD5(0x00+'war'),MD5(0x00+'god'),MD5(0x00+'sex')}, {MD5(0x01+'war'),MD5(0x01+'god'),MD5(0x01+'sex')},…
                                                                                      Да увеличивается экспоненциально место необходимое для хранения таблиц. Но для коротких размеров солей это уже вполне бюджетное хранилище. И с каждым годом объемы хранилищ все меньше имеют значение.
                                                                                    0
                                                                                    Я вообще то не говорил что замедляет хэширование именно раундовая соль, она призвана помочь с коллизиями. А насчет винрара — в исходниках unrar в crypt.cpp есть отличные строки (не зря я его упоминал)
                                                                                    const int HashRounds=0x40000;
                                                                                    for (int I=0;I<HashRounds;I++)
                                                                                    {
                                                                                    hash_process( &c, RawPsw, RawLength, HandsOffHash);

                                                                                    можете сами глянуть…

                                                                                  Only users with full accounts can post comments. Log in, please.