Delphi2010中字符串汇编需要注意的一点,Delphi版的Base64转换函数
分类:高并发

(**************************************************************)
(*     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 位密匙操作                            *)
(*                                                            *)
(**************************************************************)

昨天研究了一下Delphi2010的Unicode,同时也改了几个单元到2010中来,今天下午修改AES的加密库的时候,碰到一个问题,我将AES中的StrtoHex换成了自己写的汇编函数!其他的地方,都修改好了,但是加密之后总是没有结果返回!奇怪了半天,然后我将修改后的AES放到2007下去运行是一点问题都没有!最后调试了半天,将断点定在了StrToHex这个函数内部,调试运行也没发现问题,但是这个函数就是没结果返回。还真是奇怪了,于是翻开了它自己带的AnsiStrings单元查看里面相关的函数,晕,恍然大悟,原来在AnsiString的管理时也多加了一个CodePage的设置。既然如此,那么函数需要做相应的修改了哈!主题代码如下:

unit AES;                  

前几天,兴趣所致,写了2个Delphi版的Base64转换函数,见《Delphi版的Base64转换函数》一文。后来觉得这些函数使用不够灵活,所以重新写了几个放在这里,核心的转换代码用BASM写的(不知是否快一点,不过,我觉得用汇编写这种代码好像比Pascal还容易些,因为有些二进制操作,高级语言不方便,同时使用汇编也能使算法更合理,可比较《Delphi版的Base64转换函数》代码和汇编码的注释伪代码),如果有错误和建议,请指正,本人不甚感激!

代码

interface

unit Base64;

Code highlighting produced by Actipro CodeHighlighter (freeware) 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
    add  edx,edx
    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;

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

interface

 

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

uses SysUtils, Classes;

在LStrSetLength之前要同时传入CodePage设置,这样这个函数经过这样修改之后就可以正常返回信息了!

type
  TKeyBit = (kb128, kb192, kb256);

type
{$IFDEF UNICODE}
Base64String = AnsiString;
{$ELSE}
Base64String = string;
{$ENDIF}

同时附上修改的AES代码 AES代码下载

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

