亚洲免费av电影一区二区三区,日韩爱爱视频,51精品视频一区二区三区,91视频爱爱,日韩欧美在线播放视频,中文字幕少妇AV,亚洲电影中文字幕,久久久久亚洲av成人网址,久久综合视频网站,国产在线不卡免费播放

        ?

        實現(xiàn)Javascript-Delphi高強(qiáng)度加密傳輸安全

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

        曾程勝

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

        1 設(shè)計思想

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

        2 Web前端的實現(xiàn)。

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

        //引入JS庫

        3 后端的實現(xiàn)

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

        3.1 使用OPENSSL動態(tài)鏈接庫實現(xiàn)后端

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

        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的動態(tài)鏈接庫,這里須將動態(tài)鏈接庫拷貝至運(yùn)行目錄下

        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位足夠安全,過高將嚴(yán)重影響性能

        FSslCertTools.DoKeyPair;//隨機(jī)產(chǎn)生 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;

        //將公鑰發(fā)至前端

        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);//建立內(nèi)存流

        f_PEM_write_bio_PUBKEY(ABio,

        FSslCertTools.PrivateKey);//把從私鑰中導(dǎo)出公鑰并寫入內(nèi)存流

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

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

        f_bio_free(ABio);//釋放內(nèi)存流

        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;

        //將解密的字符發(fā)送至前端進(jìn)行驗證

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

        Write(t.toJSON);

        t.Free;

        end;

        end;

        3.2 使用SecureBlackbox組件實現(xiàn)

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

        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);//產(chǎn)生 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);//導(dǎo)出公鑰

        //將生成的公鑰發(fā)送到客戶端用于加密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加密的字符解密后發(fā)送至客戶端進(jìn)行驗證

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

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

        Write(t.toJSON);

        t.Free;

        end;

        end;

        4 現(xiàn)在編譯部署后運(yùn)行進(jìn)行驗證:

        解密的結(jié)果正確,驗證通過。

        [1] 王珊珊. 計算機(jī)網(wǎng)絡(luò)安全防范措施探討[J]. 軟件, 2013,(8).

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

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

        [4] Bear Bibeault, Yehuda Katz. jQuery實戰(zhàn)[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.

        宅宅午夜无码一区二区三区| 真实国产精品vr专区| 久久午夜夜伦鲁鲁片免费无码| 国产精品一区二区在线观看99| 欧美亚洲另类 丝袜综合网| 91精品国产自拍视频| 又湿又紧又大又爽a视频国产| 制服丝袜人妻中文字幕在线| 狠狠亚洲婷婷综合色香五月| 久久精品国产亚洲av热东京热| 精品国产品香蕉在线| 国产成人免费一区二区三区| 丝袜欧美视频首页在线| 美腿丝袜一区在线观看| 精品人妻伦一二三区久久| 人人澡人人澡人人看添av| 欧美 亚洲 国产 日韩 综AⅤ| 亚洲伊人伊成久久人综合| 999zyz玖玖资源站永久| 俺来也俺去啦最新在线| 亚洲 暴爽 AV人人爽日日碰| 精品亚洲一区二区三区在线播放| 无码a级毛片免费视频内谢| 六月丁香婷婷色狠狠久久| 欧美人与动牲交片免费播放| 久久久精品国产免费看| 久久久无码人妻精品无码| 99热成人精品免费久久| 一本大道加勒比东京热| 色欲色香天天天综合网www| 人禽伦免费交视频播放| 国产精品麻豆A啊在线观看| 日本韩国亚洲三级在线| 日本熟妇hdsex视频| 亚洲精品视频久久| 视频在线播放观看免费| 国产猛男猛女超爽免费视频| 日本在线观看| 亚洲女同精品久久女同| 色婷婷精品久久二区二区蜜桃| 亚洲精品无码专区在线|