18 Уникальных идентификаторов Цифры - Надежность кода

Я хочу число, которое было бы уникально навсегда, я придумал следующий код, это генерирует число и добавляет контрольный разряд в конец его, я хотел бы знать, насколько надежный этот код?

public void GenerateUniqueNumber(out string ValidUniqueNumber) {
        string GeneratedUniqueNumber = "";

        // Default implementation of UNIX time of the current UTC time
        TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
        string FormatedDateTime = Convert.ToInt64(ts.TotalSeconds).ToString();
        string ssUniqueId = DateTime.UtcNow.ToString("fffffff");
        //Add Padding to UniqueId
        string FormatedUniqueId = ssUniqueId.PadLeft(7, '0'); 

        if (FormatedDateTime.Length == 10 && FormatedUniqueId.Length == 7)
        {
            // Calculate checksum number using Luhn's algorithm.
            int sum = 0;
            bool odd = true;
            string InputData = FormatedDateTime + FormatedUniqueId;
            int CheckSumNumber;

            for (int i = InputData.Length - 1; i >= 0; i--)
            {
                if (odd == true)
                {
                    int tSum = Convert.ToInt32(InputData[i].ToString()) * 2;
                    if (tSum >= 10)
                    {
                        string tData = tSum.ToString();
                        tSum = Convert.ToInt32(tData[0].ToString()) + Convert.ToInt32(tData[1].ToString());
                    }
                    sum += tSum;
                }
                else
                    sum += Convert.ToInt32(InputData[i].ToString());
                odd = !odd;
            }
            //CheckSumNumber = (((sum / 10) + 1) * 10) - sum;
            CheckSumNumber = (((sum + 9) / 10) * 10) - sum;

            // Compute Full length 18 digit UniqueNumber
            GeneratedUniqueNumber = FormatedDateTime + FormatedUniqueId + Convert.ToString(CheckSumNumber);
        }
        else
        {
            // Error
            GeneratedUniqueNumber = Convert.ToString(-1);
        }

        ValidUniqueNumber = GeneratedUniqueNumber;        
    }

Править: разъяснение GUID не может использоваться, число, должно будет быть введено в систему IVR по телефону клавиатура.

5
задан 001 26 June 2010 в 14:52
поделиться

9 ответов

Вы не можете использовать GUID, но вы можете создать свой собственный формат уникального номера, аналогичный GUID, который основан на MAC-адресе (пространстве) аппарата и текущем время и дата (время). Это гарантированно будет уникальным, если все машины имеют синхронизированные часы.

Для получения дополнительной информации см. здесь

6
ответ дан 18 December 2019 в 07:53
поделиться

Почему бы вам просто не использовать Guid?

5
ответ дан 18 December 2019 в 07:53
поделиться

У этого метода есть несколько проблем:

  • Вы просто подсчитываете количество миллисекунд с 1 января 1970 года. Вы можете получить это из ts.TotalSeconds округлено до 0,0000001. Все ваши преобразования и миллисекунды не нужны.

  • 10 лет - это примерно 3 × 10¹¹ миллисекунд. Вы сохраняете 17 значащих цифр, поэтому в течение следующих 10 лет первые 5 цифр никогда не изменятся и не могут использоваться для различения чисел. Они бесполезны.

  • Вы генерируете числа для миллисекунд с 1970 года по настоящее время? В противном случае они также не могут использоваться для различения чисел и бесполезны.

  • Это полностью зависит от того, какая машина возвращает дату. Любой, у кого есть доступ к этой машине, может сгенерировать любые «уникальные» числа, какие пожелает. Это проблема?

  • Любой, кто видит одно из этих чисел, может сказать, когда оно было сгенерировано. Это проблема?

  • Кто угодно может предсказать, какое число и когда будет сгенерировано. Это проблема?

  • 10 15 миллисекунд - это примерно 30000 лет. После этого ваш алгоритм будет повторять числа. Похоже на долгое время, но вы указали «навсегда», а 30000 лет - это не «навсегда». Вы действительно имеете в виду «навсегда»?

4
ответ дан 18 December 2019 в 07:53
поделиться

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

Если он уже существует, сгенерируйте новый, иначе все готово.

Однако есть одно но: я бы убедился, что проверка существования ID и фактическое сохранение записи в БД выполняются в транзакции, иначе вы рискуете получить другой запрос, создающий эту запись в промежутке между проверкой ID и созданием строки.

Также просто проверьте, почему бы не сработать автоинкрементному номеру, сгенерированному самой базой данных? БД гарантировала бы его уникальность (во всяком случае, для этой таблицы)

.
1
ответ дан 18 December 2019 в 07:53
поделиться

Если я правильно понимаю вашу реализацию, она использует только текущую дату/время в качестве основы. Это означает, что если вы создадите два ID одновременно, они не будут уникальными.

3
ответ дан 18 December 2019 в 07:53
поделиться

Вы не говорите, для чего будут использоваться числа. Есть ли у них какая-то ценность, связанная с ними? Будет ли проблемой, если пользователи смогут разгадать схему и угадать номера действительных билетов?

Если важно, чтобы эти номера было трудно угадать, то эта схема отпадает; лучше использовать что-то, что выводит данные, которые выглядят действительно случайными. Можно взять монотонно возрастающий серийный номер и зашифровать его с помощью блочного шифра (с размером блока 64 бита); это даст на выходе 64 бита или около 20 десятичных цифр, из которых можно взять (скажем) последние 18. (Если важна обратимость, т.е. если по номеру билета вы хотите иметь возможность восстановить серийный номер, то здесь нужно быть немного осторожнее.)

Нужна ли вам чугунная 100% гарантия того, что ни один номер билета никогда не будет одинаковым? Если да, то вам нужно хранить их в базе данных и отмечать их при использовании. Если вы это сделаете, то разумнее будет просто использовать хороший генератор случайных чисел и каждый раз проверять их на наличие дубликатов.

1
ответ дан 18 December 2019 в 07:53
поделиться

Использование системного времени - хорошее начало, но оно дает вам коллизии, если вам нужно сгенерировать два UID одновременно. Использование формата «fffffff» не помогает: разрешение часов Windows составляет всего 15–16 мс, поэтому только одно или два из этих «f» работают хоть как-то.

Кроме того, ваш подход сообщает вам, когда именно был сгенерирован идентификатор. В зависимости от ваших потребностей это может быть желательной функцией или угрозой безопасности.

Вам понадобятся ваши идентификаторы, чтобы включить другую информацию вместо времени или в дополнение к нему. Некоторые возможные варианты:

  • Случайное число
  • Циклический счетчик
  • Хэш имени программы (если вам нужны эти идентификаторы в нескольких программах)
  • MAC-адрес или другой идентификатор для машины (если идентификаторы должны быть уникальными на нескольких компьютерах)

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

1
ответ дан 18 December 2019 в 07:53
поделиться

Как говорит "Andrew Hare", вы можете использовать Guid. По поводу вашего кода ответ "НЕТ"! потому что если время DateTime на компьютере клиента было неправильным или изменилось, результат может быть пара или больше!

0
ответ дан 18 December 2019 в 07:53
поделиться

Нет такой вещи, как случайность в любом случае. Вот предложение.

  1. Создайте собственное "случайное" 18-значное число
  2. Перед отправкой пользователю проверьте его на соответствие существующим в БД
  3. Если оно уже есть в БД, прополощите и повторите.
-1
ответ дан 18 December 2019 в 07:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: