使用php mcrypt加密解密

简介:

数字签名:对数据和私钥进行hash运算得到消息摘要,连同消息本身一块发给客户端。数据签名强调客户端接收到的数据是来自特定服务端,服务端具有对数据不可否认性。客户端通过确认此次签名的正确性来判断拿到的消息是否来自特定服务端。


数据加密:对数据进行加密,有对称加密和非对称加密两种。PHP中常使用 mcrypt和openssl扩展对数据进行加解密。mcrypt常用在对称加密中,openssl常用在非对称加密中。另外在编程中还经常使用到一种单项散列加密算法,比如MD5,HASH,SHA1,password_hash等对数据(通常是用户密码)进行加密,这种加密是不可解密的(理论上没有不可解密的算法,只是说解密的机器耗时较长便认为不可解密。一般情况下仍然可采用暴力字典破解和查找彩虹表的方式破解),hash单向加密一般会有个盐值。


在实际应用场景中,有只使用数据签名然后明文传输数据的(这是最多的),也有使用数据签名和加密数据进行传输的,一半很少只有数据加密而没有数据签名的情况吧。、


MCRYPT加密

首先明确这几个概念

算法名称:即 MCRYPT扩展所支持的密码算法,详细列表可参见mcrypt.c文件。mcypt支持的算法见文末。

算法模式:MCRYPT_MODE_modename 常量中的一个,或以下字符串中的一个:"ecb","cbc","cfb","ofb","nofb" 和 "stream"。

算法模块:使用mcrypt_module_open()打开的指定算法和模式对应的模块,是一个资源类型

初始向量:加密时需要用到的一个参数,使用mcrypt_create_iv()从随机源创建

初始向量大小:是指由mcrypt_get_iv_size()返回的指定算法/模式组合的初始向量大小。mcrypt_create_iv()根据初始向量大小创建初始向量。


mcrypt加密解密需要以下几个步骤

加密:

1 使用mcrypt_module_open()打开指定算法和模式的对应模块。

2 mcrypt_get_iv_size()获得指定算法和模式的初始向量长度,或mcrypt_enc_get_iv_size($td)获取打开模块的初始向量长度。

3 根据初始向量长度创建初始向量 mcrypt_create_iv()

4 初始化加密所需的缓冲区 mcrypt_generic_init()

5 加密数据 mcrypt_generic()

6 结束加密,执行清理工作 mcrypt_generic_deinit()


解密需要以下几个步骤

1 初始化解密模块 mcrypt_generic_init()

2 解密数据 mcrypt_decrypt()

3 结束解密,执行清理工作 mcrypt_generic_deinit()

4 关闭开始时打开的模块 mcrypt_module_close


整个加解密的过程类似创建图片的过程,首先创建画布资源,创建颜色,填充,最后image_destroy一样。


然后来看一下上面提到的几个函数的用法

1.mcrypt_module_open — 打开算法和模式对应的模块

resource mcrypt_module_open ( string $algorithm , string $algorithm_directory , string $mode , string $mode_directory )

返回资源类型

参数说明见表 1-1 

表1-1 

参数 说明
algorithm MCRYPT_ciphername 常量中的一个,或者是字符串值的算法名称。见文末
algorithm_directory algorithm_directory 参数指示加密模块的位置。 如果你提供此参数,则使用你指定的值。 如果将此参数设置为空字符串(""),将使用 php.ini 中的 mcrypt.algorithms_dir 。 如果不指定此参数,则使用 libmcrypt 的编译路径 (通常是 /usr/local/lib/libmcrypt)。
mode MCRYPT_MODE_modename 常量中的一个,或以下字符串中的一个:"ecb","cbc","cfb","ofb","nofb" 和 "stream"。
mode_directory algorithm_directory 参数指示加密模式的位置。 如果你提供此参数,则使用你指定的值。 如果将此参数设置为空字符串(""),将使用 php.ini 中的 mcrypt.modes_dir 。 如果不指定此参数,则使用 libmcrypt 的编译路径 (通常是 /usr/local/lib/libmcrypt)。


2.mcrypt_get_iv_size — 返回指定算法/模式组合的初始向量大小

int mcrypt_get_iv_size ( string $cipher , string $mode )

返回初始向量大小

可使用mcrypt_enc_get_iv_size($td) 代替,$td可以是由 mcrypt_module_open() 返回的资源作为参数。

参数说明见表 1-2

表1-2 

参数 说明
cipher MCRYPT_ciphername 常量中的一个,或者是字符串值的算法名称。
mode MCRYPT_MODE_modename 常量中的一个,或以下字符串中的一个:"ecb","cbc","cfb","ofb","nofb" 和 "stream"。


3.mcrypt_create_iv — 从随机源创建初始向量

string mcrypt_create_iv ( int $size [, int $source = MCRYPT_DEV_URANDOM ] )

返回初始向量

表1-3

