Delphi RSA加解密(二)

本文详细介绍了如何使用DelphiXE10.1Berlin封装DLL以实现RSA加解密功能,同时处理了与Delphi6主程序中libeay32.dll的兼容问题。通过提供接口,DLL可以被其他低版本的Delphi程序调用,进行不同类型的RSA加密操作。文章还提供了主程序模拟示例,展示了如何在VCL应用程序中使用这些加密接口。
摘要由CSDN通过智能技术生成

dll开发环境: Delphi XE 10.1 Berlin

exe开发环境: Delphi 6

前提文章: Delphi RSA加解密(一)

目录

1. 概述

2. 准备工作

        2.1 下载DEMO程序

        2.2 字符编码说明

3. Cryption.dll封装

        3.1 接口概况

        3.2 uPub.pas单元代码

        3.3 uInterface.pas单元代码

        3.4 特别注意

4. 主程序模拟

        4.1 程序目录结构说明

        4.2 建立VCL应用程序

        4.3 接口引入单元

        4.4 接口加密验证

5. 结语


1. 概述

        公司用D6来编写三方接口,当前做某银行转账接口,采用RSA算法。在上一篇文章Delphi RSA加解密(一)中在网上找到了解决方案。

        D6版本低了,所有只有采用XE 10.1来封装dll。当前加密算法基于opelSSL,则依赖"libeay32.dll", 由于HIS程序目录下已有该dll,担心替换libeay32.dll会影响相关功能,特进行了特殊处理。

2. 准备工作

        2.1 下载DEMO程序

        在前提文章中提到了大佬分享的Demo. 下载后会发现bin目录有libeay32.dll。 这个文件很关键,后来我调试中,我使用XE 10.1对应的libeay32.dll文件,加密是不成功的。 但使用Demo的libeay32.dll进行加解密是正常的。

        2.2 字符编码说明

        原Demo的Delphi版本不确定,至少是D2010以后,版本太多了。

        悲催的是,我只有XE 10.1,下了Demo后进行部分调整。

3. Cryption.dll封装

        3.1 接口概况

        该dll开发工具我使用Delphi XE 10.1 Berlin版本.

        新建一个静态DLL工程,将原Demo的三个单元RSAOpenSSL.pas、libeay32.pas、EncdDecd_suman.pas拷贝到当前rsa目录下. 并加入当前dll工程. 另新建一个uPub.pas公共单元,新建一个uInterface.pas单元。工程目录如下

        

        具体代码在后面,相信当前还在使用Delphi的,应该已能看懂的。

        3.2 uPub.pas单元代码

unit uPub;

interface

uses
  System.SysUtils, System.Classes, qaes, qstring, IdHashMessageDigest, IdHash;

type
  TMD5= class(TIdHashMessageDigest5);

  TAppPara = class
  public
    class function AppPath: string;
    class function AppName: string;
  end;

  TFilePath = class(TAppPara)
  public
    class function IniFile: string;
  end;

//写日志
procedure systemLog(Msg: AnsiString);

implementation

procedure systemLog(Msg: AnsiString);
var
  F: TextFile;
  FileName: string;
  ExeRoad: string;
begin
  try
    ExeRoad := ExtractFilePath(ParamStr(0));
    if ExeRoad[Length(ExeRoad)] = '\' then
      SetLength(ExeRoad, Length(ExeRoad) - 1);
    if not DirectoryExists(ExeRoad + 'log') then
    begin
      CreateDir(ExeRoad + '\log');
    end;
    FileName := ExeRoad + '\log\DLL_Log' + FormatDateTime('YYMMDD', NOW) + '.txt';
    if not FileExists(FileName) then
    begin
      AssignFile(F, FileName);
      ReWrite(F);
    end
    else
      AssignFile(F, FileName);
    Append(F);
    Writeln(F, FormatDateTime('HH:NN:SS.zzz ', Now) + Msg);
    CloseFile(F);
  except
    //可能在事务中调用,避免意外
    Exit;
  end;
end;

{ TAppPara }

class function TAppPara.AppName: string;
begin
  Result := ExtractFileName(ParamStr(0));
end;

class function TAppPara.AppPath: string;
begin
  Result := ExtractFilePath(ParamStr(0));
end;

{ TFilePath }

class function TFilePath.IniFile: string;
begin
  Result := AppPath + 'set.ini';
end;

end.

        3.3 uInterface.pas单元代码

        需要注意,由于D6版本低,此处参数使用PAnsiChar。

unit uInterface;

interface

uses
  Winapi.Windows, System.SysUtils, System.Classes, EncdDecd, Qjson,
  RSAOpenSSL;

