pgpencode.pas
来自「用DELPHI实现的 PGP 加密算法」· PAS 代码 · 共 857 行 · 第 1/2 页
PAS
857 行
KeyPropsList.Free;
end;
end;
finally
PGPFreeKeySet(pPGPKeySet(RecipientKeys));
end;
end;
end
else if FEncryptToSelf and (EncryptKeyIDs.Count<>0) then EncryptKeyIDs.Add(SignKeyID);
end;
function GetPGPHashAlgorithm(SignAlgorithm: TSignAlgorithm): PGPHashAlgorithm;
begin
Result:=PGPHashAlgorithm(
ord(SignAlgorithm) +
ord(SignAlgorithm>HashAlgorithm_RIPEMD160) * ord(pred(kPGPHashAlgorithm_SHA256-kPGPHashAlgorithm_RIPEMD160))
);
end;
function TPGPEncodeCustom.GetOptionList(var OptionList: pPGPOptionList): PGPError;
var
Cancel : Longbool;
KeyPropsList : TKeyPropsList;
BadPassphrase : Longbool;
SelectedKey : Longint;
SignKeyHexID : String;
SigningKey : pPGPKey;
AlgorithmList : TPGPCipherAlgorithms;
AlgCount : Longint;
Armor : PGPUInt32;
MIME : PGPUInt32;
Textmode : PGPUInt32;
RipeMD : PGPUInt32;
begin
Cancel:=false;
FPassphraseBufSize:=MaxUTF8Length;
KeyPropsList:=TKeyPropsList.Create(0, spgpKeyPropFlag_IDComplete);
try
if FDetachedSign then begin
Result:=PGPBuildOptionList(FContext, OptionList,
[
PGPOSendNullEvents(FContext, FProgressInterval),
PGPOEventHandler(FContext, EventHandler, Self),
PGPOArmorOutput(FContext, PGPBoolean(Format_Armor in FFormatOptions)),
PGPODetachedSig(FContext, PGPOLastOption(FContext), nil),
PGPOCommentString(FContext, PChar(FComment)),
PGPOVersionString(FContext, MyVersion)
]);
end
else begin
Result:=PGPBuildOptionList(FContext, OptionList,
[
PGPOSendNullEvents(FContext, FProgressInterval),
PGPOEventHandler(FContext, EventHandler, Self),
PGPOClearSign(FContext, PGPBoolean(FClear) and 1),
PGPOCompression(FContext, PGPBoolean(FCompress) and 1),
PGPOCommentString(FContext, PChar(FComment)),
PGPOVersionString(FContext, MyVersion)
]);
end;
if Result<>0 then Exit;
BadPassphrase:=false;
if FConventional then begin
Result:=PGPAppendOptionList(OptionList,
[PGPOCipherAlgorithm(FContext, PGPCipherAlgorithm(succ(FConventionalAlgorithm)))]);
if Result<>0 then Exit;
if Assigned(FOnEnterPassphrase) then begin
SelectedKey:=-1;
FPassphrase:=PGPNewSecureData(PGPGetDefaultMemoryMgr, FPassphraseBufSize, kPGPMemoryMgrFlags_Clear);
if FPassphrase<>nil then begin
Result:=kPGPError_UserAbort;
FOnEnterPassphrase(FPassphrase, KeyPropsList, SelectedKey, 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 begin
Result:=ConvEncPassphraseDialog(FContext, FPassphrase, FPassDlgPrompt, FParentHandle);
if Result<>0 then Exit;
end;
Result:=PGPAppendOptionList(OptionList,
[PGPOConventionalEncrypt(FContext, PGPOPassphrase(FContext, FPassphrase), PGPOLastOption(FContext))]);
if Result<>0 then Exit;
end
else begin
SigningKey:=nil;
if FSign or FDetachedSign then begin
Armor:=ord(Format_Armor in FFormatOptions);
MIME:=ord(Format_MIME in FFormatOptions);
Textmode:=ord(Format_Textmode in FFormatOptions);
if Assigned(FOnEnterPassphrase) then begin
if FindKeyProps('', KeyPropsList, spgpKeyPropFlag_IDComplete,
KeyFilterFlag_CanSign, UserID_Ordering)>0 then begin
Result:=GetHexIDByAnyID(FContext, FKeySetMain, FSignKeyID, SignKeyHexID);
if Result<>1 then with FPreferences do begin
if DefaultKeyHexID<>'' then begin
FSignKeyID:=DefaultKeyHexID;
Result:=1;
end;
end
else FSignKeyID:=SignKeyHexID;
if Result=1 then with KeyPropsList do begin
SelectedKey:=IndexOf(FSignKeyID);
if SelectedKey>0 then Move(SelectedKey, 0);
end;
end
else begin
Result:=kPGPError_SecretKeyNotFound;
Exit;
end;
SelectedKey:=0;
FPassphrase:=PGPNewSecureData(PGPGetDefaultMemoryMgr, 256, kPGPMemoryMgrFlags_Clear);
if FPassphrase<>nil then begin
Result:=kPGPError_UserAbort;
repeat
FOnEnterPassphrase(FPassphrase, KeyPropsList, SelectedKey, BadPassphrase, Cancel);
if not Cancel then begin
if PGP8X then AnsiToUtf8PChar(FPassphrase, FPassphrase, FPassphraseBufSize);
if (SelectedKey>=0) and (SelectedKey<KeyPropsList.Count) then begin
FSignKeyID:=KeyPropsList[SelectedKey];
BadPassphrase:=not PassphraseIsValid(FContext, FKeySetMain, PChar(FSignKeyID), FPassphrase);
end
else begin
Result:=kPGPError_SecretKeyNotFound;
Exit;
end;
end;
until Cancel or not BadPassphrase;
if Cancel then Exit;
end
else begin
Result:=kPGPError_OutOfMemory;
Exit;
end;
Result:=GetKeyByHexID(FKeySetMain, PChar(FSignKeyID), SigningKey);
if Result<>0 then Exit;
end
else begin
if (FSignKeyID='')
or (FindKeyProps(FSignKeyID, KeyPropsList,
spgpKeyPropFlag_KeyID,
KeyFilterFlag_CanSign,
Any_Ordering)<>1) then begin
FSignKeyID:=FPreferences.DefaultKeyHexID;
end;
RipeMD:=ord(FSignAlgorithm=HashAlgorithm_RIPEMD160);
Result:=SigningPassphraseDialog(FContext, FKeySetMain, SigningKey, FPassphrase, FSignKeyID, true,
TSignOption((ord(FClear) and 1)*ord(soClear) +
(ord(FDetachedSign) and 1)*ord(soDetached)),
Armor, MIME, RipeMD, FPassDlgPrompt, FParentHandle);
if Result<>0 then Exit;
if not FEncrypt then begin
FFormatOptions:=[];
if Armor<>0 then Include(FFormatOptions, Format_Armor);
if MIME<>0 then Include(FFormatOptions, Format_MIME);
if Textmode<>0 then Include(FFormatOptions, Format_Textmode);
end;
if RipeMD<>0 then FSignAlgorithm:=HashAlgorithm_RIPEMD160;
end;
if FSignAlgorithm=HashAlgorithm_Default then begin
case GetKeyPropAlg(SigningKey) of
KeyAlgorithm_RSA..KeyAlgorithm_RSASignOnly: if GetKeyPropLegacy(SigningKey) then
FSignAlgorithm:=HashAlgorithm_MD5
else FSignAlgorithm:=HashAlgorithm_SHA;
KeyAlgorithm_DH..KeyAlgorithm_DHDSS: FSignAlgorithm:=HashAlgorithm_SHA;
else
Result:=kPGPError_UnknownPublicKeyAlgorithm;
Exit;
end;
end;
Result:=PGPAppendOptionList(OptionList,
[
PGPOSignWithKey(FContext, SigningKey, PGPOPassphrase(FContext, FPassphrase), PGPOLastOption(FContext)),
PGPOHashAlgorithm(FContext, GetPGPHashAlgorithm(FSignAlgorithm))
]);
if Result<>0 then Exit;
end;
if SigningKey<>nil then FSignKeyID:=GetKeyPropKeyID(SigningKey);
if FEncrypt then begin
Result:=GetEncryptKeyIDs(FEncryptKeyIDs, FSignKeyID);
if Result<>0 then Exit;
Result:=GetKeySetByAnyIDs(FContext, FKeySetMain, FEncryptKeyIDs.CommaText, FEncryptKeySet);
if Result<>0 then Exit;
Result:=PGPAppendOptionList(OptionList, [PGPOEncryptToKeySet(FContext, FEncryptKeySet)]);
if Result<>0 then Exit;
if GetAllowedCipherAlgorithms(AlgorithmList, AlgCount)=0 then begin
PGPAppendOptionList(OptionList, [PGPOPreferredAlgorithms(FContext, AlgorithmList, AlgCount)]);
end;
end;
end;
if not FDetachedSign then begin
Result:=PGPAppendOptionList(OptionList,
[
PGPOForYourEyesOnly(FContext, PGPBoolean(FEyesOnly) and 1),
PGPOArmorOutput(FContext, PGPBoolean(Format_Armor in FFormatOptions)),
PGPODataIsASCII(FContext, PGPBoolean(Format_Textmode in FFormatOptions))
]);
if Result<>0 then Exit;
if Format_Mime in FFormatOptions then begin
SetLength(FMimeSeparator, SizeOf(TMimeSeparator));
FMimeBodyOffset:=0;
FMimeSeparator[1]:=#0;
Result:=PGPAppendOptionList(OptionList,
[
PGPOPGPMIMEEncoding(FContext, PGPTrue, PGPSize(FMimeBodyOffset), @FMimeSeparator[1]),
PGPOOmitMIMEVersion(fContext, PGPBoolean(FOmitMimeVersion) and 1)
]);
if Result<>0 then Exit;
end;
end;
finally
KeyPropsList.Free;
end;
end;
function TPGPEncodeCustom.SetOutputOption(var OptionList: pPGPOptionList): PGPError;
begin
if FFileOutput then begin
if (FOutputFileName='') or FileExists(FOutputFileName) then begin
if FOutputFileName='' then begin
if FDetachedSign then
FOutputFileName:=FInputFileName + '.sig'
else begin
if Format_Armor in FFormatOptions then
FOutputFileName:=FInputFileName + '.asc'
else FOutputFileName:=FInputFileName + '.pgp';
end;
end;
if Assigned(FOnGetOutputFileName) then
FOnGetOutputFileName(FOutputFileName)
else FOutputFileName:='';
end;
if FOutputFileName='' then begin
Result:=kPGPError_CantOpenFile;
Exit;
end;
end;
Result:=PGPAppendOptionList(OptionList,
[PGPOAllocatedOutputBuffer(FContext, FAllocatedOutputBuffer, $FFFFFFFF, FActualOutputSize)]);
end;
function TPGPEncodeCustom.Encode(const Input: String; IsFile: Longbool): Longint;
var
OptionList : pPGPOptionList;
FileSpec : pPGPFileSpec;
FileHandle : THandle;
FileSizeHigh : DWord;
begin
Result:=0;
if IsFile then begin
FInputFileName:=Input;
if not FileExists(FInputFileName) then begin
if Assigned(FOnGetInputFileName) then begin
FOnGetInputFileName(FInputFileName);
if FInputFileName='' then Result:=kPGPError_FileNotFound;
end
else Result:=kPGPError_FileNotFound;
end;
end
else if Input='' then Result:=kPGPError_ItemNotFound;
if Result=0 then begin
FileSpec:=nil;
OptionList:=nil;
FEncryptKeySet:=nil;
Result:=InitEncode;
if Result<>0 then Exit;
try
if IsFile then begin
Result:=PGPNewFileSpecFromFullPath(FContext, PChar(FInputFileName), FileSpec);
if Result<>0 then Exit;
end;
try
Result:=GetOptionList(OptionList);
try
if Result<>0 then Exit;
if IsFile then begin
FileHandle:=FileOpen(FInputFileName, fmOpenRead or fmShareDenyNone);
if FileHandle<>INVALID_HANDLE_VALUE then begin
FInputSize:=GetFileSize(FileHandle, @FileSizeHigh);
FileClose(FileHandle);
end
else FInputSize:=$FFFFFFFF;
if (FInputSize=0) or (FInputSize=$FFFFFFFF) or (FileSizeHigh<>0) then begin
Result:=kPGPError_ReadFailed;
Exit;
end;
Result:=PGPAppendOptionList(OptionList, [PGPOInputFile(FContext, FileSpec)]);
end
else begin
FInputSize:=Length(Input);
Result:=PGPAppendOptionList(OptionList, [PGPOInputBuffer(FContext, @Input[1], FInputSize)]);
end;
if Result<>0 then Exit;
Result:=SetOutputOption(OptionList);
if Result<>0 then Exit;
Result:=pgpEvents.PGPEncode(FContext, OptionList, PGPOLastOption(FContext));
try
if (Result=0) and (FActualOutputSize<>0) then begin
if FFileOutput then
Result:=WriteOutputFile
else begin
SetLength(FOutputBuffer, FActualOutputSize);
Move(FAllocatedOutputBuffer[0], FOutputBuffer[1], FActualOutputSize);
end;
end;
except
on EOutOfMemory do Result:=kPGPError_OutOfMemory;
end;
finally
try
SetLength(FMimeSeparator, StrLen(PChar(FMimeSeparator)));
PGPFreeOptionList(OptionList);
PGPFreeKeySet(FEncryptKeySet);
if Assigned(FOnWipePassphrase) then begin
if PGP8X then begin
FPassphraseBufSize:=MaxUTF8Length;
Utf8ToAnsiPChar(FPassphrase, FPassphrase, FPassphraseBufSize);
end;
FOnWipePassphrase(FPassphrase);
end;
finally
PGPFreeData(FAllocatedOutputBuffer);
PGPFreeData(FPassphrase);
FPassphrase:=nil;
end;
end;
finally
PGPFreeFileSpec(FileSpec);
end;
finally
FinitEncode;
end;
end;
end;
function TPGPEncodeCustom.KeyEncryptBuffer(const DataBuffer: String; Sign: Longbool): Longint;
begin
SetSign(Sign);
SetEncrypt(true);
FCompress:=true;
Result:=Encode(DataBuffer, false);
end;
function TPGPEncodeCustom.KeyEncryptFile(const FileName: String; Sign: Longbool): Longint;
begin
SetSign(Sign);
SetEncrypt(true);
FCompress:=true;
Result:=Encode(FileName, true);
end;
function TPGPEncodeCustom.ConventionalEncryptBuffer(const DataBuffer: String): Longint;
begin
FCompress:=true;
SetConventional(true);
Result:=Encode(DataBuffer, false);
end;
function TPGPEncodeCustom.ConventionalEncryptFile(const FileName: String): Longint;
begin
FCompress:=true;
SetConventional(true);
Result:=Encode(FileName, true);
end;
function TPGPEncodeCustom.ClearSignBuffer(const DataBuffer: String): Longint;
begin
SetClear(true);
Result:=Encode(DataBuffer, false);
end;
function TPGPEncodeCustom.ClearSignFile(const FileName: String): Longint;
begin
SetClear(true);
Result:=Encode(FileName, true);
end;
function TPGPEncodeCustom.ArmorBuffer(const DataBuffer: String): Longint;
begin
FClear:=false;
FCompress:=true;
FDetachedSign:=false;
FEncrypt:=false;
FSign:=false;
Include(FFormatOptions, Format_Armor);
Result:=Encode(DataBuffer, false);
end;
function TPGPEncodeCustom.ArmorFile(const FileName: String): Longint;
begin
FClear:=false;
FCompress:=true;
FDetachedSign:=false;
FEncrypt:=false;
FSign:=false;
Include(FFormatOptions, Format_Armor);
Result:=Encode(FileName, true);
end;
function TPGPEncodeCustom.DetachedSignBuffer(const DataBuffer: String): Longint;
begin
FClear:=false;
FConventional:=false;
FEncrypt:=false;
FSign:=false;
FDetachedSign:=true;
Result:=Encode(DataBuffer, false);
end;
function TPGPEncodeCustom.DetachedSignFile(const FileName: String): Longint;
begin
FClear:=false;
FConventional:=false;
FEncrypt:=false;
FSign:=false;
FDetachedSign:=true;
Result:=Encode(FileName, true);
end;
end.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?