ホームページ  >  記事  >  バックエンド開発  >  32桁のphpを使用してIDを暗号化および復号化する方法(コードが添付されています)

32桁のphpを使用してIDを暗号化および復号化する方法(コードが添付されています)

不言
不言オリジナル
2018-08-03 14:04:323920ブラウズ
この記事では、PHP を使用して 16 進数の 32 を使用して ID を暗号化および復号化する方法 (コードが添付されています) を紹介します。一定の参考値があります。必要な友人は参照できます。お役に立てれば幸いです。

最近プロジェクトで問題が発生しました。現在のユーザーが友人と招待コードを共有しています。その友人が招待コードに基づいて新規ユーザーとして登録すると、特定の条件下で現在のユーザーの部下になります。 、従属ユーザーの情報を取得できます。ここで実装されているのは、現在のユーザーの ID に基づいて、逆に復号化できる暗号化された文字列を生成することです。絶え間ないテストと調整を経て、最終的な結果が得られました。例:

id ​​= 12 code = 85U43DM

最初の実装

最初に次のようにコードを入力します。

/**
 * 加密解密用户邀请码,
 * @param unknown $string
 * @param string $action  encode|decode
 * @return string
 */
function endecodeUserId($string, $action = 'encode') {
    $startLen = 13;
    $endLen = 8;

    $coderes = '';
    #TOD 暂设定uid字符长度最大到9
    if ($action=='encode') {
        $uidlen = strlen($string);
        $salt = 'yourself_code';
        $codestr = $string.$salt;
        $encodestr = hash('md4', $codestr);
        $coderes = $uidlen.substr($encodestr, 5,$startLen-$uidlen).$string.substr($encodestr, -12,$endLen);
        $coderes = strtoupper($coderes);
    }elseif($action=='decode'){
        $strlen = strlen($string);
        $uidlen = $string[0];
        $coderes = substr($string, $startLen-$uidlen+1,$uidlen);
    }
    return  $coderes;
}

アイデアの紹介:

ソルト値 $salt を設定し、それを ID と連結して新しい文字列を形成します。ソルト値は次の目的で使用できます。後で招待コードを安全に調整してください。文字列に対して md4 暗号化を実行し (md4 は md5 よりも高速で安全性が低いことを考慮して)、 $encodestr を取得し、文字列を 2 つの部分 (最初の部分 $startLen 、13 個の文字列、2 番目の部分 $endLen 、8 個の文字列) に分割します。 $string (ここでは渡された ID) と $uidlen を文字列の前の部分に混ぜます。したがって、現在は id の最大長 9 のみをサポートしているため、$uidlen の長さは 1 となり、最終的に長さ 22 の文字列が得られます。

暗号化処理では、実際に ID の値と ID の長さを暗号化文字列に混合し、保存されている情報に基づいて対応する位置を見つけて ID を取得します。

ここでは、セキュリティに対する高度な要件はありませんが、プログラムの実行速度を上げるために、復号化中に検証は行われません。

テスト、ID の暗号化:

echo endecodeUserId(12);

出力結果:

23471DC2352712F34D6780

テスト、招待コードの復号化

 echo endecodeUserId('23471DC2352712F34D6780','decode');

出力結果:

12

得られた結果は問題ないようですが、実際のテストではこのような問題が見つかりました。これは一般のユーザーにも存在する可能性があります。友人が次の宛先にメッセージを送信しました。 WeChatの携帯電話に招待コードを入力し、その後パソコンで登録したいが、携帯電話からパソコンに招待コードを転送する方法が分からない、または面倒だと感じている。招待コードをパソコンで手入力すると、なんと22桁、しかも大文字と数字が混在しているので、登録は諦めるしかないでしょう。

そのため調整を行い、7桁の招待コードに変更させていただきました。

もう一度調べてください

メソッドは記事を書く前にカプセル化されていますか、それとも最初にコードを直接追加したほうがよいでしょうか

<?php

class convert
{
    /**
     * 初始数字,自定义
     */
    const INIT_NUM = 123456789;

    /**
     * @var 进制的基本字符串
     */
    private $baseChar;

    /**
     * @var 进制类型
     */
    private $type;

    /**
     * @var array 各进制字符串列表
     */
    private static $convertList = array(
        &#39;32&#39; => '0123456789ABCDEFGHJKMNPQRSTVWXYZ',//不含ILOU
    );

    public function __construct($type='32')
    {
        $this->type = $type;
        $this->baseChar = self::$convertList[$type];
    }

