Delphi AES加密


(**************************************************************)
(*    Advanced Encryption Standard (AES)    *)
(*    Interface Unit v1.3    *)
(*    *)
(*    Copyright (c) 2002 Jorlen Young    *)
(*    *)
(* 说明:    *)
(*    基于 ElASE.pas 单元封装    *)
(*    *)
(*    这是一个 AES 加密算法的标准接口。    *)
(* 调用示例:    *)
(* if not EncryptStream(src, key, TStream(Dest), keybit) then *)
(*   showmessage('encrypt error');    *)
(*    *)
(* if not DecryptStream(src, key, TStream(Dest), keybit) then *)
(*   showmessage('encrypt error');    *)
(*    *)
(* *** 一定要对Dest进行TStream(Dest) ***    *)
(* ========================================================== *)
(*    *)
(*   支持 128 / 192 / 256 位的密匙    *)
(*   默认情况下按照 128 位密匙操作    *)
(*    *)
(**************************************************************)

unit AES;   

interface

{$IFDEF VER210}
  {$WARN IMPLICIT_STRING_CAST OFF} //关闭警告
  {$WARN IMPLICIT_STRING_CAST_LOSS OFF}
{$ENDIF}
uses
  SysUtils, Classes, Math, ElAES;

const
  SDestStreamNotCreated = 'Dest stream not created.';
  SEncryptStreamError = 'Encrypt stream error.';
  SDecryptStreamError = 'Decrypt stream error.';

type
  TKeyBit = (kb128, kb192, kb256);

function StrToHex(Const str: AnsiString): AnsiString;
function HexToStr(const Str: AnsiString): AnsiString;

function EncryptString(Value: AnsiString; Key: AnsiString;
  KeyBit: TKeyBit = kb128): AnsiString;
function DecryptString(Value: AnsiString; Key: AnsiString;
  KeyBit: TKeyBit = kb128): AnsiString;

function EncryptStream(Src: TStream; Key: AnsiString;
  var Dest: TStream; KeyBit: TKeyBit = kb128): Boolean;
function DecryptStream(Src: TStream; Key: AnsiString;
  var Dest: TStream; KeyBit: TKeyBit = kb128): Boolean;

procedure EncryptFile(SourceFile, DestFile: String;
  Key: AnsiString; KeyBit: TKeyBit = kb128);
procedure DecryptFile(SourceFile, DestFile: String;
  Key: AnsiString; KeyBit: TKeyBit = kb128);

implementation

function StrToHex(Const str: Ansistring): Ansistring;
asm
   push ebx
   push esi
   push edi
   test eax,eax
   jz   @@Exit
   mov  esi,edx    //保存edx值,用来产生新字符串的地址
   mov  edi,eax    //保存原字符串
   mov  edx,[eax-4]  //获得字符串长度
   test edx,edx    //检查长度
   je   @@Exit    {Length(S) = 0}
   mov  ecx,edx    //保存长度
   Push ecx
   shl  edx,1
   mov  eax,esi
   {$IFDEF VER210}
   movzx ecx, word ptr [edi-12] {需要设置CodePage}
   {$ENDIF}
   call System.@LStrSetLength //设置新串长度
   mov  eax,esi    //新字符串地址
   Call UniqueString  //产生一个唯一的新字符串,串位置在eax中
   Pop   ecx
  @@SetHex:
   xor  edx,edx    //清空edx
   mov  dl, [edi]    //Str字符串字符
   mov  ebx,edx    //保存当前的字符
   shr  edx,4    //右移4字节,得到高8位
   mov  dl,byte ptr[edx+@@HexChar] //转换成字符
   mov  [eax],dl    //将字符串输入到新建串中存放
   and  ebx,$0F    //获得低8位
   mov  dl,byte ptr[ebx+@@HexChar] //转换成字符
   inc  eax    //移动一个字节,存放低位
   mov  [eax],dl
   inc  edi
   inc  eax
   loop @@SetHex
  @@Exit:
   pop  edi
   pop  esi
   pop  ebx
   ret
  @@HexChar: db '0123456789ABCDEF'
end;

function HexToStr(const Str: AnsiString): AnsiString;
asm
  push ebx
  push edi
  push esi
  test eax,eax //为空串
  jz   @@Exit
  mov  edi,eax
  mov  esi,edx
  mov  edx,[eax-4]
  test edx,edx
  je   @@Exit
  mov  ecx,edx
  push ecx
  shr  edx,1
  mov  eax,esi //开始构造字符串
  {$IFDEF VER210}
  movzx ecx, word ptr [edi-12] {需要设置CodePage}
  {$ENDIF}
  call System.@LStrSetLength //设置新串长度
  mov  eax,esi    //新字符串地址
  Call UniqueString  //产生一个唯一的新字符串,串位置在eax中
  Pop   ecx
  xor  ebx,ebx
  xor  esi,esi
@@CharFromHex:
  xor  edx,edx
  mov  dl, [edi]    //Str字符串字符
  cmp  dl, '0'  //查看是否在0到f之间的字符
  JB   @@Exit   //小于0,退出
  cmp  dl,'9'   //小于=9
  ja  @@DoChar//CompOkNum
  sub  dl,'0'
  jmp  @@DoConvert
@@DoChar:
  //先转成大写字符
  and  dl,$DF
  cmp  dl,'F'
  ja   @@Exit  //大于F退出
  add  dl,10
  sub  dl,'A'
@@DoConvert: //转化
  inc  ebx
  cmp  ebx,2
  je   @@Num1
  xor  esi,esi
  shl  edx,4
  mov  esi,edx
  jmp  @@Num2
@@Num1:
  add  esi,edx
  mov  edx,esi
  mov  [eax],dl
  xor  ebx,ebx
  inc  eax
@@Num2:
  dec  ecx
  inc  edi
  test ecx,ecx
  jnz  @@CharFromHex
@@Exit:
  pop  esi
  pop  edi
  pop  ebx
end;

{  --  字符串加密函数 默认按照 128 位密匙加密 --  }
function EncryptString(Value: AnsiString; Key: AnsiString;
  KeyBit: TKeyBit = kb128): AnsiString;
var
  {$IFDEF VER210}
  SS,DS: TMemoryStream;
  {$ELSE}
  SS, DS: TStringStream;
  {$ENDIF}
  Size: Int64;
  AESKey128: TAESKey128;
  AESKey192: TAESKey192;
  AESKey256: TAESKey256;
  st: AnsiString;
begin
  Result := '';
  {$IFDEF VER210}
   ss := TMemoryStream.Create;
   SS.WriteBuffer(PAnsiChar(Value)^,Length(Value));
   DS := TMemoryStream.Create;
  {$ELSE}
   SS := TStringStream.Create(Value);
   DS := TStringStream.Create('');
  {$ENDIF}
  try
   Size := SS.Size;
   DS.WriteBuffer(Size, SizeOf(Size));
   {  --  128 位密匙最大长度为 16 个字符 --  }
   if KeyBit = kb128 then
   begin
   FillChar(AESKey128, SizeOf(AESKey128), 0 );
   Move(PAnsiChar(Key)^, AESKey128, Min(SizeOf(AESKey128), Length(Key)));
   EncryptAESStreamECB(SS, 0, AESKey128, DS);
   end;
   {  --  192 位密匙最大长度为 24 个字符 --  }
   if KeyBit = kb192 then
   begin
   FillChar(AESKey192, SizeOf(AESKey192), 0 );
   Move(PAnsiChar(Key)^, AESKey192, Min(SizeOf(AESKey192), Length(Key)));
   EncryptAESStreamECB(SS, 0, AESKey192, DS);
   end;
   {  --  256 位密匙最大长度为 32 个字符 --  }
   if KeyBit = kb256 then
   begin
   FillChar(AESKey256, SizeOf(AESKey256), 0 );
   Move(PAnsiChar(Key)^, AESKey256, Min(SizeOf(AESKey256), Length(Key)));
   EncryptAESStreamECB(SS, 0, AESKey256, DS);
   end;
   {$IFDEF VER210}
   SetLength(st,Ds.Size);
   DS.Position := 0;
   DS.ReadBuffer(PAnsiChar(st)^,DS.Size);
   Result := StrToHex(st);
   {$ELSE}
   Result := StrToHex(DS.DataString);
   {$ENDIF}
  finally
   SS.Free;
   DS.Free;
  end;
end;

{  --  字符串解密函数 默认按照 128 位密匙解密 --  }
function DecryptString(Value: AnsiString; Key: AnsiString;
  KeyBit: TKeyBit = kb128): AnsiString;
var
  SS, DS: TStringStream;
  Size: Int64;
  AESKey128: TAESKey128;
  AESKey192: TAESKey192;
  AESKey256: TAESKey256;
