Hash golf crittografico


34

Questo concorso è finito.

A causa della natura delle sfide dei , la sfida dei poliziotti diventa molto più semplice quando l'interesse per la sfida dei ladri associati è diminuito. Pertanto, mentre puoi ancora pubblicare funzioni hash, la tua risposta non verrà accettata o farà parte della classifica.

Questa sfida è una ricerca per il più breve implementazione di una funzione di hash che è resistente collisione , cioè, dovrebbe essere impossibile trovare due messaggi diversi con lo stesso hash.

Come poliziotto, cerchi di inventare e implementare una funzione hash trovando il miglior compromesso tra dimensione del codice e resistenza alle collisioni. Usa troppi byte e un altro poliziotto ti supererà!

Come ladro, cerchi di sventare i tentativi degli sbirri violando le loro funzioni, dimostrando che non sono adatti. Questo li costringerà a usare più byte per rafforzare i loro algoritmi!

Sfida poliziotti

Compito

Implementa una funzione di hash crittografica H: I -> O di tua scelta, dove I è l'insieme di tutti gli interi non negativi inferiori a 2 2 30 e O è l'insieme di tutti gli interi non negativi inferiori a 2 128 .

È possibile implementare H come una funzione effettiva che accetta e restituisce un singolo intero, una rappresentazione in stringa di un numero intero o un array di numeri interi o un programma completo che legge da STDIN e stampa su STDOUT in base 10 o 16.

punteggio

  • H che deve resistere alla sfida dei ladri definita di seguito.

    Se un ladro sconfigge il tuo invio nelle prime 168 ore dopo la sua pubblicazione, viene considerato incrinato .

  • L'implementazione di H dovrebbe essere il più breve possibile. La presentazione non crackata più breve sarà il vincitore della sfida della polizia.

Regole aggiuntive

  • Se si implementa H come funzione, fornire un wrapper per eseguire la funzione all'interno di un programma che si comporta come spiegato sopra.

  • Fornisci almeno tre vettori di prova per il tuo programma o wrapper (esempi di input e relativi output).

  • H può essere il tuo nuovo design (preferito) o un noto algoritmo, purché tu lo implementi da solo. È vietato utilizzare qualsiasi tipo di funzione hash integrata, funzione di compressione, cifratura, PRNG, ecc.

    Qualsiasi built-in comunemente usato per implementare le funzioni di hashing (ad es. Conversione di base) è un gioco equo.

  • L'output del tuo programma o funzione deve essere deterministico.

  • Dovrebbe esserci un compilatore / interprete gratuito (come nella birra) che può essere eseguito su una piattaforma x86 o x64 o da un browser web.

  • Il vostro programma o di una funzione dovrebbe essere ragionevolmente efficiente e deve hash qualsiasi messaggio nel I di sotto del 2 2 19 in meno di un secondo.

    Per i casi limite, il tempo (a parete) impiegato sulla mia macchina (Intel Core i7-3770, 16 GiB di RAM) sarà decisivo.

  • Data la natura di questa sfida, è vietato modificare il codice della risposta in qualsiasi modo, che cambi l'output o meno.

    Se il tuo invio è stato violato (o anche se non lo è), puoi pubblicare una risposta aggiuntiva.

    Se la risposta non è valida (ad es. Non è conforme alla specifica I / O), si prega di eliminarla.

Esempio

Python 2.7, 22 byte

def H(M):
 return M%17

involucro

print H(int(input()))

Sfida i ladri

Compito

Crack uno qualsiasi dei poliziotti osservazioni inviando quanto segue nella briganti filo : due messaggi M e N in mi tale che H (M) = H (N) e M ≠ N .

punteggio

  • Infrangere ogni invio di poliziotti ti fa guadagnare un punto. Vince il ladro con il maggior numero di punti.

    In caso di pareggio, vince il ladro che ha spezzato la sottomissione più lunga.

Regole aggiuntive

  • Ogni invio di poliziotti può essere decifrato solo una volta.

  • Se l'invio di un poliziotto si basa su comportamenti definiti o non definiti dall'implementazione, devi solo trovare un crack che funzioni (in modo verificabile) sul tuo computer.

  • Ogni crack appartiene a una risposta separata nel thread dei ladri.

  • Pubblicare un tentativo di cracking non valido ti vieta di crackare quel particolare invio per 30 minuti.

  • Non puoi infrangere la tua stessa richiesta.

Esempio

Python 2.7, 22 byte dall'utente8675309

1

e

18

Classifica

Invio sicuro

  1. CJam, 21 byte di eBusiness
  2. C ++, 148 byte di tucuxi
  3. C ++, 233 (?) Byte di Vi.

Contributi non crackati

Puoi utilizzare questo frammento di stack per ottenere un elenco di risposte non ancora crackate.

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>


Se una funzione hash restituisce erroneamente numeri maggiori di 2 ^ 128-1, ciò invalida l'invio o prenderemo semplicemente il risultato modulo 2 ^ 128?
Martin Ender,

@ MartinBüttner: Sì, dovresti prendere il risultato modulo 2 ^ 128.
Dennis,

1
@Scimonster Non soddisfa i requisiti (fino a 2 ^ 30 bit di input, 128 bit di output)
CodesInChaos

1
Poliziotti e ladri di solito non fanno il contrario?
haneefmubarak,

2
Forse potremmo avere una regola in base alla quale gli invii devono includere esempi di hash, è abbastanza fastidioso dover eseguire il linguaggio di programmazione scelto dai presentatori per avere un risultato per confrontare quelli con cui si infrange l'implementazione.
aaaaaaaaaaaa

Risposte:


6

CJam, 21 byte

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

Accetta una stringa di byte come input.

In pseudocodice:

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

Hash di esempio:

"" (stringa vuota) -> 1
"Test" -> 2607833638733409808360080023081587841
"test" -> 363640467424586895504738713637444713

Potrebbe essere un po 'semplice, la gamma di output è solo un po' più di 122 bit, il rinforzo della tripla iterazione è già un po 'rotto poiché fa esattamente la stessa cosa ogni volta, quindi inserisci l'hash a 1 nel primo l'iterazione sarà una pausa completa. Ma è breve e non è divertente essere troppo sicuri.


Esiste una versione C di accompagnamento come nell'altro post di CJam?
Vi.

@Vi. No, non ancora almeno. Non mi sono mai dilettato con bigint in C, esiste una libreria standard per quello?
aaaaaaaaaaaa,

GMP ?
Vi.


1
@ Agawa001 Stai mescolando la tua terminologia. È un algoritmo hash con funzione spugna a triplo passaggio. Una cifra di Cesare è un algoritmo di crittografia specifico senza stato interno.
aaaaaaaaaaaa,

7

Pitone, 109 bytes [ cracking , e di nuovo ]

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

Ho provato ad implementare la funzione one-at-time di Jenkins così com'è, con l'unica differenza che sono il seme e il numero di bit.

Curiosità: apparentemente Perl ad un certo punto ha usato l'hash Jenkins .

involucro

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

Esempi

>>> 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 byte

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 è un'estensione GCC e funziona come previsto. L'hash si basa sull'iterazione dell'hash FNV (ho preso in prestito il loro numero primo, sebbene asiano le prime cifre di Pi in esadecimale) con una rotazione simile a sha1 all'inizio di ogni iterazione. Compilare -O3, l'hashing di un file da 10 MB richiede meno di 2 secondi, quindi c'è ancora margine per aumentare le iterazioni nel ciclo interno, ma oggi mi sento generoso.

Disgraziato (nomi delle variabili modificati, commenti aggiunti, spazi bianchi e un paio di parentesi graffe) per il tuo piacere di cracking:

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
}

I suggerimenti sul golf sono i benvenuti (anche se non riesco a migliorare il codice basato su di essi).

modifica: correzioni di errori di battitura nel codice disattivato (la versione golfata rimane invariata).


osembra non essere inizializzato. Dove outputviene dichiarato? O forse lo oè output?
Vi.

Lo stesso per n. Hai effettivamente controllato il codice "sgraziato" per l'esecuzione?
Vi.

Iniziato il bruteforcer ...
Vi.

Anche la versione a 3 round non è facile.
Vi.