    /**
     * 公用方法,数字进行进制转换
     * @param $num
     * @return string
     */
    private function _idToString($num){
        $str = '';
        while ($num!=0){
            $tmp = $num % $this->type;
            $str .= $this->baseChar[$tmp];
            $num = intval($num/$this->type);
        }

        return $str;
    }

    /**
     * @desc  im:十机制数转换成三十二进制数
     * @param (string)$char 三十二进制数
     * return 返回:十进制数
     */
    public function idToString($id){//10位内id 返回7位字母数字
        //数组 增加备用数值
        $id += self::INIT_NUM;

        //左补0 补齐10位
        $str = str_pad($id,10,'0',STR_PAD_LEFT);

        //按位 拆分 4 6位(32进制 4 6位划分)
        $num1 = intval($str[0].$str[2].$str[6].$str[9]);
        $num2 = intval($str[1].$str[3].$str[4].$str[5].$str[7].$str[8]);
        $str1 = $str2 = '';

        $str1 = $this->_idToString($num1);
        $str1 = strrev($str1);

        $str2 = $this->_idToString($num2);
        $str2 = strrev($str2);

        //4 补足 3 4位 U L
        return str_pad($str1,3,'U',STR_PAD_RIGHT).str_pad($str2,4,'L',STR_PAD_RIGHT);
    }

    /**
     * @desc  im:三十二进制数转换成十机制数
     * @param (string)$char 三十二进制数
     * return 返回:十进制数
     */
    public function stringToId($str){
        //1 清除 3 4 位补足位
        $str1 = trim(substr($str,0,3),'U');
        $str2 = trim(substr($str,3,4),'L');

        $num1 = $this->_stringToId($str1);
        $num2 = $this->_stringToId($str2);
        //补位拼接
        $str1 = str_pad($num1,4,'0',STR_PAD_LEFT);
        $str2 = str_pad($num2,6,'0',STR_PAD_LEFT);
        $id = ltrim($str1[0].$str2[0].$str1[1].$str2[1].$str2[2].$str2[3].$str1[2].$str2[4].$str2[5].$str1[3],'0');
        //减去 备用数值
        $id -= self::INIT_NUM;
        return $id;
    }

    /**
     * 公用方法字符串转数字
     * @param $str
     * @return float|int|string
     */
    private function _stringToId($str){
        //转换为数组
        $charArr = array_flip(str_split($this->baseChar));
        $num = 0;
        for ($i=0;$i<=strlen($str)-1;$i++)
        {
            $linshi = substr($str,$i,1);
            if(!isset($charArr[$linshi])){
                return &#39;&#39;;
            }
            $num += $charArr[$linshi]*pow($this->type,strlen($str)-$i-1);
        }

        return $num;
    }
}

アイデアのご紹介

この手法は長年の師匠の指導のもと採用されました。 ID を固定長の 32 桁の文字列に変換し、独自のアルゴリズムを追加します。ここでは他の基数ではなく基数 32 が使用されるのはなぜですか? 32 桁システムには十分な英語文字を含めることができ、生成される暗号化文字列はより標準化されたように見えますが、一方で、認識しにくい一部の英語文字 (ここでは ILOU は除外します) が除外されるため、32 桁システムは36 ベースの代わりに使用されます。

暗号化処理、メソッド idToString() では、最初の id が比較的小さい場合、16 進数 32 に変換するときに 0 が多くなり、非常に不規則に見えることを考慮して、初期値 INIT_NUM が設定されます。 、これはカスタマイズできます。渡されたidに従って初期値を加算すると10桁の値が得られ、この値のインターバルビットが4桁の$num1と6桁の$num2に分割されます。 2 つの値は別々に変換されます。16 進数です。変換後、$num1 は長さ 3 の文字列を取得します。不足を補うために U を使用します。$num2 は長さ 4 の文字列を取得します。不足分を補うL。

復号化は逆の操作です。操作を逆にするだけです。

テスト:

$obj = new convert(32);
$res1 = $obj->idToString(12);

の生成 結果:

85U43DM

復号化:

$obj = new convert(32);
$res1 = $obj->stringToId('85U43DM');

結果:

12

おすすめ関連記事:

#php の 4 つのセキュリティ フィルタリング関数のまとめ (コード付き)

php で文字列からの数値抽出を実装 まとめメソッド(コード)

PHPシステムプログラムの実行関数(system、passthru、exec)の簡易解析(コード付き)

以上が32桁のphpを使用してIDを暗号化および復号化する方法(コードが添付されています)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。