2012-03-08 24 views
2

私はユーザーがいるMySQLデータベースを持っています。すべての行に一意の自動インクリメントID(1,2,3 ...)があります。今私はIDに変換することができますユニークでランダムなシリアル番号に変換する必要があります - すべてPHPを使用しています。 99999999999から1から自動インクリメントIDを9桁のランダムシリアル番号に変換してください

ユーザーIDのゴー(INT(11))。

シリアル番号はすべて最低9桁で、0で始まらないようにしてください。 作業中のシリアル番号の推測方法を簡単に把握できません。

感謝の:)

+0

何MD5について($ userIdを$塩。)? – aletzo

+0

IDが99999999999のユーザーがいる場合、11桁の文字列を9に変換するにはどうすればよいのでしょうか? あなたは、より大きなシリアル番号(例えば11桁)を持つか、またはX個のメンバーを超えないことを決定する必要があります。 –

+0

9桁の数字が大きい場合は、シリアルに数字を追加しても問題ありません。いくつかの簡単な数学のトリックが仕事をするかもしれないので、超安全である必要はありません。 – dotmlj

答えて

1

単純な「暗号化」を行うことができます。 (例えば)( '秘密')プライムp27407base17してください。ベースモディファイドの乗法逆invを計算するp-112897wolframalphaこれを行うことができます。

イドIDとシリアルシリアル番号

serial = id^base mod p 
serial = 42^17 % 27407 = 24978 

id = serial^inv mod p 
id = 24978^12897 % 27407 = 42 

これはexponentiation bysquaringによって迅速に算出することができます。 0と27407の間のIDだけが使用できます(十分でない場合は、より大きい素数を取る)。すべてが一意の可逆シリアル番号を持ちます。

あいまいさを増やすには、結果をある値でXORできます。

それは本当の暗号、ちょうど愚かsecurity through obscurityはありませんが、ほとんどの人間にクラックする、かなりの労力がかかります。

+0

ありがとうございます。私は非常に安全である必要はなく、数字だけである必要があるので、簡単な数学で行くつもりです。 – dotmlj

1

最も簡単な答えは

$secretKey = 'oh no nobody will guess this'; 
$userId = 312; 
$serialNumber = hash('sha256', $secretKey . $userId); 

あなたが保存する必要がありますので、ハッシュは、当然の一方向の作品のキーとして使用される秘密塩でハッシュ関数を用いることであろう指定されたシリアル番号からIDを計算することはできないため、DBのシリアル番号も入力してください。

+0

私は両方の方法を変換できる必要があります。それは数字だけでなければなりません(ハッシュは機能しません)。 IDを大きくしない限り、常に9桁でなければなりません。 – dotmlj

+0

sha256は64文字を返しますが、8文字を返す 'crc32'を使うべきではないでしょうか? –

+0

crc32は暗号が強くないわけではありません。 8文字しか必要ないなら、 'substr($ hash、0、8)'を使うことができます。これはcrc32よりもずっと優れています(パフォーマンスが大きな問題でない限り)。 – xato

1

私は何をしようとすることはお勧めしません。

通常、冗長なデータを避けるためにはautoincrementが一般的です。は可読性です。

ので、代わりに同様のハッシュを格納するためのデータベース構造を更新。構造は、id,hashnameのようなものであるかもしれません。ハッシュで

は、あなたが任意のロジックを使用することができます

$hash = sha1("secretanswer".$userid); 
$trimmedhash = substr($has,0,9); //get a 9 digit random hash 

ハッシュは一方向暗号化であり、それも理由そうです。とにかく、ハッシュを検証するために、あなたはYにXからそれを変換し、XにYからできるようにしたい、もう一度

$userid = "getthissomehow"; 
    $hash = sha1("secretanswer".$userid); 
    $trimmedhash = substr($has,0,9); 

    $prevhash = "asfaf23rfs"; //get previously stored hash somehow 
    if($trimmedhash == $prevhash) { 
    //valid 
    } 
+0

著者はデータベース構造の更新について何を言ったのですか?私が読むことができるのは、明らかに中間層として機能するPHPの自動インクリメントを暗号化/復号化したいということだけです。 –

+0

PHPでそれを行うのが好きですが、双方向に進む必要があります。シリアル番号は9桁の数字でなければなりません(IDが大きくない限り)。スーパーセキュアである必要はありません... – dotmlj

+0

@dotmlj、次に、$ trimhash = substr($ has、0,9) 'を削除します。アップデート – Starx

0

まずBeacuseを同じアルゴリズムを行うことができ、それはRANDOMすることはできません。何ができるのかは、次のステップに従うだけです。

1. IDの長さは、ID自体の定数桁または数字で9までを補完します。 ご注意:ランダムな数字は使用できません。それ以外の場合、両方の方法で動作しません。

2.各桁を1ずつ増やすような数学操作を行います。 この数学的アクションによって数字のいずれかが完全に変更された場合、ほとんど戻ってくることはありません。 たとえば、各桁を2ずつ増やしていて、次の桁がある場合:「carryover」メソッドを使用しない限り、問題に遭遇します。8,9 Xで各桁を増やすことをお勧めしますが、DIGIT + X> 10の場合はDIGITのままにしてください。

3.それを元に戻すには?単純に、それらのステップを逆に実行してください。

0

これは非常に興味深い問題でした。うまくいけば私はあなたが探しているものを理解しています。

$test_limit = 25; 
$test_ids = array(1, 99999999999); 
for($i=0; $i<($test_limit-2); $i++) $test_ids[] = mt_rand(1, 99999999999); 