参数 说明
size 初始向量大小。可由mcrypt_get_iv_size或mcrypt_enc_get_iv_size获得
source 初始向量数据来源。可选值有: MCRYPT_RAND (系统随机数生成器), MCRYPT_DEV_RANDOM (从 /dev/random 文件读取数据) 和 MCRYPT_DEV_URANDOM (从 /dev/urandom 文件读取数据)。 在 Windows 平台,PHP 5.3.0 之前的版本中,仅支持 MCRYPT_RAND。


4.mcrypt_generic_init — 初始化加密所需的缓冲区

int mcrypt_generic_init ( resource $td , string $key , string $iv )

如果发生错误,将会返回负数: -3 表示密钥长度有误,-4 表示内存分配失败, 其他值表示未知错误, 同时会显示对应的警告信息。 如果传入参数不正确,返回 FALSE。

表1-4

参数 说明
td 加密描述符。由mcrypt_module_open获得的资源类型
key 调用 mcrypt_enc_get_key_size() 函数获得的密钥最大长度。 小于最大长度的数值都被视为非法参数。
iv 通常情况下,向量大小等于算法的分组大小, 但是你应该通过 mcrypt_enc_get_iv_size() 函数 来获得这个值。在 ECB 模式下,初始向量会被忽略, 在 CFB,CBC,STREAM,nOFB 和 OFB 模式下,必须提供初始向量。 初始向量要求是随机的,并且是唯一的(不需要是安全的)。 加密和解密必须使用相同的初始向量。 如果你不想使用初始向量,请将其设置为全 0 值,但是不建议你这么做。


5.mcrypt_generic — 加密数据

string mcrypt_generic ( resource $td , string $data )

返回加密后的数据

表1-5

参数 说明
td 加密描述符。由mcrypt_module_open获得的资源类型
data 要加密的数据


6.mdecrypt_generic — 解密数据

string mdecrypt_generic ( resource $td , string $data )

返回解密后的字符串

请注意,由于存在数据补齐的情况, 返回字符串的长度可能和明文的长度不相等

参数 td 加密描述符。由mcrypt_module_open获得的资源类型,data是需要解密的密文



6.mcrypt_generic_deinit — 对加密模块进行清理工作

bool mcrypt_generic_deinit ( resource $td )

参数 td 加密描述符。由mcrypt_module_open获得的资源类型

本函数终止由加密描述符(td)指定的加密模块, 它会清理缓冲区,但是并不关闭模块。 要想关闭加密模块, 你需要自行调用 mcrypt_module_close() 函数。 (但是 PHP 会在脚本末尾为你关闭已打开的加密模块)


7.mcrypt_module_close — 关闭加密模块

bool mcrypt_module_close ( resource $td )

参数 td 加密描述符。由mcrypt_module_open获得的资源类型


下面一个例子说明加解密过程

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
class  McryptModel{
     protected  $td  '' ;
     protected  $iv  '' ;
     protected  $key  '' ;
     private  static  $instance  = NULL;
 
     private  function  __construct( $cipher , $mode , $key ) {
         $this ->cipher =  $cipher ;
         $this ->mode =  $mode ;
         $this ->key =  $key ;
     }
 
     public  static  function  getInstance( $cipher =MCRYPT_RIJNDAEL_128, $mode =MCRYPT_MODE_CBC,
     $key = 'H5gOs1ZshKZ6WikN' ) {
         if  (self:: $instance  == NULL) {
             self:: $instance  new  self( $cipher , $mode , $key );
         }
         return  self:: $instance ;
     }
 
     function  encrypt( $str ) {
         $td  = mcrypt_module_open( $this ->cipher, '' , $this ->mode, '' ); //打开算法模块
         $this ->td =  $td ;
         $iv_size  = mcrypt_enc_get_iv_size( $td ); // 获取向量大小
         $iv  = mcrypt_create_iv( $iv_size ,MCRYPT_RAND); //初始化向量
         $this ->iv =  $iv ;
         $num  = mcrypt_generic_init( $td , $this ->key, $iv ); //初始化加密空间
         //var_dump($num);
         $encypt  = mcrypt_generic( $td , $str ); //执行加密
         mcrypt_generic_deinit( $td );  // 结束加密,执行清理工作
         return  base64_encode ( $encypt ); //base64编码成字符串适合数据传输
 
     }
 
     function  decyrpt( $str ) {
         $str  base64_decode ( $str );
         $td  $this ->td;
         mcrypt_generic_init( $td , $this ->key, $this ->iv);
         $decrypt  = mdecrypt_generic( $td , $str );
         mcrypt_generic_deinit( $td );
         mcrypt_module_close( $td ); //关闭算法模块
         return  $decrypt ;
     }
}
 
$m  = McryptModel::getInstance();
echo  $s  $m ->encrypt( 'hello' );  // 输出 4cnqrVkCjcr5unW0ySUdWg==
echo  $m ->decyrpt( $e );   // 输出 hello


mcrypt加解密属于对称加密,算法是公开的,其安全性是来自对秘钥的保密。用户可选择不同的算法名称和算法模式。常用的算法是MCRYPT_RIJNDAEL_128,MCRYPT_DES,rijndael-256等,常用的模式是 cbc,ecb


php中支持的算法如下:

  • MCRYPT_3DES

  • MCRYPT_ARCFOUR_IV ( 仅 libmcrypt > 2.4.x 可用 )

  • MCRYPT_ARCFOUR ( 仅 libmcrypt > 2.4.x 可用 )

  • MCRYPT_BLOWFISH

  • MCRYPT_CAST_128

  • MCRYPT_CAST_256

  • MCRYPT_CRYPT

  • MCRYPT_DES

  • MCRYPT_DES_COMPAT ( 仅 libmcrypt 2.2.x 可用 )

  • MCRYPT_ENIGMA ( 仅 libmcrypt > 2.4.x 可用,MCRYPT_CRYPT 的别名)

  • MCRYPT_GOST

  • MCRYPT_IDEA (非免费算法)

  • MCRYPT_LOKI97 ( 仅 libmcrypt > 2.4.x 可用 )

  • MCRYPT_MARS ( 仅 libmcrypt > 2.4.x 可用,非免费算法)

  • MCRYPT_PANAMA ( 仅 libmcrypt > 2.4.x 可用 )

  • MCRYPT_RIJNDAEL_128 ( 仅 libmcrypt > 2.4.x 可用 )

  • MCRYPT_RIJNDAEL_192 ( 仅 libmcrypt > 2.4.x 可用 )

  • MCRYPT_RIJNDAEL_256 ( 仅 libmcrypt > 2.4.x 可用 )

  • MCRYPT_RC2

  • MCRYPT_RC4 ( 仅 libmcrypt 2.2.x 可用 )

  • MCRYPT_RC6 ( 仅 libmcrypt > 2.4.x 可用 )

  • MCRYPT_RC6_128 ( 仅 libmcrypt 2.2.x 可用 )

  • MCRYPT_RC6_192 ( 仅 libmcrypt 2.2.x 可用 )

  • MCRYPT_RC6_256 ( 仅 libmcrypt 2.2.x 可用 )

  • MCRYPT_SAFER64

  • MCRYPT_SAFER128

  • MCRYPT_SAFERPLUS ( 仅 libmcrypt > 2.4.x 可用 )

  • MCRYPT_SERPENT( 仅 libmcrypt > 2.4.x 可用 )

  • MCRYPT_SERPENT_128 ( 仅 libmcrypt 2.2.x 可用 )

  • MCRYPT_SERPENT_192 ( 仅 libmcrypt 2.2.x 可用 )

  • MCRYPT_SERPENT_256 ( 仅 libmcrypt 2.2.x 可用 )

  • MCRYPT_SKIPJACK ( 仅 libmcrypt > 2.4.x 可用 )

  • MCRYPT_TEAN ( 仅 libmcrypt 2.2.x 可用 )

  • MCRYPT_THREEWAY

  • MCRYPT_TRIPLEDES ( 仅 libmcrypt > 2.4.x 可用 )

  • MCRYPT_TWOFISH ( mcrypt 2.x 之前的版本,或者 2.4.x 之后版本可用 )

  • MCRYPT_TWOFISH128 (TWOFISHxxx 在新的 2.x 版本可用,但在 2.4.x 版本不可用)

  • MCRYPT_TWOFISH192

  • MCRYPT_TWOFISH256

  • MCRYPT_WAKE ( 仅 libmcrypt > 2.4.x 可用 )

  • MCRYPT_XTEA ( 仅 libmcrypt > 2.4.x 可用 )

  • 本文转自  陈小龙哈   51CTO博客,原文链接:http://blog.51cto.com/chenxiaolong/1851454

相关文章
|
1月前
|
PHP 数据安全/隐私保护
在PHP中使用AES进行加密和解密
在PHP中使用AES进行加密和解密
|
4月前
|
存储 算法 安全
百度搜索:蓝易云【php几种常用的加密解密算法】
请注意,以上算法都有各自的特点和用途,选择合适的加密解密算法应根据具体需求和安全性要求。此外,加密只是数据保护的一部分,安全实现还应考虑其他因素,如密钥管理、访问控制和安全传输等。
58 0
|
5月前
|
JSON 算法 PHP
使用php实现简单的对称加密和解密过程
php实现简单的对称加密和解密
56 0
使用php实现简单的对称加密和解密过程
|
7月前
|
PHP 数据安全/隐私保护 Python
记一次对php异或加密的解密过程
记一次对php异或加密的解密过程
97 0
|
16天前
|
PHP 数据安全/隐私保护
PHP在线加密系统网站源码
这个是sg的加密,免费可用(目前)并不会收费 源码说明:下载直接上传即可
18 1
PHP在线加密系统网站源码
|
3月前
|
PHP 数据安全/隐私保护
|
3月前
|
PHP 数据安全/隐私保护
|
3月前
|
PHP 数据安全/隐私保护
|
6月前
|
算法 安全 PHP
PHP非对称与对称双向加密解密的方式
PHP非对称与对称双向加密解密的方式
|
6月前
|
安全 API 网络安全
api接口为什么需要加密,PHP接口加密的方法有哪些
api接口为什么需要加密,PHP接口加密的方法有哪些