[精讚] [會員登入]
645

PHP 數字加解密函式

自寫的數字加解密,勉強用

分享此文連結 //n.sfs.tw/12797

分享連結 PHP 數字加解密函式@新精讚
(文章歡迎轉載,務必尊重版權註明連結來源)
2019-10-22 06:24:44 最後編修
2018-10-12 01:03:14 By 張○○
 

自動目錄

在 URL 中常會有帶出參數的情況,其中可能有數字。例如 http://n.sfs.tw/?n=123456

但是手賤的使用者(就是我) 會企圖去修改這個數字,+1看看會出現什麼

http://n.sfs.tw/?n=123457

結果就和總統府網站中馬英九的治國日記被看到明天的內容一樣出狀況,為了解決使用者改數字的問題,

設計了一個正整數加解密函數。

例如上例的123456,改為加密的字串:

http://n.sfs.tw/?n=99ht

使用者無法將 99ht +1,就算是變成 99hu 也無法得到文章的正確數字。

上面是想法,想直接看解法的話捲到最下面。

一、現況分析

現有的雙向 hash 函數,如 base64 ,會產生過長的字串,整體看來不美觀。因為要加密的只有數字,應該不必這麼麻煩。

參考已有的整數 HASH,這裡參考了 Thomas Wang 的網站(連結佚失),其中有他的整數HASH算法

/**
 * Thomas Wang的算法,整数hash
*/
function intHash($k)
{
  $k = ~$k + ($k << 15); // $k = ($k << 15) - $k - 1;
  $k = $k ^ SHR($k,12);
  $k = $k + ($k << 2);
  $k = $k ^ SHR($k,4);
  $k = $k * 2057; // $k = ($k + ($k << 3)) + ($k << 11);
  $k = $k ^ SHR($k,16);
  return $k;
}

function SHR($x, $n)    // x >>> n
{
    $mask = 0x40000000;
    if ($x < 0)
    {
        $x &= 0x7FFFFFFF;
        $mask = $mask >> ($n-1);
        return ($x >> $n) | $mask;
    }
    return (int)$x >> (int)$n;
}

因為php並沒有 >>> 這個運算子,所以上面的 SHR 函式我把他寫成函數。

OK,看起來一切都不錯?但是?怎麼解hash值…?原站沒有提供 decode 的函式

看來是行不通的,如果沒辦法把 HASH過的值寫回就沒意義了。

 

二、自寫函數初稿

所以我花了二個多小時,寫了二個整數的加解密函數:

function iencode($v){
  $code="OlPkQjRiShTgUfAz5By6Cx7Dw8Ev9Fu0Gt1Hs2Ir3Jq4KpLoMnNmVeWdXcYbZa";    //想要使用的字串符,字元不得重覆。
  $shift=6;
  $len = strlen($code);
  $v = ($v <<  $shift);
  $out="";
  do{
    $r = $v%$len;
    $out .= $code[$r];
    $v = ($v - $r)/$len;
  }while($v>0);
  return $out;
}

function idecode($s){
  $code="OlPkQjRiShTgUfAz5By6Cx7Dw8Ev9Fu0Gt1Hs2Ir3Jq4KpLoMnNmVeWdXcYbZa";
  $shift=6;
  $len = strlen($code);
  $in=0;
  for($ii=0;$ii<strlen($s);$ii++){
    $r=strpos($code, $s[$ii]);
    $in += $r* pow($len,$ii);
  }
  $in = ($in >>$shift);
  return $in;
}

看來 WORK fine,可惜,輸入的 $v 值太大會有溢位的問題,最大只能接受 約32,000,000的正整數

叫用例:
print iencode(123456);   //99ht
print idecode("99ht"); //123456

所以上面的函式不OK。

 

三、自寫函數改良

再花四個小時改善原程式,加強了以下功能:

1. 可接受任意值整數,不必擔心溢位的問題;

2. 有檢查加密字串是否合法的功能

 

// Number Encode/Decode class By Axer 991208
class LongDEnCrypt{
  var $code="OlPkQjRiShTgUfAz5By6Cx7Dw8Ev9Fu0Gt1Hs2Ir3Jq4KpLoMnNmVeWdXcYbZa"; // A character string without dupl. char.
  var $shift=6;  //shift value : no shift 0-10 largely shift

