| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- unit IdHashIntf;
- interface
- {$i IdCompilerDefines.inc}
- uses
- Classes,
- IdFIPS,
- IdGlobal, IdHash,
- {$IFDEF DOTNET}
- System.Security.Cryptography,
- IdException
- {$ELSE}
- IdStreamVCL
- {$ENDIF}
- ;
- type
- TIdHashInt = class(TIdHash)
- protected
- function HashToHex(const AHash: TIdBytes): String; override;
- function GetHashInst : TIdHashInst; virtual; abstract;
- function InitHash : TIdHashIntCtx; virtual;
- procedure UpdateHash(ACtx : TIdHashIntCtx; const AIn : TIdBytes);
- function FinalHash(ACtx : TIdHashIntCtx) : TIdBytes;
- function GetHashBytes(AStream: TStream; ASize: TIdStreamSize): TIdBytes; override;
- {$IFNDEF DOTNET}
- public
- class function IsAvailable : Boolean; override;
- {$ENDIF}
- end;
- TIdHashSHA224 = class(TIdHashInt)
- protected
- function GetHashInst : TIdHashInst; override;
- {$IFNDEF DOTNET}
- public
- class function IsAvailable : Boolean; override;
- {$ENDIF}
- end;
- TIdHashSHA256 = class(TIdHashInt)
- protected
- function GetHashInst : TIdHashInst; override;
- {$IFNDEF DOTNET}
- public
- class function IsAvailable : Boolean; override;
- {$ENDIF}
- end;
- TIdHashSHA386 = class(TIdHashInt)
- protected
- function GetHashInst : TIdHashInst; override;
- {$IFNDEF DOTNET}
- public
- class function IsAvailable : Boolean; override;
- {$ENDIF}
- end;
- TIdHashSHA512 = class(TIdHashInt)
- protected
- function GetHashInst : TIdHashInst; override;
- {$IFNDEF DOTNET}
- public
- class function IsAvailable : Boolean; override;
- {$ENDIF}
- end;
- {$IFDEF DOTNET}
- EIdSecurityAPIException = class(EIdException);
- EIdSHA224NotSupported = class(EIdSecurityAPIException);
- {$ELSE}
- EIdDigestError = class(EIdOpenSSLAPICryptoError);
- EIdDigestFinalEx = class(EIdDigestError);
- EIdDigestInitEx = class(EIdDigestError);
- EIdDigestUpdate = class(EIdDigestError);
- {$ENDIF}
- implementation
- {$IFNDEF DOTNET}
- uses IdCTypes;
- {$ENDIF}
- { TIdHashInt }
- function TIdHashInt.FinalHash(ACtx: TIdHashIntCtx): TIdBytes;
- var
- {$IFDEF DOTNET}
- LDummy : TIdBytes;
- {$ELSE}
- LLen, LRet : TIdC_UInt;
- {$ENDIF}
- begin
- {$IFDEF DOTNET}
- //This is a funny way of coding. I have to pass a dummy value to
- //TransformFinalBlock so that things can work similarly to the OpenSSL
- //Crypto API. You can't pass nul to TransformFinalBlock without an exception.
- SetLength(LDummy,0);
- ACtx.TransformFinalBlock(LDummy,0,0);
- Result := ACtx.Hash;
- {$ELSE}
- SetLength(Result,OPENSSL_EVP_MAX_MD_SIZE);
- LRet := IdSslEvpDigestFinalEx(@ACtx,@Result[0],LLen);
- if LRet <> 1 then begin
- EIdDigestFinalEx.RaiseException('EVP_DigestFinal_ex error');
- end;
- SetLength(Result,LLen);
- IdSslEvpMDCtxCleanup(@ACtx);
- {$ENDIF}
- end;
- function TIdHashInt.GetHashBytes(AStream: TStream; ASize: TIdStreamSize): TIdBytes;
- var LBuf : TIdBytes;
- LSize : Int64;
- LCtx : TIdHashIntCtx;
- begin
- LCtx := InitHash;
- try
- SetLength(LBuf,2048);
- repeat
- LSize := ReadTIdBytesFromStream(AStream,LBuf,2048);
- if LSize = 0 then begin
- break;
- end;
- if LSize < 2048 then begin
- SetLength(LBuf,LSize);
- UpdateHash(LCtx,LBuf);
- break;
- end else begin
- UpdateHash(LCtx,LBuf);
- end;
- until False;
- finally
- Result := FinalHash(LCtx);
- end;
- end;
- function TIdHashInt.HashToHex(const AHash: TIdBytes): String;
- begin
- Result := ToHex(AHash);
- end;
- function TIdHashInt.InitHash: TIdHashIntCtx;
- {$IFNDEF DOTNET}
- var
- LHash : TIdHashInst;
- LRet : TIdC_Int;
- {$ENDIF}
- begin
- {$IFDEF DOTNET}
- Result := GetHashInst;
- {$ELSE}
- LHash := GetHashInst;
- IdSslEvpMDCtxInit(@Result);
- LRet := IdSslEvpDigestInitEx(@Result, LHash, nil);
- if LRet <> 1 then begin
- EIdDigestInitEx.RaiseException('EVP_DigestInit_ex error');
- end;
- {$ENDIF}
- end;
- {$IFNDEF DOTNET}
- class function TIdHashInt.IsAvailable: Boolean;
- begin
- Result := Assigned(IdSslEvpDigestInitEx) and
- Assigned(IdSslEvpDigestUpdate) and
- Assigned(IdSslEvpDigestFinalEx);
- end;
- {$ENDIF}
- procedure TIdHashInt.UpdateHash(ACtx: TIdHashIntCtx; const AIn: TIdBytes);
- {$IFNDEF DOTNET}
- var LRet : TIdC_Int;
- {$ENDIF}
- begin
- {$IFDEF DOTNET}
- ACtx.TransformBlock(AIn,0,Length(AIn),AIn,0);
- {$ELSE}
- LRet := IdSslEvpDigestUpdate(@ACtx,@Ain[0],Length(AIn));
- if LRet <> 1 then begin
- EIdDigestInitEx.RaiseException('EVP_DigestUpdate error');
- end;
- {$ENDIF}
- end;
- { TIdHashSHA224 }
- function TIdHashSHA224.GetHashInst: TIdHashInst;
- begin
- {$IFDEF DOTNET}
- Result := nil;
- Raise EIdSHA224NotSupported.Create('SHA224 not supported.');
- {$ELSE}
- Result := IdSslEvpSHA224;
- {$ENDIF}
- end;
- {$IFNDEF DOTNET}
- class function TIdHashSHA224.IsAvailable: Boolean;
- begin
- Result := Assigned(IdSslEvpSHA224) and inherited IsAvailable;
- end;
- {$ENDIF}
- { TIdHashSHA256 }
- function TIdHashSHA256.GetHashInst: TIdHashInst;
- begin
- {$IFDEF DOTNET}
- Result := System.Security.Cryptography.SHA256Managed.Create;
- {$ELSE}
- Result := IdSslEvpSHA256;
- {$ENDIF}
- end;
- {$IFNDEF DOTNET}
- class function TIdHashSHA256.IsAvailable: Boolean;
- begin
- Result := Assigned(IdSslEvpSHA256) and inherited IsAvailable;
- end;
- {$ENDIF}
- { TIdHashSHA386 }
- function TIdHashSHA386.GetHashInst: TIdHashInst;
- begin
- {$IFDEF DOTNET}
- Result := System.Security.Cryptography.SHA384Managed.Create;
- {$ELSE}
- Result := IdSslEvpSHA384;
- {$ENDIF}
- end;
- {$IFNDEF DOTNET}
- class function TIdHashSHA386.IsAvailable: Boolean;
- begin
- Result := Assigned(IdSslEvpSHA384) and inherited IsAvailable;
- end;
- {$ENDIF}
- { TIdHashSHA512 }
- function TIdHashSHA512.GetHashInst: TIdHashInst;
- begin
- {$IFDEF DOTNET}
- Result := System.Security.Cryptography.SHA512Managed.Create;
- {$ELSE}
- Result := IdSslEvpSHA512;
- {$ENDIF}
- end;
- {$IFNDEF DOTNET}
- class function TIdHashSHA512.IsAvailable: Boolean;
- begin
- Result := Assigned(IdSslEvpSHA512) and inherited IsAvailable;
- end;
- {$ENDIF}
- end.
|