ADD: Simple 32-bits checksum in available checksum functions (#160)

Used in retrocomputing to validate old ROM files.
This commit is contained in:
Denis Bisson 2021-08-24 12:48:06 -04:00 committed by GitHub
commit 48451b4aa4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 164 additions and 7 deletions

View file

@ -0,0 +1,150 @@
{******************************************************************************}
{* Simple 32-bits checksum class integrated in existing **********}
{* DCPcrypt v2.0 written by David Barton (crypto@cityinthesky.co.uk) **********}
{******************************************************************************}
{* A binary compatible implementation of simple 32-bits checksum *}
{******************************************************************************}
{* Copyright (C) 2021 Alexander Koblov (alexx2000@mail.ru) *}
{* 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. *}
{******************************************************************************}
unit dcpchecksum32;
{$mode objfpc}{$H+}
interface
uses
Classes, Sysutils, DCPcrypt2, DCPconst;
type
{ TDCP_checksum32 }
TDCP_checksum32 = class(TDCP_hash)
protected
CurrentHash: DWORD;
public
class function GetId: integer; override;
class function GetAlgorithm: string; override;
class function GetHashSize: integer; override;
class function SelfTest: boolean; override;
constructor Create(AOwner: TComponent); override;
procedure Init; override;
procedure Burn; override;
procedure Update(const Buffer; Size: longword); override;
procedure Final(var Digest); override;
end;
implementation
{$R-}{$Q-}
{ TDCP_checksum32 }
{ TDCP_checksum32.GetHashSize }
class function TDCP_checksum32.GetHashSize: integer;
begin
Result:= 32;
end;
{ TDCP_checksum32.GetId }
class function TDCP_checksum32.GetId: integer;
begin
Result:= DCP_checksum32;
end;
{ TDCP_checksum32.GetAlgorithm }
class function TDCP_checksum32.GetAlgorithm: string;
begin
Result:= 'CHECKSUM32';
end;
{ TDCP_checksum32.SelfTest }
class function TDCP_checksum32.SelfTest: boolean;
const
Test1Out: array[0..3] of byte=($00, $00, $01, $26); //Verified on 2021-08-24
Test2Out: array[0..3] of byte=($00, $00, $0B, $1F);
var
TestHash: TDCP_checksum32;
TestOut: array[0..3] of byte;
begin
dcpFillChar(TestOut, SizeOf(TestOut), 0);
TestHash:= TDCP_checksum32.Create(nil);
TestHash.Init;
TestHash.UpdateStr('abc');
TestHash.Final(TestOut);
Result:= CompareMem(@TestOut,@Test1Out,Sizeof(Test1Out));
TestHash.Init;
TestHash.UpdateStr('abcdefghijklmnopqrstuvwxyz');
TestHash.Final(TestOut);
Result:= CompareMem(@TestOut,@Test2Out,Sizeof(Test2Out)) and Result;
TestHash.Free;
end;
{ TDCP_checksum32.Create }
constructor TDCP_checksum32.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
end;
{ TDCP_checksum32.Init }
procedure TDCP_checksum32.Init;
begin
Burn;
CurrentHash:= 0;
fInitialized:= true;
end;
{ TDCP_checksum32 }
procedure TDCP_checksum32.Burn;
begin
CurrentHash:= 0;
fInitialized:= false;
end;
{ TDCP_checksum32.Update }
{$PUSH}{$R-}{$Q-}{$OPTIMIZATION LEVEL4} // no range, no overflow checks, optimize for speed (not size)
procedure TDCP_checksum32.Update(const Buffer; Size: longword);
var
data: PByte;
iIndex: longword;
iChecksumLocal: DWORD;
begin
iChecksumLocal := CurrentHash; //Manipulating the copy "iChecksumLocal" in the loop is overall faster then working directly with property "CurrentHash".
data := @Buffer;
for iIndex := 1 to Size do
begin
iChecksumLocal := iChecksumLocal + data^;
inc(data);
end;
CurrentHash := iChecksumLocal;
end;
{$POP}
{ TDCP_checksum32.Final }
procedure TDCP_checksum32.Final(var Digest);
begin
if not fInitialized then
raise EDCP_hash.Create('Hash not initialized');
CurrentHash:= SwapEndian(CurrentHash);
Move(CurrentHash, Digest, Sizeof(CurrentHash));
Burn;
end;
end.

View file

@ -63,6 +63,7 @@ const
DCP_sha256 = 28;
DCP_sha384 = 29;
DCP_sha512 = 30;
DCP_checksum32 = 93;
DCP_blake3 = 94;
DCP_blake2bp = 95;
DCP_blake2b = 96;

View file

@ -39,7 +39,7 @@
www.cityinthesky.co.uk/cryptography.html
"/>
<Version Major="3" Minor="1"/>
<Files Count="32">
<Files Count="33">
<Item1>
<Filename Value="dcpbase64.pas"/>
<UnitName Value="DCPbase64"/>
@ -168,6 +168,10 @@ www.cityinthesky.co.uk/cryptography.html
<Filename Value="Hashes/dcpblake3.pas"/>
<UnitName Value="DCPblake3"/>
</Item32>
<Item33>
<Filename Value="Hashes/dcpchecksum32.pas"/>
<UnitName Value="dcpchecksum32"/>
</Item33>
</Files>
<RequiredPkgs Count="2">
<Item1>

View file

@ -11,7 +11,7 @@ uses
DCPbase64, DCPblockciphers, DCPconst, DCPcrypt2, DCPhaval, DCPmd4, DCPmd5,
DCPripemd128, DCPripemd160, DCPsha1, DCPsha256, DCPsha512, DCPtiger,
DCPcrc32, DCcrc32, DCblake2, DCPblake2, DCPsha3, HMAC, SHA3, SHA3_512,
ISAAC, scrypt, DCPrijndael, SHA1, Argon2, DCPblake3;
ISAAC, scrypt, DCPrijndael, SHA1, Argon2, DCPblake3, dcpchecksum32;
implementation

View file

@ -4,7 +4,7 @@
General Hash Unit: This unit defines the common types, functions,
and procedures
Copyright (C) 2009-2019 Alexander Koblov (alexx2000@mail.ru)
Copyright (C) 2009-2021 Alexander Koblov (alexx2000@mail.ru)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -33,7 +33,7 @@ uses
type
THashContext = TDCP_hash;
THashAlgorithm = (HASH_BLAKE2S, HASH_BLAKE2SP, HASH_BLAKE2B, HASH_BLAKE2BP, HASH_BLAKE3,
HASH_CRC32, HASH_HAVAL, HASH_MD4, HASH_MD5, HASH_RIPEMD128, HASH_RIPEMD160,
HASH_CHECKSUM32, HASH_CRC32, HASH_HAVAL, HASH_MD4, HASH_MD5, HASH_RIPEMD128, HASH_RIPEMD160,
HASH_SFV, HASH_SHA1, HASH_SHA224, HASH_SHA256, HASH_SHA384, HASH_SHA512,
HASH_SHA3_224, HASH_SHA3_256, HASH_SHA3_384, HASH_SHA3_512, HASH_TIGER,
HASH_BEST
@ -41,14 +41,14 @@ type
var
HashFileExt: array[Low(THashAlgorithm)..Pred(High(THashAlgorithm))] of String = (
'blake2s', 'blake2sp', 'blake2b', 'blake2bp', 'blake3', 'crc32', 'haval',
'blake2s', 'blake2sp', 'blake2b', 'blake2bp', 'blake3', 'checksum32', 'crc32', 'haval',
'md4', 'md5', 'ripemd128', 'ripemd160', 'sfv', 'sha', 'sha224', 'sha256',
'sha384', 'sha512', 'sha3', 'sha3', 'sha3', 'sha3', 'tiger'
);
var
HashName: array[Low(THashAlgorithm)..Pred(High(THashAlgorithm))] of String = (
'blake2s', 'blake2sp', 'blake2b', 'blake2bp', 'blake3', 'crc32', 'haval',
'blake2s', 'blake2sp', 'blake2b', 'blake2bp', 'blake3', 'checksum32', 'crc32', 'haval',
'md4', 'md5', 'ripemd128', 'ripemd160', 'sfv', 'sha1_160', 'sha2_224',
'sha2_256', 'sha2_384', 'sha2_512', 'sha3_224', 'sha3_256',
'sha3_384', 'sha3_512', 'tiger'
@ -67,7 +67,7 @@ function FileExtToHashAlg(const FileExt: String): THashAlgorithm;
implementation
uses
LazUTF8, DCPhaval, DCPmd4, DCPmd5, DCPripemd128, DCPripemd160, DCPcrc32,
LazUTF8, DCPhaval, DCPmd4, DCPmd5, DCPripemd128, DCPripemd160, DCPChecksum32, DCPcrc32,
DCPsha1, DCPsha256, DCPsha512, DCPtiger, DCPblake2, DCPblake3, DCPsha3;
procedure HashInit(out Context: THashContext; Algorithm: THashAlgorithm);
@ -87,6 +87,7 @@ begin
HASH_BLAKE2B: Context:= TDCP_blake2b.Create(nil);
HASH_BLAKE2BP: Context:= TDCP_blake2bp.Create(nil);
HASH_BLAKE3: Context:= TDCP_blake3.Create(nil);
HASH_CHECKSUM32: Context:= TDCP_checksum32.Create(nil);
HASH_CRC32: Context:= TDCP_crc32.Create(nil);
HASH_HAVAL: Context:= TDCP_haval.Create(nil);
HASH_MD4: Context:= TDCP_md4.Create(nil);
@ -105,6 +106,7 @@ begin
HASH_SHA3_512: Context:= TDCP_sha3_512.Create(nil);
HASH_TIGER: Context:= TDCP_tiger.Create(nil);
end;
Context.Init;
end;