Портирование bcrypt.codeplex.com с повышенной безопасностью, недостающими исправлениями, функциями и улучшенной поддержкой .net.
Загрузите с помощью nuget или Paket (https://fsprojects.github.io/Paket/)
Пакет: https://www.nuget.org/packages/BCrypt.Net-Next/
Подписанный пакет — https://www.nuget.org/packages/BCrypt.Net-Next.StrongName/
В нашей папке test-harness и unit-tests есть различные примеры.
Простейшее использование заключается в следующем...
Чтобы хешировать пароль:
Показаны пространства имен в области файлов; представьте себе фигурные скобки, если вам нужно.
Top level namespace
namespace DotNetSix ;
using BCrypt . Net ;
string passwordHash = BCrypt . HashPassword ( "my password" ) ;
Из-за именования библиотеки, если пространство имен находится после операторов using, вызов меняется, поскольку .net не может правильно разрешить именование, я бы посоветовал вместо того, чтобы вводить все пространство имен, просто использовать псевдоним импорта, как показано ниже.
using BC = BCrypt . Net . BCrypt ;
namespace DotNetSix ;
string passwordHash = BC . HashPassword ( "my password" ) ;
Вы также можете использовать псевдонимы на уровне CSProj; и вообще не нужно будет добавлять оператор using
Этот пример позволит вам использовать псевдоним BC.HashPassword() в вашем коде.
< ItemGroup >
<!-- emits global using BcryptNet = global::BCrypt.Net.BCrypt; -->
< Using Include = " BCrypt.Net.BCrypt " Alias = " BC " />
</ ItemGroup >
Эта версия позволит вам просто вызывать Verify
и HashPassword
в вашей базе кода без каких-либо других ссылок.
< ItemGroup >
<!-- emits global using static global::BCrypt.Net.BCrypt; -->
< Using Include = " BCrypt.Net.BCrypt " Static = " True " />
</ ItemGroup >
Примечание. Хотя эта библиотека позволяет вам предоставлять свою собственную соль, настоятельно рекомендуется разрешить ей генерировать соль за вас. Эти методы предоставляются для обеспечения совместимости и для более сложных межплатформенных требований, которые могут потребовать их использования.
Чтобы проверить пароль по хешу (при условии, что вы сохранили хеш и извлекли его из хранилища для проверки):
Все предыдущие замечания о пространстве имен применимы и здесь.
BCrypt . Verify ( "my password" , passwordHash ) ;
Эта реализация хеширования автоматически сгенерирует для вас соль с рабочим коэффициентом (2^количество раундов), установленным на 11 (что соответствует значению по умолчанию для большинства реализаций и в настоящее время рассматривается как хороший уровень безопасности/риска).
Чтобы избавить вас от математики, ниже представлена небольшая таблица, описывающая итерации. Минимально допустимое значение в этой библиотеке — 4 для совместимости, максимальное — 31 (при 31 ваш процессор будет желать смерти).
| Cost | Iterations |
|-------|--------------------------|
| 8 | 256 iterations |
| 9 | 512 iterations |
| 10 | 1,024 iterations |
| 11 | 2,048 iterations |
| 12 | 4,096 iterations |
| 13 | 8,192 iterations |
| 14 | 16,384 iterations |
| 15 | 32,768 iterations |
| 16 | 65,536 iterations |
| 17 | 131,072 iterations |
| 18 | 262,144 iterations |
| 19 | 524,288 iterations |
| 20 | 1,048,576 iterations |
| 21 | 2,097,152 iterations |
| 22 | 4,194,304 iterations |
| 23 | 8,388,608 iterations |
| 24 | 16,777,216 iterations |
| 25 | 33,554,432 iterations |
| 26 | 67,108,864 iterations |
| 27 | 134,217,728 iterations |
| 28 | 268,435,456 iterations |
| 29 | 536,870,912 iterations |
| 30 | 1,073,741,824 iterations |
| 31 | 2,147,483,648 iterations |
etc
и простой тест, который вы можете запустить, создав консольную программу, добавив библиотеку BCrypt и используя этот код.
var cost = 16 ;
var timeTarget = 100 ; // Milliseconds
long timeTaken ;
do
{
var sw = Stopwatch . StartNew ( ) ;
BCrypt . HashPassword ( "RwiKnN>9xg3*C)1AZl.)y8f_:GCz,vt3T]PI" , workFactor : cost ) ;
sw . Stop ( ) ;
timeTaken = sw . ElapsedMilliseconds ;
cost -= 1 ;
} while ( ( timeTaken ) >= timeTarget ) ;
Console . WriteLine ( "Appropriate Cost Found: " + ( cost + 1 ) ) ;
Console . ReadLine ( ) ;
Это начнется с 16, что составляет 65,536 iterations
, и приведет к снижению затрат до тех пор, пока не будет достигнуто целевое время. Вам решать, какое время вы считаете допустимым, но если оно ниже 10, я бы серьезно посоветовал оставить его равным 10 и, возможно, инвестировать в более крупный серверный пакет.
Рекомендуемый предел пароля в 56 байт (включая нулевой байт завершения) для bcrypt соответствует пределу в 448 бит ключа Blowfish; Любые байты, превышающие этот предел, не полностью смешиваются с хешем, что делает абсолютный предел в 72 байта для паролей bcrypt менее актуальным, учитывая фактическое влияние этих байтов на результирующий хэш.
Другие языки решают эту предполагаемую проблему путем предварительного хеширования парольной фразы/пароля для увеличения используемой энтропии, Dropbox является одной из наиболее общедоступных статей по этому поводу.
Вы можете выбрать расширенное хеширование, просто используя следующий код (в основном с префиксом вызовов методов Enhanced)
var enhancedHashPassword = BCrypt . EnhancedHashPassword ( myPassword ) ;
var validatePassword = BCrypt . EnhancedVerify ( myPassword , enhancedHashPassword ) ;
По умолчанию библиотека использует хеширование парольной фразы SHA384, затем сгенерированный материал передается в bcrypt для формирования хеша с помощью обычной процедуры bcrypt. Если вы хотите указать другую версию SHA или просто хотите явно указать в своем коде используемую версию на случай, если она когда-либо изменится в основной версии библиотеки, вы можете сделать это, используя следующее изменение к приведенному выше.
var enhancedHashPassword = BCrypt . EnhancedHashPassword ( myPassword , hashType : HashType . SHA384 ) ;
var validatePassword = BCrypt . EnhancedVerify ( myPassword , enhancedHashPassword , hashType : HashType . SHA384 ) ;
Почему SHA384? Это хороший баланс производительности, безопасности, защиты от коллизий и единственная версия, которая не была уязвима для атак с расширением длины https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash -длина-расширение-атаки.
Должен ли я использовать расширенную энтропию? Вы ничего не теряете, используя его
Зачем мне менять тип SHA? Некоторые библиотеки, такие как хэш PassLib, используют SHA256, так что в основном это вопрос совместимости. DropBox использовал SHA512, поэтому, если вы работали в Dropbox, вам нужна совместимость. Это улучшение в основном является расширением удобства, поскольку вы уже можете предварительно хешировать и передавать стандартные вызовы методов.
Что он делает? Мы берем байты utf8 вашего пароля в качестве хэш-кода inputBytes SHA, преобразуем их в base64 (для совместимости с другими языковыми реализациями), а затем используем эти байты для выполнения стандартного вызова bcrypt.
Вам понадобится как минимум VS2022 с текущим SDK https://www.microsoft.com/net/download;
Пакеты nuget можно собрать, запустив buildfornuget.cmd
или
dotnet restore . s rc
dotnet pack . s rc B Crypt.Net --configuration Release
Вы можете запустить тесты из основной папки, набрав dotnet test .srcBCrypt.Net.UnitTests
Выполнение TestGenerateSaltWithMaxWorkFactor
займет значительное время.
.Net-порт jBCrypt, реализованный на C#. Он использует вариант расписания ключей алгоритма шифрования Blowfish и вводит рабочий коэффициент, который позволяет вам определить, насколько дорогой будет хэш-функция, что позволяет алгоритму быть «готовым к будущему».
По сути, это прямой порт jBCrypt, написанный Дэмиеном Миллером. Основные отличия заключаются в добавлении некоторых удобных методов и небольшом рефакторинге. Самый простой способ проверить четность BCrypt.Net с jBCrypt — сравнить модульные тесты.
Обзор того, почему BCrypt важен, см. в разделе «Как безопасно хранить пароль». В общем, это алгоритм хеширования, который со временем можно корректировать, чтобы требовать больше мощности процессора для генерации хэшей. По сути, это обеспечивает некоторую защиту от закона Мура. То есть по мере того, как компьютеры становятся быстрее, этот алгоритм можно настроить так, чтобы он требовал большей мощности процессора. Чем больше мощности процессора требуется для хеширования данного пароля, тем больше времени «хакер» должен потратить на каждый пароль. Поскольку «рабочий фактор» встроен в результирующий хеш, хэши, генерируемые этим алгоритмом, являются прямыми и обратными совместимыми.
Он использует вариант расписания ключей алгоритма шифрования Blowfish и вводит рабочий коэффициент, который позволяет определить, насколько дорогой будет хеш-функция. Благодаря этому BCrypt может соответствовать закону Мура. По мере того, как компьютеры становятся быстрее, вы можете увеличить рабочий коэффициент, и хэш будет замедляться.
Нильс Провос и Дэвид Мазьер разработали схему crypt() под названием bcrypt на основе Blowfish и представили ее на USENIX в 1999 году.[14]
Печатная форма этих хешей начинается с
$2$ – Currently obsolete
$2a$ – The current key used to identify this scheme.
Since a major security flaw was discovered in 2011 in a third-party implementation of the algorithm,
hashes indicated by this string are now ambiguous and might have been generated by the flawed
implementation, or a subsequent fixed, implementation.
The flaw may be triggered by some password strings containing non-ASCII characters, such as specially
crafted password strings.
$2b$ – Used by some recent implementations which include a mitigation to a wraparound problem.
Previous versions of the algorithm have a problem with long passwords. By design, long passwords
are truncated at 72 characters, but there is an 8-bit wraparound problem with certain password
lengths resulting in weak hashes.
$2x$ – Post-2011 bug discovery, old hashes can be renamed to be $2x$ to indicate that they were generated with
the broken algorithm. These hashes are still weak, but at least it's clear which algorithm was used to
generate them.
$2y$ – Post Post-2011 bug discovery, $2y$ may be used to unambiguously use the new, corrected algorithm. On an
implementation suffering from the bug, $2y$ simply won't work. On a newer, fixed implementation, it will
produce the same result as using $2a$.
Прежде всего, эта библиотека возникла как порт jBCrypt от mindrot
, и впоследствии была установлена соответствующая ревизия bcrypt, которая в данном случае равна $2a$
. Это было изменено, поскольку обработка только одной ревизии приводит к проблемам с кросс-платформенностью, когда реализации, которые переместились, изменили свою ревизию для обработки миграций и других проблем.
The original bcrypt code (released in OpenBSD 2.1) identified itself as
$2$. Shortly after release, a bug was fixed and the hash identifier
changed to $2a$. Support for "minor" versions wasn't really
planned, but it was backwards compatible.
Solar Designer wrote a second implementation of bcrypt. This
reimplementation suffered from a flaw dealing with 8 bit characters
and led to the introduction of the 'x' and 'y' flavours. OpenBSD did
not have this problem and supports neither 'x' nor 'y' hash versions.
---
Solar found a bug in their OpenBSD implementation of bcrypt when hashing
long passwords. The length is stored in an unsigned char type, which
will overflow and wrap at 256. Although we consider the existence of
affected hashes very rare, in order to differentiate hashes generated
before and after the fix, we are introducing a new minor 'b'.
OpenBSD 5.5 (coming this spring) will accept and verify 'b' hashes,
although it will still generate 'a' hashes. OpenBSD 5.6 (coming this
fall) will change to generating 'b' hashes by default.
A future release of Solar's bcrypt code should also support 'b'.
Нет никакой разницы между 2a, 2x, 2y и 2b. Все они выдают один и тот же результат.
примечания к выпуску находятся здесь https://github.com/BcryptNet/bcrypt.net/releases
v4.0.3 — Добавлен таргетинг на .net 6; привести в порядок цели.
v4.0.2 — Добавлен таргетинг на .net 5; оберните создание shaxxx
в использование для выпуска.
v4.0.0 (критические изменения) — обнаружена ошибка в Enhanced Hashing
, из-за которой созданные хэши становятся неработоспособными на разных языках. Версия 4 содержит исправление этой проблемы, а также добавляет тестовые векторы из PHP и Python, чтобы гарантировать, что проблема останется устраненной в будущем. В версии 4 также удалена устаревшая опция 384, которая существовала до добавления Base64.
v3.5.0 — Обнаружена ошибка в Enhanced Hashing
, из-за которой созданные хэши становятся неработоспособными на разных языках. В рамках исправления версии 3.5 появилась возможность Verify
, а HashPassword
получил дополнительный параметр v4CompatibleEnhancedEntropy
. Это позволяет пользователю проверять свой расширенный хеш как обычно; затем перехешируйте + сохраните, используя V4. Эта функция предназначена исключительно для обеспечения миграции и удалена в версии V4.
v3.3.3 -Производительность (уменьшение кучи) для сетевого ядра и удаление регулярных выражений https://github.com/BcryptNet/bcrypt.net/releases/tag/3.3.0
v2.1.3 -
v2.1.2 -
PasswordNeedsReshash
на PasswordNeedsRehash
v2.1.1 -
v2.1.0 -
PasswordNeedsReshash(string hash, int newMinimumWorkLoad)
в качестве вспомогательного метода, который разработчики смогут использовать при входе пользователя в систему для увеличения устаревших рабочих нагрузок.ValidateAndReplacePassword
, чтобы разрешить встроенную проверку и замену пароля. Выдает исключение BcryptAuthenticationException
в случае сбоя аутентификации.v2.0.1 -
v2.0.0 -
Свежий выпуск, упакованный для большинства .net и содержащий безопасные эквиваленты для снижения рисков от атак по времени https://en.wikipedia.org/wiki/Timing_attack / https://cryptocoding.net/index.php/Coding_rules#Compare_secret_strings_in_constant_time Технически детали реализации BCrypt теоретически защищают от атак по времени. Но официальная функция проверки Bcrypt.net была уязвима для атак по времени, поскольку она возвращалась, как только при сравнении хэшей был обнаружен несовпадающий байт.