999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

實現Javascript-Delphi高強度加密傳輸安全

2018-02-05 09:16:58曾程勝
軟件 2018年1期

曾程勝

(江西省撫州市臨川區政務信息化工作辦公室,江西 撫州 344000)

1 設計思想

為了保證應用前端向后端傳輸數據的安全,我們通常采用SSL加密方式,本文是在通常HTTP上實現前臺Javascript向后臺Delphi開發的服務器端傳輸數據的加密[1],防止由于第三方攻擊導致重要信息泄露。由于RSA加密[2]對明文字符長度有限制,所以設計思想是:客戶端首先向服務器端發出AJAX請求,獲取后臺隨機生的RSA加密算法的公鑰,然后客戶端隨機生成 AES對稱加密算法[3]的Key及 iv向量,當客戶端提交表單數據時,利用AES加密表單數據,再用RSA公鑰加密AES的Key、iv向量,并以jQuery POST[4]方式向后臺提交這些加密數據,最后在后臺使用RSA私鑰解密Key、iv,從而解密表單數據。

2 Web前端的實現。

前端使用了JAVASCRIPT加密庫FORGE[5],下載地址 https://github.com/digitalbazaar/forge以及forge瀏覽器支持庫 https://github.com/digitalbazaar/forge-dist,具體實現代碼如下:

//引入JS庫

3 后端的實現

下面我將分別探討使用 OPENSSL[6]動態鏈接庫及商用組件SecureBlackbox[7]實現后端處理。我這里服務器端開發采用 IIS[8]+RealThinClient[9]+ISAPI[10]方式,僅供參考。

3.1 使用OPENSSL動態鏈接庫實現后端

由于直接使用openssl動態鏈接庫不是很方便,我借助開源組件 ICS[11]進行開發,該組件完整實現了對 OPENSSL的封裝,下載地址為 http://wiki.overbyte.eu/arch/icsv8w.zip。該方案優點是性能好,處理速度快,缺點是部署時須附帶 OPENSSL動態鏈接庫。

uses

System.SysUtils, System.Classes, rtcConn,rtcDataSrv, rtcISAPISrv, rtcInfo,

rtcSys

tem,OverbyteIcsSSLEAY,OverbyteIcsMimeUtils,Over byteIcsWSocket,

Over

byteIcsSslX509Utils,OverbyteIcsLibeay,OverByteIcs MD5,OverbyteIcsTypes,

OverbyteIcsLogger,OverbyteIcsUtils;

type

TWebModule = class(TDataModule)

GetPubKey: TRtcDataProvider;

PrdWebServer: TRtcISAPIServer;

SendEncTxt: TRtcDataProvider;

procedure GetPubKeyCheckRequest(Sender:TRtcConnection);

procedure SendEncTxtCheckRequest(Sender: TRtcConnection);

procedure SendEncTxtDataReceived(Sender:TRtcConnection);

procedure DataModuleCreate(Sender: Tobject);

procedure DataModuleDestroy(Sender: Tobject);

private

{ Private declarations }

FProgDir:string;

FSslCertTools: TSslCertTools;

public

{ Public declarations }

end;

const

AES_BLOCK_SIZE = 16;

type

TAesType = (aesCbc, aesEcb);

TAesContext = packed record

Ctx : PEVP_CIPHER_CTX;

Aes : PEVP_CIPHER;

Encrypt : Boolean;//True為加密False為解密

end;

PAesContext = ^TAesContext;

function StrToHex(AStr: AnsiString): AnsiString;

var

len : Integer;

begin

len:=Length(AStr);

SetLength(Result, len*2);

BinToHex(@AStr[1], PAnsiChar(Result), len);

Result:=string.LowerCase(Result);

end;

function HexToStr(AHex: AnsiString): AnsiS-

tring;

var

len : Integer;

begin

len:=Length(AHex)div 2;

SetLength(Result, len);

HexToBin(PAnsiChar(AHex),Result[1] , len);

end;

procedure AesFinalize(var AesCtx: TAesContext);

begin

if Assigned(AesCtx.Ctx) then begin

f_EVP_CIPHER_CTX_cleanup(AesCtx.Ctx);

f_EVP_CIPHER_CTX_free(AesCtx.Ctx);

end;

FillChar(AesCtx, SizeOf(AesCtx), #0);

end;

procedure AesInitialize(

var AesCtx : TAesContext;

Key : PAnsiChar; // if not nil Pwd is ignored and the user is responsible to provide a valid Key and IV

IV : PAnsiChar;

AesType : TAesType;

Enc : Boolean);

begin

AesFinalize(AesCtx);

AesCtx.Encrypt := Enc;

case AesType of

aesCbc, aesEcb :

begin

if AesType = aesCbc then

AesCtx.Aes := f_EVP_aes_256_cbc//CBC加密方式

else begin

AesCtx.Aes := f_EVP_aes_256_ecb;//ECB加密

end;

end;

else

raise Exception.Create('Not implemented');

end;

AesCtx.Ctx := f_EVP_CIPHER_CTX_new;

if ICS_OPENSSL_VERSION_NUMBER

f_EVP_CIPHER_CTX_init(AesCtx.Ctx)

else

f_EVP_CIPHER_CTX_reset(AesCtx.Ctx);

if not f_EVP_CipherInit_ex(AesCtx.Ctx,AesCtx.Aes, nil,

@key[0],

@IV[0],

Ord(Enc)) then

raise Exception.Create('Function f_EVP_CipherInit_ex');

end;

procedure AesUpdate(

const InBuf;

InLen : Integer;

const OutBuf;

var OutLen : Integer;

AesCtx : TAesContext);

begin

if not Assigned(AesCtx.Ctx) then

raise Exception.Create('Aes context not initialized');

if not f_EVP_CipherUpdate(AesCtx.Ctx,PAnsiChar(@OutBuf), OutLen,

AnsiChar(@InBuf),InLen) then

raise Exception.Create('f_EVP_Cipher-Update')

end;

procedure AesFinal(

const OutBuf;

var OutLen : Integer;

AesCtx : TAesContext);

begin

if not Assigned(AesCtx.Ctx) then

raise Exception.Create('Aes context not initialized');

if not f_EVP_CipherFinal_ex(AesCtx.Ctx,

PAnsiChar(@OutBuf), OutLen) then raise Exception.Create('Function f_

EVP_CipherFinal_ex:');

end;

{ Takes plain text, returns an encrypted string,optionally base64 encoded }

function StrEncAES(

const S : AnsiString;

Key : PAnsiChar;

IV : PAnsiChar;

B64 : Boolean): AnsiString;

var

Len, TmpLen : Integer;

AesCtx : TAesContext;

begin

FillChar(AesCtx, SizeOf(AesCtx), #0);

AesInitialize(AesCtx, Key, IV, aesCbc, True);

try

Len := Length(S);

SetLength(Result, Len + AES_BLOCK_SIZE);

AesUpdate(S[1], Length(S), Result[1],Len, AesCtx);

AesFinal(Result[Len + 1], TmpLen,AesCtx);

Inc(Len, TmpLen);

SetLength(Result, Len);

finally

AesFinalize(AesCtx);

end;

if B64 then

Result := Base64Encode(Result)

else

Result := StrToHex(Result)

end;

function StrDecAES(

S : AnsiString;

Key : PAnsiChar;

IV : PAnsiChar;

B64 : Boolean): AnsiString;

var

Len, TmpLen : Integer;

AesCtx : TAesContext;

begin

FillChar(AesCtx, SizeOf(AesCtx), #0);

AesInitialize(AesCtx, Key, IV, aesCbc,False);

try

if B64 then

S := Base64Decode(S);

Len := Length(S);

SetLength(Result, Len + AES_BLOCK_SIZE);

AesUpdate(S[1], Length(S), Result[1],Len, AesCtx);

AesFinal(Result[Len + 1], TmpLen,

AesCtx);

Inc(Len, TmpLen);

SetLength(Result, Len);finally AesFinalize(AesCtx);

end;end;

procedure TWebModule.DataModuleCreate(Sender: TObject);

begin

//掛載OPENSSL的動態鏈接庫,這里須將動態鏈接庫拷貝至運行目錄下

FProgDir := ExtractFilePath(ParamStr(0));

GSSLEAY_DLL_IgnoreNew := False; { V8.38 don't ignore OpenSSL 1.1.0 and later }

//GSSLEAY_DLL_IgnoreNew := True; { V8.38 don't ignore OpenSSL 1.1.0 and later }

//GSSLEAY_DLL_IgnoreOld := True; { V8.38 ignore OpenSSL 1.0.2 and earlier }

GSSL_DLL_DIR := FProgDir; { V8.38 only from our directory }

//GSSL_SignTest_Check := True; { V8.38 check digitally signed }

//GSSL_SignTest_Certificate := True; { V8.38 check digital certificate }

OverbyteIcsWSocket.LoadSsl;

FSslCertTools := TSslCertTools.Create(self);

//TSslPrivKeyType(0),0--1024位,1--2048 2--3072 3--4096 4--7680 5--15360

FSslCertTools.PrivKeyType :=TSslPrivKeyType(1);//2048位足夠安全,過高將嚴重影響性能

FSslCertTools.DoKeyPair;//隨機產生 RSA公鑰及私鑰

end;

procedure TWebModule.DataModuleDestroy(Sender: TObject);

begin

FreeAndNil(FSslCertTools);

end;

//允許請求獲取公鑰

procedure TWebModule.GetPubKeyCheckRequest(Sender: TRtcConnection);

begin

with Sender as TRtcDataServer do

if UpperCase(Request.FileName)='/GETPUBKEY' then

Accept;

end;

//將公鑰發至前端

procedure TWebModule.GetPubKeyDataReceived(Sender: TRtcConnection);

var

ABio: PBIO;

Len: Integer;

PubKey:string;

t:TRtcRecord;

begin

with Sender as TRtcDataServer do

if Request.Complete then

begin

ABio := f_BIO_new(f_BIO_s_mem);//建立內存流

f_PEM_write_bio_PUBKEY(ABio,

FSslCertTools.PrivateKey);//把從私鑰中導出公鑰并寫入內存流

Len := f_BIO_ctrl(ABio, BIO_CTRL_PENDING, 0, nil);

PubKey := String(FSslCertTools.ReadStr-Bio(ABio, Len));{ V8.41 }

f_bio_free(ABio);//釋放內存流

Re

sponse.ContentType:='application/json';

t:=TRtcRecord.Create;

t.asText['pubkey']:=PubKey;

Write(t.toJSON);

t.Free;

end;

end;

procedure TWebModule.SendEncTxtCheckRequest(Sender: TRtcConnection);

begin

with Sender as TRtcDataServer do

if UpperCase(Request.FileName)='/SENDENCTXT' then

Accept;

end;

procedure TWebModule.SendEncTxtDataReceived(Sender: TRtcConnection);

var

CipherText:AnsiString;

Key:AnsiString;

IV:AnsiString;

t:TRtcRecord;

begin

with Sender as TRtcDataServer do

if Request.Complete then

begin

Request.Params.AddText(Read);

Key:=AnsiString(StrDecRsa(FSslCertTools.Priva teKey, AnsiString(TNetEncoding.URL.Decode(Request.Params['key'])),True));

IV:=AnsiString(StrDecRsa(FSslCertTools.PrivateKey, AnsiString(TNetEncoding.URL.Decode(Request.Params['iv'])),True));

CipherText:=AnsiString(Request.Params['encrypted']);

Response.ContentType:='application/json';

t:=TRtcRecord.Create;

//將解密的字符發送至前端進行驗證

t.asText['str']:=StrDecAES(HexToStr(CipherText),PAnsiChar(HexToStr(Key)),PAnsiChar(HexToStr(IV)),False);

Write(t.toJSON);

t.Free;

end;

end;

3.2 使用SecureBlackbox組件實現

此方案優點是部署無須附帶額外文件,缺點就是處理速度稍慢,并且此組件正版費用較高。

uses

System.SysUtils, System.Classes, rtcConn,rtcDataSrv, rtcISAPISrv, rtcInfo,

rtcSystem,SBTypes, SBUtils, SBSymmetric-Crypto, SBConstants, SBHashFunction,

SBEncoding, SBRandom, SBPublicKeyCrypto,SBX509,System.NetEncoding;

type

TWebModule = class(TDataModule)

GetPubKey: TRtcDataProvider;

PrdWebServer: TRtcISAPIServer;

SendEncTxt: TRtcDataProvider;

procedure GetPubKeyCheckRequest(Sender:TRtcConnection);

procedure GetPubKeyDataReceived(Sender:TRtcConnection);

procedure SendEncTxtCheckRequest(Sender: TRtcConnection);

procedure SendEncTxtDataReceived(Sender:TRtcConnection);

procedure DataModuleCreate(Sender: TObject);

procedure DataModuleDestroy(Sender: Tobject);

private

{ Private declarations }

FFactory : TElSymmetricCryptoFactory;

RSAKeyMaterial: TElRSAKeyMaterial;

RSACrypto : TElRSAPublicKeyCrypto;

function CreateKeyMaterial(AESKey:AnsiString;AESIV:AnsiString): TelSymmetricKeyMaterial;

public

{ Public declarations }end;

function TWebModule.CreateKeyMaterial(AESKey:AnsiString;AESIV:AnsiString): TelSymmetricKeyMaterial;

var

IV, Key : ByteArray;

Size : integer;

begin

if (Length(AESKey) <> 256 div 4) or(Length(AESIV) <> 128 div 4) then

raise Exception.Create('Empty or invalid Key/IV value!');

SetLength(IV, 16);

Size := 16;

SBUtils.StringToBinary(AESIV, @IV[0], Size);

SetLength(IV, Size);

SetLength(Key, 32);

Size := 32;

SBUtils.StringToBinary(AESKey, @Key[0], Size);

SetLength(Key, Size);

Result := TElSymmetricKeyMaterial.Create;

Result.Key := Key;

Result.IV := IV;

end;

procedure TWebModule.DataModuleCreate(Sender: TObject);

begin

FFactory := TElSymmetricCryptoFactory.Create;

RSAKeyMaterial := TElRSAKeyMaterial.Create;

RSAKeyMaterial.PEMEncode:=True;//編碼公鑰私鑰

RSAKeyMaterial.Generate(2048);//產生 2048位密鑰

RSACrypto := TElRSAPublicKeyCrypto.Create();

RSACrypto.KeyMaterial := RSAKeyMaterial;

end;

procedure TWebModule.DataModuleDestroy(Sender: TObject);

begin

FreeAndNil(FFactory);

FreeAndNil(RSAKeyMaterial);

FreeAndNil(RSACrypto);

end;

procedure TWebModule.GetPubKeyCheckRequest(Sender: TRtcConnection);

begin

with Sender as TRtcDataServer do

if UpperCase(Request.FileName)='/GETPUBKEY' then

Accept;

end;

procedure TWebModule.GetPubKeyDataReceived(Sender: TRtcConnection);

var

KeyStream:TStringStream;

t:TRtcRecord;

begin

with Sender as TRtcDataServer do

if Request.Complete then

begin

KeyStream:=TStringStream.Create;

RSAKeyMate

rial.SavePublic(KeyStream);//導出公鑰

//將生成的公鑰發送到客戶端用于加密AES KEY IV

Response.ContentType:='application/json';

t:=TRtcRecord.Create;

t.asText['pubkey']:=KeyStream.DataString;

Write(t.toJSON);

t.Free;

FreeAndNil(KeyStream);

end;

end;

procedure TWebModule.SendEncTxtCheckRequest(Sender: TRtcConnection);

begin

with Sender as TRtcDataServer do

if UpperCase(Request.FileName)='/SENDENCTXT' then

Accept;

end;

procedure TWebModule.SendEncTxtDataReceived(Sender: TRtcConnection);

var

Crypto : TElSymmetricCrypto;

KeyMaterial : TElSymmetricKeyMaterial;

InBuf, OutBuf : ByteArray;

//BufSt : AnsiString;

CipherSize:Integer;

OutSize : integer;

Key:AnsiString;

IV:AnsiString;

CipherText:AnsiString;

DecryptedStr:AnsiString;

InputStream:TStringStream;

OutputStream:TStringStream;

t:TRtcRecord;

begin

with Sender as TRtcDataServer do

if Request.Complete then

begin

Request.Params.AddText(Read);

//用RSA私鑰解密出AES的KEY IV

RSACrypto.InputEncoding := pkeBase64;//輸入流編碼方式

RSACrypto.OutputEncoding := pkeBinary;//輸出流編碼方式

InputStream:=TStringStream.Create(AnsiString(TNet-

Encoding.URL.Decode(Request.Params['key'])));

OutputStream:= TStringStream.Create;

RSACrypto.Decrypt(InputStream, OutputStream);

Key:=OutputStream.DataString;InputStream:=TStringStream.Create(AnsiString(Tnet-Encoding.URL.Decode(Request.Params['iv'])));

OutputStream:= TStringStream.Create;

RSACrypto.Decrypt(InputStream, OutputStream);

IV:=OutputStream.DataString;

FreeAndNil(InputStream);

FreeAndNil(OutputStream);

//用KEY IV解密字符串

Cipher-

Text:=AnsiString(Request.Params['encrypted']);

Crypto := FFactory.CreateInstance(SB_ALGORITHM_CNT_AES256, cmCBC);

CipherSize:=Length(CipherText) div 2;

SetLength(InBuf,CipherSize);

SBU-

tils.StringToBinary(CipherText,@InBuf[0],CipherSize);

KeyMaterial := CreateKeyMaterial(Key,IV);

Crypto.KeyMaterial := KeyMaterial;

OutSize := 0;

Crypto.Decrypt(@InBuf[0],Length(InBuf), nil, OutSize);

SetLength(OutBuf, OutSize);

Crypto.Decrypt(@InBuf[0],Length(InBuf), @OutBuf[0], OutSize);

SetLength(OutBuf, OutSize);

DecryptedStr := SBUtils.AnsiStringOf-Bytes(OutBuf);

FreeAndNil(KeyMaterial);

FreeAndNil(Crypto);

//將AES加密的字符解密后發送至客戶端進行驗證

Response.ContentType:='application/json';t:=TRtcRecord.Create;

t.asText['str']:=DecryptedStr;

Write(t.toJSON);

t.Free;

end;

end;

4 現在編譯部署后運行進行驗證:

解密的結果正確,驗證通過。

[1] 王珊珊. 計算機網絡安全防范措施探討[J]. 軟件, 2013,(8).

[2] 馬玉琢, 郭玉翠. 基于3DES和RSA的Android系統短信加密設計與實現[J], 軟件, 2016, (6).

[3] Daryl Miller, 辛磊夫. 網絡安全比加密更重要[J]. 軟件,2007, (1).

[4] Bear Bibeault, Yehuda Katz. jQuery實戰[D]. 人民郵電出版社. 2010.

[5] GitHub-digitalbazaar/forge. https://github.com/digitalbazaar/forge.

[6] openssl Cryptography and SSL/TLS Toolkit. https://www.openssl.org/.

[7] SecureBlackbox. https://www.secureblackbox. com/.

[8] Internet Information Services Development. https://msdn.microsoft.com/en-us/library/ms692515(v=vs. 90).Aspx.

[9] RTC HTTP Server in 199 lines of code. http://www. realthinclient.com/write-a-robust-cross-platform-server-in-199- lines/.

[10] ISAPI Extension Overview. https://msdn.microsoft.com/en-us/library/ms525172(v=vs. 90). Aspx.

[11] Internet Component Suite. http://wiki.overbyte.eu/wiki/index.php/Main_Page.

主站蜘蛛池模板: 国产97视频在线| 毛片免费在线视频| 久久综合丝袜长腿丝袜| 久久久久国产精品免费免费不卡| 2020亚洲精品无码| 亚洲欧美日韩中文字幕一区二区三区 | 最新亚洲人成网站在线观看| 超碰aⅴ人人做人人爽欧美| 自拍偷拍欧美日韩| 中文字幕久久波多野结衣| 色男人的天堂久久综合| 久久久久免费精品国产| 女同国产精品一区二区| 欧美区日韩区| 538国产在线| 久久青草免费91观看| 免费无码网站| 香港一级毛片免费看| 91外围女在线观看| 免费三A级毛片视频| 久久国产高潮流白浆免费观看| 欧美另类第一页| 亚洲av色吊丝无码| 国产精品白浆在线播放| 丝袜美女被出水视频一区| 亚洲高清免费在线观看| 国产精品va免费视频| 九色综合视频网| 1769国产精品免费视频| 九九免费观看全部免费视频| 国产三级成人| 欧美另类视频一区二区三区| 色综合国产| 久久6免费视频| 亚洲欧洲日韩久久狠狠爱| 日本人妻一区二区三区不卡影院| 欧美亚洲香蕉| 91无码视频在线观看| 国产免费怡红院视频| 露脸真实国语乱在线观看| 国产在线高清一级毛片| 试看120秒男女啪啪免费| 五月激情婷婷综合| 免费看一级毛片波多结衣| 国产成人亚洲欧美激情| 亚洲天堂视频在线观看免费| 91青青在线视频| 亚洲美女高潮久久久久久久| 国产精品视频a| 福利国产在线| 浮力影院国产第一页| 日韩123欧美字幕| 亚洲欧美日韩成人高清在线一区| 国产精品欧美在线观看| 欧美精品啪啪| 免费女人18毛片a级毛片视频| 亚洲精品无码抽插日韩| 精品久久久久久久久久久| 在线另类稀缺国产呦| 午夜视频免费试看| 亚洲欧美日韩视频一区| 午夜啪啪网| 国产一二三区视频| 无码国产偷倩在线播放老年人| 欧美日韩国产成人高清视频| 国产激情无码一区二区APP| 欧美翘臀一区二区三区| 日韩福利在线观看| 久久香蕉国产线看观看式| 99re视频在线| 国产欧美日韩资源在线观看| 中文字幕人妻av一区二区| 国产簧片免费在线播放| 亚洲天堂精品视频| 国产乱人免费视频| 亚洲综合色婷婷| 毛片在线看网站| 亚洲无码一区在线观看| 日韩一区二区三免费高清| 日本黄色不卡视频| 亚洲人人视频| 欧美日本在线观看|