Implement UTF8 support
This commit is contained in:
parent
dae6e78b8a
commit
46bec8c24d
31
BCrypt.pas
31
BCrypt.pas
|
@ -11,13 +11,16 @@
|
|||
*}
|
||||
unit BCrypt;
|
||||
{$mode objfpc}{$H+}
|
||||
{$codepage utf8}
|
||||
{$CODEPAGE UTF-8}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
SysUtils,
|
||||
Classes;
|
||||
sysutils,
|
||||
classes
|
||||
;
|
||||
|
||||
|
||||
|
||||
const
|
||||
// bcrypt uses 128-bit (16-byte) salt
|
||||
|
@ -219,6 +222,7 @@ type
|
|||
BCryptSalt,
|
||||
BCryptHash : AnsiString;
|
||||
end;
|
||||
UTF8String = type AnsiString(CP_UTF8);
|
||||
|
||||
EHash = class(EArgumentException);
|
||||
|
||||
|
@ -228,7 +232,7 @@ private
|
|||
FPBox: array[0..17] of DWord;
|
||||
function BsdBase64Encode(const RawByteData: TBytes; CharacterLength: Sizeint): AnsiString;
|
||||
function BsdBase64Decode(const EncodedString : AnsiString): TBytes;
|
||||
function Crypt(const Password, Salt : AnsiString; Cost : Byte; HashType : THashTypes) : AnsiString;
|
||||
function Crypt(const Password : UTF8String; const Salt : AnsiString; Cost : Byte; HashType : THashTypes) : AnsiString;
|
||||
function CryptRaw(const HashKey, Salt: TBytes; Cost : Byte): TBytes;
|
||||
procedure EKSKey(const Salt, HashKey: TBytes);
|
||||
procedure Encipher(var lr: array of DWord; const offset: SizeInt);
|
||||
|
@ -247,10 +251,10 @@ private
|
|||
public
|
||||
constructor Create; overload;
|
||||
destructor Destroy; override;
|
||||
function CreateHash(const Password : AnsiString) : AnsiString; overload;
|
||||
function CreateHash(const Password : AnsiString; HashType : THashTypes) : AnsiString; overload;
|
||||
function CreateHash(const Password : AnsiString; HashType : THashTypes; Cost : Byte) : AnsiString; overload;
|
||||
function VerifyHash(const Password, Hash : AnsiString) : Boolean;
|
||||
function CreateHash(const Password : UTF8String) : AnsiString; overload;
|
||||
function CreateHash(const Password : UTF8String; HashType : THashTypes) : AnsiString; overload;
|
||||
function CreateHash(const Password : UTF8String; HashType : THashTypes; Cost : Byte) : AnsiString; overload;
|
||||
function VerifyHash(const Password : UTF8STring; const Hash : AnsiString) : Boolean;
|
||||
function NeedsRehash(const BCryptHash : AnsiString) : Boolean; overload;
|
||||
function NeedsRehash(const BCryptHash : AnsiString; Cost : Byte) : Boolean; overload;
|
||||
function HashGetInfo(const Hash : AnsiString) : RTPasswordInformation;
|
||||
|
@ -263,6 +267,7 @@ Uses
|
|||
|
||||
constructor TBCryptHash.Create;
|
||||
begin
|
||||
|
||||
inherited Create;
|
||||
end;
|
||||
|
||||
|
@ -687,16 +692,16 @@ begin
|
|||
Result := RandomFileBuffer;
|
||||
end; { TBCryptHash.unixRandomBytes }
|
||||
|
||||
function TBCryptHash.CreateHash(const Password : AnsiString) : AnsiString; overload;
|
||||
function TBCryptHash.CreateHash(const Password : UTF8String) : AnsiString; overload;
|
||||
begin
|
||||
Result := CreateHash(Password, bcPHP, BCRYPT_DEFAULT_COST);
|
||||
end;
|
||||
function TBCryptHash.CreateHash(const Password : AnsiString; HashType : THashTypes) : AnsiString; overload;
|
||||
function TBCryptHash.CreateHash(const Password : UTF8String; HashType : THashTypes) : AnsiString; overload;
|
||||
begin
|
||||
Result := CreateHash(Password, HashType, BCRYPT_DEFAULT_COST);
|
||||
end; { TBCryptHash.CreateHash }
|
||||
|
||||
function TBCryptHash.CreateHash(const Password : AnsiString; HashType : THashTypes; Cost : Byte) : AnsiString; overload;
|
||||
function TBCryptHash.CreateHash(const Password : UTF8String; HashType : THashTypes; Cost : Byte) : AnsiString; overload;
|
||||
var
|
||||
PasswordKey,
|
||||
SaltBytes,
|
||||
|
@ -714,7 +719,7 @@ begin
|
|||
Result := FormatPasswordHash(SaltBytes, Hash, Cost, HashType);
|
||||
end; { TBCryptHash.CreateHash }
|
||||
|
||||
function TBCryptHash.Crypt(const Password, Salt : AnsiString; Cost : Byte; HashType : THashTypes) : AnsiString;
|
||||
function TBCryptHash.Crypt(const Password : UTF8String; const Salt : AnsiString; Cost : Byte; HashType : THashTypes) : AnsiString;
|
||||
var
|
||||
PasswordKey,
|
||||
SaltBytes,
|
||||
|
@ -745,7 +750,7 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
function TBCryptHash.VerifyHash(const Password, Hash : AnsiString) : Boolean;
|
||||
function TBCryptHash.VerifyHash(const Password : UTF8String; const Hash : AnsiString) : Boolean;
|
||||
var
|
||||
WorkingBcryptHash, Salt : AnsiString;
|
||||
HashCounter, ResultStatus, BCryptCost : Byte;
|
||||
|
|
|
@ -2,6 +2,7 @@ Program BCryptHashTest;
|
|||
{$mode objfpc}{$H+}
|
||||
{$ASSERTIONS ON}
|
||||
{$UNITPATH ../}
|
||||
{$CODEPAGE UTF-8}
|
||||
|
||||
uses BCrypt, Classes, SysUtils, Crt;
|
||||
const
|
||||
|
@ -21,6 +22,10 @@ var
|
|||
PassedAssertions : Word;
|
||||
Passed : Boolean;
|
||||
|
||||
UTF8TestString : UTF8String = 'Τη γλώσσα μου έδωσαν ελληνική';
|
||||
UTF8TestHash : AnsiString = '$2y$12$RSxqgCt5T4qPXLM3AzKMCueMBZo6cc9o/bN4wqcX6KA6lZnOkqzTG';
|
||||
UTF8PHPHash : AnsiString = '$2y$12$KrBUSn54WO5C/aw2H3imKurgsnrGq7PsrIZYXusaTNIO.27IGsmkG';
|
||||
|
||||
PasswordHashes : array [1..14] of AnsiString = (
|
||||
'$2y$10$LCb3aOt8lAXSzNrEpQKDQO1zc2wCCQltrDwSEbb9JaUo4OKbphC3i',
|
||||
'$2y$11$H7TRTJZqQTzN5RCiwMOne.yjVxyKCd4GyLrBQzV91gK0T4XQeKTNa',
|
||||
|
@ -104,6 +109,38 @@ for i := 1 to 7 do
|
|||
WriteLn(' - Pass');
|
||||
Inc(PassedAssertions);
|
||||
end;
|
||||
WriteLn(#10#13'Testing UTF8 with ', UTF8TestString, ' ... '#10#13);
|
||||
Write('Testing : ', UTF8TestHash);
|
||||
try
|
||||
Assert(TBCrypt.VerifyHash(UTF8TestString, UTF8TestHash) = True, 'Should Be True');
|
||||
Inc(Assertions);
|
||||
Inc(PassedAssertions);
|
||||
Writeln(' - Pass');
|
||||
except
|
||||
on e: EAssertionFailed do
|
||||
begin
|
||||
WriteLn(' - Fail');
|
||||
Inc(FailedAssertions);
|
||||
Dec(PassedAssertions);
|
||||
end;
|
||||
end;
|
||||
|
||||
WriteLn(#10#13'Testing UTF8 PHP Hash with ', UTF8TestString, ' ... '#10#13);
|
||||
Write('Testing : ', UTF8PHPHash);
|
||||
try
|
||||
Assert(TBCrypt.VerifyHash(UTF8TestString, UTF8PHPHash) = True, 'Should Be True');
|
||||
Inc(Assertions);
|
||||
Inc(PassedAssertions);
|
||||
Writeln(' - Pass');
|
||||
except
|
||||
on e: EAssertionFailed do
|
||||
begin
|
||||
WriteLn(' - Fail');
|
||||
Inc(FailedAssertions);
|
||||
Dec(PassedAssertions);
|
||||
end;
|
||||
end;
|
||||
|
||||
WriteLn(#10#13'Testing Failures ...'#10#13);
|
||||
for i := 1 to 7 do
|
||||
begin
|
||||
|
@ -325,7 +362,6 @@ for i := 1 to 7 do
|
|||
Inc(FailedAssertions);
|
||||
end;
|
||||
|
||||
|
||||
Writeln(#10#13'Testing hashing ...'#10#13);
|
||||
Writeln(TBCrypt.CreateHash(StaticPassword));
|
||||
Writeln(TBCrypt.CreateHash(StaticPassword, bcBSD));
|
||||
|
|
|
@ -14,6 +14,8 @@ assert_options(ASSERT_CALLBACK, 'bcrypt_assert_handler');
|
|||
|
||||
$bsdPascalHash = '$2a$12$9NWTTEbRtjLNd4KdW.VtUekFA6pJ3DF23FqdvwwvMtoMD9zqdaZg2';
|
||||
$bsdPascalHashFail = '$2a$12$9NWTTEbRtjLNd4KdW.VtUekFA6pJ3DF23FqdvwwvMtoMD9zqdaZg1';
|
||||
$utf8String = 'Τη γλώσσα μου έδωσαν ελληνική';
|
||||
$utf8PascalHash = '$2y$12$RSxqgCt5T4qPXLM3AzKMCueMBZo6cc9o/bN4wqcX6KA6lZnOkqzTG';
|
||||
|
||||
$pascalHashesMT = [
|
||||
'$2y$10$kJgRFQ993paFLArmPE3gn.8yuUB/SRpaEw7lkJJ1oVqhWVIecI5nO',
|
||||
|
@ -35,6 +37,13 @@ $pascalHashesURandom = [
|
|||
'$2y$16$Y0QNc8vaJJY5mQO0IkN6oeAxEVjtnHYqk0WeWLPm7bRjxA7fWHRBG',
|
||||
];
|
||||
|
||||
print PHP_EOL . 'Testing UTF8Hashe ... ' . str_repeat(PHP_EOL, 2);
|
||||
print 'Testing : ' . $utf8PascalHash;
|
||||
print PHP_EOL . ' with : ' . $utf8String;
|
||||
if(true === assert(password_verify($utf8String, $utf8PascalHash), ' - Fail')) {
|
||||
print ' - Pass' . PHP_EOL;
|
||||
}
|
||||
|
||||
print PHP_EOL . 'Testing bsdPascalHash ... ' . str_repeat(PHP_EOL, 2);
|
||||
print 'Testing : ' . $bsdPascalHash;
|
||||
if (true === assert(password_verify('password', $bsdPascalHash), ' - Fail')) {
|
||||
|
|
Loading…
Reference in New Issue