var
  FRSAOpenSSL : TRSAOpenSSL;

//----------------------------------测试部分------------------------------------
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

//测试
function dll_test: Byte; stdcall;

function dll_chinese_test(sIn: AnsiString; var sOut: PAnsiChar): Byte; stdcall;

//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

//----------------------------------加密部分------------------------------------
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

//RSA 加密 初始化
function dll_rsa_init(pubFile, priFile: PAnsiChar): Byte; stdcall;

//RSA SHA1加密
function dll_sha1_encrypt(sIn: PAnsiChar; var pOut: PAnsiChar): Byte; stdcall;

//RSA SHA256加密
function dll_sha256_encrypt(sIn: PAnsiChar; var pOut: PAnsiChar): Byte; stdcall;

//RSA SHA512加密
function dll_sha512_encrypt(sIn: PAnsiChar; var pOut: PAnsiChar): Byte; stdcall;

//RSA SHA1WITHRSA 加密
function dll_sha1withrsa_encrypt(sIn: PAnsiChar; var pOut: PAnsiChar): Byte; stdcall;

//RSA SHA256WITHRSA 加密
function dll_sha256withrsa_encrypt(sIn: PAnsiChar; var pOut: PAnsiChar): Byte; stdcall;

//RSA SHA512WITHRSA 加密
function dll_sha512withrsa_encrypt(sIn: PAnsiChar; var pOut: PAnsiChar): Byte; stdcall;

//RSA 加密 释放
function dll_rsa_uninit: Byte; stdcall;

//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<



implementation

uses uPub, qaes;

//----------------------------------测试部分------------------------------------
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

//测试
function dll_test: Byte; stdcall;
begin
  Result:= 1;
end;

function dll_chinese_test(sIn: AnsiString; var sOut: PAnsiChar): Byte; stdcall;
begin
  result:= 0;
  sOut:= PAnsiChar(sIn);
  Result:= 1;
end;

//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

//RSA 加密 初始化
function dll_rsa_init(pubFile, priFile: PAnsiChar): Byte; stdcall;
begin
  result:= 0;
  if (not FileExists(priFile))
    or (not FileExists(pubFile)) then
    Exit;
  if not Assigned(FRSAOpenSSL) then
    FRSAOpenSSL := TRSAOpenSSL.Create(AnsiString(pubFile), AnsiString(priFile));
  Result:= 1;
end;

//RSA SHA1加密
function dll_sha1_encrypt(sIn: PAnsiChar; var pOut: PAnsiChar): Byte; stdcall;
var
  sAnsiStr: AnsiString;
  sOut: AnsiString;
begin
  result:= 0;
  sAnsiStr:= UTF8Encode(sIN);
  sOut:= FRSAOpenSSL.SHA1(sAnsiStr);
  pOut:= PAnsiChar(sOut);
  Result:= 1;
end;

//RSA SHA256加密
function dll_sha256_encrypt(sIn: PAnsiChar; var pOut: PAnsiChar): Byte; stdcall;
var
  sAnsiStr: AnsiString;
  sOut: AnsiString;
begin
  result:= 0;
  sAnsiStr:= UTF8Encode(sIN);
  sOut:= FRSAOpenSSL.SHA256(sAnsiStr);
  pOut:= PAnsiChar(sOut);
  Result:= 1;
end;

//RSA SHA512加密
function dll_sha512_encrypt(sIn: PAnsiChar; var pOut: PAnsiChar): Byte; stdcall;
var
  sAnsiStr: AnsiString;
  sOut: AnsiString;
begin
  result:= 0;
  sAnsiStr:= UTF8Encode(sIN);
  sOut:= FRSAOpenSSL.SHA512(sAnsiStr);
  pOut:= PAnsiChar(sOut);
  Result:= 1;
end;

//RSA SHA1WITHRSA 加密
function dll_sha1withrsa_encrypt(sIn: PAnsiChar; var pOut: PAnsiChar): Byte; stdcall;
var
  sAnsiStr: AnsiString;
  sOut: AnsiString;
begin
  result:= 0;
  sAnsiStr:= UTF8Encode(sIn);
  sOut:= FRSAOpenSSL.SHA1_Sign_PK(sAnsiStr);
  pOut:= PAnsiChar(sOut);
  Result:= 1;
end;

//RSA SHA256WITHRSA 加密
function dll_sha256withrsa_encrypt(sIn: PAnsiChar; var pOut: PAnsiChar): Byte; stdcall;
var
  sAnsiStr: AnsiString;
  sOut: AnsiString;
