diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..c745a66
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "HashLib"]
+ path = HashLib
+ url = https://github.com/Xor-el/HashLib4Pascal.git
diff --git a/Hash.Base64.pp b/Hash.Base64.pp
new file mode 100644
index 0000000..bf1c420
--- /dev/null
+++ b/Hash.Base64.pp
@@ -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 }
+{ . }
+
+{*******************************************************}
+{ _______ __ }
+{ | _ .-----.-----.-----.-----.---.-.--| .-----. }
+{ |. 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.
diff --git a/Hash.Blake2b.pp b/Hash.Blake2b.pp
index e69de29..7e0774c 100644
--- a/Hash.Blake2b.pp
+++ b/Hash.Blake2b.pp
@@ -0,0 +1 @@
+{ TODO }
diff --git a/Hash.Sha3_224.pp b/Hash.Blake2s.pp
similarity index 100%
rename from Hash.Sha3_224.pp
rename to Hash.Blake2s.pp
diff --git a/Hash.Md.pp b/Hash.Md.pp
index 7812ade..2b6710a 100644
--- a/Hash.Md.pp
+++ b/Hash.Md.pp
@@ -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;
diff --git a/Hash.Sha.pp b/Hash.Sha.pp
index dfa2af3..a02978c 100644
--- a/Hash.Sha.pp
+++ b/Hash.Sha.pp
@@ -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.
diff --git a/Hash.Sha3_384.pp b/Hash.Sha3_384.pp
deleted file mode 100644
index e69de29..0000000
diff --git a/Hash.Sha3_512.pp b/Hash.Sha3_512.pp
deleted file mode 100644
index e69de29..0000000
diff --git a/Hash.Util.pp b/Hash.Util.pp
new file mode 100644
index 0000000..8355536
--- /dev/null
+++ b/Hash.Util.pp
@@ -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 }
+{ . }
+
+{*******************************************************}
+{ _______ __ }
+{ | _ .-----.-----.-----.-----.---.-.--| .-----. }
+{ |. 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.
diff --git a/HashLib b/HashLib
new file mode 160000
index 0000000..7a84816
--- /dev/null
+++ b/HashLib
@@ -0,0 +1 @@
+Subproject commit 7a84816f501674e73d01dbfe01f2adbe17828a6e
diff --git a/Renegade.Hash.pp b/Renegade.Hash.pp
new file mode 100644
index 0000000..d9288f2
--- /dev/null
+++ b/Renegade.Hash.pp
@@ -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 }
+{ . }
+
+{*******************************************************}
+{ _______ __ }
+{ | _ .-----.-----.-----.-----.---.-.--| .-----. }
+{ |. 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.
+
+
diff --git a/tests/Base64Test.pp b/tests/Base64Test.pp
new file mode 100644
index 0000000..ae5a256
--- /dev/null
+++ b/tests/Base64Test.pp
@@ -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.
+
diff --git a/tests/GenerateKnownShaHashes b/tests/GenerateKnownShaHashes
new file mode 100755
index 0000000..e83995d
--- /dev/null
+++ b/tests/GenerateKnownShaHashes
@@ -0,0 +1,29 @@
+#!/usr/bin/env php
+ '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));
\ No newline at end of file
diff --git a/tests/GeneratePascalShaHashes.pp b/tests/GeneratePascalShaHashes.pp
index 7fe943b..4b2ee35 100644
--- a/tests/GeneratePascalShaHashes.pp
+++ b/tests/GeneratePascalShaHashes.pp
@@ -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;
-end.
\ No newline at end of file
+ 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.
diff --git a/tests/GenerateProperHashes.php b/tests/GenerateProperHashes.php
deleted file mode 100644
index e82cda1..0000000
--- a/tests/GenerateProperHashes.php
+++ /dev/null
@@ -1,24 +0,0 @@
- (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));
\ No newline at end of file
diff --git a/tests/HashEquals.pp b/tests/HashEquals.pp
new file mode 100644
index 0000000..5e41292
--- /dev/null
+++ b/tests/HashEquals.pp
@@ -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.
\ No newline at end of file
diff --git a/tests/MDTest.pp b/tests/MDTest.pp
index ebf451f..b76d88c 100644
--- a/tests/MDTest.pp
+++ b/tests/MDTest.pp
@@ -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.
\ No newline at end of file
diff --git a/tests/Makefile.fpc b/tests/Makefile.fpc
index bf5f04e..61fccbd 100644
--- a/tests/Makefile.fpc
+++ b/tests/Makefile.fpc
@@ -12,7 +12,7 @@ packages=
fpcpackage=y
[compiler]
-options=-Fu..
+options=-Fu"..;../HashLib/HashLib/src/*"
[default]
fpcdir=${FPCDIR}
diff --git a/tests/ShaTest.pp b/tests/ShaTest.pp
deleted file mode 100644
index 7fe943b..0000000
--- a/tests/ShaTest.pp
+++ /dev/null
@@ -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.
\ No newline at end of file
diff --git a/Hash.Sha3_256.pp b/tests/ShaTests.pp
similarity index 100%
rename from Hash.Sha3_256.pp
rename to tests/ShaTests.pp
diff --git a/tests/sha_hashes.json b/tests/sha_hashes.json
deleted file mode 100644
index f75b8fd..0000000
--- a/tests/sha_hashes.json
+++ /dev/null
@@ -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"
- }
-}
\ No newline at end of file