最近在對接客戶的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)
引數說明:
- $data 加密明文
-
$method 加密方法
- DES-ECB
- DES-CBC
- DES-CTR
- DES-OFB
- DES-CFB
- $passwd 加密金鑰[密碼]
-
$options 資料格式選項(可選)【選項有:】
- 0
- OPENSSL_RAW_DATA=1
- OPENSSL_ZERO_PADDING=2
- OPENSSL_NO_PADDING=3
- $iv 密初始化向量(可選)
-
需要注意:如果$method為DES-ECB,則$iv無需填寫
二、解密用到的方法:
openssl_decrypt($data, $method, $password, $options, $iv)
引數說明:
- $data 要解密的資料
- 其他引數同加密方法
三、用法案例:
引數:
$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, " "); } $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, " "); } $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加密的結果。 **
參照的文件有:
- PHP 基礎篇 – PHP 中 DES 加解密詳解
https://www.jianshu.com/p/546… - 關於mcrypt_encrypt和openssl_encrypt加密結果不一致的解決
http://www.heylc.com/fuanyuop…
相關知識文章
- RSA密碼傳輸加密方案
https://wenku.baidu.com/view/… - iOS 實現對稱加密多種填充方式(ANSIX923、ISO10126、Zero)
https://www.jianshu.com/p/7b6… - PHP由mcrypt擴充套件加密改為openssl擴充套件加密
https://www.xxling.com/blog/a… - PHP用openssl_encrypt代替mcrypt_encrypt
https://coderlife.cn/1624.html - AES加密CBC模式相容互通四種程式語言平臺【PHP、Javascript、Java、C#】
https://my.oschina.net/Jacker… - 在PHP7.1中使用openssl取代mcrypt
https://swoole.app/2018/05/15… - PHP openssl加密擴充套件使用總結
https://www.bbsmax.com/A/ke5j… - PHP 7.2+使用openssl進行加解密
https://www.lytit.com/2018/01… - PHP OpenSSL擴充套件 – 對稱加密
https://www.jianshu.com/p/8f8… - DES 加解密工具
http://tool.chacuo.net/cryptdes - RSA填充方式
https://www.jianshu.com/p/205… - AES加密模式和填充方式,hash,md5,ca
http://blog.sina.com.cn/s/blo…