| 
/*****************************************************
* COPYRIGHT NOTICE
 * Copyright (c) 2011, 艾克视图
 * All rights reserved
 *
 * @file XHaffmanSec.class.php
 * @brief X哈弗曼码加密类
 * 本PHP类实现了以哈弗曼编码形式对文本进行加密及解密。
 * 使用方法
 * $xhaff = new XHaffman();
 * $text_1 = $xhaf-->Encode("明文", "密钥"); ///< 加密
 * $text_2 = $xhaff->Decode("密文", "密钥"); ///< 解密
 *
 * @version 1.0
 * @author XadillaX
 * @date 2011-1-13
 * @web http://www.xcoder.in
 *
 * 修订说明:最初版本
 *****************************************************/
 define("COPY_CONSTRUCT", "-65535");
 define("NO_NODE", "-65535");
 define("NO_POS", "-65535");
 class HTNode {
 var $data = 0;
 var $lc = NO_NODE, $rc = NO_NODE;
 var $w = 0;
 var $pos = 0;
 public function __construct($_d, $_w, $_pos = NO_POS, $_l = NO_NODE, $_r = NO_NODE) {
 $this->data = $_d;
 $this->w = $_w;
 $this->lc = $_l;
 $this->rc = $_r;
 $this->pos = $_pos;
 }
 };
 
 function HTNodeCmp(HTNode $a, HTNode $b) {
 return $a->w < $b->w;
 }
 
 class XHaffman {
 /** 权值从Lolita小说中抽样取出 */
 var $ch = array(
 10, 32, 33, 37, 40, 41, 44, 45, 46, 48,
 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
 59, 63, 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, 91, 93,
 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
 117, 118, 119, 120, 121, 122, 123, 161, 164, 166,
 168, 170, 173, 174, 175, 176, 177, 180, 186,
 95
 );
 
 var $fnum = array(
 2970, 99537, 265, 1, 496, 494, 9032, 1185, 5064, 108,
 180, 132, 99, 105, 82, 64, 62, 77, 126, 296,
 556, 548, 818, 443, 543, 435, 225, 271, 260, 797,
 3487, 158, 50, 1053, 589, 498, 332, 316, 61, 276,
 724, 855, 54, 293, 543, 11, 185, 11, 25, 26,
 42416, 7856, 12699, 23670, 61127, 10229, 10651, 27912, 32809, 510,
 4475, 23812, 13993, 34096, 38387, 9619, 500, 30592, 30504, 42377,
 14571, 4790, 11114, 769, 10394, 611, 1, 4397, 12, 71,
 117, 1234, 81, 5, 852, 1116, 1109, 1, 3,
 5000
 );
 
 var $root = NULL;
 var $nodes = array();
 var $_nodes = array();
 var $decode_arr = array();
 var $encode_arr = array();
 
 /**
 * 创建哈弗曼树
 */
 private function __CreateHT() {
 $len = count($this->nodes);
 $_len = 0;
 
 while($len > 1) {
 /** 对结点排序并取出权值最小的两个节点 */
 usort($this->nodes, "HTNodeCmp");
 $lmin = $this->nodes[$len - 1];
 $rmin = $this->nodes[$len - 2];
 
 /** 若此节点未记录,则在_nodes中记录 */
 if($lmin->pos == NO_POS) {
 $lmin->pos = $_len;
 $this->_nodes[$_len] = $lmin;
 $_len++;
 }
 if($rmin->pos == NO_POS) {
 $rmin->pos = $_len;
 $this->_nodes[$_len] = $rmin;
 $_len++;
 }
 
 /** 合并两个节点,并将新节点放入数组 */
 $this->_nodes[$_len] = new HTNode(0, $lmin->w + $rmin->w, $_len, $lmin->pos, $rmin->pos);
 $_len++;
 
 unset($this->nodes[$len - 1]);
 unset($this->nodes[$len - 2]);
 $len--;
 $this->nodes[$len - 1] = $this->_nodes[$_len - 1];
 }
 
 /** 根节点 */
 $this->root = $this->nodes[0];
 }
 
 /**
 * 创建哈弗曼编码
 */
 private function __CreateHTCode($pos, $num) {
 if($pos == NO_POS) return;
 
 $node = $this->_nodes[$pos];
 if($node->data != 0) {
 $this->decode_arr[strval($num)] = $node->data;
 $this->encode_arr[$node->data] = $num;
 }
 
 $this->__CreateHTCode($node->lc, $num << 1);
 $this->__CreateHTCode($node->rc, ($num << 1) + 1);
 }
 
 public function __construct() {
 /** 构造函数 */
 $len = count($this->fnum);
 
 /** 照权值设置结点 */
 for($i = 0; $i < $len; $i++)
 $this->nodes[$i] = new HTNode($this->ch[$i], (int)($this->fnum[$i]));
 
 /** 未设置的编码以4000为权值 */
 for($i = 1; $i < 256; $i++)
 if(!in_array($i, $this->ch))
 $this->nodes[$len++] = new HTNode($i, 4000);
 
 /** 创建Haffman编码 */
 $this->__CreateHT();
 $this->__CreateHTCode($this->root->pos, 1);
 }
 
 /**
 * 解密函数
 * @param  $str
 * @param  $key
 * @return  明文
 * 将密文$str以密钥$key解密,返回明文
 */
 public function Decode($str, $key) {
 $comlen = strlen($str);
 $klen = strlen($key);
 $decode = "";
 $decode_arr = array();
 
 for($i = 0; $i < $comlen; $i++)
 $str[$i] = chr(ord($str[$i]) ^ ord($key[$i % $klen]));
 
 $str = gzuncompress($str);
 
 $decode_arr = explode("#", $str);
 $len = count($decode_arr);
 for($i = 0; $i < $len; $i++) {
 $type = $decode_arr[$i][0];
 $haff = intval(substr($decode_arr[$i], 1, strlen($decode_arr[$i]) - 1));
 $haff ^= ord($key[$i % $klen]);
 if(array_key_exists(strval($haff), $this->decode_arr))
 $ch = $this->decode_arr[strval($haff)];
 else $ch = $haff;
 
 //echo $ch . " ";
 $decode .= chr($ch);
 }
 
 return $decode;
 }
 
 /**
 * 加密函数
 * @param  $str
 * @param  $key
 * @return  密文
 * 将$str以$key为密钥进行加密,返回加密串
 */
 public function Encode($str, $key) {
 $len = strlen($str);
 $klen = strlen($key);
 $encode_arr = array();
 for($i = 0; $i < $len; $i++) {
 $asc = ord($str[$i]);
 if(array_key_exists($asc, $this->encode_arr)) {
 $haff = $this->encode_arr[$asc];
 $haff ^= ord($key[$i % $klen]);
 $encode_arr[$i] = "1" . $haff;
 }
 else {
 $haff = $asc;
 $haff ^= ord($key[$i % klen]);
 $encode_arr[$i] = "2" . $haff;
 }
 
 }
 
 $text = implode("#", $encode_arr);
 $text = gzcompress($text, 9);
 $comlen = strlen($text);
 for($i = 0; $i < $comlen; $i++)
 $text[$i] = chr(ord($text[$i]) ^ ord($key[$i % $klen]));
 return $text;
 }
 }
 
 //$h = new XHaffman(); //$text = $h->Encode("的发生加拉克四谛法加拉克", "12345");
 //
 //echo $h->Decode($text, "12345");
 ?>
 |