• 
    

    
    

      99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看 ?

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

      2018-02-05 09:16:58曾程勝
      軟件 2018年1期
      關(guān)鍵詞:表單私鑰公鑰

      曾程勝

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

      1 設(shè)計(jì)思想

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

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

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

      //引入JS庫(kù)

      3 后端的實(shí)現(xiàn)

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

      3.1 使用OPENSSL動(dòng)態(tài)鏈接庫(kù)實(shí)現(xiàn)后端

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

      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的動(dòng)態(tài)鏈接庫(kù),這里須將動(dòng)態(tài)鏈接庫(kù)拷貝至運(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位足夠安全,過(guò)高將嚴(yán)重影響性能

      FSslCertTools.DoKeyPair;//隨機(jī)產(chǎn)生 RSA公鑰及私鑰

      end;

      procedure TWebModule.DataModuleDestroy(Sender: TObject);

      begin

      FreeAndNil(FSslCertTools);

      end;

      //允許請(qǐng)求獲取公鑰

      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)行驗(yàn)證

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

      Write(t.toJSON);

      t.Free;

      end;

      end;

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

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

      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)行驗(yà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)行驗(yàn)證:

      解密的結(jié)果正確,驗(yàn)證通過(guò)。

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

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

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

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

      猜你喜歡
      表單私鑰公鑰
      比特幣的安全性到底有多高
      電子表單系統(tǒng)應(yīng)用分析
      華東科技(2021年9期)2021-09-23 02:15:24
      基于改進(jìn)ECC 算法的網(wǎng)絡(luò)信息私鑰變換優(yōu)化方法
      一種基于混沌的公鑰加密方案
      一種基于虛擬私鑰的OpenSSL與CSP交互方案
      淺談網(wǎng)頁(yè)制作中表單的教學(xué)
      HES:一種更小公鑰的同態(tài)加密算法
      SM2橢圓曲線公鑰密碼算法綜述
      基于格的公鑰加密與證書基加密
      基于Infopath實(shí)現(xiàn)WEB動(dòng)態(tài)表單的研究
      電子世界(2012年24期)2012-12-17 10:49:06
      额尔古纳市| 玉树县| 祥云县| 阿图什市| 察哈| 衡水市| 车致| 富平县| 阿坝| 化德县| 英山县| 武冈市| 石狮市| 高淳县| 嘉兴市| 剑川县| 灵寿县| 新干县| 东丰县| 翁牛特旗| 苍梧县| 深泽县| 信丰县| 黄平县| 兴安县| 望谟县| 苏尼特左旗| 称多县| 三穗县| 瓮安县| 日土县| 乌鲁木齐县| 萍乡市| 台前县| 东阿县| 黄山市| 城市| 彩票| 沂南县| 清苑县| 昌江|