[精讚] [會員登入]
637

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程式經驗 #2 -- print和echo的差異 常在寫php的人一定會想知道echo和print這兩個函數有什麼不一樣 驗證 1. 比較print 和echo 函式的執

[PHP] 台灣身分證號及檢查程式 台灣身分證號及PHP檢查程式

[PHP] codeignitor4+ smarty4 這篇整合 php 的framework codeignitor4 + smarty4。

作業上傳程式 提供學生作業上傳的程式

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

PHP 移除陣列中的元素 要移除陣列中的其中一項元素

我有話要說

>>

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

訪客留言

[無留言]

隨機好文

[MAC] 截取螢幕畫面的方法 截取螢幕畫面的方法,在MAC中叫作螢幕快照,英文是screenshot

Linux shell 的date表示法 linux下SHELL中的date表示法

為什麼要重造輪子? 什麼輪子?造什麼輪子?我為什麼要重造輪子?

NETCRAFT發現你的網站及作業系統 NETCRAFT可以發現你的網站及作業系統

好用的3+2碼郵遞區號查詢系統推薦 網路上找到用地址輸入判斷3+2碼郵遞區號的辨識率不高,除了這個網站…