@@ -1177,34 +1177,48 @@ THash_BCrypt = class(TDECPasswordHash)
11771177 // / Returns the parameters required for the crypt-like password storing
11781178 // / in that format.
11791179 // / </summary>
1180- // / <param name="Format">
1181- // / Format class for formatting the output
1180+ // / <param name="Params">
1181+ // / In case of BCrypt this has to be the numeric integer value of "Cost".
1182+ // / This method will ensure it is prefixed with 0 when having too few chars
11821183 // / </param>
1183- function GetCryptParams (Format : TDECFormatClass):RawByteString; override;
1184- // / <summary>
1185- // / Returns the salt required for the crypt-like password storing
1186- // / in that format.
1187- // / </summary>
11881184 // / <param name="Format">
11891185 // / Format class for formatting the output
11901186 // / </param>
1191- function GetCryptSalt (Format: TDECFormatClass):RawByteString; override;
1187+ class function GetCryptParams (
1188+ const Params : RawByteString;
1189+ Format : TDECFormatClass):RawByteString; override;
11921190 // / <summary>
11931191 // / Returns the hash required for the crypt-like password storing
1194- // / in that format. If a salt etc. is needed that needs to be scepcified
1192+ // / in that format. If a salt etc. is needed that needs to be specified
11951193 // / before calling this method.
11961194 // / </summary>
11971195 // / <param name="Password">
11981196 // / Password entered which shall be hashed.
11991197 // / </param>
1198+ // / <param name="Params">
1199+ // / In case of BCrypt this has to be the numeric integer value of "Cost"
1200+ // / </param>
1201+ // / <param name="Salt">
1202+ // / Salt value used by the password hash calculation. Depending on the
1203+ // / value of SaltIsRaw, the salt needs to specified in raw encoding or
1204+ // / in the encoding used in the Crypt/BSD password storage string.
1205+ // / </param>
1206+ // / <param name="SaltIsRaw">
1207+ // / If true the passed salt value is a raw value. If false it is encoded
1208+ // / like in the Crypt/BSD password storage string.
1209+ // / </param>
12001210 // / <param name="Format">
12011211 // / Format class for formatting the output
12021212 // / </param>
12031213 // / <returns>
12041214 // / Calculated hash value
12051215 // / </returns>
1206- function GetCryptHash (Password : RawByteString;
1207- Format : TDECFormatClass):RawByteString; override;
1216+ class function GetCryptHash (
1217+ const Password : RawByteString;
1218+ const Params : RawByteString;
1219+ const Salt : RawByteString;
1220+ SaltIsRaw : Boolean;
1221+ Format : TDECFormatClass):RawByteString; override;
12081222 { $EndRegion}
12091223 public
12101224 // / <summary>
@@ -5076,16 +5090,16 @@ procedure THash_BCrypt.Expandkey(Salt : TBytes;
50765090begin
50775091 KBP := @Password[0 ];
50785092
5079- { Text explanations and comments are from the N.Provos & D.Mazieres paper.}
5093+ // Text explanations and comments are from the N.Provos & D.Mazieres paper.
50805094
5081- { ExpandKey(state,salt,key) modifies the P-Array and S-boxes based on the }
5082- { value of the 128-bit salt and the variable length key. First XOR all the}
5083- { subkeys in the P-array with the encryption key. The first 32 bits of the}
5084- { key are XORed with P1, the next 32 bits with P2, and so on. The key is }
5085- { viewed as being cyclic; when the process reaches the end of the key, it }
5086- { starts reusing bits from the beginning to XOR with subkeys. }
5095+ // ExpandKey(state,salt,key) modifies the P-Array and S-boxes based on the
5096+ // value of the 128-bit salt and the variable length key. First XOR all the
5097+ // subkeys in the P-array with the encryption key. The first 32 bits of the
5098+ // key are XORed with P1, the next 32 bits with P2, and so on. The key is
5099+ // viewed as being cyclic; when the process reaches the end of the key, it
5100+ // starts reusing bits from the beginning to XOR with subkeys.
50875101
5088- { WE: Same as standard key part except that PArray[i] is used for _bf_p[i]}
5102+ // WE: Same as standard key part except that PArray[i] is used for _bf_p[i]
50895103 k := 0 ;
50905104 for i := 0 to 17 do
50915105 begin
@@ -5102,20 +5116,20 @@ procedure THash_BCrypt.Expandkey(Salt : TBytes;
51025116 FContext.PArray[i] := FContext.PArray[i] xor KL;
51035117 end ;
51045118
5105- { Subsequently, ExpandKey blowfish-encrypts the first 64 bits of}
5106- { its salt argument using the current state of the key schedule.}
5119+ // Subsequently, ExpandKey blowfish-encrypts the first 64 bits of
5120+ // its salt argument using the current state of the key schedule.
51075121 BF_Encrypt(PBFBlock(@salt[0 ])^, tmp);
51085122
5109- { The resulting ciphertext replaces subkeys P_1 and P_2.}
5123+ // The resulting ciphertext replaces subkeys P_1 and P_2.
51105124 FContext.PArray[0 ] := SwapUInt32(TBF2Long(tmp).L);
51115125 FContext.PArray[1 ] := SwapUInt32(TBF2Long(tmp).R);
51125126
5113- { That same ciphertext is also XORed with the second 64-bits of }
5114- { salt, and the result encrypted with the new state of the key }
5115- { schedule. The output of the second encryption replaces subkeys}
5116- { P_3 and P_4. It is also XORed with the first 64-bits of salt }
5117- { and encrypted to replace P_5 and P_6. The process continues, }
5118- { alternating between the first and second 64 bits salt. }
5127+ // That same ciphertext is also XORed with the second 64-bits of
5128+ // salt, and the result encrypted with the new state of the key
5129+ // schedule. The output of the second encryption replaces subkeys
5130+ // P_3 and P_4. It is also XORed with the first 64-bits of salt
5131+ // and encrypted to replace P_5 and P_6. The process continues,
5132+ // alternating between the first and second 64 bits salt.
51195133 h := 8 ;
51205134 for i := 1 to 8 do
51215135 begin
@@ -5126,53 +5140,62 @@ procedure THash_BCrypt.Expandkey(Salt : TBytes;
51265140 FContext.PArray[2 *i+1 ] := SwapUInt32(TBF2Long(tmp).R);
51275141 end ;
51285142
5129- { When ExpandKey finishes replacing entries in the P-Array, it continues}
5130- { on replacing S-box entries two at a time. After replacing the last two}
5131- { entries of the last S-box, ExpandKey returns the new key schedule. }
5143+ // When ExpandKey finishes replacing entries in the P-Array, it continues
5144+ // on replacing S-box entries two at a time. After replacing the last two
5145+ // entries of the last S-box, ExpandKey returns the new key schedule.
51325146 for j := 0 to 3 do
51335147 begin
51345148 for i := 0 to 127 do
51355149 begin
51365150 BF_XorBlock(tmp, PBFBlock(@Salt[h])^, tmp);
51375151 h := h xor 8 ;
51385152 BF_Encrypt(tmp, tmp);
5139- FContext.SBox[j, 2 *i] := SwapUInt32(TBF2Long(tmp).L);
5140- FContext.SBox[j, 2 *i+1 ]:= SwapUInt32(TBF2Long(tmp).R);
5153+ FContext.SBox[j, 2 *i] := SwapUInt32(TBF2Long(tmp).L);
5154+ FContext.SBox[j, 2 *i+1 ] := SwapUInt32(TBF2Long(tmp).R);
51415155 end ;
51425156 end ;
51435157end ;
51445158
5145- function THash_BCrypt.GetCryptHash (Password : RawByteString;
5146- Format : TDECFormatClass): RawByteString;
5159+ class function THash_BCrypt.GetCryptHash (
5160+ const Password : RawByteString;
5161+ const Params : RawByteString;
5162+ const Salt : RawByteString;
5163+ SaltIsRaw : Boolean;
5164+ Format : TDECFormatClass): RawByteString;
5165+ var
5166+ Hash : THash_BCrypt;
51475167begin
5148- // BCrypt leaves off the $ in front of the actual password hash value
5149- Result := CalcString(Password, Format);
5168+ Hash := THash_BCrypt.Create;
5169+ try
5170+ Hash.Cost := StrToInt(string(Params));
5171+ if SaltIsRaw then
5172+ Hash.Salt := BytesOf(Salt)
5173+ else
5174+ Hash.Salt := Format.Decode(BytesOf(Salt));
5175+
5176+ // BCrypt leaves off the $ in front of the actual password hash value
5177+ Result := Hash.CalcString(Password, Format);
5178+ finally
5179+ Hash.Free;
5180+ end ;
51505181end ;
51515182
51525183class function THash_BCrypt.GetCryptID : RawByteString;
51535184begin
51545185 Result := ' $2a' ;
51555186end ;
51565187
5157- function THash_BCrypt.GetCryptParams (Format : TDECFormatClass): RawByteString;
5188+ class function THash_BCrypt.GetCryptParams (
5189+ const Params : RawByteString;
5190+ Format : TDECFormatClass): RawByteString;
51585191begin
5159- Result := RawByteString(FCost.ToString) ;
5192+ Result := Params ;
51605193 if (Length(Result) < 2 ) then
51615194 Result := ' 0' + Result;
51625195
51635196 Result := ' $' + Result;
51645197end ;
51655198
5166- function THash_BCrypt.GetCryptSalt (Format: TDECFormatClass): RawByteString;
5167- var
5168- FormattedSalt : TBytes;
5169- begin
5170- FormattedSalt := Format.Encode(FSalt);
5171- SetLength(Result, Length(FormattedSalt) + 1 );
5172- Move(FormattedSalt[0 ], Result[Low(Result) + 1 ], Length(FormattedSalt));
5173- Result[Low(Result)] := ' $' ;
5174- end ;
5175-
51765199procedure THash_BCrypt.BF_Encrypt (const BI: TBFBlock; var BO: TBFBlock);
51775200var
51785201 xl, xr : UInt32;
0 commit comments