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/
- procedure TFrmMain.btnLoadImageClick(Sender: TObject);
- var
- LInput : TMemoryStream;
- LOutput: TMemoryStream;
- begin
- // show open file dialog
- if
- dlgOpen.Execute then
- begin
- // load image into image component (TPicture)
- Image.Picture.LoadFromFile(dlgOpen.FileName);
- LInput := TMemoryStream.Create;
- LOutput := TMemoryStream.Create;
- // write picture to stream and encode
- try
- Image.Picture.SaveToStream(LInput);
- LInput.Position := 0;
- TNetEncoding.Base64.Encode( LInput, LOutput );
- LOutput.Position := 0;
- Memo.Lines.LoadFromStream( LOutput );
- finally
- LInput.Free;
- LOutput.Free;
- end;
- end;
- end;
-
- procedure TFrmMain.btnLoadTextClick(Sender: TObject);
- var
- LInput: TMemoryStream;
- LOutput: TMemoryStream;
- begin
- if dlgOpen.Execute then
- begin
- Memo.Lines.LoadFromFile(dlgOpen.FileName);
- LInput := TMemoryStream.Create;
- LOutput := TMemoryStream.Create;
- try
- Memo.Lines.SaveToStream(LInput);
- LInput.Position := 0;
- TNetEncoding.Base64.Decode( LInput, LOutput );
- LOutput.Position := 0;
- Image.Picture.LoadFromStream(LOutput);
- finally
- LInput.Free;
- LOutput.Free;
- end;
- end;
- 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.
沒有留言:
張貼留言