Solved

Hash - crc32 - help with portting a pascal unit to delphi 6

Posted on 2004-09-23
11
909 Views
Last Modified: 2010-04-05

I have a old pascal that isn't mine, but looks as thought it is public a domain unit that I would like to port to be able to use it in a delphi application.  In pascal it creates a crc32 hash value from a all upper case string and stores that in a longint.  Then later compares what a user enters for a password against that hash value.  So, I don't have to store the accual password in a record file just the returned hash.

Here is the unit.

unit crc32a;
{
  /* ============================================================= */
  /*  COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or       */
  /*  code or tables extracted from it, as desired without restriction.     */
  /*                                                                        */
  /*  First, the polynomial itself and its table of feedback terms.  The    */
  /*  polynomial is                                                         */
  /*  X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0   */
  /*                                                                        */
  /*  Note that we take it "backwards" and put the highest-order term in    */
  /*  the lowest-order bit.  The X^32 term is "implied"; the LSB is the     */
  /*  X^31 term, etc.  The X^0 term (usually shown as "+1") results in      */
  /*  the MSB being 1.                                                      */
  /*                                                                        */
  /*  Note that the usual hardware shift register implementation, which     */
  /*  is what we're using (we're merely optimizing it by doing eight-bit    */
  /*  chunks at a time) shifts bits into the lowest-order term.  In our     */
  /*  implementation, that means shifting towards the right.  Why do we     */
  /*  do it this way?  Because the calculated CRC must be transmitted in    */
  /*  order from highest-order term to lowest-order term.  UARTs transmit   */
  /*  characters in order from LSB to MSB.  By storing the CRC this way,    */
  /*  we hand it to the UART in the order low-byte to high-byte; the UART   */
  /*  sends each low-bit to hight-bit; and the result is transmission bit   */
  /*  by bit from highest- to lowest-order term without requiring any bit   */
  /*  shuffling on our part.  Reception works similarly.                    */
  /*                                                                        */
  /*  The feedback terms table consists of 256, 32-bit entries.  Notes:     */
  /*                                                                        */
  /*      The table can be generated at runtime if desired; code to do so   */
  /*      is shown later.  It might not be obvious, but the feedback        */
  /*      terms simply represent the results of eight shift/xor opera-      */
  /*      tions for all combinations of data and CRC register values.       */
  /*                                                                        */
  /*      The values must be right-shifted by eight bits by the "updcrc"    */
  /*      logic; the shift must be unsigned (bring in zeroes).  On some     */
  /*      hardware you could probably optimize the shift in assembler by    */
  /*      using byte-swap instructions.                                     */
  /*      polynomial $edb88320                                              */
  /*                                                                        */
  /*  --------------------------------------------------------------------  */
}

interface

type
  pbyte = ^byte;
  longrec = record
    lo,hi : word;
  end;

var
  crc32val : longint;


procedure updatecrc(s : pchar; len : integer);

implementation

