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;
}
Python, 109 байтов от Sp3000
Обратите внимание, что Мартин сломался первым, поэтому я не уверен, заслуживает ли это очков. С другой стороны, я сделал атаку прообразом, а не простым столкновением - гораздо более сильный результат. Это означает, что вы можете присвоить ему произвольное хеш-значение, и оно создаст вход, который генерирует это хеш-значение.
И показать, что это работает:
И дать определенный набор чисел, которые сталкиваются:
источник
Python, 109 байтов от Sp3000
и
оба дают
Алгоритм разбивает входные данные на порции по 128 битов и многократно изменяет хеш (посеянный
42
) для каждого чанка перед выполнением некоторого дополнительного хеширования в конце. Чтобы найти коллизию, наша цель - найти два числа, которые дают одинаковый результат после запуска следующего псевдокода на каждом чанке:Поскольку для хэша взят мод 2 128, мы хотим искать числа, которые сдвигают все интересные вещи за пределы этого диапазона битов. Но для хэша добавлено
42
несколько не столь значимых битов:Моя идея состояла в том, чтобы избавиться от этих битов при добавлении первого куска. Итак, давайте попробуем 2 128 -42:
Это довольно просто, поэтому давайте попробуем использовать это как одно из двух чисел. (Действительно, первое число столкновений, которое я использовал, составляет 2 128 -42.
Теперь, как нам найти другое число с таким же результатом? Ну, после одной итерации хеш больше не
42
существует, но,2**122
как мы только что показали. Теперь, добавив второй блок к нашему входному номеру, мы можем запустить еще одну итерацию. Мы можем выбрать второй блок по тому же аргументу, что и этот, т.е. мы хотим 2 128 -2 122 . Тогда промежуточный результат послеhash += chunk
будет идентичным, и мы получим тот же результат в конце.Таким образом, мы можем вычислить два числа столкновения:
Мы можем легко создать еще много таких столкновений.
источник
Mathematica, 89 байт от LegionMammal978
и
Оба дают
0
.Принцип этого полицейского состоит в том, чтобы развить «случайный» двоичный 1-D клеточный автомат из «случайного» начального условия для «случайного» числа шагов, а затем интерпретировать первые 128 ячеек результата как целое число.
Проблема в том, что правило определяется просто так
Mod[#^2,256]
, что любое кратное 16 дает правило0
, которое является тривиальным правилом, когда все ячейки всегда равны нулю. Если вход не делится на 99, то мы будем развивать как минимум 1 шаг, поэтому выход всегда равен нулю. Таким образом, любые два кратных, которые не являются кратными 99, определенно сталкиваются. Тем не менее, вход0
также дает 0 (несмотря на то, что никогда не использует правило), потому что начальное условие - это просто двоичное представление ввода (в данном случае все нули).Кроме того, мы можем найти другие столкновения, которые полностью независимы от правила. Как отмечено выше, любое число, кратное 99, означает, что клеточный автомат вообще не развит, поэтому результатом являются просто первые (наиболее значимые) 128 бит начального условия ... которое само по себе является просто входным числом. Таким образом, если мы возьмем два кратных, которые не отличаются в первых 128 битах (дополненных нулями справа), мы также получим коллизию. Простейшим примером этого является
M = 99
,N = 99*2 = 198
.источник
J, 39 байт
Первый номер:
То есть
10000000
повторяется 64 раза. Второе число это плюс один, т.е.Оба дают
объяснение
Давайте начнем с
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
, и для первого шага мы получаемИтак, теперь мы хотим найти два числа
a, b
, чтоa == b mod k
. Чтобы сделать это, мы устанавливаем ,y
чтобы бытьk
и попытаться найтиa, b
такое , чтоx^a == x^b mod y
снова. Используя ту же логику, мы снова берем дискретный логарифм и получаемМы повторяем это до тех пор, пока не доберемся до малого
y
, и в этот момент тривиально найти два числа, которые хешируют одно и то же по модулюy
. После 63 итерацийy = 4
, в этот момент в основном работают любые два числа.Вот код Mathematica для генерации цепочки дискретных журналов:
Это дает следующий вывод .
источник
2^(2^30)
лимит, отсюда и чек.Pyth, 8 байт, FryAmTheEggman
и
Точность с плавающей точкой недостаточно велика для этого.
источник
437409784163148
за оба. Интересно, почему есть разница ...437409784163148
и37409784163148
я думаю, что он почему-то потерял последнюю цифру, но 99 ... 997 дает тот же ответ, что и 999 ... 98.CJam, 44 байта,
пользовательjimmy23013Числа слишком велики, чтобы их можно было публиковать, поэтому они находятся на Pastebin: num 1 , num 2 .
Первый номер
600^2 = 360000
один. Второй номер такой же, за исключением следующих изменений:Оба хеша
271088937720654725553339294593617693056
.объяснение
Давайте посмотрим на первую половину кода:
Итак, если мы сможем найти два входных числа, чтобы суммы
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)
так, чтобыгде
1 <= k <= 8
- величина, на которую нужно увеличить цифру 1 (т. е. изменить ее на цифру от 2 до 9 - мы могли бы включить 0, но она нам не нужна) и0 <= i < j < 600
это индексные пары.После того как мы
(i, j, k)
тройня, мы меняем цифры на(i, j)
и(j, i)
для того1+k
чтобы получить второй номер. Триплеты были найдены с использованием алгоритма жадного возврата, и для второго числа над цифрой квадрат выглядит так:Например,
(i, j, k) = (0, 1, 7)
соответствует изменению цифр(0, 1)
(позиция600*0 + 1 = 1
) и(1, 0)
(позиция600*1 + 0 = 600
) на1 + 7 = 8
.Вот обратный трекер в Python 3, хотя при ближайшем рассмотрении выяснилось, что нам повезло, так как никакого обратного отслеживания на самом деле не произошло:
Для бонуса, вот не очень эффективный порт хэша в Python 3. Он был бесполезен.
источник
PHP 4.1, 66 байт , Исмаэль Мигель
Найдено с помощью простого итеративного хэширования, начиная с 1:
источник
hash(hash(hash(...(hash(1)...)))
). Первая цепь сошлась в петлю почти мгновенно. Мне даже не нужно было поднимать мой многопоточный хэш-взломщик.Python 3 (216) от Sp3000
Мои сообщения
Я использовал этот код Python 2 для их генерации:
Большой модуль был произведением двух простых чисел
a
иb
. Я предполагаю, что надежда была на то, что для нас было бы невозможно NP-фактор, чтобы учесть полупростую, но я предполагаю, что 128 бит слишком малы, так как какая-то веб-страница дала мне ответ сразу.Мультипликативная группа по модулю
ab
будет иметь порядок (a - 1) (b - 1), что означает, что если мы возведем любое число в эту степень, это должно привести к 0 или (обычно) 1. Поэтому я помещаю 1 бит в местах, которые привели к 2 (a-1) (b-1) умножается на хеш. Тогда другое сообщение в основном равно 0, но я установил еще один бит в каждом числе, чтобы сделать длины одинаковыми.Я думаю, что было бы более раздражающим, если бы хэш возводился в квадрат на каждом бите, а не только после использования всех простых чисел. Тогда было бы не так просто построить для них произвольные показатели.
источник
C, 128 байтов - by: брезгливое оссифраж
Следующие две строки оба хэшируют все нули:
Хэш-функция построена так, что биты высшего порядка никогда не влияют на биты младшего разряда, поэтому я могу сгенерировать коллекцию строк, где все
x
биты младшего разряда равны нулю, а затем я могу попробовать каскадные комбинации этих строк, чтобы найти некоторые из них, где больше младшие биты равны нулю и т. д. Я почти уверен, что есть и другие способы этого, а также способы создания значительно более коротких строк, но таким образом я избегал много математических вычислений.источник
0x0000000a0000000a0000000a0000000a
моей системе, но это все еще довольно удивительно. (echo -ne '\x0a' |./hash
также дает тот же результат.)Python 3, 118 байт
и
(то есть: 9E400 и 9E4000)
Оба производят
Если копнуть немного глубже, то кажется, что любое целое число, за которым следуют k повторяющихся цифр, так что k> 128 и (k% 4 == 0) будут возвращать один и тот же хэш. Например,
H("1"+"1"*32*4)
иH("1"+"1"*33*4)
есть оба13493430891393332689861502800964084413
. Хм, 128 ...источник
Python 2, 161 байт, автор Puzzled
и
Оба имеют выход:
Числа 2 ^ 128 и 2 ^ 128 + (3 * 5 * 7 * 11 * 13 * 17) ^ 2 * 19 * 2 ^ 32.
источник
Java, 299 байт от SuperJedi224
Пастебин для
M
. В двоичном форматеM
имеет 655351
с, затем 20
с.Пастебин для
N
. В двоичном форматеN
имеет 218451
с, затем 1747660
с.Оба дают
0
.Обратите внимание, что в основе алгоритма лежит
i.bitCount()*i.bitLength()+1
и, в конечном счете, мы берем результат в степеньi
и принимаем его mod 2 128 . Таким образом, идея состояла в том, чтобы просто найти дваi
, которые делятся на четыре, но где первое выражение дает 2 32 . Это было легко сделать с помощью множителя 2 32 -1 и выбора двух факторов для подсчета 1 с и общей ширины в битах числа.Изменить: На самом деле, есть немного больше, почему
M
дает ноль, но мы можем легко найти больше чисел, которые дают ноль из-за моего объяснения, используя другие факторы 2 32 -1, так что в конце есть по крайней мере 64 нуля.источник
C, 134 байта (от Barteks2x)
и
оба хеша
потому что алгоритм хэширует только последнюю цифру!
источник
C 87 байтов
Нашел с помощью моего столкновения брутфорсер.
источник
473E0B6ED5AF2B92 7EC2BC9B5E9F5645 -> 0000000000000000 0EAC34C8A9F94389
после 3525078917 хеш вызовов иreal 14m24.970s user 48m42.410s
времени.Python 2, 115 байт, по брезгливому оссиффражу
и
Значение хеша не имеет ничего общего с порядком блоков.
источник
Python 2.x, 139 байт от Puzzled
H(2)
и
H(128)
оба возвращаются
16645614427504350476847004633262883518
,источник
C ++, 239 байт по SpelingMistake
Используя предоставленную «основную» программу, следующие два входа производят одинаковый хэш:
и
В первые 8 байт ввода никогда не обрабатываются , из - за этой ошибки в коде:
потому что
--i
оценивается как ложное, когдаi==1
,q[0]
(первые 8 байтов:I
являетсяint64
). Замена условия цикла наfor(I i=n;i--;)
исправила бы это.источник
Рубин, 90 байтов, МегаТом
и
2 и 11, за которыми следуют 40 нулевых байтов. Таким образом, они оба имеют 41 байт. Значение хеша добавляется к входной длине для каждого байта, а затем возвращается в десятичном виде. Длина ввода, заканчивающаяся на,
1
может гарантировать, что значение хеша закончится0
довольно быстро. Затем его обращение уменьшает длину хеш-значения на 1.Оба имеют хэш-значение
259
.источник
C # - 393 байта - от: Логан Дам
70776e65642062792031333337206861786f72
и70776e65642062792031333337206861786f7200
оба хеша18E1C8E645F1BBD1
.источник