Php 将自动递增ID转换为9位随机序列号

Php 将自动递增ID转换为9位随机序列号,php,math,encryption,Php,Math,Encryption,我有一个MySQL数据库和用户。每行都有一个唯一的自动增量ID(1,2,3…)。现在我需要将其转换为一个唯一的随机序列号,我可以使用PHP将其转换回ID 用户ID从1变为999999999(INT(11)) 所有序列号至少应有9位数字,且不得以0开头。 用户不应该很容易就能猜出一个工作序列号 Thank's:)最简单的答案是使用一个哈希函数,并使用一个秘密的salt作为密钥 $secretKey = 'oh no nobody will guess this'; $userId = 312; $

我有一个MySQL数据库和用户。每行都有一个唯一的自动增量ID(1,2,3…)。现在我需要将其转换为一个唯一的随机序列号,我可以使用PHP将其转换回ID

用户ID从1变为999999999(INT(11))

所有序列号至少应有9位数字,且不得以0开头。 用户不应该很容易就能猜出一个工作序列号


Thank's:)

最简单的答案是使用一个哈希函数,并使用一个秘密的salt作为密钥

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

散列当然是单向的,因此您还必须将序列号存储在数据库中,因为您无法根据给定的序列号计算ID。

我不建议您尝试这样做

您可以看到,
autoincrement
通常用于表示,以不断避免冗余数据并保持可读性

因此,请更新数据库结构以存储哈希。结构可能是类似于
id
hash
name
等的东西

在散列中,可以使用任何逻辑

$hash = sha1("secretanswer".$userid);
$trimmedhash = substr($has,0,9); //get a 9 digit random hash
散列是单向加密,这也是有原因的。无论如何,为了验证散列,您可以再次执行相同的算法

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

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

首先,因为你想把它从X转换成Y,从Y转换成X,所以它不能是随机的。可以做的只是数学操作,遵循以下步骤:

1.使用恒定数字或ID本身的数字完成ID到9的长度。 提醒一下:你不能使用随机数字!否则,它不会双向工作

2.做一个数学运算,比如将每个数字增加1。 请注意,如果此数学动作完全更改其中一个数字,则几乎 不可能把它拿回来。 例如,如果您将每个数字增加2,那么接下来的数字是:8,9 除非你使用“结转”方法,否则你会遇到麻烦。 因此,我建议将每个数字增加X,但如果数字+X>10,则保留该数字


3.如何将其转换回?简单地说,按照这些步骤后退。

你可以做一些简单的“加密”。以('secret')素数
p
27407
base
17
(例如)。计算基本模
p-1
12897
的乘法逆
inv
。我可以帮你

Id到序列号

serial = id^base mod p
serial = 42^17 % 27407 = 24978
序列号到id

id = serial^inv mod p
id = 24978^12897 % 27407 = 42
这可以通过以下公式快速计算。只能使用0到27407之间的ID(如果不够,则使用更大的素数),并且所有ID都具有唯一的可逆序列号

为了增加模糊度,可以将结果与某个值进行异或运算


这不是真正的密码学,只是很愚蠢,但需要大多数人付出相当多的努力才能破解。

这是一个非常有趣的问题。希望我明白你在找什么。以下是我的想法:

$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

那么md5($userId.$salt)呢?我认为这是不可能的,因为如果有一个ID为9999999999的用户,你怎么能将一个11位的字符串转换成9位呢?您必须决定:拥有更大的序列号(例如11位数字)或拥有不超过X个成员。如果ID对于9位数字来说太大,则可以向序列号添加数字。不必是超级安全的,所以一些简单的数学技巧就可以了。我需要能够双向转换。而且它必须是一个数字(哈希不起作用)。除非ID太大,否则它也应该是9位数字。sha256将返回64个字符,难道他不应该使用
crc32
,它返回8个字符,然后只添加1个数字吗?crc32在加密方面一点都不强。如果只需要8个字符,您可以使用
substr($hash,0,8)
。这仍然比crc32好得多(除非性能是一个主要问题)。作者在哪里提到过更新数据库结构?我所能读到的是,他想在PHP中加密/解密自动增量,这显然起到了中间层的作用。他更喜欢在PHP中进行加密/解密,需要双向加密,并且序列号必须是9位数字(除非ID太大)。不必是超级安全的…@dotmlj,然后将has向下修剪,
$trimhash=substr($has,0,9)
。检查update@N.B.,我在提建议@Strax我需要能够双向转换Hanks。我将使用一些简单的数学,因为我不需要非常安全,只需要是一个数字。
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)