PHP数据压缩、加解密(pack, unpack)

PHP数据压缩、加解密(pack, unpack)

网络通信、文件存储中经常需要交换数据,为了减少网络通信流量、文件存储大小以及加密通信规则,经常需要对数据进行双向加解密以保证数据的安全。

PHP中实现此功能主要需要使用的函数主要是pack及unpack函数

 

pack

压缩资料到位字符串之中。

语法: string pack(string format, mixed [args]...);

返回值: 字符串

本函数用来将资料压缩打包到位的字符串之中。

a - NUL- 字符串填满[padded string] 将字符串空白以 NULL 字符填满

A - SPACE- 字符串填满[padded string]

h – 十六进制字符串,低“四位元”[low nibble first] (低位在前)

H - 十六进制字符串,高“四位元”[high nibble first](高位在前)

c – 带有符号的字符

C – 不带有符号的字符

s – 带有符号的短模式[short](通常是16位,按机器字节顺序)

S – 不带有符号的短模式[short](通常是16位,按机器字节排序)

n -不带有符号的短模式[short](通常是16位,按大endian字节排序)

v -不带有符号的短模式[short](通常是16位,按小endian字节排序)

i – 带有符号的整数(由大小和字节顺序决定)

I – 不带有符号的整数(由大小和字节顺序决定)

l– 带有符号的长模式[long](通常是32位,按机器字节顺序)

L – 不带有符号的长模式[long](通常是32位,按机器字节顺序)

N – 不带有符号的长模式[long](通常是32位,按大edian字节顺序)

V– 不带有符号的长模式[long](通常是32位,按小edian字节顺序)

f –浮点(由大小和字节顺序决定)

d – 双精度(由大小和字节顺序决定)

x – 空字节[NUL byte]

X- 后面一个字节[Back up one byte](倒回一位)

unpack

解压缩位字符串资料。

语法: string pack(string format, mixed [args]...);

返回值: 数组

本函数用来将位的字符串的资料解压缩。本函数和 Perl 的同名函数功能用法完全相同。

案例一、pack实现缩减文件数据存储大小

[php] view plaincopy

  1. <?php
  2. //存储整数1234567890
  3. file_put_contents("test.txt", 1234567890);

此时test.txt的文件大小是10byte。注意此时文件大小是10字节,实际占用空间大小是1KB。

上面存储的整数实际是以字符串形式存储于文件test.txt中。

但如果以整数的二进制字符串存jy储,将会缩减至4byte。

[php] view plaincopy

  1. <?php
  2. print_r(unpack("i", file_get_contents("test.txt")));

案例二、数据加密

以字符串形式存储一段有意义数据,7-110-abcdefg-117。

字符"-"分割后,第一位表示字符串长度,第二位表示存储位置,第三位表示实际存储的字符串,第四位表示结尾位置。

[php] view plaincopy

  1. <?php
  2. file_put_contents("test.txt", "7-110-abcdefg-117");

上述方法缺点:

一、数据存储大小

二、数据以明文方式存储,如果是任何敏感信息,都可能造成不安全访问。

三、文件存储大小,以不规则方式递增。

加密:

[php] view plaincopy

  1. <?php
  2. file_put_contents("test.txt", pack("i2a7i1", 7, 110, "abcdefg", 117));

存储一段数据,加密格式为:整数2位长度字符串10位长度整数1位长度。

优点:

一、数据大小最优化

二、在不知道"i2a7i1"这样的压缩格式时,即使拿到文件,也无法正确读出二进制文件转化为明文。

三、数据增加时,文件存储大小是等量递增。每次都是以19byte递增。

案例三、key-value型文件存储

存储生成的文件为两个:索引文件,数据文件

文件中数据存储的格式如下图:

代码实现:

[php] view plaincopy

  1. <?php
  2. error_reporting(E_ALL);
  3. class fileCacheException extends Exception{
  4. }
  5. //Key-Value型文件存储
  6. class fileCache{
  7. private $_file_header_size = 14;
  8. private $_file_index_name;
  9. private $_file_data_name;
  10. private $_file_index;//索引文件句柄
  11. private $_file_data;//数据文件句柄
  12. private $_node_struct;//索引结点结构体
  13. private $_inx_node_size = 36;//索引结点大小
  14. public function __construct($file_index="filecache_index.dat", $file_data="filecache_data.dat"){
  15. $this->_node_struct = array(
  16. ‘next‘=>array(1, ‘V‘),
  17. ‘prev‘=>array(1, ‘V‘),
  18. ‘data_offset‘=>array(1,‘V‘),//数据存储起始位置
  19. ‘data_size‘=>array(1,‘V‘),//数据长度
  20. ‘ref_count‘=>array(1,‘V‘),//引用此处,模仿PHP的引用计数销毁模式
  21. ‘key‘=>array(16,‘H*‘),//存储KEY
  22. );
  23. $this->_file_index_name = $file_index;
  24. $this->_file_data_name = $file_data;
  25. if(!file_exists($this->_file_index_name)){
  26. $this->_create_index();
  27. }else{
  28. $this->_file_index = fopen($this->_file_index_name, "rb+");
  29. }
  30. if(!file_exists($this->_file_data_name)){
  31. $this->_create_data();
  32. }else{
  33. $this->_file_data = fopen($this->_file_data_name, "rb+");//二进制存储需要使用b
  34. }
  35. }
  36. //创建索引文件
  37. private function _create_index(){
  38. $this->_file_index = fopen($this->_file_index_name, "wb+");//二进制存储需要使用b
  39. if(!$this->_file_index)
  40. throw new fileCacheException("Could‘t open index file:".$this->_file_index_name);
  41. $this->_index_puts(0, ‘<‘.‘?php exit()?‘.‘>‘);//定位文件流至起始位置0, 放置php标记防止下载
  42. $this->_index_puts($this->_file_header_size, pack("V1", 0));
  43. }
  44. //创建存储文件
  45. private function _create_data(){
  46. $this->_file_data = fopen($this->_file_data_name, "wb+");//二进制存储需要使用b
  47. if(!$this->_file_index)
  48. throw new fileCacheException("Could‘t open index file:".$this->_file_data_name);
  49. $this->_data_puts(0, ‘<‘.‘?php exit()?‘.‘>‘);//定位文件流至起始位置0, 放置php标记防止下载
  50. }
  51. private function _index_puts($offset, $data, $length=false){
  52. fseek($this->_file_index, $offset);
  53. if($length)
  54. fputs($this->_file_index, $data, $length);
  55. else
  56. fputs($this->_file_index, $data);
  57. }
  58. private function _data_puts($offset, $data, $length=false){
  59. fseek($this->_file_data, $offset);
  60. if($length)
  61. fputs($this->_file_data, $data, $length);
  62. else
  63. fputs($this->_file_data, $data);
  64. }
  65. /**
  66. * 文件锁
  67. * @param $is_block 是否独占、阻塞锁
  68. */
  69. private function _lock($file_res, $is_block=true){
  70. flock($file_res, $is_block ? LOCK_EX : LOCK_EX|LOCK_NB);
  71. }
  72. private function _unlock($file_res){
  73. flock($file_res, LOCK_UN);
  74. }
  75. public function add($key, $value){
  76. $key = md5($key);
  77. $value = serialize($value);
  78. $this->_lock($this->_file_index, true);
  79. $this->_lock($this->_file_data, true);
  80. fseek($this->_file_index, $this->_file_header_size);
  81. list(, $index_count) = unpack(‘V1‘, fread($this->_file_index, 4));
  82. $data_size = filesize($this->_file_data_name);
  83. fseek($this->_file_data, $data_size);
  84. $value_size = strlen($value);
  85. $this->_data_puts(filesize($this->_file_data_name), $value);
  86. $node_data =
  87. pack("V1V1V1V1V1H32", ($index_count==0) ? 0 : $index_count*$this->_inx_node_size, 0, filesize($this->_file_data_name), strlen($value), 0, $key);
  88. $index_count++;
  89. $this->_index_puts($this->_file_header_size, $index_count, 4);
  90. $this->_index_puts($this->get_new_node_pos($index_count), $node_data);
  91. $this->_unlock($this->_file_data);
  92. $this->_unlock($this->_file_index);
  93. }
  94. public function get_new_node_pos($index_count){
  95. return $this->_file_header_size + 4 + $this->_inx_node_size * ($index_count-1);
  96. }
  97. public function get_node($key){
  98. $key = md5($key);
  99. fseek($this->_file_index, $this->_file_header_size);
  100. $index_count = fread($this->_file_index, 4);
  101. if($index_count>0) {
  102. for ($i=0; $i < $index_count ; $i++) {
  103. fseek($this->_file_index, $this->_file_header_size + 4 + $this->_inx_node_size * $i);
  104. $data = fread($this->_file_index, $this->_inx_node_size);
  105. $node = unpack("V1next/V1prev/V1data_offset/V1data_size/V1ref_count/H32key", $data);
  106. if($key == $node[‘key‘]){
  107. return $node;
  108. }
  109. }
  110. }else{
  111. return null;
  112. }
  113. }
  114. public function get_data($offset, $length){
  115. fseek($this->_file_data, $offset);
  116. return unserialize(fread($this->_file_data, $length));
  117. }
  118. }
  119. //使用方法
  120. $cache = new fileCache();
  121. $cache->add(‘abcdefg‘ , ‘testabc‘);
  122. $data = $cache->get_node(‘abcdefg‘);
  123. print_r($data);
  124. echo $cache->get_data($data[‘data_offset‘], $data[‘data_size‘]);

案例四、socket通信加密

通信双方都定义好加密格式:

例如:

[php] view plaincopy

  1. $LOGIN = array(
  2. ‘COMMAND‘=>array(‘a30‘, ‘LOGIN‘),
  3. ‘DATA‘=>array(‘a30‘, ‘HELLO‘)
  4. );
  5. $LOGOUT = array(
  6. ‘COMMAND‘=>array(‘a30‘, ‘LOGOUT‘),
  7. ‘DATA‘=>array(‘a30‘, ‘GOOD BYE‘)
  8. );
  9. $LOGIN_SUCCESS = array(
  10. ‘COMMAND‘=>array(‘a30‘, ‘LOGIN_SUCCESS‘),
  11. ‘DATA‘=>array(‘V1‘, 1)
  12. );
  13. $LOGOUT_SUCCESS = array(
  14. ‘COMMAND‘=>array(‘a30‘, ‘LOGIN_SUCCESS‘),
  15. ‘DATA‘=>array(‘V1‘, time())
  16. );

服务器端与客户端根据解析COMMAND格式,找到对应的DATA解码方式,得到正确的数据.

http://blog.csdn.net/yongcto/article/details/17366605

时间: 2024-10-13 11:06:28

PHP数据压缩、加解密(pack, unpack)的相关文章

Cryptography中的对称密钥加解密:fernet算法探究

原创文章,欢迎转发朋友圈,转载请注明出处 cryptography是python语言中非常著名的加解密库,在算法层面提供了高层次的抽象,使用起来非常简单.直观,pythonic,同时还保留了各种不同算法的低级别接口,保留灵活性. 我们知道加密一般分为对称加密(Symmetric Key Encryption)和非对称加密(Asymmetric Key Encryption).,各自对应多种不同的算法,每种算法又有不同的密钥位长要求,另外还涉及到不同的分组加密模式,以及末尾补齐方式.因此需要高层次

【PHP】微信开放平台---消息加解密-php7.1 使用openssl代替Mcrypt

1.问题 微信开发小程序消息加解密,官方给出的dome中使用正常,最近升级了7.1发现接收消息不能解密了,最后查了日志又查了各种资料发现 Mcrypt 函数php7.1已经被废弃: 2.解决方式 在Prpcrypt类中使用openssl代替Mcrypt 官方代码: /** * 对密文进行解密 * @param string $encrypted 需要解密的密文 * @return string 解密得到的明文 */ public function decrypt($encrypted, $app

CryptoGUI | 文件加解密

分类: 杂类工具    版本: 0.0.3    发布日期: 2015-03-31 根据 crypto 强加密命令行工具制作的可视化版本,可快速进行任意文件的加解密操作,提供丰富的加解密选项以适应多种不同需求:CryptoGui 在 crypto 的基础上进行了人性化定制,使用更方便. 功能简介 支持当今绝大部分对称强加密算法 可定制的密钥长度,从最低32位到最高的448位.信息安全强度由用户自由选择. 算法库基于优秀的 Cryptopp 库封装,已通过FIPS 140-2美国国家信息处理标准一

一点一滴解读网狐的加解密

先贴出来源码 #ifndef PACKET_HEAD_FILE #define PACKET_HEAD_FILE #pragma pack(1) ////////////////////////////////////////////////////////////////////////////////// //端口定义 #define MAX_CONTENT 512 //并发容量 #define PORT_AUTO_SELECT INVALID_WORD //自动端口 #define POR

多语言(Java&amp;C#&amp;Ruby&amp;C++&amp;Objective-C&amp;Android)互通的TripleDES加解密算法实现

直入主题:前段时间根据公司对开发API的安全性要求,采用了小数据加密验证的方式,根据需求采用了三重DES加密算法.在实施的过程中发现各个语言之间加密由于加密补位的方式有所不同,导致不同语言之间加密之后无法相互解析.在强大的会联网技术和公司其他同事的支持下,最终整合了集Java,C#,Ruby,C++,Objective-C,Android多语言的可以互通的TripleDES加密算法,虽然在AES加密推崇的今天DES有些乏力,但小可大胆贴上代码,希望能给大家提供一些思路. Java DES加密(J

PHP版3DES加解密类

<?php /** * * PHP版3DES加解密类 * * 可与java的3DES(DESede)加密方式兼容 * * @Author:蓝凤(ilanfeng.com) * * @version: V0.1 2011.02.18 * */ class Cc3des{ //加密的时候只用替换key就行了,ecb模式不需要提供iv值 public $key = "0123456789QWEQWEEWQQ1234"; public $iv = "33889955"

php pack &amp;&amp; unpack函数详解

在看下面一个例子前先提及一组函数pack,unpack. 任何一款拥有socket操作能力的语言都有一个专门用于组包的函数,php也不例外当然这组函数的用途不仅仅是组包.下面简单的介绍一下:应用一:输入16进制或者2进制流.<?php$src="3B06";$binvar = pack('H*',$src);echo $binvar;?> 看看这个程序,相当于下面的程序echo chr(0x3B).chr(0x06); 在数据量很小的时候后面的做法,更为简便.但是大量数据的

超强php加解密扩展:cryptopp

cryptopp是一个用c++编写的超强加解密扩展.性能优异可靠.完全可以替换所有PHP编写的加解密类.不仅如此,它的提供的编程接口非常简明易用,可说是PHP程序员必备扩展. cryptopp扩展的接口如下: class cryptopp { public function __construct($param); public function setkey($param); public function encode($param); public function decode($par

【转】 Java 进行 RSA 加解密时不得不考虑到的那些事儿

[转] Java 进行 RSA 加解密时不得不考虑到的那些事儿 1. 加密的系统不要具备解密的功能,否则 RSA 可能不太合适 公钥加密,私钥解密.加密的系统和解密的系统分开部署,加密的系统不应该同时具备解密的功能,这样即使黑客攻破了加密系统,他拿到的也只是一堆无法破解的密文数据.否则的话,你就要考虑你的场景是否有必要用 RSA 了. 2. 可以通过修改生成密钥的长度来调整密文长度 生成密文的长度等于密钥长度.密钥长度越大,生成密文的长度也就越大,加密的速度也就越慢,而密文也就越难被破解掉.著名