| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- {
- $Project$
- $Workfile$
- $Revision$
- $DateUTC$
- $Id$
- This file is part of the Indy (Internet Direct) project, and is offered
- under the dual-licensing agreement described on the Indy website.
- (http://www.indyproject.org/)
- Copyright:
- (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
- }
- {
- $Log$
- }
- {
- HMAC specification on the NIST website
- http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf
- }
- unit IdHMAC;
- interface
- {$i IdCompilerDefines.inc}
- uses
- Classes,
- IdFIPS,
- IdGlobal, IdHash;
- type
- TIdHMACKeyBuilder = class(TObject)
- public
- class function Key(const ASize: Integer) : TIdBytes;
- class function IV(const ASize: Integer) : TIdBytes;
- end;
- TIdHMAC = class
- protected
- FHashSize: Integer; // n bytes
- FBlockSize: Integer; // n bytes
- FKey: TIdBytes;
- FHash: TIdHash;
- FHashName: string;
- procedure InitHash; virtual; abstract;
- procedure InitKey;
- procedure SetHashVars; virtual; abstract;
- function HashValueNative(const ABuffer: TIdBytes; const ATruncateTo: Integer = -1) : TIdBytes; // for now, supply in bytes
- function HashValueIntF(const ABuffer: TIdBytes; const ATruncateTo: Integer = -1) : TIdBytes; // for now, supply in bytes
- function IsIntFAvail : Boolean; virtual;
- function InitIntFInst(const AKey : TIdBytes) : TIdHMACIntCtx; virtual; abstract;
- public
- constructor Create; virtual;
- destructor Destroy; override;
- function HashValue(const ABuffer: TIdBytes; const ATruncateTo: Integer = -1) : TIdBytes; // for now, supply in bytes
- property HashSize: Integer read FHashSize;
- property BlockSize: Integer read FBlockSize;
- property HashName: string read FHashName;
- property Key: TIdBytes read FKey write FKey;
- end;
- implementation
- uses
- SysUtils;
- { TIdHMACKeyBuilder }
- class function TIdHMACKeyBuilder.Key(const ASize: Integer): TIdBytes;
- var
- I: Integer;
- begin
- SetLength(Result, ASize);
- for I := Low(Result) to High(Result) do begin
- Result[I] := Byte(Random(255));
- end;
- end;
- class function TIdHMACKeyBuilder.IV(const ASize: Integer): TIdBytes;
- var
- I: Integer;
- begin
- SetLength(Result, ASize);
- for I := Low(Result) to High(Result) do begin
- Result[I] := Byte(Random(255));
- end;
- end;
- { TIdHMAC }
- constructor TIdHMAC.Create;
- begin
- inherited Create;
- SetLength(FKey, 0);
- SetHashVars;
- LoadHashLibrary;
- if IsIntFAvail then begin
- FHash := nil;
- end else begin
- InitHash;
- end;
- end;
- destructor TIdHMAC.Destroy;
- begin
- FreeAndNil(FHash);
- inherited Destroy;
- end;
- function TIdHMAC.HashValueNative(const ABuffer: TIdBytes; const ATruncateTo: Integer = -1) : TIdBytes; // for now, supply in bytes
- const
- CInnerPad : Byte = $36;
- COuterPad : Byte = $5C;
- var
- TempBuffer1: TIdBytes;
- TempBuffer2: TIdBytes;
- LKey: TIdBytes;
- I: Integer;
- begin
- InitKey;
- LKey := Copy(FKey, 0, MaxInt);
- SetLength(LKey, FBlockSize);
- SetLength(TempBuffer1, FBlockSize + Length(ABuffer));
- for I := Low(LKey) to High(LKey) do begin
- TempBuffer1[I] := LKey[I] xor CInnerPad;
- end;
- CopyTIdBytes(ABuffer, 0, TempBuffer1, Length(LKey), Length(ABuffer));
- TempBuffer2 := FHash.HashBytes(TempBuffer1);
- SetLength(TempBuffer1, 0);
- SetLength(TempBuffer1, FBlockSize + FHashSize);
- for I := Low(LKey) to High(LKey) do begin
- TempBuffer1[I] := LKey[I] xor COuterPad;
- end;
- CopyTIdBytes(TempBuffer2, 0, TempBuffer1, Length(LKey), Length(TempBuffer2));
- Result := FHash.HashBytes(TempBuffer1);
- SetLength(TempBuffer1, 0);
- SetLength(TempBuffer2, 0);
- SetLength(LKey, 0);
- if ATruncateTo > -1 then begin
- SetLength(Result, ATruncateTo);
- end;
- end;
- function TIdHMAC.HashValueIntF(const ABuffer: TIdBytes; const ATruncateTo: Integer = -1) : TIdBytes; // for now, supply in bytes
- var
- LCtx : TIdHMACIntCtx;
- begin
- if FKey = nil then begin
- FKey := TIdHMACKeyBuilder.Key(FHashSize);
- end;
- LCtx := InitIntFInst(FKey);
- try
- UpdateHMACInst(LCtx,ABuffer);
- finally
- Result := FinalHMACInst(LCtx);
- end;
- if (ATruncateTo >-1) and (ATruncateTo < Length(Result)) then begin
- SetLength(Result, ATruncateTo);
- end;
- end;
- function TIdHMAC.HashValue(const ABuffer: TIdBytes; const ATruncateTo: Integer = -1): TIdBytes; // for now, supply in bytes
- begin
- if IsIntFAvail then begin
- Result := HashValueIntF(ABuffer,ATruncateTo);
- end else begin
- Result := HashValueNative(ABuffer,ATruncateTo);
- end;
- end;
- procedure TIdHMAC.InitKey;
- begin
- if FKey = nil then begin
- FKey := TIdHMACKeyBuilder.Key(FHashSize);
- end
- else if Length(FKey) > FBlockSize then begin
- FKey := FHash.HashBytes(FKey);
- end;
- end;
- function TIdHMAC.IsIntFAvail: Boolean;
- begin
- Result := IsHMACAvail;
- end;
- initialization
- Randomize;
- end.
|