keyfuncs.pas

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

PAS
1,570
字号
      end;
    finally
      PGPFreeKeyList(KeyList);
    end;
  finally
    PGPFreeKeySet(KeySet);
  end;
end;

function GetGroupsList(Context: pPGPContext; KeySetMain: pPGPKeySet; var GroupsList: TGroupsList): Integer;
var
  GroupFileSpec	: pPGPFileSpec;
  GroupSet	: pPGPGroupSet;
  GroupCount	: PGPUInt32;
  GroupIndex	: PGPUInt32;
  GroupID	: PGPGroupID;
  GroupInfo	: TPGPGroupInfo;
  KeyCount	: PGPUInt32;
  ItemCount	: PGPUInt32;
  GroupItemIter	: pPGPGroupItemIter;
  GroupItem	: TPGPGroupItem;
  HexIDList	: String;
  Key		: pPGPKey;
  HexID		: String;
begin
  Result:=kPGPError_OutOfMemory;
  if GroupsList<>nil then begin
    try
      GroupsList.Clear;
      GroupFileSpec:=nil;
      GroupSet:=nil;
      Result:=PGPNewFileSpecFromFullPath(Context, PChar(KeyRings.GroupsFile), GroupFileSpec);
      if Result<>0 then Exit;
      try
	Result:=PGPNewGroupSetFromFile(Context, GroupFileSpec, GroupSet);
	if Result<>0 then Exit;
	try
	  Result:=PGPCountGroupsInSet(GroupSet, GroupCount);
	  if (Result<>0) or (GroupCount=0) then Exit;
	  for GroupIndex:=0 to pred(GroupCount) do begin
	    Result:=PGPGetIndGroupID(GroupSet, GroupIndex, GroupID);
	    if Result<>0 then Continue;
	    Result:=PGPGetGroupInfo(GroupSet, GroupID, GroupInfo);
	    if Result<>0 then Continue;
	    Result:=PGPCountGroupItems(GroupSet, GroupID, PGPTrue, KeyCount, ItemCount);
	    if (Result<>0) or (KeyCount=0) then Continue;
	    with GroupInfo do begin
	      if Description<>'' then
		GroupsList.Add(Description + ' <' + Name + '>' + #9)
	      else GroupsList.Add('<' + Name + '>' + #9);
	    end;
	    GroupItemIter:=nil;
	    Result:=PGPNewGroupItemIter(GroupSet, GroupID, kPGPGroupIterFlags_AllKeysRecursive, GroupItemIter);
	    if Result<>0 then Continue;
	    try
	      HexIDList:='';
	      while PGPGroupItemIterNext(GroupItemIter, GroupItem)=0 do begin
		with GroupItem.Item.Key do begin
		  if PGP7X then
		    Result:=PGPGetKeyByKeyID(KeySetMain, KeyStruct7.KeyID, kPGPPublicKeyAlgorithm_Invalid, Key)
		  else Result:=PGPGetKeyByKeyID(KeySetMain, KeyStruct6.KeyID, kPGPPublicKeyAlgorithm_Invalid, Key);
		end;
		if Result<>0 then Continue;
		HexID:=GetKeyPropKeyID(Key);
		if HexID<>'' then HexIDList:=HexIDList + ',' + HexID;
	      end;
	      Delete(HexIDList, 1, 1);
	      if HexIDList<>'' then with GroupsList do Strings[GroupIndex]:=Strings[GroupIndex] + HexIDList;
	    finally
	      PGPFreeGroupItemIter(GroupItemIter);
	    end;
	  end;
	  Result:=GroupsList.Count;
	finally
	  if GroupSet<>nil then PGPFreeGroupSet(GroupSet);
	end;
      finally
	PGPFreeFileSpec(GroupFileSpec);
      end;
    except
      Result:=0;
    end;
    if (Result<=0) and (GroupsList<>nil) then GroupsList.Clear;
  end;
end;

function GetKeyPropsData(KeySet: pPGPKeySet; KeyFound: pPGPKey; Flags: DWord;
			 KeyPropsList: TKeyPropsList; KeyIndex: Integer): Integer;
var
  KeyPropsRec	: pKeyPropsRec;
begin
  Result:=-1;
  if KeyPropsList.Objects[KeyIndex]<>nil then begin
    KeyPropsRec:=pKeyPropsRec(KeyPropsList.Objects[KeyIndex]);
    with KeyPropsRec^ do begin
      try
	// "string" properties
	KeyPropsList.Strings[KeyIndex]:=GetKeyPropKeyID(KeyFound);
	if Flags and spgpKeyPropFlag_KeyID<>0 then begin
	  kHexID:='0x' + Copy(KeyPropsList[KeyIndex], Length(KeyPropsList.Strings[KeyIndex])-7, 8);
	end;
	if Flags and spgpKeyPropFlag_UserID<>0 then kUserID:=GetKeyPropUserID(KeyFound);
	if Flags and spgpKeyPropFlag_Fingerprint<>0 then kFingerprint:=GetKeyPropFingerprint(KeyFound);
	if Flags and spgpKeyPropFlag_CreationTimeStr<>0 then kCreaTimeStr:=GetKeyPropKeyCreationTimeStr(KeyFound);
	if Flags and spgpKeyPropFlag_ExpirationTimeStr<>0 then kExpTimeStr:=GetKeyPropKeyExpirationTimeStr(KeyFound);
	// "number" properties
	if Flags and spgpKeyPropFlag_Keybits<>0 then kSize:=GetKeyPropKeyBits(KeyFound);
	if Flags and spgpKeyPropFlag_KeyAlg<>0 then kAlgorithm:=GetKeyPropAlg(KeyFound);
	if Flags and spgpKeyPropFlag_Trust<>0 then kTrust:=GetKeyPropTrust(KeyFound);
	if Flags and spgpKeyPropFlag_Validity<>0 then kValidity:=GetKeyPropValidity(KeyFound);
	if Flags and spgpKeyPropFlag_CreationTime<>0 then kCreaTimeNum:=GetKeyPropKeyCreationTime(KeyFound);
	if Flags and spgpKeyPropFlag_ExpirationTime<>0 then kExpTimeNum:=GetKeyPropKeyExpirationTime(KeyFound);
	// "boolean" properties
	if Flags and spgpKeyPropFlag_IsSecret<>0 then kPrivate:=GetKeyPropIsSecret(KeyFound);
	if Flags and spgpKeyPropFlag_IsAxiomatic<>0 then kImplicitTrust:=GetKeyPropIsAxiomatic(KeyFound);
	if Flags and spgpKeyPropFlag_IsRevoked<>0 then kRevoked:=GetKeyPropIsRevoked(KeyFound);
	if Flags and spgpKeyPropFlag_IsDisabled<>0 then kDisabled:=GetKeyPropIsDisabled(KeyFound);
	if Flags and spgpKeyPropFlag_IsExpired<>0 then kExpired:=GetKeyPropIsExpired(KeyFound);
	if Flags and spgpKeyPropFlag_IsSecretShared<>0 then kSecShared:=GetKeyPropIsSecretShared(KeyFound);
	if Flags and spgpKeyPropFlag_CanEncrypt<>0 then kCanEncrypt:=GetKeyPropCanEncrypt(KeyFound);
	if Flags and spgpKeyPropFlag_CanDecrypt<>0 then kCanDecrypt:=GetKeyPropCanDecrypt(KeyFound);
	if Flags and spgpKeyPropFlag_CanSign<>0 then kCanSign:=GetKeyPropCanSign(KeyFound);
	if Flags and spgpKeyPropFlag_CanVerify<>0 then kCanVerify:=GetKeyPropCanVerify(KeyFound);
	if Flags and spgpKeyPropFlag_HasRevoker<>0 then kHasRevoker:=GetKeyPropHasRevoker(KeySet, KeyFound, KeyPropsRec);
	if Flags and spgpKeyPropFlag_HasADK<>0 then kHasADK:=GetKeyPropHasARR(KeySet, KeyFound, KeyPropsRec);
	if Flags and spgpKeyPropFlag_HasSubKey<>0 then kHasSubKey:=GetKeyPropHasSubKey(KeySet, KeyFound);
	if Flags and spgpKeyPropFlag_LegacyKey<>0 then kLegacyKey:=GetKeyPropLegacy(KeyFound);
	// "list" properties
	if Flags and spgpKeyPropFlag_IncludeUserIDs<>0 then begin
	  GetKeyPropUserIDs(KeyFound, KeyPropsRec, (Flags and spgpKeyPropFlag_IncludeSignerIDs<>0));
	end;
	Result:=0;
      except
      end;
    end;
  end;
end;

function GetKeySetProps(Context: pPGPContext; KeySet: pPGPKeySet;
			var KeyPropsList: TKeyPropsList;
			PropertyFlags, FilterFlags: DWord;
			KeyOrder: TPGPKeyOrdering): Integer;
var
  KeyFilter	: pPGPFilter;
  KeySetFound	: pPGPKeySet;
  KeyCount	: PGPUInt32;
  KeyList	: pPGPKeyList;
  KeyIter	: pPGPKeyIter;
  KeyFound	: pPGPKey;
  KeyIndex	: Longint;
begin
  KeyFilter:=nil;
  KeySetFound:=nil;
  KeyList:=nil;
  KeyIter:=nil;
  if FilterFlags<>KeyFilterFlag_AllKeys then begin
    Result:=GetKeyFilter(Context, FilterFlags, KeyFilter);
    try
      if Result<>0 then Exit;
      Result:=PGPFilterKeySet(KeySet, KeyFilter, KeySetFound);
      if Result<>0 then Exit;
      KeySet:=KeySetFound;
    finally
      PGPFreeFilter(KeyFilter);
    end;
  end
  else Result:=0;
  try
    if Result<>0 then Exit;
    Result:=PGPCountKeys(KeySet, KeyCount);
    if Result<>0 then Exit;
    if PropertyFlags<>0 then begin
      if KeyPropsList=nil then begin
	KeyPropsList:=TKeyPropsList.Create(KeyCount, PropertyFlags);
	KeyIndex:=0;
      end
      else KeyIndex:=KeyPropsList.Append(KeyCount);
      if (KeyPropsList=nil) or (KeyIndex<0) then begin
	Result:=kPGPError_OutOfMemory;
	Exit;
      end;
      if (KeyIndex=0) and ((PropertyFlags and spgpKeyPropFlag_IncludeGroupsList)<>0) then begin
	GetGroupsList(Context, KeySet, KeyPropsList.GroupsList);
      end;
      Result:=PGPOrderKeySet(KeySet, PGPKeyOrdering(succ(ord(KeyOrder) shr 1)), PGPBoolean(odd(ord(KeyOrder))), KeyList);
      if Result<>0 then Exit;
      try
	Result:=PGPNewKeyIter(KeyList, KeyIter);
	try
	  if Result<>0 then Exit;
	  while PGPKeyIterNextKeyDBObj(KeyIter, kPGPKeyDBObjType_Key, KeyFound)=0 do begin
	    Result:=GetKeyPropsData(KeySet, KeyFound, PropertyFlags, KeyPropsList, KeyIndex);
	    if Result=0 then
	      inc(KeyIndex)
	    else Exit;
	  end;
	  Result:=KeyPropsList.Count;
	finally
	  PGPFreeKeyIter(KeyIter);
	end;
      finally
	PGPFreeKeyList(KeyList);
      end;
    end
    else Result:=KeyCount;
  finally
    PGPFreeKeySet(KeySetFound);
  end;
end;

function AddKeysToKeyRing(Context: pPGPContext; KeySetMain: pPGPKeySet;
			  KeysToImport: Pointer; var KeyPropsList: TKeyPropsList;
			  PropertyFlags: DWord): Integer; 
var
  KeySetToAdd	: pPGPKeySet;
begin
  if PGP7X then begin
    KeySetToAdd:=nil;
    Result:=PGPCopyKeys(PGPPeekKeyDBRootKeySet(pPGPKeyDB(KeysToImport)), PGPPeekKeySetKeyDB(KeySetMain), KeySetToAdd);
    if Result<>0 then Exit;
    try
      Result:=KeyRings.UpdateKeyRings;
      if Result<>0 then Exit;
      Result:=GetKeySetProps(Context, KeySetToAdd, KeyPropsList,
			     PropertyFlags, KeyFilterFlag_AllKeys, UserID_Ordering);
    finally
      PGPFreeKeySet(KeySetToAdd);
    end;
  end
  else begin
    Result:=PGPAddKeys(pPGPKeySet(KeysToImport), KeySetMain);
    if Result<>0 then Exit;
    Result:=KeyRings.UpdateKeyRings;
    if Result<>0 then Exit;
    Result:=GetKeySetProps(Context, pPGPKeySet(KeysToImport), KeyPropsList,
			   PropertyFlags, KeyFilterFlag_AllKeys, UserID_Ordering);
  end;
end;

function GetHexIDByAnyID(Context: pPGPContext; KeySetMain: pPGPKeySet;
			 const AnyID: String; var HexID: String): Integer;
var
  KeySetFound	: pPGPKeySet;
  KeyCount	: PGPUInt32;
  Key		: pPGPKey;
begin
  HexID:='';
  Result:=0;
  KeySetFound:=nil;
  if AnyID<>'' then begin
    try
      Result:=GetKeySetByAnyIDs(Context, KeySetMain, AnyID, KeySetFound);
      if Result<>0 then Exit;
      Result:=PGPCountKeys(KeySetFound, KeyCount);
      if Result<>0 then Exit;
      if KeyCount>0 then begin
	Result:=GetKeyFromKeySet(KeySetFound, Key);
	if Result<>0 then Exit;
	HexID:=GetKeyPropKeyID(Key);
      end;
      Result:=KeyCount;
    finally
      PGPFreeKeySet(KeySetFound);
    end;
  end;
end;

function PassphraseIsValid(Context: pPGPContext; KeySetMain: pPGPKeySet; AnyID, Passphrase: PChar): Longbool;
var
  KeySetFound	: pPGPKeySet;
  KeyCount	: PGPUInt32;
  Key		: pPGPKey;
begin
  Result:=false;
  KeySetFound:=nil;
  if GetKeySetByAnyIDs(Context, KeySetMain, AnyID, KeySetFound)=0 then begin
    try
      Result:=(PGPCountKeys(KeySetFound, KeyCount)=0) and (KeyCount=1) and (GetKeyFromKeySet(KeySetFound, Key)=0) and
	      (PGPPassphraseIsValid(Key, PGPOPassphrase(Context, Passphrase), PGPOLastOption(Context))<>PGPFalse);
    finally
      PGPFreeKeySet(KeySetFound);
    end;
  end;
end;

function TKeyRings.UpdateKeyRings: PGPError;
begin
  Result:=kPGPError_NoErr;
  if PGP7X then
    Result:=PGPFlushKeyDB(RingKeyDB)
  else if boolean(PGPKeySetNeedsCommit(RingKeySet)) then Result:=PGPCommitKeyringChanges(RingKeySet);
  if Result=0 then PGPclNotifyKeyringChanges(GetCurrentProcessID);
end;

function TKeyRings.SetKeyRings(const Pubring, Secring: String): Longbool;
begin
  PubringFile:=Pubring;
  SecringFile:=Secring;
  Result:=((PubringFile<>'') and (SecringFile<>''));
end;

function TKeyRings.InitKeyRings(var Context: pPGPContext; var KeySetMain: pPGPKeySet): PGPError;
var
  Prefs: TPreferenceRec;
  PubFileSpec: pPGPFileSpec;
  SecFileSpec: pPGPFileSpec;
begin
  Result:=kPGPError_ImproperInitialization;
  if PGPInitErrorCode=ieNone then begin
    if InitCount<=0 then begin
      InitCount:=0;
      RingKeyDB:=nil;
      RingKeySet:=nil;
      RingContext:=nil;
      PubFileSpec:=nil;
      SecFileSpec:=nil;
      Result:=PGPNewContext(kPGPsdkAPIVersion, RingContext);
      if Result<>0 then Exit;
      if (PubRingFile='') or (SecringFile='') then begin
	GetPreferences(Prefs, PrefsFlag_PublicKeyring or PrefsFlag_PrivateKeyring or PrefsFlag_GroupsFile);
	SetKeyRings(Prefs.PublicKeyring, Prefs.PrivateKeyring);
	if GroupsFile='' then GroupsFile:=Prefs.GroupsFile;
      end
      else if (GroupsFile='') and (GetPreferences(Prefs, PrefsFlag_GroupsFile)=0) then GroupsFile:=Prefs.GroupsFile;
      try
	Result:=PGPNewFileSpecFromFullPath(RingContext, PChar(PubringFile), PubFileSpec);
	if Result<>0 then Exit;
	Result:=PGPNewFileSpecFromFullPath(RingContext, PChar(SecringFile), SecFileSpec);
	if Result<>0 then Exit;
	if PGP7X then begin
	  Result:=PGPOpenKeyDBFile(RingContext, kPGPOpenKeyDBFileOptions_Mutable, PubFileSpec, SecFileSpec, RingKeyDB);
	  if Result=0 then RingKeySet:=PGPPeekKeyDBRootKeySet(RingKeyDB);
	end
	else Result:=PGPOpenKeyRingPair(RingContext, kPGPKeyRingOpenFlags_Mutable, PubFileSpec, SecFileSpec, RingKeySet);
      finally
	PGPFreeFileSpec(PubFileSpec);
	PGPFreeFileSpec(SecFileSpec);
      end;
      if Result<>0 then begin
	PGPFreeContext(RingContext);
	RingContext:=nil;
	if PGP7X then begin
	  PGPFreeKeyDB(RingKeyDB);
	  RingKeyDB:=nil;
	end
	else begin
	  PGPFreeKeySet(RingKeySet);
	  RingKeySet:=nil;
	end;
      end;
    end
    else Result:=0;
    if Result=0 then inc(InitCount);
    KeySetMain:=RingKeySet;
    Context:=RingContext;
  end;
end;

procedure TKeyRings.FreeKeyRings;
begin
  try
    if InitCount=1 then begin
      try
	if PGP7X then
	  PGPFreeKeyDB(RingKeyDB)
	else PGPFreeKeySet(RingKeySet);
      finally
	RingKeySet:=nil;
	RingKeyDB:=nil;
	try
	  PGPFreeContext(RingContext);
	finally
	  RingContext:=nil;
	end;
      end;
    end;
  finally
    if InitCount>0 then dec(InitCount);
  end;
end;

initialization
  KeyRings:=TKeyRings.Create;

finalization
  KeyRings.Free;
  KeyRings:=nil;

end.

⌨️ 快捷键说明

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