pgpdecode.pas

来自「用DELPHI实现的 PGP 加密算法」· PAS 代码 · 共 1,048 行 · 第 1/3 页

PAS
1,048
字号
      end;
    finally
      FinitDecode;
    end;
  end;
  // OutputHandler errors don't get returned correctly by PGP
  if (Result=kPGPError_BadParams) and (FOutputError<>0) then Result:=FOutputError;
end;

function TPGPDecodeCustom.AnalyseBuffer(const DataBuffer: String): Longint;
begin
  FPassOption:=AnalyseOnly;
  Result:=Decode(DataBuffer, false);
end;

function TPGPDecodeCustom.AnalyseFile(const FileName: String): Longint;
begin
  FPassOption:=AnalyseOnly;
  Result:=Decode(FileName, true);
end;

function TPGPDecodeCustom.DecodeBuffer(const DataBuffer: String): Longint;
begin
  FPassOption:=AnalysePass;
  Result:=Decode(DataBuffer, false);
end;

function TPGPDecodeCustom.DecodeFile(const FileName: String): Longint;
begin
  FPassOption:=AnalysePass;
  Result:=Decode(FileName, true);
end;

function TPGPDecodeCustom.AnalyzeHandler(Event: pPGPEvent): PGPError;
var
  SkipSection	: Longbool;
begin
  Result:=0;
  SkipSection:=false;
  with Event^.EData.AnalyzeData do begin
    case FPassOption of
      AnalyseOnly: begin
	if Assigned(FOnGetAnalysis) then FOnGetAnalysis(FSectionNumber, TAnalysis(SectionType), SkipSection);
	if SectionType<>kPGPAnalyze_Key then Result:=kPGPError_SkipSection; // avoid key data bug
      end;
      AnalysePass: begin
	FRecognized:=(SectionType<>kPGPAnalyze_Unknown);
	case SectionType of
	  kPGPAnalyze_Signed: FClearSigned:=true;
	  kPGPAnalyze_DetachedSignature: FDetachedSigVerify:=true;
	end;
	if FDetachedSigVerify or FClearSigned then
	  Result:=kPGPError_UserAbort
	else if SectionType<>kPGPAnalyze_Key then Result:=kPGPError_SkipSection; // avoid key data bug
      end;
      DecodePass: begin
	if Assigned(FOnGetAnalysis) then FOnGetAnalysis(FSectionNumber, TAnalysis(SectionType), SkipSection);
	Result:=(ord(SkipSection) and 1)*kPGPError_SkipSection;
      end;
    end;
  end;
end;

function TPGPDecodeCustom.RecipientsHandler(Event: pPGPEvent): PGPError;
var
  KeyIDArraySize: PGPSize;
begin
  Result:=0;
  with Event^.EData.RecipientsData do begin
    PGPIncKeySetRefCount(RecipientSet);
    FRecipientsData.RecipientSet:=RecipientSet;
    FRecipientsData.KeyCount:=KeyCount;
    if PGP7X then
      KeyIDArraySize:=SizeOf(TPGPKeyID7)*KeyCount
    else KeyIDArraySize:=SizeOf(TPGPKeyID6)*KeyCount;
    GetMem(FRecipientsData.KeyIDArray, KeyIDArraySize);
    if FRecipientsData.KeyIDArray<>nil then Move(KeyIDArray^, FRecipientsData.KeyIDArray^, KeyIDArraySize)
  end;
end;

function TPGPDecodeCustom.PassphraseHandler(Event: pPGPEvent): PGPError;
var
  Cancel	: Longbool;
  KeyPropsList	: TKeyPropsList;
  BadPassphrase	: Longbool;
  DecryptionKey	: pPGPKey;
begin
  Result:=0;
  Cancel:=false;
  FPassphraseBufSize:=MaxUTF8Length;
  with Event^.EData.PassphraseData do begin
    KeyPropsList:=TKeyPropsList.Create(0, spgpKeyPropFlag_IDComplete);
    try
      if (FPassphrase=nil) or (FSectionNumber=FPassSection) then begin
	FPassSection:=FSectionNumber;
	BadPassphrase:=false;
	if FPassphrase<>nil then begin
	  PGPFreeData(FPassphrase);
	  FPassphrase:=nil;
	  BadPassphrase:=true;
	end;
	if Assigned(FOnEnterPassphrase) then begin
	  if not boolean(IsConventional) then begin
	    Result:=GetKeySetProps(FContext, KeySet, KeyPropsList, spgpKeyPropFlag_IDComplete,
				   KeyFilterFlag_CanDecrypt, UserID_Ordering);
	    if Result=0 then Result:=kPGPError_SecretKeyNotFound;
	  end;
	  if Result>=0 then begin
	    Result:=kPGPError_UserAbort;
	    FPassphrase:=PGPNewSecureData(PGPGetDefaultMemoryMgr, FPassphraseBufSize, kPGPMemoryMgrFlags_Clear);
	    if FPassphrase<>nil then begin
	      FOnEnterPassphrase(FPassphrase, KeyPropsList, boolean(IsConventional), BadPassphrase, Cancel);
	      if not Cancel then begin
		if PGP8X then AnsiToUtf8PChar(FPassphrase, FPassphrase, FPassphraseBufSize);
	      end
	      else Exit;
	    end
	    else begin
	      Result:=kPGPError_OutOfMemory;
	      Exit;
	    end;
	  end
	  else Exit;
	end
	else begin
	  if boolean(IsConventional) then
	    Result:=ConvDecPassphraseDialog(FContext, FPassphrase, FPassDlgPrompt, FParentHandle)
	  else with FRecipientsData do begin
	    Result:=DecryptionPassphraseDialog(FContext, RecipientSet, KeyCount, KeyIDArray,
					       DecryptionKey, FPassphrase, true, FPassDlgPrompt, FParentHandle);
	  end;
	  if Result<>0 then Exit;
	end;
      end
      else FPassSection:=FSectionNumber;
    finally
      KeyPropsList.Free;
    end;
  end;
  Result:=PGPAddJobOptions(Event^.Job, PGPOPassphrase(FContext, FPassphrase), PGPOLastOption(FContext));
end;

function TPGPDecodeCustom.KeyFoundHandler(Event: pPGPEvent): PGPError;
var
  KeySetSelected: pPGPKeySet;
begin
  Result:=0; // don't cancel decoding whatever happens here
  with Event^.EData.KeyFoundData do begin
    if PGP7X then begin
      try
	if FQueryAddKeys then begin
	  KeySetSelected:=PGPPeekKeyDBRootKeySet(KeysFound);
	  Result:=GetExclusiveKeySet(KeySetSelected, FKeySetMain, FContext, FIgnoreKnownFlag);
	  if Result<>0 then Exit;
	  if FKeyDlgPrompt<>'' then begin
	    SelectAddKeysToKeyRing(FContext, FtlsContext, PGPPeekKeyDBRootKeySet(KeysFound), FKeySetMain,
				   FKeyPropsList, PChar(FKeyDlgPrompt),
				   false, spgpKeyPropFlag_IDFlags,
				   FParentHandle);
	  end
	  else AddKeysToKeyRing(FContext, FKeySetMain, KeysFound, FKeyPropsList, spgpKeyPropFlag_IDFlags);
	end;
      finally
	PGPFreeKeyDB(PGPPeekKeySetKeyDB(KeysFound));
      end;
    end
    else begin
      try
	if FQueryAddKeys then begin
	  Result:=GetExclusiveKeySet(KeysFound, FKeySetMain, FContext, FIgnoreKnownFlag);
	  if Result<>0 then Exit;
	  if FKeyDlgPrompt<>'' then begin
	    SelectAddKeysToKeyRing(FContext, FtlsContext, KeysFound, FKeySetMain,
				   FKeyPropsList, PChar(FKeyDlgPrompt),
				   false, spgpKeyPropFlag_IDFlags,
				   FParentHandle);
	  end
	  else AddKeysToKeyRing(FContext, FKeySetMain, KeysFound, FKeyPropsList, spgpKeyPropFlag_IDFlags);
	end;
      finally
	PGPFreeKeySet(KeysFound);
      end;
    end;
  end;
end;

