@@ -676,6 +676,39 @@ TBCryptBSDTestData = record
676676 Cost : UInt8;
677677 end ;
678678
679+ TPair = record
680+ pn: byte;
681+ bs: string;
682+ end ;
683+ const
684+ Passwords: array [0 ..4 ] of string = (' ' , ' a' , ' abc' ,
685+ ' abcdefghijklmnopqrstuvwxyz' ,
686+ ' ~!@#$%^&*() ~!@#$%^&*()PNBFRD' );
687+
688+ // Source of test data: Wolfgang Erhardt's implementation.
689+ // pn is the index into Passwords
690+ TestData: array [1 ..20 ] of TPair = (
691+ (pn: 0 ; bs: ' $2a$06$DCq7YPn5Rq63x1Lad4cll.TV4S6ytwfsfvkgY8jIucDrjc8deX1s.' ),
692+ (pn: 0 ; bs: ' $2a$08$HqWuK6/Ng6sg9gQzbLrgb.Tl.ZHfXLhvt/SgVyWhQqgqcZ7ZuUtye' ),
693+ (pn: 0 ; bs: ' $2a$10$k1wbIrmNyFAPwPVPSVa/zecw2BCEnBwVS2GbrmgzxFUOqW9dk4TCW' ),
694+ (pn: 0 ; bs: ' $2a$12$k42ZFHFWqBp3vWli.nIn8uYyIkbvYRvodzbfbK18SSsY.CsIQPlxO' ),
695+ (pn: 1 ; bs: ' $2a$06$m0CrhHm10qJ3lXRY.5zDGO3rS2KdeeWLuGmsfGlMfOxih58VYVfxe' ),
696+ (pn: 1 ; bs: ' $2a$08$cfcvVd2aQ8CMvoMpP2EBfeodLEkkFJ9umNEfPD18.hUF62qqlC/V.' ),
697+ (pn: 1 ; bs: ' $2a$10$k87L/MF28Q673VKh8/cPi.SUl7MU/rWuSiIDDFayrKk/1tBsSQu4u' ),
698+ (pn: 1 ; bs: ' $2a$12$8NJH3LsPrANStV6XtBakCez0cKHXVxmvxIlcz785vxAIZrihHZpeS' ),
699+ (pn: 2 ; bs: ' $2a$06$If6bvum7DFjUnE9p2uDeDu0YHzrHM6tf.iqN8.yx.jNN1ILEf7h0i' ),
700+ (pn: 2 ; bs: ' $2a$08$Ro0CUfOqk6cXEKf3dyaM7OhSCvnwM9s4wIX9JeLapehKK5YdLxKcm' ),
701+ (pn: 2 ; bs: ' $2a$10$WvvTPHKwdBJ3uk0Z37EMR.hLA2W6N9AEBhEgrAOljy2Ae5MtaSIUi' ),
702+ (pn: 2 ; bs: ' $2a$12$EXRkfkdmXn2gzds2SSitu.MW9.gAVqa9eLS1//RYtYCmB1eLHg.9q' ),
703+ (pn: 3 ; bs: ' $2a$06$.rCVZVOThsIa97pEDOxvGuRRgzG64bvtJ0938xuqzv18d3ZpQhstC' ),
704+ (pn: 3 ; bs: ' $2a$08$aTsUwsyowQuzRrDqFflhgekJ8d9/7Z3GV3UcgvzQW3J5zMyrTvlz.' ),
705+ (pn: 3 ; bs: ' $2a$10$fVH8e28OQRj9tqiDXs1e1uxpsjN0c7II7YPKXua2NAKYvM6iQk7dq' ),
706+ (pn: 3 ; bs: ' $2a$12$D4G5f18o7aMMfwasBL7GpuQWuP3pkrZrOAnqP.bmezbMng.QwJ/pG' ),
707+ (pn: 4 ; bs: ' $2a$06$fPIsBO8qRqkjj273rfaOI.HtSV9jLDpTbZn782DC6/t7qT67P6FfO' ),
708+ (pn: 4 ; bs: ' $2a$08$Eq2r4G/76Wv39MzSX262huzPz612MZiYHVUJe/OcOql2jo4.9UxTW' ),
709+ (pn: 4 ; bs: ' $2a$10$LgfYWkbzEvQ4JakH7rOvHe0y8pHKF9OaFgwUZ2q7W2FFZmZzJYlfS' ),
710+ (pn: 4 ; bs: ' $2a$12$WApznUOJfkEGSmYRfnkrPOr466oFDCaj4b6HY3EXGvfxm43seyhgC' ));
711+
679712 function SplitTestVector (const Vector: string):TBCryptBSDTestData;
680713 protected
681714 procedure ConfigHashClass (aHashClass: TDECHash; aIdxTestData:Integer); override;
@@ -700,7 +733,9 @@ TBCryptBSDTestData = record
700733 procedure TestCostFactorTooShortException ;
701734 procedure TestCostFactorTooLongException ;
702735 procedure TestSetGetCostFactor ;
703- procedure TestCryptBSDFormat ;
736+ procedure TestCreateCryptBSDFormat ;
737+ procedure TestIsValidPasswordOK ;
738+ procedure TestIsValidPasswordFalse ;
704739 procedure TestNoSaltSpecified ;
705740 procedure TestTooShortSaltSpecified ;
706741 procedure TestTooLongSaltSpecified ;
@@ -6325,41 +6360,7 @@ procedure TestTHash_BCrypt.TestCostFactorTooShortException;
63256360 CheckException(DoTestCostFactorTooShortException, EDECHashException);
63266361end ;
63276362
6328- procedure TestTHash_BCrypt.TestCryptBSDFormat ;
6329- type
6330- TPair = record
6331- pn: byte;
6332- bs: string;
6333- end ;
6334- const
6335- Passwords: array [0 ..4 ] of string = (' ' , ' a' , ' abc' ,
6336- ' abcdefghijklmnopqrstuvwxyz' ,
6337- ' ~!@#$%^&*() ~!@#$%^&*()PNBFRD' );
6338- const
6339- // Source of test data: Wolfgang Erhardt's implementation.
6340- // pn is the index into Passwords
6341- TestData: array [1 ..20 ] of TPair = (
6342- (pn: 0 ; bs: ' $2a$06$DCq7YPn5Rq63x1Lad4cll.TV4S6ytwfsfvkgY8jIucDrjc8deX1s.' ),
6343- (pn: 0 ; bs: ' $2a$08$HqWuK6/Ng6sg9gQzbLrgb.Tl.ZHfXLhvt/SgVyWhQqgqcZ7ZuUtye' ),
6344- (pn: 0 ; bs: ' $2a$10$k1wbIrmNyFAPwPVPSVa/zecw2BCEnBwVS2GbrmgzxFUOqW9dk4TCW' ),
6345- (pn: 0 ; bs: ' $2a$12$k42ZFHFWqBp3vWli.nIn8uYyIkbvYRvodzbfbK18SSsY.CsIQPlxO' ),
6346- (pn: 1 ; bs: ' $2a$06$m0CrhHm10qJ3lXRY.5zDGO3rS2KdeeWLuGmsfGlMfOxih58VYVfxe' ),
6347- (pn: 1 ; bs: ' $2a$08$cfcvVd2aQ8CMvoMpP2EBfeodLEkkFJ9umNEfPD18.hUF62qqlC/V.' ),
6348- (pn: 1 ; bs: ' $2a$10$k87L/MF28Q673VKh8/cPi.SUl7MU/rWuSiIDDFayrKk/1tBsSQu4u' ),
6349- (pn: 1 ; bs: ' $2a$12$8NJH3LsPrANStV6XtBakCez0cKHXVxmvxIlcz785vxAIZrihHZpeS' ),
6350- (pn: 2 ; bs: ' $2a$06$If6bvum7DFjUnE9p2uDeDu0YHzrHM6tf.iqN8.yx.jNN1ILEf7h0i' ),
6351- (pn: 2 ; bs: ' $2a$08$Ro0CUfOqk6cXEKf3dyaM7OhSCvnwM9s4wIX9JeLapehKK5YdLxKcm' ),
6352- (pn: 2 ; bs: ' $2a$10$WvvTPHKwdBJ3uk0Z37EMR.hLA2W6N9AEBhEgrAOljy2Ae5MtaSIUi' ),
6353- (pn: 2 ; bs: ' $2a$12$EXRkfkdmXn2gzds2SSitu.MW9.gAVqa9eLS1//RYtYCmB1eLHg.9q' ),
6354- (pn: 3 ; bs: ' $2a$06$.rCVZVOThsIa97pEDOxvGuRRgzG64bvtJ0938xuqzv18d3ZpQhstC' ),
6355- (pn: 3 ; bs: ' $2a$08$aTsUwsyowQuzRrDqFflhgekJ8d9/7Z3GV3UcgvzQW3J5zMyrTvlz.' ),
6356- (pn: 3 ; bs: ' $2a$10$fVH8e28OQRj9tqiDXs1e1uxpsjN0c7II7YPKXua2NAKYvM6iQk7dq' ),
6357- (pn: 3 ; bs: ' $2a$12$D4G5f18o7aMMfwasBL7GpuQWuP3pkrZrOAnqP.bmezbMng.QwJ/pG' ),
6358- (pn: 4 ; bs: ' $2a$06$fPIsBO8qRqkjj273rfaOI.HtSV9jLDpTbZn782DC6/t7qT67P6FfO' ),
6359- (pn: 4 ; bs: ' $2a$08$Eq2r4G/76Wv39MzSX262huzPz612MZiYHVUJe/OcOql2jo4.9UxTW' ),
6360- (pn: 4 ; bs: ' $2a$10$LgfYWkbzEvQ4JakH7rOvHe0y8pHKF9OaFgwUZ2q7W2FFZmZzJYlfS' ),
6361- (pn: 4 ; bs: ' $2a$12$WApznUOJfkEGSmYRfnkrPOr466oFDCaj4b6HY3EXGvfxm43seyhgC' ));
6362-
6363+ procedure TestTHash_BCrypt.TestCreateCryptBSDFormat ;
63636364var
63646365 Result : string;
63656366 i : Integer;
@@ -6371,11 +6372,11 @@ TPair = record
63716372 for i := Low(TestData) to High(TestData) do
63726373 begin
63736374 SplitData := SplitTestVector(TestData[i].bs);
6374- Result := string( HashInst.GetDigestInCryptFormat(Passwords[TestData[i].pn],
6375- SplitData.Cost.ToString,
6376- SplitData.Salt,
6377- False,
6378- TFormat_BCryptBSD) );
6375+ Result := HashInst.GetDigestInCryptFormat(Passwords[TestData[i].pn],
6376+ SplitData.Cost.ToString,
6377+ SplitData.Salt,
6378+ False,
6379+ TFormat_BCryptBSD);
63796380
63806381 CheckEquals(TestData[i].bs, Result);
63816382 end ;
@@ -6399,6 +6400,96 @@ procedure TestTHash_BCrypt.TestIsPasswordHash;
63996400 CheckEquals(true, FHash.IsPasswordHash);
64006401end ;
64016402
6403+ procedure TestTHash_BCrypt.TestIsValidPasswordFalse ;
6404+ var
6405+ Result : Boolean;
6406+ HashInst : THash_BCrypt;
6407+ begin
6408+ HashInst := THash_BCrypt.Create;
6409+ try
6410+ Result := HashInst.IsValidPassword(' a' ,
6411+ ' 1234567890123456789012345678901234567' +
6412+ ' 8901234567890123456789' ,
6413+ TFormat_BCryptBSD);
6414+
6415+ CheckEquals(false, Result, ' Failure at wrong CryptData length' );
6416+
6417+ Result := HashInst.IsValidPassword(' a' ,
6418+ TestData[1 ].bs,
6419+ TFormat_BCryptBSD);
6420+
6421+ CheckEquals(false, Result, ' Failed to detect wrong password for empty password' );
6422+
6423+ Result := HashInst.IsValidPassword(' ab' ,
6424+ TestData[5 ].bs,
6425+ TFormat_BCryptBSD);
6426+
6427+ CheckEquals(false, Result, ' Failed to detect wrong password for password a' );
6428+
6429+ Result := HashInst.IsValidPassword(' a' ,
6430+ ' $3a$06$m0CrhHm10qJ3lXRY.5zDGO3rS2Kdee' +
6431+ ' WLuGmsfGlMfOxih58VYVfxe' ,
6432+ TFormat_BCryptBSD);
6433+
6434+ CheckEquals(false, Result, ' Failed to detect wrong CryptData format for ID' );
6435+
6436+ Result := HashInst.IsValidPassword(' a' ,
6437+ ' $2a06$m0CrhHm10qJ3lXRY.5zDGO3rS2Kdee' +
6438+ ' WLuGmsfGlMfOxih58VYVfxe' ,
6439+ TFormat_BCryptBSD);
6440+
6441+ CheckEquals(false, Result, ' Failed to detect wrong CryptData format for ' +
6442+ ' cost missing' );
6443+
6444+ Result := HashInst.IsValidPassword(' a' ,
6445+ ' $2a$06m0CrhHm10qJ3lXRY.5zDGO3rS2Kdee' +
6446+ ' WLuGmsfGlMfOxih58VYVfxe' ,
6447+ TFormat_BCryptBSD);
6448+
6449+ CheckEquals(false, Result, ' Failed to detect wrong CryptData format for ' +
6450+ ' salt missing' );
6451+
6452+ Result := HashInst.IsValidPassword(' a' ,
6453+ ' $2a$06$n0CrhHm10qJ3lXRY.5zDGO3rS2Kdee' +
6454+ ' WLuGmsfGlMfOxih58VYVfxe' ,
6455+ TFormat_BCryptBSD);
6456+
6457+ CheckEquals(false, Result, ' Failed to detect wrong password with wrong ' +
6458+ ' salt given' );
6459+
6460+ Result := HashInst.IsValidPassword(' a' ,
6461+ ' $2a$06$m0CrhHm10qJ3lXRY.5zDGO3rS2Kdee' +
6462+ ' WLuGmsfGlMfOxih58VYVfxf' ,
6463+ TFormat_BCryptBSD);
6464+
6465+ CheckEquals(false, Result, ' Failed to detect wrong password with wrong ' +
6466+ ' password hash given' );
6467+ finally
6468+ HashInst.Free;
6469+ end ;
6470+ end ;
6471+
6472+ procedure TestTHash_BCrypt.TestIsValidPasswordOK ;
6473+ var
6474+ Result : Boolean;
6475+ i : Integer;
6476+ HashInst : THash_BCrypt;
6477+ begin
6478+ HashInst := THash_BCrypt.Create;
6479+ try
6480+ for i := Low(TestData) to High(TestData) do
6481+ begin
6482+ Result := HashInst.IsValidPassword(Passwords[TestData[i].pn],
6483+ TestData[i].bs,
6484+ TFormat_BCryptBSD);
6485+
6486+ CheckEquals(true, Result, ' Failure at test data index: ' + i.ToString);
6487+ end ;
6488+ finally
6489+ HashInst.Free;
6490+ end ;
6491+ end ;
6492+
64026493procedure TestTHash_BCrypt.TestMaxCost ;
64036494begin
64046495 CheckEquals(31 , THash_BCrypt(FHash).MaxCost);
0 commit comments