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 [email protected] //设置新串长度
    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[[email protected]@HexChar] //转换成字符
    mov  [eax],dl      //将字符串输入到新建串中存放
    and  ebx,$0F       //获得低8位
    mov  dl,byte ptr[[email protected]@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 [email protected] //设置新串长度
  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.
时间: 2024-11-04 10:18:27

Delphi AES加密(转)的相关文章

透过 Delphi 使用二进位金钥做 AES 加密.

从 1994 年开始,笔者就开始接触加密与网路安全的世界,从鲁立忠老师的指导当中获益良多,后来在台湾的元智大学就读研究所的时候,也以此为研究主题. 在当时,电子商务是显学,Visa跟 Master Card还特别为了网路交易制作了厚厚三大本的商务通讯协定,命名为SET (Secure Electronic Transaction,安全电子交易),从客户端.商店端.银行端定义了绵绵密密的交易规范. 然而,网际网路的世界跟 Visa Master Card所熟悉的专用网路世界差的远了,不是大狗们(B

Linux进行AES加密每次结果都不一致并且解密失败报错

1. 现象 windows操作系统下进行"123456"的AES加密 encrypted message is below : QLNYZyjRnKF/zxAjzDt/lw== decrypted message is below : 123456 阿里云服务器,同样是"123456"的密码,每次加密结果都不一样,且不是QLNYZyjRnKF/zxAjzDt/lw==,解密是报错的 2.解决方法 经过检查之后,定位在生成KEY的方法上,如下: public stat

AES加密

package util; import java.io.UnsupportedEncodingException;import java.security.InvalidKeyException;import java.security.NoSuchAlgorithmException;import java.security.SecureRandom;import javax.crypto.BadPaddingException;import javax.crypto.Cipher;impo

aes加密步骤

最近学了aes加密,在这写一下自己对加密过程的理解. 1.加密采用轮秘钥加密,密钥长度一般为128bit,也对应着是16个字节.128bit的秘钥长度对应的是10轮. 首先是轮秘钥的生成,即秘钥的编排方案,先选取128bit的种子秘钥,对10轮版本的aes需要11个轮秘钥,每个轮秘钥都由16个字节组成,一个字节用两个二进制数来表示.秘钥编排算法是面向字的,即一个字4字节,32bit,即每一轮要四个字.轮秘钥的并联叫做扩展秘钥,共有44个字.每个w[i]都是一个字.未完待续,先去写秘钥编排算法.

Java aes加密C#解密的取巧方法

摘要: 项目开发过程中遇到一个棘手的问题:A系统使用java开发,通过AES加密数据,B系统使用C#开发,需要从A系统获取数据,但在AES解密的时候遇到麻烦.Java的代码和C#的代码无法互通. Java代码: /** * 加密 * * @param content 需要加密的内... 项目开发过程中遇到一个棘手的问题:A系统使用java开发,通过AES加密数据,B系统使用C#开发,需要从A系统获取数据,但在AES解密的时候遇到麻烦.Java的代码和C#的代码无法互通. Java代码: /**

非对称技术栈实现AES加密解密

非对称技术栈实现AES加密解密 正如前面的一篇文章所述,https协议的SSL层是实现在传输层之上,应用层之下,也就是说在应用层上看到的请求还是明码的,对于某些场景下要求这些http请求参数是非可读的,这就要求在前端和后端不同的技术栈上完成信息的加密解密.当然我们通常完成这样专业的功能都会考虑使用相应的框架或者程序库来完成功能,前端或者NodeJS平台通常是JavaScript语言,JavaScript主流的加密解密库分别是SjclJS和CryptoJS, 本文以CryptoJS为例进行讨论.另

王立平--AES加密图片实现 SkImageDecoder::Factory return null

这个问题是在加密图片,存入sd卡,在解密出来展示,出现的.我个人研究了非常久没解决.最后经过高人指点,最终攻克了. 在此,拿出来分享,希望各位少走弯路. 我之前的设计思路是:(能够不看哦) 1.把图片从drawable读入成bitmap 2.bitmap-->byte 3.调用AES的byte加密算法. 4.加密成byte,在转化为string 5,把string存入sd卡. -------------------------------- 4,从sd卡获取string. 5.string-->

OC与JAVA通用的AES加密解密

最近项目中用到AES加密,但在网上找了很多的库都是OC与JAVA加密后不能项目解密,因为我们的服务器是用java写的,所以不能通用对于做iOS的就是个大麻烦,Android就比较悠哉用java写所以没什么事.不过,在把度娘全身搜遍后,还是让我找到了这个库,出处记不清了,之前找了好多好多的库.下面记录下使用方法. 例子:http://pan.baidu.com/s/1dDktRPn OC调用方法: // // ViewController.m // AESTest // // Created by

Android AES加密工具类实现(基础回顾)

1 package com.powercreator.cms.util; 2 3 import java.security.SecureRandom; 4 import javax.crypto.Cipher; 5 import javax.crypto.KeyGenerator; 6 import javax.crypto.SecretKey; 7 import javax.crypto.spec.IvParameterSpec; 8 import javax.crypto.spec.Secr