[返回]
计算机世界1999年第25期

用修改时间的方法加密

武汉市华中师大计科系 江 立

  谈到文件加密,已经有很多方法了,但传统的文件型加密方法都存在一些不足。例如:让人头痛的密码技术、复杂的全文加/ 解密算法、会产生垃圾文件的暗贴等等。这里我向大家介绍一种新的文件加密思路:在Win 95/98 中选定一个文件后,单击鼠标右键可以查看文件的属性, 其中会列出该文件的创建时间、修改时间和访问时间。这些信息的设置一般都是由操作系统(也就是由Dos/Windows 等等)自动完成的,不会让用户轻易修改。利用这一特性就可以实现很隐蔽的加密技术。

  加密原理

  用特定的时间信息替换原来的文件时间信息。
解密原理

  获取已加密文件的时间信息与特定时间信息比较,如相同则说明该文件是合法的,如不同则说明该文件属于过期或盗版软件。
  以上简单介绍了文件时间属性的修改方法,利用这种方法可以起到简单的软件加密。例如:假设某个软件或游戏执行完后存储了一些存档文件,则操作系统会自动设置该文件的修改时间,那么稍有经验的用户就可以用Windows 中的“查找文件”功能找到最后被修改的文件。如果该文件是记录密码或用户信息的文件(实际上很多情况都是这样),后果简直不堪设想。另外,如果适当设置文件的创建、修改时间和访问时间,例如:保持三者之间为一定的时间间隔就可以作为加密的一种好手段。运行主软件时只要动态地检测一下文件时间是否满足特定的要求就知道该软件是否过期或属于盗版软件,从而达到加密和保护软件的目的,并且不会产生垃圾文件。

  实现方法

  利用Delphi 中的FindFirst 函数可以得到一个文件的属性记录,该记录中的FindData 域中就记载了详细的文件时间信息。FindData 中的时间信息不能直接得到, 利用本文源程序中的CovFileDate 函数可以完成文件时间格式的转换。设置文件的时间要复杂一些,利用Delphi 中的DataTimePicker 组件来辅助完成这一复杂的操作。可以利用四个DataTimePicker 组件来完成文件创建时间和修改时间的设置。注意:文件的访问时间用修改时间来代替。使用下面的例子时,请在您的Form 上添加四个DataTimePicker 组件。其中第一和第三个DataTimePicker 组件中的Kind 设置为dtkDate,第二个和第四个DataTimePicker 组件中的Kind 设置为dtkTime,DateMode 设置为dmUpDown。下图为程序运行后的界面:
de044_1.jpg (20082 字节)
  源程序清单(仅供参考):

unit FileTime;
interface
uses
Windows, Messages, SysUtils, Classes,
Graphics, Controls, Forms, Dialogs,
StdCtrls, Buttons, ComCtrls;

type
TForm1 = class(TForm)
  DateTimePicker1: TDateTimePicker;
  DateTimePicker2: TDateTimePicker;
  DateTimePicker3: TDateTimePicker;
  DateTimePicker4: TDateTimePicker;
  BitBtn1: TBitBtn;
  Label1: TLabel;
  Label2: TLabel;
  Label3: TLabel;
  Label4: TLabel;
  procedure BitBtn1Click(Sender: TObject);
  procedure FormCreate(Sender: TObject);
private
  { Private declarations }
public
  { Public declarations }
end;

const
Tf='C:\Command.com';
{ 待修改文件名称,
 可自行更改为其它文件名}

var
Form1: TForm1;

implementation

{ $R *.DFM}

function CovFileDate(Fd:_FileTime):TDateTime;
{ 文件时间转换函数}
var
Tct:_SystemTime;
Temp:_FileTime;
begin
FileTimeToLocalFileTime(Fd,Temp);
FileTimeToSystemTime(Temp,Tct);
CovFileDate:=SystemTimeToDateTime(Tct);
end;

procedure SetFileDateTime
(const Tf:string;CreatDate,ModifyDate:Tdate;
       CreatTime,ModifyTime:Ttime);
{ 文件时间设置过程}
var
Dt1,Dt2:Integer;
Fs:TFileStream;
Fct,Flt:TFileTime;
begin
Dt1 := DateTimeToFileDate
(Trunc(CreatDate) +Frac(CreatTime));
Dt2 := DateTimeToFileDate
(Trunc(ModifyDate) +Frac(ModifyTime));
{ 转换用户输入在DataTimePicker 中的信息}
try
  FS := TFileStream.Create(Tf, fmOpenReadWrite);
  try
   if DosDateTimeToFileTime
(LongRec(DT1).Hi, LongRec(DT1).Lo, Fct) and
    LocalFileTimeToFileTime(Fct, Fct) and
    DosDateTimeToFileTime
(LongRec(DT2).Hi, LongRec(DT2).Lo, Flt) and
    LocalFileTimeToFileTime(Flt, Flt)
   then SetFileTime(FS.Handle, @Fct, @Flt, @Flt);
   { 设置文件时间属性}
  finally
   FS.Free;
  end;
except
MessageDlg
('日期修改操作失败!', mtError, [mbOk], 0);
{ 因为目标文件正在被
使用等原因而导致失败}
end;
end;

procedure UpdateFile;
const
Model='yyyy/mm/dd,hh:mm:ss';
Mode2='yyyy/m/d';
Mode3='hh:mm:ss';
{ 设置用于显示的日期时间格式}
var
Tp:TSearchRec;
T1,T2:string;
begin
FindFirst(Tf,faAnyFile,Tp);
T1:=FormatDateTime(Mode2,CovFileDate
(Tp.FindData.ftCreationTime));
T2:=FormatDateTime(Mode3,CovFileDate
(Tp.FindData.ftCreationTime));
Form1.DateTimePicker1.Date:=StrToDate(T1);
Form1.DateTimePicker2.Time:=StrToTime(T2);
{ 返回文件的创建时间}
T1:=FormatDateTime(Mode2,CovFileDate
(Tp.FindData.ftLastWriteTime));
T2:=FormatDateTime(Mode3,CovFileDate3
(Tp.FindData.ftLastWriteTime));
Form1.DateTimePicker3.Date:=StrToDate(T1);
Form1.DateTimePicker4.Time:=StrToTime(T2);
{ 返回文件的修改时间}
FindClose(Tp);
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
SetFileDateTime
(Tf,DateTimePicker1.Date,DateTimePicker3.Date,
   DateTimePicker2.Time,DateTimePicker4.Time);
{ 设置文件时间}
UpdateFile;
{ 刷新日期和时间的显示}
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
UpdateFile;
end;

end.
  备注:修改文件时间的范围是从公元1792 年9 月19 日开始的,上限可以达到公元2999 年或更高。另外,请不要将此技术用于破坏他人文件等非正当途径。