 /**
  * function LongEncode(): Encrypted a integer to a string.
  * @scope public
  * @param string $v input number
  * @return encrypted integer string
  * ex. LongEncode("5611236889745123")   //IBmyw1tytILDi
  */
  public function LongEncode($v){
    $code= $this->code;
    $shift=$this->shift;
    $len = strlen($code); //62
    $vs = (string)$v;
    $segment = floor( log10( PHP_INT_MAX >>$shift));  //7
    $segnum = ceil(strlen($vs)/ $segment);
    $out="";
    for($ii=0; $ii<$segnum;$ii++){
      $seg = substr($vs,$ii*$segment, $segment);
      $v = (int)$seg <<$shift;
      if($v===0){
        $zeronum =strlen($seg);
        $out .= ".". $code[$zeronum];
      }
      else
        do{
          $r = $v%$len;
          $out .= $code[$r];
          $v = ($v - $r)/$len;
        }while($v>0);
    }
    // Add check char.
    $c=0;
    for($ii=0;$ii< strlen($out);$ii++)if($out[$ii]!=='.') $c+=strpos($code, $out[$ii]);
    $out .= $code[$c%$len];
    return $out;
  }

 /**
  * function LongDecode(): Decrypted a string to a number string.
  * @scope public
  * @param string $s encrypted string
  * @return -1: string too short, -2: not a valid encrypted string and success: a number string
  * ex. LongDecode("Bmyw1tytILDi"); //5611236889745123
  * ex. $obj= new LongDEnCrypt();
  *     if( $v=$obj->LongDecode("SOMESTRING") <=0) print "Invalid encrypted string"; //Error control
  *     else // Do something
  */
 public function LongDecode($s){
    $code=  $this->code;
    $shift= $this->shift;  //6
    //check decoded string
    $len = strlen($code);
    $slen = strlen($s)-1;
    if($slen<=1)return -1;
    $c=0;
    for($ii=0;$ii<$slen;$ii++)if($s[$ii]!=='.')$c+=strpos($code, $s[$ii]);
    if($code[$c%$len] !== $s[$slen])return -2;   //Validate Err
    $segment = ceil( log( PHP_INT_MAX >>$shift)/log($len) ); //5
    $out="";
    $ii=0;
    $index=0;
    $v=0;
    do{
      if($s[$index] !=="."){
        $r=strpos($code, $s[$index]);
        $v += $r* pow($len,$ii);
        if( $ii == $segment-1 || $index==$slen-1 ){
          $ii=0;
          $v >>= $shift;
          $out .= $v;
          $v=0;
        }
      }else{ //ZERO
        $pos= strpos($code, $s[$index+1]);
        $out .= str_repeat("0", $pos);
        $ii=0;
        $index++;
        $v=0;
      }
      $ii++;
      $index++;
    }while($index<$slen);
    return $out;
} //End Class

 

用來尚可,沒發現啥BUG


原文 2010-12-08 14:07:58

END

你可能感興趣的文章

[PHP] IPv6檢查IP是否在某個網段內 mtachcidr6 要檢查IPv6是否在某個IPv6的網段內?

[PHP] 類別中要怎麼使用callback function 召回函數(回呼函數)? 在類別中使用標準函數,若其中的callback 函數也是在類別中,該怎麼使用?

[PHP7] 利用Memcached 儲存 Session Memcached+ PHP7,利用Memcached 儲存 Session。

[PHP] 判斷程式是從CLI、本地網路或是網際網路端執行的方法 PHP利用IP判斷程式是從CLI、本地網路或是網際網路端執行的方法

[PHP] 命名空間 namespace及 use PHP >=5.3 開始支援命名空間:namespace

[PHP] 陣列排序 sort, ksort, asort, usort... 簡單的記錄PHP的陣列排序,因為常常會用到。

我有話要說

>>

限制:留言最高字數1000字。 限制:未登入訪客,每則留言間隔需超過10分鐘,每日最多5則留言。

訪客留言

[無留言]

隨機好文

HP SAS硬碟leds燈號說明 HP SAS硬碟leds燈號(hp g7/g6系統適用)說明

[jQuery] select 元件的取值及給值 html中的元件select,在jquery中要如何使用?

[大型機台] 熱血高校躲避球 多少少年時光歲月耗在這個遊戲上,二十幾年前的那個時光,唯一想做的事就是把吃飯錢省下來拿去打一場五塊錢的電動,就算是沒錢也

[MYSQL] 設定字串欄位的預設值 新增表格的時候,字串欄位給予預設空值;數字欄位給預設數值;日期欄位給空值。

分享還是炫耀? 是分享還是炫耀,取決於對方的的心態和你的心態...