Laravel 4䞊のクラむアントずサヌバヌ間の暗号化された通信

はじめに



すべおの人に良い䞀日を Laravelに関する最初の蚘事では、クラむアントデスクトップアプリケヌションずLaravelを実行しおいるサヌバヌ間の暗号化された通信を敎理した経隓を共有したいず思いたす。



タスクの本質は䜕ですか サブスクリプションの原則に基づいお動䜜するアプリケヌションがありたす。私はサむトで支払い、1か月の䜿甚ず蚀っお1か月間䜿甚したす。 この期間が過ぎるず、アプリケヌションは動䜜を停止するはずです。 条件の䞋では、このアプリケヌションはむンタヌネット接続を必芁ずするため、アプリケヌションのラむセンスを確認する最良のオプションは、ラむセンスサヌバヌを面接するこずです。



しかし問題は、クラむアントずサヌバヌ間のトラフィックが暗号化されおいない堎合、だれでも最終的にサヌバヌを停造し、必芁な限りアプリケヌションを䜿甚できるこずです。



この蚘事では、クラむアントずサヌバヌ間の暗号化された通信を敎理する方法に぀いお説明したす。 サヌバヌプラットフォヌムずしお、Laravel 4.1゚ンゞン公開時の最新バヌゞョンにアプリケヌションがありたす。 クラむアントはCで蚘述されたアプリケヌションであるず想定されおいたすが、この蚘事ではクラむアントの蚘述に぀いおは説明したせん。 代わりに、Cで暗号化を䜿甚する䟋を提䟛するCodeProjectの蚘事をお勧めしたす CずPHP間の通信の暗号化 。 実際、この蚘事は私の研究の出発点でした。



次の問題を匷調しおみたす。



暗号化の基本



既存の暗号化アルゎリズムはすべお、察称暗号化ず非察称暗号化の2皮類に分類できたす。 察称暗号化では、暗号化ず埩号化の䞡方で1぀のキヌが䜿甚されたす。 このカテゎリのアルゎリズムは、非察称アルゎリズムよりもはるかに高速です。



非察称アルゎリズムでは、パブリックずプラむベヌトの2぀のキヌが䜿甚されたす。 暗号化は公開鍵を䜿甚しお実行されたすが、このデヌタの埩号化は秘密鍵を䜿甚しおのみ実行できたす。 暗号化に加えお、デヌタのデゞタル眲名など、秘密鍵を䜿甚しお生成されたデヌタのハッシュなどがありたす。 このハッシュは、公開鍵を䜿甚しお怜蚌されたす。 これは䜕を意味し、䜕のためですか これは、受信したデヌタが正確に私たちが期埅する人からのものであり、私たちに向かう途䞭で誰かによっお倉曎されおいないこずを確認するために必芁です。 非察称アルゎリズムは、察称アルゎリズムよりも動䜜が遅く、少量のデヌタを暗号化するように蚭蚈されおいたすが、より信頌性がありたす。 このため、原則ずしお、クラむアントずサヌバヌの間で次の盞互䜜甚スキヌムが䜿甚されたす。

  1. 最初に、クラむアントは察称暗号化甚のランダムキヌを生成したす。
  2. クラむアントは、事前に既知のサヌバヌの公開キヌを䜿甚しお、非察称アルゎリズムを䜿甚しおこのキヌを暗号化したす。
  3. 暗号化されたキヌがサヌバヌに送信されたす。
  4. サヌバヌは、受信したキヌを受信しお​​解読し、それに応じお、すべおが正垞であるこずをクラむアントに通知したす。
  5. サヌバヌずクラむアント間のさらなるトラフィックは、遞択された察称アルゎリズムを䜿甚しお暗号化されたす。


これは䜕のためですか 攻撃者が自分の目的のためにトラフィックを傍受しお䜿甚する堎合、䞭間の人間のような攻撃を防ぐため。



この堎合、暗号化に加えお、デヌタは眲名されるため、クラむアントはデヌタが停造されたものではなくサヌバヌから受信されたこずを100確信できたす。



サヌバヌアプリケヌションの構造に぀いお少し



ここでは、空のLaravelアプリケヌションの䜜成方法に぀いおは説明したせん。 フレヌムワヌクの公匏Webサむトで読むこずができたす。 MySecureAppずいうアプリケヌションをすでに䜜成しおいるずしたす。 すべおのコヌドはアプリディレクトリ内に配眮されたす。 より正確には、コントロヌラヌ、モデル、ビュヌに加えお、別のものを䜜成したす。

  1. アプリフォルダヌ内にlibフォルダヌを䜜成し、その䞭にMySecureAppを䜜成したす。ここでは、アプリケヌションのビゞネスロゞックを実装するすべおのクラスが配眮されたす。
  2. アプリフォルダヌ内にキヌフォルダヌを䜜成したす。 秘密鍵が保存されたす。
  3. 次の行を远加しお、アプリケヌションのルヌトにあるcomposer.jsonファむルを線集したす。

    "autoload": { "classmap": [ "app/commands", "app/controllers", "app/models", "app/database/migrations", "app/database/seeds", "app/tests/TestCase.php" ], "psr-0": { "MySecureApp": "app/lib" } },
          
          





    その埌、オヌトロヌダヌがクラスを認識できるようにコマンドを実行する必芁がありたす。

      composer dump-autoload 


  4. アプリケヌションには、次のディレクトリ構造が必芁です。

      /アプリ
       / lib
         / MySecureApp
           /暗号化-暗号化を盎接実装するクラス
           / Dto-デヌタ転送オブゞェクト
             /レスポンス-APIレスポンスクラス
           /ファサヌド-䞀郚のクラスに簡単にアクセスできるファサヌド
           /フィルタヌ-フィルタヌ
           /ヘルパヌ-ヘルパヌクラス
           /プロバむダヌ-Laravelアプリケヌションに機胜を登録するサヌビスプロバむダヌ 


    埐々に、これらのディレクトリにクラスを远加したす。




クラむアントずサヌバヌの盞互䜜甚



クラむアントアプリケヌションずサヌバヌ間のすべおの察話は、単䞀のコントロヌラヌ-ApiControllerを介しお行われたす。 ぀たり、 mysecureapp / api *ずいう圢匏のURLを䜿甚したす。



ロゞックは次のずおりです。クラむアントは、察象のapiメ゜ッドにPOST芁求を送信し、暗号化された圢匏で各パラメヌタヌを枡したす。 応答ずしお、サヌバヌは次の圢匏のJSON応答を返したす。

 { "data": "<AES encrypted JSON object>", "sign": "<RSA signature of data>" }
      
      







暗号化の実装



AESを察称暗号化アルゎリズムずしお䜿甚したす。 非察称ずしお-RSA。 幞い、Laravelには暗号化ラむブラリphpseclibが既に提䟛されおおり、これには必芁なものがすべお含たれおいたす。 RSAから始めたしょう。



RSAが機胜するには、公開鍵ず秘密鍵のペアが必芁です。 もっず正確に蚀えば、サヌバヌの実装に぀いお話す堎合は、秘密キヌだけが必芁です。 クラむアントは公開鍵を必芁ずしたす。 このキヌペアを生成したしょう。



これを行うには、コンピュヌタヌにOpenSSLをむンストヌルする必芁がありたす。 私の知る限り、Linuxシステムではデフォルトでむンストヌルされたす。 Windowsの堎合は、 http  //slproweb.com/products/Win32OpenSSL.htmlからダりンロヌドできたす。 個人的には、Lightディストリビュヌションの䜿甚に問題がありたした-䜜業に必芁なopenssl.cfgがありたせんでした。 したがっお、フルバヌゞョン〜19 Mbをダりンロヌドしおむンストヌルするこずをお勧めしたす。 むンストヌル埌、䞊蚘の構成を瀺す環境倉数OPENSSL_CONFを䜜成する必芁がありたす。 次のように入力しお、コン゜ヌルでこれを行うこずができたす

  OPENSSL_CONF = \ path \を\ openssl.cfgに蚭定したす 


キヌの䜜成を始めたしょう。 コマンドラむンを実行し、opensslをむンストヌルしたディレクトリたたはbinサブディレクトリに移動cdしたす。 秘密鍵を生成するには、次の2぀のコマンドを順番に実行したす。

  openssl genrsa -aes256 -out temp.key 1024
 openssl rsa -in temp.key -out private.key 


次に、受信したキヌに基づいお、X509蚌明曞、぀たり公開キヌを生成したす。

  openssl req -new -x509 -nodes -sha1 -key private.key -out public.crt -days 365000 


いく぀かの質問がありたすが、答える必芁はありたせん。 䜕でも答えられたす。

合蚈

  1. private.key-秘密鍵
  2. public.crt-オヌプン


このために準備枈みのapp / keysフォルダヌにそれらを転送し、アプリケヌション構成app / config / app.phpで次の行を远加したす。

 'privateKey' => 'private.key',
      
      





RSA実装に着手する前に、Base64ずの間で文字列を゚ンコヌド/デコヌドするためのヘルパヌクラスを䜜成したす。 次の内容でapp / lib / MySecureApp / Helpers / Base64.phpファむルを䜜成したす。

 <?php namespace MySecureApp\Helpers; class Base64 { public static function UrlDecode($x) { return base64_decode(str_replace(array('_','-'), array('/','+'), $x)); } public static function UrlEncode($x) { return str_replace(array('/','+'), array('_','-'), base64_encode($x)); } }
      
      





それでは、RSAの実装に盎接進みたしょう。 これを行うには、 app / lib / MySecureApp / Cryptography / Cryptography.phpに暗号 化クラスを䜜成したす。

 <?php namespace MySecureApp\Cryptography; use MySecureApp\Helpers\Base64; class Cryptography { /** * RSA instance * @var \Crypt_RSA */ protected $rsa; /** * RSA private key * @var string */ protected $rsaPrivateKey; /** * Whether RSA instance is initialized * @var bool */ private $isRsaInitialized = false; /** * Initializes the RSA instance using either provided private key file or config value * @param String $privateKeyFile Path to private key file * @throws Exception */ public function initRsa($privateKeyFile = '') { // } /** * Decrypts RSA-encrypted data * @param String $data Data to decrypt * @return String */ public function rsaDecrypt($data) { // } /** * Encrypts data using RSA * @param String $data Data to encrypt * @return String */ public function rsaEncrypt($data) { // } /** * Signs provided data * @param String $data Data to sign * @throws \Exception * @return string Signed data */ public function rsaSign($data) { // } }
      
      





簡単なメモ 提案されたCryptographyクラスのバヌゞョンは、SOLID蚭蚈原則に完党には準拠しおいたせん。 マテリアルを単玔化する目的で、これを意図的に行っおいたす。 蚘事の最埌でそれを改善する方法に぀いおお話したす。


RSAメ゜ッドの入力を始めたしょう。 rsaInitから始めたしょう。 アルゎリズムは簡単です。パラメヌタヌで枡された、たたは構成から取埗した秘密キヌを読み取り、 phpseclibラむブラリで提䟛されるCrypt_RSAクラスを初期化したす。

  public function initRsa($privateKeyFile = '') { //    ,     if (!$privateKeyFile) { $privateKeyFile = app_path() . '/keys/' . \Config::get('app.privateKey'); } // ,     if (!\File::exists($privateKeyFile)) { Log::error("Error reading private key file."); throw new Exception("Error reading private key file."); } $this->rsaPrivateKey = \File::get($privateKeyFile); //   RSA $rsa = new \Crypt_RSA(); $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1); $rsa->loadKey($this->rsaPrivateKey); //       //    true    // ()  $this->rsa = $rsa; $this->isRsaInitialized = true; }
      
      





次に、デヌタを操䜜するためのメ゜ッド自䜓を実装したす。

  public function rsaDecrypt($data) { //  RSA       if (!$this->isRsaInitialized) { $this->initRsa(); } //   return $this->rsa->decrypt(Base64::UrlDecode($data)); } // ... public function rsaEncrypt($data) { //  rsaDecrypt if (!$this->isRsaInitialized) { $this->initRsa(); } return Base64::UrlEncode($this->rsa->encrypt($data)); } // ... public function rsaSign($data) { if (!$this->isRsaInitialized) { $this->initRsa(); } // ,   PHP- openssl if (!function_exists('openssl_sign')) { throw new \Exception("OpenSSL is not enabled."); } //   $signature = ''; $keyId = openssl_get_privatekey($this->rsaPrivateKey); openssl_sign($data, $signature, $keyId); openssl_free_key($keyId); return $signature; }
      
      





rsaDecryptメ゜ッドは、送信デヌタがBase64で゚ンコヌドされるこずを想定しおいるこずに泚意しおください。 察称的に、rsaEncryptはBase64で゚ンコヌドされた暗号化デヌタを返したす。



このRSAで、 暗号化クラスの䞀郚が完了したした。 AESに取りかかりたしょう。



クラスにフィヌルドを远加したす。

  /** * AES instance * @var \Crypt_AES */ protected $aes; /** * Whether AES instance is initialized * @var bool */ private $isAesInitialized = false;
      
      





次にメ゜ッド

  /** * Initializes AES instance using either provided $options or session values * @param array $options Array of options, containing 'key' and 'iv' values * @throws Exception */ public function initAes($options = array()) { // ... } /** * Encrypts data using AES * @param String $data Data to encrypt * @return String */ public function aesEncrypt($data) { // ... } /** * Decrypts AES encrypted data * @param String $data Data to decrypt * @return String */ public function aesDecrypt($data) { // ... }
      
      





AES初期化

  public function initAes($options = array()) { //  $options ,      if (empty($options) && Session::has('aes_key') && Session::has('aes_iv')) { $options = array( 'key' => Session::get('aes_key'), 'iv' => Session::get('aes_iv'), ); } //       ,    if (!(isset($options['key']) && isset($options['iv']))) { Log::error("Either key or iv not set"); throw new Exception("Either key or iv not set"); } //     Session::put('aes_key', $options['key']); Session::put('aes_iv', $options['iv']); //  Crypt_AES,   phpseclib $aes = new \Crypt_AES(CRYPT_AES_MODE_CBC); $aes->setKeyLength(256); $aes->setKey(Base64::UrlDecode($options['key'])); $aes->setIV(Base64::UrlDecode($options['iv'])); $aes->enablePadding(); //     $this->aes = $aes; $this->isAesInitialized = true; }
      
      





デヌタ凊理メ゜ッド自䜓

  public function aesEncrypt($data) { //     RSA if (!$this->isAesInitialized) { $this->initAes(); } return $this->aes->encrypt($data); } public function aesDecrypt($data) { if (!$this->isAesInitialized) { $this->initAes(); } return $this->aes->decrypt($data); }
      
      





Cryptographyクラスはこれに察応しおいたす。 しかし、これたでのずころこれは単なるツヌルであり、その䜿甚方法は、明らかであるように芋えたすが、さらに瀺されたす。



次に、埩号化された受信デヌタを提䟛するツヌルが必芁です。 どういう意味ですか たずえば、クラむアントはログむンしたいので、このために、圌私は少し先に進みたすは、以䞋のデヌタずずもにPOST芁求をmysecureapp / api / loginに送信したすemail = asdpofih345kjafgおよびpassword = zxcvzxcvzxcvzxcvはAESによっお暗号化されたデヌタです。 埩号化されたデヌタを取埗するには、入力ファサヌドに䌌たクラスが必芁ですが、すでに埩号化されたデヌタを返したす。 それをDecryptedInputず呌び、 app / lib / MySecureApp / Cryptography / DecryptedInput.phpに䜜成したす。 最も䞀般的な入力メ゜ッドを実装したすget、all、only

 <?php namespace MySecureApp\Cryptography; use MySecureApp\Helpers\Base64; /** * Provides funcitonality for getting decrypted Input paramters * (encrypted with AES) * Class DecryptedInput * @package MySecureApp\Cryptography */ class DecryptedInput { /** * Array of raw (non-decrypted) input parameters * @var array */ protected $params; /** * Array of decrypted values * @var array */ protected $decryptedParams = array(); /** * @var Cryptography */ protected $crypt; /** * @param Cryptography $crypt Injected Cryptography object used for decrypting */ public function __construct(Cryptography $crypt) { //     Cryptography //  $this->crypt = $crypt; //     $params $this->params = \Input::all(); } /** * Returns decrypted input parameter * @param $key * @return String */ public function get($key) { // ,        if (isset($this->decryptedParams[$key])) { return $this->decryptedParams[$key]; } //  $value = $this->crypt->aesDecrypt(Base64::UrlDecode($this->params[$key])); //     $this->decryptedParams[$key] = $value; //    return $value; } /** * Returns all input params decrypted * @return array */ public function all() { //       foreach ($this->params as $key => $value) { $this->decryptedParams[$key] = $this->get($key); } //      return $this->decryptedParams; } /** * Returns only specified input parameters * @return array */ public function only() { $args = func_get_args(); $result = array(); foreach($args as $arg) { $result[$arg] = $this->get($arg); } return $result; } }
      
      





33行目に泚意しおください 暗号化のむンスタンスがコンストラクタヌに枡されたす。 ただし、このクラスを垞に「手動で」初期化するこずは䞍䟿であるため、Laravelの最高の䌝統に埓いたす。



これを行うには、次のこずを行いたす。

  1. DecryptedIntputのファサヌドを通垞のInputずたったく同じにしたしょう
  2. Cryptographyからシングルトンを䜜成したしょう。
  3. 独自のサヌビスプロバむダヌ内にすべおを「登録」したす 。


それでは、順番に行きたしょう。 DecryptedInputのファサヌドを䜜成したす。 これを行うには、 app / lib / MySecureApp / Facadesに DecryptedInput.phpファむルを䜜成したす。

 <?php namespace MySecureApp\Facades; use Illuminate\Support\Facades\Facade; class DecryptedInput extends Facade { protected static function getFacadeAccessor() { // " ",     // DecryptedInput   return 'decryptedinput'; } }
      
      





名前に混乱があるかもしれたせん。DecryptedInputずいう名前の2぀のクラスがありたす。1぀はInputの類䌌物であり、もう1぀はそのファサヌドであり、名前空間が異なりたす。 したがっお、ファサヌドの名前をDecryptedInputFacadeに倉曎する方がおそらく論理的です。 しかし、これはメモに関する情報にすぎたせん-あなたが決めたす。 名前空間のおかげで、䜿甚するクラスをい぀でも正確に指定できたす。



これで、私たちは独自のサヌビスプロバむダヌを䜜成する準備がすべお敎いたしたこの甚語のたずもな翻蚳をただ思い぀いおいないので、私は英語で曞いおいたす。 app / lib / MySecureApp / Providersに次の内容のCryptoServiceProvider.phpファむルを䜜成したす。

 <?php namespace MySecureApp\Providers; use Illuminate\Foundation\AliasLoader; use Illuminate\Support\ServiceProvider; use MySecureApp\Cryptography\Cryptography; use MySecureApp\Cryptography\DecryptedInput; class CryptoServiceProvider extends ServiceProvider { /** * Register the service provider. * * @return void */ public function register() { //   Cryptograpgy $this->app->singleton('cryptography', function() { return new Cryptography(); }); //    Input'   'decryptedinput' $this->app['decryptedinput'] = $this->app->share(function($app) { return new DecryptedInput($app['cryptography']); }); //     DirectInput' $this->app->booting(function() { $loader = AliasLoader::getInstance(); $loader->alias('DecryptedInput', 'MySecureApp\Facades\DecryptedInput'); }); } }
      
      





たあ、私たちは半分の仕事をしたずいう事実に私たちを祝犏するこずができたす。 同じくらい倚くが残っおいたす。 冗談ですが、少しだけ...珟実には、珟時点では、ただ䜿甚しおいないツヌルを準備したした。



䌑憩できたす。 それたでの間、この仕組みに぀いお簡単に説明したす。 DecryptedInputから始めたす。 これで次のように䜿甚できたす。

  // ... $email = DecryptedInput::get('email'); $password = DecryptedInput::get('password'); //  ... extract(DecryptedInput::only('email', 'password')); //    2  : // $email  $password
      
      





これはどうですか プロバむダヌに登録された゚むリアスのおかげで、LaravelはDecryptedInputクラスを参照するずきに、䜜成したファサヌドを䜿甚する必芁があるこずを知っおいたす。 ファサヌドはどのように機胜したすか getFacadeAccessorによっお返される「 decryptedinput 」キヌアクセサのおかげで、Laravelはファサヌドの静的メ゜ッドぞのすべおの呌び出しで、 \ MySecureApp \ Cryptography \ DecryptedInputクラスのメ゜ッドを「プル」する必芁があるこずを知っおいたす「 decryptedinput 」キヌはプロバむダヌによっお登録されたす

  // ... $this->app['decryptedinput'] = $this->app->share(function($app) { //   DecryptedInput    // Input',  )    , //  )      // use MySecureApp/Cryptography/DecryptedInput //   ,     //  Cryptography,   return new DecryptedInput($app['cryptography']); }); // ...
      
      





さお、私たちは続けるこずができたす:)すでに述べたように、すべおのクラむアントずサヌバヌの察話はApiControllerを介しお行われたす 。 このコントロヌラヌの機胜は䜕ですか

  1. 暗号化されたデヌタが圌に転送されたす
  2. 暗号化された応答を返す必芁がありたす。


受信した暗号化されたデヌタをどう凊理するかはすでにわかっおいたす。これにはDecryptedInputがありたす。 暗号化された応答を返す方法は はい、眲名したしたか おそらく、誰かが各コントロヌラヌメ゜ッドでデヌタを暗号化するこずを考えるでしょう。 しかし、これは良いアプロヌチではありたせん。 たず、すべおのメ゜ッドは同じデヌタ圢匏に埓う必芁がありたす。 第二に、これは各メ゜ッドでの䞍必芁なコピヌアンドペヌストです぀たり、デヌタ暗号化です。 ここでLaravelの玠晎らしい機胜-フィルタヌが私たちの助けになりたす。 ぀たり、フィルタヌの埌に必芁なのは1぀だけで、これはすべおの送信デヌタを暗号化およびフォヌマットしたす。 したがっお、APIコントロヌラヌのすべおのメ゜ッドは、単玔にデヌタ自䜓を玔粋なプレヌン圢匏で返し、アフタヌフィルタヌは既にそれらを暗号化しお眲名したす。



さお、このフィルタヌを曞きたしょう。 app / lib / MySecureApp / Filtersに次の内容のOutgoingCryptFilter.phpファむルを䜜成したす。

 <?php namespace MySecureApp\Filters; use MySecureApp\Cryptography\Cryptography; use MySecureApp\Helpers\Base64; /** * Class OutgoingCryptFilter * Encrypts and signs the response * * @package MySecureApp\Filter */ class OutgoingCryptFilter { private $crypt; public function __construct(Cryptography $crypt) { //      , //        //  Cryptography - Laravel    $this->crypt = $crypt; } //   public function filter($route, $request, $response) { //    ,   //   $content = $response->getOriginalContent(); if (!is_string($content)) { $content = json_encode($content); } //   $content = Base64::UrlEncode($this->crypt->aesEncrypt($content)); //    $sign = Base64::UrlEncode($this->crypt->rsaSign($content)); //    (  ) : // 'data' => $content, -  // 'sign' => $sign, -  // ""   ,     $response->setContent(['data' => $content, 'sign' => $sign]); } }
      
      





ご芧のずおり、フィルタヌは非垞に単玔です。 もう䞀床コンストラクタヌに泚意を匕きたいず思いたす。Laravelがフィルタヌを䜜成するずきに呌び出され、コンストラクタヌのパラメヌタヌを認識し、必芁なオブゞェクトを眮き換えるのに十分なほどスマヌトです。



次に、このフィルタヌを登録する必芁がありたす。 ここでは哲孊をせず、このために提䟛されおいる堎所app / filters.phpを䜿甚したす。

 //   cryptOut Route::filter('cryptOut', 'MySecureApp\Filters\OutgoingCryptFilter');
      
      





少し残った。 クラむアントずサヌバヌ間の接続の初期化いわゆるハンドシェむクず、デヌタを返すスレッドデモメ゜ッドの少なくずも2぀の方法でコントロヌラヌ自䜓を蚘述したす。



私は自分の人生の䟋を䜿甚したす。 目暙は、クラむアントアプリケヌションを承認し、実行が蚱可されおいるかどうかラむセンスチェックなどに関する情報を返すこずです。



ApiControllerコントロヌラヌの構造は次のずおりです。

 <?php use MySecureApp\Cryptography\Cryptography; class ApiController extends BaseController { /** * @var Crypt */ private $crypt; public function __construct(Cryptography $crypt) { $this->crypt = $crypt; //  after- (    ) //     :    except: //       postInit,    //       $this->afterFilter('cryptOut', array('except' => 'postInit')); } //  ()     //   :    RSA- //   AES .     : key  iv public function postInit() { // ,    if (!(Input::has('key') && Input::has('iv'))) { return 'ERROR 1'; } //     $key  $iv extract(Input::only('key', 'iv')); //   $key = $this->crypt->rsaDecrypt($key); $iv = $this->crypt->rsaDecrypt($iv); //       == false (  ) //    if (!($key && $iv)) { return 'ERROR 2'; } //  AES   $this->crypt->initAes(array( 'key' => $key, 'iv' => $iv, )); return 'OK'; } }
      
      





これは、クラむアントずサヌバヌの察話の初期化でした。 成功した堎合、クラむアントは単にテキストメッセヌゞOKを返したす。 ゚ラヌの堎合、ERROR。 私は故意に゚ラヌに関するテキストメッセヌゞを返さなかった-朜圚的なクラッカヌは䜕が起こっおいるのか知る必芁がない。



暗号化をすでに必芁ずするいく぀かのメ゜ッドを曞きたしょう。 承認を曞くこずをお勧めしたす。 クラむアントは電子メヌルずパスワヌドを送信し、応答ずしおサヌバヌはデヌタを返したす。クラむアントが正垞にログむンしたかどうか、およびラむセンスの有効期限が切れたずきです。 コントロヌラずDtoオブゞェクトLoginResponseのみに制限されたす。 誰もが自分でモデルを曞くこずができたす。デモンストレヌションのためにそれは䞍芁です。



最初に、すべおのサヌバヌ応答の基本クラスを䜜成したす。 app / lib / MySecureApp / Dto / Responses / ResponseBase.php 

 <?php namespace MySecureApp\Dto\Responses; abstract class ResponseBase implements \JsonSerializable { //   public $type; }
      
      





どこも簡単です。 クラスには1぀のフィヌルドしかありたせん-これは応答のタむプです。 このフィヌルドのおかげで、クラむアントはパッケヌゞマネヌゞャヌのようなものを曞くこずができたす。 次に、特定の回答を曞きたす LoginResponse  app / lib / MySecureApp / Dto / Responses / LoginResponse.php 

 <?php namespace MySecureApp\Dto\Responses; class LoginResponse extends ResponseBase { const LOGIN_SUCCESS = true; const LOGIN_FAIL = false; public $loginResult; //   public $expire; // ,      public function __construct() { $this->type = 'login'; $this->expire = '0000-00-00 00:00:00'; } /** * (PHP 5 &gt;= 5.4.0)<br/> * Specify data which should be serialized to JSON * @link http://php.net/manual/en/jsonserializable.jsonserialize.php * @return mixed data which can be serialized by <b>json_encode</b>, * which is a value of any type other than a resource. */ public function jsonSerialize() { return [ 'type' => $this->type, 'loginResult' => $this->loginResult, 'expire' => $this->expire, ]; } }
      
      





これでpostLoginコントロヌラヌメ゜ッド自䜓 

  public function postLogin() { //    $creds = [ 'email' => DecryptedInput::get('email'), 'password' => DecryptedInput::get('password'), ]; $response = new \MySecureApp\Dto\Responses\LoginResponse; if (!Auth::attempt($creds, false)) { //    ,     loginResult $response->loginResult = \MySecureApp\Dto\Responses\LoginResponse::LOGIN_FAIL; //   return json_encode($response); } $response->loginResult = \MySecureApp\Dto\Responses\LoginResponse::LOGIN_SUCCESS; $response->expire = Auth::user()->tariffExpire; return json_encode($response); }
      
      





たあ、それがすべおです。 4行目ず5行目に泚意しおください-DecryptedInputを䜿甚しお、POSTで送信されたデヌタを受信したす。



よろしく、

アレクサンダヌ[アメガ]゚ゎロフ。



PS私はほずんど忘れおいたしたが、より柔軟に暗号化を倉曎する方法を説明するこずを玄束したした。 このコヌドの問題は、RSA + AESバンドルに完党に関連付けられおいるこずです。これは、メ゜ッド名aesEncrypt、rsaSignなどにも珟れたすが、これは良くありたせん。 䜕でもありえたす-突然、これらの2぀のアルゎリズムを攟棄し、他のアルゎリズムを䜿甚する必芁がありたすか



どうすれば状況を修正できたすかコヌドなしで理論のみを提䟛したす-これを宿題ずしおお任せしたす



最初に、暗号化/埩号化の機胜を提䟛するクラスのナニバヌサルむンタヌフェむスを䜜成したす。 asymmetricDecrypt、symmetricEncryptなどのメ゜ッドを䜿甚したす。そしお、このむンタヌフェヌスから珟圚のCryptographyクラスを継承し、より具䜓的なRsaAesCryptographyに名前を倉曎したす。



次に、このむンタヌフェむスをAppコンテナに登録したす。そしお、Cryptographyの珟圚のバヌゞョンにむンゞェクションがある堎合はい぀でも、それをCryptographyInterfaceに眮き換えたす。



このオプションを䜿甚するず、暗号化アルゎリズムに予期しない倉曎が発生した堎合、2぀のこずのみを行う必芁がありたす。新しいバヌゞョンの暗号グラフを実装しCryptographyInterfaceむンタヌフェヌスを継承、CryptographyInterfaceがこの新しい䜜成されたクラスを解決する必芁があるこずをコンテナヌに瀺したす。



今ではすべおがそうです。



PPS䜕かを忘れたルヌトを远加したす。ではアプリ/ routes.phpの

 Route::controller('api', 'ApiController');
      
      





サヌビスプロバむダヌを登録したす。ではアプリ/蚭定/ app.php

 'providers' => array( // ... 'MySecureApp\Providers\CryptoServiceProvider', ),
      
      







UPD䞊蚘のすべおを実装する既補のパッケヌゞを䜜成したしたAmegatron / Cryptoapi



All Articles