Switched out openssl for HashLib

This commit is contained in:
R. Eric Wheeler 2017-03-01 16:22:02 -08:00
parent 824b4804e8
commit 3f4acbbad3
21 changed files with 711 additions and 329 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "HashLib"]
path = HashLib
url = https://github.com/Xor-el/HashLib4Pascal.git

247
Hash.Base64.pp Normal file
View File

@ -0,0 +1,247 @@
{*******************************************************}
{ Renegade BBS }
{ Copyright (c) 1990-2013 The Renegade Dev Team }
{ Copyleft (ↄ) 2016-2017 Renegade BBS }
{ This file is part of Renegade BBS }
{ Renegade is free software: you can redistribute it }
{ and/or modify it under the terms of the GNU General }
{ Public License as published by the Free Software }
{ Foundation, either version 3 of the License, or }
{ (at your option) any later version. }
{ Renegade is distributed in the hope that it will be }
{ useful, but WITHOUT ANY WARRANTY; without even the }
{ implied warranty of MERCHANTABILITY or FITNESS FOR }
{ A PARTICULAR PURPOSE. See the GNU General Public }
{ License for more details. }
{ You should have received a copy of the GNU General }
{ Public License along with Renegade. If not, see }
{ <http://www.gnu.org/licenses/>. }
{*******************************************************}
{ _______ __ }
{ | _ .-----.-----.-----.-----.---.-.--| .-----. }
{ |. l | -__| | -__| _ | _ | _ | -__| }
{ |. _ |_____|__|__|_____|___ |___._|_____|_____| }
{ |: | | |_____| }
{ |::.|:. | }
{ `--- ---' }
{*******************************************************}
unit Hash.Base64;
{$codepage utf8}
{$h+}{$mode objfpc}
interface
uses
Classes,
SysUtils,
Base64;
const
BSDEncodeTable: array[0..63] of char =
{ 0:} './' +
{ 2:} 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
{28:} 'abcdefghijklmnopqrstuvwxyz' +
{54:} '0123456789';
BSDDecodeTable: array[#0..#127] of integer = (
{ 0:} -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
{ 16:} -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
{ 32:} -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1,
{ 48:} 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, -1, -1, -1, -1, -1, -1,
{ 64:} -1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
{ 80:} 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1,
{ 96:} -1, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
{113:} 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, -1, -1, -1, -1, -1
);
type
RTBase64 = object
private
function Char64(Character: AnsiChar): SizeInt;
procedure AppendChar(var WorkingResult: TBytes; Value: byte);
public
function Encode(S: UTF8String): ansistring; static;
function Decode(S: ansistring): UTF8String; static;
function BSDEncode(S: UTF8STring): ansistring; static;
function BSDDecode(S: ansistring): UTF8STring; static;
function BSDEncodeBytes(const RawByteData: TBytes;
CharacterLength: Sizeint): ansistring;
function BSDDecodeBytes(const EncodedString: ansistring): TBytes;
end;
implementation
function RTBase64.Char64(Character: AnsiChar): SizeInt;
begin
if Ord(Character) > Length(BSDDecodeTable) then
begin
Result := -1;
end
else
begin
Result := BSDDecodeTable[Character];
end;
end;
procedure RTBase64.AppendChar(var WorkingResult: TBytes; Value: byte);
var
i: SizeUint;
begin
i := Length(WorkingResult);
SetLength(WorkingResult, i + 1);
WorkingResult[i] := Value;
end;
function RTBase64.Encode(S: UTF8String): ansistring;
begin
Result := EncodeStringBase64(S);
end;
function RTBase64.Decode(S: ansistring): UTF8String;
begin
Result := DecodeStringBase64(S);
end;
function RTBase64.BSDEncode(S: UTF8String): ansistring;
var
TBaseBytes: TBytes;
begin
SetLength(TBaseBytes, Length(S) + 1);
Move(S[1], TBaseBytes[0], Length(S) + 1);
Result := RTBase64.BSDEncodeBytes(TBaseBytes, Length(TBaseBytes));
end;
function RTBase64.BSDDecode(S: ansistring): UTF8String;
var
TBaseBytes: TBytes;
begin
SetLength(TBaseBytes, Length(S) + 1);
TBaseBytes := RTBase64.BSDDecodeBytes(S);
SetLength(Result, Length(TBaseBytes));
Move(TBaseBytes[0], Result[1], Length(TBaseBytes));
end;
function RTBase64.BSDEncodeBytes(const RawByteData: TBytes;
CharacterLength: Sizeint): ansistring;
var
i, b1, b2: SizeInt;
begin
Result := '';
if (CharacterLength <= 0) or (CharacterLength > Length(RawByteData)) then
begin
Exit;
end;
i := 0;
while i < CharacterLength do
begin
b1 := RawByteData[i] and $ff;
Inc(i);
Result := Result + BSDEncodeTable[(b1 shr 2) and $3f];
b1 := (b1 and $03) shl 4;
if i >= CharacterLength then
begin
Result := Result + BSDEncodeTable[b1 and $3f];
Exit;
end;
b2 := RawByteData[i] and $ff;
Inc(i);
b1 := b1 or ((b2 shr 4) and $0f);
Result := Result + BSDEncodeTable[b1 and $3f];
b1 := (b2 and $0f) shl 2;
if i >= CharacterLength then
begin
Result := Result + BSDEncodeTable[b1 and $3f];
Exit;
end;
b2 := RawByteData[i] and $ff;
Inc(i);
b1 := b1 or ((b2 shr 6) and $03);
Result := Result + BSDEncodeTable[b1 and $3f];
Result := Result + BSDEncodeTable[b2 and $3f];
end;
end;
function RTBase64.BSDDecodeBytes(const EncodedString: ansistring): TBytes;
var
i, EncodedStringLength, c1, c2, c3, c4: Sizeint;
begin
SetLength(Result, 0);
i := 1;
EncodedStringLength := Length(EncodedString);
while (i < EncodedStringLength) and (Length(Result) < EncodedStringLength) do
begin
c1 := self.Char64(EncodedString[i]);
Inc(i);
c2 := self.Char64(EncodedString[i]);
Inc(i);
if (c1 = -1) or (c2 = -1) then
begin
Exit;
end;
{
Now we have at least one byte in c1|c2
c1 = ..111111
c2 = ..112222
}
self.AppendChar(Result, (c1 shl 2) or ((c2 and $30) shr 4));
//If there's a 3rd character, then we can use c2|c3 to form the second byte
if (i > EncodedStringLength) or (Length(Result) >= EncodedStringLength) then
begin
Break;
end;
c3 := self.Char64(EncodedString[i]);
Inc(i);
if (c3 = -1) then
begin
Exit;
end;
{
Now we have the next byte in c2|c3
c2 = ..112222
c3 = ..222233
}
self.AppendChar(Result, ((c2 and $0f) shl 4) or ((c3 and $3c) shr 2));
//If there's a 4th caracter, then we can use c3|c4 to form the third byte
if (i > EncodedStringLength) or (Length(Result) >= EncodedStringLength) then
begin
Break;
end;
c4 := self.Char64(EncodedString[i]);
Inc(i);
if c4 = -1 then
begin
Exit;
end;
{
Now we have the next byte in c3|c4
c3 = ..222233
c4 = ..333333
}
self.AppendChar(Result, ((c3 and $03) shl 6) or c4);
end; { While }
end;
end.

View File

@ -0,0 +1 @@
{ TODO }

View File

@ -45,26 +45,26 @@ uses
Classes;
type
Md = class(TObject)
RTMd = object
public
function md2(S: UTF8String): ansistring;
function md4(S: UTF8String): ansistring;
function md5(S: UTF8STring): ansistring;
function md2(S: UTF8String): ansistring;static;
function md4(S: UTF8String): ansistring;static;
function md5(S: UTF8STring): ansistring;static;
end;
implementation
function Md.md2(S: UTF8String): ansistring;
function RTMd.md2(S: UTF8String): ansistring;
begin
Result := MD2Print(MDString(S, MD_VERSION_2));
end;
function Md.md4(S: UTF8String): ansistring;
function RTMd.md4(S: UTF8String): ansistring;
begin
Result := MD4Print(MDString(S, MD_VERSION_4));
end;
function Md.md5(S: UTF8String): ansistring;
function RTMd.md5(S: UTF8String): ansistring;
begin
Result := MD5Print(MDString(S, MD_VERSION_5));
end;

View File

@ -1,7 +1,5 @@
{*******************************************************}
{ Renegade BBS }
{ Copyright (c) 1990-2013 The Renegade Dev Team }
{ Copyleft (ↄ) 2016-2017 Renegade BBS }
@ -32,6 +30,49 @@
{ |::.|:. | }
{ `--- ---' }
{*******************************************************}
{ }
{ This unit contains code from the HashLib Library }
{ by Ugochukwu Mmaduekwe licensed under the MIT }
{ license. (https://github.com/Xor-el/HashLib4Pascal) }
{ }
{*******************************************************}
{ }
{ HashLib Library }
{ Copyright (c) Ugochukwu Mmaduekwe 2016 - 2017 }
{ }
{*******************************************************}
{ }
{ The MIT License (MIT) }
{ }
{ Copyright (c) 2016 Ugochukwu Mmaduekwe }
{ }
{ Permission is hereby granted, free of charge, to any }
{ person obtaining a copy of this software and }
{ associated documentation files (the "Software"), to }
{ deal in the Software without restriction, including }
{ without limitation the rights to use, copy, modify, }
{ merge, publish, distribute, sublicense, and/or sell }
{ copies of the Software, and to permit persons to whom }
{ the Software is furnished to do so, subject to the }
{ following conditions: }
{ }
{ The above copyright notice and this permission notice }
{ shall be included in all copies or substantial }
{ portions of the Software. }
{ }
{ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF }
{ ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT }
{ LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS }
{ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO }
{ EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE }
{ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, }
{ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, }
{ ARISING FROM, OUT OF OR IN CONNECTION WITH THE }
{ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE }
{ SOFTWARE. }
{ }
{*******************************************************}
{$mode objfpc}
{$codepage utf8}
{$h+}
@ -43,261 +84,149 @@ interface
uses
SysUtils,
Classes,
OpenSSL,
CTypes;
HlpSHA0,
HlpSHA1,
HlpSHA2_224,
HlpSHA2_256,
HlpSHA2_384,
HlpSHA2_512,
HlpSHA2_512_224,
HlpSHA2_512_256,
HlpSHA3;
const
SHA512_DIGEST_LENGTH = 64;
SHA384_DIGEST_LENGTH = 48;
SHA256_DIGEST_LENGTH = 32;
SHA224_DIGEST_LENGTH = 28;
type
RTSha = class(TObject)
RTSupportedShaHashTypes = (
rtSha0,
rtSha1,
rtSha224,
rtSha256,
rtSha384,
rtSha512_224,
rtSha512_256,
rtSha512,
rtSha3_224,
rtSha3_256,
rtSha3_384,
rtSha3_512
);
RTSupportedShaHashTypesSet = set of RTSupportedShaHashTypes;
RTSha = object
public
constructor Create();
destructor Destroy();override;
function Sha1(S: UTF8String): ansistring;
function Sha224(S: UTF8String): ansistring;
function Sha256(S: UTF8String): ansistring;
function Sha384(S: UTF8String): ansistring;
function Sha512(S: UTF8String): ansistring;
function CreateSha(S : UTF8String; ShaType : RTSupportedShaHashTypes): ansistring; static;
function Sha(S: UTF8String): ansistring; static;
function Sha0(S: UTF8String): ansistring; static;
function Sha1(S: UTF8String): ansistring; static;
function Sha224(S: UTF8String): ansistring; static;
function Sha256(S: UTF8String): ansistring; static;
function Sha384(S: UTF8String): ansistring; static;
function Sha512(S: UTF8String): ansistring; static;
function Sha512_224(S: UTF8String): ansistring; static;
function Sha512_256(S: UTF8String): ansistring; static;
function Sha3_224(S: UTF8String): ansistring; static;
function Sha3_256(S: UTF8String): ansistring; static;
function Sha3_384(S: UTF8String): ansistring; static;
function Sha3_512(S: UTF8String): ansistring; static;
end;
implementation
constructor RTSha.Create();
var
HaveOpenSSL : Boolean;
function RTSha.CreateSha(S : UTF8String; ShaType : RTSupportedShaHashTypes) : ansistring;
begin
HaveOpenSSL := InitSSLInterface;
if not HaveOpenSSL then
begin
raise Exception.Create('Please install OpenSSL.') at
get_caller_addr(get_frame),
get_caller_frame(get_frame);
Fail;
case ShaType of
rtSha0 : Result := Sha(S);
rtSha1 : Result := Sha1(S);
rtSha224 : Result := Sha224(S);
rtSha256 : Result := Sha256(S);
rtSha384 : Result := Sha384(S);
rtSha512_224 : Result := Sha512_224(S);
rtSha512_256 : Result := Sha512_256(S);
rtSha512 : Result := Sha512(S);
rtSha3_224 : Result := Sha3_224(S);
rtSha3_256 : Result := Sha3_256(S);
rtSha3_384 : Result := Sha3_384(S);
rtSha3_512 : Result := Sha3_512(S);
end;
end;
destructor RTSha.Destroy();
function RTSha.Sha(S: UTF8String): ansistring;
begin
inherited Destroy;
EVPcleanup;
DestroySSLInterface;
Result := System.LowerCase(TSHA0.Create().ComputeString(PChar(S), TEncoding.UTF8).ToString());
end;
function RTSha.Sha0(S: UTF8String): ansistring;
begin
Result := Sha(S);
end;
function RTSha.Sha1(S: UTF8String): ansistring;
var
Digest : PEVP_MD;
ShaCTX : PEVP_MD_CTX;
HexValue : AnsiString;
BinValue : PChar;
Hash : PByte;
DigestLength: pcuint;
begin
GetMem(Hash, SHA_DIGEST_LENGTH);
GetMem(DigestLength, SHA_DIGEST_LENGTH);
GetMem(ShaCTX, SizeOf(PEVP_MD_CTX));
GetMem(BinValue, SHA_DIGEST_LENGTH*2);
SetLength(HexValue, SHA_DIGEST_LENGTH*2);
try
Digest := EvpGetDigestByName('sha1');
EVP_DigestInit(ShaCTX, Digest);
EVP_DigestUpdate(ShaCTX, @S[1], Length(S));
EVP_DigestFinal(ShaCTX, Hash, DigestLength);
except
On e: Exception do
begin
WriteLn(e.Message);
Writeln(e.HelpContext);
Free;
exit;
end;
end;
Move(Hash[0], BinValue[0], SHA_DIGEST_LENGTH);
BinToHex(BinValue, PChar(HexValue), SHA_DIGEST_LENGTH);
// Cleanup
FreeMem(Hash);
FreeMem(DigestLength);
FreeMem(BinValue);
Result := LowerCase(HexValue);
Result := System.LowerCase(TSHA1.Create().ComputeString(PChar(S),
TEncoding.UTF8).ToString());
end;
function RTSha.Sha224(S: UTF8String): ansistring;
var
Digest : PEVP_MD;
ShaCTX : PEVP_MD_CTX;
HexValue : AnsiString;
BinValue : PChar;
Hash : PByte;
DigestLength: pcuint;
begin
GetMem(Hash, SHA224_DIGEST_LENGTH);
GetMem(DigestLength, SHA224_DIGEST_LENGTH);
GetMem(ShaCTX, SizeOf(PEVP_MD_CTX));
GetMem(BinValue, SHA224_DIGEST_LENGTH);
SetLength(HexValue, SHA224_DIGEST_LENGTH*2);
try
Digest := EvpGetDigestByName('sha224');
EVP_DigestInit(ShaCTX, Digest);
EVP_DigestUpdate(ShaCTX, @S[1], Length(S));
EVP_DigestFinal(ShaCTX, Hash, DigestLength);
except
On e: Exception do
begin
WriteLn(e.Message);
Writeln(e.HelpContext);
Free;
exit;
end;
end;
Move(Hash[0], BinValue[0], SHA224_DIGEST_LENGTH);
BinToHex(BinValue, PChar(HexValue), SHA224_DIGEST_LENGTH);
// Cleanup
FreeMem(Hash);
FreeMem(DigestLength);
FreeMem(BinValue);
Result := LowerCase(HexValue);
Result := System.LowerCase(TSHA2_224.Create().ComputeString(PChar(S),
TEncoding.UTF8).ToString());
end;
function RTSha.Sha256(S: UTF8String): ansistring;
var
Digest : PEVP_MD;
ShaCTX : PEVP_MD_CTX;
HexValue : AnsiString;
BinValue : PChar;
Hash : PByte;
DigestLength: pcuint;
begin
GetMem(Hash, SHA256_DIGEST_LENGTH);
GetMem(DigestLength, SHA256_DIGEST_LENGTH);
GetMem(ShaCTX, SizeOf(PEVP_MD_CTX));
GetMem(BinValue, SHA256_DIGEST_LENGTH);
SetLength(HexValue, SHA256_DIGEST_LENGTH*2);
try
Digest := EvpGetDigestByName('sha256');
EVP_DigestInit(ShaCTX, Digest);
EVP_DigestUpdate(ShaCTX, @S[1], Length(S));
EVP_DigestFinal(ShaCTX, Hash, DigestLength);
except
On e: Exception do
begin
WriteLn(e.Message);
Writeln(e.HelpContext);
Free;
exit;
end;
end;
Move(Hash[0], BinValue[0], SHA256_DIGEST_LENGTH);
BinToHex(BinValue, PChar(HexValue), SHA256_DIGEST_LENGTH);
// Cleanup
FreeMem(Hash);
FreeMem(DigestLength);
FreeMem(BinValue);
Result := LowerCase(HexValue);
Result := System.LowerCase(TSHA2_256.Create().ComputeString(PChar(S),
TEncoding.UTF8).ToString());
end;
function RTSha.Sha384(S: UTF8String): ansistring;
var
Digest : PEVP_MD;
ShaCTX : PEVP_MD_CTX;
HexValue : AnsiString;
BinValue : PChar;
Hash : PByte;
DigestLength: pcuint;
begin
GetMem(Hash, SHA384_DIGEST_LENGTH);
GetMem(DigestLength, SHA384_DIGEST_LENGTH);
GetMem(ShaCTX, SizeOf(PEVP_MD_CTX));
GetMem(BinValue, SHA384_DIGEST_LENGTH);
SetLength(HexValue, SHA384_DIGEST_LENGTH*2);
try
Digest := EvpGetDigestByName('sha384');
EVP_DigestInit(ShaCTX, Digest);
EVP_DigestUpdate(ShaCTX, @S[1], Length(S));
EVP_DigestFinal(ShaCTX, Hash, DigestLength);
except
On e: Exception do
begin
WriteLn(e.Message);
Writeln(e.HelpContext);
Free;
exit;
end;
end;
Move(Hash[0], BinValue[0], SHA384_DIGEST_LENGTH);
BinToHex(BinValue, PChar(HexValue), SHA384_DIGEST_LENGTH);
// Cleanup
FreeMem(Hash);
FreeMem(DigestLength);
FreeMem(BinValue);
Result := LowerCase(HexValue);
Result := System.LowerCase(TSHA2_384.Create().ComputeString(PChar(S),
TEncoding.UTF8).ToString());
end;
function RTSha.Sha512(S: UTF8String): ansistring;
var
Digest : PEVP_MD;
ShaCTX : PEVP_MD_CTX;
HexValue : AnsiString;
BinValue : PChar;
Hash : PByte;
DigestLength: pcuint;
begin
Result := System.LowerCase(TSHA2_512.Create().ComputeString(PChar(S),
TEncoding.UTF8).ToString());
end;
GetMem(Hash, SHA512_DIGEST_LENGTH);
GetMem(DigestLength, SHA512_DIGEST_LENGTH);
GetMem(ShaCTX, SizeOf(PEVP_MD_CTX));
GetMem(BinValue, SHA512_DIGEST_LENGTH);
SetLength(HexValue, SHA512_DIGEST_LENGTH*2);
try
Digest := EvpGetDigestByName('sha512');
EVP_DigestInit(ShaCTX, Digest);
EVP_DigestUpdate(ShaCTX, @S[1], Length(S));
EVP_DigestFinal(ShaCTX, Hash, DigestLength);
except
function RTSha.Sha512_224(S: UTF8String): ansistring;
begin
Result := System.LowerCase(TSHA2_512_224.Create().ComputeString(PChar(S),
TEncoding.UTF8).ToString());
end;
On e: Exception do
begin
WriteLn(e.Message);
Writeln(e.HelpContext);
Free;
exit;
end;
end;
Move(Hash[0], BinValue[0], SHA512_DIGEST_LENGTH);
function RTSha.Sha512_256(S: UTF8String): ansistring;
begin
Result := System.LowerCase(TSHA2_512_256.Create().ComputeString(PChar(S),
TEncoding.UTF8).ToString());
end;
BinToHex(BinValue, PChar(HexValue), SHA512_DIGEST_LENGTH);
// Cleanup
FreeMem(Hash);
FreeMem(DigestLength);
FreeMem(BinValue);
function RTSha.Sha3_224(S: UTF8String): ansistring;
begin
Result := System.LowerCase(TSHA3_224.Create().ComputeString(PChar(S),
TEncoding.UTF8).ToString());
end;
Result := LowerCase(HexValue);
function RTSha.Sha3_256(S: UTF8String): ansistring;
begin
Result := System.LowerCase(TSHA3_256.Create().ComputeString(PChar(S),
TEncoding.UTF8).ToString());
end;
function RTSha.Sha3_384(S: UTF8String): ansistring;
begin
Result := System.LowerCase(TSHA3_384.Create().ComputeString(PChar(S),
TEncoding.UTF8).ToString());
end;
function RTSha.Sha3_512(S: UTF8String): ansistring;
begin
Result := System.LowerCase(TSHA3_512.Create().ComputeString(PChar(S),
TEncoding.UTF8).ToString());
end;
end.

View File

View File

80
Hash.Util.pp Normal file
View File

@ -0,0 +1,80 @@
{*******************************************************}
{ Renegade BBS }
{ Copyright (c) 1990-2013 The Renegade Dev Team }
{ Copyleft (ↄ) 2016-2017 Renegade BBS }
{ This file is part of Renegade BBS }
{ Renegade is free software: you can redistribute it }
{ and/or modify it under the terms of the GNU General }
{ Public License as published by the Free Software }
{ Foundation, either version 3 of the License, or }
{ (at your option) any later version. }
{ Renegade is distributed in the hope that it will be }
{ useful, but WITHOUT ANY WARRANTY; without even the }
{ implied warranty of MERCHANTABILITY or FITNESS FOR }
{ A PARTICULAR PURPOSE. See the GNU General Public }
{ License for more details. }
{ You should have received a copy of the GNU General }
{ Public License along with Renegade. If not, see }
{ <http://www.gnu.org/licenses/>. }
{*******************************************************}
{ _______ __ }
{ | _ .-----.-----.-----.-----.---.-.--| .-----. }
{ |. l | -__| | -__| _ | _ | _ | -__| }
{ |. _ |_____|__|__|_____|___ |___._|_____|_____| }
{ |: | | |_____| }
{ |::.|:. | }
{ `--- ---' }
{*******************************************************}
unit Hash.Util;
{$codepage utf8}
{$h+}{$mode objfpc}
interface
type
RTHashUtil = object
public
function HashEquals(KnownHash, CheckedHash : ansistring): boolean;static;
end;
implementation
function RTHashUtil.HashEquals(KnownHash, CheckedHash : ansistring): boolean;
var
HashCounter,
ResultStatus : SizeInt;
begin
ResultStatus := 0;
if Length(KnownHash) <> Length(CheckedHash) then
begin
Result := False;
Exit;
end;
for HashCounter := 1 to Length(KnownHash) do
begin
{
From ext/standard/password.c php_password_verify line 244
We're using this method instead of = in order to provide
resistance towards timing attacks. This is a constant time
equality check that will always check every byte of both
values.
}
ResultStatus := ResultStatus or
(ord(CheckedHash[HashCounter]) xor
ord(KnownHash[HashCounter]));
end;
Result := (ResultStatus = 0);
end;
end.

1
HashLib Submodule

@ -0,0 +1 @@
Subproject commit 7a84816f501674e73d01dbfe01f2adbe17828a6e

69
Renegade.Hash.pp Normal file
View File

@ -0,0 +1,69 @@
{*******************************************************}
{ Renegade BBS }
{ Copyright (c) 1990-2013 The Renegade Dev Team }
{ Copyleft (ↄ) 2016-2017 Renegade BBS }
{ This file is part of Renegade BBS }
{ Renegade is free software: you can redistribute it }
{ and/or modify it under the terms of the GNU General }
{ Public License as published by the Free Software }
{ Foundation, either version 3 of the License, or }
{ (at your option) any later version. }
{ Renegade is distributed in the hope that it will be }
{ useful, but WITHOUT ANY WARRANTY; without even the }
{ implied warranty of MERCHANTABILITY or FITNESS FOR }
{ A PARTICULAR PURPOSE. See the GNU General Public }
{ License for more details. }
{ You should have received a copy of the GNU General }
{ Public License along with Renegade. If not, see }
{ <http://www.gnu.org/licenses/>. }
{*******************************************************}
{ _______ __ }
{ | _ .-----.-----.-----.-----.---.-.--| .-----. }
{ |. l | -__| | -__| _ | _ | _ | -__| }
{ |. _ |_____|__|__|_____|___ |___._|_____|_____| }
{ |: | | |_____| }
{ |::.|:. | }
{ `--- ---' }
{*******************************************************}
unit Renegade.Hash;
{$codepage utf8}
{$h+}{$mode objfpc}
interface
uses
Classes,
SysUtils,
Hash.Md,
Hash.Sha,
Hash.Base64,
Hash.Util;
type
RTHash = object
public
Base64 : RTBase64;static;
Sha : RTSha;static;
Md : RTMd;static;
Util : RTHashUtil;static;
function HashEquals(KnownHash, CheckedHash : ansistring): boolean;static;
end;
implementation
function RTHash.HashEquals(KnownHash, CheckedHash : ansistring): boolean;
begin
Result := Util.HashEquals(KnownHash, CheckedHash);
end;
end.

21
tests/Base64Test.pp Normal file
View File

@ -0,0 +1,21 @@
Program Base64Test;
{$mode objfpc}{$H+}
{$codepage utf8}
uses
Classes, SysUtils, Hash.Base64, Math;
var
TestString, Teststring2 : UTF8String;
begin
TestString := 'Humans are creative beings. People tend to read writing. This text will not appear in a consistent order. After Hours Programming created this application. Default text is for web developers and designers that need default text quickly. Thank you for using this application. Your design looks awesome by the way. JavaScript has the awesome power to manipulate DOM elements on the fly. This string is randomly generated. I hope you enjoyed the fake text.';
TestString2 := 'Humans are creative beings. People tend to read writing. This text will not appear in a consistent order. After Hours Programming created this application. Default text is for web developers and designers that need default text quickly. Thank you for using this application. Your design looks awesome by the way. JavaScript has the awesome power to manipulate DOM elements on the fly. This string is randomly generated. I hope you enjoyed the fake text.';
writeln(RTBase64.Encode(TestString));
writeln(RTBase64.Decode('SHVtYW5zIGFyZSBjcmVhdGl2ZSBiZWluZ3MuIFBlb3BsZSB0ZW5kIHRvIHJlYWQgd3JpdGluZy4gVGhpcyB0ZXh0IHdpbGwgbm90IGFwcGVhciBpbiBhIGNvbnNpc3RlbnQgb3JkZXIuIEFmdGVyIEhvdXJzIFByb2dyYW1taW5nIGNyZWF0ZWQgdGhpcyBhcHBsaWNhdGlvbi4gRGVmYXVsdCB0ZXh0IGlzIGZvciB3ZWIgZGV2ZWxvcGVycyBhbmQgZGVzaWduZXJzIHRoYXQgbmVlZCBkZWZhdWx0IHRleHQgcXVpY2tseS4gVGhhbmsgeW91IGZvciB1c2luZyB0aGlzIGFwcGxpY2F0aW9uLiBZb3VyIGRlc2lnbiBsb29rcyBhd2Vzb21lIGJ5IHRoZSB3YXkuIEphdmFTY3JpcHQgaGFzIHRoZSBhd2Vzb21lIHBvd2VyIHRvIG1hbmlwdWxhdGUgRE9NIGVsZW1lbnRzIG9uIHRoZSBmbHkuIFRoaXMgc3RyaW5nIGlzIHJhbmRvbWx5ICBnZW5lcmF0ZWQuIEkgaG9wZSB5b3UgZW5qb3llZCB0aGUgZmFrZSB0ZXh0Lg=='));
writeln(RTBase64.BSDEncode(TestString2));
writeln(RTBase64.BSDDecode('QFTrWU3xGEDwXQ/hakTfbEj0XQ/gXUjsX1KsGD/jZ1/qXQ/yXU3iGFPtGFHjWUOeb1HnbEjsXw2eTEfnaw/yXVfyGFbnZEueZk7yGEDuaETfag/nZg/fGELtZlLna1PjZlOeZ1HiXVGsGCDkbETwGCftbVHxGD/wZ0bwWUzrYU3lGELwXUDyXUOebEfnaw/faF/qYULfbEjtZg2ePETkWVTqbA/yXVfyGEjxGEXtag/1XUGeXET0XUvtaETwaw/fZkOeXETxYUbsXVHxGFPmWVOeZkTjXA/iXUXfbUvyGFPjcFOeaVTnW0rqcQ2eTEffZkqecU7zGEXtag/za0jsXw/yYEjxGEDuaEvnW0DyYU7sJg/XZ1TwGEPja0jlZg/qZ07paw/fb0TxZ0zjGEH3GFPmXQ/1WVisGCnfbkDRW1HnaFOeYEDxGFPmXQ/fb0TxZ0zjGF/tb0TwGFPtGEzfZkjubUvfbESePC7LGETqXUzjZlPxGE7sGFPmXQ/kZFisGDPmYVKea1PwYU3lGEjxGFHfZkPtZUv3GA/lXU3jakDyXUOsGCieYE7uXQ/3Z1SeXU3oZ1jjXA/yYESeXkDpXQ/yXVfyJe.'));
end.

29
tests/GenerateKnownShaHashes Executable file
View File

@ -0,0 +1,29 @@
#!/usr/bin/env php
<?php
$testWord = 'testing';
$result = [];
$sha0 = explode(' ', exec('echo -n "testing"|openssl dgst -sha -r'));
$result['sha-sha0'] = [
'sha' => '0',
'length' => (int)strlen(trim($sha0[0])),
'word' => $testWord,
'hash' => trim($sha0[0]),
];
foreach(hash_algos() as $algo)
{
if(false === (bool)preg_match('/(sha)/', $algo))
{
continue;
}
$hash = hash($algo, $testWord);
$filtered = preg_replace(['/sha/i', '/\//'], ['','-'], $algo);
$result[preg_replace('/\//', '-', $algo)] = [
'sha' => $filtered,
'length' => (int)strlen($hash),
'word' => $testWord,
'hash' => $hash,
];
}
file_put_contents('known.json', json_encode($result, JSON_PRETTY_PRINT));

View File

@ -1,22 +1,94 @@
{$codepage utf8}
{$h+}{$mode objfpc}
Program ShaTest;
program GeneratePascalShaHashes;
uses
SysUtils,
Classes,
fpJson,
TestFramework,
Hash.Sha;
function ConstToString(const ShaConst: RTSupportedShaHashTypes): ansistring;
begin
case ShaConst of
rtSha0: Result := 'Sha-Sha0';
rtSha1: Result := 'Sha1';
rtSha224: Result := 'Sha224';
rtSha256: Result := 'Sha256';
rtSha384: Result := 'Sha384';
rtSha512_224: Result := 'Sha512-224';
rtSha512_256: Result := 'Sha512-256';
rtSha512: Result := 'Sha512';
rtSha3_224: Result := 'Sha3-224';
rtSha3_256: Result := 'Sha3-256';
rtSha3_384: Result := 'Sha3-384';
rtSha3_512: Result := 'Sha3-512';
else
Result := 'Unknown';
end;
end;
function stripAlpha(S: ansistring): ansistring;
var
C: set of char;
i: integer;
begin
C := ['a'..'z'];
for i := length(S) downto 1 do
begin
if LowerCase(S[i]) in C then
begin
Delete(S, i, 1);
end;
end;
if S = '-0' then
begin
Result := '0';
end
else
begin
Result := S;
end;
end;
Uses
SysUtils,
Classes,
Hash.Sha;
var
Hash : RTSha;
S : UTF8String;
S: UTF8String;
Hash, ConstString, JSONResult: ansistring;
JObjectResult, JObject: TJSONOBject;
ConstType: RTSupportedShaHashTypes;
FileStream: TFileStream;
begin
Hash := RTSha.Create;
S := 'testing';
WriteLn(Hash.Sha1(S));
Writeln(Hash.Sha224(S));
Writeln(Hash.Sha256(S));
Writeln(Hash.Sha384(S));
Writeln(Hash.Sha512(S));
Hash.Free;
Exit;
JObject := TJSONObject.Create;
JObjectResult := TJSONObject.Create;
S := 'testing';
FileStream := TFileStream.Create('pascal.json', fmOpenWrite or fmCreate);
for ConstType in RTSupportedShaHashTypesSet do
begin
ConstString := ConstToString(ConstType);
Hash := RTSha.CreateSha(S, ConstType);
JObject.Add('sha', LowerCase(StripAlpha(ConstString)));
JObject.Add('length', Length(Hash));
JObject.Add('word', S);
JObject.Add('hash', Hash);
JOBjectResult.Add(LowerCase(ConstString), JObject);
JObject := TJSONObject.Create;
end;
FileStream.Seek(0, soBeginning);
JSONResult := JObjectResult.FormatJSON(DefaultFormat, 4);
FileStream.Write(JSONResult[1], Length(JSONResult));
FileStream.Free;
JObject.Free;
JObjectResult.Free;
end.

View File

@ -1,24 +0,0 @@
<?php
$algos = [
'sha1',
'sha224',
'sha256',
'sha384',
'sha512',
];
$testWord = 'testing';
$result = [];
foreach($algos as $algo)
{
$hash = hash($algo, $testWord);
$result[$algo] = [
'sha' => (int) trim(filter_var($algo, FILTER_SANITIZE_NUMBER_INT), '+-'),
'length' => (int)strlen($hash),
'word' => $testWord,
'hash' => $hash,
];
}
file_put_contents('sha_hashes.json', json_encode($result, JSON_PRETTY_PRINT));

13
tests/HashEquals.pp Normal file
View File

@ -0,0 +1,13 @@
Program test;
Uses
SysUtils,
Classes,
Renegade.Hash;
var
R : Boolean;
begin
Writeln(RTHash.Base64.Encode('testing'));
R := RTHash.HashEquals('881c7d6ba98678bcd96e253086c4048c3ea15306d0d13ff48341c6285ee71102a47b6f16e20e4d65c0c3d677be689dfda6d326695609cbadfafa1800e9eb7fc1','881c7d6ba98678bcd96e253086c4048c3ea15306d0d13ff48341c6285ee71102a47b6f16e20e4d65c0c3d677be689dfda6d326695609cbadfafa1800e9eb7fc1');
Writeln(R);
end.

View File

@ -9,13 +9,8 @@ Uses
DateUtils,
Classes;
var
Hash : Md;
begin
Hash := Md.Create;
Writeln('MD2 : ', Hash.md2(DateTimeToStr(Now)));
Writeln('MD4 : ', Hash.md4(DateTimeToStr(Now)));
Writeln('MD5 : ', Hash.md5(DateTimeToStr(Now)));
Hash.Free;
Writeln('MD2 : ', Md.md2(DateTimeToStr(Now)));
Writeln('MD4 : ', Md.md4(DateTimeToStr(Now)));
Writeln('MD5 : ', Md.md5(DateTimeToStr(Now)));
end.

View File

@ -12,7 +12,7 @@ packages=
fpcpackage=y
[compiler]
options=-Fu..
options=-Fu"..;../HashLib/HashLib/src/*"
[default]
fpcdir=${FPCDIR}

View File

@ -1,22 +0,0 @@
{$codepage utf8}
{$h+}{$mode objfpc}
Program ShaTest;
Uses
SysUtils,
Classes,
Hash.Sha;
var
Hash : RTSha;
S : UTF8String;
begin
Hash := RTSha.Create;
S := 'testing';
WriteLn(Hash.Sha1(S));
Writeln(Hash.Sha224(S));
Writeln(Hash.Sha256(S));
Writeln(Hash.Sha384(S));
Writeln(Hash.Sha512(S));
Hash.Free;
Exit;
end.

View File

@ -1,32 +0,0 @@
{
"sha1": {
"sha": 1,
"length": 40,
"word": "testing",
"hash": "dc724af18fbdd4e59189f5fe768a5f8311527050"
},
"sha224": {
"sha": 224,
"length": 56,
"word": "testing",
"hash": "9e8965af89bd98c015512f1eb17ae07f48494da2d9a06a8f9659f749"
},
"sha256": {
"sha": 256,
"length": 64,
"word": "testing",
"hash": "cf80cd8aed482d5d1527d7dc72fceff84e6326592848447d2dc0b0e87dfc9a90"
},
"sha384": {
"sha": 384,
"length": 96,
"word": "testing",
"hash": "cf4811d74fd40504674fc3273f824fa42f755b9660a2e902b57f1df74873db1a91a037bcee65f1a88ecd1ef57ff254c9"
},
"sha512": {
"sha": 512,
"length": 128,
"word": "testing",
"hash": "521b9ccefbcd14d179e7a1bb877752870a6d620938b28a66a107eac6e6805b9d0989f45b5730508041aa5e710847d439ea74cd312c9355f1f2dae08d40e41d50"
}
}