// causes trouble when used with FPassThroughClearSigned on clear signed input
function TPGPDecodeCustom.OutputHandler(Event: pPGPEvent): PGPError;
begin
  Result:=0;
  with Event^.EData.OutputData do begin
    if boolean(ForYourEyesOnly) then FEyesOnly:=true;
    if FOutputExists then
      Result:=SecureMove
    else if FFileOutput and not FEyesOnly then begin
      if FOutputFileName='' then begin
	if SuggestedName<>'' then
	  FOutputFileName:=ExtractFilePath(FInputFileName) + SuggestedName
	else FOutputFileName:=FInputFileName;
      end;
      if GetOutputFile='' then Result:=kPGPError_CantOpenFile;
    end;
    if Result=0 then begin
      Result:=PGPAddJobOptions(Event^.Job,
			       PGPOAllocatedOutputBuffer(FContext, FAllocatedOutputBuffer,
			       				 $FFFFFFFF, FActualOutputSize),
			       PGPOLastOption(FContext));
      FOutputExists:=true;
    end
    else FOutputError:=Result;
  end;
end;

function TPGPDecodeCustom.SignatureHandler(Event: pPGPEvent): PGPError;
var
  IsSigningKey	: PGPBoolean;
  PGPSignKeyID	: TPGPKeyID7;
  SignKeyID	: TKeyID;
  KeysFound	: Pointer;
