diff --git a/Hash.Md.pp b/Hash.Md.pp
index 7a11c65..7812ade 100644
--- a/Hash.Md.pp
+++ b/Hash.Md.pp
@@ -1,38 +1,72 @@
+{*******************************************************}
+
+{ 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 | -__| | -__| _ | _ | _ | -__| }
+{ |. _ |_____|__|__|_____|___ |___._|_____|_____| }
+{ |: | | |_____| }
+{ |::.|:. | }
+{ `--- ---' }
+{*******************************************************}
{$codepage utf8}
{$h+}
{$mode objfpc}
-Unit Hash.Md;
+unit Hash.Md;
interface
-Uses
- md5,
- SysUtils,
- Classes;
+uses
+ md5,
+ SysUtils,
+ Classes;
-Type
- Md = class(TObject)
- public
- function md2(S : UTF8String) : AnsiString;
- function md4(S : UTF8String) : AnsiString;
- function md5(S : UTF8STring) : AnsiString;
- end;
+type
+ Md = class(TObject)
+ public
+ function md2(S: UTF8String): ansistring;
+ function md4(S: UTF8String): ansistring;
+ function md5(S: UTF8STring): ansistring;
+ end;
implementation
-function Md.md2(S : UTF8String) : AnsiString;
+function Md.md2(S: UTF8String): ansistring;
begin
Result := MD2Print(MDString(S, MD_VERSION_2));
end;
-function Md.md4(S : UTF8String) : AnsiString;
+function Md.md4(S: UTF8String): ansistring;
begin
Result := MD4Print(MDString(S, MD_VERSION_4));
end;
-function Md.md5(S : UTF8String) : AnsiString;
+function Md.md5(S: UTF8String): ansistring;
begin
Result := MD5Print(MDString(S, MD_VERSION_5));
end;
-End.
\ No newline at end of file
+end.
diff --git a/Hash.Sha.pp b/Hash.Sha.pp
index e69de29..13b4935 100644
--- a/Hash.Sha.pp
+++ b/Hash.Sha.pp
@@ -0,0 +1,302 @@
+{*******************************************************}
+
+{ 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 | -__| | -__| _ | _ | _ | -__| }
+{ |. _ |_____|__|__|_____|___ |___._|_____|_____| }
+{ |: | | |_____| }
+{ |::.|:. | }
+{ `--- ---' }
+{*******************************************************}
+{$mode objfpc}
+{$codepage utf8}
+{$h+}
+
+unit Hash.Sha;
+
+interface
+
+uses
+ SysUtils,
+ Classes,
+ OpenSSL,
+ CTypes;
+
+const
+ SHA512_DIGEST_LENGTH = 64;
+ SHA384_DIGEST_LENGTH = 48;
+ SHA256_DIGEST_LENGTH = 32;
+ SHA224_DIGEST_LENGTH = 28;
+
+type
+ RTSha = class(TObject)
+ 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;
+ end;
+
+implementation
+
+constructor RTSha.Create();
+var
+ HaveOpenSSL : Boolean;
+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);
+ end;
+end;
+
+destructor RTSha.Destroy();
+begin
+ inherited Destroy;
+ EVPcleanup;
+ DestroySSLInterface;
+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);
+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);
+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);
+
+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);
+
+end;
+
+function RTSha.Sha512(S: UTF8String): ansistring;
+var
+ Digest : PEVP_MD;
+ ShaCTX : PEVP_MD_CTX;
+ HexValue : AnsiString;
+ BinValue : PChar;
+ Hash : PByte;
+ DigestLength: pcuint;
+begin
+
+ 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
+
+ On e: Exception do
+ begin
+ WriteLn(e.Message);
+ Writeln(e.HelpContext);
+ Free;
+ exit;
+ end;
+ end;
+
+ Move(Hash[0], BinValue[0], SHA512_DIGEST_LENGTH);
+
+ BinToHex(BinValue, PChar(HexValue), SHA512_DIGEST_LENGTH);
+ // Cleanup
+ FreeMem(Hash);
+ FreeMem(DigestLength);
+ FreeMem(BinValue);
+
+ Result := LowerCase(HexValue);
+
+end;
+
+end.
diff --git a/Hash.Sha1.pp b/Hash.Sha1.pp
deleted file mode 100644
index e69de29..0000000
diff --git a/Hash.Sha224.pp b/Hash.Sha224.pp
deleted file mode 100644
index e69de29..0000000
diff --git a/Hash.Sha256.pp b/Hash.Sha256.pp
deleted file mode 100644
index e69de29..0000000
diff --git a/Hash.Sha384.pp b/Hash.Sha384.pp
deleted file mode 100644
index e69de29..0000000
diff --git a/Hash.Sha512.pp b/Hash.Sha512.pp
deleted file mode 100644
index e69de29..0000000
diff --git a/tests/GeneratePascalShaHashes.pp b/tests/GeneratePascalShaHashes.pp
new file mode 100644
index 0000000..7fe943b
--- /dev/null
+++ b/tests/GeneratePascalShaHashes.pp
@@ -0,0 +1,22 @@
+{$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/tests/GenerateProperHashes.php b/tests/GenerateProperHashes.php
new file mode 100644
index 0000000..e82cda1
--- /dev/null
+++ b/tests/GenerateProperHashes.php
@@ -0,0 +1,24 @@
+ (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/MDTest.pp b/tests/MDTest.pp
similarity index 100%
rename from MDTest.pp
rename to tests/MDTest.pp
diff --git a/tests/Makefile.fpc b/tests/Makefile.fpc
new file mode 100644
index 0000000..bf5f04e
--- /dev/null
+++ b/tests/Makefile.fpc
@@ -0,0 +1,23 @@
+#
+# Makefile.fpc for hash units example
+#
+
+[target]
+programs=MDTest GeneratePascalShaHashes
+
+[require]
+packages=
+
+[install]
+fpcpackage=y
+
+[compiler]
+options=-Fu..
+
+[default]
+fpcdir=${FPCDIR}
+
+
+
+
+
diff --git a/tests/ShaTest.pp b/tests/ShaTest.pp
new file mode 100644
index 0000000..7fe943b
--- /dev/null
+++ b/tests/ShaTest.pp
@@ -0,0 +1,22 @@
+{$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/tests/autogen.sh b/tests/autogen.sh
new file mode 100755
index 0000000..a58be65
--- /dev/null
+++ b/tests/autogen.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+fpcBaseInput=$1
+
+if [ "$fpcBaseInput" == "" ]; then
+ fpcBase=$(dirname $(dirname $(which fpc)))/lib/fpc/$(fpc -iV)
+else
+ fpcBase=$fpcBaseInput
+fi
+
+if [ ! -d $fpcBase ]; then
+ echo "Need an FPC base to fpc sources"
+ echo "Usually /usr/lib{32,64}/fpc/{fpc-version}/ on Linux machines."
+ echo "or C:\FPC\..\.. on Windows machines."
+ exit 255
+fi
+
+[ -f "Makefile" ] && rm Makefile
+
+echo "Making with unit/source directory '$fpcBase'"
+
+FPCDIR="$fpcBase" fpcmake
+
diff --git a/tests/sha_hashes.json b/tests/sha_hashes.json
new file mode 100644
index 0000000..f75b8fd
--- /dev/null
+++ b/tests/sha_hashes.json
@@ -0,0 +1,32 @@
+{
+ "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