10.1 对称加密

对称加密指的是采用单密钥进行加密,并且该密钥可以对数据进行加密和解密处理,目前这类加密算法安全性均比较高,数据的实际安全性取决于密钥的管理,就算黑客拿到加密后的数据,如果没有密钥,这些数据对于黑客来说也是垃圾数据而已,而拿到密钥之后可以对加密数据进行还原,所以笔者不建议使用对称加密对用户密码进行加密存储。它的原理比较简单,如图10-1所示。

图 10-1

明文数据123456可以在加密算法的作用下使用密钥0s9ansk2处理后变成d2fm83jjf,同样使用这个密钥也能把d2fm83jjf解密回123456。

在对称加密算法中常用的算法有DES、3DES、TDEA、Blowfish、RC2、RC4、RC5、IDEA、SKIPJACK、AES等。

10.1.1 3DES加密

DES(Data Encrypt Standard)又称Triple DES,是DES加密算法的一种模式,它使用3条56位的密钥对数据进行三次加密。DES加密算法是美国的一种由来已久的加密标准,这种算法通常用于加密需要传输的数据。

PHP中需要在php.ini中打开php_mcrypt.dll以及php_mcrypt_filter.dll两个lib库的引用,即去掉以下代码前面的分号:


extension=php_mcrypt.dll extension=php_mcrypt_filter.dll

PHP的3DES已经有很简洁成熟的加密,我们来看一个简单的3DES加解密类,代码如下:


< php

class Crypt3Des {

    public $key = "xxxx"
// 加密密钥

    function Crypt3Des
$key {

        $this->key=$key


    }

//
加密函数

function encrypt
$input {

    $size = mcrypt_get_block_size
MCRYPT_3DES 'ecb' );

    $input = $this->pkcs5_pad
$input $size );

    $key = str_pad
$this->key 24 '0' );

    $td = mcrypt_module_open
MCRYPT_3DES '' 'ecb' '' );

    $iv = @mcrypt_create_iv
mcrypt_enc_get_iv_size $td ), MCRYPT_RAND );

    @mcrypt_generic_init
$td $key $iv );

    $data = mcrypt_generic
$td $input );

    mcrypt_generic_deinit
$td );

    mcrypt_module_close
$td );

    $data = base64_encode
$data );

    return $data


}

//
解密函数

function decrypt
$encrypted {

    $encrypted = base64_decode
$encrypted );

    $key = str_pad
$this->key 24 '0' );

    $td = mcrypt_module_open
MCRYPT_3DES '' 'ecb' '' );

    $iv = @mcrypt_create_iv
mcrypt_enc_get_iv_size $td ), MCRYPT_RAND );

    $ks = mcrypt_enc_get_key_size
$td );

    @mcrypt_generic_init
$td $key $iv );

    $decrypted = mdecrypt_generic
$td $encrypted );

    mcrypt_generic_deinit
$td );

    mcrypt_module_close
$td );

    $y=$this->pkcs5_unpad
$decrypted );

    return $y


}

function pkcs5_pad
$text $blocksize {

    $pad = $blocksize -
strlen $text % $blocksize );

    return $text . str_repeat
chr $pad ), $pad );

}

function pkcs5_unpad
$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 );

}

function PaddingPKCS7
$data {

    $block_size = mcrypt_get_block_size
MCRYPT_3DES MCRYPT_MODE_CBC );

    $padding_char = $block_size -
strlen $data % $block_size );

    $data .= str_repeat
chr $padding_char ), $padding_char );

    return $data


    }

}
>

使用方法很简单,只要实例化这个类,直接调用相应函数即可,如下所示:


$rep=new Crypt3Des ' 加密 key' );

$input="hello 3des"


echo "
原文: ".$input."<br/>"

$encrypt_card=$rep->encrypt
$input );

echo "
加密: ".$encrypt_card."<br/>"

echo "
解密: ".$rep->decrypt $rep->encrypt $input ));

我们来看看经过它处理后的数据,如图10-2所示。

图 10-2

10.1.2 AES加密

AES(Advanced Encryption Standard)加密在密码学中又称Rijndael加密法,比3DES更加安全,密钥长度的最少支持为128、192、256位,所以逐渐替代原先的DES。

PHP中需要在php.ini中打开php_mcrypt.dll库的引用,设置方法我们已在上一小节介绍过,我们来看一个PHP中AES的加解密实例:


< php

class Aes{

  public $_secrect_key=''
// 密钥

  function Aes
$key {

      $this->_secrect_key = $key


  }

  /**

   *
加密方法

   * @param string $str

   * @return string

   */

  function encrypt
$str {

      //AES
128 ECB 模式加密数据

      $screct_key = $this->_secrect_key


      $screct_key = base64_decode
$screct_key );

      $str = trim
$str );

      $str = $this->addPKCS7Padding
$str );

      $iv = mcrypt_create_iv
mcrypt_get_iv_size MCRYPT_RIJNDAEL_128 MCRYPT_MODE_ECB ), MCRYPT_RAND );

      $encrypt_str =  mcrypt_encrypt
MCRYPT_RIJNDAEL_128 $screct_key $str MCRYPT_MODE_ECB $iv );

      return base64_encode
$encrypt_str );

  }

  /**

   *
解密方法

   * @param string $str

   * @return string

   */

  function decrypt
$str {

      //AES
128 ECB 模式加密数据

      $screct_key = $this->_secrect_key


      $str = base64_decode
$str );

      $screct_key = base64_decode
$screct_key );

      $iv = mcrypt_create_iv
mcrypt_get_iv_size MCRYPT_RIJNDAEL_128 MCRYPT_MODE_ECB ), MCRYPT_RAND );

      $encrypt_str =  mcrypt_decrypt
MCRYPT_RIJNDAEL_128 $screct_key $str MCRYPT_MODE_ECB $iv );

      $encrypt_str = trim
$encrypt_str );

      $encrypt_str = $this->stripPKSC7Padding
$encrypt_str );

      return $encrypt_str


  }

  /**

   *
填充算法

   * @param string $source

   * @return string

   */

  function addPKCS7Padding
$source {

      $source = trim
$source );

      $block = mcrypt_get_block_size
'rijndael-128' 'ecb' );

      $pad = $block -
strlen $source % $block );

      if
$pad <= $block {

          $char = chr
$pad );

          $source .= str_repeat
$char $pad );

      }

      return $source


  }

  /**

   *
移去填充算法

   * @param string $source

   * @return string

   */

  function stripPKSC7Padding
$source {

      $source = trim
$source );

      $char = substr
$source -1 );

      $num = ord
$char );

      if
$num==62 return $source

      $source = substr
$source 0 -$num );

      return $source


  }

}

这个加密类使用起来也相当简单:


$rep=new Aes 'xxxx' );

$input="hello aes"


echo "
原文: ".$input."<br/>"

$encrypt_card=$rep->encrypt
$input );

echo "
加密: ".$encrypt_card."<br/>"

echo "
解密: ".$rep->decrypt $rep->encrypt $input ));

我们来看看使用它加解密后的效果,如图10-3所示。

图 10-3