Delphi“流”实现文件加密器

V項总

V項总

2016-02-19 16:15

岁数大了,QQ也不闪了,微信也不响了,电话也不来了,但是图老师依旧坚持为大家推荐最精彩的内容,下面为大家精心准备的Delphi“流”实现文件加密器,希望大家看完后能赶快学习起来。

  数据流是面向对象程序设计语言中面向对象思想的典型体现,它彻底地取代了早期的利用函数实现输入输出的功能,克服了用函数实现输入输出功能的诸多弊端。简单来说,流就是建立在面向对象基础上的一种抽象的处理数据的工具。在流中,可定义一些处理数据的基本操作,如读取数据、写入数据等,程序员是对流进行操作,而不用关心流的另一头数据的真正流向。流不但可以处理文件,还可以处理动态内存、网络数据等多种数据形式。掌握好对流的操作在并程序中充分利用流的方便性,不仅能使在编写面向过程的程序时效率大大提高。本文以文件加密为例说明Delphi编程中流的概念及应用。

  一、流的基本概念

  在Delphi中,所有流对象的基类为TStream类,其中定义了所有流的共同属性和方法。

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

  TStream类中定义的属性介绍如下:

  (1)Size:此属性以字节为单位返回流中数据大小。

  (2)Position:此属性控制流中存取指针的位置。

  TStream类中定义的四个虚方法:

  (1)Read:此方法实现将数据从流中读出。

  函数原形为:

  Function Read(var Buffer;Count:Longint):Longint;virtual;abstract;

  参数Buffer为数据读出时放置的缓冲区,Count为需要读出的数据的字节数,该方法返回值为实际读出的字节数,它可以小于或等于Count中指定的值。

  (2)Write:此方法实现将数据写入流中。

  函数原形为:

  Function Write(var Buffer;Count:Lonogint):Longint;virtual;abstract;

  参数Buffer为将要写入流中的数据的缓冲区,Count为需要写入数据的长度字节数,该方法返回值为实际写入流中的字节数。

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

  (3)Seek:此方法实现流中指针的移动。函数原形如下:Function Seek(Offset:Longint;Origint:Word):Longint;virtual;abstract;参数Offset表示以Origint为基准指针移动的方向和字节数,为正表示指针从数据头向数据尾移动,为负表示指针从数据尾向数据头方向移动。参数Origint指出指针移动参照的基准,其可能的取值如下:a)soFrombeginning:Offset以数据开始处为基准移动,此时Offset必须大于或者等于零。b)soFromCurrent:Offset以指针的当前位置为基准。c)soFromEnd:Offset以数据结束的位置为基准。此时Offset必须小于或者等于零。该方法返回值为移动后指针的位置。

  (4)Setsize:此方法实现改变数据的大小。

  函数原形为:

  Function Setsize(NewSize:Longint);virtual;

  TStream类中定义的三个静态方法:

  (1)ReadBuffer:此方法的作用是从流中当前位置读取数据。函数原形为:Procedure ReadBuffer(var Buffer;Count:Longint);参数的定义跟上面的Read函数相同。需要注意的是,当读取的数据字节数与需要读取的字节数不相同时,该函数将产生EReadError异常。

  (2)WriteBuffer:此方法的作用是在当前位置向流写入数据。函数原形为:Procedure WriteBuffer(var Buffer;Count:Longint);参数的定义跟上面的Write函数相同,同样,当写入的数据字节数与需要写入的字节数不相同时,将产生EWriteError异常。

  (3)CopyFrom:此方法的作用是从其它流中拷贝数据流。函数原形为:Function CopyFrom(Source:TStream;Count:Longint):Longint;参数Source为源数据流,Count为拷贝的数据字节数。当Count大于0时,CopyFrom从Source参数的当前位置拷贝Count个字节的数据;当Count等于0时,CopyFrom设置Source参数的Position属性为0,然后拷贝Source的所有数据。

  Tstream派生类中最常用的是TFileStream类,该类一般被用来存取文件。建立一个TFileStream类实例声明如下:constructor Create(const Filename:string;mode:Word);其中Filename为文件名(包括路径),参数Mode为找开文件的方式,它包括文件的打开模式和共享模式,其可能的取值和意义可以参考相关帮助。

  TStream还有一个叫内存流的派生类TMemoryStream,它在内存中建立一个流对象,其基本方法和函数跟TFileStream类相似。

  二、利用"流"实现exe文件的加密解密

  使用本方法加密exe文件时,要先建立两个exe文件,一个用来添加资源到另外一个exe文件里面,称为添加程序。另一个被添加的exe文件称为头文件,该文件的功能是在解密时把添加到自己里面的文件读出来。加密时,首先建立头文件,再将明文追加到头文件尾部并设置一个密码,生成密文;解密时,先校验密码,如正确,则将密文从头文件中读出,生成明文,否则报错。为了exe文件的加密,需要建立三个函数,其原型及功能如下:

  (a)Function Jmf_AddtoFile(SourceFile,PassWord,TargetFile:string):Boolean;

  实现分别把文件SoureceFile和字符串PassWord添加到文件TargetFile尾部,如果添加成功就返回True;否则返回false。

  (b)Function Jmf_LoadFromFile(SourceFile,TargetFile:string):Boolean;

  实现从SourceFile中取出文件并另保存为TargetFile。如果取出成功返回True,否则返回false。

  (c)Function Jmf_PassFromFile(var Password:string;SourceFile:string):Boolean;

  实现从SourceFile中取出密码,保存在Password中。如果取出成功就返回True,否则返回false。

  首先建立头文件。使用Delphi新建一工程,在窗口上放上一个TMaskEdit控件(属性name设置为password)和两个Button控件(属性name分别为:Unbind和Cancel;属性Caption分别为"解密"和"取消"),并在Unbind的Click事件中写入代码(参见代码部分),编译此程序生成head.exe头文件,并保留生成的head.res资源文件。

  再建一个工程,添加以下控件:二个Tedit控件(属性name分别设置为password和position)、一个OpenFileDialog控件、两个Tbutton控件(其中属性name分别设置为:Select和Encrypt;属性Caption分别设置为"选择文件"和"加密")。在Select的Click事件中实现对被加密exe文件的选择,在Encrpyt的Click事件中实现将明文和密码追加至head.exe文件结尾,需要注意的是,在该事件处理例程中调用了ExtractRes函数,其作用是把head.exe从资源文件中提取出来(在源程序中将head.res资源文件跟程序一起编译),生成编译程序生成可执行文件AddEncrypt.exe。

  在对文件进行加密时,先执行程序AddEncrypt,选择需要加密的exe文件,并在password中输入加密密码,点击"加密"按钮。源exe文件将被同名密文取代。解密时,执行加密程序,会弹出对话框询问密码,用户输入密码后,如密码正确则程序正常运行,否则程序将报错,无法运行。需要注意的是,上面的程序只不过简单地把一个文件添加到另一个文件的尾部,实际应用中可改成添加多个文件,实现过程中只要根据实际大小和个数定义好偏移地址就可以了。因为篇幅有限,文中只给出了源程序的关键代码,有兴趣的读者可自行扩弃完善。源程序清单如下:

  