begin
  result:= 0;
  sAnsiStr:= UTF8Encode(sIn);
  sOut:= FRSAOpenSSL.SHA256_Sign_PK(sAnsiStr);
  pOut:= PAnsiChar(sOut);
  Result:= 1;
end;

//RSA SHA512WITHRSA 加密
function dll_sha512withrsa_encrypt(sIn: PAnsiChar; var pOut: PAnsiChar): Byte; stdcall;
var
  sAnsiStr: AnsiString;
  sOut: AnsiString;
begin
  result:= 0;
  sAnsiStr:= UTF8Encode(sIn);
  sOut:= FRSAOpenSSL.SHA512_Sign_PK(sAnsiStr);
  pOut:= PAnsiChar(sOut);
  Result:= 1;
end;

//RSA 加密 释放
function dll_rsa_uninit: Byte; stdcall;
begin
  Result:= 0;
  if Assigned(FRSAOpenSSL) then
    FreeAndNil(FRSAOpenSSL);
  Result:= 1;
end;

//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

end.

        3.4 特别注意

        在第四章我提到了程序目录(原因请看4.1),而libeay32.pas单元的第1290行,这个里引入了libeay32.dll,但是在,在我当前设计的目录里,Cryption.dll是和libeay32.dll放在程序目录下的bin目录下,通过Demo程序调用的话,程序认定的目录其实是程序根目录,所以在这里必须特殊处理下,加入路劲:

const
  LIBEAY_DLL_NAME = 'bin\libeay32.dll';

        如果编写dll与主程序同一个目录,不担心加密的libeay32.dll影响的话,就放在程序目录下就可以了。

4. 主程序模拟

        注意: SHA1WITHRSA、SHA256WITHRSA、SHA512WITHRSA需要公私钥的支持.

        4.1 程序目录结构说明

        在文章开始部分,我已说明使用Demo的libeay32.dll可能与主程序原本的libeay32.dll冲突,所以,第三章封装的Cryptiond.dll和libeay32.dll,以及可能用到的公私钥文件,我一起放在程序的某个目录下。

        

bin目录如下所示

        

        4.2 建立VCL应用程序

        丢下控件,界面如图所示:

 主要是初始化时候,我指定了公私钥文件,就像Demo里窗体创建一样。

主窗体代码如下:

unit uFrmMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, EncdDecd;

type
  TForm2 = class(TForm)
    btn1: TButton;
    btn2: TButton;
    btn3: TButton;
    btn4: TButton;
    btn5: TButton;
    btn6: TButton;
    btn7: TButton;
    btn8: TButton;
    lbl1: TLabel;
    lbl2: TLabel;
    mmo_in: TMemo;
    mmo_out: TMemo;
    procedure btn1Click(Sender: TObject);
    procedure btn8Click(Sender: TObject);
    procedure btn2Click(Sender: TObject);
    procedure btn5Click(Sender: TObject);
    procedure btn3Click(Sender: TObject);
    procedure btn4Click(Sender: TObject);
    procedure btn6Click(Sender: TObject);
    procedure btn7Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    priFile: AnsiString;
    pubFile: AnsiString;
  end;

var
  Form2: TForm2;
  iRet: Byte;

implementation

uses uCryption;

{$R *.dfm}

procedure TForm2.btn1Click(Sender: TObject);
begin
  iRet:= 0;
  pubFile:= 'bin\apprsakey.pub';
  priFile:= 'bin\apprsakey.pri';
  iRet:= dll_rsa_init(PChar(pubFile), PChar(priFile));
  if iRet<> 1 then
    ShowMessage('初始化失败!')
end;

procedure TForm2.btn8Click(Sender: TObject);
begin
  iRet:= 0;
  iRet:= dll_rsa_uninit;
  if iRet= 1 then
    ShowMessage('释放成功!')
  else
    ShowMessage('释放失败!')
end;

procedure TForm2.btn2Click(Sender: TObject);
var
  pOut: PChar;
  sIn: string;
