Шифрование и расшифровка 19-значного BigInteger


Как я могу взять максимум 19 цифр длиной BigInteger и зашифровать его с помощью следующих правил:

    Результат должен быть основан только на цифрах и строчных английских буквах.
  • все выходы должны иметь одинаковую длину для любого входа. Длина должна быть от 11 до 16 символов, в зависимости от вашего метода, , но должна быть согласованной для всех возможных входных данных.
  • нет простых шаблонов. Например, если вы шифруете 000...1 и 000...2 результаты должны выглядеть полностью различный.
  • никаких столкновений вообще
  • должен быть в состоянии расшифровать обратно к исходному BigInteger.

Вещи, которые я пробовал

3 2

3 ответа:

19 цифр-это немного меньше, чем 64 бита, поэтому вы можете просто использовать 8-байтовый блочный шифр, такой как TDEA в режиме ECB, для шифрования значений BigInteger. Сначала извлеките 64-битную кодировку BigInteger по умолчанию,затем зашифруйте секретным ключом и, наконец, кодируйте его на базе 36. Результат будет на несколько символов меньше 16 символов,но вы всегда можете добавить любое значение.

Обратите внимание, что если вы зашифруете одно и то же значение дважды, то получите один и тот же результат, поэтому в этом отношении зашифрованный текст утечка некоторой информации о простом тексте.

Методика вы хотите формат ожесточенной шифрования. Это позволит вам зашифровать 19-значное число как другое 19-значное число.

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

Вот фрагмент кода, который, кажется, делает это, при условии, что вы можете преобразовать BigInteger в ulong (9999999999999999999-это на самом деле ulong). Результатом всегда является фиксированная строка из 16 символов (шестнадцатеричная).

    byte[] key = // put your 16-bytes private key here
    byte[] iv = Guid.NewGuid().ToByteArray(); // or anything that varies and you can carry

    string s = EncryptUInt64(ul, key, iv); // encode
    ulong dul = DecryptUInt64(s, key, iv).Value; // decode if possible


    public static string EncryptUInt64(ulong ul, byte[] key, byte[] iv)
    {
        using (MemoryStream output = new MemoryStream())
        using (var algo = TripleDES.Create())
        {
            algo.Padding = PaddingMode.None;
            using (CryptoStream stream = new CryptoStream(output, algo.CreateEncryptor(key, iv), CryptoStreamMode.Write))
            {
                byte[] ulb = BitConverter.GetBytes(ul);
                stream.Write(ulb, 0, ulb.Length);
            }
            return BitConverter.ToUInt64(output.ToArray(), 0).ToString("x16");
        }
    }

    public static ulong? DecryptUInt64(string text, byte[] key, byte[] iv)
    {
        if (text == null)
            return null;

        ulong ul;
        if (!ulong.TryParse(text, NumberStyles.HexNumber, null, out ul))
            return null;

        using (MemoryStream input = new MemoryStream(BitConverter.GetBytes(ul)))
        using (var algo = TripleDES.Create())
        {
            algo.Padding = PaddingMode.None;
            using (CryptoStream stream = new CryptoStream(input, algo.CreateDecryptor(key, iv), CryptoStreamMode.Read))
            {
                byte[] olb = new byte[8];
                try
                {
                    stream.Read(olb, 0, olb.Length);
                }
                catch
                {
                    return null;
                }
                return BitConverter.ToUInt64(olb, 0);
            }
        }
    }