Function Jmf_AddtoFile(SourceFile,PassWord,TargetFile:String):Boolean; Var  Target,Source:TFileStream;  MyFileSize,PassWordSize:integer; Begin  Try   Source:=TFileStream.Create(SoureceFile,fmOpenRead or fmShareExclusive);   Target:=TFileStream.Create(TargetFile,fmOpenWrite of fmShareExclusive);   Try    Target.Seek(0,soFromEnd);{往尾部添加资源}    Target.CopyFrom(Source,0);    MyFileSize:=Source.Size++Sizeof(MyFileSize);{计算资源大小,并写入辅程尾部}    Target.WriteBuffer(MyFilesSize,sizefo(MyFileSize));    PassWordSize:=Sizeof(PassWord)+sizeof(PassWordSize);    Target.Seek(0,soFromEnd);    Target.WriteBuffer(PassWord,Sizeof(PassWord));    Target.WriteBuffer(PassWordSize,sizeof(PassWordSize));   Finally    Target.Free;    Source.Free;   End;   Except    Result:=False;    Exit;   End;  Reslut:=True;  End;Function Jmf_LoadFromFile(SourceFile,TargetFile:string):Boolean; Var Source:TFileStream;  Target:TmemoryStream;  MyFilesize,Position:integer; Begin  Try   Target:=TmemoryStream.Create;   Source:=TFileStream(SourceFile,fmOpenRead or fmShareDenyNone);   Try    Source.Seek(-sizeof(Position),soFromEnd);    Source.ReadBuffer(Position,sizeof(Position));    Source.Seek(-Position-sizefo(MyFileSize),soFromEnd);    Source.ReadBuffer(MyFileSize,sizeof(MyFileSize));{读出资源大小}    Source.Seek(-Position-MyFileSize,soFromEnd);{定位到资源位置}    Target.CopyFrom(Source,MyFileSize-sizefo(MyFileSize));{取出资源}    Target.SaveToFile(TargetFile);{存放到文件}   finally    Target.Free;    Source.Free;   end;  except   Result:=false;   Exit;  end;  Result:=true; end;Function Jmf_PassFromFile(var password:string;SourceFile:string):Boolean; Var  Source:TFileStream;  PassWordSize:interger; Begin  Try   Source:=TFileStream.Create(SourceFile,fmOpenRead or fmShareDenyNone);  Try   Source.Seek(0,soFromEnd);{定位到资源位置}   Source.Read(PassWordSize,Sizeof(PassWordSize));   Source.Seek(-PassWordSize,soFromEnd);   Source.Read(PassWord,PassWordSize-Sizeof(PassWordSize));  Finally   Source.Free;  End;  Except   Result:=false;  Exit; End;  Result:=true; End;Procedure Tfom1.unbindClick(Sender:TObject); Var  S:string;  pass,inpass:string; begin  inpass:=password.text;  S:=ChangeFileExt(Application.ExeName,'Jmf');  If Jmf_PassFromFile(pass,Application.ExeName) then   If pass=password.text then   Begin    Jmf_LordFromFile(Application.ExeName,S);{取出文件保存在当前路径下并命名"原文件.Jmf"}    Winexec(pchar(S),SW_Show);{运行"原文件.Jmf"}    Application.Terminate;{退出程序}   end  else   Application.MessageBox('密码错误,重新输入!','密码错误',MB_OK);  end;Procedure Tform1.openClick(Sender:TObject); begin  If OpenDialog1.Execute then position.Text:=OpenDialog1.FileName; end;procedure Tform1.secretClick(Sender:TObject); var s:string;  spass:string; begin  s:=ExtractFilePath(position.text);  spass:=pass.Text;  if ExtractRes('exefile','head',s+'head.exe') then   if Jmf_AddtoFile(position.text,s+'head.exe',spass) then    if DeleteFile(position.text)then     if RenameFile(s+'head.exe',position.text)then      Application.MessageBox('文件加密成功!!','信息',MB_OK)     Else      Begin       If FileExists(s+'head.exe')        then DeleteFile(S+'head.exe');         Application.MessageBox('文件加密失败!!','信息',MB_OK)       end;Function ExtractRes(Restype,Resname,ResNewName:string):Boolean; Var Res:TresourceStream; begin try  Res:=TresourceStream.Create(Hinstance,Resname,Pchar(ResType));  try   Res.SaveToFile(ResNewName);   Result:=true;  Finally   Res.Free;  end;  except   Result:=False; end;

  三、小结

  本文论述了exe文件加密的方法,它的实现原理与文件捆绑机的道理是一致的,就是把两个或者多个程序添加到一个头文件里面,自解压程序和安装程序的原理也是一样的,只需在文件添加和文件读取时,调用解压缩程序就可以了。

展开更多 50%)
分享

猜你喜欢

Delphi“流”实现文件加密器

编程语言 网络编程
Delphi“流”实现文件加密器

用DELPHI实现文件加密压缩

编程语言 网络编程
用DELPHI实现文件加密压缩

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

实现文件加密功能

C语言教程 C语言函数
实现文件加密功能

用Delphi实现文件关联

Delphi
用Delphi实现文件关联

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

金盾视频加密器的使用手册

电脑入门
金盾视频加密器的使用手册

用JavaScript实现文件夹轻松加密

电脑网络
用JavaScript实现文件夹轻松加密

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

兼容多种浏览器“复制到剪贴板”的解决方案

兼容多种浏览器“复制到剪贴板”的解决方案

word中版权符号® ©怎么打

word中版权符号® ©怎么打
下拉加载更多内容 ↓