php中使用openssl_encrypt代替mcrypt_encrypt實現js加密php解密的方法

項目背景

  • 由於本身開發的接口但願在傳遞的工程中能夠保證參數是密文的形式,主要是前端使用js加密,後端使用php解密javascript

  • 在網絡上搜索了不少的方法,可是大部分的都是使用mcrypt_decrypt和mcrypt_encrypt進行php端的加解密,可是衆所周知的問題,這兩個方法在php7.1之後將會被廢棄,故而採用。php

實現方式說明

  • php使用mcrypt_decrypt和mcrypt_encrypt的組合方式,以及openssl_decrypt和openssl_encrypt的組合方式css

  • js端使用Crypto-jshtml

  • 爲了說明兩種方式的區別,在使用mcrypt_decrypt和mcrypt_encrypt方式的時候,使用crypto-helper-zeropadding.js來命名自定義的js加密幫助類,使用test_crypto_zeropadding.html來命令對應的測試html文件;在使用openssl_decrypt和openssl_encrypt的組合方式的時候,使用crypto-helper-pkcs7.js來命名自定義的js加密幫助類,使用test_crypto_pcks7.html來命名測試頁面 ,詳細的區別能夠參見 帖子
    https://segmentfault.com/q/10...前端

demo地址

github地址java

方法一 :使用mcrypt_decrypt和mcrypt_encrypt

php加密解密類

<?php

class AesJs
{
    /**向量
     * @var string
     */
    const IV = "1234567890123412";//16位
    /**
     * 默認祕鑰
     */
    const KEY = '201707eggplant99';//16位

    public static function init($iv = '')
    {
        self::$iv = $iv;
    }

    /**
     * 加密字符串
     * @param string $data 字符串
     * @param string $key 加密key
     * @return string
     */
    public static function encrypt($data = '', $key = self::KEY)
    {
        $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, self::$iv);
        return base64_encode($encrypted);
    }

    /**
     * 解密字符串
     * @param string $data 字符串
     * @param string $key  加密key
     * @return string
     */
    public static function decrypt($data = '', $key = self::KEY)
    {
        $decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, base64_decode($data), MCRYPT_MODE_CBC, self::$iv);
        return rtrim($decrypted, "\0");
    }



    public static function pkcs7_pad($str){
        $len = mb_strlen($str, '8bit');
        $c = 16 - ($len % 16);
        $str .= str_repeat(chr($c), $c);
        return $str;
    }

}

js端的關鍵代碼

自定義封裝的crypto-helper-zeropadding.js

var IV = '1234567890123412';

var KEY = '201707eggplant99'
/**
 * 加密
 */
function encrypt(str) {
    key = CryptoJS.enc.Utf8.parse(KEY);// 祕鑰
    var iv= CryptoJS.enc.Utf8.parse(IV);//向量iv
    var encrypted = CryptoJS.AES.encrypt(str, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.ZeroPadding });
    return encrypted.toString();
}
/**
 * 解密
 * @param str
 */
function decrypt(str) {
    var key = CryptoJS.enc.Utf8.parse(KEY);// 祕鑰
    var iv=    CryptoJS.enc.Utf8.parse(IV);//向量iv
    var decrypted = CryptoJS.AES.decrypt(str,key,{iv:iv,padding:CryptoJS.pad.ZeroPadding});
    return decrypted.toString(CryptoJS.enc.Utf8);
}

js測試調用頁面test_crypto_zeropadding.html

<html>
<head>test crypto-js</head>
<script src="crypto-js/aes.js" type="text/javascript"></script>
<script src="crypto-js/md5.js" type="text/javascript"></script>
<script src="crypto-js/components/pad-zeropadding-min.js" type="text/javascript"></script>
<script src="crypto-helper-zeropadding.js" type="text/javascript"></script>

<script type="text/javascript">

var data = '111111';
var encode = encrypt(data);
console.log('encode is =======>'+encode);
var decode = decrypt(encode);
console.log('decode is =======>'+decode);
alert('encode is ====>'+encode+',decode is ====>'+decode);
</script>


</html>

js端頁面運行效果

clipboard.png

方法二 :openssl_decrypt和openssl_encrypt的組合方式

php加密解密類

<?php
/*
+--------------------------------------------------------------------------
|   因爲在php7.1以後mcrypt_encrypt會被廢棄,所以使用openssl_encrypt方法來替換
|   ========================================
|   by Focus
|   ========================================
|
|
+---------------------------------------------------------------------------
*/
class OpensslEncryptHelper
{
    /**向量
     * @var string
     */
    const IV = "1234567890123412";//16位
    /**
     * 默認祕鑰
     */
    const KEY = '201707eggplant99';//16位

    /**
     * 解密字符串
     * @param string $data 字符串
     * @param string $key 加密key
     * @return string
     */
    public static function decryptWithOpenssl($data,$key = self::KEY,$iv = self::IV){
        return openssl_decrypt(base64_decode($data),"AES-128-CBC",$key,OPENSSL_RAW_DATA,$iv);
    }

    /**
     * 加密字符串
     * 參考網站: https://segmentfault.com/q/1010000009624263
     * @param string $data 字符串
     * @param string $key 加密key
     * @return string
     */
    public static function encryptWithOpenssl($data,$key = self::KEY,$iv = self::IV){

//        echo base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, "1234567890123456", pkcs7_pad("123456"), MCRYPT_MODE_CBC, "1234567890123456"));
//        echo base64_encode(openssl_encrypt("123456","AES-128-CBC","1234567890123456",OPENSSL_RAW_DATA,"1234567890123456"));
//        $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, self::$iv);
//        return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, "1234567890123456", pkcs7_pad("123456"), MCRYPT_MODE_CBC, "1234567890123456"));
        return base64_encode(openssl_encrypt($data,"AES-128-CBC",$key,OPENSSL_RAW_DATA,$iv));
    }


}

js端的關鍵代碼

自定義封裝的crypto-helper-pkcs7.js

var IV = '1234567890123412';

var KEY = '201707eggplant99'
/**
 * 加密
 */
function encrypt(str) {
    key = CryptoJS.enc.Utf8.parse(KEY);// 祕鑰
    var iv= CryptoJS.enc.Utf8.parse(IV);//向量iv
    var encrypted = CryptoJS.AES.encrypt(str, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7});
    return encrypted.toString();
}
/**
 * 解密
 * @param str
 */
function decrypt(str) {
    var key = CryptoJS.enc.Utf8.parse(KEY);// 祕鑰
    var iv=    CryptoJS.enc.Utf8.parse(IV);//向量iv
    var decrypted = CryptoJS.AES.decrypt(str,key,{iv:iv,padding:CryptoJS.pad.Pkcs7});
    return decrypted.toString(CryptoJS.enc.Utf8);
}

test_crypto_pcks7.html代碼

<html>
<head>test crypto-js</head>
<script src="crypto-js/aes.js" type="text/javascript"></script>
<script src="crypto-js/md5.js" type="text/javascript"></script>
<script src="crypto-js/components/pad-zeropadding-min.js" type="text/javascript"></script>
<script src="crypto-helper-pkcs7.js" type="text/javascript"></script>

<script type="text/javascript">

var data = '111111';
var encode = encrypt(data);
console.log('encode is =======>'+encode);
var decode = decrypt(encode);
console.log('decode is =======>'+decode);
alert('encode is ====>'+encode+',decode is ====>'+decode);

</script>


</html>

參考資料

前端基於jsencrypt、php基於openssl的rsa非對稱加密的實現git

PHP OpenSSL&Mcrypt實現AES加密github

crypto-js項目地址segmentfault

爲何 CryptoJS DES 加密的結果和 Java DES 不同後端

JS AES加密與PHP解密

相關文章
相關標籤/搜索