Целочисленные идентификационные методы путаницы

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

Это не предназначено, чтобы быть безопасным каким-либо образом, таким образом, это не огромное беспокойство. Кроме того, целые числа, которые я буду запутывать, не являются большими - между один и 10,000 - но я не хочу коллизий, также.

У кого-либо есть какие-либо идеи для чего-то, что соответствовало бы этому критерии?

8
задан Brian Tompsett - 汤莱恩 23 July 2018 в 13:59
поделиться

6 ответов

Я получил идею из хеширования Пирсона, которая будет работать и для произвольных входных данных, а не только для 32-битных целых чисел. Я не знаю, совпадает ли это с ответом Грега, но я не мог понять, что он имел в виду. Но я точно знаю, что требования к памяти здесь постоянные. Независимо от того, насколько велик ввод, это все равно надежный трюк обфускации / шифрования.

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

Для работы вам нужен секретный ключ _encryptionTable , который представляет собой случайную перестановку включающего диапазона 0..255. Вы используете это для перемешивания байтов. Чтобы сделать реверсирование действительно сложным, он использует XOR для небольшого смешивания байтовой строки.

public byte[] Encrypt(byte[] plaintext)
{
    if (plaintext == null)
    {
        throw new ArgumentNullException("plaintext");
    }
    byte[] ciphertext = new byte[plaintext.Length];
    int c = 0;
    for (int i = 0; i < plaintext.Length; i++)
    {
        c = _encryptionTable[plaintext[i] ^ c];
        ciphertext[i] = (byte)c;
    }
    return ciphertext;
}

Затем вы можете использовать BitConverter для перехода между значениями и байтовыми массивами или преобразовать их в базу 64 или 32 для получения текстового представления. Кодировка Base 32 может быть дружественной к URL, если это важно. Расшифровка - это так же просто, как обратная операция путем вычисления инверсии _encryptionTable .

    public byte[] Decrypt(byte[] ciphertext)
    {
        if (ciphertext == null)
        {
            throw new ArgumentNullException("ciphertext");
        }
        byte[] plaintext = new byte[ciphertext.Length];
        int c = 0;
        for (int i = 0; i < ciphertext.Length; i++)
        {
            plaintext[i] = (byte)(_decryptionTable[ciphertext[i]] ^ c);
            c = ciphertext[i];
        }
        return plaintext;
    }

Вы также можете делать другие забавные вещи, если работаете с 32-битным целым числом и заботитесь только о числах, больших или равных 0, что затрудняет угадание запутанного числа.

Я также использую секретное слово для заполнения генератора псевдочислений и использую его для настройки начальной перестановки. Вот почему я могу просто получить ценность, зная, какое секретное слово я использовал для создания каждой вещи.

var mt = new MersenneTwister(secretKey.ToUpperInvariant());
var mr = new byte[256];
for (int i = 0; i < 256; i++)
{
    mr[i] = (byte)i;
}
var encryptionTable = mt.NextPermutation(mr);
var decryptionTable = new byte[256];
for (int i = 0; i < 256; i++)
{
    decryptionTable[encryptionTable[i]] = (byte)i;
}
this._encryptionTable = encryptionTable;
this._decryptionTable = decryptionTable;

Это в некоторой степени надежно, самый большой недостаток здесь в том, что шифрование XOR с 0 является идентификатором XOR и не меняет значения ( a ^ 0 == a ). Таким образом, первый зашифрованный байт представляет собой случайную позицию этого байта. Чтобы обойти это, вы можете выбрать начальное значение для c , которое не является постоянным, на основе секретного ключа, просто запросив PRNG (после инициализации с семенем) для случайного байта. Таким образом, даже с большой выборкой намного сложнее взломать шифрование, если вы не можете наблюдать ввод и вывод.

6
ответ дан 5 December 2019 в 05:55
поделиться

Просто получите хэш MD5 / SHA1 байтового представления целого числа. У вас гарантированно не будет столкновений.

-2
ответ дан 5 December 2019 в 05:55
поделиться

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

0
ответ дан 5 December 2019 в 05:55
поделиться

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

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

Вы можете реализовать это в таблице базы данных или в памяти (например, двусторонний словарь) в зависимости от ваших потребностей.

11
ответ дан 5 December 2019 в 05:55
поделиться

XOR - хороший и быстрый способ обфускации целых чисел:

1 xor 1234 = 1235
2 xor 1234 = 1232
3 xor 1234 = 1233
100 xor 1234 = 1206
120 xor 1234 = 1194

Это быстро, и xor-ing снова с тем же номером возвращает оригинал! Единственная проблема заключается в том, что если «злоумышленник» знает какое-либо из чисел, он может тривиально вычислить маску xor ... путем поиска результата с известным оригиналом!

Например, я («злоумышленник») теперь, когда четвертое число в этом списке - запутанное «100». Итак, я сделаю:

100 xor 1206 = 1234

... и теперь у меня есть маска XOR, и я могу разблокировать любое из чисел. К счастью, у этой проблемы есть тривиальное решение. Алгоритмически изменить маску XOR. Например, если вам нужно скрыть 1000 целых чисел в массиве, начните с маски XOR «1234» и увеличивайте МАСКУ на 4 для каждого числа в массиве.

4
ответ дан 5 December 2019 в 05:55
поделиться

Если кому-то интересно, кто-то несколько лет назад адаптировал 32-битный блочный шифр, который особенно полезен для этой задачи.

Также доступны Perl и Ruby-порт из перечисленных выше:

Если вам нужен результат в 8 символов или меньше, вы можете использовать шестнадцатеричное или base64 представление.

2
ответ дан 5 December 2019 в 05:55
поделиться
Другие вопросы по тегам:

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