1. 程式人生 > 實用技巧 >PHP版DES演算法加密資料

PHP版DES演算法加密資料

php7之前的版本

function encrypt($input)
{
    if (version_compare(PHP_VERSION, '7.0.0') >= 0) {
        $size = 16;
        $k = C('KEY_LONG');
        $input = pkcs5_pad($input, $size);

        $data = openssl_encrypt($input, 'AES-128-CBC', $k, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $k);
    } else {
        $size = 8;
        $k = C('KEY_SHORT');
        $input = pkcs5_pad($input, $size);

        $td = mcrypt_module_open(MCRYPT_DES, '', 'cbc', '');
        mcrypt_generic_init($td, $k, $k);
        $data = mcrypt_generic($td, $input);
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);
    }
    $data = base64_encode($data);
    return $data;
}

function decrypt($input)
{
    $crypt = base64_decode($input);
    if (version_compare(PHP_VERSION, '7.0.0') >= 0) {
        $size = 16;
        $k = C('KEY_LONG');

        $data = openssl_decrypt($crypt, 'AES-128-CBC', $k, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $k);
    } else {
        $size = 8;
        $k = C('KEY_SHORT');

        $td = mcrypt_module_open(MCRYPT_DES, '', 'cbc', '');
        mcrypt_generic_init($td, $k, $k);
        $data = mdecrypt_generic($td, $crypt);
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);
    }
    $data = pkcs5_unpad($data);
    $data = rtrim($data);
    return $data;
}
function pkcs5_pad($_var_308, $_var_309)
{
    $_var_310 = $_var_309 - strlen($_var_308) % $_var_309;
    return $_var_308 . str_repeat(chr($_var_310), $_var_310);
}

function pkcs5_unpad($_var_308)
{
    $_var_310 = ord($_var_308[strlen($_var_308) - 1]);
    if ($_var_310 > strlen($_var_308)) {
        return false;
    }
    return substr($_var_308, 0, -1 * $_var_310);
}

php7之後的版本

class Des
{
    private static $_instance = NULL;
    var $key;//祕鑰向量
    var $iv;//混淆向量 ->偏移量
 
    function __construct()
    {
        $this->key = env('DES_KEY');
        $this->iv = env('DES_IV');
    }
 
    /**
     *
     * @User yaokai
     * @return Des|null
     */
    public static function share()
    {
        if (is_null(self::$_instance)) {
            self::$_instance = new Des();
        }
        return self::$_instance;
    }
 
    /**
     * 加密演算法
     * @User yaokai
     * @param $input 要加密的資料
     * @return string 返回加密後的字串
     */
    function encrypt($input)
    {
        //獲得加密演算法的分組大小  8
        $size = mcrypt_get_block_size(MCRYPT_DES, MCRYPT_MODE_CBC); //3DES加密將MCRYPT_DES改為MCRYPT_3DES
        //ascii 填充
        $input = $this->pkcs5_pad($input, $size); //如果採用PaddingPKCS7,請更換成PaddingPKCS7方法。
        //用0填充祕鑰為指定長度8
        $key = str_pad($this->key, 8, '0'); //3DES加密將8改為24
        //開啟演算法和模式對應的模組
        $td = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_CBC, '');
        //判斷混淆向量是否為空
        if ($this->iv == '') {
            //從演算法源隨機生成混淆向量
            $iv = @mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);//類似b"¨ß^\f\x1EÅ╩5"
        } else {
            //反之取設定的混淆向量
            $iv = $this->iv;
        }
        //初始化加密所需的緩衝區
        @mcrypt_generic_init($td, $key, $iv);
        //加密資料  $td為演算法物件模組  $input為處理過後的值
        $data = mcrypt_generic($td, $input);// 類似b"ýyP\x7FN\x00èiÝd>À?s\x18Î"
        //對加密模組進行清理工作
        mcrypt_generic_deinit($td);
        //關閉加密模組
        mcrypt_module_close($td);
        //使用 MIME base64 對資料進行編碼
        $data = base64_encode($data);//如需轉換二進位制可改成 bin2hex 轉換
        //如果設定了混淆向量 則加密的值是固定的   如果沒設定混淆向量 則加密的值是隨機的
        return $data;
    }
 
 
    /**
     * 解密演算法
     * @User yaokai
     * @param $encrypted 加密後的字串
     * @return bool|string
     */
    function decrypt($encrypted)
    {
        //對使用 MIME base64 編碼的資料進行解碼
        $encrypted = base64_decode($encrypted); //如需轉換二進位制可改成 bin2hex 轉換
        //使用另一個字串填充字串為指定長度 獲取祕鑰
        $key = str_pad($this->key, 8, '0'); //3DES加密將8改為24
        //開啟演算法和模式對應的模組
        $td = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_CBC, '');//3DES加密將MCRYPT_DES改為MCRYPT_3DES
        //判斷混淆向量是否為空
        if ($this->iv == '') {
            //從演算法源隨機生成混淆向量
            $iv = @mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
        } else {
            //反之取設定的混淆向量
            $iv = $this->iv;
        }
        //返回開啟的模式所能支援的最長金鑰  沒用上
        $ks = mcrypt_enc_get_key_size($td);//DES 8   3DES 24
        //初始化加密所需的緩衝區
        @mcrypt_generic_init($td, $key, $iv);
        //解密資料  $td為演算法物件模組  $encrypted為需要解密的資料
        $decrypted = mdecrypt_generic($td, $encrypted);//類似於 "15549070665\x05\x05\x05\x05\x05" 之前加密的資料
        //對加密模組進行清理工作
        mcrypt_generic_deinit($td);
        //關閉加密模組
        mcrypt_module_close($td);
        //返回取出解密資料
        $data = $this->pkcs5_unpad($decrypted);
 
        return $data;
    }
 
    /**
     * 填補需加密的字串
     * PKCS7Padding VS PKCS5Padding
     * 區別,PKCS5Padding的blocksize為8位元組,而PKCS7Padding的blocksize可以為1到255位元組
     * @User yaokai
     * @param $text
     * @param $blocksize
     * @return string
     */
    function pkcs5_pad($text, $blocksize)
    {
        //$pad=5  blocksize=11  $test=8  %取餘
        $pad = $blocksize - (strlen($text) % $blocksize);//5
        //返回ascii填補後的字串, 類似 "15549070665\x05\x05\x05\x05\x05"
        return $text . str_repeat(chr($pad), $pad);
    }
 
    /**
     * 去除加密填補的字串
     * PKCS7Padding VS PKCS5Padding
     * 區別,PKCS5Padding的blocksize為8位元組,而PKCS7Padding的blocksize可以為1到255位元組
     * @User yaokai
     * @param $text
     * @return bool|string
     */
    function pkcs5_unpad($text)
    {
        //取出最後一個字串 {15}   ord返回字元的 ASCII 碼值
        $pad = ord($text{strlen($text) - 1});//5
        //判斷$pad的值是否大於本身字串
        if ($pad > strlen($text)) {
            //如果大於  則多餘
            return false;
        }
        //計算ASCII 碼值中全部字元都存在於$text字元集合中的第一段子串的長度是否等於取出的$pad
        if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) {
            //如果不相等  則缺失
            return false;
        }
        //返回字串的子串
        return substr($text, 0, -1 * $pad);
    }
 
 
    /**
     * 填補需加密的字串
     * PKCS7Padding VS PKCS5Padding
     * 區別,PKCS5Padding的blocksize為8位元組,而PKCS7Padding的blocksize可以為1到255位元組
     * @User yaokai
     * @param $text
     * @param $blocksize
     * @return string
     */
    function PaddingPKCS7($data)
    {
        $block_size = mcrypt_get_block_size(MCRYPTDES, MCRYPT_MODE_CBC);//3DES加密將MCRYPT_DES改為MCRYPT_3DES
        $padding_char = $block_size - (strlen($data) % $block_size);
        $data .= str_repeat(chr($padding_char), $padding_char);
        return $data;
    }
 
 
    /**
     * 去除加密填補的字串
     * PKCS7Padding VS PKCS5Padding
     * 區別,PKCS5Padding的blocksize為8位元組,而PKCS7Padding的blocksize可以為1到255位元組
     * @User yaokai
     * @param $text
     * @return bool|string
     */
    private function UnPaddingPKCS7($text)
    {
        $pad = ord($text{strlen($text) - 1});
        if ($pad > strlen($text)) {
            return false;
        }
        if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) {
            return false;
        }
        return substr($text, 0, -1 * $pad);
    }
 
 
}