Как стать автором
Обновить
1
0

Пользователь

Отправить сообщение

Для параноиков можно было бы сделать так:


  1. Часть encKey хранится на телефоне
  2. Генерируется одноразовая пара ключей, и на телефон вместе с запросом приватного ключа отправляется открытая часть (с подписанным запросом).
  3. Телефон при подтверждении отправляет ее в зашифрованном виде, и браузер ее расшифровывает. Поскольку ключ одноразовый, то через что бы оно ни пересылалось, повторно это использовать будет нельзя.

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


На самом деле, само хранение можно делегировать и Яндексу, что все равно добавит второй фактор, и требует только нахождение онлайн при вводе мастер-пароля.

Нет, компилятор тащить я совсем не предлагал. Я предлагал заранее собрать под каждый хост свой бинарник/библиотеку через -march=native, не используя специальных реализаций, и при запуске выбирать нужное, для чего мне пришли в голову 3 вышеперечисленных способа.


То есть тут сложность поддержки реализации заменяется сложностью сборки под каждый хост.

При хешировании у вас нет задачи это делать быстро — надо проверить один пароль. При брутфорсе надо проверить много. И тут задач стоит чтобы GPU вёл себя не лучше CPU. А дальше уже всё это можно как угодно ускорять — пользователей с паролем password таким способом всё равно не спасти.

Они же проголосовали просто за включение, вроде никто bcrypt не убирает.


Но кажется что никаких причин срочно отказываться от bcrypt нет (как отказываются сейчас от SHA1 и MD5).

Ну в принципе можно прямо внутри контейнера выбирать с какой версией библиотеки линковать или даже какой скомпилированный бинарник запускать (при static-linkage). Наверное, можно и через dlopen. Но не ясно что дешевле — поддерживать разные имплементации или сборку для разных targets.

Хеши же наверняка солёные. Я думаю что защищаются от того чтобы по дампу базы нельзя было бы сломать "словарные" пароли конкретных аккаунтов.

Интересно, получилась ли версия с Runtime CPU dispatching в результате быстрее чем референс с march=native под конкретный сервер. Можно и на этапе деплоймента, а не в рантайме, разбираться какие инструкции есть.

А bcrypt уже считается "устаревшим"?

Ну вот стек gdb в момент SIGSEGV


Стек
Program received signal SIGSEGV, Segmentation fault.
0x00000000004044ae in ctemplate::ArenaAllocator<int, ctemplate::UnsafeArena>::construct (this=0x7fffffffda30, p=0x4) at arena-inl.h:109
109     new(reinterpret_cast<void*>(p)) T();

#0  0x00000000004044ae in ctemplate::ArenaAllocator<int, ctemplate::UnsafeArena>::construct (this=0x7fffffffda30, p=0x4) at arena-inl.h:109
#1  0x0000000000404340 in std::allocator_traits<ctemplate::ArenaAllocator<int, ctemplate::UnsafeArena> >::_S_construct<int> (__a=..., __p=0x4)
    at /usr/include/c++/5/bits/alloc_traits.h:256
#2  0x000000000040417c in std::allocator_traits<ctemplate::ArenaAllocator<int, ctemplate::UnsafeArena> >::construct<int> (__a=..., __p=0x4)
    at /usr/include/c++/5/bits/alloc_traits.h:402
#3  0x0000000000403f41 in std::__uninitialized_default_n_a<int*, unsigned long, ctemplate::ArenaAllocator<int, ctemplate::UnsafeArena> > (__first=0x0, 
    __n=9999999998, __alloc=...)
    at /usr/include/c++/5/bits/stl_uninitialized.h:623
#4  0x0000000000403d13 in std::vector<int, ctemplate::ArenaAllocator<int, ctemplate::UnsafeArena> >::_M_default_append (this=0x7fffffffda30, __n=9999999999)
    at /usr/include/c++/5/bits/vector.tcc:565
#5  0x0000000000403ab3 in std::vector<int, ctemplate::ArenaAllocator<int, ctemplate::UnsafeArena> >::resize (this=0x7fffffffda30, __new_size=9999999999)
    at /usr/include/c++/5/bits/stl_vector.h:676
#6  0x00000000004035bf in test_vector () at main.cc:27
#7  0x000000000040374c in main () at main.cc:55

Что очень логично — resize сразу же начинает конструировать объекты, в данном случае по адресу nullptr.


Наверное у Google очень много памяти) Что более реально — большой набор своих контейнеров.

Как раз для этого есть std::new_handler. Он вызывается, когда памяти перестает хватать.

Ну да, но это происходит в рамках аллокации, пока что управление находится внутри operator new(), то есть невалидный указатель нам никто не возвращает


Обычный паттерн «команда» + какая-нибудь арена, чтобы разом прибить память, затраченную на операцию.

То есть вы сами пишете все строки где вызывается operator new() и можно там везде вызвать именно nothrow-версию?


AllocAligned вернет NULL, если что-то пошло не так.

Это вот этот код?


Любопытный пример.