begin
  Result := '';
  SS := TStringStream.Create(HexToStr(Value));
  DS := TStringStream.Create('');
  try
   Size := SS.Size;
   SS.ReadBuffer(Size, SizeOf(Size));
   {  --  128 位密匙最大长度为 16 个字符 --  }
   if KeyBit = kb128 then
   begin
   FillChar(AESKey128, SizeOf(AESKey128), 0 );
   Move(PAnsiChar(Key)^, AESKey128, Min(SizeOf(AESKey128), Length(Key)));
   DecryptAESStreamECB(SS, SS.Size - SS.Position, AESKey128, DS);
   end;
   {  --  192 位密匙最大长度为 24 个字符 --  }
   if KeyBit = kb192 then
   begin
   FillChar(AESKey192, SizeOf(AESKey192), 0 );
   Move(PAnsiChar(Key)^, AESKey192, Min(SizeOf(AESKey192), Length(Key)));
   DecryptAESStreamECB(SS, SS.Size - SS.Position, AESKey192, DS);
   end;
   {  --  256 位密匙最大长度为 32 个字符 --  }
   if KeyBit = kb256 then
   begin
   FillChar(AESKey256, SizeOf(AESKey256), 0 );
   Move(PAnsiChar(Key)^, AESKey256, Min(SizeOf(AESKey256), Length(Key)));
   DecryptAESStreamECB(SS, SS.Size - SS.Position, AESKey256, DS);
   end;
   Result := DS.DataString;
  finally
   SS.Free;
   DS.Free;
  end;
end;

{ 流加密函数, default keybit: 128bit }
function EncryptStream(Src: TStream; Key: AnsiString;
  var Dest: TStream; KeyBit: TKeyBit = kb128): Boolean;
var
  Count: Int64;
  AESKey128: TAESKey128;
  AESKey192: TAESKey192;
  AESKey256: TAESKey256;
begin
  if Dest = nil then
  begin
   raise Exception.Create(SDestStreamNotCreated);
   Result:= False;
   Exit;
  end;

  try
   Src.Position:= 0;
   Count:= Src.Size;
   Dest.Write(Count, SizeOf(Count));
   {  --  128 位密匙最大长度为 16 个字符 --  }
   if KeyBit = kb128 then
   begin
   FillChar(AESKey128, SizeOf(AESKey128), 0 );
   Move(PAnsiChar(Key)^, AESKey128, Min(SizeOf(AESKey128), Length(Key)));
   EncryptAESStreamECB(Src, 0, AESKey128, Dest);
   end;
   {  --  192 位密匙最大长度为 24 个字符 --  }
   if KeyBit = kb192 then
   begin
   FillChar(AESKey192, SizeOf(AESKey192), 0 );
   Move(PAnsiChar(Key)^, AESKey192, Min(SizeOf(AESKey192), Length(Key)));
   EncryptAESStreamECB(Src, 0, AESKey192, Dest);
   end;
   {  --  256 位密匙最大长度为 32 个字符 --  }
   if KeyBit = kb256 then
   begin
   FillChar(AESKey256, SizeOf(AESKey256), 0 );
   Move(PAnsiChar(Key)^, AESKey256, Min(SizeOf(AESKey256), Length(Key)));
   EncryptAESStreamECB(Src, 0, AESKey256, Dest);
   end;

   Result := True;
  except
   raise Exception.Create(SEncryptStreamError);
   Result:= False;
  end;
end;

{ 流解密函数, default keybit: 128bit }
function DecryptStream(Src: TStream; Key: AnsiString;
  var Dest: TStream; KeyBit: TKeyBit = kb128): Boolean;
var
  Count, OutPos: Int64;
  AESKey128: TAESKey128;
  AESKey192: TAESKey192;
  AESKey256: TAESKey256;
begin
  if Dest = nil then
  begin
   raise Exception.Create(SDestStreamNotCreated);
   Result:= False;
   Exit;
  end;

  try
   Src.Position:= 0;
   OutPos:= Dest.Position;
   Src.ReadBuffer(Count, SizeOf(Count));
   {  --  128 位密匙最大长度为 16 个字符 --  }
   if KeyBit = kb128 then
   begin
   FillChar(AESKey128, SizeOf(AESKey128), 0 );
   Move(PAnsiChar(Key)^, AESKey128, Min(SizeOf(AESKey128), Length(Key)));
   DecryptAESStreamECB(Src, Src.Size - Src.Position,
   AESKey128, Dest);
   end;
   {  --  192 位密匙最大长度为 24 个字符 --  }
   if KeyBit = kb192 then
   begin
   FillChar(AESKey192, SizeOf(AESKey192), 0 );
   Move(PAnsiChar(Key)^, AESKey192, Min(SizeOf(AESKey192), Length(Key)));
   DecryptAESStreamECB(Src, Src.Size - Src.Position,
   AESKey192, Dest);
   end;
   {  --  256 位密匙最大长度为 32 个字符 --  }
   if KeyBit = kb256 then
   begin
   FillChar(AESKey256, SizeOf(AESKey256), 0 );
   Move(PAnsiChar(Key)^, AESKey256, Min(SizeOf(AESKey256), Length(Key)));
   DecryptAESStreamECB(Src, Src.Size - Src.Position,
   AESKey256, Dest);
   end;
   Dest.Size := OutPos + Count;
   Dest.Position := OutPos;

   Result := True;
  except
   raise Exception.Create(SDecryptStreamError);
   Result:= False;
  end;
