Криптографічний хеш-гольф


34

Цей конкурс закінчився.

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

Цей виклик - це пошук найкоротшого виконання хеш-функції , стійкої до зіткнень , тобто знайти два різних повідомлення з одним і тим же хешем має бути нездійсненно.

Як поліцейський, ви намагаєтесь винайти та реалізувати хеш-функцію, знаходячи найкращий компроміс між розміром коду та стійкістю до зіткнення. Використовуйте занадто багато байтів, і інший поліцейський перевершить вас!

Як грабіжник, ви намагаєтесь зірвати спроби поліцейських, розбивши їх функції, доводячи, що вони непридатні. Це змусить їх використовувати більше байтів для посилення своїх алгоритмів!

Виклики копів

Завдання

Реалізуйте криптографічну хеш-функцію H: I -> O на ваш вибір, де I - безліч усіх негативних цілих чисел нижче 2 2 30, а O - безліч всіх негативних цілих чисел нижче 2 128 .

Ви можете реалізувати H як фактичну функцію, яка приймає і повертає єдине ціле число, рядкове подання цілого чи масиву цілих чисел або повну програму, яка читає зі STDIN і друкує до STDOUT в базі 10 або 16.

Оцінка балів

  • H, що вона має протистояти розбійникові, визначеному нижче

    Якщо грабіжник зазнає поразки у ваших поданнях протягом перших 168 годин після публікації, він вважається розбитим .

  • Реалізація Н повинна бути якомога коротшою. Найкоротший нереалізований подання стане переможцем виклику копів.

Додаткові правила

  • Якщо ви реалізуєте функцію H як функцію, надайте обгортку для виконання функції з програми, яка веде себе, як пояснено вище.

  • Будь ласка, надайте принаймні три тестові вектори для вашої програми або обгортки (приклади входів та їх відповідні результати).

  • H може бути вашим новим дизайном (кращим) або відомим алгоритмом, якщо ви його реалізуєте самостійно. Забороняється використовувати будь-які вбудовані хеш-функції, функції стиснення, шифр, PRNG тощо.

    Будь-яка вбудована, яка зазвичай використовується для реалізації хеш-функцій (наприклад, перетворення базових даних) - це чесна гра.

  • Вихід програми або функції повинен бути детермінованим.

  • Має бути безкоштовний (як у пиві) компілятор / перекладач, який можна запускати на платформі x86 або x64 або з веб-браузера.

  • Ваша програма або функція повинна бути достатньо ефективною і має хешувати будь-яке повідомлення в I нижче 2 2 19 менше ніж за секунду.

    Для крайових випадків вирішальним буде вирішення часу (стінного) часу на моїй машині (Intel Core i7-3770, 16 ГБ оперативної пам’яті).

  • Враховуючи характер цього виклику, заборонено будь-яким чином змінювати код вашої відповіді, чи змінює вона результат чи ні.

    Якщо ваше повідомлення було зламано (або навіть якщо воно не відбулося), ви можете опублікувати додаткову відповідь.

    Якщо ваша відповідь недійсна (наприклад, вона не відповідає специфікації вводу-виводу), видаліть її.

Приклад

Python 2.7, 22 байти

def H(M):
 return M%17

Обгортка

print H(int(input()))

Розбійник виклик

Завдання

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

Оцінка балів

  • Якщо зламати кожне подання поліції, ви отримаєте один бал. Перемагає грабіжник з найбільшою кількістю очок.

    У разі краватки виграє прив'язаний розбійник, який тріснув найдовше.

Додаткові правила

  • Кожне подання копа може бути зламано лише один раз.

  • Якщо подання на поліцейських покладається на визначену реалізацією чи не визначену поведінку, вам залишається лише знайти тріщину, яка працює (перевірено) на вашій машині.

  • Кожна тріщина належить до окремої відповіді в нитці розбійників.

  • Опублікування недійсної спроби злому забороняє вам зламати саме це подання протягом 30 хвилин.

  • Ви не можете зламати власне подання.

Приклад

Python 2.7, 22 байти користувачем8675309

1

і

18

Таблиця лідерів

Безпечні матеріали

  1. CJam, 21 байт електронного бізнесу
  2. C ++, 148 байт по tucuxi
  3. C ++, 233 (?) Байт від Vi.

Невикористані подання

Ви можете використовувати цей фрагмент стека, щоб отримати список ще не взламаних відповідей.

