Есть ли способ сгенерировать начальное число из последовательности чисел?

Например, если java создает псевдослучайную последовательность: 9 3 2 5 6, используя 23 в качестве семени, как я могу сделать обратное? то есть получение 23 из последовательности 9 3 2 5 6.

Или как назначить начальное число для определенной последовательности?

Это легко сделать, если есть база данных — достаточно назначить случайный ключ для последовательности

INSERT INTO SEQUENCE_TABLE VALUES (RANDOM_KEY, SEQUENCE)

Однако, если мне не разрешено использовать базу данных, есть ли формула для этого?


person Frank Smith    schedule 20.01.2012    source источник
comment
Насколько мне известно, невозможно определить начальное число по выходным данным, если не иметь заранее справочной таблицы для каждой возможной пары начальное число/последовательность. Каков ваш вариант использования для этого? Возможно, существует более элегантное решение, чем попытка реконструировать PRNG в Java.   -  person Erica    schedule 20.01.2012
comment
Мне просто нужно назначить ключ последовательности уникальных чисел, но ключ также должен быть коротким. Ключ просто служит коротким способом представления последовательности, например, seed в java для представления последовательности псевдослучайных чисел.   -  person Frank Smith    schedule 20.01.2012
comment
Я просто подумал об использовании начальных и случайных функций Java для восстановления моей последовательности уникальных чисел. Если есть более простой способ сделать это, надеюсь, вы можете предложить и поблагодарить вас.   -  person Frank Smith    schedule 20.01.2012
comment
Я не уверен, чего именно вы пытаетесь достичь здесь. Можешь подробнее рассказать о своей проблеме? Какие входные данные вы будете получать и что вам нужно производить?   -  person jkraybill    schedule 20.01.2012
comment
Вы должны: (1) Сгенерировать начальное число в соответствии с требованиями алгоритма ГСЧ. (2) Сохраните это начальное число в БД вместе с последовательностью (или подпоследовательностью чисел, включая начальную позицию); (3) Воспроизвести поток по запросу, повторно задав то же значение. Если вы пытаетесь реконструировать вывод ГСЧ, см. мой ответ ниже.   -  person ingyhere    schedule 11.03.2015


Ответы (5)


Да, абсолютно легко реконструировать числовой поток плохо спроектированного генератора псевдослучайных чисел, такого как реализация Linear Congruential PRNG на языке программирования Java (java.util.Random).

На самом деле, имея всего лишь ДВА значения от этого конкретного генератора и информацию о порядке появления значений, можно предсказать весь поток.

Random random = new Random();
long v1 = random.nextInt();
long v2 = random.nextInt();
for (int i = 0; i < 65536; i++) {
    long seed = v1 * 65536 + i;
    if (((seed * multiplier + addend) & mask) >>> 16) == v2) {
        System.out.println("Seed found: " + seed);
        break;
    }
}

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

Существует гораздо больше информации об обратном проектировании PRNG, в том числе java.util.Random здесь. ...

person ingyhere    schedule 11.03.2015
comment
PS, это не должно использоваться как архитектурная особенность. Я просто размещаю это здесь, чтобы это было известно. - person ingyhere; 03.04.2017

Суть генераторов случайных чисел в том, что это невозможно. SecureRandom разработан, чтобы быть особенно криптографически стойким, но, вообще говоря, если вы записываете случайное число генератор и это возможно или легко, вы делаете это неправильно.

Тем не менее, вполне вероятно, что это не невозможно со встроенным в Java классом Random. (Однако SecureRandom — это совсем другая история.) Но для этого потребуется ошеломляющее количество математических вычислений.

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

person Louis Wasserman    schedule 20.01.2012
comment
На самом деле это тривиально с java.util.Random, см. мой пост здесь. - person ingyhere; 11.03.2015

Конечно, можно восстановить начальное значение, используемое java.util.Random. В этом сообщении описывается математика линейной конгруэнтной формулы Random, и вот функция чтобы обнаружить текущее начальное число из двух последних целых чисел, возвращенных функцией nextInt().

public static long getCurrentSeed(int i1, int i2) {
        final long multiplier = 0x5DEECE66DL;
        final long inv_mult = 0xDFE05BCB1365L;
        final long increment = 0xBL;
        final long mask = ((1L << 48) - 1);

        long suffix = 0L;
        long lastSeed;
        long currSeed;
        int lastInt;

        for (long i=0; i < (1<<16); i++) {
                suffix = i;
                currSeed = ((long)i2 << 16) | suffix;
                lastSeed = ((currSeed - increment) * inv_mult) & mask;
                lastInt = (int)(lastSeed >>> 16);

                if (lastInt == i1) {
                        /* We've found the current seed, need to roll back 2 seeds */
                        currSeed = lastSeed;
                        lastSeed = ((currSeed - increment) * inv_mult) & mask;
                        return  lastSeed ^ multiplier;
                }
        }

        /* Error, current seed not found */
        System.err.println("current seed not found");
        return 0;
}

Эта функция возвращает значение, которое можно использовать с rand.setSeed() для генерации псевдослучайной последовательности чисел, начиная с i1 и i2.

person David M    schedule 25.11.2013

Если вы согласны с использованием String в качестве семени, вы можете использовать это:

String seed = "9 3 2 5 6";

Тогда ваш генератор будет выглядеть так:

String[] numbers = seed.split(" ");

Если вы действительно хотите перепроектировать генератор «случайных» чисел в java, это будет довольно сложно (я думаю).

Было бы лучше сделать это наоборот, если вы можете: начать с семени, создать последовательность, а затем начать оттуда.

person Bohemian♦    schedule 20.01.2012
comment
Я также думал об этом, однако это будет проблемой, если последовательность будет слишком длинной. Спасибо за предложение - person Frank Smith; 20.01.2012

Вы хотите взять произвольные последовательности чисел, а затем определить короткий (фиксированной длины?) Ключ, который позволит вам регенерировать эту последовательность чисел без сохранения оригинала? К сожалению, то, что вы хотите, технически невозможно. Вот почему:

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

К сожалению, математика так не работает. Любая заданная последовательность имеет определенную меру энтропии — среднюю степень сложности этой последовательности. Чтобы воспроизвести эту последовательность без потерь, вы должны иметь возможность кодировать как минимум достаточно информации для представления ее энтропии.

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

person Erica    schedule 20.01.2012
comment
Это совершенно и абсолютно неправильно. Между CSPRNG и PRNG есть разница, и CSPRNG разработаны именно для того, чтобы избежать этой дилеммы. Как только известно начальное начальное число для ГСЧ (порядка периода ГСЧ или меньше для плохо разработанного алгоритма), ВСЕ числа в последовательности известны окончательно. en.wikipedia.org/wiki/Random_number_generator_attack - person ingyhere; 11.03.2015
comment
@ingyhere, я думаю, вы, возможно, не читали исходный вопрос полностью. Автор не спрашивает, может ли он генерировать числа из последовательности, если он знает ключ, он спрашивает, есть ли способ (без перечисления всех возможных вариантов) определить, что однозначный ключ может без потерь генерировать любую случайную последовательность цифр. . - person Erica; 14.03.2015