2
0
Эх сурвалжийг харах

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

Used in retrocomputing to validate old ROM files.
Denis Bisson 4 жил өмнө
parent
commit
48451b4aa4

+ 150 - 0
components/dcpcrypt/Hashes/dcpchecksum32.pas

@@ -0,0 +1,150 @@
+{******************************************************************************}
+{* Simple 32-bits checksum class integrated in existing              **********}
+{* DCPcrypt v2.0 written by David Barton ([email protected]) **********}
+{******************************************************************************}
+{* A binary compatible implementation of simple 32-bits checksum              *}
+{******************************************************************************}
+{* Copyright (C) 2021 Alexander Koblov ([email protected])                    *}
+{* 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.
+

+ 1 - 0
components/dcpcrypt/dcpconst.pas

@@ -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;

+ 5 - 1
components/dcpcrypt/dcpcrypt.lpk

@@ -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>

+ 1 - 1
components/dcpcrypt/dcpcrypt.pas

@@ -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
 

+ 7 - 5
src/uhash.pas

@@ -4,7 +4,7 @@
     General Hash Unit: This unit defines the common types, functions,
     and procedures
 
-    Copyright (C) 2009-2019 Alexander Koblov ([email protected])
+    Copyright (C) 2009-2021 Alexander Koblov ([email protected])
 
     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;