30

クライアントには、単純に増加する順序番号 (1、2、3...) があります。彼は、エンドユーザーが 8 桁または 9 桁 (数字のみ -- 文字なし) の「乱数」を受け取ることを望んでいます。明らかに、この「乱数」は実際には一意で可逆でなければなりません (これは実際には actualOrderNumber の暗号化です)。

私の最初の考えは、いくつかのビットをシャッフルすることでした。クライアントにサンプル シーケンスを見せたところ、「シャッフル」ポイント (下位ビットが機能するポイント) に達するまで、後続の obfuscOrderNumbers が増加していると不満を漏らしました。彼は、obfuscOrderNumbers ができるだけランダムに見えるようにしたいと考えています。

次に考えたのは、線形合同疑似乱数ジェネレーターを決定論的にシードしてから、actualOrderNumber 番目の値を取得することでした。しかし、その場合、衝突について心配する必要があります。クライアントは、少なくとも 10^7 サイクルで衝突しないことが保証されているアルゴリズムを必要としています。

私の 3 番目の考えは、「ああ、暗号化するだけだ」というものでしたが、ストック暗号化ライブラリを使用する場合は、8 桁または 9 桁のみの要件を取得するために後処理する必要があります。

私の 4 番目の考えは、actualOrderNumber のビットをグレイ コードの整数として解釈し、それを返すことでした。

私の 5 番目は、「私はおそらくこれを考えすぎています。StackOverflow の誰かが数行のコードでこれを実行できるに違いありません」でした。

4

7 に答える 7

22

ランダムに 8 桁または 9 桁の数字、たとえば 839712541 を選びます。次に、注文番号のバイナリ表現 (この例では、2 の補数は使用していません) を取り、同じビット数 (30) になるまでパディングし、逆にします。 、反転した注文番号とマジック ナンバーを xor します。例えば:

1         = 000000000000000000000000000001

Flip      = 100000000000000000000000000000
839712541 = 110010000011001111111100011101
XOR       = 010010000011001111111100011101 = 302841629

2         = 000000000000000000000000000010

Flip      = 010000000000000000000000000000
839712541 = 110010000011001111111100011101
XOR       = 100010000011001111111100011101 = 571277085

注文番号を元に戻すには、出力番号をマジック ナンバーで xor し、ビット文字列に変換して逆順にします。

于 2009-03-04T19:33:02.553 に答える
6

ハッシュ関数? http://www.partow.net/programming/hashfunctions/index.html

于 2009-03-04T19:10:02.157 に答える
5

クライアントは、難読化された連続した注文番号の配布が特定のように見えることを要求しますか?

暗号化を複雑にしたくない場合は、ビットシャッフルとランダムなソルティングを組み合わせて使用​​します(ビット/桁に余裕がある場合)。誰が注文したかなど、難読化された注文 ID と一緒にいつでも利用できcustomer_idます)。


編集

クライアントが望んでいるのは、外部の第三者が販売の進捗状況を推測できないことだけであるようです。この場合、シャッフル ソリューション (ビット マッピング、たとえば元のビット 1 を難読化されたビット 6 にマップし、元のビット 6 を難読化されたビット 3 にマップするなど) で十分です。解読を本当に難しくしたい場合は、ランダムなビットを追加します。ただし、追加のビットが利用可能である場合 (たとえば、元の注文番号は 6 桁までしかないと仮定しますが、難読化された注文番号では 8 ~ 9 が許可されていると仮定すると、ビットマッピングを実行する前に、ランダム性のために 2 ~ 3 桁を使用できます)。おそらく、追加の脅迫のために結果を XOR します (好奇心旺盛な当事者は、難読化された 2 つの連続した注文を生成しようとする可能性があります。それらを互いに XOR して、XOR 定数を取り除きます。


EDIT2

もちろん、難読化された注文 ID に完全に乱数を割り当て、対応を永続ストレージ (DB など) に保存し、同じストレージに対して衝突検出と難読化解除を実行できます。私に言わせれば、少しやり過ぎかもしれませんが、難読化に関して言えば、プラス面としては最高です (そして、魂が望む分散関数を実装し、いつでも好きなときに分散関数を変更できます)。

于 2009-03-04T19:09:47.087 に答える
4

9 桁の数字で、最初の桁は 0 から 7 (または 1 から 8) の間のランダムなインデックスです。その位置に別の乱数を置きます。残りは「実際の注文番号:

  • 元の注文: 100
  • ランダム インデックス: 5
  • 乱数: 4 (保証、サイコロを振った:) )
  • 結果: 500040100

  • 元の番号: 101

  • ランダム インデックス: 2
  • 乱数 6
  • 結果: 200001061

