1. 程式人生 > >php如何openssl_encrypt加密解密

php如何openssl_encrypt加密解密

最近在對接客戶的CRM系統,獲取令牌時,要用DES方式加密解密,由於之前沒有搞錯這種加密方式,經過請教了“百度”和“谷歌”兩個老師後,結合了多篇文件內容後,終於實現了。

一、DES介紹

DES 是對稱性加密裡面常見一種,全稱為 Data Encryption Standard,即資料加密標準,是一種使用金鑰加密的塊演算法。金鑰長度是64位(bit),超過位數金鑰被忽略。所謂對稱性加密即加密和解密金鑰相同,對稱性加密一般會按照固定長度,把待加密字串分成塊,不足一整塊或者剛好最後有特殊填充字元。

  • 跨語言做 DES 加密解密經常會出現問題,往往是填充方式不對、編碼不一致或者加密解密模式沒有對應上造成。
  • 常見的填充模式有: pkcs5、pkcs7、iso10126、ansix923、zero。
  • 加密模式有:DES-ECB、DES-CBC、DES-CTR、DES-OFB、DES-CFB。

加密用到的方法:

 openssl_encrypt($data, $method, $password, $options, $iv)

引數說明:

  1. $data 加密明文

  2. $method 加密方法

    • DES-ECB
    • DES-CBC
    • DES-CTR
    • DES-OFB
    • DES-CFB
  3. $passwd 加密金鑰[密碼]

  4. $options 資料格式選項(可選)【選項有:】

    • 0
    • OPENSSL_RAW_DATA=1
    • OPENSSL_ZERO_PADDING=2
    • OPENSSL_NO_PADDING=3
  5. $iv 密初始化向量(可選)

  • 需要注意:如果 m e t h
    o d D E S E C B method為DES-ECB,則
    iv無需填寫

二、解密用到的方法:

openssl_decrypt($data, $method, $password, $options, $iv)

引數說明:

  1. $data 要解密的資料
  2. 其他引數同加密方法

三、用法案例:

引數:

   $data = '1234567887654321';//加密明文
   $method = 'DES-ECB';//加密方法
   $passwd = '12344321';//加密金鑰
   $options = 0;//資料格式選項(可選)
   $iv = '';//加密初始化向量(可選)

(1) 預設填充方式:

  • 加密:
    $result = openssl_encrypt($data, $method, $passwd, $options);
    var_dump($result);
    
    結果:
    string(32) "kQYOdswcm9I5elv2wdJucplqAgqDNqXg"
    
  • 解密
    $result = 'kQYOdswcm9I5elv2wdJucplqAgqDNqXg';
    var_dump(openssl_decrypt($result, $method, $passwd, 0));
    
    結果:
    string(16) "1234567887654321"
    

(2) OPENSSL_RAW_DATA方式【會用PKCS#7進行補位】

  • 加密
$result = openssl_encrypt($data, $method, $passwd, OPENSSL_RAW_DATA);
var_dump($result);

結果:

string(24) "�v���9z[���nr�j �6��"

我們可以看到結果是亂碼的,這時我們需要base64一下

$result = openssl_encrypt($data, $method, $passwd, OPENSSL_RAW_DATA);
var_dump(base64_encode($result));

這時結果是

string(32) "kQYOdswcm9I5elv2wdJucplqAgqDNqXg"
  • 解密
result = openssl_encrypt($data, $method, $passwd, OPENSSL_RAW_DATA);

var_dump(openssl_decrypt($result, $method, $passwd,OPENSSL_RAW_DATA));

結果:

string(16) "1234567887654321"

我們可以看到:預設填充方式與OPENSSL_RAW_DATA,這兩種方式加密結果是一樣的

(3) OPENSSL_ZERO_PADDING方式

看字面意思,是用0填充,但是測試並不起作用

  • 加密
$result = openssl_encrypt($data, $method, $passwd, OPENSSL_ZERO_PADDING);
var_dump($result);

結果:

string(24) "kQYOdswcm9I5elv2wdJucg==" 
  • 解密:
$result = openssl_encrypt($data, $method, $passwd, OPENSSL_ZERO_PADDING);
var_dump(openssl_decrypt($result, $method, $passwd,OPENSSL_ZERO_PADDING));

結果:

string(16) "1234567887654321"

(4) OPENSSL_NO_PADDING【不填充,需要手動填充】

  • 在openssl_encrypt前加上填充過程

  • 加密

      $str_padded = $data;
      if (strlen($str_padded) % 16) {
          $str_padded = str_pad($str_padded,strlen($str_padded) + 16 - strlen($str_padded) % 16, "\0");
      }
      $result = openssl_encrypt($str_padded, $method, $passwd, OPENSSL_NO_PADDING);
      var_dump($result);
      echo '<br>';
      var_dump( base64_encode($result));
    

    結果:

    string(16) "�v���9z[���nr" 
    string(24) "kQYOdswcm9I5elv2wdJucg=="
    

    我們可以看到結果是加密的亂碼,需要用base64一下,就可以看到結果了

  • 解密:

     //加密begin
      $str_padded = $data;
      if (strlen($str_padded) % 16) {
          $str_padded = str_pad($str_padded,strlen($str_padded) + 16 - strlen($str_padded) % 16, "\0");
      }
      $result = openssl_encrypt($str_padded, $method, $passwd, OPENSSL_NO_PADDING);
      //加密end
     //解密begin
     $str = base64_encode($result);
     $m = openssl_decrypt( base64_decode($str) , $method, $passwd, OPENSSL_NO_PADDING);
     var_dump( rtrim( rtrim( $m,chr(0) ), chr(7) ) );
     //解密 end
    

    結果:

    string(16) "1234567887654321"
    

** 結尾要去除填充字元’\0’和’\a’。
‘\a’是為了相容用OPENSSL_RAW_DATA加密的結果。 **

參照的文件有:

相關知識文章