首頁 後端開發 php教程 Laravel中encrypt和decrypt實作方法實例分享

Laravel中encrypt和decrypt實作方法實例分享

Jan 10, 2018 pm 04:57 PM
decrypt encrypt laravel

本文主要為大家介紹了關於Laravel中encrypt和decrypt的實現方法,文中透過範例程式碼介紹的非常詳細,對大家的學習或工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。

前言

Laravel 的加密機制使用OpenSSL 提供AES-256 和AES-128 的加密,本文將詳細介紹關於Laravel中encrypt和decrypt的實現,分享出來供大家參考學習,下面話不多說了,來一起看看詳細的介紹吧。

1. 使用方法

首先是產生秘金鑰。要需要在.env目錄裡提供APP_KEY,這個如果沒有的話,可以透過指令php artisan key:generate生成,也可以自己設定。產生後範例應該是這樣的

APP_KEY=base64:5BM1BXGOBrGeeqJMAWJZSzyzh5yPcCGOcOGPtUij65g=
登入後複製

在檔案設定加密key和加密演算法,在config/app.php的目錄裡有設定

$ 'key' => env('APP_KEY'),
 
  'cipher' => 'AES-256-CBC',
登入後複製

使用方法,在laravel裡已經有使用方法了,這裡就不在過多的說了。主要使用的兩個方法,一個是encrypt的加密,一個是decrypt的解密

2. 尋找加密解密的檔案

實作方法的位置是在vendor/illuminate/ encryption/的目錄下發現兩個文件,一個是EncryptionServiceProvider另外一個是Encrypter

3. 分析EncryptionServiceProvider文件

 public function register()
 {
  $this->app->singleton('encrypter', function ($app) {
   $config = $app->make('config')->get('app'); //从config/app.php里拿到配置文件

   if (Str::startsWith($key = $config['key'], 'base64:')) { //分析配置文件里的key里面有没有带'base64'
    $key = base64_decode(substr($key, 7)); //如果有的话,把key前面的base64:给取消,并且解析出原来的字符串
   }

   return new Encrypter($key, $config['cipher']); //实例化Encrypte类,注入到框架里
  });
 }
登入後複製

這個文件沒太多東西,但是透過這個我們可以看出,但是透過這個我們可以看出,但是透過這個我們可以看出其實在設定檔的,我們可以直接寫key,而且前面不帶base64也是可以解析。相當於省幾步操作

另外,在實例化類別的時候,需要傳入key以及加密方式

4. 分析Encrypter檔案

##1.分析__construct,在實例化之前執行

 public function __construct($key, $cipher = 'AES-128-CBC')
 {
  $key = (string) $key; //把key转换为字符串

  if (static::supported($key, $cipher)) { //调用一个自定义的方法,用来判断加密方式和要求的key长度是否一样
   $this->key = $key;
   $this->cipher = $cipher;
  } else {
   throw new RuntimeException('The only supported ciphers are AES-128-CBC and AES-256-CBC with the correct key lengths.');
  }
 }
登入後複製
上面的方法,主要是用來判斷加密方式和傳的key的長度是否相同,因為不同的加密方式,要求的對應的key的長度也是有要求的,具體每種加密方式要求key的長度可以查找對應的文檔

 public static function supported($key, $cipher)
 {
  $length = mb_strlen($key, '8bit'); //判断key的字符的长度,按照8bit位的方式计算字符长度

  return ($cipher === 'AES-128-CBC' && $length === 16) ||
    ($cipher === 'AES-256-CBC' && $length === 32); //编码格式为AES128的要求字符长度为16。编码格式为AES256的要求字符长度为32位
 }
登入後複製
上面這個方法展現了一個嚴謹的地方,用了mb_strlen方法,並且要求計算長度是按照8bit位元來計算的。這樣的好處是,不管是在哪一種作業系統,計算的長度都是一樣的。


透過這個考慮到不同作業系統的情況,不會出現加密出現問題的情況。

2. 分析encrypt方法

 public function encrypt($value, $serialize = true)
 {
  $iv = random_bytes(16); //生成一个16位的随机字符串
  
  
  // 使用openssl_encrypt把数据生成一个加密的数据
  // 1、判断需要不需要生成一个可存储表示的值,这样做是为了不管你的数据是数组还是字符串都能给你转成一个字符串,不至于在判断你传过来的数据是数组还是字符串了。
  // 2、使用openssl_encrypt。第一个参数是传入数据,第二个参数是传入加密方式,目前使用AES-256-CBC的加密方式,第三个参数是,返回加密后的原始数据,还是把加密的数据在经过一次base64的编码,0的话表示base64位数据。第四个参数是项量,这个参数传入随机数,是为了在加密数据的时候每次的加密数据都不一样。
  $value = \openssl_encrypt(
   $serialize ? serialize($value) : $value,
   $this->cipher, $this->key, 0, $iv
  ); //使用AES256加密内容

  if ($value === false) {
   throw new EncryptException('Could not encrypt the data.');
  }

  $mac = $this->hash($iv = base64_encode($iv), $value); //生成一个签名,用来保证内容参数没有被更改

  $json = json_encode(compact('iv', 'value', 'mac')); //把随机码,加密内容,已经签名,组成数组,并转成json格式

  if (! is_string($json)) {
   throw new EncryptException('Could not encrypt the data.');
  }

  return base64_encode($json); //把json格式转换为base64位,用于传输
 }