function g(p){$.getJSON('//api.stackexchange.com/2.2/questions/51068/answers?page='+p+'&pagesize=100&order=desc&sort=creation&site=codegolf&filter=!.Fjs-H6J36w0DtV5A_ZMzR7bRqt1e',function(s){s.items.map(function(a){var h=$('<div/>').html(a.body).children().first().text();if(!/cracked/i.test(h)&&(typeof a.comments=='undefined'||a.comments.filter(function(b){var c=$('<div/>').html(b.body);return /^cracked/i.test(c.text())||c.find('a').filter(function(){return /cracked/i.test($(this).text())}).length>0}).length==0)){var m=/^\s*((?:[^,(\s]|\s+[^-,(\s])+)\s*(?:[,(]|\s-).*?([0-9]+)/.exec(h);$('<tr/>').append($('<td/>').append($('<a/>').text(m?m[1]:h).attr('href',a.link)),$('<td class="score"/>').text(m?m[2]:'?'),$('<td/>').append($('<a/>').text(a.owner.display_name).attr('href',a.owner.link))).appendTo('#listcontent');}});if(s.length==100)g(p+1);});}g(1);
table th, table td {padding: 5px} th {text-align: left} .score {text-align: right} table a {display:block}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"><table><tr><th>Language</th><th class="score">Length</th><th>User</th></tr><tbody id="listcontent"></tbody></table>


Якщо хеш-функція помилково повертає числа, більші за 2 ^ 128-1, чи це недійсне подання, чи ми б просто взяли результат модуля 2 ^ 128?
Мартін Ендер

@ MartinBüttner: Так, вам доведеться взяти результат модуля 2 ^ 128.
Денніс

1
@Scimonster Не відповідає вимогам (до 2 ^ 30 біт вводу, 128 біт вихідних даних)
CodesInChaos

1
Чи не поліцейські та грабіжники зазвичай йдуть навпаки?
haneefmubarak

2
Можливо, у нас може бути правило, згідно з яким подання має містити хеші прикладів, досить дратує те, що потрібно запускати вибрану мову програмування для відправників, щоб мати результат порівняти ті, які тріскають реалізацію.
aaaaaaaaaaaa

Відповіді:


6

CJam, 21 байт

1q3*{i+_E_#*^26_#)%}/

Беруть рядок байтів як вхід.

У псевдокоді:

hash = 1
3 times:
    for i in input:
        hash = hash + i
        hash = hash xor hash * 14^14
        hash = hash mod (26^26 + 1)
output hash

Приклад хешей:

"" (порожня рядок) -> 1
"Тест" -> 2607833638733409808360080023081587841
"тест" -> 363640467424586895504738713637444713

Це може бути трохи на простому боці, діапазон виходу лише трохи більше 122 біт, посилення потрійної ітерації вже трохи порушено, оскільки це робить щойно те саме, що кожного разу, тому введіть хеш до 1 у першому ітерація буде повною перервою. Але він короткий, і не буває весело бути занадто безпечним.


Чи є супровідна версія C, як в іншому посту CJam?
Ві.

@Vi. Ні, ще принаймні. Я ніколи не спіймався з bigint в C, чи є для цього стандартна бібліотека?
aaaaaaaaaaaa



1
@ Agawa001 Ви змішуєте свою термінологію. Це алгоритм хеш-функції функцій потрійного проходу. Шифр Цезаря - це один конкретний алгоритм шифрування без внутрішнього стану.
aaaaaaaaaaaa

7

Python, 109 байт [ тріснув , і знову ]

def f(n,h=42,m=2**128):
 while n:h+=n&~-m;n>>=128;h+=h<<10;h^=h>>6;h%=m
 h+=h<<3;h^=h>>11;h+=h<<15;return h%m

Я спробував реалізувати функцію однієї за часом Дженкінса як є, з тією лише різницею, як насіння та кількість бітів.

Факт забави: Мабуть, Perl в якийсь момент використовував хеш Дженкінса .

Обгортка

print(f(int(input())))

Приклади

>>> f(0)
12386682
>>> f(1)
13184902071
>>> f(2**128-1)
132946164914354994014709093274101144634
>>> f(2**128)
13002544814292
>>> f(2**128+1)
13337372262951
>>> f(2**(2**20))
290510273231835581372700072767153076167



6

C ++, 148 байт

typedef __uint128_t U;U h(char*b,U n,U&o){U a=0x243f6a8885a308d,p=0x100000001b3;for(o=a;n--;)for(U i=27;--i;){o=(o<<i)|(o>>(128-i));o*=p;o^=b[n];}}

__uint128_t є розширенням GCC і працює як очікувалося. Хеш заснований на ітераційному хеші FNV (я запозичив їх прем'єр, хоча aце перші цифри Pi в шістнадцятковій) з ша1-подібним обертанням на початку кожної ітерації. Для компіляції -O3хешування 10MB-файлу займає менше 2 секунд, тому все ще є запас для збільшення ітерацій у внутрішньому циклі - але я відчуваю себе щедрим сьогодні.

Зніміть зміну (змінені назви змінних, додані коментарі, пробіл та пара дужок) для ваших задоволень:

typedef __uint128_t U;
U h(char* input, U inputLength, U &output){
    U a=0x243f6a8885a308d,p=0x100000001b3;    
    for(output=a;inputLength--;) {   // initialize output, consume input
        for(U i=27;--i;) {                          // evil inner loop
            output = (output<<i)|(output>>(128-i)); // variable roll 
            output *= p;                            // FNV hash steps
            output ^= input[inputLength];        
        }
    }
    // computed hash now available in output
}

Пропозиції з гольфу вітаються (навіть якщо мені не вдається вдосконалити код на їх основі).

редагувати: виправлені помилки з помилковим кодом (версія для гольфу залишається незмінною).


oначебто неініціалізовані. Де outputоголошено? А може, oє output?
Ві.

Те саме для n. Ви дійсно перевірили запуск "знеціненого" коду?
Ві.

Почав грубий борець ...
Ві.

Навіть 3-кругла версія непроста.
Ві.

@Vi. Виправлена ​​непридатна версія - вибачте, що не перевірили її краще. Я пишаюся тим внутрішнім циклом; U i=81;i-=3могла бути ще більш мерзенною, без значних витрат на виконання.
tucuxi

5

CJam, 44 байти [ тріщини ]

lW%600/_z]{JfbDbGK#%GC#[md\]}%z~Bb4G#%\+GC#b

Вхід знаходиться в базі 10.

CJam повільний. Я сподіваюся, що він працює за 1 секунду на якомусь комп’ютері ...

Пояснення

lW%600/            e# Reverse, and split into chunks with size 600.
_z                 e# Duplicate and swap the two dimensions.
]{                 e# For both versions or the array:
    JfbDb          e# Sum of S[i][j]*13^i*19^j, where S is the character values,
                   e# and the indices are from right to left, starting at 0.
    GK#%GC#[md\]   e# Get the last 32+48 bits.
}%
z~                 e# Say the results are A, B, C, D, where A and C are 32 bits.
Bb4G#%             e# E = the last 32 bits of A * 11 + C.
\+GC#b             e# Output E, B, D concatenated in binary.

Що ж, двомірні речі здавалися слабкістю ... На початку покликано було зробити кілька повільних обчислень. Але він не може працювати за секунду, що б я не робив, тому я остаточно видалив повільний код.

Так само краще, якщо я використовував бінарні біти та вищі бази.

C версія

__uint128_t hash(unsigned char* s){
    __uint128_t a=0,b=0;
    __uint128_t ar=0;
    __uint128_t v[600];
    int l=0,j=strlen(s);
    memset(v,0,sizeof v);
    for(int i=0;i<j;i++){
        if(i%600)
            ar*=19;
        else{
            a=(a+ar)*13;
            ar=0;
        }
        if(i%600>l)
            l=i%600;
        v[i%600]=v[i%600]*19+s[j-i-1];
        ar+=s[j-i-1];
    }
    for(int i=0;i<=l;i++)
        b=b*13+v[i];
    a+=ar;
    return (((a>>48)*11+(b>>48))<<96)
        +((a&0xffffffffffffull)<<48)
        +(b&0xffffffffffffull);
}

Не могли б ви додати опис? Не всі знають CJam.
orlp

@orlp Відредаговано ...
jimmy23013

На моєму комп'ютері це займає 0,4 с, тому це добре в межах дозволеного діапазону.
Денніс

Що таке A, B, C тощо? Якісь матриці? Які розміри? Чи легко його реалізувати в C?
Ві.

1
Тріснув , я вважаю.
Sp3000

5

C ++, 182 символи (+ близько 51 символу котла)

h=0xC0CC3051F486B191;j=0x9A318B5A176B8125;char q=0;for(int i=0;i<l;++i){char w=buf[i];h+=((w<<27)*257);j^=(h+0x5233);h+=0xAA02129953CC12C3*(j>>32);j^=(w+0x134)*(q-0x16C552F34);q=w;}

Котельня:

void hash(const unsigned char* buf, size_t len, unsigned long long *hash1, unsigned long long *hash2)
{
    unsigned long long &h=*hash1;
    unsigned long long &j=*hash2;
    size_t l = len;
    const unsigned char* b = buf;

    // code here
}

Пробіжна програма з функцією гольфу

#include <stdio.h>

// The next line is 227 characters long
int hash(char*b,int l,long long&h,long long&j){h=0xC0CC3051F486B191;j=0x9A318B5A176B8125;char q=0;for(int i=0;i<l;++i){char w=b[i];h+=((w<<27)*257);j^=(h+0x5233);h+=0xAA02129953CC12C3*(j>>32);j^=(w+0x134)*(q-0x16C552F34);q=w;}}

int main() {
    char buf[1024];
    int l  = fread(buf, 1, 1024, stdin);
    long long q, w;
    hash(buf, l, q, w);
    printf("%016llX%016llX\n", q, w);
}

2
Я думаю, що декларація функції тощо зараховується до кількості символів.
Ypnypn

@Ypnypn, підраховує символи в декларації про функцію гольфу.
Ві.

Що таке вихідний хеш? Я припускаю, що це ((h << 64) | j).
tucuxi

Так. Або просто пара 64-бітних чисел. Я дізнався про це __uint128_tлише після цього.
Ві.

1
@Dennis, Готово.󠀠
Vi.

4

Pyth, 8 Cracked

sv_`.lhQ

Спробуйте в Інтернеті

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

Переклад python виглядатиме так:

import math
n = eval(input()) + 1
rev = str(math.log(n))[::-1]
print(int(eval(rev)))


4

Python 3, 216 байт [ тріщини ]

def f(m):
 h=1;p=[2]+[n for n in range(2,102)if 2**n%n==2];l=len(bin(m))-2;*b,=map(int,bin((l<<(l+25)//26*26)+m)[2:])
 while b:
  h*=h
  for P in p:
   if b:h=h*P**b.pop()%0xb6ee45a9012d1718f626305a971e6a21
 return h

Через несумісність із специфікацією я можу подумати про принаймні одну незначну вразливість, але крім цього, я думаю, що це принаймні жорстокі докази. Я, серед іншого, перевірив перші 10 мільйонів хешей.

Що стосується гольфу, це було б коротше в Python 2, але я пожертвував деякими байтами для ефективності (оскільки, мабуть, все одно не виграю).

Редагувати: Це була моя спроба реалізувати Very Smooth Hash , але, на жаль, 128-бітових було занадто мало.

Обгортка

print(f(int(input())))

Приклади

>>> f(0)
2
>>> f(123456789)
228513724611896947508835241717884330242
>>> f(2**(2**19)-1)
186113086034861070379984115740337348649
>>> f(2**(2**19))
1336078

Пояснення коду

def f(m):
 h=1                                             # Start hash at 1
 p=[2]+[n for n in range(2,102)if 2**n%n==2]     # p = primes from 2 to 101
 l=len(bin(m))-2                                 # l = bit-length of m (input)
 *b,=map(int,bin((l<<(l+25)//26*26)+m)[2:])      # Convert bits to list, padding to
                                                 # a multiple of 26 then adding the
                                                 # bit-length at the front

 while b:                                        # For each round
  h*=h                                           # Square the hash
  for P in p:                                    # For each prime in 2 ... 101
   if b:h=(h*P**b.pop()                          # Multiply by prime^bit, popping
                                                 # the bit from the back of the list
           %0xb6ee45a9012d1718f626305a971e6a21)  # Take mod large number

 return h                                        # Return hash

Приклад прокладки для f(6):

[1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0]

(len 3)(------------------ 23 zeroes for padding -------------------------)(input 6)
       (---------------------------- length 26 total ------------------------------)


4

C, 87 байт [ тріскається ]

Це повна програма; не потрібна обгортка. Приймає двійковий вхід через stdin та видає шістнадцятковий хеш для stdout.

c;p;q;main(){while((c=getchar())+1)p=p*'foo+'+q+c,q=q*'bar/'+p;printf("%08x%08x",p,q);}

Це обчислює лише 64-бітний хеш, тому я тут трохи граю.

У випадку, коли комусь цікаво, ці дві константи 'foo+'і 'bar/'прості числа 1718578987 та 1650553391.


Приклади:

Ігнорує провідні нулі:

echo -ne '\x00\x00\x00\x00' |./hash
0000000000000000

Однобайтові входи:

echo -ne '\x01' |./hash
0000000100000001
echo -ne '\xff' |./hash
000000ff000000ff

Багатобайтові входи:

echo -ne '\x01\x01' |./hash
666f6f2dc8d0e15c
echo -ne 'Hello, World' |./hash
04f1a7412b17b86c

Як би він себе з «aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa» і «aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa»?
Ісмаїл Мігель

1
foo|(d5c9bef71d4f5d1b) та foo\(d5c9bef71d4f5d1b) створюють ДУЖЕ подібні хеші.
Ісмаїл Мігель

1
Зламали !!! \x00і \x00\x00!
Ісмаїл Мігель

1
Виходячи з коментарів чату, я вважаю, це все ще не зламано? Просто подвійну перевірку, тому що оновлений коментар може бентежити тих, хто скупиться за нерозкритим хешем.
Sp3000


3

J - 39 байт - тріщини

Функція приймає рядок як вхідний і повертає ціле число <2 128 . Я припускаю, що ми маємо назвати нашу функцію дійсною, тому відкиньте ще 3 символи від рахунку, якщо ми можемо подати анонімні функції.

H=:_8(".p:@+5,9:)a\(a=.(2^128x)&|@^/@)]

Для тих із вас, хто не читає ієрогліфіки, ось пробіг того, що я роблю.

  • a=.(2^128x)&|@^/@ This is a subroutine* which takes an array of numbers, and then treats it as a power tower, where exponentiation is taken mod 2128. By "power tower", I mean if you gave it the input 3 4 5 6, it would calculate 3 ^ (4 ^ (5 ^ 6)).
  • (".p:@+5,9:)a This function takes a string, converts it to the number N, and then calculates the (n+5)-th and (n+9)-th prime numbers, and then throws the a from before on it. That is, we find p(n+5) ^ p(n+9) mod 2128 where p(k) is the k-th prime.
  • H=:_8...\(a...)] Perform the above function on 8-character subblocks of the input, and then a all the results together and call the resulting hash function H. I use 8 characters because J's "k-th prime" function fails when p(k) > 231, i.e. k=105097564 is the largest safe k.

Have some sample outputs. You can try this yourself online at tryj.tk, but I really recommend doing this at home by downloading the interpreter from Jsoftware.

   H=:_8(".p:@+5,9:)a\(a=.(2^128x)&|@^/@)]
   H '88'
278718804776827770823441490977679256075
   H '0'
201538126434611150798503956371773
   H '1'
139288917338851014461418017489467720433
   H '2'
286827977638262502014244740270529967555
   H '3'
295470173585320512295453937212042446551
   30$'0123456789'  NB. a 30 character string
012345678901234567890123456789
   H 30$'0123456789'
75387099856019963684383893584499026337
   H 80$'0123456789'
268423413606061336240992836334135810465

* Technically, it's not a function in and of itself, it attaches to other functions and acts on their output. But this is a semantic issue of J, not a conceptual difference: the program flow is as I described it above.



2

Python 3, 118 bytes [cracked]

def H(I):
    o=0;n=3;M=1<<128
    for c in I:i=ord(c);o=(o<<i^o^i^n^0x9bb90058bcf52d3276a7bf07bcb279b7)%M;n=n*n%M
    return o

Indentation is a single tab. Simple hash, haven't really tested it thoroughly yet.

Call as follows:

print(H("123456789"))

result: 73117705077050518159191803746489514685


How should the input integer be converted to a string to use in your algorithm?
feersum

@feersum base-10 string is what I tested. It doesn't use anything but ord(c) though, so really, any string will do :) (except things like nul chars, I think those make hash collisions really easy. So stick with a 0-9 string.)
tomsmeding

1
Broke it: codegolf.stackexchange.com/a/51160/41288. Started out by observing that strings like "10000" and "20000" produce very close hashes. Started to play around with more and more zeroes, and after 128 or so, any digit + k*4 zeroes repeats returns the same hash regardless of k.
tucuxi

@tucuxi Already thought it shouldn't bee too hard; glad that is wasn't trivial but that someone broke it anyway. Good work.
tomsmeding

2

C++, 239 bytes

My very first code golf! [Please be gentle]

#define r(a,b) ((a<<b)|(a>>(64-b)))
typedef uint64_t I;I f(I*q, I n, I&h){h=0;for(I i=n;--i;)h=r(h^(r(q[i]*0x87c37b91114253d5,31)*0x4cf5ad432745937f),31)*5+0x52dce729;h^=(h>>33)*0xff51afd7ed558ccd;h^=(h>>33)*0xc4ceb9fe1a85ec53;h^=(h>>33);}

Ungolfed version:

I f(I* q, I n, I& h) // input, length and output
{
    h = 0; // initialize hashes
    for (I i=n;--i;)
    {
        q[i] *= 0x87c37b91114253d5;
        q[i]  = rotl(q[i], 31);
        q[i] *= 0x4cf5ad432745937f;

        h ^= q[i]; // merge the block with hash

        h *= rotl(h, 31);
        h = h * 5 + 0x52dce729;
    }
    h ^= h>>33;
    h *= 0xff51afd7ed558ccd;
    h ^= h>>33;
    h *= 0xc4ceb9fe1a85ec53; // avalanche!
    h ^= h>>33;
}

Not the best hash, and definitely not the shortest code in existence. Accepting golfing tips and hoping to improve!

Wrapper

Probably not the best in the world, but a wrapper nonetheless

I input[500];

int main()
{
    string s;
    getline(cin, s);
    memcpy(input, s.c_str(), s.length());
    I output;
    f(input, 500, output);
    cout << hex << output << endl;
}

2
Looks solid, but with 64 bits, it may be subject to brute-forcing. There is about a 50% chance to find a collision in ~sqrt(n) tests (from among n total outputs); 2^32 tries is not that much for a modern pc.
tucuxi

Wrapper lacks header inclusions and in general leads to many equal hashes.
Vi.

Provide some hash samples. For me both "3" and "33" lead to 481c27f26cba06cf (using this wrapper).
Vi.

Cracked: codegolf.stackexchange.com/a/51215/41288 . I suspect right before @Vi. found out why so many hashes were equal.
tucuxi

1
Proper collision (without bug using): printf '33333333\x40\xF3\x32\xD6\x56\x91\xCA\x66' | ./hash7_ -> a4baea17243177fd; printf '33333333\x77\x39\xF3\x82\x93\xDE\xA7\x2F' | ./hash7_ -> a4baea17243177fd. The bruteforcer finds collisions here much faster compared to in other 64-bit hash here.
Vi.

2

Java, 299 291 282 bytes, cracked.

import java.math.*;class H{public static void main(String[]a){BigInteger i=new java.util.Scanner(System.in).nextBigInteger();System.out.print(BigInteger.valueOf(i.bitCount()*i.bitLength()+1).add(i.mod(BigInteger.valueOf(Long.MAX_VALUE))).modPow(i,BigInteger.valueOf(2).pow(128)));}}

Does some operations on BigIntegers, then takes the result modulo 2128.


How do I run this? Ideone refuses to compile it.
Martin Ender

1
You can run it on Ideone by renaming the class to "Main" or removing the first "public" keyword (but NOT the second one). Either one will work.
SuperJedi224


1
@SuperJedi224 Why not remove the first public yourself, saving 7 chars?
user253751

@immibis Because then I don't think it would work right on Eclipse. I'll try it though. EDIT: I guess it does. That's a surprise.
SuperJedi224

2

C, 128 bytes [cracked]

p;q;r;s;main(c){while((c=getchar())+1)p=p*'foo+'+s^c,q=q*'bar/'+p,r=r*'qux3'^q,s=s*'zipO'+p;printf("%08x%08x%08x%08x",p,q,r,s);}

This is more or less the same algorithm as my last effort (cracked by Vi.), but now has enough hamster wheels to generate proper 128-bit hashes.

The four prime constants in the code are as follows:

'foo+' = 1718578987
'bar/' = 1650553391
'qux3' = 1903523891
'zipO' = 2053730383

As before, this is a complete program with no need for a wrapper. The integer I is input via stdin as raw binary data (big-endian), and the hash O is printed in hex to stdout. Leading zeroes in I are ignored.

Examples:

echo -ne '\x00' |./hash
00000000000000000000000000000000
echo -ne '\x00\x00' |./hash
00000000000000000000000000000000
echo -ne '\x01' |./hash
00000001000000010000000100000001
echo -ne 'A' |./hash
00000041000000410000004100000041
echo -ne '\x01\x01' |./hash
666f6f2dc8d0e15cb9a5996fe0d8df7c
echo -ne 'Hello, World' |./hash
da0ba2857116440a9bee5bb70d58cd6a


Didn't your example show a collision right there (the first two)?
mbomb007

@mbomb007 No. The input is a number between 0 and 2^(2^30). 0x00 and 0x0000 are both equal to zero, so they produce the same output.
squeamish ossifrage

2

C, 122 bytes [cracked]

long long x,y,p;main(c){for(c=9;c|p%97;c=getchar()+1)for(++p;c--;)x=x*'[3QQ'+p,y^=x^=y^=c*x;printf("%016llx%016llx",x,y);}

Nested loops, half-assed LCGs, and variable swapping. What's not to love?

Here's a ungolf'd version to play around with:

long long x,y,p;

int main(int c){
    // Start with a small number of iterations to
    //   get the state hashes good and mixed because initializing takes space
    // Then, until we reach the end of input (EOF+1 == 0)
    //   and a position that's a multiple of 97
    for (c=9;c|p%97;c=getchar()+1) {

        // For each input c(haracter) ASCII value, iterate down to zero
        for (++p;c--;) {

            // x will act like a LCG with a prime multiple
            //   partially affected by the current input position
            // The string '[3QQ' is the prime number 0x5B335151
            x=x*'[3QQ'+p;

            // Mix the result of x with the decrementing character
            y^=c*x;

            // Swap the x and y buffers
            y^=x^=y;
        }
    }

    // Full 128-bit output
    printf("%016llx%016llx",x,y);
    return 0;
}

This is a fully self-contains program that reads from STDIN and prints to STDOUT.

Example:

> echo -n "Hello world" | ./golfhash
b3faef341f70c5ad6eed4c33e1b55ca7

> echo -n "" | ./golfhash
69c761806803f70154a7f816eb3835fb

> echo -n "a" | ./golfhash
5f0e7e5303cfcc5ecb644cddc90547ed

> echo -n "c" | ./golfhash
e64e173ed4415f7dae81aae0137c47e5

In some simple benchmarks, it hashes around 3MB/s of text data. The hash speed depends on the input data itself, so that should probably be taken into consideration.



1

PHP 4.1, 66 bytes [cracked]

I'm just warming up.

I hope you find this insteresting.

<?for($l=strlen($b.=$a*1);$i<40;$o.=+$b[+$i]^"$a"/$a,$i++);echo$o;

I've tried it numbers as large as 999999999999999999999999999.
The output seemed to be within the 2128 range.


PHP 4.1 is required because of the register_globals directive.

It works by automatically creating local variables from the session, POST, GET, REQUEST and cookies.

It uses the key a. (E.G.: access over http://localhost/file.php?a=<number>).

If you want to test it with PHP 4.2 and newer, try this:

<?for($l=strlen($b.=$a=$_REQUEST['a']*1);$i<40;$o.=+$b[+$i]^"$a"/$a,$i++);echo$o;

This version only works with POST and GET.


Example output:

0 -> 0000000000000000000000000000000000000000
9 -> 8111111111111111111111111111111111111111
9999 -> 8888111111111111111111111111111111111111
1234567890 -> 0325476981111111111111111111111111111111
99999999999999999999999999999999999999999999999999999999999999999999999999999999 -> 0111191111111111111111111111111111111111

(I assure you that there are numbers that produce the same hash).



1

C, 134 bytes, Cracked

This is complete C program.

long long i=0,a=0,e=1,v,r;main(){for(;i++<323228500;r=(e?(scanf("%c",&v),e=v>'/'&&v<':',v):(a=(a+1)*7)*(7+r)));printf("0x%llx\n", r);}

What it does: The idea is to take input as byte array and append pseudo random (but deterministic) bytes at the end to make the length equal to about 2230 (a bit more). The implementation reads input byte by byte and starts using pseudo random data when it finds the first character that isn't a digit.

As builtin PRNG isn't allowed I implemented it myself.

There is undefined/implementation defined behavior that makes the code shorter (the final value should be unsigned, and I should use different types for different values). And I couldn't use 128 bit values in C. Less obfuscated version:

long long i = 0, prand = 0, notEndOfInput = 1, in, hash;

main() {
    for (; i++ < 323228500;) {
        if (notEndOfInput) {
            scanf("%c", &in);
            notEndOfInput = in >= '0' && in <= '9';
            hash = in;
        } else {
            prand = (prand + 1)*7;
            hash = prand*(7 + hash);
        }
    }
    printf("0x%llx\n", hash);
}


1

Python 2.X - 139 bytes [[Cracked]]

This is quite similar to all the other (LOOP,XOR,SHIFT,ADD) hashes out here. Come get your points robbers ;) I'll make a harder one after this one is solved.

M=2**128
def H(I):
 A=[1337,8917,14491,71917];O=M-I%M
 for z in range(73):
  O^=A[z%4]**(9+I%9);O>>=3;O+=9+I**(A[z%4]%A[O%4]);O%=M
 return O

Wrapper (expects one argument in base-16 also known as hexadecimal):

import sys
if __name__ == '__main__':
 print hex(H(long(sys.argv[1], 16)))[2:][:-1].upper()


1
Also, I am not sure that this entry meets the OP's spec, since on my machine the function takes multiple seconds on large inputs. For example, H(2**(2**10)) took around 8 or 9 seconds, while H(2**(2**12)) took around 29 seconds and H(2**(2**14)) took over two minutes.
mathmandan

You are absolutely right, I obviously should have tested the timing for larger inputs. Also, I appear to have forgot to run my own test after that shift was added. The original version was without shift (before posting) and it was passing my "no collisions in the first 100000 integers" test :/
Puzzled

1

Python 2.7 - 161 bytes [[Cracked]]

Well since I managed to change my first hash function into an useless version before posting it, I think I will post another version of a similar structure. This time I tested it against trivial collisions and I tested most of the possible input magnitudes for speed.

A=2**128;B=[3,5,7,11,13,17,19]
def H(i):
 o=i/A
 for r in range(9+B[i%7]):
  v=B[i%7];i=(i+o)/2;o=o>>v|o<<128-v;o+=(9+o%6)**B[r%6];o^=i%(B[r%6]*v);o%=A
 return o

Wrapper (not counted in the bytecount)

import sys
if __name__ == '__main__':
 arg = long(sys.argv[1].strip(), 16)
 print hex(H(arg))[2:][:-1].upper()

Run example (input is always a hexadecimal number):

$ python crypt2.py 1
3984F42BC8371703DB8614A78581A167
$ python crypt2.py 10
589F1156882C1EA197597C9BF95B9D78
$ python crypt2.py 100
335920C70837FAF2905657F85CBC6FEA
$ python crypt2.py 1000
B2686CA7CAD9FC323ABF9BD695E8B013
$ python crypt2.py 1000AAAA
8B8959B3DB0906CE440CD44CC62B52DB


Well done jimmy :)
Puzzled

1

Ruby, 90 Bytes

def H(s);i=823542;s.each_byte{|x|i=(i*(x+1)+s.length).to_s.reverse.to_i%(2**128)};i;end

A highly random hash algorithm I made up without looking at any real hashes...no idea if it is good. it takes a string as input.

Wrapper:

def buildString(i)
  if(i>255)
    buildString(i/256)+(i%256).chr
  else
    i.chr
  end
end 
puts H buildString gets

Could you please provide the wrapper the question requires?
Dennis

What's the input format? I tried with a number but it says comparison of String with 255 failed (ArgumentError).
jimmy23013

H takes a string, Build string takes the number required by the OP and transforms it to a string.
MegaTom

I think you need a gets.to_i in the wrapper.
jimmy23013



0

PHP, 79 Bytes (cracked. With a comment):

echo (('.'.str_replace('.',M_E*$i,$i/pi()))*substr(pi(),2,$i%20))+deg2rad($i);

This does alot of scary things via type-conversions in php, which makes it hard to predict ;) (or at least I hope so). It's not the shortest or most unreadable answer, however.

To run it you can use PHP4 and register globals (with ?i=123) or use the commandline:

php -r "$i = 123.45; echo (('.'.str_replace('.',M_E*$i,$i/pi()))*substr(pi(),2,$i%20))+deg2rad($i);"

5
The hash's output value looks floating-point. And It's the same for 3000000000000000000000000000000000000000000001 and 3000000000000000000000000000000000000000000000.
Vi.

0

C# - 393 bytes cracked

using System;class P{static void Main(string[]a){int l=a[0].Length;l=l%8==0?l/8:l/8+1;var b=new byte[l][];for(int i=0;i<l;i++){b[i]=new byte[8];};int j=l-1,k=7;for(int i=0;i<a[0].Length;i++){b[j][k]=Convert.ToByte(""+a[0][i],16);k--;if((i+1)%8==0){j--;k=7;}}var c=0xcbf29ce484222325;for(int i=0;i<l;i++){for(int o=0;o<8;o++){c^=b[i][o];c*=0x100000001b3;}}Console.WriteLine(c.ToString("X"));}}

Ungolfed:

using System;
class P
{
    static void Main(string[]a)
    {
      int l = a[0].Length;
      l = l % 8 == 0 ? l / 8 : l / 8 + 1;
      var b = new byte[l][];
      for (int i = 0; i < l; i++) { b[i] = new byte[8]; };
      int j = l-1, k = 7;
      for (int i = 0; i < a[0].Length; i++)
      {
        b[j][k] = Convert.ToByte(""+a[0][i], 16);
        k--;
        if((i+1) % 8 == 0)
        {
          j--;
          k = 7;
        }
      }
      var c = 0xcbf29ce484222325;
      for (int i = 0; i < l; i++)
      {
        for (int o = 0; o < 8; o++)
        {
          c ^= b[i][o];
          c *= 0x100000001b3;
        }
      }
      Console.WriteLine(c.ToString("X"));
    }
}

I have never touched cryptography or hashing in my life, so be gentle :)

It's a simple implementation of an FNV-1a hash with some array pivoting on the input. I am sure there is a better way of doing this but this is the best I could do.

It might use a bit of memory on long inputs.


Cracked: codegolf.stackexchange.com/a/51277/101 On top of having faulty padding, this is not a cryptographic hash, there is so many ways to break it.
aaaaaaaaaaaa

0

Python 2, 115 bytes [Cracked already!]

OK, here's my last effort. Only 115 bytes because the final newline isn't required.

h,m,s=1,0,raw_input()
for c in[9+int(s[x:x+197])for x in range(0,len(s),197)]:h+=pow(c,257,99**99+52)
print h%4**64

This is a complete program that inputs a decimal integer on stdin and prints a decimal hash value on stdout. Extra leading zeroes will result in different hash values, so I'll just assume that the input doesn't have any.

This works by stuffing 197-digit chunks of the input number through a modular exponentiation. Unlike some languages, the int() function always defaults to base 10, so int('077') is 77, not 63.

Sample outputs:

$ python hash.py <<<"0"
340076608891873865874583117084537586383

$ python hash.py <<<"1"
113151740989667135385395820806955292270

$ python hash.py <<<"2"
306634563913148482696255393435459032089

$ python hash.py <<<"42"
321865481646913829448911631298776772679

$ time python hash.py <<<`python <<<"print 2**(2**19)"`
233526113491758434358093601138224122227

real    0m0.890s   <-- (Close, but fast enough)
user    0m0.860s
sys     0m0.027s

1
It didn't use the order of blocks... Cracked.
jimmy23013

Ugh. I give in :-(
squeamish ossifrage
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.