begin
  Result:=0; // don't cancel decoding whatever happens here
  IsSigningKey:=PGPFalse;
  FillChar(FSigPropsRec, SizeOf(TSigPropsRec), 0);
  if PGP7X then with Event^.EData.SignatureData.PGPEventSignatureData7, FSigPropsRec do begin
    if boolean(Checked)
    and (PGPGetKeyDBObjBooleanProperty(SigningKey, kPGPKeyProperty_IsSigningKey, IsSigningKey)=0) then begin
      sHexID:=GetKeyPropKeyID(SigningKey);
      sUserID:=GetKeyPropUserID(SigningKey);
      sCreaTimeNum:=PGPGetStdTimeFromPGPTime(CreationTime);
      sCreaTimeStr:=UnixTimeToLocalTimeStr(sCreaTimeNum);
      sChecked:=boolean(Checked);
      sVerified:=boolean(Verified);
      sValidity:=TValidityLevel(KeyValidity);
      sRevoked:=boolean(KeyRevoked);
      sDisabled:=boolean(KeyDisabled);
      sExpired:=boolean(KeyExpired);
      sAxiomatic:=GetKeyPropIsAxiomatic(SigningKey);
      if PGP8X and (ExpirationPeriod<>0) then begin
	sExpTimeNum:=sCreaTimeNum + ExpirationPeriod;
	sExpTimeStr:=UnixTimeToLocalTimeStr(sExpTimeNum);
      end;
      if boolean(IsSigningKey) then begin
	sStatus:=TSigStatus(Checked + Verified);
	if PGP8X and (sStatus=SIGNED_GOOD) and (ExpirationPeriod<>0) and (sExpTimeNum<SystemTimeToUnixTimeNum) then begin
	  sStatus:=SIGNED_SIG_EXPIRED;
	end;
      end
      else sStatus:=SIGNED_UNKNOWN_ALG;
    end
    else begin
      Move(SigningKeyID, PGPSignKeyID, SizeOf(TPGPKeyID7));
      Result:=PGPGetKeyIDString(PGPSignKeyID, kPGPKeyIDString_Full, SignKeyID);
      if Result=0 then begin
	sCreaTimeNum:=PGPGetStdTimeFromPGPTime(CreationTime);
	sCreaTimeStr:=UnixTimeToLocalTimeStr(sCreaTimeNum);
	sHexID:=SignKeyID;
      end;
      sStatus:=SIGNED_NO_KEY;
      if (Result=0) and FGetKeyFromServer then begin
	KeysFound:=nil;
	Result:=KeyServerDialog(FContext, FtlsContext, FKeySetMain, SignKeyID, pPGPKeyDB(KeysFound), FParentHandle);
	if (Result=0) and (KeysFound<>nil) then begin
	  try
	    if FKeyDlgPrompt<>'' then begin
	      SelectAddKeysToKeyRing(FContext, FtlsContext, PGPPeekKeyDBRootKeySet(pPGPKeyDB(KeysFound)), FKeySetMain,
				     FKeyPropsList, PChar(FKeyDlgPrompt),
				     false, spgpKeyPropFlag_IDFlags,
				     FParentHandle);
	    end;
	    PGPAddJobOptions(Event^.Job,
			     PGPOKeySetRef(FContext, PGPPeekKeyDBRootKeySet(pPGPKeyDB(KeysFound))),
			     PGPOLastOption(FContext));
	  finally
	    PGPFreeKeyDB(pPGPKeyDB(KeysFound));
	  end;
	end;
      end;
      Result:=0;
    end;
    sDetached:=FDetachedSigVerify;
  end
  else with Event^.EData.SignatureData.PGPEventSignatureData6, FSigPropsRec do begin
    if boolean(Checked)
    and (PGPGetKeyDBObjBooleanProperty(SigningKey, kPGPKeyProperty_IsSigningKey, IsSigningKey)=0) then begin
      sHexID:=GetKeyPropKeyID(SigningKey);
      sUserID:=GetKeyPropUserID(SigningKey);
      sCreaTimeNum:=PGPGetStdTimeFromPGPTime(CreationTime);
      sCreaTimeStr:=UnixTimeToLocalTimeStr(sCreaTimeNum);
      sChecked:=boolean(Checked);
      sVerified:=boolean(Verified);
      sValidity:=TValidityLevel(KeyValidity);
      sRevoked:=boolean(KeyRevoked);
      sDisabled:=boolean(KeyDisabled);
      sExpired:=boolean(KeyExpired);
      sAxiomatic:=GetKeyPropIsAxiomatic(SigningKey);
      if boolean(IsSigningKey) then
	sStatus:=TSigStatus(Checked + Verified)
      else sStatus:=SIGNED_UNKNOWN_ALG;
    end
    else begin
      Move(SigningKeyID, PGPSignKeyID, SizeOf(TPGPKeyID6));
      Result:=PGPGetKeyIDString(PGPSignKeyID, kPGPKeyIDString_Full, SignKeyID);
      if Result=0 then begin
	sCreaTimeNum:=PGPGetStdTimeFromPGPTime(CreationTime);
	sCreaTimeStr:=UnixTimeToLocalTimeStr(sCreaTimeNum);
	sHexID:=SignKeyID;
      end;
      sStatus:=SIGNED_NO_KEY;
      if (Result=0) and FGetKeyFromServer then begin
	KeysFound:=nil;
	Result:=KeyServerDialog(FContext, FtlsContext, FKeySetMain, SignKeyID, pPGPKeySet(KeysFound), FParentHandle);
	if (Result=0) and (KeysFound<>nil) then begin
	  try
	    if FKeyDlgPrompt<>'' then begin
	      SelectAddKeysToKeyRing(FContext, FtlsContext, pPGPKeySet(KeysFound), FKeySetMain,
				     FKeyPropsList, PChar(FKeyDlgPrompt),
				     false, spgpKeyPropFlag_IDFlags,
				     FParentHandle);
	    end;
	    PGPAddJobOptions(Event^.Job,
			     PGPOKeySetRef(FContext, pPGPKeySet(KeysFound)),
			     PGPOLastOption(FContext));
	  finally
	    PGPFreeKeySet(pPGPKeySet(KeysFound));
	  end;
	end;
      end;
      Result:=0;
    end;
    sDetached:=FDetachedSigVerify;
  end;
  if FShowSigLog then ShowSigInfo;
  if Assigned(FOnGetSignature) then FOnGetSignature(SigPropsRec);
end;

function TPGPDecodeCustom.EndLexHandler(Event: pPGPEvent): PGPError;
begin
  Result:=0;
  with FRecipientsData do begin
    if KeyIDArray<>nil then FreeMem(KeyIDArray);
    PGPFreeKeySet(RecipientSet);
  end;
  FillChar(FRecipientsData, SizeOf(TPGPEventRecipientsData), 0);
end;

end.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?