Криптографический хэш-гольф (грабители)


12

Этот конкурс окончен.

В задании полицейских нет остающегося взломанного ответа.

Сопутствующая нить Cryptographic hash golf

В качестве напоминания, вот правила для грабителей из основной задачи:

задача

Трещина любой из полицейских Доводы, разместив следующие данные в потоке грабителей: два сообщения M и N в I таким образом, что H (M) = H (N) и M ≠ N .

счет

Взлом каждого подчиненного полицейского приносит вам одно очко. Грабитель с наибольшим количеством очков побеждает.

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

Дополнительные правила

  • Каждое подчинение полицейского может быть взломано только один раз.

  • Если представление полицейского основывается на поведении, определяемом реализацией или неопределенном, вам нужно только найти трещину, которая работает (достоверно) на вашей машине.

  • Каждая трещина принадлежит отдельному ответу в ветке грабителей.

  • Публикация неверной попытки взлома запрещает взломать эту конкретную отправку в течение 30 минут.

  • Вы не можете взломать ваше собственное представление.

пример

Python 2.7, 22 байта пользователем8675309

1

и

18

Leaderboard

  1. Электронный бизнес: 3 трещины, 393 байта
  2. Мартин Бюттнер: 3 трещины, 299 байт
  3. jimmy23013: 3 трещины, 161 байт
  4. Sp3000: 3 трещины, 44 байта
  5. tucuxi: 2 трещины, 239 байт
  6. Vi .: 2 трещины, 87 байт
  7. feersum: 1 трещина, 216 байт
  8. mathmandan: 1 трещина, 139 байтов
  9. брезгливое ossifrage: 1 трещина, 134 байта

Ответы:


5

C, 122 байта - автор: г-н Лама

bmaj8PCosFLAJjeHaevvvchnJedmg2iujpePOPivI2x2asw0yKa2eA15xvFJMFe82RGIcdlvxyaAPRuDuJhFjbh78BFsnCufJkarwEyKa0azHxccw5qegpcP9yaO0FKoohanxgiAfK1Lqwba51bKtjacbvdjMmcBkiv8kd62sBd98c4twa98sgj3iPh7nkP4
rlaejTPrua1DhBdg0jrIoDBi8fc1GIJAigivIGaxs1OmfPcctNadK3HErvzPLCeDPD8fkMNPCBcIwuoGfEHegOfk9k9pwktslqaBenaati1uNthMiyk9ndpy7gdIz88iot6A09cbNeIMheyjBvbeegL7aGp7mCb91hCxnvgV5abfImrPfLbrbraAsN6loJgh

Обе строки хеш bb66000000000000d698000000000000

Как и «C, 128 байт - by: squeamish ossifrage», биты более высокого порядка никогда не влияют на биты более низкого порядка, это можно использовать.

Код

Visual C ++, использует « небезопасные » строковые операции

#include "stdafx.h"
#include <string>
#include <iostream>
#include <fstream>

long long x, y;

//Original hash function (not used for cracking).
void h(char inp[]){
    long long c;
    int index = 0;
    int len = strlen(inp);
    x = 0;
    y = 0;
    long long p = 0;
    for (c = 9; c ; c = (index<len?inp[index++]:-1) + 1) {
        for (++p; c--;) {
            x = x*'[3QQ' + p;
            y ^= c*x;
            y ^= x ^= y;
        }
    }
    printf("%016llx%016llx\n", x, y);
}

//Partial hash, takes a string and a starting point in the stream.
//The byte 0x08 must be prepended to a string in order to produce a full legal hash.
void hp(char inp[],long long p){
    long long c;
    int index = 0;
    int len = strlen(inp);
    x = 0;
    y = 0;
    for (index = 0; index<len; index++) {
        c = inp[index] + 1;
        for (++p; c--;) {
            x = x*'[3QQ' + p;
            y ^= c*x;
            y ^= x ^= y;
        }
    }
}

//Reverse partial hash, backtracks the inner state.
void hprev(char inp[], long long p){
    long long c;
    long long clim;
    int index = 0;
    int len = strlen(inp);
    p += len + 1;
    x = 0;
    y = 0;
    for (index = len-1; index>=0; index--) {
        clim = inp[index] + 1;
        c = 0;
        for (--p; c<clim;c++) {
            y ^= x;
            x ^= y;
            y ^= c*x;
            x -= p;
            x = x * 17372755581419296689;
            //The multiplicative inverse of 1530089809 mod 2^64.
        }
    }
}
const int rows = 163840;
const int maprows = 524288;

//Store for intermediate input strings, row 0 contains 64 columns with 3-char strings,
//row 1 contain 32 columns with 6-char strings and so forth, the final strings will
//contain one string from each column, in order.
char store[7][rows][512];

//Storage for a hashmap, used for matching n strings with n string in O(n) time.
char map[maprows][512];

int _tmain(int argc, _TCHAR* argv[])
{
    char alpha[] = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    int row;
    int col;
    int layer;
    int a=0, b=0, c=0;
    int colzero;
    //Produce some starting strings.
    for (row = 0; row < rows; row++){
        //All column 0 strings begin with 0x08 in order to imitate the hash.
        store[0][row][0] = 8;
        colzero = 1;
        for (col = 0; col < 64; col++){
            store[0][row][col * 8 + colzero] = alpha[a];
            store[0][row][col * 8 + colzero + 1] = alpha[b];
            store[0][row][col * 8 + colzero + 2] = alpha[c];
            store[0][row][col * 8 + colzero + 3] = 0;
            colzero = 0;
        }
        a++;
        if (a >= 52){
            b++;
            a = 0;
            if (b >= 52){
                c++;
                b = 0;
            }
        }
    }
    //Layer for layer, column for column, build strings that preserve successively
    //more zero bits. Forward calculated partial hashes are matched with backwards
    //calculated partial hashes.
    for (layer = 1; layer < 7; layer++){
        int slayer = layer - 1;
        int swidth = 1 << (slayer + 3);
        int width = 1 << (layer + 3);
        int slen = 3 << slayer;
        int len = 3 << layer;
        int colnum;
        int layershift=slayer*8;
        for (col = 0,colnum=0; col < 512; col+=width,colnum++){
            printf("Layer: %i, column: %i\n",layer,colnum);
            memset(map, 0, sizeof map);
            int col2 = col + swidth;
            for (row = 0; row < rows; row++){
                hprev(store[slayer][row] + col2, 1 + slen*(1 + colnum * 2));
                x = (x >> layershift) & 255;
                y = (y >> layershift) & 255;
                int index = (x << 3) | (y << 11);
                for (a = 0; a < 8; a++){
                    if (map[index + a][0] == 0){
                        strcpy_s(map[index + a], store[slayer][row] + col2);
                        break;
                    }
                }
            }
            int destrow = 0;
            for (row = 0; row < rows && destrow < rows; row++){
                hp(store[slayer][row] + col, !!colnum + slen*(colnum * 2));
                x = (x >> layershift) & 255;
                y = (y >> layershift) & 255;
                int index = (x << 3) | (y << 11);
                for (a = 0; a < 8 && destrow < rows; a++){
                    if (map[index + a][0]){
                        strcpy(store[layer][destrow] + col, store[slayer][row] + col);
                        strcat(store[layer][destrow] + col, map[index + a]);
                        destrow++;
                    }
                }
            }
        }
    }
    memset(map, 0, sizeof map);
    char temp[1000];
    std::ofstream myfile;
    myfile.open("hashout.txt");
    for (row = 0; row < rows; row++){
        hp(store[6][row], 0);
        sprintf(temp, "%016llx%016llx", x, y);
        myfile << store[6][row] <<" " << temp << "\n";
    }
    myfile << "\n";
    //The final hash set has 96 of 128 output bits set to 0, I could have gone all
    //the way, but this is enough to find a collision via the birthday paradox.
    for (row = 0; row < rows; row++){
        hp(store[6][row], 0);
        long long xc = x;
        long long yc = y;
        int pos = (xc >> 45 | ((yc >> 48) & 7)) & (maprows-1);
        while (map[pos][0]!=0){
            hp(map[pos], 0);
            if (x == xc && y == yc){
                myfile << store[6][row] << "\n" << map[pos] << "\n";
                sprintf(temp,"%016llx%016llx", x, y);
                myfile << temp << "\n\n";
            }
            pos = (pos + 1) % maprows;
        }
        strcpy_s(map[pos], store[6][row]);
    }
    myfile.close();
    printf("done");
    getchar();
    return 0;
}

Потрясающие! Я на самом деле польщен странным способом! : D
Мистер Лама

Кроме того, для моего личного образования, когда вы говорите, что биты высшего порядка никогда не влияют на младшие, что вы имеете в виду? Биты высшего порядка входной строки или состояния хеша?
Мистер Лама

@ Mr.Llama В состоянии хеширования верхние биты x и y никогда не будут влиять на младшие биты, поэтому, например, если вы включите средние биты во время вычисления, младшая часть хеша все равно будет правильной. Это позволяет мне вначале игнорировать все, кроме самых младших битов в хэш-состоянии, затем, когда они полностью контролируются, я перехожу к следующему слою битов и так далее.
аааааааааааа

Здорово! Спасибо за объяснение!
Мистер Лама

Поздравляем с победой в конкурсе грабителей!
Деннис

12

Python, 109 байтов от Sp3000

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

M = 2**128

# The hash to crack.
def jenkins(n):
    h = 42
    while n:
        h += n & (M - 1)
        n >>= 128
        h *= 1025
        h ^= h >> 6
        h %= M

    h *= 9
    h ^= h >> 11
    h *= 32769

    return h % M

def egcd(a, b):
    if a == 0:
        return (b, 0, 1)
    else:
        g, y, x = egcd(b % a, a)
        return (g, x - (b // a) * y, y)

def modinv(a, m):
    g, x, y = egcd(a, m)
    if g != 1:
        raise Exception('modular inverse does not exist')
    else:
        return x % m

def invxorshift(h, s):
    r = h >> s
    while r:
        h ^= r
        r >>= s
    return h

def moddiv(a, b):
    return (a * modinv(b, M)) % M

def jenkins_crack(h):
    h = moddiv(h, 32769)
    h = invxorshift(h, 11)
    h = moddiv(h, 9)
    h = invxorshift(h, 6)
    h = moddiv(h, 1025)
    h -= 42
    return h

И показать, что это работает:

>>> from crack import *
>>> n = 2**128 + 1337
>>> h = jenkins(n)
>>> n2 = jenkins_crack(h)
>>> h2 = jenkins(n2)
>>> n != n2
True
>>> h == h2
True

И дать определенный набор чисел, которые сталкиваются:

N: 2**128
M: 43617

3
Мое первоначальное предложение в «песочнице» давало очки за коллизии, прообразы и (слегка упрощенные вещи) атаки на увеличение длины, но я решил сохранить счет простым. Когда я отредактировал эти части, тот факт, что каждое представление может быть взломано только один раз (как обычно работают полицейские и грабители), как-то утрачен. Когда я вижу твой ответ, мне жаль, что я не держал прообразы ...
Деннис

9

Python, 109 байтов от Sp3000

340282366920938463463374607431768211414

и

113982837842983129870077688367927159293402923522160868689804433865221255200726

оба дают

132946164914354994014709093261515948032

Алгоритм разбивает входные данные на порции по 128 битов и многократно изменяет хеш (посеянный 42) для каждого чанка перед выполнением некоторого дополнительного хеширования в конце. Чтобы найти коллизию, наша цель - найти два числа, которые дают одинаковый результат после запуска следующего псевдокода на каждом чанке:

hash += chunk
hash += (hash << 10)
hash ^= (hash >> 6)
hash %= 2**128

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

000000000000000000000000 ... 000000000000000000101010

Моя идея состояла в том, чтобы избавиться от этих битов при добавлении первого куска. Итак, давайте попробуем 2 128 -42:

           000000000000000000000000 ... 000000000000000000101010     hash = 42
           111111111111111111111111 ... 111111111111111111010110     chunk = 2**128 - 42
          1000000000000000000000000 ... 000000000000000000000000     hash += chunk
10000000001000000000000000000000000 ... 000000000000000000000000     hash += hash << 10
10000010001000001000000000000000000 ... 000000000000000000000000     hash ^= hash >> 6
           000001000000000000000000 ... 000000000000000000000000     hash %= 2**128

Это довольно просто, поэтому давайте попробуем использовать это как одно из двух чисел. (Действительно, первое число столкновений, которое я использовал, составляет 2 128 -42.

Теперь, как нам найти другое число с таким же результатом? Ну, после одной итерации хеш больше не 42существует, но, 2**122как мы только что показали. Теперь, добавив второй блок к нашему входному номеру, мы можем запустить еще одну итерацию. Мы можем выбрать второй блок по тому же аргументу, что и этот, т.е. мы хотим 2 128 -2 122 . Тогда промежуточный результат после hash += chunkбудет идентичным, и мы получим тот же результат в конце.

Таким образом, мы можем вычислить два числа столкновения:

>>> 2**128-42
340282366920938463463374607431768211414L
>>> 2**128-42 + ((2**128-2**122)<<128)
113982837842983129870077688367927159293402923522160868689804433865221255200726L

Мы можем легко создать еще много таких столкновений.


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

@orlp Обычно только первый грабитель получает очко. В противном случае, люди могут просто генерировать миллионы дополнительных трещин после того, как будет опубликована первая трещина.
Мартин Эндер

1
Хромой = / Думаю, я перестану делать этот вызов тогда. Я не люблю гоняться против других - я просто хочу озадачить. Разве не может быть временное окно для трещин после первого, только 1 трещина на человека?
orlp

@orlp Оригинальная версия в песочнице содержала три различных метода взлома полицейского, и все три могли быть опубликованы независимо. Я думаю, что это интересная модель для изучения в какой-то момент. Но до сих пор в предыдущих CnR, допускающих множественные взломы, вызов всегда был бы более серьезным, чем улучшением.
Мартин Эндер

1
Смотрите мой ответ для атаки прообраз, а не столкновения :)
orlp

8

Mathematica, 89 байт от LegionMammal978

0

и

16

Оба дают 0.

Принцип этого полицейского состоит в том, чтобы развить «случайный» двоичный 1-D клеточный автомат из «случайного» начального условия для «случайного» числа шагов, а затем интерпретировать первые 128 ячеек результата как целое число.

Проблема в том, что правило определяется просто так Mod[#^2,256], что любое кратное 16 дает правило 0, которое является тривиальным правилом, когда все ячейки всегда равны нулю. Если вход не делится на 99, то мы будем развивать как минимум 1 шаг, поэтому выход всегда равен нулю. Таким образом, любые два кратных, которые не являются кратными 99, определенно сталкиваются. Тем не менее, вход 0 также дает 0 (несмотря на то, что никогда не использует правило), потому что начальное условие - это просто двоичное представление ввода (в данном случае все нули).

Кроме того, мы можем найти другие столкновения, которые полностью независимы от правила. Как отмечено выше, любое число, кратное 99, означает, что клеточный автомат вообще не развит, поэтому результатом являются просто первые (наиболее значимые) 128 бит начального условия ... которое само по себе является просто входным числом. Таким образом, если мы возьмем два кратных, которые не отличаются в первых 128 битах (дополненных нулями справа), мы также получим коллизию. Простейшим примером этого является M = 99, N = 99*2 = 198.


8

J, 39 байт

Первый номер:

10000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000

То есть 10000000повторяется 64 раза. Второе число это плюс один, т.е.

10000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000001

Оба дают

322124197561777885386414076216564234267

объяснение

Давайте начнем с x := H 10000000 = 146018215378200688979555343618839610915, и y := 2^128. Вместо того, чтобы находить a, bтакое a == b mod y, мы будем искать a, bтакое x^a == x^b mod y, используя в алгоритме башни мощности.

Но должно быть что-то kтакое x^k == 1 mod y, потому что x, yэто взаимно, и для этого kмы должны иметь a == b mod k. Таким образом, мы можем найти дискретный логарифм 1 мод y, и для первого шага мы получаем

x ^ (k = 85070591730234615865843651857942052864) == 1 mod 2^128

Итак, теперь мы хотим найти два числа a, b, что a == b mod k. Чтобы сделать это, мы устанавливаем , yчтобы быть kи попытаться найти a, bтакое , что x^a == x^b mod yснова. Используя ту же логику, мы снова берем дискретный логарифм и получаем

x ^ (k = 21267647932558653966460912964485513216) == 1 mod 85070591730234615865843651857942052864

Мы повторяем это до тех пор, пока не доберемся до малого y, и в этот момент тривиально найти два числа, которые хешируют одно и то же по модулю y. После 63 итераций y = 4, в этот момент в основном работают любые два числа.

Вот код Mathematica для генерации цепочки дискретных журналов:

k = 0; x = 146018215378200688979555343618839610915; y = 2^128; While[y > 10, y = MultiplicativeOrder[x, y]; k++; Print[k, " ", y]];

Это дает следующий вывод .


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

@eBusiness Это правда. Оказалось, что здесь это не имеет большого значения, но сначала я беспокоился о том, чтобы преодолеть 2^(2^30)лимит, отсюда и чек.
Sp3000

На самом деле, я подозреваю, что может быть невозможно изготовить строку, где что-либо, кроме 512-й цифры, имеет значение. Вам удалось создать худший сценарий. Самым простым взломом должно быть использование внутренних ведущих нулей: «100000001», «1000000001».
аааааааааааа

7

Pyth, 8 байт, FryAmTheEggman

99999999999999999999999999

и

99999999999999999999999998

Точность с плавающей точкой недостаточно велика для этого.


Я на самом деле получаю разные результаты для этого, но я верю, что эта стратегия будет работать в любом случае, поэтому я отмечу ее как взломанную. Быстрая работа: P
FryAmTheEggman

Хм странно. Я получаю 437409784163148за оба. Интересно, почему есть разница ...
Sp3000

Вы, вероятно, используете Python 3.5 не так ли? Я еще не обновился, все еще на 3.4 может быть, это все?
FryAmTheEggman

@FryAmTheEggman Я использую онлайн переводчик, на самом деле ...
Sp3000

На самом деле, да, 437409784163148и 37409784163148я думаю, что он почему-то потерял последнюю цифру, но 99 ... 997 дает тот же ответ, что и 999 ... 98.
FryAmTheEggman

6

CJam, 44 байта, пользователь jimmy23013

Числа слишком велики, чтобы их можно было публиковать, поэтому они находятся на Pastebin: num 1 , num 2 .

Первый номер 600^2 = 360000один. Второй номер такой же, за исключением следующих изменений:

Positions to change to "2": 605, 1811, 3001, 6603
Positions to change to "4": 1805, 3003, 57348, 208895
Positions to change to "5": 602, 1201, 2405, 3004
Positions to change to "6": 1203, 1802
Positions to change to "7": 12, 609, 5401, 7200
Positions to change to "8": 1, 2, 4, 6, 600, 1200, 1808, 2400, 3600, 4803

Оба хеша 271088937720654725553339294593617693056.

объяснение

Давайте посмотрим на первую половину кода:

lW%                e#  Read input number as string, and reverse
600/               e#  Split every 600 digits, forming a 2D array
_z                 e#  Duplicate and zip, swapping rows and columns
{           }%     e#  For both arrays...
 JfbDb             e#  Find sum of S[i][j]*13^i*19^j, where S are the character values
                   e#  and the indices are from right to left, starting at 0.
      GK#          e#  Take modulo 16^20

         ...  ...  e#  (Rest of code irrelevant)

Итак, если мы сможем найти два входных числа, чтобы суммы S[i][j]*13^i*19^jбыли одинаковыми по модулю 16^20как для исходного массива шириной 600, так и для сжатого массива, то мы закончили.

Чтобы упростить задачу, мы рассмотрим только 600^2 = 360000-значные входные числа, так что массив шириной 600 - это просто 600 на 600 квадратных цифр. Это делает вещи проще для визуализации и действует с тех пор 10^360000 ~ 2^(2^20.19) < 2^(2^30). Чтобы еще больше упростить ситуацию, мы рассмотрим только такие входные строки, у которых квадрат цифр симметричен вдоль главной диагонали, так что исходный массив и сжатый массив совпадают. Это также позволяет нам игнорировать начальное обращение строк и нумерацию индексов справа налево, которые компенсируют друг друга.

Чтобы начать нас, мы можем взять первый номер, чтобы быть 360000теми. Чтобы получить второе число, мы хотим изменить это, изменив некоторые цифры так, чтобы суммы были одинаковыми по модулю 16^20, сохраняя при этом симметрию квадрата цифр. Мы достигаем этого, находя список троек (i, j, k)так, чтобы

sum of k*(13^i 19^j + 19^i 13^j) == 0 mod 16^20

где 1 <= k <= 8- величина, на которую нужно увеличить цифру 1 (т. е. изменить ее на цифру от 2 до 9 - мы могли бы включить 0, но она нам не нужна) и 0 <= i < j < 600это индексные пары.

После того как мы (i, j, k)тройня, мы меняем цифры на (i, j)и (j, i)для того 1+kчтобы получить второй номер. Триплеты были найдены с использованием алгоритма жадного возврата, и для второго числа над цифрой квадрат выглядит так:

188181811111711 ...
815112111711111 ...
851611111111111 ...
116114118112111 ...
811115111111111 ...
121451111111111 ...
811111111111111 ...
111111111111111 ...
111811111111111 ...
171111111111111 ...
111111111111111 ...
111211111111111 ...
711111111111111 ...
111111111111111 ...
111111111111111 ...

............... .
...............  .
...............   .

Например, (i, j, k) = (0, 1, 7)соответствует изменению цифр (0, 1)(позиция 600*0 + 1 = 1) и (1, 0)(позиция 600*1 + 0 = 600) на 1 + 7 = 8.


Вот обратный трекер в Python 3, хотя при ближайшем рассмотрении выяснилось, что нам повезло, так как никакого обратного отслеживания на самом деле не произошло:

n = 16**20
L = [(k *(pow(13,i,n)*pow(19,j,n) + pow(19,i,n)*pow(13,j,n)) % n, i, j, k)
     for i in range(600) for j in range(600) for k in range(1, 9) if i < j]

L.sort(reverse=True)
stack = [(n, 0, [])]

while stack:
    k, index, result = stack.pop()

    if k == 0:
        print(result)
        break

    if index == len(L):
        continue

    stack.append((k, index+1, result)) # Don't include triplet

    if L[index][0] <= k:
        stack.append((k - L[index][0], index+1, result + [L[index][1:]])) # Include

Для бонуса, вот не очень эффективный порт хэша в Python 3. Он был бесполезен.


5

PHP 4.1, 66 байт , Исмаэль Мигель

$ A=0111129112911291111111111111111111111111 php hash.php 2> /dev/null ; echo
0100038003800381129111111111111111111111
$ A=0111129112911291129111111111111111111111 php hash.php 2> /dev/null ; echo
0100038003800381129111111111111111111111
$ cat hash.php 
<? $a = getenv("A"); for($l=strlen($b.=$a*1);$i<40;$o.=+$b[+$i]^"$a"/$a,$i++);echo$o;

Найдено с помощью простого итеративного хэширования, начиная с 1:

$ i=1; while true; do i=$(A=$i php hash.php  2> /dev/null); echo $i; done | head -n 10
0111111111111111111111111111111111111111
0100000000000001129111111111111111111111
0111129111111111111111111111111111111111
0100038000000001129111111111111111111111
0111129112911111111111111111111111111111
0100038003800001129111111111111111111111
0111129112911291111111111111111111111111
0100038003800381129111111111111111111111
0111129112911291129111111111111111111111
0100038003800381129111111111111111111111

Да, тот взломан. Сколько времени понадобилось, чтобы добраться туда?
Исмаэль Мигель

Вторая попытка. Первая попытка - поиск значений первых 100 хэшей, вторая - создание цепочек хешей (т.е. hash(hash(hash(...(hash(1)...)))). Первая цепь сошлась в петлю почти мгновенно. Мне даже не нужно было поднимать мой многопоточный хэш-взломщик.
Ви.

Перевод: довольно слабый хэш?
Исмаэль Мигель

Да.
Ви.

5

Python 3 (216) от Sp3000

Мои сообщения

5012053369354645637214643587103597313576086380250249302980438772005248488380915054746146050001036696049972235875591571028140916001206596142280971107479334216535925703480968283657357930602076844092875640359192729378384507238123245417656548512647301639542279794868512420586823155070914644206130805893968511673770843170450832829657206145931885656157628306896903719624729809643572222159364893644113710867223921580178741177106141068298067479650611992859787419779579962211254029169589775046869542029842374359998053713002047081002506346875804341770199884355810931652447801492691887376948615365487982834690942054717077615539311699691010938426302886867891090301248321702485904291177813145565144089044261424329155436660979948932491709511914065619715728353376578192548334780893602675684085757434059540582004872746967999949306946618036846307799677491651967418565531672392468089533111553281620101129322575737949904022139471688252420467041529301533363008476437812216585923822571793353317799365005036029476865
5012053369354645637214643587103103086948976188724715498910865650846170784131001427390927276355140411160919276493388206817700368694224128444524223814513348177926532982330730066315320819293979046126543806115318009892783577432467861426768883700930779409885418980853424256180864755881414774514084197887594253752179391098292488771920695965135791582218083012144604515253506370334133858904659263953147111654656123599460222236152128559750436960308887683690915261431659087040402402092795259541564130228515353133867041828417398395559815392177084002004583988047406317670433664624642858480970640416500369367395538257341309676777745698712896295462462064271676447460293684100001583256400774270688958051470568447233589146620275159126426142305307007744396679875427883384557759778766330566230012377845843842097372663092379922300568052486301863154557664156185573021849420011058607321977550938866119133331529852821217331665195832442542012455132139770813510559894254061471149750738447764616026512400623344132554752

Я использовал этот код Python 2 для их генерации:

a,b = 14460445391122031029,16815296360833931837 #http://www.numberempire.com/numberfactorizer.php
pr = ~-a * ~-b

m0 = reduce(long.__or__, [long(b) << 26*i for i,b in enumerate(bin(pr)[2:])])
m1 = 1 << 26*i-1
m0 |= m1

#print m0, m1
print f(m0), f(m1)

Большой модуль был произведением двух простых чисел aи b. Я предполагаю, что надежда была на то, что для нас было бы невозможно NP-фактор, чтобы учесть полупростую, но я предполагаю, что 128 бит слишком малы, так как какая-то веб-страница дала мне ответ сразу.

Мультипликативная группа по модулю abбудет иметь порядок (a - 1) (b - 1), что означает, что если мы возведем любое число в эту степень, это должно привести к 0 или (обычно) 1. Поэтому я помещаю 1 бит в местах, которые привели к 2 (a-1) (b-1) умножается на хеш. Тогда другое сообщение в основном равно 0, но я установил еще один бит в каждом числе, чтобы сделать длины одинаковыми.

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


Отличная работа :) Да, уязвимость, которую я имел в виду, заключалась в том, что полупрограмма видна в коде, и я понял, что Mathematica может мгновенно ее учесть.
Sp3000

+1 Твой код трудно читать, но в остальном хороший и поучительный треск.
аааааааааааа

5

C, 128 байтов - by: брезгливое оссифраж

Следующие две строки оба хэшируют все нули:

dddl|lddH4|@dhxdxXdh0TXPdhhdx(dTxtlpdd@4Lhd|hdDpdhDdXLdXP4(PdddL|ldXdD(lddX4|0hddp4|ddP4Lxdp0dP@dhpTxPdhXdXxdhHDxHdllLttdhPT8pd(pT8Pdd0TL8dlLLTtddPtl8dP@DPPdhhDxhd804(pdh0Txpd@DDpLdhL4xtdXXdHXdd04lXht40dlddh4|@ddPTLXdhhDXHhtPH40dh0t8pd(pt80dhPtX0dhLtXtdhLT8thlLplTdhpt80dh0txpdhHDX(hdX8txdhhdxHdp|d@tdhlTx4dlptdxdh0T8PdT@t|Hdd@tL(ht(8DhdhHD8(hpHHP8dhLtXtdX8dhxdhpt8Pd@(D@Hdd@tLhdtxTLPdd0tlxhhL8X|dd8t|0dT04|Xddxt|phxxxhhdhpt8PhhxX8hdhlTX4dd4l||dd@TLHdXlTHtdhHd8hdX0THPdh(D8(d8xdh8dhp4xPd0HDp(dhl4xTdxlthtdhlTx4d8lT(TdhhdXHdphdP(dhp4x0d0Xd0XddTl||d88DH8dhhdxhdx|tHDdhLT8Thll0lTddPTlXdxXd(xdd0Tlxdhp480dhp4x0dd|LltdhPt80dtll|dddPTlXdxXd(xdd0Tlxdhp480dhp4x0dd|LltdhPt80dtll|dddP4Lxd|ptT8dhddxldH|4xDdhp4x0dDdl|LdhtD8|hhHx88ddpTL8hhphx@dhtd8|dphDP(dh0tx0hhDHx4dhpt8Pd@(D@HddLLLDhh|xxldhl4xTdhL4x4dhPt8Pd(HDx(dh(D8Hd4PT|8ddH4|@hh4H8ddhxd8XdDP4lxdhHd8hdl04d8ddXT|phdh8Thdd@TlHdhXdxxdllL44dD@4lHdhxdxXhd8XtxddLlLddT@T|(dhxdXXd|P44Xdhpt8pdlHDT0dhL4Xtd@ldpDdddl|LdXP4h0dhltXtdX8d(Xdh|tXdhhLXX|dhxd8XdP@D0PdhXDxXhtpHtPdd84|pddtl||dh(dx(d88Dh8ddx4|PhtT0DLdd@tL(hdX8Txdhp480d08d08dlll44d4dLLldhTdX|hh8Xxhdh048pd08d08ddPtL8d4H4l@dhhdxHd|pt4Xddp4lXhp(hPxdh|48DdxhDh(ddLlldd8XdH8dddl|LdLHDT0dhpt8pdlHDT0dh(d8hdTHtl@ddptl8dt84LPdh8dxxdlptD8dd04lxhhH8XxddDl|ldP|D@4ddTl||d|ptT8dh(dXhhd8X48dhPtXpd(8DxXdh@TX@dDP4L8dhpTX0d4@4|hdhHdxHdX8DHxdhPT8PhllplTdh0TXPhlXHLXddp4lXhtHXD(dhP4X0htH8dhdhLTx4hpxHPHdhhd8(dX8DHxdhpt80hhdHxTdlll44d@Hd@(dhhDxhdh0t8Pddh4|@ddh4|@dhptx0dpPD0@ddPtlxdhPT8pdhhdX(htTpDLdd@4L(dLHDtpdhxd8xdt84lPdlpTdxdDPTLXddLLLDdxlThtdlhd4PdXLTh4ddptLxd|@44(dhhd8HdtDLLlddxt|pd|hDd0ddPtLXhl@H|pdhDD8ld8dDhLdhXDXxdDxT|PdhHD8hdp8dpxdhp480d@XD@xddpTLXdHhD8(ddllLDdD|LL4dhpt80d@LdPDdh|4xDdP8dpXddLllddl8d4@dhptXpdd(4|@dhltx4d0Dd@LdhptxphdPHdpdhl4xTdxlthtdhHD8HdTdllldhLtX4dXP4(PdhLTxTd4X4LpddlllDdlpTD8dllltTdL(dtPdhDDxLdhLTx4dhptx0d|0T4Xdhl4xTdHL4XtdhpTXpdLp4dxddHt|@dHL484dhHDXHdHLtxtdhDdXldxL4H4dh|TxDhh8xX(dhLt8td8Lt(TdhHDx(d4DlLlddXT|PdHHD8(dlll44dlP4dxdd@tL(dL@4dhdd0tLxd4X4l0dhhdxhdDlLldddLLlddD04l8ddPtlxd(hd8hdd(T|@hdDp4|ddP4Lxdp0dP@dhptXpd(p4X0dhhd8(d8pT(0dh8d8Xhd(XT(dhddxLd@XD@8dd@tlhd@ld0ddhTD8|hhPH8@ddtl||dH0Tx0ddLlLddhp480dhHdxhd4lL|DdhXD8xdhhDX(dh048pd4Ll|ddddl|LdXP4h0dlll4thhdhxtddP4LXdhXdxXdhpTX0hdXXtxddlLLddx0Th0ddTl||hlhhlHdd|Ll4dHDdXldhhDX(hpxh0HdhDDXLdXDDhLdlhDTpht8Xdxdhpt8phhHXX8dd(t|@dHl4xtddp4LXhxhXH8dhDDxldDXt|PdhTDX|d|0ttxdhdDXLdDLLLddd84|PdT84LpdlhDTphl8hlxdhXD8xdHpt8Pdlhd40ddHT|@dhxdX8dhlT84dh|T8dhlXHLxdhxDxXdT4lL|dlllttd@xd@xdhhDXHhtXXD8dh(d8(d4p4|8dd04lxdxPThpdhHD8Hhdhx4hdhl4xthl|pLDdhltX4dhP4XPdd0Tlxdl@tDhddP4lXd0xD0xdhHD8Hd@8D@xdh0T8Pd0XDpxddPtl8dP@DPPdhhDxhd804(pdd04L8hpxHphdhDdxLdppD0@dd@tl(d88dHXdh0txpdXhDhHdd@Tlhdx8DHXdh0tXPdxxdH8dhPT8Pd484LPdlhD4pdxxdHxdd|Lltdhptx0dhlTx4hp8HPhdhPt8pdt4lL|ddtl||dH0Tx0dhxd8xhl@H|pddLllDhldP||dhdD8ldXLTHTdlhDTpddllLddd04lxhhH8Xxdh|48DdP8d0XddLLldd|@44hdhhd8hd4x4L0dhltXthh4H8Ddh4DX|dD@Tlhdh0tXpd8|T(ddhtDX|dlhdTPdd@tLhdThTl@dh8D8xdT(TL@dd@Tl(d8Hd(hdhXdxxhtHXdhdd0tl8d|HDDPdd8T|PdH04xPdd@Tl(d|@4t(dd(4|@dHp4xpdhpt80dh0txpdhp48phdXxTxdhhDXHhtPH40dh0t8pd(pt80dd8T|pdlxdt@dhp48PdD0TLXdh0t8Pd|lldTdh|t8DhphHp8

ddTl||d4|L|4dhptX0d4dllLddxT|pdxXdH8dlhDtPhlpH|@dd|Lltdhptx0dhlTx4hp8HPhdhPt8pdt4lL|ddtl||dH0Tx0ddLLLDd8tdH|dhDD8LdtxtLpdhxD8Xhd8xtxdhPt8Pd(8DX8dhddxLd0xd08dd0Tlxdxdd(Lddh4|@dXpt(Pdh048pd0xd0xdhhDX(d8p4Hpdh0480d(8DX8dhL4x4d4PT|XddPTLXdPDd@Ldddl|ld(P4X0ddDL|lht88DXdhPtxpd((Dx(dh0tx0dxXd(8dhpT8Pd0xD0XdlhD4pdT0T|8dh04XPht0H40dlhDtpdpHDP(dhlTXtdPHdpHdhXDxXhpPH0pddDl|lhltp|Ldh04x0dtXTL0ddLLLDdLhdtpdhL4xtdHDdXLddxt|0d4X4l0dh(Dxhdx04h0ddllLDd0PD0@dhXDxxhdx848dhDDxldpXDpXdhPt8pdhltxTdd04lxhhH8Xxdh|48DdP8d0XddLLldd|@44hdhhd8hd4x4L0dhltXthh4H8Ddh4DX|dD@Tlhdh0tXpd8|T(ddhtDX|dlhdTPdhlTXtdTX4L0dd@Tlhhh8xXHdhPt80d|XdD@dhp4xphd4Ptldd|LL4dL|ltDdhPTx0d80T(pdhpt8pd|pTtXdhpTX0hhth8Ddhxd8xdphdP(dh8D88dp(DPhdhHD8(htxXdXdh8dXXdXpTH0ddx4|PdpXDPxdhXDXXdxxdhXdhlt8Td@xD@8dhP4XPdhltX4dd@tlHdhXDxxdhPtXPd(8Dxxdh0t8PhdpHd0dh(D8HdX(D(Hdd@tLhht|@4Tdd@4lHdttll|dd0tlXhh|xxldd@TLHdlHdTPdd|LL4dt@T|hddx4|PdlHdtPddTl||d88DH8dlhdTpd40t|xddht|@dpPDP@dhHDxHhxthHDdhddxldxtDH|dhltx4d8Dd(ldd|LLthp0H0Pdhl4x4d|0T4Xdd|ll4dt8tLPdd@4lhd|0TTXddPtLXd(8d8xdhPTxPdHxd8xdhHDX(ddLllddhp48Pd0@d0PdhptxpdX(DhHdd0TlXhtPHTPddh4|@dTDlLldhDDxLhp(hPxdhdD8ldXLTHTddPtLXdTh4L@dhLtxTdlpTd8dhPtXpdhLtX4ddPTlXdxxdhXdhhd8(d404|8dhTd8|dhL4Xtddp4l8d4X4LpdhL4Xtd@ldpDdddl|LdXP4h0dhpTX0htXxDxdhpt8pddLlLddhp4XPhp0H00dh4Dx|dlp4D8dhPtxpd((Dx(dh0tx0dxXd(8dhDDxlhlL0ltdhhDxHd@|d0TdhHdxhdL0tD8dhhD8hhl|pLdddxt|pd|hDd0ddPtLXhl@H|pdhxDXxd8DdhldlhdtphpphppdhpT8PdH8dxXdlhd40dtXtlPdhTd8|dXlthtdhTDX|dx|4HDddxT|pdHDd8ldhL4X4dhP4XpdhtDx|ddXt|Pdh|T8DdHhdxhddLLLDhlxHl8dh0tXPd|(ddPddDL|LdHhdxhdhp4x0dl8dT@ddXT|phdh8Thdh(DXhd0HDP(dddl|lhd(xT(dhXdXxdTxtl0dd|lLtd8|4hddd4l||dXLTh4dd04lxdP8DP8ddxT|0dXXdh8ddP4lxd0@DpPdh8dXxddp4lxdhLt8tdHTdx|dh4Dx|dxLTHtdhhd8hd@DDpldd04LXdXlT(tdhXdXxdhPT8pdh(DXHdP@dp0ddP4LXdXpThPdllL4td((D8(dh0tXpd|(ddpdh(DxhhdL@DDdhHDx(dxL4(tdhLtXtdl@4dHdhxd8xdTh4L@dhXDXXhhdH8Tdd8T|PdH04xPdlllT4hllpLtdhhDXHhxxXhhdhXDxXdPDd@Ldd0TlXdHLtX4ddDL|ldXLT(4dhPtXPdXXd(8dhpt8phdH8thddxT|pd(ptXpddP4LxdLXDT@dhpT80dLptDxddxt|pdP@Dp0dhptx0d|0T4XdlpTdxdxpt(PdhHD8(d4TlL|dhHDx(d@hD@(dd@tl(d88dHXdh(Dx(d4pT|xddPtl8dP@DPPdhhDxhd804(pdhHD8Hhdhx4hddP4lxhdhXt(dhxdX8dp@DppdlllT4dP0dp@dddl|ldH8DXXdllLT4dPXdp8dd@tLHdlPTd8ddtL||d8PtHpddHt|@hd|@d4dh(dX(hdhXT(dhpT80hdHX4(dlpTdxdtDlLlddxT|pd(ptXpddP4LxdLXDT@dhpT80dLptDxddxt|pdP@Dp0dhptx0d|0T4XdlpTdxdxpt(PdhHD8(d4TlL|dhHDx(d@hD@(dddL|lhtph40dhpTxPdlp4dXdhDDxldpxD08dh(dX(dHlTxTdd|ll4d40t|Xdh0480ht@hT@dhptXphdHxT(dh(D8Hd4PT|8dhpt8pd88dhXddDl|LhxdHHtddPtlXd|pt4Xdd0Tl8d0(D0hdhhd8hdppd0@ddPTlXd8P4hpdhlTx4d8dDhLdd@TLhhllplTddXT|0dH|4XDdh|4xDht8XD8ddptl8dH8d88dd|LLTdh(DXhddHt|@hpXhp(dhdDxLdDhT|@dhP4X0dXhDHhdh0T8Pd((dxhdhhDx(hdx8Txddp4LXd8xDH8dhPTXpdlPtD8dh(DxHd@8D@Xdhl48Td00Dp@dhLT8Tdp(d0(dhhd8(d404|8dhhdx(dx0T(pdd|lL4ddXt|Pdd0TlXhxdH(4ddllLDhhLXX|dhXDx8hl8hLxdhpT80dLPtDXdhptX0dPXd0XddP4lxd0@DpPdlptd8dl(dTPdhxDx8d(ptX0dhpT80htxxdXdhhDxhdXltHtddh4|@d@|dPTdhdDXLhpph0Pdhp48Pdt4lL|dh04xpdLpTD8dd@4lhdl8dt@ddhT|@dPxDp8dd04lXd40t|xdd0TLxdTdlLLddpTLXd|pTT8dd04lxhhH8XxdhddxlhddPT|dd04LXdlhd4pdh8d8xhh|8XLdhxd8xd(8d8xdhp48pd(8DX8dhhDXHd4dllLddx4|0d8PTH0ddPtlxd|P44XdlpTdxd(XDXXddpTlxdHltX4dhLTxtd|HDD0

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


Потрясающие! Они оба хэш в 0x0000000a0000000a0000000a0000000aмоей системе, но это все еще довольно удивительно. ( echo -ne '\x0a' |./hashтакже дает тот же результат.)
r3mainer

1
@squeamishossifrage У вас есть строка новой строки после каждой из строк, без чего это просто нули.
аааааааааааа

Ах, да, моя ошибка :-)
r3mainer

4

Python 3, 118 байт

int(H("9"+"0"*400))

и

int(H("9"+"0"*4000))

(то есть: 9E400 и 9E4000)

Оба производят

83909358607540647658718900164058931893

Если копнуть немного глубже, то кажется, что любое целое число, за которым следуют k повторяющихся цифр, так что k> 128 и (k% 4 == 0) будут возвращать один и тот же хэш. Например, H("1"+"1"*32*4)и H("1"+"1"*33*4)есть оба 13493430891393332689861502800964084413. Хм, 128 ...


4

Python 2, 161 байт, автор Puzzled

340282366920938463463374607431768211456 (decimal)
100000000000000000000000000000000 (hexadecimal)

и

340282366920938468780317283222139437056 (decimal)
100000000000001203B66F94300000000 (hexadecimal)

Оба имеют выход:

83F172CC3D050D131F64FD04B8181DC2

Числа 2 ^ 128 и 2 ^ 128 + (3 * 5 * 7 * 11 * 13 * 17) ^ 2 * 19 * 2 ^ 32.


3

Java, 299 байт от SuperJedi224

Пастебин для M. В двоичном формате Mимеет 65535 1с, затем 2 0с.

Пастебин для N. В двоичном формате Nимеет 21845 1с, затем 174766 0с.

Оба дают 0.

Обратите внимание, что в основе алгоритма лежит i.bitCount()*i.bitLength()+1и, в конечном счете, мы берем результат в степень iи принимаем его mod 2 128 . Таким образом, идея состояла в том, чтобы просто найти два i, которые делятся на четыре, но где первое выражение дает 2 32 . Это было легко сделать с помощью множителя 2 32 -1 и выбора двух факторов для подсчета 1 с и общей ширины в битах числа.

Изменить: На самом деле, есть немного больше, почему Mдает ноль, но мы можем легко найти больше чисел, которые дают ноль из-за моего объяснения, используя другие факторы 2 32 -1, так что в конце есть по крайней мере 64 нуля.



3

C 87 байтов

$ echo B075343F9832CD60 | ./hash6_ ; echo
fc2e9f02bd284bd1
$ echo 5914BD1B71164C77 | ./hash6_ ; echo
fc2e9f02bd284bd1

Нашел с помощью моего столкновения брутфорсер.


Возможно это из-за того, что только 64-битный.
Ви.

Молодцы :-) Сколько времени это заняло?
r3mainer

Около 7 минут работы программы. Теперь снова начал с измерений.
Ви.

1
Обнаружил еще одну коллизию: 473E0B6ED5AF2B92 7EC2BC9B5E9F5645 -> 0000000000000000 0EAC34C8A9F94389после 3525078917 хеш вызовов и real 14m24.970s user 48m42.410sвремени.
Ви.

3

Python 2, 115 байт, по брезгливому оссиффражу

1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222

и

2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

Значение хеша не имеет ничего общего с порядком блоков.



2

C ++, 239 байт по SpelingMistake

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

echo -n "dog" | ./h
481c27f26cba06cf

и

echo -n "fog" | ./h
481c27f26cba06cf

В первые 8 байт ввода никогда не обрабатываются , из - за этой ошибки в коде:

 for(I i=n;--i;) // and then we use q[i] for this iteration

потому что --iоценивается как ложное, когда i==1, q[0](первые 8 байтов: Iявляется int64). Замена условия цикла на for(I i=n;i--;)исправила бы это.


Похоже, первые 8 байтов ввода просто игнорируются.
Ви.

Похоже, ошибка в коде; исправление идет суффикс вместо префикса.
Tucuxi

1
Также есть столкновения без ошибок (см. Комментарии к исходному вопросу).
Ви.

2

Рубин, 90 байтов, МегаТом

4271974071841820164790043412339104229205409044713305539894083215644439451561281100045924173873152

и

23495857395130010906345238767865073260629749745923180469417457686044416983587046050252582956302336

2 и 11, за которыми следуют 40 нулевых байтов. Таким образом, они оба имеют 41 байт. Значение хеша добавляется к входной длине для каждого байта, а затем возвращается в десятичном виде. Длина ввода, заканчивающаяся на, 1может гарантировать, что значение хеша закончится 0довольно быстро. Затем его обращение уменьшает длину хеш-значения на 1.

Оба имеют хэш-значение 259.


2

C # - 393 байта - от: Логан Дам

70776e65642062792031333337206861786f72и 70776e65642062792031333337206861786f7200оба хеша 18E1C8E645F1BBD1.


Здорово! Не могли бы вы объяснить, как вы взломали это? А может быть "неисправная прокладка"?
ldam

@LoganDam Это весь этот код, который переключается вокруг ввода, в итоге вы обрабатываете кратное 8 символов, а если длина ввода не кратна 8, вы заменяете нули. Если я добавлю несколько нулей в нужном месте, они просто займут место отступа, который был нулем в первую очередь.
аааааааааааа
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.