登入後複製
上面用到了一個自訂的方法hash(),我們可以看下方法的實作。

 protected function hash($iv, $value)
 {
  // 生成签名
  // 1、把随机值转为base64
  // 2、使用hash_hmac生成sha256的加密值,用来验证参数是否更改。第一个参数表示加密方式,目前是使用sha256,第二个是用随机值连上加密过后的内容进行,第三个参数是上步使用的key。生成签名。
  return hash_hmac('sha256', $iv.$value, $this->key); /根据随机值和内容,生成一个sha256的签名
 }
登入後複製
以上加密共分了三大步

     1、產生隨機碼


     2、產生加密內容


     3 、產生簽章

框架用到一個優雅的方法,使用serialize產生一個值,這個方法高雅在哪裡,就是不管你得內容是陣列還是字串,都能轉換成字串。 而使用serialize和使用json_encode的差別在哪,我想最大的好處就是,你要加密的內容比較大的時候,serialize相對於要快。


另一個地方是,框架在加密的時候使用了一個隨機字串。為什麼要使用隨機字串呢,因為使用了隨機字串,使每次加密的內容都是不一樣的,防止別人猜出來。

3. 分析decrypt方法

解密數據,可以說是最複雜的一塊,不僅要進行資料的解密,還要保證資料的完整性,以及資料防篡改

public function decrypt($payload, $unserialize = true)
 {
  $payload = $this->getJsonPayload($payload); //把加密后的字符串转换出成数组。

  $iv = base64_decode($payload['iv']); //把随机字符串进行base64解密出来

  $decrypted = \openssl_decrypt( //解密数据
   $payload['value'], $this->cipher, $this->key, 0, $iv
  );

  if ($decrypted === false) {
   throw new DecryptException('Could not decrypt the data.');
  }

  return $unserialize ? unserialize($decrypted) : $decrypted; //把数据转换为原始数据
 }
登入後複製
getJsonPayload方法

 protected function getJsonPayload($payload)
 {
  $payload = json_decode(base64_decode($payload), true); //把数据转换为原来的数组形式

  if (! $this->validPayload($payload)) { //验证是不是数组以及数组里有没有随机字符串,加密后的内容,签名
   throw new DecryptException('The payload is invalid.');
  }

  if (! $this->validMac($payload)) { //验证数据是否被篡改
   throw new DecryptException('The MAC is invalid.');
  }

  return $payload;
 }
登入後複製
validPayload方法就不說了,比較簡單和基本,重點就說說validMac驗證這塊,保證數據不被篡改,這是最重要的

 protected function validMac(array $payload)
 {
  $calculated = $this->calculateMac($payload, $bytes = random_bytes(16)); //拿数据和随机值生成一个签名

  return hash_equals( //比对上一步生成的签名和下面生成的签名的hash是否一样。
   hash_hmac('sha256', $payload['mac'], $bytes, true), $calculated //根据原始数据里的签名在新生成一个签名
  );
 }
登入後複製
calculateMac方法是為了根據原始資料和隨機值產生一個簽名,然後用這個簽章再次產生一個簽章

 protected function calculateMac($payload, $bytes)
 {
  return hash_hmac(
   'sha256', $this->hash($payload['iv'], $payload['value']), $bytes, true
  );
 }
登入後複製
以上解密共分了三大步

     1、判斷數據的完整性


     2、判斷資料的一致性


     3、解密資料內容。

這個驗證簽名有個奇怪的地方,他並不像我們平常驗證簽名一樣。我們平常驗證簽名都是,拿原始資料和隨機值產生一個簽名,然後拿產生的簽名和原始資料的簽名進行比對來判斷是否有被竄改。


而框架卻多了一個,他用的是,透過原始資料和隨機值產生簽名後,又拿這個簽名生成了一個簽名,而要比對的也是拿原始資料裡的簽名在產生一個簽名,然後進行比對。目前想不出,為什麼要多幾步操作。


在加密的時候,我們把原始資料用serialize轉換了一下,所以我們對應的也需要用unserialize把資料轉換回來。

注意

  • 加密時使用的openssl_encrypt裡的隨機項量值是使用的原始資料raw這種二進位的值,使用openssl_decrypt解密後的值是使用的經過base64位元後的隨機字串。

  • 解密的時候產生簽名比較的時候,不是用原來的簽名,然後根據原始資料的內容,重新產生一次簽名進行比較,而是使用原始簽名為基礎生成一個簽名,然後在拿原始資料為基礎產生的簽名,在用這個新產生的簽名重新產生了一次簽名。然後進行比較的。

  • AES256是加密數據,後面能夠逆向在進行解密出資料。而SHA256是產生簽章的,這個過程是不可逆的,是為了驗證資料的完整性。