// 按源长度SourceSize返回Base64编码所需缓冲区字节数
function Base64EncodeBufSize(SourceSize: Integer): Integer;
// 获取Sourec的Base64编码,Base64Buf必须有足够长度。返回实际编码字节数
function Base64Encode(const Source; SourceSize: Integer; var Base64Buf): Integer; overload;
// 将Source编码为Base64字符串返回
function Base64Encode(const Source; SourceSize: Integer): Base64String; overload;
// 将Source从StartPos开始的Size长度的内容源编码为Base64,写入流Dest。
// Size=0 表示一直编码到文件尾
procedure Base64Encode(Source, Dest: TStream; StartPos: Int64 = 0; Size: Int64 = 0,',','); overload;
// 把字符串Str编码为Base64字符串返回
{$IFDEF UNICODE}
function StrToBase64(const Str: AnsiString): Base64String; overload;
function StrToBase64(const Str: string): Base64String; overload;
{$ELSE}
function StrToBase64(const Str: string): Base64String;
{$ENDIF}

 

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

// 按给定的编码源Source和长度SourceSize计算并返回解码缓冲区所需字节数
function Base64DecodeBufSize(const Base64Source; SourceSize: Integer): Integer;
// 将Base64编码源Base64Source解码,Buf必须有足够长度。返回实际解码字节数
function Base64Decode(const Base64Source; SourceSize: Integer; var Buf): Integer; overload;
// 将Source从StartPos开始的Size长度的Base64编码内容解码,写入流Dest。
// Size=0 表示一直解码到文件尾
procedure Base64Decode(Source, Dest: TStream; StartPos: Int64 = 0; Size: Int64 = 0,',','); overload;
// 将Base64编码源Base64Source解码为字符串返回
function Base64Decode(const Base64Source; SourceSize: Integer): string; overload;
// 把Base64字符串Base64Str解码为字符串返回
function Base64ToStr(const Base64Str: Base64String): string;

来源:

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;

implementation

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

const
Base64_Chars: array[0..63] of AnsiChar = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
Base64_Bytes: array[0..79] of Byte =
(
62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0,
0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
,',',');

implementation

type
Base64Proc = function(const Source; SourceSize: Integer; var Buf): Integer;

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;

procedure Base64Stream(Source, Dest: TStream; Proc: Base64Proc;
StartPos, Size: Int64; RBufSize, WBufSize: Integer,',',');
var
RBuf: array of Byte;
WBuf: array of Byte;
RSize, WSize: Integer;
begin
if (StartPos < 0) or (StartPos >= Source.Size) then Exit;
Source.Position := StartPos;
if (Size <= 0) or (Size > Source.Size - Source.Position) then
Size := Source.Size
else
Size := Size + Source.Position;
SetLength(RBuf, RBufSize,',',');
SetLength(WBuf, WBufSize,',',');
while Size <> Source.Position do
begin
if RBufSize > Size - Source.Position then
RBufSize := Size - Source.Position;
RSize := Source.Read(RBuf[0], RBufSize,',',');
WSize := Proc(RBuf[0], RSize, WBuf[0],',',');
Dest.Write(WBuf[0], WSize,',',');
end;
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;

function Base64EncodeBufSize(SourceSize: Integer): Integer;
begin
Result := ((SourceSize + 2) div 3) shl 2;
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;

(****************************************************************************
* *
* BASE64 Encode hint: *
* *
* addr: (high) 4 byte 3 byte 2 byte 1 byte (low) *
* sourec ASCII(3 bytes): 33333333 22222222 11111111 *
* bswap: 11111111 22222222 33333333 00000000 *
* b4 = Base64_Chars[(source >> 8) & 63]: [00333333]->44444444 *
* b3 = Base64_Chars[(source >> 14) & 63]: [00222233]->33333333 *
* b2 = Base64_Chars[(source >> 20) & 63]: [00112222]->22222222 *
* b1 = Base64_Chars[source >> 26]: [00111111]->11111111 *
* b4 << 24 b3 << 16 b2 << 8 b1 *
* dest BASE64(4 bytes) 44444444 33333333 22222222 11111111 *
* *
****************************************************************************)

{  --  字符串解密函数 默认按照 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;

function Base64Encode(const Source; SourceSize: Integer; var Base64Buf): Integer;
asm
push ebp
push esi
push edi
push ebx
mov esi, eax // esi = Source
mov edi, ecx // edi = Buf
mov eax, edx
cdq
mov ecx, 3
div ecx // edx = SourceSize % 3
mov ecx, eax // ecx = SourceSize / 3
test edx, edx
jz @@1
inc eax // eax = (SourceSize + 2) / 3
@@1:
push eax
push edx
lea ebp, Base64_Chars
jecxz @Last
cld
@EncodeLoop: // while (ecx > 0){
mov edx, [esi] // edx = 00000000 33333333 22222222 11111111
bswap edx // edx = 11111111 22222222 33333333 00000000
push edx
push edx
push edx
pop ebx // ebx = edx
shr edx, 20
shr ebx, 26 // ebx = 00111111
and edx, 63 // edx = 00112222
mov ah, [ebp + edx] // *(word*)edi = (Base64_Chars[edx] << 8) |
mov al, [ebp + ebx] // Base64_Chars[ebx]
stosw // edi += 2
pop edx // edx = 11111111 22222222 33333333 00000000
pop ebx // ebx = edx
shr edx, 8
shr ebx, 14
and edx, 63 // edx = 00333333
and ebx, 63 // ebx = 00222233
mov ah, [ebp + edx] // *(word*)edi = (Base64_Chars[edx] << 8) |
mov al, [ebp + ebx] // Base64_Chars[ebx]
stosw // edi += 2
add esi, 3 // esi += 3
loop @EncodeLoop // }
@Last:
pop ecx // ecx = SourceSize % 3
jecxz @end // if (ecx == 0) return
mov eax, 3d3d0000h // preset 2 bytes '='
mov [edi], eax
test ecx, 2
jnz @@3
mov al, [esi] // if (ecx == 1)
shl eax, 4 // eax = *esi << 4
jmp @@4
@@3:
mov ax, [esi] // else
xchg al, ah // eax = ((*esi << 8) or *(esi + 1)) << 2
shl eax, 2
@@4:
add edi, ecx // edi += ecx
inc ecx // ecx = last encode bytes
@LastLoop:
mov edx, eax // for (; cex > 0; ecx --, edi --)
and edx, 63 // {
mov dl, [ebp + edx] // edx = eax & 63
mov [edi], dl // *edi = Base64_Chars[edx]
shr eax, 6 // eax >>= 6
dec edi // }
loop @LastLoop
@end:
pop eax
shl eax, 2 // return encode bytes
pop ebx
pop edi
pop esi
pop ebp
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;

function Base64Encode(const Source; SourceSize: Integer): Base64String;
begin
SetLength(Result, Base64EncodeBufSize(SourceSize),',',');
Base64Encode(Source, SourceSize, Result[1],',',');
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;

procedure Base64Encode(Source, Dest: TStream; StartPos: Int64; Size: Int64,',',');
begin
Base64Stream(Source, Dest, Base64Encode, StartPos, Size, 6144, 8192,',',');
end;

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

{$IFDEF UNICODE}
function StrToBase64(const Str: AnsiString): Base64String;
begin
Result := Base64Encode(Str[1], Length(Str),',',');
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;

function StrToBase64(const Str: string): Base64String;
begin
Result := StrToBase64(AnsiString(Str),',',');
end;
{$ELSE}
function StrToBase64(const Str: string): Base64String;
begin
Result := Base64Encode(Str[1], Length(Str),',',');
end;
{$ENDIF}

  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;

function Base64DecodeBufSize(const Base64Source; SourceSize: Integer): Integer;
asm
mov ecx, eax // ecx = Source + Size
add ecx, edx
mov eax, edx // eax = Size / 4 * 3
shr edx, 2
shr eax, 1
add eax, edx
mov edx, eax
jz @@2
@@1:
dec ecx
cmp byte ptr [ecx], 61
jne @@2 // if (*--ecx == '=')
dec eax // eax --
jmp @@1
@@2: // return eax: BufSize; edx: Size / 4 * 3
end;

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

function Base64Decode(const Base64Source; SourceSize: Integer; var Buf): Integer;
asm
push ebp
push esi
push edi
push ebx
mov esi, eax // esi = Source
mov edi, ecx // edi = Buf
mov ebx, edx
call Base64DecodeBufSize
push eax // eax = Base64DecodeBufSize(Source, SourceSize)
sub edx, eax // edx -= eax // edx: '=' count
lea ebp, Base64_Bytes
shr ebx, 2 // ebx = SourceSize / 4
test ebx, ebx
jz @end
push edx
cld
@DecodeLoop: // for (; ebx > 0; ebx --; edi += 3)
mov ecx, 4 // {
xor eax, eax
@xchgLoop: // for (ecx = 4, eax = 0; ecx > 0; ecx --)
movzx edx, [esi] // {
sub edx, 43 // edx = *(int*)esi - 43
shl eax, 6 // eax <<= 6
or al, [ebp + edx]// al |= Base64_Bytes[edx]
inc esi // esi ++
loop @xchgLoop // }
bswap eax // bswap(eax)
dec ebx // if (ebx == 1) break
jz @Last
shr eax, 8 // eax >>= 8
stosw // *edi = ax; edi += 2
shr eax, 16 // eax >>= 16
stosb // *edi++ = al
jmp @DecodeLoop // }
@Last:
pop ecx
xor ecx, 3 // ecx = last bytes
@LastLoop: // for (; ecx > 0; ecx --)
shr eax, 8 // {
stosb // eax >>= 8; *edi ++ = al
loop @LastLoop // }
@end:
pop eax // return eax
pop ebx
pop edi
pop esi
pop ebp
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;

procedure Base64Decode(Source, Dest: TStream; StartPos: Int64; Size: Int64,',',');
begin
Base64Stream(Source, Dest, Base64Decode, StartPos, Size, 8192, 6144,',',');
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.

{$IFDEF UNICODE}
function Base64Decode(const Base64Source; SourceSize: Integer): string;
var
s: AnsiString;
begin
SetLength(s, Base64DecodeBufSize(Base64Source, SourceSize),',',');
Base64Decode(Base64Source, SourceSize, s[1],',',');
Result := string(s,',',');
end;
{$ELSE}
function Base64Decode(const Base64Source; SourceSize: Integer): string;
begin
SetLength(Result, Base64DecodeBufSize(Base64Source, SourceSize),',',');
Base64Decode(Base64Source, SourceSize, Result[1],',',');
end;
{$ENDIF}

function Base64ToStr(const Base64Str: Base64String): string;
begin
Result := Base64Decode(Base64Str[1], Length(Base64Str),',',');
end;

end.

 

// 文件流的Base64测试
procedure TForm1.Button3Click(Sender: TObject,',',');
var
Source, Dest: TStream;
md5: TMessageDigest5;
Value: THashValue128;
s1, s2: string;
begin
if OpenDialog1.Execute then
begin
md5 := TMessageDigest5.Create;
try
Source := TFileStream.Create(OpenDialog1.FileName, fmOpenRead,',','); // 打开源文件
Value := md5.HashValue(Source,',','); // 取得源文件Hash
s1 := md5.AsHex(Value,',',');
Dest := TFileStream.Create('Base64EncodeTest.txt', fmCreate,',','); // Base64编码文件
try
Base64Encode(Source, Dest,',',');
finally
Source.Free;
Dest.Free;
end;
Source := TFileStream.Create('Base64EncodeTest.txt', fmOpenRead,',',');// 打开编码文件
Dest := TFileStream.Create('Base64DecodeTest.txt', fmCreate,',','); // 还原源文件内容
try
Base64Decode(Source, Dest,',',');
Dest.Position := 0;
Value := md5.HashValue(Dest,',','); // 取得还原文件Hash
s2 := md5.AsHex(Value,',',');
finally
Source.Free;
Dest.Free;
end;
finally
md5.Free;
end;
// 显示源文件和还原文件的Hash十六进制字串,如果相等,证明编码和解码过程正确
ShowMessage(s1 + #10 + s2,',',');
end;
end;

另有一点需要说明:有不少Delphi新手对本文编码(解码)过程的无类型参数感到困惑,不知该传递什么类型。其实,Delph中有不少这类无类型参数,如常用的Move过程,只要把它当着一个Byte类型的数组看待就行了,当使用string类型作实参传递给无类型形参时,要把s[1]作为参数传递(string类型下标是从1开始的),或者用指针转换,如PChar(s)^。如果是Delphi2009及以上版本,string类型作实参传递给无类型形参时,要注意不能简单的将Length(s)传递给SourceSize,而应该是Length(s) * Sizeof(char),因为Length(s)是字符串的长度,而不是实际缓冲区的长度,Delphi2009及以上版本中默认的string是WideString,char也等于WideChar,每个char占2字节。当然用string类型传递给无类型参数计算的是Unicode字符串的Base64编码,只有用AnsiString类型传递给无类型参数,或者使用StrToBase64过程(会自动转换string为AnsiString),才可能是你需要的Base64编码.

本文来自CSDN博客,转载请标明出处:

本文由10bet手机官网发布于高并发,转载请注明出处:Delphi2010中字符串汇编需要注意的一点,Delphi版的Base64转换函数

上一篇:Apache启动时无法加载php5apache2_2,error的解决方法 下一篇:Win32病毒入门,Delphi嵌入循环汇编
猜你喜欢
热门排行
精彩图文