@Vi. Risolto il problema con la versione disattivata - scusate se non la controllavo meglio. Sono orgoglioso di quel ciclo interiore; U i=81;i-=3avrebbe potuto essere ancora più vile, senza costi di runtime significativi.
Tucuxi,

5

CJam, 44 byte [ crackato ]

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

L'ingresso è nella base 10.

CJam è lento. Spero che funzioni in 1 secondo in alcuni computer ...

spiegazioni

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.

Bene, le cose bidimensionali sembravano essere un punto debole ... All'inizio si intendeva rendere più veloci alcuni calcoli lenti. Ma non può essere eseguito in un secondo, non importa quello che faccio, quindi alla fine ho rimosso il codice lento.

Dovrebbe essere anche meglio se ho usato bit binari e basi più alte.

Versione 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);
}

Potresti per favore aggiungere una descrizione? Non tutti conoscono CJam.
orlp

@orlp Edited ...
jimmy23013

Questo richiede 0,4 s sul mio computer, quindi rientra nell'intervallo consentito.
Dennis

Che cos'è A, B, C e così via? Alcune matrici? Quali dimensioni? Può essere facilmente implementato in C?
Vi.

1
Incrinato , credo.
Sp3000,

5

C ++, 182 caratteri (+ circa 51 caratteri della piastra di caldaia)

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;}

boilerplate:

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
}

Programma eseguibile con una funzione golf

#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
Penso che la dichiarazione di funzione ecc. Conti ai fini del conteggio dei caratteri.
Ypnypn,

@Ypnypn, ha contato i caratteri in una dichiarazione di funzione ridotta.
Vi.

Qual è l'hash di output? Suppongo che sia ((h << 64) | j).
Tucuxi,

Sì. O solo una coppia di numeri a 64 bit. Ho scoperto __uint128_tsolo dopo aver implementato questo.
Vi.

1
@Dennis, Done.󠀠
Vi.

4

Pyth, 8 Incrinato

