Portabilidade de bcrypt.codeplex.com com segurança aprimorada, correções ausentes, recursos e melhor suporte .net.
Baixe usando nuget ou Paket (https://fsprojects.github.io/Paket/)
Pacote: https://www.nuget.org/packages/BCrypt.Net-Next/
Pacote assinado - https://www.nuget.org/packages/BCrypt.Net-Next.StrongName/
Existem vários exemplos em nossa pasta test-harness e testes unitários
O uso mais simples é o seguinte...
Para hash uma senha:
Namespaces com escopo de arquivo são mostrados; imagine colchetes se precisar.
Top level namespace
namespace DotNetSix ;
using BCrypt . Net ;
string passwordHash = BCrypt . HashPassword ( "my password" ) ;
Devido à nomenclatura da biblioteca, se o namespace estiver após as instruções using, a chamada muda, pois .net não consegue resolver a nomenclatura corretamente. Aconselho, em vez de inserir o namespace inteiro, você simplesmente usa o alias de importação conforme abaixo.
using BC = BCrypt . Net . BCrypt ;
namespace DotNetSix ;
string passwordHash = BC . HashPassword ( "my password" ) ;
Você também pode fazer alias no nível CSProj; e não precisaria adicionar a instrução using
Este exemplo permitiria que você usasse um alias BC.HashPassword() em seu código
< ItemGroup >
<!-- emits global using BcryptNet = global::BCrypt.Net.BCrypt; -->
< Using Include = " BCrypt.Net.BCrypt " Alias = " BC " />
</ ItemGroup >
Esta versão permitiria apenas chamar Verify
e HashPassword
em sua base de código sem qualquer outra referência.
< ItemGroup >
<!-- emits global using static global::BCrypt.Net.BCrypt; -->
< Using Include = " BCrypt.Net.BCrypt " Static = " True " />
</ ItemGroup >
Nota: Embora esta biblioteca permita que você forneça seu próprio sal, é altamente recomendável que você permita que a biblioteca gere o sal para você. Esses métodos são fornecidos para manter a compatibilidade e para requisitos de plataforma cruzada mais avançados que podem exigir seu uso.
Para verificar uma senha em relação a um hash (supondo que você armazenou o hash e o recuperou do armazenamento para verificação):
Todas as notas anteriores sobre namespace também se aplicam aqui
BCrypt . Verify ( "my password" , passwordHash ) ;
Esta implementação em hash irá gerar um salt automaticamente para você com o fator de trabalho (2 ^ número de rodadas) definido como 11 (que corresponde ao padrão na maioria das implementações e atualmente é visto como um bom nível de segurança/risco).
Para economizar matemática, uma pequena tabela cobrindo as iterações é fornecida abaixo. O mínimo permitido nesta biblioteca é 4 para compatibilidade, o máximo é 31 (aos 31 seu processador estará desejando a morte).
| 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
e um benchmark simples que você pode executar criando um programa de console, adicionando esta biblioteca BCrypt e usando este código.
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 ( ) ;
Isso começará em 16, o que equivale a 65,536 iterations
, e reduzirá o custo até que a meta de tempo seja atingida. Depende de você o que você considera um tempo permitido, mas se estiver abaixo de 10, aconselho seriamente deixá-lo em 10 e talvez investir em um pacote de servidor maior.
O limite de senha recomendado de 56 bytes (incluindo byte de terminação nulo) para bcrypt está relacionado ao limite de 448 bits da chave Blowfish; Quaisquer bytes além desse limite não são totalmente misturados ao hash, tornando o limite absoluto de 72 bytes em senhas bcrypt menos relevante, considerando o efeito real desses bytes no hash resultante.
Outras linguagens lidaram com esse problema percebido pré-hashing da frase secreta/senha para aumentar a entropia usada, sendo o dropbox um dos artigos mais públicos sobre isso.
Você pode optar pelo hash aprimorado simplesmente usando o código a seguir (basicamente prefixando as chamadas de método com Aprimorado)
var enhancedHashPassword = BCrypt . EnhancedHashPassword ( myPassword ) ;
var validatePassword = BCrypt . EnhancedVerify ( myPassword , enhancedHashPassword ) ;
Por padrão, a biblioteca usa hash SHA384 da senha, o material gerado é então passado para o bcrypt para formar seu hash por meio da rotina normal do bcrypt. Se você deseja especificar uma versão diferente do SHA, ou apenas deseja definir explicitamente em seu código a versão usada caso ela mude em uma versão principal da biblioteca, você pode fazer isso usando a seguinte alteração acima.
var enhancedHashPassword = BCrypt . EnhancedHashPassword ( myPassword , hashType : HashType . SHA384 ) ;
var validatePassword = BCrypt . EnhancedVerify ( myPassword , enhancedHashPassword , hashType : HashType . SHA384 ) ;
Por que SHA384? É um bom equilíbrio entre desempenho, segurança, proteção contra colisão e é a única versão que não era vulnerável a ataques de extensão de comprimento https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash -ataques de extensão de comprimento.
Devo usar Entropia Aprimorada? Você não perde nada ao usá-lo
Por que eu precisaria alterar o tipo SHA? Algumas bibliotecas como PassLib hash usando SHA256, portanto, principalmente uma questão de compatibilidade. O DropBox usou SHA512, portanto, se você trabalhou no Dropbox, deseja compatibilidade. A melhoria é principalmente uma extensão de conveniência, pois você já pode pré-hash e passar para as chamadas de método padrão.
O que isso faz? Pegamos os bytes utf8 da sua senha como inputBytes SHA hash, convertemos para base64 (para compatibilidade com outras implementações de linguagem) e usamos esses bytes para executar a chamada bcrypt padrão.
Você precisará de pelo menos VS2022 com o SDK atual https://www.microsoft.com/net/download;
Os pacotes nuget podem ser compilados executando buildfornuget.cmd
ou
dotnet restore . s rc
dotnet pack . s rc B Crypt.Net --configuration Release
Você pode executar os testes a partir da pasta principal digitando dotnet test .srcBCrypt.Net.UnitTests
A execução de TestGenerateSaltWithMaxWorkFactor
levará um tempo significativo.
Uma porta .Net do jBCrypt implementada em C#. Ele usa uma variante da programação de codificação do algoritmo de criptografia Blowfish e introduz um fator de trabalho, que permite determinar o quão cara a função hash será, permitindo que o algoritmo seja "à prova de futuro".
Esta é, para todos os efeitos, uma versão direta do jBCrypt escrita por Damien Miller. As principais diferenças são a adição de alguns métodos de conveniência e algumas refatorações leves. A maneira mais fácil de verificar a paridade do BCrypt.Net com o jBCrypt é comparar os testes de unidade.
Para uma visão geral de por que o BCrypt é importante, consulte Como armazenar uma senha com segurança. Em geral, é um algoritmo de hash que pode ser ajustado ao longo do tempo para exigir mais potência da CPU para gerar os hashes. Isto, em essência, proporciona alguma proteção contra a Lei de Moore. Ou seja, à medida que os computadores ficam mais rápidos, esse algoritmo pode ser ajustado para exigir mais potência da CPU. Quanto mais energia da CPU for necessária para fazer o hash de uma determinada senha, mais tempo um “hacker” deve investir, por senha. Como o "fator de trabalho" está incorporado no hash resultante, os hashes gerados por este algoritmo são compatíveis com versões anteriores e posteriores.
Ele usa uma variante da programação de codificação do algoritmo de criptografia Blowfish e introduz um fator de trabalho, que permite determinar o quão cara será a função hash. Por causa disso, o BCrypt pode acompanhar a lei de Moore. À medida que os computadores ficam mais rápidos, você pode aumentar o fator de trabalho e o hash ficará mais lento.
Niels Provos e David Mazières projetaram um esquema crypt() chamado bcrypt baseado em Blowfish e o apresentaram na USENIX em 1999.[14]
A forma imprimível desses hashes começa com
$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$.
Em primeiro lugar, esta biblioteca se originou como uma versão do jBCrypt do mindrot
e, posteriormente, a revisão do bcrypt foi definida para corresponder, que neste caso é $2a$
. Isso foi alterado porque lidar apenas com a revisão única causa problemas entre plataformas com implementações que mudaram sua revisão para lidar com migrações e outros problemas.
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'.
Não há diferença entre 2a, 2x, 2y e 2b. Todos eles produzem o mesmo resultado.
as notas de lançamento estão aqui https://github.com/BcryptNet/bcrypt.net/releases
v4.0.3 - Adição de segmentação .net 6; arrumar alvos.
v4.0.2 - Adição de segmentação .net 5; envolva a criação shaxxx
usando para liberar.
v4.0.0 (alterações importantes) - Foi descoberto um bug no Enhanced Hashing
que faz com que os hashes criados fiquem inoperantes entre diferentes idiomas. V4 fornece a correção para isso, bem como adiciona vetores de teste de PHP e Python para garantir que o problema permaneça corrigido no futuro. A V4 também remove a opção 384 herdada que veio antes da adição do Base64.
v3.5.0 - Foi descoberto um bug no Enhanced Hashing
que faz com que os hashes criados fiquem inoperantes entre diferentes idiomas. Como parte da correção, a versão 3.5 contém a capacidade de Verify
e HashPassword
recebeu um parâmetro v4CompatibleEnhancedEntropy
adicional. Isso permite que o usuário verifique seu hash aprimorado normalmente; em seguida, re-hash + store usando V4. Esta funcionalidade serve apenas para permitir a migração e foi removida na V4.
v3.3.3 -Desempenho (redução de heap) para netcore e remoção de regex https://github.com/BcryptNet/bcrypt.net/releases/tag/3.3.0
v2.1.3 -
v2.1.2 -
PasswordNeedsReshash
para PasswordNeedsRehash
v2.1.1 -
v2.1.0 -
PasswordNeedsReshash(string hash, int newMinimumWorkLoad)
como um método auxiliar para os desenvolvedores usarem ao fazer login de um usuário para aumentar as cargas de trabalho legadasValidateAndReplacePassword
para permitir a validação e substituição de senha embutida. Lança BcryptAuthenticationException
em caso de falha de autenticação.v2.0.1 -
v2.0.0 -
Nova versão empacotada para a maioria do .net e contendo igualdades seguras para reduzir os riscos de ataques de temporização https://en.wikipedia.org/wiki/Timing_attack / https://cryptocoding.net/index.php/Coding_rules#Compare_secret_strings_in_constant_time Tecnicamente, os detalhes de implementação do BCrypt mitigam teoricamente os ataques de temporização. Mas a função de validação oficial do Bcrypt.net era vulnerável a ataques de temporização, pois retornava assim que um byte não correspondente era encontrado na comparação de hash.