Генерация уникального серийного номера против подделки

0

Я пытаюсь создать случайный серийный номер, чтобы надеть голографические наклейки, чтобы клиенты могли проверить подлинность приобретенного продукта или нет.

Предисловие: как только вы вводите это и запрашиваете этот код, он будет нулевым, поэтому в следующий раз, когда вы это сделаете снова, вы получите сообщение о том, что продукт может быть поддельным, потому что код уже используется.

Учитывая, что я должен сделать эту систему для фабрики, которая производит не более 2/3 миллионов штук в год, для меня немного сложно понять, как настроить все, по крайней мере в первый раз...

Я думал о 20-значном коде в 4-х группах (без букв, потому что пользователю очень легко читать и вводить код)

12345-67890-98765-43210

Это то, что я считаю самым простым способом сделать все:

function mycheckdigit()
{
...
return $myserial;
}
$mycustomcode="123";
$qty=20000;
$myfile = fopen("./thefile.txt","w")  or die("Houston we got a problem here");
//using a txt file for a test, should be a DB instead...
for($i=0;$i<=$qty;$i++) {
    $txt = date("y").$mycustomcode.str_pad(gettimeofday()['usec'],6,STR_PAD_LEFT).random_int(1000000,9999999). "\n";
    //here the code to make check digits
    mycheckdigit($txt);
    fwrite($myfile,$myserial);
}
fclose($myfile);
  • 1-я группа, идентифицирующая что-то вроде года: 18 и 3 пользовательских кода
  • Вторая группа включает microtime (gettimeofday()['usec'])
  • Третий полностью случайный
  • последняя группа, включая 3 случайных числа и контрольную цифру для группы 1 и контрольную цифру для группы 2

короче:

Y= year
E= part of the EAN or custom code
M= Microtime generated number (gettimeofday()['usec'])
D= random_int() digits
C= Check Digit

YYEEE-MMMMM-MDDDD-DDDCC

Таким образом, у меня есть префикс, который меняется каждый год, я могу узнать, какой бренд является продуктом (поэтому я мог бы использовать только один источник базы данных), и у меня все еще есть достаточные случайные цифры, которые могут быть - возможно, совершенно уникальными, если я считаю, что я будет "собирать" только часть чисел от 1,000,000 и 9,999,999 и разделить ее после использования выше сортировки

Некоторые вопросы для вас:

  • Как вы думаете, у меня достаточно комбинаций, чтобы не генерировать одинаковый код за один год, учитывая 2 миллиона кодов? Я бы не использовал поиск в БД для того же кода, если это действительно не нужно, потому что это может замедлить выпуск партии (выполняется в пакетном режиме во время производственного процесса)
  • Может быть, лучше добавить еще один уникальный идентификатор, например, день года (001-365) и сделать random_int() 3 цифры короче? Учтите, что я буду генерировать коды ежемесячно, а не ежедневно (но я думаю, что нет больших изменений в уникальности)
  • Учитывая, что backend в PHP я думаю использовать функцию mt_rand(), может быть хороший подход?

ОБНОВЛЕНИЕ: после предложения @apokryfos, я больше читал о генерации UUID и тому подобное, я нашел хороший компромисс с использованием random_int(). Потому что мне просто нужны цифры, поэтому хеши HEX не полезны для моих нужд и усложняют ситуацию

Я бы избегал использовать сложные криптографические вещи, такие как ключи RSA и т.д. Мне не нужен такой уровень безопасности и сложности, мне просто нужен способ генерации уникального серийного номера, максимально возможного, насколько это возможно, что нелегко угадать и притупить, если вы не поцарапаете наклейку (так что создание числа не должно делаться от A до Z, но случайным образом)

  • 0
    вместо YYrrr (случайный) вы можете использовать YYYDDD (день месяца, 001-365) или YYcwD (CalenderWeek 01-52 и dayOfWeek (1-7). Чем больше чисел вы сгенерируете по фиксированному алгоритму, тем ниже вероятность дубликат. В зависимости от вашего (надежного) временного разрешения вы можете перейти к минутам, секундам и даже миллисекундам, что, вероятно, оставляет вам всего несколько цифр - для этого «число» лучше случайного. Вы можете даже добавить некоторые "маскировки", такие как добавление 543 в DDD , обмен местами и т. д. Интересный вопрос, но, к сожалению, "не по теме" на SO.
  • 0
    @Stephan спасибо за ваше предложение, это простая и интересная реализация, которая делает код «чище». Про "не по теме" я подумал, что это правильное место ТАК, извините за это. Если вы предложите мне правильное место, где можно задать такой вопрос, я буду иметь в виду следующий.
Показать ещё 2 комментария
Теги:
batch-file
random
unique

1 ответ

0

Вы можете играть с 11 случайными цифрами в год, так что 11-значный номер от 1 до 99999999999 (99,9 миллиарда - намного больше, чем 2 миллиона), так что хватайте комбинаций, я думаю, вы охвачены.

Однако, используя mt_rand вы, вероятно, столкнетесь с конфликтами. Здесь вы можете спланировать свой путь до 2 миллионов случайных чисел перед использованием базы данных:

<?php
$arr = [];
while (count($arr) < 1000000) {
    $num = mt_rand(1, 99999999999);
    $numStr = str_pad($num,11,0,STR_PAD_LEFT); //Force 11 digits
    if (!isset($arr[$numStr])) {
        $arr[$numStr] = true;
    } 
}
$keys= array_keys($arr);

Количество столкновений, как правило, невелико (первое столкновение происходит примерно на 300 000 - 500 000 чисел, сгенерированных таким образом, что это довольно редко.

Каждое значение в массиве $keys - это 11-значное число, которое является случайным и уникальным.

Этот подход относительно быстр, но имейте в виду, что ему потребуется довольно много памяти (более 128 МБ).

При этом более широко используемый метод заключается в создании универсально уникального идентификатора (UUID), который, скорее всего, будет уникальным и поэтому не нуждается в проверке на уникальность.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню