Home  >  Article  >  Backend Development  >  PHP data compression, encryption and decryption (pack, unpack)_PHP tutorial

PHP data compression, encryption and decryption (pack, unpack)_PHP tutorial

WBOY
WBOYOriginal
2016-07-14 10:09:281238browse

Data is often exchanged in network communications and file storage. In order to reduce network communication traffic, file storage size, and encrypted communication rules, it is often necessary to perform two-way encryption and decryption of data to ensure data security.

The main functions needed to implement this function in PHP are mainly the pack and unpack functions
pack
Compress data into bit strings.
Syntax: string pack(string format, mixed [args]...);
Return value: String
This function is used to compress and package the data into a string.
a - NUL- padded string [padded string] Pad the string blanks with NULL characters
A - SPACE- string padded [padded string]
h – hexadecimal string, low nibble first (low nibble first)
H - Hexadecimal string, high nibble first (high nibble first)
c – character with sign
C – Character without sign
s – signed short pattern [short] (usually 16 bits, in machine byte order)
S – unsigned short pattern (usually 16 bits, machine byte sorted)
n - unsigned short pattern [short] (usually 16 bits, big endian byte sorted)
v - unsigned short pattern [short] (usually 16 bits, little endian byte sorted)
i – ​​signed integer (determined by size and byte order)
I – unsigned integer (determined by size and byte order)
l – signed long pattern [long] (usually 32 bits, in machine byte order)
L – unsigned long pattern [long] (usually 32 bits, in machine byte order)
N – unsigned long pattern [long] (usually 32 bits, in big edian byte order)
V – unsigned long mode [long] (usually 32 bits, in little edian byte order)
f – floating point (determined by size and byte order)
d – double (determined by size and byte order)
x – null byte [NUL byte]
X- Back up one byte [Back up one byte]
unpack
Decompress the bit string data.
Syntax: string pack(string format, mixed [args]...);
Return value: array
This function is used to decompress the bit string data. This function has exactly the same functionality and usage as the Perl function of the same name.
Case 1, pack reduces file data storage size
[php]
//Storage integer 1234567890
file_put_contents("test.txt", 1234567890);
//Storage integer 1234567890
file_put_contents("test.txt", 1234567890); At this time, the file size of test.txt is 10byte. Note that the file size is 10 bytes at this time, and the actual space occupied is 1KB.
The integers stored above are actually stored in the file test.txt in the form of strings.
But if it is stored as an integer binary string, it will be reduced to 4 bytes.
[php]
print_r(unpack("i", file_get_contents("test.txt")));
print_r(unpack("i", file_get_contents("test.txt")));
Case 2, Data Encryption
Storing a piece of meaningful data in the form of a string, 7-110-abcdefg-117.
After the character "-" is divided, the first digit indicates the length of the string, the second digit indicates the storage location, the third digit indicates the actual stored string, and the fourth digit indicates the end position.
[php]
file_put_contents("test.txt", "7-110-abcdefg-117");
file_put_contents("test.txt", "7-110-abcdefg-117");
Disadvantages of the above method:
1. Data storage size
2. The data is stored in clear text. If it is any sensitive information, it may cause unsafe access.
3. The file storage size increases in an irregular manner.
Encryption:
[php]
file_put_contents("test.txt", pack("i2a7i1", 7, 110, "abcdefg", 117));
file_put_contents("test.txt", pack("i2a7i1", 7, 110, "abcdefg", 117));
Storage a piece of data, the encryption format is: integer 2-digit length string 10-digit length integer 1-digit length.
Advantages:
1. Data size optimization
2. When you don’t know the compression format such as "i2a7i1", even if you get the file, you cannot correctly read the binary file and convert it into plain text.
3. When data increases, the file storage size increases by the same amount. Each time it is incremented by 19byte.
Case 3, key-value file storage www.2cto.com
The generated files are stored in two: index file and data file
The format of data storage in the file is as follows:
Code implementation:
[php]
error_reporting(E_ALL);
class fileCacheException extends Exception{
}
//Key-Value type file storage
class fileCache{
private $_file_header_size = 14;
private $_file_index_name;
private $_file_data_name;
private $_file_index;//index file handle
private $_file_data;//data file handle
private $_node_struct;//index node structure
private $_inx_node_size = 36; //Index node size
public function __construct($file_index="filecache_index.dat", $file_data="filecache_data.dat"){
$this->_node_struct = array(
              'next'=>array(1, 'V'),  
              'prev'=>array(1, 'V'),  
'data_offset'=>array(1,'V'),//Starting position of data storage
'data_size'=>array(1,'V'),//data length
'ref_count'=>array(1,'V'),//Quote here, imitating PHP's reference count destruction mode
              'key'=>array(16,'H*'),//Storage KEY  
);
$this->_file_index_name = $file_index;
$this->_file_data_name = $file_data;
if(!file_exists($this->_file_index_name)){
$this->_create_index();
                                                                 
                                            $this->_file_index = fopen($this->_file_index_name, "rb+");  
                                         
if(!file_exists($this->_file_data_name)){
$this->_create_data();
                                                                      
                                                                                                                                                                                                                                     
                                         
}
//Create index file
private function _create_index(){
$this->_file_index = fopen($this->_file_index_name, "wb+");//Binary storage requires the use of b
if(!$this->_file_index)
throw new fileCacheException("Could't open index file:".$this->_file_index_name);
$this->_index_puts(0, '<'.'?php exit()?'.'>');//Locate the file flow to the starting position 0, and place a php tag to prevent downloading
$this->_index_puts($this->_file_header_size, pack("V1", 0));
}
//Create storage file
private function _create_data(){
$this->_file_data = fopen($this->_file_data_name, "wb+");//Binary storage requires the use of b
if(!$this->_file_index)
throw new fileCacheException("Could't open index file:".$this->_file_data_name);
$this->_data_puts(0, '<'.'?php exit()?'.'>');//Locate the file flow to the starting position 0, and place a php tag to prevent downloading
}
private function _index_puts($offset, $data, $length=false){
fseek($this->_file_index, $offset);
if($length)
fputs($this->_file_index, $data, $length);
else else
fputs($this->_file_index, $data);
}
private function _data_puts($offset, $data, $length=false){
fseek($this->_file_data, $offset);
if($length)
fputs($this->_file_data, $data, $length);
else else
fputs($this->_file_data, $data);
}
/**
* File lock
* @param $is_block Whether it is an exclusive or blocking lock
*/
private function _lock($file_res, $is_block=true){
flock($file_res, $is_block ? LOCK_EX : LOCK_EX|LOCK_NB);
}
private function _unlock($file_res){
flock($file_res, LOCK_UN);
}
public function add($key, $value){
$key = md5($key);
$value = serialize($value);
$this->_lock($this->_file_index, true);
$this->_lock($this->_file_data, true);
fseek($this->_file_index, $this->_file_header_size);
list(, $index_count) = unpack('V1', fread($this->_file_index, 4));
$data_size = filesize($this->_file_data_name);
fseek($this->_file_data, $data_size);
$value_size = strlen($value);
$this->_data_puts(filesize($this->_file_data_name), $value);
$node_data =
pack("V1V1V1V1V1H32", ($index_count==0) ? 0 : $index_count*$this->_inx_node_size, 0, filesize($this->_file_data_name), strlen($value), 0, $ key);
$index_count++;
          $this->_index_puts($this->_file_header_size, $index_count, 4);  
  
          $this->_index_puts($this->get_new_node_pos($index_count), $node_data);  
  
          $this->_unlock($this->_file_data);  
          $this->_unlock($this->_file_index);  
     }  
  
     public function get_new_node_pos($index_count){  
          return $this->_file_header_size + 4 + $this->_inx_node_size * ($index_count-1);  
     }  
  
     public function get_node($key){  
          $key = md5($key);  
          fseek($this->_file_index, $this->_file_header_size);  
          $index_count = fread($this->_file_index, 4);  
  
          if($index_count>0) {  
               for ($i=0; $i < $index_count ; $i++) {   
                    fseek($this->_file_index, $this->_file_header_size + 4 + $this->_inx_node_size * $i);  
                    $data = fread($this->_file_index, $this->_inx_node_size);  
                    $node = unpack("V1next/V1prev/V1data_offset/V1data_size/V1ref_count/H32key", $data);  
  
                    if($key == $node['key']){  
                         return $node;  
                    }  
               }  
          }else{  
               return null;  
          }  
     }  
  
     public function get_data($offset, $length){  
          fseek($this->_file_data, $offset);  
          return unserialize(fread($this->_file_data, $length));  
     }  
}  
  
//使用方法   
$cache = new fileCache();  
$cache->add('abcdefg' , 'testabc');  
$data = $cache->get_node('abcdefg');  
print_r($data);  
echo $cache->get_data($data['data_offset'], $data['data_size']);  
 
error_reporting(E_ALL);
 
class fileCacheException extends Exception{
 
}
 
//Key-Value型文件存储
class fileCache{
     private $_file_header_size = 14;
     private $_file_index_name;
     private $_file_data_name;
     private $_file_index;//索引文件句柄
     private $_file_data;//数据文件句柄
     private $_node_struct;//索引结点结构体
     private $_inx_node_size = 36;//索引结点大小
 
     public function __construct($file_index="filecache_index.dat", $file_data="filecache_data.dat"){
          $this->_node_struct = array(
               'next'=>array(1, 'V'),
               'prev'=>array(1, 'V'),
              'data_offset'=>array(1,'V'),//数据存储起始位置
              'data_size'=>array(1,'V'),//数据长度
'ref_count' = & gt; array (1, 'v'), // Quote here, imitate the reference counting of PHP, the destruction mode
              'key'=>array(16,'H*'),//Storage KEY
);
$this->_file_index_name = $file_index;
$this->_file_data_name = $file_data;
if(!file_exists($this->_file_index_name)){
$this->_create_index();
     }else{
                                              $this->_file_index = fopen($this->_file_index_name, "rb+");
    }
if(!file_exists($this->_file_data_name)){
$this->_create_data();
     }else{
                                              $this->_file_data = fopen($this->_file_data_name, "rb+");//Binary storage needs to use b
    }
}
//Create index file
private function _create_index(){
$this->_file_index = fopen($this->_file_index_name, "wb+");//Binary storage needs to use b
if(!$this->_file_index)
throw new fileCacheException("Could't open index file:".$this->_file_index_name);
$this->_index_puts(0, '<'.'?php exit()?'.'>');//Locate the file flow to the starting position 0, and place a php tag to prevent downloading
$this->_index_puts($this->_file_header_size, pack("V1", 0));
}
//Create storage file
private function _create_data(){
$this->_file_data = fopen($this->_file_data_name, "wb+");//Binary storage needs to use b
if(!$this->_file_index)
throw new fileCacheException("Could't open index file:".$this->_file_data_name);
$this->_data_puts(0, '<'.'?php exit()?'.'>');//Locate the file flow to the starting position 0, and place a php tag to prevent downloading
}
private function _index_puts($offset, $data, $length=false){
fseek($this->_file_index, $offset);
if($length)
fputs($this->_file_index, $data, $length);
else
fputs($this->_file_index, $data);
}
private function _data_puts($offset, $data, $length=false){
fseek($this->_file_data, $offset);
if($length)
fputs($this->_file_data, $data, $length);
else
fputs($this->_file_data, $data);
}
/**
* File Lock
* @param $is_block Whether it is an exclusive or blocking lock
*/
private function _lock($file_res, $is_block=true){
flock($file_res, $is_block ? LOCK_EX : LOCK_EX|LOCK_NB);
}
private function _unlock($file_res){
flock($file_res, LOCK_UN);
}
     public function add($key, $value){
          $key = md5($key);
          $value = serialize($value);
          $this->_lock($this->_file_index, true);
          $this->_lock($this->_file_data, true);
 
          fseek($this->_file_index, $this->_file_header_size);
 
          list(, $index_count) = unpack('V1', fread($this->_file_index, 4));
 
          $data_size = filesize($this->_file_data_name);
 
          fseek($this->_file_data, $data_size);
 
          $value_size = strlen($value);
 
          $this->_data_puts(filesize($this->_file_data_name), $value);
 
          $node_data = 
          pack("V1V1V1V1V1H32", ($index_count==0) ? 0 : $index_count*$this->_inx_node_size, 0, filesize($this->_file_data_name), strlen($value), 0, $key);
 
          $index_count++;
 
          $this->_index_puts($this->_file_header_size, $index_count, 4);
 
          $this->_index_puts($this->get_new_node_pos($index_count), $node_data);
 
          $this->_unlock($this->_file_data);
          $this->_unlock($this->_file_index);
     }
 
     public function get_new_node_pos($index_count){
          return $this->_file_header_size + 4 + $this->_inx_node_size * ($index_count-1);
     }
 
     public function get_node($key){
          $key = md5($key);
          fseek($this->_file_index, $this->_file_header_size);
          $index_count = fread($this->_file_index, 4);
 
          if($index_count>0) {
               for ($i=0; $i < $index_count ; $i++) { 
                    fseek($this->_file_index, $this->_file_header_size + 4 + $this->_inx_node_size * $i);
                    $data = fread($this->_file_index, $this->_inx_node_size);
                    $node = unpack("V1next/V1prev/V1data_offset/V1data_size/V1ref_count/H32key", $data);
 
                    if($key == $node['key']){
                         return $node;
                    }
               }
          }else{
               return null;
          }
     }
 
     public function get_data($offset, $length){
          fseek($this->_file_data, $offset);
          return unserialize(fread($this->_file_data, $length));
     }
}
 
//使用方法
$cache = new fileCache();
$cache->add('abcdefg' , 'testabc');
$data = $cache->get_node('abcdefg');
print_r($data);
echo $cache->get_data($data['data_offset'], $data['data_size']);
 
 
 
 
案例四、socket通信加密
通信双方都定义好加密格式:
例如:
[php] 
LOGIN = array(  
     'COMMAND'=>array('a30', 'LOGIN'),  
     'DATA'=>array('a30', 'HELLO')  
);  
  
$LOGOUT = array(  
     'COMMAND'=>array('a30', 'LOGOUT'),  
     'DATA'=>array('a30', 'GOOD BYE')  
);  
  
$LOGIN_SUCCESS = array(  
     'COMMAND'=>array('a30', 'LOGIN_SUCCESS'),  
     'DATA'=>array('V1', 1)  
);  
  
$LOGOUT_SUCCESS = array(  
     'COMMAND'=>array('a30', 'LOGIN_SUCCESS'),  
     'DATA'=>array('V1', time())  
);  
 
$LOGIN = array(
     'COMMAND'=>array('a30', 'LOGIN'),
     'DATA'=>array('a30', 'HELLO')
);
 
$LOGOUT = array(
     'COMMAND'=>array('a30', 'LOGOUT'),
     'DATA'=>array('a30', 'GOOD BYE')
);
 
$LOGIN_SUCCESS = array(
     'COMMAND'=>array('a30', 'LOGIN_SUCCESS'),
     'DATA'=>array('V1', 1)
);
 
$LOGOUT_SUCCESS = array(
     'COMMAND'=>array('a30', 'LOGIN_SUCCESS'),
     'DATA'=>array('V1', time())
);服务器端与客户端根据解析COMMAND格式,找到对应的DATA解码方式,得到正确的数据
 

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/477666.htmlTechArticle网络通信、文件存储中经常需要交换数据,为了减少网络通信流量、文件存储大小以及加密通信规则,经常需要对数据进行双向加解密以保...
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn