>  기사  >  백엔드 개발  >  PHP 보안-암호화

PHP 보안-암호화

黄舟
黄舟원래의
2017-02-20 09:04:041088검색



암호화

보안에 관한 책에서 암호화는 반드시 언급해야 할 주제입니다. 내가 이 책의 주요 부분에서 암호화를 무시하는 이유는 암호화의 사용 범위가 좁고 개발자는 보안을 더 큰 그림에서 생각해야 하기 때문입니다. 암호화에 대한 과도한 의존으로 인해 문제의 원인이 모호해지는 경우가 많습니다. 암호화 자체는 효과적이지만 이를 암호화한다고 해서 마법처럼 애플리케이션이 더 안전해지는 것은 아닙니다.

PHP 개발자는 주로 다음 암호화 방법에 익숙해야 합니다.

l 대칭 암호화

l 비대칭 암호화(공개 키)

l 해시 함수(정보 요약)

l 정보 확인 코드

이 부록은 주로 mcrypt 확장자를 사용하는 대칭 암호화 알고리즘에 중점을 둡니다. 참고하셔야 할 내용은 다음과 같습니다.

Applied Cryptography, by Bruce Schneier (와일리)

http://www.php.cn/

http://www.php.cn/

http://www.php.cn/

http://www.php.cn/

http://www.php.cn/

C.1 비밀번호 보관

데이터베이스에 비밀번호를 저장할 때 비밀번호의 해시를 저장하고 다음 문자열을 사용하세요.

<?php
 
  /* $password contains the password. */
 
  $salt = &#39;SHIFLETT&#39;;
  $password_hash = md5($salt . md5($password .
$salt));
 
  /* Store password hash. */
 
  ?>


