Migración de bcrypt.codeplex.com con seguridad mejorada, correcciones faltantes, características y mejor soporte para .net.
Descargue usando nuget o Paket (https://fsprojects.github.io/Paket/)
Paquete: https://www.nuget.org/packages/BCrypt.Net-Next/
Paquete firmado: https://www.nuget.org/packages/BCrypt.Net-Next.StrongName/
Hay varios ejemplos en nuestra carpeta de pruebas de arnés y pruebas unitarias.
El uso más simple es el siguiente...
Para codificar una contraseña:
Se muestran los espacios de nombres con ámbito de archivo; imagina llaves si es necesario.
Top level namespace
namespace DotNetSix ;
using BCrypt . Net ;
string passwordHash = BCrypt . HashPassword ( "my password" ) ;Debido al nombre de la biblioteca, si el espacio de nombres está después de las declaraciones de uso, la llamada cambia ya que .net no resuelve el nombre correctamente. Le recomiendo que, en lugar de ingresar todo el espacio de nombres, simplemente use el alias de importación como se muestra a continuación.
using BC = BCrypt . Net . BCrypt ;
namespace DotNetSix ;
string passwordHash = BC . HashPassword ( "my password" ) ;También puede crear alias en el nivel CSProj; y no sería necesario agregar la declaración de uso en absoluto
Este ejemplo le permitiría utilizar un alias BC.HashPassword() en su código
< ItemGroup >
<!-- emits global using BcryptNet = global::BCrypt.Net.BCrypt; -->
< Using Include = " BCrypt.Net.BCrypt " Alias = " BC " />
</ ItemGroup > Esta versión le permitiría simplemente llamar Verify y HashPassword en su código base sin ninguna otra referencia.
< ItemGroup >
<!-- emits global using static global::BCrypt.Net.BCrypt; -->
< Using Include = " BCrypt.Net.BCrypt " Static = " True " />
</ ItemGroup >Nota: Aunque esta biblioteca le permite suministrar su propia sal, es muy recomendable que permita que la biblioteca genere la sal por usted. Estos métodos se proporcionan para mantener la compatibilidad y para requisitos multiplataforma más avanzados que puedan requerir su uso.
Para verificar una contraseña con un hash (suponiendo que haya almacenado el hash y lo haya recuperado del almacenamiento para su verificación):
Todas las notas anteriores sobre el espacio de nombres también se aplican aquí
BCrypt . Verify ( "my password" , passwordHash ) ;Esta implementación de hash generará un salt automáticamente con el factor de trabajo (2^número de rondas) establecido en 11 (que coincide con el valor predeterminado en la mayoría de las implementaciones y actualmente se considera un buen nivel de seguridad/riesgo).
Para ahorrarle los cálculos, a continuación se proporciona una pequeña tabla que cubre las iteraciones. El mínimo permitido en esta biblioteca es 4 por compatibilidad, el máximo es 31 (a los 31 tu procesador estará deseando morir).
| 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
y un punto de referencia simple que puede ejecutar creando un programa de consola, agregando esta biblioteca BCrypt y 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 ( ) ; Esto comenzará en 16, que son 65,536 iterations y reducirá el costo hasta alcanzar el tiempo objetivo. Depende de usted lo que considere un tiempo permitido, pero si es inferior a 10, le recomendaría seriamente dejarlo en 10 y tal vez invertir en un paquete de servidor más grande.
El límite de contraseña recomendado de 56 bytes (incluido el byte de terminación nula) para bcrypt se relaciona con el límite de 448 bits de la clave Blowfish; Cualquier byte que supere ese límite no se mezcla completamente en el hash, lo que hace que el límite absoluto de 72 bytes en las contraseñas de bcrypt sea menos relevante considerando el efecto real de esos bytes en el hash resultante.
Otros lenguajes han manejado este problema percibido mediante un hash previo de la frase de contraseña/contraseña para aumentar la entropía utilizada, siendo Dropbox uno de los artículos más públicos sobre esto.
Puede optar por el hash mejorado simplemente usando el siguiente código (básicamente anteponiendo las llamadas al método con Mejorado)
var enhancedHashPassword = BCrypt . EnhancedHashPassword ( myPassword ) ;
var validatePassword = BCrypt . EnhancedVerify ( myPassword , enhancedHashPassword ) ;De forma predeterminada, la biblioteca utiliza hash SHA384 de la frase de contraseña, el material generado luego se pasa a bcrypt para formar su hash a través de la rutina habitual de bcrypt. Si desea especificar una versión diferente de SHA, o simplemente desea establecer explícitamente en su código la versión utilizada en caso de que alguna vez cambie en una versión principal de la biblioteca, puede hacerlo utilizando el siguiente cambio a lo anterior.
var enhancedHashPassword = BCrypt . EnhancedHashPassword ( myPassword , hashType : HashType . SHA384 ) ;
var validatePassword = BCrypt . EnhancedVerify ( myPassword , enhancedHashPassword , hashType : HashType . SHA384 ) ;¿Por qué SHA384? Es un buen equilibrio entre rendimiento, seguridad, protección contra colisiones y es la única versión que no fue vulnerable a ataques de extensión de longitud https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash -ataques-de-extensión-de-longitud.
¿Debería utilizar entropía mejorada? No pierdes nada al usarlo
¿Por qué necesitaría cambiar el tipo SHA? Algunas bibliotecas como PassLib hash usan SHA256, por lo que principalmente es una cuestión de compatibilidad. DropBox usó SHA512, por lo que si trabajaras en Dropbox querrás compatibilidad. La mejora es principalmente una extensión conveniente en el sentido de que ya se puede realizar un hash previo y pasar a las llamadas al método estándar.
¿Qué hace? Tomamos los bytes utf8 de su contraseña como hash inputBytes SHA, los convertimos a base64 (para compatibilidad con implementaciones de otros idiomas) y luego usamos esos bytes para realizar la llamada bcrypt estándar.
Necesitará al menos VS2022 con el SDK actual https://www.microsoft.com/net/download;
Los paquetes nuget se pueden compilar ejecutando buildfornuget.cmd o
dotnet restore . s rc
dotnet pack . s rc B Crypt.Net --configuration Release Puede ejecutar las pruebas desde la carpeta principal escribiendo dotnet test .srcBCrypt.Net.UnitTests Ejecutar TestGenerateSaltWithMaxWorkFactor llevará mucho tiempo.
Un puerto .Net de jBCrypt implementado en C#. Utiliza una variante del programa de codificación del algoritmo de cifrado Blowfish e introduce un factor de trabajo que le permite determinar qué tan costosa será la función hash, lo que permite que el algoritmo esté "preparado para el futuro".
Este es, para todos los efectos, una adaptación directa de jBCrypt escrita por Damien Miller. Las principales diferencias son la adición de algunos métodos de conveniencia y una ligera refactorización. La forma más sencilla de verificar la paridad de BCrypt.Net con jBCrypt es comparar las pruebas unitarias.
Para obtener una descripción general de por qué BCrypt es importante, consulte Cómo almacenar una contraseña de forma segura. En general, es un algoritmo hash que se puede ajustar con el tiempo para requerir más potencia de CPU para generar los hashes. Esto, en esencia, proporciona cierta protección contra la Ley de Moore. Es decir, a medida que las computadoras se vuelven más rápidas, este algoritmo se puede ajustar para requerir más potencia de CPU. Cuanta más potencia de CPU se requiera para codificar una contraseña determinada, más tiempo deberá invertir un "hacker", por contraseña. Dado que el "factor de trabajo" está integrado en el hash resultante, los hashes generados por este algoritmo son compatibles con versiones anteriores y posteriores.
Utiliza una variante del programa de claves del algoritmo de cifrado Blowfish e introduce un factor de trabajo, que le permite determinar qué tan costosa será la función hash. Debido a esto, BCrypt puede mantenerse al día con la ley de Moore. A medida que las computadoras se vuelven más rápidas, puede aumentar el factor de trabajo y el hash se volverá más lento.
Niels Provos y David Mazières diseñaron un esquema crypt() llamado bcrypt basado en Blowfish y lo presentaron en USENIX en 1999.[14]
La forma imprimible de estos hashes comienza con
$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$.
En primer lugar, esta biblioteca se originó como una adaptación de jBCrypt de mindrot y, posteriormente, se configuró la revisión de bcrypt para que coincidiera, que en este caso es $2a$ . Esto se ha cambiado ya que manejar solo una revisión única causa problemas multiplataforma con implementaciones que cambiaron su revisión para manejar migraciones y otros 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'.
No hay diferencia entre 2a, 2x, 2y y 2b. Todos dan el mismo resultado.
las notas de la versión están aquí https://github.com/BcryptNet/bcrypt.net/releases
v4.0.3 - Adición de segmentación .net 6; ordenar los objetivos.
v4.0.2 - Adición de segmentación .net 5; envuelva la creación shaxxx usando para liberar.
v4.0.0 (cambios importantes) : se descubrió un error en Enhanced Hashing que hace que los hash creados no funcionen entre diferentes idiomas. V4 proporciona la solución para esto, además de agregar vectores de prueba de PHP y Python para garantizar que el problema siga solucionado en el futuro. V4 también elimina la opción 384 heredada que venía antes de que se agregara Base64.
v3.5.0 : se descubrió un error en Enhanced Hashing que hace que los hashes creados no funcionen entre diferentes idiomas. Como parte de la solución, la versión 3.5 contiene la capacidad de Verify y HashPassword se le proporcionó un parámetro v4CompatibleEnhancedEntropy adicional. Esto permite al usuario verificar su hash mejorado como de costumbre; luego vuelva a hacer hash + almacenar usando V4. Esta funcionalidad es únicamente para permitir la migración y se elimina en V4.
v3.3.3 -Rendimiento (reducción del montón) para netcore y eliminación de expresiones regulares https://github.com/BcryptNet/bcrypt.net/releases/tag/3.3.0
v2.1.3 -
v2.1.2 -
PasswordNeedsReshash a PasswordNeedsRehashv2.1.1 -
v2.1.0 -
PasswordNeedsReshash(string hash, int newMinimumWorkLoad) como método auxiliar para que los desarrolladores lo utilicen al iniciar sesión como usuario para aumentar las cargas de trabajo heredadas.ValidateAndReplacePassword para permitir la validación y el reemplazo de contraseñas en línea. Lanza BcryptAuthenticationException en caso de error de autenticación.v2.0.1 -
v2.0.0 -
Versión nueva empaquetada para la mayoría de .net y que contiene valores seguros para reducir los riesgos de ataques de tiempo https://en.wikipedia.org/wiki/Timing_attack / https://cryptocoding.net/index.php/Coding_rules#Compare_secret_strings_in_constant_time Técnicamente, los detalles de implementación de BCrypt teóricamente mitigan los ataques de sincronización. Pero la función de validación oficial de Bcrypt.net era vulnerable a ataques de sincronización, ya que regresaba tan pronto como se encontraba un byte que no coincidía en la comparación de hash.