const
  crc_32_tab : array[0..255] of longint = (
      $00000000, $77073096, $ee0e612c, $990951ba, $076dc419,
      $706af48f, $e963a535, $9e6495a3, $0edb8832, $79dcb8a4,
      $e0d5e91e, $97d2d988, $09b64c2b, $7eb17cbd, $e7b82d07,
      $90bf1d91, $1db71064, $6ab020f2, $f3b97148, $84be41de,
      $1adad47d, $6ddde4eb, $f4d4b551, $83d385c7, $136c9856,
      $646ba8c0, $fd62f97a, $8a65c9ec, $14015c4f, $63066cd9,
      $fa0f3d63, $8d080df5, $3b6e20c8, $4c69105e, $d56041e4,
      $a2677172, $3c03e4d1, $4b04d447, $d20d85fd, $a50ab56b,
      $35b5a8fa, $42b2986c, $dbbbc9d6, $acbcf940, $32d86ce3,
      $45df5c75, $dcd60dcf, $abd13d59, $26d930ac, $51de003a,
      $c8d75180, $bfd06116, $21b4f4b5, $56b3c423, $cfba9599,
      $b8bda50f, $2802b89e, $5f058808, $c60cd9b2, $b10be924,
      $2f6f7c87, $58684c11, $c1611dab, $b6662d3d, $76dc4190,
      $01db7106, $98d220bc, $efd5102a, $71b18589, $06b6b51f,
      $9fbfe4a5, $e8b8d433, $7807c9a2, $0f00f934, $9609a88e,
      $e10e9818, $7f6a0dbb, $086d3d2d, $91646c97, $e6635c01,
      $6b6b51f4, $1c6c6162, $856530d8, $f262004e, $6c0695ed,
      $1b01a57b, $8208f4c1, $f50fc457, $65b0d9c6, $12b7e950,
      $8bbeb8ea, $fcb9887c, $62dd1ddf, $15da2d49, $8cd37cf3,
      $fbd44c65, $4db26158, $3ab551ce, $a3bc0074, $d4bb30e2,
      $4adfa541, $3dd895d7, $a4d1c46d, $d3d6f4fb, $4369e96a,
      $346ed9fc, $ad678846, $da60b8d0, $44042d73, $33031de5,
      $aa0a4c5f, $dd0d7cc9, $5005713c, $270241aa, $be0b1010,
      $c90c2086, $5768b525, $206f85b3, $b966d409, $ce61e49f,
      $5edef90e, $29d9c998, $b0d09822, $c7d7a8b4, $59b33d17,
      $2eb40d81, $b7bd5c3b, $c0ba6cad, $edb88320, $9abfb3b6,
      $03b6e20c, $74b1d29a, $ead54739, $9dd277af, $04db2615,
      $73dc1683, $e3630b12, $94643b84, $0d6d6a3e, $7a6a5aa8,
      $e40ecf0b, $9309ff9d, $0a00ae27, $7d079eb1, $f00f9344,
      $8708a3d2, $1e01f268, $6906c2fe, $f762575d, $806567cb,
      $196c3671, $6e6b06e7, $fed41b76, $89d32be0, $10da7a5a,
      $67dd4acc, $f9b9df6f, $8ebeeff9, $17b7be43, $60b08ed5,
      $d6d6a3e8, $a1d1937e, $38d8c2c4, $4fdff252, $d1bb67f1,
      $a6bc5767, $3fb506dd, $48b2364b, $d80d2bda, $af0a1b4c,
      $36034af6, $41047a60, $df60efc3, $a867df55, $316e8eef,
      $4669be79, $cb61b38c, $bc66831a, $256fd2a0, $5268e236,
      $cc0c7795, $bb0b4703, $220216b9, $5505262f, $c5ba3bbe,
      $b2bd0b28, $2bb45a92, $5cb36a04, $c2d7ffa7, $b5d0cf31,
      $2cd99e8b, $5bdeae1d, $9b64c2b0, $ec63f226, $756aa39c,
      $026d930a, $9c0906a9, $eb0e363f, $72076785, $05005713,
      $95bf4a82, $e2b87a14, $7bb12bae, $0cb61b38, $92d28e9b,
      $e5d5be0d, $7cdcefb7, $0bdbdf21, $86d3d2d4, $f1d4e242,
      $68ddb3f8, $1fda836e, $81be16cd, $f6b9265b, $6fb077e1,
      $18b74777, $88085ae6, $ff0f6a70, $66063bca, $11010b5c,
      $8f659eff, $f862ae69, $616bffd3, $166ccf45, $a00ae278,
      $d70dd2ee, $4e048354, $3903b3c2, $a7672661, $d06016f7,
      $4969474d, $3e6e77db, $aed16a4a, $d9d65adc, $40df0b66,
      $37d83bf0, $a9bcae53, $debb9ec5, $47b2cf7f, $30b5ffe9,
      $bdbdf21c, $cabac28a, $53b39330, $24b4a3a6, $bad03605,
      $cdd70693, $54de5729, $23d967bf, $b3667a2e, $c4614ab8,
      $5d681b02, $2a6f2b94, $b40bbe37, $c30c8ea1, $5a05df1b,
      $2d02ef8d);

procedure updatecrc(s : pchar; len : integer);
(* update running CRC calculation with contents of a buffer *)

