Mcrypt模块简介(译)

在这篇教程中你将学到如何使用PHP自带的Mcrypt函数进行加密和解密。Mcypt 库 (http://mcrypt.sourceforge.net/), 让加密/解密变的非常容易。 Mcrypt 支持非常多的加密算法,一定能够满足你的需求. 在教程中,我可能不会涉及所有Mcrypt支持的算法和模块,但是我会提供一个简单的加密接口一边从php访问。虽然mcrypt提供了相当好用的加密方式,但没有任何加密时牢不可破的,因此你把加密过的信息保存在数据库或其他类似的足够安全的地方。

教程需求:
+ 任何安装有PHP 4.x 或者 PHP 5.x的web服务器
+ 编译进php的Mcrypt模块或者作为一个共享模块存在(需要 libmcrypt)

为什么我们使用Mcrypt?
和hash算法相比, 比如: md5, sha1, 或其他加密算法,他们只允许信息加密后以便以后验证比较使用, Mcrypt 允许人们轻松地加密并且解密信息, mcrypt 提供的两种加密方式有着非常广泛的应用,包括但不限于:
+ 安全储存机密信息 (ie: 密码, 信用卡号码, 身份证号码, etc)
+ 安全的信息验证 (ie: email, 服务器与服务器通信, 应用和应用间的通信, etc)
+ 安全储存文件 (ie: 私钥, 安全证书, etc )

mcrypt 同样提供了丰富的加密模式:
+ ECB (electronic codebook) 适用于较小量的数据,如积分值等。
+ CBC (cipher block chaining) 适用于加密大量的数据,如文件。
+ CFB (cipher feedback) 适用于数据量非常小的加密,其中每个字节都会被加密,安全程度高

根据你安装的 libmcrypt/mcrypt 的版本, mcrypt 支持很多种加密算法:
3DES
ARCFOUR_IV (libmcrypt > 2.4.x only)
ARCFOUR (libmcrypt > 2.4.x only)
BLOWFISH
CAST_128
CAST_256
CRYPT
DES
DES_COMPAT (libmcrypt 2.2.x only)
ENIGMA (libmcrypt > 2.4.x only, alias for CRYPT)
GOST
IDEA (non-free)
LOKI97 (libmcrypt > 2.4.x only)
MARS (libmcrypt > 2.4.x only, non-free)
PANAMA (libmcrypt > 2.4.x only)
RIJNDAEL_128 (libmcrypt > 2.4.x only)
RIJNDAEL_192 (libmcrypt > 2.4.x only)
RIJNDAEL_256 (libmcrypt > 2.4.x only)
RC2
RC4 (libmcrypt 2.2.x only)
RC6 (libmcrypt > 2.4.x only)
RC6_128 (libmcrypt 2.2.x only)
RC6_192 (libmcrypt 2.2.x only)
RC6_256 (libmcrypt 2.2.x only)
SAFER64
SAFER128
SAFERPLUS (libmcrypt > 2.4.x only)
SERPENT(libmcrypt > 2.4.x only)
SERPENT_128 (libmcrypt 2.2.x only)
SERPENT_192 (libmcrypt 2.2.x only)
SERPENT_256 (libmcrypt 2.2.x only)
SKIPJACK (libmcrypt > 2.4.x only)
TEAN (libmcrypt 2.2.x only)
THREEWAY
TRIPLEDES (libmcrypt > 2.4.x only)
TWOFISH (for older mcrypt 2.x versions, or mcrypt > 2.4.x )
TWOFISH128 (TWOFISHxxx are available in newer 2.x versions, but not in the 2.4.x versions)
TWOFISH192
TWOFISH256
WAKE (libmcrypt > 2.4.x only)
XTEA (libmcrypt > 2.4.x only)

最后推荐一个Mcrypt的加密类,phpFreaksCrypto Class (PHP4)
这个类会帮你完成绝大部分加密解密的工作,你只需要掌握一些最基本的使用方法即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
<?php  
 
/*  
 * phpFreaksCrypto.class.php4 -> phpFreaksCrypto Class (PHP4)  
 */  
 
/**  
  * @author Dustin Whittle  
  * @version 0.01  
  */  
 
if (realpath(__FILE__) == realpath($_SERVER['SCRIPT_FILENAME']))  
{  
  // tell people trying to access this file directly goodbye...  
  exit('This file can not be accessed directly...');  
}  
 
class phpFreaksCrypto  
{  
 
  var $td;  
 
  // this gets called when class is instantiated  
  function phpFreaksCrypto($key = 'MyRandomStringThatWillAlwaysBeTheSame', $iv = false, $algorithm = 'tripledes', $mode = 'ecb') 
  {  
 
    if(extension_loaded('mcrypt') === FALSE)  
    {  
      $prefix = (PHP_SHLIB_SUFFIX == 'dll') ? 'php_' : '';  
      dl($prefix . 'mcrypt.' . PHP_SHLIB_SUFFIX) or die('The Mcrypt module could not be loaded.');  
    }  
 
    if($mode != 'ecb' && $iv === false)  
    {  
      /*  
        the iv must remain the same from encryption to decryption and is usually  
        passed into the encrypted string in some form, but not always.  
      */  
      die('In order to use encryption modes other then ecb, you must specify a unique and consistent initialization vector.');  
    }  
 
    // set mcrypt mode and cipher  
    $this->td = mcrypt_module_open($algorithm, '', $mode, '') ;  
 
    // Unix has better pseudo random number generator then mcrypt, so if it is available lets use it!  
    $random_seed = strstr(PHP_OS, "WIN") ? MCRYPT_RAND : MCRYPT_DEV_RANDOM;  
 
    // if initialization vector set in constructor use it else, generate from random seed  
    $iv = ($iv === false) ? mcrypt_create_iv(mcrypt_enc_get_iv_size($this->td), $random_seed) : substr($iv, 0, mcrypt_enc_get_iv_size($this->td));  
 
    // get the expected key size based on mode and cipher  
    $expected_key_size = mcrypt_enc_get_key_size($this->td);  
 
    // we dont need to know the real key, we just need to be able to confirm a hashed version  
    $key = substr(md5($key), 0, $expected_key_size);  
 
    // initialize mcrypt library with mode/cipher, encryption key, and random initialization vector  
    mcrypt_generic_init($this->td, $key, $iv);  
  }  
 
  function encrypt($plain_string)  
  {  
    /*  
      encrypt string using mcrypt and then encode any special characters  
      and then return the encrypted string  
    */  
    return base64_encode(mcrypt_generic($this->td, $plain_string));  
  }  
 
  function decrypt($encrypted_string)  
  {  
    /*  
      remove any special characters then decrypt string using mcrypt and then trim null padding  
      and then finally return the encrypted string  
    */  
    return trim(mdecrypt_generic($this->td, base64_decode($encrypted_string)));  
  }  
 
  // since php 4 does not have deconstructors, we will need to manually call this function  
  function __destruct()  
  {  
    // shutdown mcrypt  
    mcrypt_generic_deinit($this->td);  
 
    // close mcrypt cipher module  
    mcrypt_module_close($this->td);  
  }  
 
}  
?>

一个简单的示例 (PHP4)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php  
 
require_once('phpFreaksCrypto.class.php4'); // require the phpFreaksCrypto class 
 
$crypto = new phpFreaksCrypto();  
$the_string_to_be_encrypted = 'blah.blah.blah';  
$the_string_that_is_encrypted = $crypto->encrypt($the_string_to_be_encrypted);  
$the_encrypted_string_decrypted = $crypto->decrypt($the_string_that_is_encrypted);  
$crypto->__destruct();  
 
echo 'Original: ' . $the_string_to_be_encrypted . '<br />';  
echo 'Encrypted: ' . $the_string_that_is_encrypted . '<br />';  
echo 'Decrypted: ' . $the_encrypted_string_decrypted . '<br />';  
?>

适用于PHP5的 phpFreaksCrypto Class (PHP5)
这两个类只是有些语法上的差别,引入了PHP5的一些新的特性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
<?php  
 
/*  
 * phpFreaksCrypto.class.php5 -> phpFreaksCrypto Class (PHP5)  
 */  
 
 /**  
  * @author Dustin Whittle  
  * @version 0.01  
  */  
 
if (realpath(__FILE__) == realpath($_SERVER['SCRIPT_FILENAME']))  
{  
  // tell people trying to access this file directly goodbye...  
  exit('This file can not be accessed directly...');  
}  
 
class phpFreaksCrypto  
{  
 
  private $td;  
 
  // this gets called when class is instantiated  
  public function __construct($key = 'MyRandomStringThatWillAlwaysBeTheSame', $iv = false, $algorithm = 'tripledes', $mode = 'ecb') 
  {    
    if(extension_loaded('mcrypt') === FALSE)  
    {  
      $prefix = (PHP_SHLIB_SUFFIX == 'dll') ? 'php_' : '';  
      dl($prefix . 'mcrypt.' . PHP_SHLIB_SUFFIX) or die('The Mcrypt module could not be loaded.');  
    }  
 
    if($mode != 'ecb' && $iv === false)  
    {  
      /*  
        the iv must remain the same from encryption to decryption and is usually  
        passed into the encrypted string in some form, but not always.  
      */  
      die('In order to use encryption modes other then ecb, you must specify a unique and consistent initialization vector.');  
    }  
 
    // set mcrypt mode and cipher  
    $this->td = mcrypt_module_open($algorithm, '', $mode, '') ;  
 
    // Unix has better pseudo random number generator then mcrypt, so if it is available lets use it!  
    $random_seed = strstr(PHP_OS, "WIN") ? MCRYPT_RAND : MCRYPT_DEV_RANDOM;  
 
    // if initialization vector set in constructor use it else, generate from random seed  
    $iv = ($iv === false) ? mcrypt_create_iv(mcrypt_enc_get_iv_size($this->td), $random_seed) : substr($iv, 0, mcrypt_enc_get_iv_size($this->td));  
 
    // get the expected key size based on mode and cipher  
    $expected_key_size = mcrypt_enc_get_key_size($this->td);  
 
    // we dont need to know the real key, we just need to be able to confirm a hashed version  
    $key = substr(md5($key), 0, $expected_key_size);  
 
    // initialize mcrypt library with mode/cipher, encryption key, and random initialization vector  
    mcrypt_generic_init($this->td, $key, $iv);  
  }  
 
  public function encrypt($plain_string)  
  {      
    /*  
      encrypt string using mcrypt and then encode any special characters  
      and then return the encrypted string  
    */  
    return base64_encode(mcrypt_generic($this->td, $plain_string));  
  }  
 
  public function decrypt($encrypted_string)  
  {   
    /*  
      remove any special characters then decrypt string using mcrypt and then trim null padding  
      and then finally return the encrypted string  
    */  
    return trim(mdecrypt_generic($this->td, base64_decode($encrypted_string)));  
  }    
 
  // this function gets called when php garbage collection destroys the object  
  public function __destruct()  
  {  
    // shutdown mcrypt  
    mcrypt_generic_deinit($this->td);  
 
    // close mcrypt cipher module  
    mcrypt_module_close($this->td);  
  }  
 
}  
?>

使用示例(PHP5)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php  
 
require_once('phpFreaksCrypto.class.php5'); // require the phpFreaksCrypto class 
 
$crypto = new phpFreaksCrypto();  
$the_string_to_be_encrypted = 'blah.blah.blah';  
$the_string_that_is_encrypted = $crypto->encrypt($the_string_to_be_encrypted);  
$the_encrypted_string_decrypted = $crypto->decrypt($the_string_that_is_encrypted);  
 
echo 'Original: ' . $the_string_to_be_encrypted . '<br />';  
echo 'Encrypted: ' . $the_string_that_is_encrypted . '<br />';  
echo 'Decrypted: ' . $the_encrypted_string_decrypted . '<br />';  
 
?>

另外在Codeigniter上也有一个实现了mcrypt的库,也可以考虑把那个类移植过来使用

你可能还对以下日志感兴趣

分类:PHPer  |  阅读(518次)

Mcrypt模块简介(译)》有 4 条评论

  1. 博主,能否帮我下.我编译安装mcrypt无法通过.

    [回复]

  2. 这个模板很简洁~
    第一次来这~

    [回复]

  3. 博主的代码框是怎么弄的?

    [回复]

    南柯一梦 回复:

    是WordPress里的一个插件,名字貌似是codebox

    [回复]

发表评论

*

评论仅支持“a、abbr、strong、em、blockquote、code”几个简单的标签