begin
  sIn:= StringReplace(mmo_in.Lines.Text,#13#10,'',[rfIgnoreCase,rfReplaceAll]);
  iRet:= 0;
  pOut:= nil;
  iRet:= dll_sha1_encrypt(PChar(sIn), pOut);
  if iRet=1 then
    mmo_out.Lines.Add(pOut)
  else
    ShowMessage('dll_sha1_encrypt加密失败!');
  pOut:= nil;
end;

procedure TForm2.btn5Click(Sender: TObject);
var
  pOut: PChar;
  sIn: string;
begin
  sIn:= StringReplace(mmo_in.Lines.Text,#13#10,'',[rfIgnoreCase,rfReplaceAll]);
  iRet:= 0;
  pOut:= nil;
  iRet:= dll_sha1withrsa_encrypt(PChar(sIn), pOut);
  if iRet=1 then
    mmo_out.Lines.Add(pOut)
  else
    ShowMessage('dll_sha1withrsa_encrypt加密失败!');
  pOut:= nil;
end;

procedure TForm2.btn3Click(Sender: TObject);
var
  pOut: PChar;
  sIn: string;
begin
  sIn:= StringReplace(mmo_in.Lines.Text,#13#10,'',[rfIgnoreCase,rfReplaceAll]);
  iRet:= 0;
  pOut:= nil;
  iRet:= dll_sha256_encrypt(PChar(sIn), pOut);
  if iRet=1 then
    mmo_out.Lines.Add(pOut)
  else
    ShowMessage('dll_sha256_encrypt加密失败!');
  pOut:= nil;
end;

procedure TForm2.btn4Click(Sender: TObject);
var
  pOut: PChar;
  sIn: string;
begin
  sIn:= StringReplace(mmo_in.Lines.Text,#13#10,'',[rfIgnoreCase,rfReplaceAll]);
  iRet:= 0;
  pOut:= nil;
  iRet:= dll_sha512_encrypt(PChar(sIn), pOut);
  if iRet=1 then
    mmo_out.Lines.Add(pOut)
  else
    ShowMessage('dll_sha512_encrypt加密失败!');
  pOut:= nil;
end;

procedure TForm2.btn6Click(Sender: TObject);
var
  pOut: PChar;
  sIn: string;
begin
  sIn:= StringReplace(mmo_in.Lines.Text,#13#10,'',[rfIgnoreCase,rfReplaceAll]);
  iRet:= 0;
  pOut:= nil;
  iRet:= dll_sha256withrsa_encrypt(PChar(sIn), pOut);
  if iRet=1 then
    mmo_out.Lines.Add(pOut)
  else
    ShowMessage('dll_sha256withrsa_encrypt加密失败!');
  pOut:= nil;
end;

procedure TForm2.btn7Click(Sender: TObject);
var
  pOut: PChar;
  sIn: string;
begin
  sIn:= StringReplace(mmo_in.Lines.Text,#13#10,'',[rfIgnoreCase,rfReplaceAll]);
  iRet:= 0;
  pOut:= nil;
  iRet:= dll_sha512withrsa_encrypt(PChar(sIn), pOut);
  if iRet=1 then
    mmo_out.Lines.Add(pOut)
  else
    ShowMessage('dll_sha512withrsa_encrypt加密失败!');
  pOut:= nil;
end;

end.

        4.3 接口引入单元

        需要注意dllName是按目录指定dll位置.

unit uCryption;

interface

uses
  Classes;

const
  dllName= 'bin\Cryption.dll';

  function dll_chinese_test(sIn: AnsiString; var sOut: PAnsiChar): Byte; stdcall; external dllName;


  //RSA 加密 初始化
  function dll_rsa_init(pubFile, priFile: PChar): Byte; stdcall; external dllName;

  //RSA SHA1加密
  function dll_sha1_encrypt(sIn: PChar; var pOut: PChar): Byte; stdcall; external dllName;

  //RSA SHA256加密
  function dll_sha256_encrypt(sIn: PChar; var pOut: PChar): Byte; stdcall; external dllName;

  //RSA SHA512加密
  function dll_sha512_encrypt(sIn: PChar; var pOut: PChar): Byte; stdcall; external dllName;

  //RSA SHA1WITHRSA 加密
  function dll_sha1withrsa_encrypt(sIn: PChar; var pOut: PChar): Byte; stdcall; external dllName;

  //RSA SHA256WITHRSA 加密
  function dll_sha256withrsa_encrypt(sIn: PChar; var pOut: PChar): Byte; stdcall; external dllName;

  //RSA SHA512WITHRSA 加密
  function dll_sha512withrsa_encrypt(sIn: PChar; var pOut: PChar): Byte; stdcall; external dllName;

  //RSA 加密 释放
  function dll_rsa_uninit: Byte; stdcall; external dllName;

implementation

end.

        4.4 接口加密验证

        在线SHA1 SHA-1在线加密工具 与Demo加密对比

        

        在线SHA256 sha256在线解密 在线加密 与Demo加密对比

        

        在线SHA512可验证 sha512在线解密 在线加密 与Demo加密对比

        另 SHA1WITHRSA、SHA256WITHRSA、SHA512WITHRSA在线验证不好找

        后面我本地写个对照下看看,后面补充.

        2023-02-27 更新

        今天在java里编写了服务,测试结果:

        

 

5. 结语

        仅供参考。

       

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值