Delphi XE RSA Demo


var
  vSignSrc, vPrivateKey: string;
begin
  vSignSrc:= 'data=<xml><treatment_id>88888</treatment_id><merchant_no>109900040300</merchant_no>'+
    '<sub_merchant></sub_merchant><username>张华</username><order_no>12345678901</order_no>'+
    '<paytype>2</paytype><trade_type>2</trade_type><total_amt>0.01</total_amt>'+
    '<spbill_create_ip>127.0.0.1</spbill_create_ip><paytimeout>6</paytimeout>'+
    '<order_subject></order_subject><order_detail>缴费</order_detail>'+
    '<auth_code>填入微信二维码上的一串号码(paytype=2刷卡付(B扫C)需要填写本参数)</auth_code>'+
    '<remark></remark></xml>&developerId=76555&funcId=P7001';


  vPrivateKey:= Memo2.Lines.Text;
  vPrivateKey:= vPrivateKey
    .Replace('-----BEGIN RSA PRIVATE KEY-----','',[rfReplaceAll])
    .Replace('-----END RSA PRIVATE KEY-----','',[rfReplaceAll])
    .Replace(#13#10,'',[rfReplaceAll])
    .Replace(' ','',[rfReplaceAll]);
  with TStringBuilder.Create do
  try
    Append('-----BEGIN RSA PRIVATE KEY-----');
    AppendLine;
    while not vPrivateKey.IsEmpty do
    begin
      Append(vPrivateKey.Substring(0,64));
      AppendLine;
      vPrivateKey:= vPrivateKey.Substring(64);
    end;
    Append('-----END RSA PRIVATE KEY-----');
    vPrivateKey:= ToString;
  finally
    Free;
  end;
  Memo3.Text:= TOpenSSLCipher.Sha1WithRSASign(vSignSrc, TEncoding.UTF8, vPrivateKey)
    .Replace('+','%2B',[rfReplaceAll])
    .Replace('=','%3D',[rfReplaceAll])
    .Replace(#13#10,'',[rfReplaceAll]);
end;

 

 

unit OpenSSL.Cipher;

interface
uses
  SysUtils,
  Classes,
  Windows,
  NetEncoding,
  IdGlobal,
  libeay32
  {IdSSLOpenSSLHeaders};

type
  TOpenSSLCipher = class
  private
    class procedure LoadLib();
  protected
    class function RSASign(APEVP_MD: PEVP_MD; const AContent: string; ACotentEncoding: TEncoding; ARSA: PRSA): string; overload;
    class function RSASign(APEVP_MD: PEVP_MD; const AContent: string; ACotentEncoding: TEncoding; const APrivateKey: string): string;overload;
    class function GetPrivateRSAKey(APBIO: PBIO): PRSA;
  public
    class function Sha1WithRSASign(const AContent: string; ACotentEncoding: TEncoding; const APrivateKey: string): string;
  end;

implementation

class procedure TOpenSSLCipher.LoadLib;
begin
  if not Load() then
    raise Exception.Create('加载ssl库时出错,请检查ssl库文件是否存在或正确!');
end;

class function TOpenSSLCipher.GetPrivateRSAKey(APBIO: PBIO): PRSA;
begin
  Result := PEM_read_bio_RSAPrivateKey(APBIO, nil, nil, nil);
  if Result = nil then
    raise Exception.Create('生成RSA密钥对象失败');
end;

class function TOpenSSLCipher.RSASign(APEVP_MD: PEVP_MD; const AContent: string; ACotentEncoding: TEncoding; ARSA: PRSA): string;
var
  vCtx: EVP_MD_CTX;
  vStringStream: TStringStream;
  vMemoStream: TMemoryStream;
  vHashedDataLen, vSignedDataLen: cardinal;
  vHashedData, vSignedData: array [0 .. 10240] of byte;
begin
  if ARSA = nil then
    raise Exception.Create('RSA签名前出错:RSA密钥为空');

  if ACotentEncoding = nil then
    ACotentEncoding := TEncoding.UTF8;

  vStringStream := TStringStream.Create(AContent, ACotentEncoding);
  vMemoStream := TMemoryStream.Create;
  try
    EVP_MD_CTX_init(@vCtx);
    EVP_SignInit(@vCtx, APEVP_MD);
    EVP_SignUpdate(@vCtx, @vStringStream.Bytes[0], vStringStream.Size);
    EVP_DigestFinal_ex(@vCtx, PIdAnsiChar(@vHashedData[0]), vHashedDataLen);
    RSA_sign(APEVP_MD._type, PIdAnsiChar(@vHashedData[0]), vHashedDataLen, PIdAnsiChar(@vSignedData[0]), @vSignedDataLen, ARSA); // 64为SHA1的NID
    EVP_MD_CTX_cleanup(@vCtx);
    Result := TNetEncoding.Base64.EncodeBytesToString(@vSignedData[0], vSignedDataLen);
  finally
    vStringStream.Free;
    vMemoStream.Free;
  end;
end;

class function TOpenSSLCipher.RSASign(APEVP_MD: PEVP_MD; const AContent: string; ACotentEncoding: TEncoding; const APrivateKey: string): string;
var
  vP_BioKey: PBIO;
  vP_Rsa: PRSA;
  vPrivateKeyStream: TStringStream;
begin
  LoadLib();
  vPrivateKeyStream := TStringStream.Create(APrivateKey, TEncoding.ASCII);
  try
    vP_BioKey := BIO_new_mem_buf(vPrivateKeyStream.Memory, vPrivateKeyStream.Size);
    vP_Rsa := GetPrivateRSAKey(vP_BioKey);
    Result := RSASign(APEVP_MD, AContent, ACotentEncoding, vP_Rsa);
    BIO_free(vP_BioKey);
  finally
    vPrivateKeyStream.Free;
  end;
end;

class function TOpenSSLCipher.Sha1WithRSASign(const AContent: string; ACotentEncoding: TEncoding; const APrivateKey: string): string;
begin
  LoadLib();
  Result := RSASign(EVP_sha1(), AContent, ACotentEncoding, APrivateKey);
end;


end.

 

 

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页