keyfuncs.pas

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

PAS
1,570
字号
{$J+,Z4}
unit KeyFuncs;

{------------------------------------------------------------------------------}
{                                                                              }
{     This unit is partly based on Steve Heller's spgpKeyUtil.pas from his     }
{         SPGP sources available from http://www.oz.net/~srheller/spgp/        }
{                                                                              }
{                Portions created by Michael in der Wiesche are                }
{              Copyright (C) 2001-2003 by Michael in der Wiesche               }
{                                                                              }
{------------------------------------------------------------------------------}

interface

uses
  Windows,
  Classes,
  SysUtils,
  TimeUtils,
  KeyPropTypes,
  UTF8,
  pgpBase,
  pgpErrors,
  pgpPubTypes,
  pgpUtilities,
  pgpOptionList,
  pgpGroups,
  pgpKeys,
  pgpCl;

type
  TKeyRings = Class
  private
    InitCount: Longint;
    RingKeyDB: pPGPKeyDB;
    RingKeySet: pPGPKeySet;
    RingContext: pPGPContext;
  public
    PubringFile: String;
    SecringFile: String;
    GroupsFile: String;
    function UpdateKeyRings: PGPError;
    function SetKeyRings(const Pubring, Secring: String): Longbool;
    function InitKeyRings(var Context: pPGPContext; var KeySetMain: pPGPKeySet): PGPError;
    procedure FreeKeyRings;
  end;

{ "public" functions }
function IsHexID(const ToCheck: String): Longbool;
function KeyRemove(KeyIDCommaText: PChar): Integer;
function KeyEnable(HexKeyID: PChar): Integer;
function KeyDisable(HexKeyID: PChar): Integer;
function KeyRevoke(HexKeyID, Passphrase: PChar): Integer;
function ChangePassphrase(HexKeyID, OldPassphrase, NewPassphrase: PChar): Integer;
// properties, key & user IDs for all keys matching the specified KeyIDCommaText
// if KeyIDCommaText='' then all keys will be checked
// - returns number of keys found or error
function FindKeyProps(const KeyIDCommaText: String;
		      var KeyPropsList: TKeyPropsList;
		      PropertyFlags, FilterFlags: DWord;
		      KeyOrder: TPGPKeyOrdering): Integer;
{ "private" functions }
function SystemTimeToUnixTimeNum: Integer;
function UnixTimeToLocalTimeStr(UnixSeconds: Integer): String;
function GetSubKeyPropKeyID(SubKey: pPGPKey): String;
function GetKeyPropKeyID(Key: pPGPKey): String;
function GetKeyPropUserID(Key: pPGPKey): String;
function GetKeyPropAlg(Key: pPGPKey): TKeyAlgorithm;
function GetKeyPropLegacy(Key: pPGPKey): Longbool;
function GetKeyPropIsAxiomatic(Key: pPGPKey): Longbool;
function GetKeyFromKeySet(KeySet: pPGPKeySet; var Key: pPGPKey): PGPError;
function GetKeyByHexID(KeySet: pPGPKeySet; const HexID: String; var Key: pPGPKey): PGPError;
function GetKeyFilter(Context: pPGPContext; FilterFlags: DWord; var KeyFilter: pPGPFilter): PGPError;
function GetKeyFilterByAnyID(Context: pPGPContext; const AnyID: String;
			     IncludeSubKeys: Longbool; var KeyFilter: pPGPFilter): PGPError;
function GetKeySetByAnyIDs(Context: pPGPContext;
			   KeySetMain: pPGPKeySet;
			   const KeyIDCommaText: String;
			   var KeySetFound: pPGPKeySet): PGPError;
function GetExclusiveKeySet(var KeySetToCheck: pPGPKeySet; KeySetMain: pPGPKeySet;
			    Context: pPGPContext; IgnoreKnownFlag: Integer): PGPError;
function GetKeySetProps(Context: pPGPContext; KeySet: pPGPKeySet;
			var KeyPropsList: TKeyPropsList;
			PropertyFlags, FilterFlags: DWord;
			KeyOrder: TPGPKeyOrdering): Integer; // - returns number of keys found or error
function AddKeysToKeyRing(Context: pPGPContext; KeySetMain: pPGPKeySet;
			  KeysToImport: Pointer; var KeyPropsList: TKeyPropsList;
			  PropertyFlags: DWord): Integer; // - returns number of keys added or error
function GetHexIDByAnyID(Context: pPGPContext; KeySetMain: pPGPKeySet;
			 const AnyID: String; var HexID: String): Integer; // - returns number of keys found or error
function PassphraseIsValid(Context: pPGPContext; KeySetMain: pPGPKeySet; AnyID, Passphrase: PChar): Longbool;

const KeyRings: TKeyRings = nil;

implementation

uses PrefFuncs;

function IsHexID(const ToCheck: String): Longbool; assembler;
asm	// EAX=@ToCheck
  OR	EAX,EAX
  JE	@FALSE
  MOV	ECX,[EAX-04h]
  CMP	ECX,LongHexIDLen
  JE	@START
  CMP	ECX,ShortHexIDLen
  JNE	@FALSE
  @START:
  MOV	DX,[EAX]
  AND	DX,0DFFFh
  CMP	DX,'X0'
  JNE	@FALSE
  SUB	ECX,2
  ADD	EAX,2
  @LOOP:
  DEC	ECX
  JS	@TRUE
  MOV	DL,[EAX+ECX]
  CMP	DL,'0'
  JB	@FALSE
  CMP	DL,'9'
  JBE	@LOOP
  AND	DL,0DFh
  CMP	DL,'A'
  JB	@FALSE
  CMP	DL,'F'
  JBE	@LOOP
  @FALSE:
  XOR	EAX,EAX
  RET
  @TRUE:
  MOV	EAX,1
end;

function KeyRemove(KeyIDCommaText: PChar): Integer;
var
  Context	: pPGPContext;
  KeySetMain	: pPGPKeySet;
  KeySetFound	: pPGPKeySet;
  KeyCount	: PGPUInt32;
begin
  KeySetFound:=nil;
  Result:=KeyRings.InitKeyRings(Context, KeySetMain);
  if Result<>0 then Exit;
  try
    Result:=GetKeySetByAnyIDs(Context, KeySetMain, KeyIDCommaText, KeySetFound);
    if Result<>0 then Exit;
    try
      Result:=PGPCountKeys(KeySetFound, KeyCount);
      if Result<>0 then Exit;
      if KeyCount<>0 then begin
	Result:=PGPRemoveKeys(KeySetFound, KeySetMain);
	if Result<>0 then Exit;
      end;
    finally
      PGPFreeKeySet(KeySetFound);
    end;
    Result:=KeyRings.UpdateKeyRings;
  finally
    KeyRings.FreeKeyRings;
  end;
end;

function KeyEnable(HexKeyID: PChar): Integer;
var
  Context	: pPGPContext;
  KeySetMain	: pPGPKeySet;
  Key		: pPGPKey;
begin
  Result:=KeyRings.InitKeyRings(Context, KeySetMain);
  if Result<>0 then Exit;
  try
    Result:=GetKeyByHexID(KeySetMain, HexKeyID, Key);
    if Result<>0 then Exit;
    Result:=PGPEnableKey(Key);
    if Result<>0 then Exit;
    Result:=KeyRings.UpdateKeyRings;
  finally
    KeyRings.FreeKeyRings;
  end;
end;

function KeyDisable(HexKeyID: PChar): Integer;
var
  Context	: pPGPContext;
  KeySetMain	: pPGPKeySet;
  Key		: pPGPKey;
begin
  Result:=KeyRings.InitKeyRings(Context, KeySetMain);
  if Result<>0 then Exit;
  try
    Result:=GetKeyByHexID(KeySetMain, HexKeyID, Key);
    if Result<>0 then Exit;
    Result:=PGPDisableKey(Key);
    if Result<>0 then Exit;
    Result:=KeyRings.UpdateKeyRings;
  finally
    KeyRings.FreeKeyRings;
  end;
end;

function KeyRevoke(HexKeyID, Passphrase: PChar): Integer;
var
  Context	: pPGPContext;
  KeySetMain	: pPGPKeySet;
  Key		: pPGPKey;
begin
  Result:=KeyRings.InitKeyRings(Context, KeySetMain);
  if Result<>0 then Exit;
  try
    Result:=GetKeyByHexID(KeySetMain, HexKeyID, Key);
    if Result<>0 then Exit;
    Result:=PGPRevokeKey(Key, PGPOPassphrase(Context, Passphrase), PGPOLastOption(Context));
    if Result<>0 then Exit;
    Result:=KeyRings.UpdateKeyRings;
  finally
    KeyRings.FreeKeyRings;
  end;
end;

function ChangePassphrase(HexKeyID, OldPassphrase, NewPassphrase: PChar): Integer;
var
  Context	: pPGPContext;
  KeySetMain	: pPGPKeySet;
  OptionList	: pPGPOptionList;
  Key		: pPGPKey;
  KeyList	: pPGPKeyList;
  KeyIter	: pPGPKeyIter;
  SubKey	: pPGPSubKey;
begin
  Result:=KeyRings.InitKeyRings(Context, KeySetMain);
  if Result<>0 then Exit;
  OptionList:=nil;
  try
    Result:=PGPBuildOptionList(Context, OptionList,
      [
	PGPOPassphrase(Context, OldPassphrase),
	PGPOPassphrase(Context, NewPassphrase)
      ]);
    if Result<>0 then Exit;
    try
      Result:=GetKeyByHexID(KeySetMain, HexKeyID, Key);
      if Result<>0 then Exit;
      Result:=PGPChangePassphrase(Key, OptionList, PGPOLastOption(Context));
      if Result<>0 then Exit;
      if not GetKeyPropLegacy(Key) then begin
	KeyList:=nil;
	KeyIter:=nil;
	Result:=PGPOrderKeySet(KeySetMain, kPGPKeyOrdering_Any, PGPFalse, KeyList);
	if Result<>0 then Exit;
	try
	  Result:=PGPNewKeyIter(KeyList, KeyIter);
	  if Result<>0 then Exit;
	  try
	    PGPKeyIterSeek(KeyIter, Key);
	    while PGPKeyIterNextKeyDBObj(KeyIter, kPGPKeyDBObjType_SubKey, SubKey)=0 do begin
	      Result:=PGPChangeSubKeyPassphrase(SubKey, OptionList, PGPOLastOption(Context));
	      if Result<>0 then Exit;
	    end;
	  finally
	    PGPFreeKeyIter(KeyIter);
	  end;
	finally
	  PGPFreeKeyList(KeyList);
	end;
      end;
      Result:=KeyRings.UpdateKeyRings;
    finally
      PGPFreeOptionList(OptionList);
    end;
  finally
    KeyRings.FreeKeyRings;
  end;
end;

function FindKeyProps(const KeyIDCommaText: String;
		      var KeyPropsList: TKeyPropsList;
		      PropertyFlags, FilterFlags: DWord;
		      KeyOrder: TPGPKeyOrdering): Integer;
var
  Context	: pPGPContext;
  KeySetMain	: pPGPKeySet;
  KeySetFound	: pPGPKeySet;
  KeyFilter	: pPGPFilter;
  KeySetFiltered: pPGPKeySet;
  KeyCount	: PGPUInt32;
begin
  KeySetFound:=nil;
  KeyFilter:=nil;
  KeySetFiltered:=nil;
  Result:=KeyRings.InitKeyRings(Context, KeySetMain);
  if Result<>0 then Exit;
  try
    if KeyIDCommaText='' then
      KeySetFound:=KeySetMain // all keys on key rings
    else Result:=GetKeySetByAnyIDs(Context, KeySetMain, KeyIDCommaText, KeySetFound); // key(s) matching KeyData
    if Result<>0 then Exit;
    try
      if PropertyFlags<>0 then begin
	Result:=GetKeySetProps(Context, KeySetFound,
			       KeyPropsList, PropertyFlags,
			       FilterFlags, KeyOrder);
      end
      else begin
	if FilterFlags<>KeyFilterFlag_AllKeys then begin
	  Result:=GetKeyFilter(Context, FilterFlags, KeyFilter);
	  try
	    if Result<>0 then Exit;
	    Result:=PGPFilterKeySet(KeySetFound, KeyFilter, KeySetFiltered);
	  finally
	    PGPFreeFilter(KeyFilter);
	  end;
	end
	else KeySetFiltered:=KeySetFound;
	if Result<>0 then Exit;
	try
	  Result:=PGPCountKeys(KeySetFiltered, KeyCount);
	  if Result=0 then Result:=KeyCount;
	finally
	  if KeySetFiltered<>KeySetFound then PGPFreeKeySet(KeySetFiltered);
	end;
      end;
    finally
      if KeySetFound<>KeySetMain then PGPFreeKeySet(KeySetFound);
    end;
  finally
    KeyRings.FreeKeyRings;
  end;
end;

function GetKeyFromKeySet(KeySet: pPGPKeySet; var Key: pPGPKey): PGPError;
var
  KeyList	: pPGPKeyList;
  KeyIter	: pPGPKeyIter;
begin
  Key:=nil;
  KeyList:=nil;
  KeyIter:=nil;
  Result:=PGPOrderKeySet(KeySet, kPGPKeyOrdering_UserID, PGPFalse, KeyList);
  if Result<>0 then Exit;
  try
    Result:=PGPNewKeyIter(KeyList, KeyIter);
    if Result<>0 then Exit;
    try
      Result:=PGPKeyIterNextKeyDBObj(KeyIter, kPGPKeyDBObjType_Key, Key);
    finally
      PGPFreeKeyIter(KeyIter);
    end;
  finally
    PGPFreeKeyList(KeyList);
  end;
end;

function GetKeyByHexID(KeySet: pPGPKeySet; const HexID: String; var Key: pPGPKey): PGPError;
var
  PGPKeyID	: TPGPKeyID7;
begin
  Key:=nil;
  Result:=PGPGetKeyIDFromString(PChar(HexID), kPGPPublicKeyAlgorithm_Invalid, PGPKeyID);
  if Result=0 then Result:=PGPGetKeyByKeyID(KeySet, PGPKeyID, kPGPPublicKeyAlgorithm_Invalid, Key);
end;

function GetKeyFilter(Context: pPGPContext; FilterFlags: DWord; var KeyFilter: pPGPFilter): PGPError;
var
  KeyBoolFilter	: pPGPFilter;
  KeyAlgFilter	: pPGPFilter;
begin
  Result:=0;
  KeyFilter:=nil;
  KeyBoolFilter:=nil;
  KeyAlgFilter:=nil;
  try
    if FilterFlags and KeyFilterMask_Boolean<>0 then begin
      if FilterFlags and KeyFilterFlag_CanEncrypt<>0 then begin
	Result:=PGPNewKeyDBObjBooleanFilter(Context, kPGPKeyProperty_CanEncrypt, PGPTrue, KeyBoolFilter);
      end
      else if FilterFlags and KeyFilterFlag_CanDecrypt<>0 then begin
	Result:=PGPNewKeyDBObjBooleanFilter(Context, kPGPKeyProperty_CanDecrypt, PGPTrue, KeyBoolFilter);
      end
      else if FilterFlags and KeyFilterFlag_CanSign<>0 then begin
	Result:=PGPNewKeyDBObjBooleanFilter(Context, kPGPKeyProperty_CanSign, PGPTrue, KeyBoolFilter);
      end
      else if FilterFlags and KeyFilterFlag_CanVerify<>0 then begin
	Result:=PGPNewKeyDBObjBooleanFilter(Context, kPGPKeyProperty_CanVerify, PGPTrue, KeyBoolFilter);
      end
      else if FilterFlags and KeyFilterFlag_Enabled<>0 then begin
	Result:=PGPNewKeyDBObjBooleanFilter(Context, kPGPKeyProperty_IsDisabled, PGPFalse, KeyBoolFilter);
      end
      else if FilterFlags and KeyFilterFlag_Disabled<>0 then begin
	Result:=PGPNewKeyDBObjBooleanFilter(Context, kPGPKeyProperty_IsDisabled, PGPTrue, KeyBoolFilter);
      end;
    end;

⌨️ 快捷键说明

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