sv_`.lhQ

Provalo online

Un po 'una risposta sciocca, ti spiego come funziona perché la maggior parte delle persone non sa leggere Pyth. Questo prende il log naturale di uno più l'input, quindi lo converte in una stringa. Quella stringa viene invertita, quindi valutata e quindi convertita in un numero intero.

Una traduzione di Python sarebbe simile a:

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


4

Python 3, 216 byte [ crackato ]

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

A causa di un'incompatibilità con le specifiche, posso pensare ad almeno una leggera vulnerabilità, ma a parte questo penso che sia almeno una prova della forza bruta. Ho controllato i primi 10 milioni di hash, tra le altre cose.

In termini di golf questo sarebbe più breve in Python 2, ma ho sacrificato alcuni byte per l'efficienza (dal momento che probabilmente non vincerà comunque).

Modifica: questo è stato il mio tentativo di implementare Very Smooth Hash , ma sfortunatamente 128 bit era troppo piccolo.

involucro

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

Esempi

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

Spiegazione del codice

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

Un esempio dell'imbottitura per 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 byte [ incrinato ]

Questo è il programma completo; nessun involucro richiesto. Accetta l'input binario tramite stdin e genera un hash esadecimale su stdout.

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

Questo calcola solo un hash a 64 bit, quindi sto facendo un po 'di scommessa qui.

Nel caso qualcuno si stia chiedendo, le due costanti 'foo+'e 'bar/'sono i numeri primi 1718578987 e 1650553391.


Esempi:

Ignora gli zeri iniziali:

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

Ingressi a byte singolo:

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

Ingressi multi-byte:

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

Come si comporterebbe con 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' e 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'?
Ismael Miguel,

1
foo|(d5c9bef71d4f5d1b) e foo\(d5c9bef71d4f5d1b) producono hash MOLTO simili.
Ismael Miguel,

1
Lo ruppe!!! \x00e \x00\x00!
Ismael Miguel,

1
Sulla base dei commenti della chat, credo che questo non sia ancora stato risolto? Doppio controllo, perché il commento votato potrebbe essere fonte di confusione per coloro che si stanno scremando per gli hash non crackati.
Sp3000,


3

J - 39 byte - incrinato

Funzione che accetta una stringa come input e restituisce un numero intero <2 128 . Presumo che dobbiamo assegnare un nome alla nostra funzione per essere validi, quindi eliminare altri 3 caratteri dal conteggio se è possibile inviare funzioni anonime.

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

Per quelli di voi che non leggono i geroglifici, ecco un riassunto di quello che sto facendo.

  • a=.(2^128x)&|@^/@Questa è una subroutine * che accetta una matrice di numeri, e quindi la tratta come una torre di potere, dove viene esponenziata mod 2 128 . Per "power tower", intendo che se gli hai dato l'input 3 4 5 6, calcolerebbe 3 ^ (4 ^ (5 ^ 6)).
  • (".p:@+5,9:)aQuesta funzione accetta una stringa, la converte nel numero N , quindi calcola i numeri primi ( n +5) e ( n +9) e quindi li lancia ada prima. Cioè, troviamo p(n+5) ^ p(n+9)mod 2 128 dove p(k)è il k-th primo.
  • H=:_8...\(a...)]Eseguire la funzione sopra su subblock di 8 caratteri dell'input, quindi atutti i risultati insieme e chiamare la funzione hash risultante H. Uso 8 caratteri perché la funzione " k-th prime" di J fallisce quando p(k)> 2 31 , ovvero k=105097564è la cassaforte più grande k.

Hanno alcuni output di esempio. Puoi provarlo tu stesso online su tryj.tk , ma consiglio vivamente di farlo a casa scaricando l'interprete da 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

* Tecnicamente, non è una funzione in sé e per sé, si attacca ad altre funzioni e agisce sul loro output. Ma questo è un problema semantico di J, non una differenza concettuale: il flusso del programma è come l'ho descritto sopra.



2

Python 3, 118 byte [ crackato ]

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

Il rientro è una singola scheda. Hash semplice, non l'ho ancora testato a fondo.

Chiama come segue:

print(H("123456789"))

risultato: 73117705077050518159191803746489514685


Come deve essere convertito il numero intero di input in una stringa da utilizzare nel tuo algoritmo?
feersum

La stringa @feersum base-10 è ciò che ho testato. Non usa nulla, ma ord(c)comunque, quindi, qualsiasi stringa farà :) (tranne cose come nul chars, penso che quelle rendono le collisioni di hash davvero facili. Quindi attenersi a una stringa 0-9.)
tomsmeding

1
Rotto : codegolf.stackexchange.com/a/51160/41288 . Iniziato osservando che stringhe come "10000" e "20000" producono hash molto vicini. Iniziato a giocare con sempre più zeri, e dopo 128 o giù di lì, ogni ripetizione di cifre + k * 4 zero restituisce lo stesso hash indipendentemente da k.
Tucuxi,

@tucuxi Già pensato che non dovrebbe essere un'ape troppo dura; felice che non fosse banale, ma che qualcuno lo abbia rotto comunque. Buon lavoro.
tomsmeding

2

C ++, 239 byte

Il mio primo codice golf! [ Per favore sii gentile ]

#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);}

Versione non golfata:

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;
}

Non il miglior hash e sicuramente non il codice più breve esistente. Accettare i suggerimenti sul golf e sperare di migliorare!

involucro

Probabilmente non il migliore al mondo, ma comunque un involucro

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
Sembra solido, ma con 64 bit, può essere soggetto a forzatura bruta. C'è circa il 50% di probabilità di trovare una collisione in ~ sqrt (n) test (tra n gli output totali); 2 ^ 32 tentativi non è così tanto per un PC moderno.
Tucuxi,

Wrapper non ha inclusioni di intestazione e in generale porta a molti hash uguali.
Vi.

Fornisci alcuni esempi di hash. Per me sia "3" che "33" portano a 481c27f26cba06cf (usando questo wrapper).
Vi.

Cracked: codegolf.stackexchange.com/a/51215/41288 . Sospetto proprio prima di @Vi. ho scoperto perché così tanti hash erano uguali.
Tucuxi,

1
Collisione corretta (senza utilizzo di bug): printf '33333333\x40\xF3\x32\xD6\x56\x91\xCA\x66' | ./hash7_-> a4baea17243177fd; printf '33333333\x77\x39\xF3\x82\x93\xDE\xA7\x2F' | ./hash7_-> a4baea17243177fd. Il bruteforcer trova qui le collisioni molto più velocemente rispetto ad altri hash a 64 bit qui.
Vi.

2

Java, 299 291 282 byte, crackato.

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)));}}

Esegue alcune operazioni su BigIntegers, quindi prende il risultato modulo 2 128 .


Come eseguo questo? Ideone si rifiuta di compilarlo.
Martin Ender,

1
Puoi eseguirlo su Ideone rinominando la classe in "Main" o rimuovendo la prima parola chiave "pubblica" (ma NON la seconda). O uno funzionerà.
SuperJedi224,


1
@ SuperJedi224 Perché non rimuovere il primo publicda solo, risparmiando 7 caratteri?
user253751

@immibis Perché allora non penso che funzionerebbe bene su Eclipse. Ci proverò comunque. EDIT: suppongo che lo sia. Questa è una sorpresa.
SuperJedi224

2

C, 128 byte [ incrinato ]

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);}

Questo è più o meno lo stesso algoritmo del mio ultimo sforzo (risolto da Vi.) , Ma ora ha abbastanza ruote per criceti per generare hash a 128 bit corretti.

Le quattro costanti prime nel codice sono le seguenti:

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

Come prima, questo è un programma completo senza la necessità di un wrapper. L'intero I viene immesso tramite stdin come dati binari non elaborati (big-endian) e l'hash O viene stampato in esadecimale su stdout. Gli zeri iniziali in I vengono ignorati.

Esempi:

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


Il tuo esempio non ha mostrato una collisione proprio lì (i primi due)?
mbomb007,

@ mbomb007 No. L'ingresso è un numero compreso tra 0 e 2 ^ (2 ^ 30). 0x00 e 0x0000 sono entrambi uguali a zero, quindi producono lo stesso output.
ossifrage squeamish

2

C, 122 byte [ incrinato ]

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);}

Anelli nidificati, LCG a metà assed e scambio variabile. Cosa non è da amare?

Ecco una versione non giocata con cui giocare:

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;
}

Questo è un programma completamente autonomo che legge da STDIN e stampa su STDOUT.

Esempio:

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

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

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

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

In alcuni semplici benchmark, esegue l'hashing di circa 3 MB / s di dati di testo. La velocità dell'hash dipende dai dati di input stessi, quindi probabilmente dovrebbero essere presi in considerazione.



1

PHP 4.1, 66 byte [ crackato ]

Mi sto solo scaldando.

Spero che questo sia interessante.

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

Ho provato numeri grandi come 999999999999999999999999999.
L'output sembrava essere compreso nell'intervallo 2 128 .


PHP 4.1 è richiesto a causa della register_globalsdirettiva.

Funziona creando automaticamente variabili locali dalla sessione, POST, GET, RICHIESTA e cookie.

Usa la chiave a. (ES: accesso sopra http://localhost/file.php?a=<number>).

Se vuoi provarlo con PHP 4.2 e successivi, prova questo:

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

Questa versione funziona solo con POST e GET.


Esempio di output:

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

(Ti assicuro che ci sono numeri che producono lo stesso hash).



1

C, 134 byte, Cracked

Questo è un programma C completo.

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);}

Cosa fa: L'idea è di prendere l'input come array di byte e aggiungere alla fine byte pseudo casuali (ma deterministici) per rendere la lunghezza pari a circa 2 2 30 (un po 'di più). L'implementazione legge input byte per byte e inizia a usare dati pseudo casuali quando trova il primo carattere che non è una cifra.

Poiché il PRNG incorporato non è consentito, l'ho implementato da solo.

Esiste un comportamento indefinito / definito dall'implementazione che rende il codice più breve (il valore finale deve essere senza segno e dovrei usare tipi diversi per valori diversi). E non ho potuto usare i valori a 128 bit in C. Versione meno offuscata:

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 byte [[ Cracked ]]

Questo è abbastanza simile a tutti gli altri hash (LOOP, XOR, SHIFT, ADD) qui. Vieni a prendere i tuoi punti ladri;) Ne farò uno più difficile dopo che questo sarà risolto.

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 (prevede un argomento in base-16 noto anche come esadecimale):

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


1
Inoltre, non sono sicuro che questa voce soddisfi le specifiche dell'OP, poiché sulla mia macchina la funzione richiede più secondi su ingressi di grandi dimensioni. Ad esempio, ci sono H(2**(2**10))voluti circa 8 o 9 secondi, mentre ci sono H(2**(2**12))voluti circa 29 secondi e ci sono H(2**(2**14))voluti più di due minuti.
Mathmandan,

Hai perfettamente ragione, ovviamente avrei dovuto testare i tempi per input più grandi. Inoltre, mi sembra di aver dimenticato di eseguire il mio test dopo aver aggiunto quel turno. La versione originale era senza turni (prima della pubblicazione) e stava superando il mio test "nessuna collisione nei primi 100000 numeri interi": /
Perplesso il

1

Python 2.7 - 161 byte [[ Cracked ]]

Bene, dato che sono riuscito a cambiare la mia prima funzione hash in una versione inutile prima di pubblicarla, penso che pubblicherò un'altra versione di una struttura simile. Questa volta l'ho testato contro banali collisioni e ho testato la maggior parte delle possibili grandezze di input per la velocità.

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 (non conteggiato nel Bytecount)

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

Esegui esempio (l'input è sempre un numero esadecimale):

$ 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


Ben fatto jimmy :)
Perplesso il

1

Rubino, 90 byte

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

Un algoritmo di hash altamente casuale che ho creato senza guardare alcun hash reale ... non ho idea se sia buono. prende una stringa come input.

Wrapper:

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

Potresti fornire il wrapper richiesto dalla domanda?
Dennis,

Qual è il formato di input? Ho provato con un numero ma dice comparison of String with 255 failed (ArgumentError).
jimmy23013,

H prende una stringa, Build string prende il numero richiesto dall'OP e lo trasforma in una stringa.
MegaTom il

Penso che tu abbia bisogno di un gets.to_iinvolucro.
jimmy23013,



0

PHP, 79 byte (rotto. Con un commento):

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

Questo fa molte cose spaventose tramite conversioni di tipo in php, il che rende difficile prevedere;) (o almeno lo spero). Non è la risposta più breve o illeggibile, tuttavia.

Per eseguirlo puoi usare PHP4 e registrare globals (con? I = 123) o usare la riga di comando:

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

5
Il valore di output dell'hash sembra in virgola mobile. Ed è lo stesso per 300000000000000000000000000000000000000000000001 e 300000000000000000000000000000000000000000000000.
Vi.

0

C # - 393 byte incrinati

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"));
    }
}

Non ho mai toccato crittografia o hashish in vita mia, quindi sii gentile :)

È una semplice implementazione di un hash FNV-1a con alcuni array imperniati sull'input. Sono sicuro che esiste un modo migliore per farlo, ma questo è il massimo che potrei fare.

Potrebbe usare un po 'di memoria su input lunghi.


Cracked: codegolf.stackexchange.com/a/51277/101 Oltre ad avere un'imbottitura difettosa, questo non è un hash crittografico, ci sono molti modi per romperlo.
aaaaaaaaaaaa

0

Python 2, 115 byte [ Cracked già! ]

OK, ecco il mio ultimo sforzo. Solo 115 byte perché non è richiesta la nuova riga finale.

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

Questo è un programma completo che inserisce un numero intero decimale su stdin e stampa un valore di hash decimale su stdout. Gli zeri iniziali aggiuntivi comporteranno valori di hash diversi, quindi suppongo che l'input non ne abbia.

Questo funziona riempiendo blocchi di 197 cifre del numero di input attraverso un'esponenziazione modulare. A differenza di alcune lingue, int()per impostazione predefinita la funzione è sempre la base 10, quindi int('077')è 77, non 63.

Output di esempio:

$ 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
Non ha usato l'ordine dei blocchi ... Incrinato .
jimmy23013,

Ugh. Cedo :-(
ossifrage schizzinoso
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.