• 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.
  • 相关阅读:
    自助Linux之问题诊断工具strace
    Linux系统与程序监控工具atop教程
    Google C++单元测试框架(Gtest)系列教程之三——测试固件(Test fixture)
    SQLServer2005:在执行批处理时出现错误。错误消息为: 目录名无效
    无法为可更新的订阅设置发布服务器登录名
    忘记SQL SERVER帐户sa的密码
    SQL Server 2008 R2 跟踪标志
    sys.dm_os_volume_stats监控物理磁盘
    SQL SERVER 中常见的高可用方案
    Vim操作的四种模式
  • 原文地址:https://www.cnblogs.com/china1/p/3400020.html
Copyright © 2020-2023  润新知