foreach($test_ids as $tii=>$ti) 
{ 
    $serial = getSerialUsingId($ti); 
    $id = getIdUsingSerial($serial); 
    if($id!=$ti) echo 'Test '.($tii+1).' (id: '.$ti.') FAILED! (serial: '.$serial.")\n"; 
    else echo 'Test '.($tii+1).' (id: '.$ti.') was a success! (serial: '.$serial.")\n"; 
} 


function getMask($index, $places=8) 
{ 
    $masks = array 
    (
    0xac976f4, 
    0x1c70f81, 
    0x441f67f, 
    0x5fb0b87, 
    0xf1542d2, 
    0xfa28851, 
    0x91bbd8c, 
    0x30a5448, 
    0x46a2708, 
    0x5856fbf, 
    0x65fa462, 
    0xf24337b, 
    0xea2c390, 
    0x8561da4, 
    0x9f77b25 
); 

    if($places==4) return $masks[$index] & 0x0000FFFF; 
    else return $masks[$index]; 

}// getMask 


function getSerialUsingId($id) 
{ 

    $prepend = ''; 
    $mask_index = mt_rand(0, 14); 

    // 8 hex places can only handle up to 4294967295 
    // If the number is greater than than that then get the additional bytes and treat separate 
    if($id>0xffffffff) 
    { 
    $packed = pack('d', $id); 
    $hex_pack = unpack('H*', $packed); 
    $hex_string = substr($hex_pack[1],4); 
    $bytes = array_reverse(explode("\n", chunk_split($hex_string, 2, "\n"))); 
    foreach($bytes as $bi=>$b) if(!$b) unset($bytes[$bi]); 
    $truncated_bytes = array_splice($bytes,0,count($bytes)-4); 
    $truncated = implode('', $truncated_bytes); 
    $prepend = dechex(hexdec($truncated)^getMask($mask_index, 4)); 
    } 

    $serial = dechex($mask_index+1).$prepend.str_pad(dechex($id^getMask($mask_index)), 8, '0', STR_PAD_LEFT); 

    return $serial; 

}// getSerialUsingId 


function getIdUsingSerial($serial) 
{ 
    $mask_index = hexdec($serial[0])-1; 
    $serial = substr($serial, 1); 
    $prepended = false; 
    if(strlen($serial)>9) 
    { 
    $prepended = substr($serial, 0, 4); 
    $serial = substr($serial, 4); 
    } 
    $id = hexdec($serial)^getMask($mask_index); 
    if($prepended) 
    { 
    $unmasked_prepended = dechex(hexdec($prepended)^getMask($mask_index, 4)); 
    $bytes = array_reverse(array_merge 
    (
     explode("\n", chunk_split($unmasked_prepended, 2, "\n")), 
     explode("\n", chunk_split(dechex($id), 2, "\n")), 
     array('00','00') 
    )); 
    foreach($bytes as $bi=>$b) if(!$b) unset($bytes[$bi]); 
    $packed = pack('H*', implode('', $bytes)); 
    $unpacked = unpack('d', $packed); 
    $id = $unpacked[1]; 
    } 

    return $id; 

}// getIdUsingSerial 

基本的には、シリアル番号は、最初の16進数は数字の残りの部分に使用するビットマスクを決定するとともに、進にあります。ここに私が思い付いたものです。これにより、IDが> 4294967295(0xFFFFFF)の場合を除き、すべてのシリアル番号の長さが9文字になります。この場合、シリアル番号には4桁の16進数があり、最初の桁にマスクされます。理にかなっている?うまくいけば、それはあなたの非常に特有の要件を満たしているか、少なくともこれを取って、それがあなたがそれを必要とする方法で動作させることができます。

コードを実行しているの出力例:

Test 1 (id: 1) was a success! (serial: 60fa28850) 
Test 2 (id: 99999999999) was a success! (serial: 24db649b1e87e) 
Test 3 (id: 487808132) was a success! (serial: 31952aafb) 
Test 4 (id: 227726272) was a success! (serial: 40869d847) 
Test 5 (id: 836896236) was a success! (serial: 53ef7473e) 
Test 6 (id: 958345007) was a success! (serial: 93d750827) 
Test 7 (id: 164308905) was a success! (serial: 30d8ad1d6) 
Test 8 (id: 715018588) was a success! (serial: 1205727a8) 
Test 9 (id: 1127737044) was a success! (serial: 8403db29c) 
Test 10 (id: 409934489) was a success! (serial: 81b654ed1) 
Test 11 (id: 907129123) was a success! (serial: f3fe6ca06) 
Test 12 (id: 720453497) was a success! (serial: b2cae9b1b) 
Test 13 (id: 500526447) was a success! (serial: 1171c1b9b) 
Test 14 (id: 322340582) was a success! (serial: 119fff012) 
Test 15 (id: 1176988677) was a success! (serial: b4078c867) 
Test 16 (id: 698755861) was a success! (serial: 92dcc0c1d) 
Test 17 (id: 555569451) was a success! (serial: 52e0813f9) 
Test 18 (id: 227332917) was a success! (serial: a0809bc8a) 
Test 19 (id: 819326158) was a success! (serial: 334941ab1) 
Test 20 (id: 659803411) was a success! (serial: d29f10e83) 
Test 21 (id: 895574245) was a success! (serial: d3bc3a375) 
Test 22 (id: 539979792) was a success! (serial: 425d47b97) 
Test 23 (id: 933093554) was a success! (serial: 83497b4fa) 
Test 24 (id: 959556569) was a success! (serial: 93d5b8cd1) 
Test 25 (id: 668064949) was a success! (serial: 22616d334) 
関連する問題