var
  crcl : longrec absolute crc32val;
  x : integer;

begin
  for x := 1 to len do
    begin
      crc32val := crc_32_tab[lo(crcl.lo) xor byte(s^)] xor ((crc32val
shr 8) and $00ffffff);
      inc(s);
    end;
end;


end.
[-------------------------------------------------------------------------------------------]


Here is how I would use it in pascal.
[-------------------------------------------------------------------------------------------]
program getpass;
uses crt;
var
   s:string;
   pw:longint;

function UpdateCRC32(CRC:longint; var buffer; Len:word):longint; external;
{$L CRC32.OBJ }

function CRC32(s:string):longint;
begin
  CRC32 := not(UpdateCRC32($FFFFFFFF, s[1], length(s)));
end;


begin
  write('Give me a password:');
  readln(s)
  pw:=crc32(s);
  writeln;
  write('Type that password again:');
  readln(s)
  if pw <> crc32(s) then writeln('Sorry that was incorrect')
  else writeln('Yep that is correct');
end.
[-------------------------------------------------------------------------------------------]
0
Comment
Question by:RenegadeBBS
  • 6
  • 5
11 Comments
 
LVL 12

Expert Comment

by:Ivanov_G
ID: 12140605
Unfortunatelly CRC32.OBJ does not exists in Delphi, but you can use TIdHashCRC32 class, found in Indy components.
You can download the from http://www.indyproject.org/download/Files/Indy9.html
0
 
LVL 12

Expert Comment

by:Ivanov_G
ID: 12140637
uses IdHashCRC;

procedure TForm1.Button1Click(Sender: TObject);
var
  stream   : TFileStream;
  hash     : LongWord;
  crc      : TIdHashCRC32;
  str_list : TStringList;
begin
  // create the list with pass and save it
  str_list := TStringList.Create;
  str_list.Add('Your Pass');
  str_list.SaveToFile('C:\Test.dat');
  // create the stream
  stream := TFileStream.Create('C:\Test.dat', fmOpenRead or fmShareDenyWrite);
  // calculate the crc32 and free resources
  crc := TIdHashCRC32.Create;
  hash :=  crc.HashValue(stream);
  stream.Free;
  // FINALLY show the calculated CRC32
  ShowMessage(IntToStr(hash));
end;
0
 
LVL 1

Author Comment

by:RenegadeBBS
ID: 12140717


Here is what I tried so far and it returns that a [ is need and found x?????

Please if lead me in the right direction..

Thanks..
[------------------------------------------]
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  pbyte = ^byte;
  longrec = record
    lo,hi : word;
  end;



var
  Form1: TForm1;
  vHash : Longint;
 
implementation

{$R *.dfm}

const
  crc_32_tab : array[0..255] of longint = (
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
0x2d02ef8d);

procedure updatecrc32(s : pchar; len : integer);
(* update running CRC calculation with contents of a buffer *)

var
  crcl : longrec absolute crc32val;
  x : integer;

begin
  for x := 1 to len do begin
      crc32val := crc_32_tab[lo(crcl.lo) xor byte(s^)] xor ((crc32val shr 8) and 0x00FFFFFF);
      inc(s);
  end;
end;

function CRC32(s:string):longint;
begin
  CRC32 := not(UpdateCRC32(0xffffffff;, s[1], length(s)));
end;


procedure TForm1.FormCreate(Sender: TObject);
begin
 vHash := 0;
end;

procedure TForm1.Button1Click(Sender: TObject);
var zHash : Longint;
begin
 if vHash := 0 then begin
    vHash := Crc32(edit1.text);
    Edit1.Text := '';
    Label1.Caption := 'Now Retype that in!';
    exit;
 end;
 zHash := Crc32(edit1.text);
 if zHash <> vHash then begin
    Label1.Caption := 'You got that wrong it was not the same';
    Edit1.Text;
 end else begin
    Label1.Caption := 'You got it right. Here is the Hash Value';
    Edit1.Text := IntToStr(vHash);
 end;

end;

end.
0
 
LVL 1

Author Comment

by:RenegadeBBS
ID: 12140853

To:  Ivanov_G
  Your code is nice, but it doesn't return what the TP program stored as the Hash value for the password.
  Just in case your wondering.  It is the correct password that is stored in the record file.

Password  := TIGGER

What your program return'd.
198863344

What my program return'd.
138649891

What lower case return'd in the program you gave me.
1661202902

I think I'll take a look to see how indy did it with the idHash.

Also, is there a way not to store the password to a text file while checking?
Oh is it returning the crc value of the text file instead of the string? I have
never used the Stream and will have to look that up as well on how to
do it.  
I askd cause all that google returns is how to check the crc32 value of files and not strings.
I did try to research it, before postting :)
0
 
LVL 1

Author Comment

by:RenegadeBBS
ID: 12140871

oh yeah, just to clear up something that might of been comfusing.

  userrec = record
     password : longint;
  end;
  var enterdpass : string;
138649891 is stored as the hash value in the record and TIGGER is what the users enter into a prompt then the program does this.
Write('Enter your Password');
Readln(enterdpass); (*they type tigger *)
if password <> crc32(enterdpass) then do_the_rest_of_the_program
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 12

Expert Comment

by:Ivanov_G
ID: 12140884
yes, there are 2 possible reasons:
1) the CRC values is the hash of the file...
2) if it is the hash on file contents (i.e. the string), but some of the values in the hash table are different...

>> Also, is there a way not to store the password to a text file while checking?
Yes, probably. I will try to do it with memory stream and keep you posted.
0
 
LVL 12

Expert Comment

by:Ivanov_G
ID: 12140897
>> Write('Enter your Password');
>> Readln(enterdpass); (*they type tigger *)

if you are going to make a console program - it will be the same way. If your application is going to have visible form - put a TEdit component on the form and then takes the text with "Edit1.Text" - this is the string representing the value in the text box...
0
 
LVL 1

Author Comment

by:RenegadeBBS
ID: 12140904

Last thing for now.. An OBj is just a old time type of *.dll
I postted what the *.obj contain'd and could just as
easily use it as a unit instead in the TP program, but
the trouble is migratting that to a delphi world.

Hrm, change longint to longword.  Thinking out loud.
0
 
LVL 12

Expert Comment

by:Ivanov_G
ID: 12140939
HERE IT IS - returns 138649891
:))))

uses IdHashCRC;

procedure TForm1.Button1Click(Sender: TObject);
var
  stream   : TMemoryStream;
  hash     : LongWord;
  crc      : TIdHashCRC32;
  str      : String;
begin
  str := 'TIGGER';
  // create the stream
  stream := TMemoryStream.Create;
  stream.WriteBuffer(PChar(str)^, length(str));
  stream.Position := 0;
  // calculate the crc32 and free resources
  crc := TIdHashCRC32.Create;
  hash := crc.HashValue(stream);
  stream.Free;
  // FINALLY show the calculated CRC32
  ShowMessage(IntToStr(hash));
end;
0
 
LVL 12

Accepted Solution

by:
Ivanov_G earned 275 total points
ID: 12140985
here is the final source (put 2 Edit boxes on the borm and 1 button) :

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses IdHashCRC;

function HashPassword (pass : String) : LongWord;
var
  stream   : TMemoryStream;
  crc      : TIdHashCRC32;
begin
  // create the stream
  stream := TMemoryStream.Create;
  stream.WriteBuffer(PChar(pass)^, length(pass));
  stream.Position := 0;
  // calculate the crc32 and free resources
  crc := TIdHashCRC32.Create;
  Result := crc.HashValue(stream);
  stream.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Edit2.Text := IntToStr(HashPassword(Edit1.Text));
end;

end.
0
 
LVL 1

Author Comment

by:RenegadeBBS
ID: 12141185
stream.WriteBuffer(PChar(pass)^, length(pass));
^^^^^^^----->Thanks I would have never of thought of this in a million years.
w00t!

Thank-you.. now I can write that *.dll that will allow people to log into the bbs through a website via a php script (php4Delphi)..  Sweet!!
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

Suggested Solutions

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now