博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Delphi AES加密(转)
阅读量:5166 次
发布时间:2019-06-13

本文共 11143 字,大约阅读时间需要 37 分钟。

(*
************************************************************
*)
(*
     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.

转载于:https://www.cnblogs.com/GarfieldTom/archive/2012/08/30/2664249.html

你可能感兴趣的文章
Python操作SQLite数据库的方法详解
查看>>
实验二:编写输出"Hello World!"
查看>>
菜单和工具条(二)
查看>>
hadoop17---RPC和Socket的区别
查看>>
[BZOJ 3531] [Sdoi2014] 旅行 【离线+LCT】
查看>>
使用JMeter代理录制app测试脚本
查看>>
MVC 未启用角色管理功能
查看>>
Linq to Object实现分页获取数据
查看>>
mac常用系统命令
查看>>
第42章:MongoDB-集群--Sharding(分片)--单机的搭建
查看>>
异步执行js脚本——防止阻塞
查看>>
利用Excel导出sql语句
查看>>
android上传文件到服务器
查看>>
我回答了90%的面试题,为什么还被拒?
查看>>
Html - Table 表头固定和 tbody 设置 height 在IE不起作用的解决
查看>>
iOS SVN终端指令
查看>>
Linux如何更新软件源
查看>>
NYOJ-289 苹果 又是一个典型的01背包和上题一样没啥好说的
查看>>
HDU 2262 回溯算法 递归枚举
查看>>
九度0J 1374 所有员工年龄排序
查看>>