비밀번호가 맞는지 확인해야 할 경우에도 같은 방법으로 계산하여 해시 값을 해시하고 유사점과 차이점을 비교합니다.

  <?php
 
  $salt = &#39;SHIFLETT&#39;;
  $password_hash = md5($salt .
md5($_POST[&#39;password&#39;] . $salt));
 
  /* Compare password hashes. */
 
  ?>


해시 값이 정확히 동일하다면 비밀번호도 동일하다고 생각할 이유가 있습니다.

이 트릭을 사용하면 사용자에게 비밀번호가 무엇인지 알려주는 것이 불가능합니다. 사용자가 비밀번호를 잊어버린 경우 새 비밀번호를 입력하고 해시 값을 다시 계산하여 데이터베이스에 저장하도록 요청할 수 있습니다. 물론 사용자 인증에 매우 주의해야 합니다. 비밀번호 알림은 공격의 빈번한 대상이자 보안 침해의 빈번한 원인입니다.

C.2 mcrypt를 사용하세요

PHP의 표준 암호화 확장은 다양한 암호화 알고리즘을 지원하는 mcrypt입니다. mcrypt_list_algorithms( ) 기능을 사용하여 플랫폼에서 지원되는 알고리즘 목록을 확인하세요:

 <?php
 
  echo &#39;<pre class="brush:php;toolbar:false">&#39; .
print_r(mcrypt_list_algorithms(), TRUE) . &#39;
'; ?>


암호화와 복호화는 각각 mcrypt_encrypt( )와 mcrypt_decrypt( )로 수행됩니다. ) 기능을 구현합니다. 두 함수 모두 5개의 매개변수가 있습니다.

 <?php
 
  mcrypt_encrypt($algorithm,
                 $key,
                 $cleartext,
                 $mode,
                 $iv);
 
  mcrypt_decrypt($algorithm,
                 $key,
                 $ciphertext,
                 $mode,
                 $iv);
 
  ?>


암호화 키(두 번째 매개변수)는 매우 민감한 데이터이므로 안전한 곳에 보관하는 것이 좋습니다. 암호화 키는 8장의 데이터베이스 권한 보호 방법을 사용하여 보호할 수 있습니다. 재정 상황이 허락한다면 매우 강력한 보안을 제공하는 하드웨어 암호화 키가 최선의 선택입니다.

이 함수에는 선택할 수 있는 여러 모드가 있으며, mcrypt_list_modes( ) 지원되는 모든 모드를 나열하려면:

<?php
 
  echo &#39;<pre class="brush:php;toolbar:false">&#39; . print_r(mcrypt_list_modes(),
TRUE) . &#39;
'; ?>


5장 매개변수($iv)는 mcrypt_create_iv() 함수를 사용하여 생성할 수 있는 초기화 벡터입니다.

다음 예제 클래스는 기본 암호화 및 복호화 방법을 제공합니다.

  class crypt
  {
    private $algorithm;
    private $mode;
    private $random_source;
 
    public $cleartext;
    public $ciphertext;
    public $iv;
 
    public function __construct($algorithm =
MCRYPT_BLOWFISH,
                                $mode =
MCRYPT_MODE_CBC,
                                $random_source =
MCRYPT_DEV_URANDOM)
    {
      $this->algorithm = $algorithm;
      $this->mode = $mode;
      $this->random_source = $random_source;
    }
 
    public function generate_iv()
    {
      $this->iv =
mcrypt_create_iv(mcrypt_get_iv_size($this->algorithm,
        $this->mode),
$this->random_source);
    }
 
    public function encrypt()
    {
      $this->ciphertext =
mcrypt_encrypt($this->algorithm,
        $_SERVER[&#39;CRYPT_KEY&#39;], $this->cleartext,
$this->mode, $this->iv);
    }
 
    public function decrypt()
    {
      $this->cleartext =
mcrypt_decrypt($this->algorithm,
        $_SERVER[&#39;CRYPT_KEY&#39;], $this->ciphertext,
$this->mode, $this->iv);
    }
  }
 
  ?>


  上面的类会在其它示例中使用,下面是它的使用方法示例:

 

<?php
 
  $crypt = new crypt();
 
  $crypt->cleartext = &#39;This is a string&#39;;
  $crypt->generate_iv();
  $crypt->encrypt();
 
  $ciphertext =
base64_encode($crypt->ciphertext);
  $iv = base64_encode($crypt->iv);
 
  unset($crypt);
 
  /* Store $ciphertext and $iv (initialization
vector). */
 
  $ciphertext = base64_decode($ciphertext);
  $iv = base64_decode($iv);
 
  $crypt = new crypt();
 
  $crypt->iv = $iv;
  $crypt->ciphertext = $ciphertext;
  $crypt->decrypt();
 
  $cleartext = $crypt->cleartext;
 
  ?>


 

小提示

  本扩展要求你在编译PHP时使用-mcrypt标识。安装指南及要求详见http://www.php.cn/。

 

C.3. 信用卡号的保存

  我常常被问到如何安全地保存信用卡号。我的总是会首先询问他们是否确实有必要保存信用卡号。毕竟不管具体是如何操作的,引入不必要的风险是不明智的。同时国家法律还有关于信用卡信息处理方面的规定,我还时刻小心地提醒我并不是一个法律专家。

  本书中我并不会专门讨论信用卡处理的方法,而是会说明如何保存加密信息到数据库及在读取时解密。该流程会导致系统性能的下降,但是确实提供了一层保护措施。其主要优点是如果数据库内容泄密暴露出的只是加密信息,但是前提是加密键是安全的。因此,加密键与加密的实现方法本身同样重要。

  保存加密数据到数据的过程是,首先加密数据,然后通过初始向量与明文建立密文来保存到数据库。由于密文是二进制字符串,还需要通过base64_encode( )转换成普通文本字符串以保证二进制编码的安全存储。

 

<?php
 
  $crypt = new crypt();
 
  $crypt->cleartext = &#39;1234567890123456&#39;;
  $crypt->generate_iv();
  $crypt->encrypt();
 
  $ciphertext = $crypt->ciphertext;
  $iv = $crypt->iv;
 
  $string = base64_encode($iv . $ciphertext);
 
  ?>


 

  保存该字串至数据库。在读取时,则是上面流程的逆处理:

 

  <?php
 
  $string = base64_decode($string);
 
  $iv_size = mcrypt_get_iv_size($algorithm,
$mode);
 
  $ciphertext = substr($string, $iv_size);
  $iv = substr($string, 0, $iv_size);
 
  $crypt = new crypt();
 
  $crypt->iv = $iv;
  $crypt->ciphertext = $ciphertext;
  $crypt->decrypt();
 
  $cleartext =  $crypt->cleartext;
 
  ?>


 

  本实现方法假定加密算法与模式不变。如果它们是不定的话,你还要保存它们以用于解密数据。加密键是唯一需要保密的数据。

 

C.4. 加密会话数据

  如果你的数据库存在安全问题,或者部分保存在会话中的数据是敏感的,你可能希望加密会话数据。除非很有必要,一般我不推荐这样做,但是如果你觉得在你的情形下需要这样做的话,本节提供了一个实现方法的示例。

  这个方案十分简单。实际上,在第八章中,已经说明了如何通过调用session_set_save_handler( )来执行你自己的会话机制。通过对保存和读取数据的函数的少量调整,你就能加密存入数据库的数据及在读取时解密数据:

 

 <?php
 
  function _read($id)
  {
    global $_sess_db;
 
    $algorithm = MCRYPT_BLOWFISH;
    $mode = MCRYPT_MODE_CBC;
 
    $id = mysql_real_escape_string($id);
 
    $sql = "SELECT data
            FROM   sessions
            WHERE  id = &#39;$id&#39;";
 
    if ($result = mysql_query($sql, $_sess_db))
    {
        $record = mysql_fetch_assoc($result);
 
        $data = base64_decode($record[&#39;data&#39;]);
 
        $iv_size = mcrypt_get_iv_size($algorithm,
$mode);
 
        $ciphertext = substr($data, $iv_size);
        $iv = substr($data, 0, $iv_size);
 
        $crypt = new crypt();
 
        $crypt->iv = $iv;
        $crypt->ciphertext = $ciphertext;
        $crypt->decrypt();
 
        return $crypt->cleartext;
    }
 
    return &#39;&#39;;
  }
 
  function _write($id, $data)
  {
    global $_sess_db;
 
    $access = time();
 
    $crypt = new crypt();
 
    $crypt->cleartext = $data;
    $crypt->generate_iv();
    $crypt->encrypt();
 
    $ciphertext = $crypt->ciphertext;
    $iv = $crypt->iv;
 
    $data = base64_encode($iv . $ciphertext);
 
    $id = mysql_real_escape_string($id);
    $access = mysql_real_escape_string($access);
    $data = mysql_real_escape_string($data);
 
    $sql = "REPLACE
            INTO    sessions
            VALUES  (&#39;$id&#39;, &#39;$access&#39;,
&#39;$data&#39;)";
 
    return mysql_query($sql, $_sess_db);
  }

 以上就是PHP安全-加密的内容,更多相关内容请关注PHP中文网(www.php.cn)!


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.