AllocAligned() вроде бы является по семантике (см комментарии в arena.h) просто malloc, то есть в конце концов он там ссылается на malloc. Но:


  • В AllocNewBlock (цепочка AllocAligned()->GetMemory()->GetMemoryFallback()->AllocNewBlock()) есть вызов new std::vector и скорее всего это обычный глобальный new, из которого может прийти bad_alloc
  • Потом там же есть вызов aligned_malloc и проверка на то что вернулось ненулевое значение.
  • И там же есть вызов обычного malloc, уже безо всяких проверок.

То есть такое впечатление что про это просто не думали c таким ранообразием сценариев обработки этого события. Свидетельством этого же является попытка записать что-то без проверки получилось ли выделить память в классе Gladiator.


Вы уверены что оно там не падает в segmentation fault когда память заканчивается?

Еще раз напоминаю, что проверяется код ОС, где можно встретить все, что угодно. Даже чтение-запись по NULL-указателю не должны вас удивлять.

Я очень удивлюсь если увижу любую реализацию libstdc++ в которой operator new() возвращает валидный адрес 0x0.


А в остальном: во-первых, спасибо за то что было не лень мне отвечать! Интересно подумать что же на самом деле вроде может работать, а что должно быть очень опасно.


TLDR: либо в коде должны быть написано new (std::nothrow), либо он не никогда не должен вернуться к исполнению после неуспеха выделения памяти в operator new.


Полная версия

Безусловно можно в случае нехватки памяти вместо terminate() попытаться сходить осободить кеши и ресурсы, или отменить текущую операцию. Но первое странно выносить за пределы работы с памятью, то есть в приципе это всё можно сделать внутри нашего operator new(). А для второго надо либо реализовывать какой-то вариант корутин (чтобы можно было выкинуть кусок стека который про это ничего не знает), либо код, который это использует, должен быть готов к этому.


Cтандартные контейнеры не готовы в целом к тому что allocate() вернёт невалидный указатель. Тот же самый std::list обязательно попытается слинковать ноды, записав что-то в память.


Наверное, можно попытаться возвращать в allocate() одинковый для всех, но хотя бы writable и хорошо выравненный кусочек памяти. А для std::vector можно внутри MyAllocator::construct() проверять была ли проблема с выделением памяти и если была то ничего не иницаильнизировать. Но тем самым нарушается всё больше и больше контрактов, и на каком-то этапе это может взорваться.


Лучший способ продемнострировать то, что код готов к невалидному указателю — написать лишние 15 символов на каждый new. И всем сразу всё ясно.


А если часть кода этого не ожидает, то надо прервать выполнение текущего стека. Это можно сделать разными способами, но я не могу придумать примеров когда это нужно делать за пределами operator new(), сначала вернув оттуда невалидный указатель.

Получается что libcxx без исключений не соблюдает стандарты? В отличие от libstdc++


new_handler handler = std::get_new_handler ();
if (! handler)
    _GLIBCXX_THROW_OR_ABORT(bad_alloc());
handler ();

Ровно такое поведение я ожидал бы увидеть если exceptions запрещены.


Видимо отклонение от стандарта позволяет писать код быстрее, но потом не надо ожидать что его будет правильно понимать PVS-Studio, когда для семантики return nullptr on fail есть специальный синтаксис, который можно использовать везде вместо обычного new. Так что мне кажется что они в своём праве всегда на это ругаться.


По сравнению с malloc выигрыш в вызове конструктора и (судя по С++ 17) учёту extra type alignment.


И я правильно понимаю что с вашим определением operator new стандартные контейнеры совсем не используются? Потому что вроде они никак нулевой указатель обрабатывать не станут, и действительно лучше было сразу std::terminate делать.

А зачем так надо? Потому что кажется что если код не рассчитан на то, что вернётся nullptr, то там плохо возвращать nullptr, и уж лучше сразу std::terminate() если исключения нельзя. А если код пишется самостоятельно, то что мешает использовать nothrow-версию?

Кстати, по стандарту есть new(std::nothrow), который как раз возвращает nullptr. Никогда сам его не использовал, правда, но работает: https://ideone.com/Z43jcF

Есть вот такая вот серия: http://www.mediahouse.ru/catalogue.html?sel=1122643220#1122643220
А почему никто не валидирует e-mail через oauth-like механизм? И почему ещё gmail не предоставляет возможности web-подтверждения подписок на рассылки/указания e-mail при регистрации? Это же на 100% решает проблему распознавания спама для активационных e-mail.
1. Изменить counter. Например, просто поставить его в 201611 и менять каждый месяц для важных паролей.
3. Если делать с синхронизацией, как предлагают многие, то после компрометации масетр-пароля всё равно надо менять все пароли.
Да не надо же вечно таскать, вполне себе выкидывают std::binary_function, например. Реализация какое-то время бдует содержаться, в этом проблема, да.
Ну нет, всё-таки одновременно два типа строк смешивать не получится нормлаьно, там же сигнатуры разные. Только если через c-интерфейс.

Но вообще вся моя идея была в том что функдамент миграции на новые бинарные и не совсем реализации заложен и вполне себе используется, так что я не очень удивлюсь если когда-то будут совсем выкидывать старые куски, требуя использовать старые компиляторы/библиотеки если что не так.

А сейчас нет чего-нибудь что требует страый gcc для сборки?
А expression-statement — это для lock-guards, или для чего-то ещё?
1

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность