ã¯ããã«
ãã¹ãŠã®äººã«è¯ãäžæ¥ãïŒ Laravelã«é¢ããæåã®èšäºã§ã¯ãã¯ã©ã€ã¢ã³ãïŒãã¹ã¯ãããã¢ããªã±ãŒã·ã§ã³ïŒãšLaravelãå®è¡ããŠãããµãŒããŒéã®æå·åãããéä¿¡ãæŽçããçµéšãå ±æããããšæããŸãã
ã¿ã¹ã¯ã®æ¬è³ªã¯äœã§ããïŒ ãµãã¹ã¯ãªãã·ã§ã³ã®ååã«åºã¥ããŠåäœããã¢ããªã±ãŒã·ã§ã³ããããŸããç§ã¯ãµã€ãã§æ¯æãã1ãæã®äœ¿çšãšèšã£ãŠ1ãæé䜿çšããŸãã ãã®æéãéãããšãã¢ããªã±ãŒã·ã§ã³ã¯åäœãåæ¢ããã¯ãã§ãã æ¡ä»¶ã®äžã§ã¯ããã®ã¢ããªã±ãŒã·ã§ã³ã¯ã€ã³ã¿ãŒãããæ¥ç¶ãå¿ èŠãšãããããã¢ããªã±ãŒã·ã§ã³ã®ã©ã€ã»ã³ã¹ã確èªããæè¯ã®ãªãã·ã§ã³ã¯ãã©ã€ã»ã³ã¹ãµãŒããŒãé¢æ¥ããããšã§ãã
ãããåé¡ã¯ãã¯ã©ã€ã¢ã³ããšãµãŒããŒéã®ãã©ãã£ãã¯ãæå·åãããŠããªãå Žåãã ãã§ãæçµçã«ãµãŒããŒãåœé ããå¿ èŠãªéãã¢ããªã±ãŒã·ã§ã³ã䜿çšã§ããããšã§ãã
ãã®èšäºã§ã¯ãã¯ã©ã€ã¢ã³ããšãµãŒããŒéã®æå·åãããéä¿¡ãæŽçããæ¹æ³ã«ã€ããŠèª¬æããŸãã ãµãŒããŒãã©ãããã©ãŒã ãšããŠãLaravel 4.1ãšã³ãžã³ïŒå ¬éæã®ææ°ããŒãžã§ã³ïŒã«ã¢ããªã±ãŒã·ã§ã³ããããŸãã ã¯ã©ã€ã¢ã³ãã¯CïŒã§èšè¿°ãããã¢ããªã±ãŒã·ã§ã³ã§ãããšæ³å®ãããŠããŸããããã®èšäºã§ã¯ã¯ã©ã€ã¢ã³ãã®èšè¿°ã«ã€ããŠã¯èª¬æããŸããã 代ããã«ãCïŒã§æå·åã䜿çšããäŸãæäŸããCodeProjectã®èšäºããå§ãããŸãïŒ CïŒãšPHPéã®éä¿¡ã®æå·å ã å®éããã®èšäºã¯ç§ã®ç 究ã®åºçºç¹ã§ããã
次ã®åé¡ã匷調ããŠã¿ãŸãã
- æå·ã®åºç€ïŒç§ã¯æå·ãããŸããªãã®ã§ãåºæ¬ã«ã€ããŠã§ãïŒ;
- Laravelã®äžã§ã®ããã°ã©ãã³ã°ãSOLIDãã¶ã€ã³ã«æºæ ïŒçæ³çã§ãããå®éã«ã¯ãèšäºãç°¡çŽ åããããã«ããã¹ãŠã®SOLIDååãå°éãããããã§ã¯ãããŸããïŒ
- ãã¶ãäœãä»ã®ãã®
æå·åã®åºæ¬
æ¢åã®æå·åã¢ã«ãŽãªãºã ã¯ãã¹ãŠã察称æå·åãšé察称æå·åã®2çš®é¡ã«åé¡ã§ããŸãã 察称æå·åã§ã¯ãæå·åãšåŸ©å·åã®äž¡æ¹ã§1ã€ã®ããŒã䜿çšãããŸãã ãã®ã«ããŽãªã®ã¢ã«ãŽãªãºã ã¯ãé察称ã¢ã«ãŽãªãºã ãããã¯ããã«é«éã§ãã
é察称ã¢ã«ãŽãªãºã ã§ã¯ããããªãã¯ãšãã©ã€ããŒãã®2ã€ã®ããŒã䜿çšãããŸãã æå·åã¯å ¬ééµã䜿çšããŠå®è¡ãããŸããããã®ããŒã¿ã®åŸ©å·åã¯ç§å¯éµã䜿çšããŠã®ã¿å®è¡ã§ããŸãã æå·åã«å ããŠãããŒã¿ã®ããžã¿ã«çœ²åãªã©ãç§å¯éµã䜿çšããŠçæãããããŒã¿ã®ããã·ã¥ãªã©ããããŸãã ãã®ããã·ã¥ã¯ãå ¬ééµã䜿çšããŠæ€èšŒãããŸãã ããã¯äœãæå³ããäœã®ããã§ããïŒ ããã¯ãåä¿¡ããããŒã¿ãæ£ç¢ºã«ç§ãã¡ãæåŸ ãã人ããã®ãã®ã§ãããç§ãã¡ã«åããéäžã§èª°ãã«ãã£ãŠå€æŽãããŠããªãããšã確èªããããã«å¿ èŠã§ãã é察称ã¢ã«ãŽãªãºã ã¯ã察称ã¢ã«ãŽãªãºã ãããåäœãé ããå°éã®ããŒã¿ãæå·åããããã«èšèšãããŠããŸãããããä¿¡é Œæ§ããããŸãã ãã®ãããååãšããŠãã¯ã©ã€ã¢ã³ããšãµãŒããŒã®éã§æ¬¡ã®çžäºäœçšã¹ããŒã ã䜿çšãããŸãã
- æåã«ãã¯ã©ã€ã¢ã³ãã¯å¯Ÿç§°æå·åçšã®ã©ã³ãã ããŒãçæããŸãã
- ã¯ã©ã€ã¢ã³ãã¯ãäºåã«æ¢ç¥ã®ãµãŒããŒã®å ¬éããŒã䜿çšããŠãé察称ã¢ã«ãŽãªãºã ã䜿çšããŠãã®ããŒãæå·åããŸãã
- æå·åãããããŒããµãŒããŒã«éä¿¡ãããŸãã
- ãµãŒããŒã¯ãåä¿¡ããããŒãåä¿¡ããŠââ解èªããããã«å¿ããŠããã¹ãŠãæ£åžžã§ããããšãã¯ã©ã€ã¢ã³ãã«éç¥ããŸãã
- ãµãŒããŒãšã¯ã©ã€ã¢ã³ãéã®ãããªããã©ãã£ãã¯ã¯ãéžæããã察称ã¢ã«ãŽãªãºã ã䜿çšããŠæå·åãããŸãã
ããã¯äœã®ããã§ããïŒ æ»æè ãèªåã®ç®çã®ããã«ãã©ãã£ãã¯ãååããŠäœ¿çšããå Žåãäžéã®äººéã®ãããªæ»æãé²ãããã
ãã®å Žåãæå·åã«å ããŠãããŒã¿ã¯çœ²åããããããã¯ã©ã€ã¢ã³ãã¯ããŒã¿ãåœé ããããã®ã§ã¯ãªããµãŒããŒããåä¿¡ãããããšã100ïŒ ç¢ºä¿¡ã§ããŸãã
ãµãŒããŒã¢ããªã±ãŒã·ã§ã³ã®æ§é ã«ã€ããŠå°ã
ããã§ã¯ã空ã®Laravelã¢ããªã±ãŒã·ã§ã³ã®äœææ¹æ³ã«ã€ããŠã¯èª¬æããŸããã ãã¬ãŒã ã¯ãŒã¯ã®å ¬åŒWebãµã€ãã§èªãããšãã§ããŸãã MySecureAppãšããã¢ããªã±ãŒã·ã§ã³ããã§ã«äœæããŠãããšããŸãã ãã¹ãŠã®ã³ãŒãã¯ã¢ããªãã£ã¬ã¯ããªå ã«é 眮ãããŸãã ããæ£ç¢ºã«ã¯ãã³ã³ãããŒã©ãŒãã¢ãã«ããã¥ãŒã«å ããŠãå¥ã®ãã®ãäœæããŸãã
- ã¢ããªãã©ã«ããŒå ã«libãã©ã«ããŒãäœæãããã®äžã«MySecureAppãäœæããŸããããã§ã¯ãã¢ããªã±ãŒã·ã§ã³ã®ããžãã¹ããžãã¯ãå®è£ ãããã¹ãŠã®ã¯ã©ã¹ãé 眮ãããŸãã
- ã¢ããªãã©ã«ããŒå ã«ããŒãã©ã«ããŒãäœæããŸãã ç§å¯éµãä¿åãããŸãã
- 次ã®è¡ãè¿œå ããŠãã¢ããªã±ãŒã·ã§ã³ã®ã«ãŒãã«ãã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
- ã¢ããªã±ãŒã·ã§ã³ã«ã¯ã次ã®ãã£ã¬ã¯ããªæ§é ãå¿
èŠã§ãã
/ã¢ã㪠/ 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
ããã€ãã®è³ªåããããŸãããçããå¿ èŠã¯ãããŸããã äœã§ãçããããŸãã
åèšïŒ
- private.key-ç§å¯éµ
- 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ã®æé«ã®äŒçµ±ã«åŸããŸãã
ãããè¡ãã«ã¯ã次ã®ããšãè¡ããŸãã
- DecryptedIntputã®ãã¡ãµãŒããéåžžã®InputãšãŸã£ããåãã«ããŸããã
- Cryptographyããã·ã³ã°ã«ãã³ãäœæããŸãããã
- ç¬èªã®ãµãŒãã¹ãããã€ããŒå ã«ãã¹ãŠããç»é²ãããŸã ã
ããã§ã¯ãé çªã«è¡ããŸãããã 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ãä»ããŠè¡ãããŸã ã ãã®ã³ã³ãããŒã©ãŒã®æ©èœã¯äœã§ããïŒ
- æå·åãããããŒã¿ã圌ã«è»¢éãããŸã
- æå·åãããå¿çãè¿ãå¿ èŠããããŸãã
åä¿¡ããæå·åãããããŒã¿ãã©ãåŠçãããã¯ãã§ã«ããã£ãŠããŸããããã«ã¯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 >= 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