相關推薦:

MySQL如何正確地利用AES_ENCRYPT()與AES_DECRYPT()加解密

#使用laravel 5.1出現No supported encrypter found錯誤的解決方法

javascript - 小程式wx.getUserInfo 中的 encryptData 解密

#

以上是Laravel中encrypt和decrypt實作方法實例分享的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Laravel和CodeIgniter的最新版本對比 Laravel和CodeIgniter的最新版本對比 Jun 05, 2024 pm 05:29 PM

Laravel9和CodeIgniter4的最新版本提供了更新的功能和改進。 Laravel9採用MVC架構,提供資料庫遷移、驗證及模板引擎等功能。 CodeIgniter4採用HMVC架構,提供路由、ORM和快取。在性能方面,Laravel9的基於服務提供者設計模式和CodeIgniter4的輕量級框架使其具有出色的性能。在實際應用中,Laravel9適用於需要靈活性和強大功能的複雜項目,而CodeIgniter4適用於快速開發和小型應用程式。

Laravel 和 CodeIgniter 中資料處理能力的比較如何? Laravel 和 CodeIgniter 中資料處理能力的比較如何? Jun 01, 2024 pm 01:34 PM

比較Laravel和CodeIgniter的資料處理能力:ORM:Laravel使用EloquentORM,提供類別物件關係映射,而CodeIgniter使用ActiveRecord,將資料庫模型表示為PHP類別的子類別。查詢建構器:Laravel具有靈活的鍊式查詢API,而CodeIgniter的查詢建構器更簡單,基於陣列。資料驗證:Laravel提供了一個Validator類,支援自訂驗證規則,而CodeIgniter的驗證功能內建較少,需要手動編碼自訂規則。實戰案例:用戶註冊範例展示了Lar

Laravel - Artisan 指令 Laravel - Artisan 指令 Aug 27, 2024 am 10:51 AM

Laravel - Artisan 指令 - Laravel 5.7 提供了處理和測試新指令的新方法。它包括測試 artisan 命令的新功能,下面提到了演示?

Laravel 和 CodeIgniter 對於初學者來說哪一個比較友善? Laravel 和 CodeIgniter 對於初學者來說哪一個比較友善? Jun 05, 2024 pm 07:50 PM

對於初學者來說,CodeIgniter的學習曲線更平緩,功能較少,但涵蓋了基本需求。 Laravel提供了更廣泛的功能集,但學習曲線稍陡。在性能方面,Laravel和CodeIgniter都表現出色。 Laravel有更廣泛的文件和活躍的社群支持,而CodeIgniter更簡單、輕量級,具有強大的安全功能。在建立部落格應用程式的實戰案例中,Laravel的EloquentORM簡化了資料操作,而CodeIgniter需要更多的手動配置。

Laravel和CodeIgniter:哪種框架更適合大型專案? Laravel和CodeIgniter:哪種框架更適合大型專案? Jun 04, 2024 am 09:09 AM

在選擇大型專案框架時,Laravel和CodeIgniter各有優勢。 Laravel針對企業級應用程式而設計,提供模組化設計、相依性注入和強大的功能集。 CodeIgniter是一款輕量級框架,更適合小型到中型項目,強調速度和易用性。對於具有複雜需求和大量用戶的大型項目,Laravel的強大功能和可擴展性更為合適。而對於簡單專案或資源有限的情況下,CodeIgniter的輕量級和快速開發能力則較為理想。

PHP 企業級應用微服務架構設計問答 PHP 企業級應用微服務架構設計問答 May 07, 2024 am 09:36 AM

微服務架構使用PHP框架(如Symfony和Laravel)來實現微服務,並遵循RESTful原則和標準資料格式來設計API。微服務透過訊息佇列、HTTP請求或gRPC進行通信,並使用工具(如Prometheus和ELKStack)進行監控和故障排除。

Laravel和CodeIgniter:哪種框架比較適合小型專案? Laravel和CodeIgniter:哪種框架比較適合小型專案? Jun 04, 2024 pm 05:29 PM

對於小型項目,Laravel適用於大型項目,需要強大的功能和安全性。 CodeIgniter適用於非常小的項目,需要輕量級和易用性。

Laravel 和 CodeIgniter 的模板引擎哪一個比較好? Laravel 和 CodeIgniter 的模板引擎哪一個比較好? Jun 03, 2024 am 11:30 AM

比較了Laravel的Blade和CodeIgniter的Twig模板引擎,根據專案需求和個人偏好進行選擇:Blade基於MVC語法,鼓勵良好程式碼組織和模板繼承。 Twig是第三方函式庫,提供靈活語法、強大過濾器、擴充支援和安全沙箱。

See all articles