2022年4月26日 星期二

Base64 Image System.NetEncoding.TBase64Encoding

https://github.com/emn178/hi-base64

 https://github.com/whatwg/wattsi/blob/main/src/lib/base64encoder.pas

 https://docwiki.embarcadero.com/Libraries/Sydney/en/System.NetEncoding.TBase64Encoding

unction BaseImage(fn: string): string;
var
    m1: TMemoryStream;
    m2: TStringStream;
    str: string;
begin
    m1 := TMemoryStream.Create;
    m2 := TStringStream.Create('');
    m1.LoadFromFile(fn);
    EncdDecd.EncodeStream(m1, m2);                       
    str := m2.DataString;
    str := StringReplace(str, #13, '', [rfReplaceAll]); 
    str := StringReplace(str, #10, '', [rfReplaceAll]);
    result := str;                                      
    m1.Free;
    m2.Free;
end;

 https://flixengineering.com/archives/270

 http://www.delphimagazine.com/2019/05/21/5-minute-snack-base64-encode-and-decode-images-in-delphi/

  1. procedure TFrmMain.btnLoadImageClick(Sender: TObject);
  2. var
  3. LInput : TMemoryStream;
  4. LOutput: TMemoryStream;
  5. begin
  6. // show open file dialog
  7. if
  8. dlgOpen.Execute then
  9. begin
  10. // load image into image component (TPicture)

  11. Image.Picture.LoadFromFile(dlgOpen.FileName);
  12. LInput := TMemoryStream.Create;
  13. LOutput := TMemoryStream.Create;

  14. // write picture to stream and encode
  15. try
  16. Image.Picture.SaveToStream(LInput);
  17. LInput.Position := 0;
  18. TNetEncoding.Base64.Encode( LInput, LOutput );
  19. LOutput.Position := 0;
  20. Memo.Lines.LoadFromStream( LOutput );
  21. finally
  22. LInput.Free;
  23. LOutput.Free;
  24. end;
  25. end;
  26. end;
  27.  

 

  1. procedure TFrmMain.btnLoadTextClick(Sender: TObject);
  2. var
  3. LInput: TMemoryStream;
  4. LOutput: TMemoryStream;
  5. begin
  6. if dlgOpen.Execute then
  7. begin
  8. Memo.Lines.LoadFromFile(dlgOpen.FileName);
  9. LInput := TMemoryStream.Create;
  10. LOutput := TMemoryStream.Create;

  11. try
  12. Memo.Lines.SaveToStream(LInput);
  13. LInput.Position := 0;
  14. TNetEncoding.Base64.Decode( LInput, LOutput );
  15. LOutput.Position := 0;
  16. Image.Picture.LoadFromStream(LOutput);
  17. finally
  18. LInput.Free;
  19. LOutput.Free;
  20. end;
  21. end;
  22. end;

unit uPublicSHA256WithRsa;

interface

uses Winapi.Windows,System.Classes, System.SysUtils,libeay32,ComObj;


const
  BIO_FLAGS_BASE64_NO_NL = $100;

type
  TSHA1Buffer = array [1..20] of byte;
  TSHA256Buffer= array[1..32] of Byte;
  TRSA_Buf_1024 = array[1..128] of byte; //1024bit RSA 樓躇怀堤
  TRSA_Buf_2048 = array[1..256] of byte; //2048bit RSA 樓躇怀堤

  TAES_Key_128 = array[1..16] of byte;

  TMD5_Digest = array[1..16] of byte;//md5 靡賦彆

  THA256_Digest = array[1..16] of byte; //SHA256 靡賦彆


  PsfAES_CBC_Data=^TsfAES_CBC_Data;
  TsfAES_CBC_Data = record
    InBuf:Pointer;
    InLen:Integer;
    Key:TAES_Key_128;
    ivec:TAES_Key_128;
  end;

  psfRSA = ^libeay32.RSA;

  TSHA256WithRSAOpenSSL=class
  protected
    FstrPublicKey:AnsiString;
    FstrPrivateKey:AnsiString;
  protected
   
    function base64_decode(Data:PAnsiChar;DataLen:Cardinal;bSingleRow:Boolean=FALSE):AnsiString;
 
    function base64_encode(Data:Pointer;Len:Integer;bSingleRow:Boolean=FALSE):AnsiString;

    function LoadPublicKey(PUBLIC_Key:AnsiString):pEVP_PKEY;
    function LoadPrivateKey(PRIVATE_Key:AnsiString):pEVP_PKEY;
  public
    function SHA256WithRSASign(const TextBuf:PAnsiChar;BufLen:Integer):AnsiString;
    function SHA256WithRSASign_verify(Data:PAnsichar;RsaSign:PAnsichar):Boolean;

    constructor Create(PUBLIC_Key,PRIVATE_Key:AnsiString);
    destructor Destroy; override;
  end;


implementation

uses
  uLogThread;

{ TSHA256WithRSAOpenSSL }

function TSHA256WithRSAOpenSSL.base64_decode(Data: PAnsiChar; DataLen: Cardinal;
  bSingleRow: Boolean): AnsiString;
var
  BIO,b64:PBIO;
  L:Integer;
begin
  b64 := Libeay32.BIO_new(BIO_f_base64());
  if bSingleRow then
    BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
  bio := Libeay32.BIO_new_mem_buf(Data,DataLen);
  bio := Libeay32.BIO_push(b64, bio);
  SetLength(Result,DataLen);
  L := Libeay32.BIO_read(bio,PAnsichar(Result),Length(Result));
  SetLength(Result,L);
  Libeay32.BIO_free_all(bio);

end;

function TSHA256WithRSAOpenSSL.base64_encode(Data: Pointer; Len: Integer;
  bSingleRow: Boolean): AnsiString;
var
  bio,b64:libeay32.pBIO;
  bptr: libeay32.PBUF_MEM ;
  pbptr:libeay32.PPBUF_MEM;
  I:Integer;
begin
  b64 := libeay32.BIO_new(BIO_f_base64());
  TRY
    if bSingleRow then
    begin
      libeay32.BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
    end;

    bio := libeay32.BIO_new(BIO_s_mem());

    b64 := BIO_push(b64, bio);

    I := libeay32.BIO_write(b64, Data, Len);
    if I < 0 then
      Exit;
    I := libeay32.BIO_flush(b64);

    pbptr := @bptr;
    I := libeay32.BIO_get_mem_ptr(b64, pbptr); //頗蔚BIO_C_GET_BUF_MEM_PTR紱釬換菰跤bio
    if I < 0 then
    begin
      Result := '';
      Exit;
    end;

    SetLength(Result,bPtr^.length);
    Move(bPtr^.data^,Result[1],bPtr^.length);
  FINALLY
    libeay32.BIO_Free_All(b64); //坻頗庋溫淕跺蟈沭
  END;

end;

constructor TSHA256WithRSAOpenSSL.Create(PUBLIC_Key, PRIVATE_Key: AnsiString);
begin
  try
    OpenSSL_add_all_algorithms;
    OpenSSL_add_all_ciphers;
    OpenSSL_add_all_digests;
    ERR_load_crypto_strings;
    ERR_load_RSA_strings;

    FstrPublicKey :=PUBLIC_Key;
    FstrPrivateKey :=PRIVATE_Key;

    if FstrPublicKey='' then
      raise Exception.Create('PublicKey Invalid');

    if FstrPrivateKey='' then
      raise Exception.Create('Privatekey Invalid');
  except
    on e:Exception do
    begin
      aiLog.Info(Format('[TSHA256WithRSAOpenSSL.Create][message=%s]',[e.Message]));
      raise e;
    end;
  end;
end;

destructor TSHA256WithRSAOpenSSL.Destroy;
begin
  try
    EVP_cleanup;
    ERR_free_strings;
    inherited;
  except
    on e:Exception do
    begin
      aiLog.Info(Format('[TSHA256WithRSAOpenSSL.Destroy]',[e.Message]));
      raise e;
    end;
  end;
end;


function TSHA256WithRSAOpenSSL.LoadPrivateKey(
  PRIVATE_Key: AnsiString): pEVP_PKEY;
var
  keyBO : PBIO;
  aRsa:pEVP_PKEY;
  iRet:integer;
begin
  aRsa :=nil;
  keyBO :=nil;

  keyBO := BIO_new_mem_buf(PAnsiChar(PRIVATE_Key),Length(PAnsiChar(PRIVATE_Key)));
  try
    Result := PEM_read_bio_PrivateKey(keyBO,aRsa,nil,nil);
  finally
    BIO_free_all(keyBO);
  end;
end;

function TSHA256WithRSAOpenSSL.LoadPublicKey(PUBLIC_Key: AnsiString): pEVP_PKEY;
var
  keyBO: PBIO;
  aRsa:pEVP_PKEY;
begin

  aRsa :=nil;
  keyBO :=nil;

  keyBO := BIO_new_mem_buf(PAnsiChar(PUBLIC_Key),Length(PAnsiChar(PUBLIC_Key)));
  try
    Result :=PEM_read_bio_PUBKEY(keyBO,aRsa,nil,nil)
  finally
    BIO_free_all(keyBO);
  end;
end;

function TSHA256WithRSAOpenSSL.SHA256WithRSASign(const TextBuf: PAnsiChar;
  BufLen: Integer): AnsiString;
var
  outSHA256: TSHA256Buffer;
  RSA_SignBinValue: TRSA_Buf_2048;
  CTX:EVP_MD_CTX;
  mLen:cardinal;
  SigLen,iRet:Integer;
  priKey:pEVP_PKEY;
begin
  ZeroMemory(@outSHA256,Length(outSHA256));
  ZeroMemory(@RSA_SignBinValue,Length(RSA_SignBinValue));

  priKey :=LoadPrivateKey(FstrPrivateKey);

  if priKey=nil then exit;

  EVP_MD_CTX_init(@CTX);
  try
    EVP_SignInit(@CTX,EVP_sha256());
    EVP_SignUpdate(@CTX,TextBuf,BufLen);
    EVP_DigestFinal(@CTX,@outSHA256,mLen);
    iRet := libeay32.RSA_sign(EVP_sha256()._type,
                                @outSHA256,
                                mLen,
                                @RSA_SignBinValue,
                                @SigLen,
                                priKey.pkey.rsa);

    if iRet > 0 then
      Result := base64_encode(@RSA_SignBinValue,SizeOf(RSA_SignBinValue),TRUE);
  finally
    EVP_PKEY_free(priKey);
    EVP_MD_CTX_cleanup(@CTX);
  end;
end;

function TSHA256WithRSAOpenSSL.SHA256WithRSASign_verify(Data,
  RsaSign: PAnsichar): Boolean;
var
  Sha256Buf:TSHA256Buffer;
  ctx: EVP_MD_CTX;
  RsaBuf: AnsiString;
  mlen: DWORD;
  iRet: Integer;
  pEVPKey:pEVP_PKEY;
begin
  Result :=false;
  pEVPKey :=LoadPublicKey(FstrPublicKey);

  if pEVPKey=nil then Exit;

  RSA_memory_lock(pEVPKey.pkey.rsa);
  libeay32.EVP_MD_CTX_init(@ctx);
  try
    EVP_SignInit(@ctx,EVP_sha256());
    EVP_SignUpdate(@ctx,Data,StrLen(Data));
    EVP_DigestFinal(@ctx,@Sha256Buf,mlen);
    RsaBuf := base64_decode(RsaSign,StrLen(RsaSign),TRUE);
    iRet := RSA_verify(EVP_sha256()._type,@Sha256Buf,SizeOf(Sha256Buf),PAnsichar(RsaBuf),Length(RsaBuf),pEVPKey.pkey.rsa);
    Result := (iRet = 1);
  finally
    EVP_PKEY_free(pEVPKey);
    libeay32.EVP_MD_CTX_cleanup(@ctx);
  end;
end;

end.

沒有留言: