@@ -596,7 +596,7 @@ public static string ValidateAndReplacePassword(string currentKey, string curren
596596 /// <returns>The hashed password</returns>
597597 /// <exception cref="ArgumentNullException">Thrown when the <paramref name="inputKey"/> is null.</exception>
598598 /// <exception cref="SaltParseException">Thrown when the <paramref name="salt"/> could not be parsed.</exception>
599- public static string HashPassword ( string inputKey , string salt , bool enhancedEntropy , HashType hashType = DefaultEnhancedHashType )
599+ public static string HashPassword ( string inputKey , string salt , bool enhancedEntropy , HashType hashType = DefaultEnhancedHashType , bool v4CompatibleEnhancedEntropy = false )
600600 {
601601 if ( inputKey == null )
602602 {
@@ -653,10 +653,14 @@ public static string HashPassword(string inputKey, string salt, bool enhancedEnt
653653
654654 byte [ ] inputBytes ;
655655
656- if ( enhancedEntropy )
656+ if ( enhancedEntropy && v4CompatibleEnhancedEntropy )
657657 {
658658 inputBytes = EnhancedHash ( SafeUTF8 . GetBytes ( inputKey ) , bcryptMinorRevision , hashType ) ;
659659 }
660+ else if ( enhancedEntropy )
661+ {
662+ inputBytes = V3EnhancedHash ( SafeUTF8 . GetBytes ( inputKey + ( bcryptMinorRevision >= 'a' ? Nul : EmptyString ) ) , hashType ) ;
663+ }
660664 else
661665 {
662666 inputBytes = SafeUTF8 . GetBytes ( inputKey + ( bcryptMinorRevision >= 'a' ? Nul : EmptyString ) ) ;
@@ -704,6 +708,29 @@ private static byte[] EnhancedHash(byte[] inputBytes, char bcryptMinorRevision,
704708 return inputBytes ;
705709 }
706710
711+ private static byte [ ] V3EnhancedHash ( byte [ ] inputBytes , HashType hashType )
712+ {
713+ switch ( hashType )
714+ {
715+ case HashType . SHA256 :
716+ inputBytes = SafeUTF8 . GetBytes ( Convert . ToBase64String ( SHA256 . Create ( ) . ComputeHash ( inputBytes ) ) ) ;
717+ break ;
718+ case HashType . SHA384 :
719+ inputBytes = SafeUTF8 . GetBytes ( Convert . ToBase64String ( SHA384 . Create ( ) . ComputeHash ( inputBytes ) ) ) ;
720+ break ;
721+ case HashType . SHA512 :
722+ inputBytes = SafeUTF8 . GetBytes ( Convert . ToBase64String ( SHA512 . Create ( ) . ComputeHash ( inputBytes ) ) ) ;
723+ break ;
724+ case HashType . Legacy384 :
725+ inputBytes = SHA384 . Create ( ) . ComputeHash ( inputBytes ) ;
726+ break ;
727+ default :
728+ throw new ArgumentOutOfRangeException ( nameof ( hashType ) , hashType , null ) ;
729+ }
730+
731+ return inputBytes ;
732+ }
733+
707734
708735 /// <summary>
709736 /// Generate a salt for use with the <see cref="BCrypt.HashPassword(string, string)"/> method.
@@ -803,9 +830,9 @@ public static string GenerateSalt()
803830 /// <returns>true if the passwords match, false otherwise.</returns>
804831 /// <exception cref="ArgumentException">Thrown when one or more arguments have unsupported or illegal values.</exception>
805832 /// <exception cref="SaltParseException">Thrown when the salt could not be parsed.</exception>
806- public static bool Verify ( string text , string hash , bool enhancedEntropy = false , HashType hashType = DefaultEnhancedHashType )
833+ public static bool Verify ( string text , string hash , bool enhancedEntropy = false , HashType hashType = DefaultEnhancedHashType , bool v4CompatibleEnhancedEntropy = false )
807834 {
808- return SecureEquals ( SafeUTF8 . GetBytes ( hash ) , SafeUTF8 . GetBytes ( HashPassword ( text , hash , enhancedEntropy , hashType ) ) ) ;
835+ return SecureEquals ( SafeUTF8 . GetBytes ( hash ) , SafeUTF8 . GetBytes ( HashPassword ( text , hash , enhancedEntropy , hashType , v4CompatibleEnhancedEntropy ) ) ) ;
809836 }
810837
811838 // Compares two byte arrays for equality. The method is specifically written so that the loop is not optimised.
0 commit comments