end;

{  --  文件加密函数 默认按照 128 位密匙解密 --  }
procedure EncryptFile(SourceFile, DestFile: String;
  Key: AnsiString; KeyBit: TKeyBit = kb128);
var
  SFS, DFS: TFileStream;
  Size: Int64;
  AESKey128: TAESKey128;
  AESKey192: TAESKey192;
  AESKey256: TAESKey256;
begin
  SFS := TFileStream.Create(SourceFile, fmOpenRead);
  try
   DFS := TFileStream.Create(DestFile, fmCreate);
   try
   Size := SFS.Size;
   DFS.WriteBuffer(Size, SizeOf(Size));
   {  --  128 位密匙最大长度为 16 个字符 --  }
   if KeyBit = kb128 then
   begin
   FillChar(AESKey128, SizeOf(AESKey128), 0 );
   Move(PAnsiChar(Key)^, AESKey128, Min(SizeOf(AESKey128), Length(Key)));
   EncryptAESStreamECB(SFS, 0, AESKey128, DFS);
   end;
   {  --  192 位密匙最大长度为 24 个字符 --  }
   if KeyBit = kb192 then
   begin
   FillChar(AESKey192, SizeOf(AESKey192), 0 );
   Move(PAnsiChar(Key)^, AESKey192, Min(SizeOf(AESKey192), Length(Key)));
   EncryptAESStreamECB(SFS, 0, AESKey192, DFS);
   end;
   {  --  256 位密匙最大长度为 32 个字符 --  }
   if KeyBit = kb256 then
   begin
   FillChar(AESKey256, SizeOf(AESKey256), 0 );
   Move(PAnsiChar(Key)^, AESKey256, Min(SizeOf(AESKey256), Length(Key)));
   EncryptAESStreamECB(SFS, 0, AESKey256, DFS);
   end;
   finally
   DFS.Free;
   end;
  finally
   SFS.Free;
  end;
end;

{  --  文件解密函数 默认按照 128 位密匙解密 --  }
procedure DecryptFile(SourceFile, DestFile: String;
  Key: AnsiString; KeyBit: TKeyBit = kb128);
var
  SFS, DFS: TFileStream;
  Size: Int64;
  AESKey128: TAESKey128;
  AESKey192: TAESKey192;
  AESKey256: TAESKey256;
begin
  SFS := TFileStream.Create(SourceFile, fmOpenRead);
  try
   SFS.ReadBuffer(Size, SizeOf(Size));
   DFS := TFileStream.Create(DestFile, fmCreate);
   try
   {  --  128 位密匙最大长度为 16 个字符 --  }
   if KeyBit = kb128 then
   begin
   FillChar(AESKey128, SizeOf(AESKey128), 0 );
   Move(PAnsiChar(Key)^, AESKey128, Min(SizeOf(AESKey128), Length(Key)));
   DecryptAESStreamECB(SFS, SFS.Size - SFS.Position, AESKey128, DFS);
   end;
   {  --  192 位密匙最大长度为 24 个字符 --  }
   if KeyBit = kb192 then
   begin
   FillChar(AESKey192, SizeOf(AESKey192), 0 );
   Move(PAnsiChar(Key)^, AESKey192, Min(SizeOf(AESKey192), Length(Key)));
   DecryptAESStreamECB(SFS, SFS.Size - SFS.Position, AESKey192, DFS);
   end;
   {  --  256 位密匙最大长度为 32 个字符 --  }
   if KeyBit = kb256 then
   begin
   FillChar(AESKey256, SizeOf(AESKey256), 0 );
   Move(PAnsiChar(Key)^, AESKey256, Min(SizeOf(AESKey256), Length(Key)));
   DecryptAESStreamECB(SFS, SFS.Size - SFS.Position, AESKey256, DFS);
   end;
   DFS.Size := Size;
   finally
   DFS.Free;
   end;
  finally
   SFS.Free;
  end;
end;
end.


联系电话:
020-00000000
联系电话:
020-00000000
联系电话:
020-12345678