5 桁目 (またはその他の桁) がインデックスであると判断できます。

または、実際の 6 桁の注文番号を使用できる場合は、「セカンダリ」インデックスも導入できます。また、「実際の」順序番号の数字の順序を逆にすることができます。

于 2009-03-04T19:20:56.280 に答える
3

私はこれをかなり遅く見ました(!)。後で来る他の人に役立つかもしれません。

あなたは次のように述べています。

それは正しいです。暗号化は元に戻すことができ、特定の入力に対して一意であることが保証されています。ご指摘のとおり、ほとんどの標準的な暗号化には適切なブロック サイズがありません。ただし、1 ビット以上の任意のブロック サイズを持つことができるHasty Pudding Cipherが 1 つあります。

または、独自に作成することもできます。NSA がクラックできないものを必要としない場合、ニーズを満たす単純なFeistel 暗号を作成できます。

于 2011-07-25T14:47:27.157 に答える
0

注文 ID が一意の場合は、プレフィックスを作成し、そのプレフィックスを注文 ID に追加/混合するだけです。

このようなもの:

long pre = DateTime.Now.Ticks % 100;
string prefix = pre.ToString();
string number = prefix + YOURID.ToString()
于 2011-11-06T10:08:53.933 に答える
-1
<?PHP 

$cry = array(0=>5,1=>3,2=>9,3=>2,4=>7,5=>6,6=>1,7=>8,8=>0,9=>4);

function enc($e,$cry,$k){
    if(strlen($e)>10)die("max encrypt digits is 10");
    if(strlen($e) >= $k)die("Request encrypt must be lesser than its length");
    if(strlen($e) ==0)die("must pass some numbers");

    $ct =  $e;
    $jump = ($k-1)-strlen($e);
    $ency = $cry[(strlen($e))];
    $n = 0;
    for($a=0;$a<$k-1;$a++){
        if($jump > 0){
            if($a%2 == 1){
                $ency .=rand(0,9);
                $jump -=1;
            }else{
                if(isset($ct[$n])){
                    $ency.=$cry[$ct[$n]];
                    $n++;
                }else{
                    $ency .=rand(0,9);
                    $jump -=1;
                }
            }
        }else{
            $ency.= $cry[$ct[$n]];
            $n++;
        }
    }
    return $ency;
}

function dec($e,$cry){
    //$decy = substr($e,6);
    $ar = str_split($e,1);
    $len = array_search($ar[0], $cry);
    $jump = strlen($e)-($len+1);
    $val = "";
    for($i=1;$i<strlen($e);$i++){
        if($i%2==0){
            if($jump >0){
                //$val .=array_search($e[$i], $cry);
                $jump--;
            }else{
                $val .=array_search($e[$i], $cry);
            }
        }else{
            if($len > 0){
                $val .=array_search($e[$i], $cry);
                $len--;
            }else{
                $jump--;
            }
        }
    }
    return $val;
}
if(isset($_GET["n"])){
    $n = $_GET["n"];
}else{
    $n = 1000;
}

$str = 1253;
$str = enc($str,$cry,15);
echo "Encerypted Value : ".$str ."<br/>";
$str = dec($str,$cry);
echo "Decrypted Value : ".$str ."<br/>";
?>
于 2014-11-20T09:45:54.917 に答える