Kryptographisches Hash-Golf


34

Dieser Wettbewerb ist vorbei.

Aufgrund der Art der Herausforderungen wird die Cops-Herausforderung viel einfacher, wenn das Interesse an der zugehörigen Robbers-Herausforderung nachgelassen hat. Obwohl Sie weiterhin Hash-Funktionen bereitstellen können, wird Ihre Antwort daher nicht akzeptiert oder ist Teil der Rangliste.

Diese Herausforderung ist eine Suche nach der kürzesten Implementierung einer Hash - Funktion , die ist resistent gegen Kollisionen , also sollte es nicht machbar sein , zwei verschiedene Nachrichten mit dem gleichen Hash zu finden.

Als Cop versuchen Sie, eine Hash-Funktion zu erfinden und zu implementieren, um den besten Kompromiss zwischen Codegröße und Kollisionsfestigkeit zu finden. Verwenden Sie zu viele Bytes und ein anderer Polizist wird Sie überraschen!

Als Räuber versuchen Sie, die Versuche der Bullen zu vereiteln, indem Sie ihre Funktionen knacken und beweisen, dass sie ungeeignet sind. Dies wird sie zwingen, mehr Bytes zu verwenden, um ihre Algorithmen zu stärken!

Polizisten fordern heraus

Aufgabe

Implementieren Sie eine kryptografische Hash-Funktion H: I -> O Ihrer Wahl, wobei I die Menge aller nicht negativen Ganzzahlen unter 2 2 30 und O die Menge aller nicht negativen Ganzzahlen unter 2 128 ist .

Sie können H entweder als eine tatsächliche Funktion implementieren , die eine einzelne Ganzzahl, eine Zeichenfolgendarstellung einer Ganzzahl oder eines Arrays von Ganzzahlen akzeptiert und zurückgibt, oder als ein vollständiges Programm, das aus STDIN liest und in STDOUT in Basis 10 oder 16 druckt.

Wertung

  • H dass sie die zu wider Räuber Herausforderung unten definiert.

    Wenn ein Räuber Ihre Übermittlung in den ersten 168 Stunden nach dem Posten besiegt, gilt sie als geknackt .

  • Die Implementierung von H sollte so kurz wie möglich sein. Die kürzeste ungerissene Einsendung ist der Gewinner der Cops Challenge.

Zusätzliche Regeln

  • Wenn Sie H als Funktion implementieren , stellen Sie bitte einen Wrapper bereit, um die Funktion in einem Programm auszuführen, das sich wie oben beschrieben verhält.

  • Bitte geben Sie mindestens drei Testvektoren für Ihr Programm oder Ihren Wrapper an (Beispieleingaben und die entsprechenden Ausgaben).

  • H kann Ihr neuartiges Design (bevorzugt) oder ein bekannter Algorithmus sein, solange Sie es selbst implementieren. Es ist verboten, eingebaute Hash-Funktionen, Komprimierungsfunktionen, Chiffren, PRNG usw. zu verwenden.

    Jedes zur Implementierung von Hashing-Funktionen (z. B. Basiskonvertierung) verwendete integrierte Element ist ein faires Spiel.

  • Die Ausgabe Ihres Programms oder Ihrer Funktion muss deterministisch sein.

  • Es sollte einen kostenlosen (wie in Beer) Compiler / Interpreter geben, der auf einer x86- oder x64-Plattform oder in einem Webbrowser ausgeführt werden kann.

  • Ihr Programm oder Ihre Funktion sollte einigermaßen effizient sein und muss in weniger als einer Sekunde eine Meldung in I unter 2 2 19 haben .

    Für Edge-Fälle ist die auf meinem Computer (Intel Core i7-3770, 16 GiB RAM) benötigte (Wand-) Zeit entscheidend.

  • Angesichts der Art dieser Herausforderung ist es verboten, den Code Ihrer Antwort in irgendeiner Weise zu ändern, unabhängig davon, ob dies die Ausgabe verändert oder nicht.

    Wenn Ihr Beitrag geknackt wurde (oder auch nicht), können Sie eine zusätzliche Antwort posten.

    Wenn Ihre Antwort ungültig ist (z. B. nicht mit der E / A-Spezifikation übereinstimmt), löschen Sie sie bitte.

Beispiel

Python 2.7, 22 Bytes

def H(M):
 return M%17

Verpackung

print H(int(input()))

Räuber herausfordern

Aufgabe

Knacken jeden der Kopse Vorbringen durch die Veröffentlichung der folgenden in dem Räuber thread : zwei Nachrichten M und N in I , so dass H (M) = H (N) und M ≠ N .

Wertung

  • Wenn Sie jeden Cop-Beitrag knacken, erhalten Sie einen Punkt. Der Räuber mit den meisten Punkten gewinnt.

    Bei einem Gleichstand gewinnt der Räuber, der die längste Einreichung geknackt hat.

Zusätzliche Regeln

  • Jeder Cop-Beitrag kann nur einmal geknackt werden.

  • Wenn sich ein Cop-Beitrag auf implementierungsdefiniertes oder undefiniertes Verhalten stützt, müssen Sie nur einen Riss finden, der (nachweislich) auf Ihrem Computer funktioniert.

  • Jeder Riss gehört zu einer eigenen Antwort im Räuber-Thread.

  • Wenn Sie einen ungültigen Cracking-Versuch veröffentlichen, können Sie diesen bestimmten Beitrag 30 Minuten lang nicht mehr knacken.

  • Sie können Ihre eigene Vorlage nicht knacken.

Beispiel

Python 2.7, 22 Bytes von user8675309

1

und

18

Bestenliste

Sichere Einsendungen

  1. CJam, 21 bytes von eBusiness
  2. C ++, 148 Bytes von Tucuxi
  3. C ++, 233 (?) Bytes von Vi.

Nicht geknackte Einsendungen

Mit diesem Stapel-Snippet können Sie eine Liste der noch nicht geknackten Antworten abrufen.

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>


Wenn eine Hash-Funktion fälschlicherweise Zahlen zurückgibt, die größer als 2 ^ 128-1 sind, macht dies die Übermittlung ungültig, oder würden wir einfach das Ergebnis modulo 2 ^ 128 nehmen?
Martin Ender

@ MartinBüttner: Ja, du müsstest das Ergebnis modulo 2 ^ 128 nehmen.
Dennis

1
@Scimonster Erfüllt nicht die Anforderungen (bis zu 2 ^ 30 Bit Eingabe, 128 Bit Ausgabe)
CodesInChaos

1
Gehen Bullen und Räuber normalerweise nicht anders herum?
Haneefmubarak

2
Vielleicht könnten wir eine Regel haben, die besagt, dass Einsendungen Beispiel-Hashes enthalten müssen. Es ist ziemlich ärgerlich, die vom Sender gewählte Programmiersprache ausführen zu müssen, um ein Ergebnis zu erzielen, mit dem die Implementierung von Cracks verglichen werden kann.
aaaaaaaaaaa

Antworten:


6

CJam, 21 Bytes

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

Nimmt eine Folge von Bytes als Eingabe.

Im Pseudocode:

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

Beispiel-Hashes:

"" (leere Zeichenfolge) -> 1
"Test" -> 2607833638733409808360080023081587841
"Test" -> 363640467424586895504738713637444713

Es mag ein bisschen einfach sein, der Ausgabebereich ist nur etwas mehr als 122 Bits, die dreifache Iterationsverstärkung ist bereits ein bisschen kaputt, da sie jedes Mal genau das Gleiche tut, also geben Sie ein, das im ersten Schritt auf 1 geht Iteration wird eine vollständige Pause sein. Aber es ist kurz und es macht keinen Spaß, zu sicher zu sein.


Gibt es eine begleitende C-Version wie in den anderen CJam-Posts?
Vi.

@Vi. Nein, zumindest noch nicht. Ich habe mich nie mit Bigint in C beschäftigt. Gibt es dafür eine Standardbibliothek?
aaaaaaaaaaa

GMP ?
Vi.


1
@ Agawa001 Ihre Terminologie ist durcheinander. Es ist ein Triple-Pass-Hash-Algorithmus mit Schwammfunktion. Eine Caesar-Chiffre ist ein spezifischer Verschlüsselungsalgorithmus ohne inneren Zustand.
aaaaaaaaaaa

7

Python, 109 Bytes [ geknackt , und wieder ]

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

Ich habe versucht, Jenkins 'einzelne Funktion so zu implementieren , wie sie ist, mit dem einzigen Unterschied, dass es sich um den Startwert und die Anzahl der Bits handelt.

Lustige Tatsache: Anscheinend hat Perl irgendwann den Jenkins-Hash benutzt .

Verpackung

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

Beispiele

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

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 ist eine GCC-Erweiterung und funktioniert wie erwartet. Der Hash basiert auf der Iteration von FNV-Hash (ich habe ihre Primzahl ausgeliehen, obwohl aes sich um die ersten Ziffern von Pi in hex handelt) mit einer sha1-ähnlichen Rotation zu Beginn jeder Iteration. Das Kompilieren mit -O3, das Hashing einer 10MB-Datei dauert weniger als 2 Sekunden, daher gibt es immer noch einen Spielraum, um die Iterationen in der inneren Schleife zu verbessern - aber ich fühle mich heute großzügig.

Deaktiviert (geänderte Variablennamen, hinzugefügte Kommentare, Leerzeichen und ein Paar geschweifte Klammern) für Ihr knackiges Vergnügen:

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
}

Golfvorschläge sind willkommen (auch wenn ich den darauf basierenden Code nicht verbessern kann).

edit: Tippfehler im de-uglified Code behoben (Golf-Version bleibt unverändert).


oscheint nicht initialisiert zu sein. Wo outputist deklariert? Oder vielleicht odoch output?
Vi.

Das selbe für n. Haben Sie den auszuführenden "de-uglified" Code tatsächlich überprüft?
Vi.

Hat den Bruteforcer gestartet ...
Vi.

Auch 3-Runden-Version ist nicht einfach.
Vi.

@Vi. Die de-uglified Version wurde korrigiert - es tut mir leid, dass ich sie nicht besser überprüft habe. Ich bin stolz auf diese innere Schleife; U i=81;i-=3hätte noch abscheulicher sein können, ohne nennenswerte Laufzeitkosten.
Tucuxi

5

CJam, 44 Bytes [ geknackt ]

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

Die Eingabe erfolgt in Basis 10.

CJam ist langsam. Ich hoffe, es läuft in 1 Sekunde in einem Computer ...

Erklärungen

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.

Nun, die zweidimensionalen Dinge schienen eine Schwäche zu sein ... Am Anfang sollten einige langsame Berechnungen schneller gemacht werden. Aber es kann nicht in einer Sekunde ausgeführt werden, egal was ich tue, also habe ich den langsamen Code endgültig entfernt.

Es sollte auch besser sein, wenn ich binäre Bits und höhere Basen verwendet habe.

C-Version

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

Könnten Sie bitte eine Beschreibung hinzufügen? Nicht jeder kennt CJam.
Orlp

@orlp Bearbeitet ...
jimmy23013

Dies dauert auf meinem Computer 0,4 s, liegt also im erlaubten Bereich.
Dennis

Was ist A, B, C und so weiter? Einige Matrizen? Welche abmessungen Kann es einfach in C implementiert werden?
Vi.

1
Cracked , glaube ich.
Sp3000,

5

C ++, 182 Zeichen (+ ca. 51 Zeichen Kesselschild)

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

Kesselplatte:

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
}

Runnable-Programm mit Golffunktion

#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
Ich denke, die Funktionsdeklaration usw. zählt zur Zeichenanzahl.
Ypnypn

@Ypnypn, gezählte Zeichen in einer Funktionsdeklaration.
Vi.

Was ist der Ausgabe-Hash? Ich gehe davon aus, dass es ((h << 64) | j) ist.
Tucuxi

Ja. Oder nur ein Paar 64-Bit-Zahlen. Ich habe es __uint128_terst herausgefunden, nachdem ich dies implementiert hatte.
Vi.

1
@ Tennis, Done.one
Vi.

4

Pyth, 8 Gebrochen

sv_`.lhQ

Probieren Sie es online aus

Eine dumme Antwort, ich werde erklären, wie es funktioniert, weil die meisten Leute Pyth nicht lesen können. Dabei wird das natürliche Protokoll von eins plus der Eingabe in eine Zeichenfolge konvertiert. Diese Zeichenfolge wird umgekehrt, ausgewertet und dann in eine Ganzzahl konvertiert.

Eine Python-Übersetzung würde so aussehen:

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


4

Python 3, 216 Bytes [ geknackt ]

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

Aufgrund einer Inkompatibilität mit der Spezifikation kann ich mir mindestens eine leichte Sicherheitslücke vorstellen, aber ansonsten denke ich, dass dies mindestens ein Brute-Force-Beweis ist. Ich habe unter anderem die ersten 10 Millionen Hashes überprüft.

In Bezug auf Golf wäre dies in Python 2 kürzer, aber ich habe einige Bytes für die Effizienz geopfert (da es wahrscheinlich sowieso nicht gewinnen wird).

Edit: Dies war mein Versuch, den Very Smooth Hash zu implementieren , aber leider waren 128-Bit viel zu klein.

Verpackung

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

Beispiele

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

Code Erklärung

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

Ein Beispiel für die Polsterung für 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 Bytes [ geknackt ]

Dies ist das vollständige Programm; Kein Wrapper erforderlich. Akzeptiert Binäreingaben über stdin und gibt einen hexadezimalen Hash an stdout aus.

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

Hiermit wird nur ein 64-Bit-Hash berechnet, sodass ich hier ein bisschen zocke.

Falls sich jemand wundert, die beiden Konstanten 'foo+'und 'bar/'sind die Primzahlen 1718578987 und 1650553391.


Beispiele:

Ignoriert führende Nullen:

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

Einzelbyte-Eingänge:

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

Mehrbyte-Eingänge:

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

Wie wäre es mit ‚aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa‘ und ‚aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa‘ verhalten?
Ismael Miguel

1
foo|(d5c9bef71d4f5d1b) und foo\(d5c9bef71d4f5d1b) erzeugen SEHR ähnliche Hashes.
Ismael Miguel

1
Brach es!!! \x00und \x00\x00!
Ismael Miguel

1
Aufgrund der Chat-Kommentare glaube ich, dass dies noch nicht geknackt ist? Nur doppelte Überprüfung, da der hochgestufte Kommentar für diejenigen verwirrend sein kann, die nach ungerissenen Hashes suchen.
Sp3000,


3

J - 39 Bytes - geknackt

Funktion, die einen String als Eingabe nimmt und eine Ganzzahl <2 128 zurückgibt . Ich gehe davon aus, dass wir unsere Funktion benennen müssen, um gültig zu sein, also lassen Sie weitere 3 Zeichen aus der Zählung aus, wenn wir anonyme Funktionen einreichen können.

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

Für diejenigen unter Ihnen, die keine Hieroglyphen lesen, ist hier ein Überblick darüber, was ich tue.

  • a=.(2^128x)&|@^/@Dies ist eine Unterroutine *, die ein Array von Zahlen aufnimmt und es dann als Power Tower behandelt, in dem die Potenzierung mod 2 128 genommen wird . Mit "Power Tower" meine ich, wenn Sie ihm den Input geben würden 3 4 5 6, würde er berechnen 3 ^ (4 ^ (5 ^ 6)).
  • (".p:@+5,9:)aDiese Funktion nimmt einen String, konvertiert ihn in die Zahl N und berechnet dann die ( n +5) -te und ( n +9) -te Primzahl und wirft dann die avon vorher darauf. Das heißt, wir finden p(n+5) ^ p(n+9)Mod 2 128, wo p(k)die k-te Primzahl ist.
  • H=:_8...\(a...)]Führen Sie die obige Funktion für 8-stellige Unterblöcke der Eingabe und dann aalle Ergebnisse zusammen aus und rufen Sie die resultierende Hash-Funktion auf H. Ich benutze 8 Zeichen, weil Js " k-th prime" -Funktion fehlschlägt, wenn p(k)> 2 31 , dh k=105097564der größte Safe ist k.

Haben Sie einige Beispielausgaben. Sie können dies online unter tryj.tk ausprobieren , ich empfehle jedoch, dies zu Hause zu tun, indem Sie den Interpreter von Jsoftware herunterladen .

   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

* Technisch gesehen ist es keine Funktion für sich, sondern hängt mit anderen Funktionen zusammen und wirkt sich auf deren Ausgabe aus. Dies ist jedoch eine semantische Frage von J, kein begrifflicher Unterschied: Der Programmablauf ist so, wie ich es oben beschrieben habe.



2

Python 3, 118 Bytes [ geknackt ]

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

Einrückung ist eine einzelne Registerkarte. Einfaches Hash, habe es noch nicht gründlich getestet.

Rufen Sie wie folgt an:

print(H("123456789"))

Ergebnis: 73117705077050518159191803746489514685


Wie soll die Eingabe-Ganzzahl in eine Zeichenfolge konvertiert werden, die in Ihrem Algorithmus verwendet wird?
Feersum

@feersum base-10 string ist das, was ich getestet habe. Es wird zwar nichts verwendet, aber ord(c)eigentlich reicht jeder String :) (mit Ausnahme von Dingen wie nul chars denke ich, dass diese Hash-Kollisionen wirklich einfach machen. Also bleiben Sie bei einem 0-9-String.)
tomsmeding

1
Brach es: codegolf.stackexchange.com/a/51160/41288 . Begonnen mit der Beobachtung, dass Zeichenfolgen wie "10000" und "20000" sehr enge Hashes erzeugen. Begann, mit immer mehr Nullen herumzuspielen, und nach etwa 128 gibt jede Ziffer + k * 4-Nullen-Wiederholung den gleichen Hash zurück, unabhängig von k.
Tucuxi

@tucuxi Schon gedacht, es sollte nicht zu schwer sein; froh, dass das nicht trivial ist, aber dass es trotzdem jemand kaputt gemacht hat. Gute Arbeit.
Tomsmeding

2

C ++, 239 Bytes

Mein allererster Code Golf! [ Bitte sei sanft ]

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

Nicht der beste Hash und definitiv nicht der kürzeste existierende Code. Golftipps annehmen und auf Besserung hoffen!

Verpackung

Wahrscheinlich nicht die beste der Welt, aber dennoch eine Hülle

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
Sieht solide aus, aber mit 64 Bit kann es zu Brute-Forcing kommen. Bei ~ sqrt (n) -Tests besteht eine Wahrscheinlichkeit von ca. 50%, eine Kollision zu finden (aus n Gesamtausgaben). 2 ^ 32 Versuche ist nicht so viel für einen modernen PC.
Tucuxi

Wrapper enthält keine Header-Einschlüsse und führt im Allgemeinen zu vielen gleichen Hashes.
Vi.

Stellen Sie einige Hash-Proben bereit. Für mich führen sowohl "3" als auch "33" zu 481c27f26cba06cf (unter Verwendung dieses Wrappers).
Vi.

Gebrochen: codegolf.stackexchange.com/a/51215/41288 . Ich vermute kurz vor @Vi. fand heraus, warum so viele Hashes gleich waren.
Tucuxi

1
Richtige Kollision (ohne Fehlerbehebung): printf '33333333\x40\xF3\x32\xD6\x56\x91\xCA\x66' | ./hash7_-> a4baea17243177fd; printf '33333333\x77\x39\xF3\x82\x93\xDE\xA7\x2F' | ./hash7_-> a4baea17243177fd. Der Bruteforcer findet Kollisionen hier viel schneller als in anderen 64-Bit-Hashes.
Vi.

2

Java, 299 291 282 Bytes, geknackt.

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

Führt einige Operationen an BigIntegers durch und übernimmt dann das Ergebnis modulo 2 128 .


Wie führe ich das aus? Ideone weigert sich, es zu kompilieren.
Martin Ender

1
Sie können es auf Ideone ausführen, indem Sie die Klasse in "Main" umbenennen oder das erste "öffentliche" Schlüsselwort (aber NICHT das zweite) entfernen. Beides wird funktionieren.
SuperJedi224,


1
@ SuperJedi224 Warum nicht den ersten publicselbst entfernen und dabei 7 Zeichen sparen?
user253751

@immibis Denn dann glaube ich nicht, dass es bei Eclipse richtig funktionieren würde. Ich werde es aber versuchen. EDIT: Ich denke schon. Das ist eine Überraschung.
SuperJedi224

2

C, 128 Bytes [ geknackt ]

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

Dies ist mehr oder weniger derselbe Algorithmus wie bei meinem letzten Versuch (geknackt von Vi.) , Aber jetzt sind genügend Hamsterräder vorhanden, um korrekte 128-Bit-Hashes zu generieren.

Die vier Hauptkonstanten im Code lauten wie folgt:

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

Dies ist nach wie vor ein vollständiges Programm, für das kein Wrapper erforderlich ist. Die ganze Zahl I wird über stdin als binäre Rohdaten (Big-Endian) eingegeben, und der Hash O wird in hexadezimal bis stdout gedruckt. Führende Nullen in I werden ignoriert.

Beispiele:

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


Hat Ihr Beispiel nicht genau dort eine Kollision gezeigt (die ersten beiden)?
mbomb007

@ mbomb007 Nein. Die Eingabe ist eine Zahl zwischen 0 und 2 ^ (2 ^ 30). 0x00 und 0x0000 sind beide gleich Null und erzeugen daher die gleiche Ausgabe.
Squeamish Ossifrage

2

C, 122 Bytes [ geknackt ]

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

Verschachtelte Schleifen, halb Assed LCGs und Variable Swapping. Was gibt es nicht zu lieben?

Hier ist eine ungolfspielte Version zum Herumspielen:

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

Dies ist ein vollständig eigenständiges Programm, das aus STDIN liest und in STDOUT druckt.

Beispiel:

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

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

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

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

In einigen einfachen Benchmarks werden ca. 3 MB / s Textdaten gehasht. Die Hash-Geschwindigkeit hängt von den Eingabedaten selbst ab, daher sollte dies wahrscheinlich berücksichtigt werden.



1

PHP 4.1, 66 Bytes [ geknackt ]

Ich wärme mich nur auf.

Ich hoffe, Sie finden das interessant.

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

Ich habe versucht, es Zahlen so groß wie 9999999999999999999999999.
Die Ausgabe schien im Bereich von 2 128 zu liegen.


PHP 4.1 wird aufgrund der register_globalsDirektive benötigt.

Dabei werden automatisch lokale Variablen aus der Sitzung, POST, GET, REQUEST und Cookies erstellt.

Es benutzt den Schlüssel a. (ZB: Zugang über http://localhost/file.php?a=<number>).

Wenn Sie es mit PHP 4.2 und neuer testen möchten, versuchen Sie Folgendes:

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

Diese Version funktioniert nur mit POST und GET.


Beispielausgabe:

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

(Ich versichere Ihnen, dass es Zahlen gibt, die denselben Hash erzeugen).



1

C, 134 Bytes, gerissen

Dies ist das vollständige C-Programm.

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

Was es tut: Die Idee ist, die Eingabe als Byte-Array zu nehmen und am Ende pseudozufällige (aber deterministische) Bytes anzuhängen, um die Länge auf ungefähr 2 2 30 (etwas mehr) zu bringen. Die Implementierung liest die eingegebenen Daten byteweise und beginnt mit der Verwendung von Pseudozufallsdaten, wenn sie das erste Zeichen findet, das keine Ziffer ist.

Da eingebautes PRNG nicht erlaubt ist, habe ich es selbst implementiert.

Es gibt ein undefiniertes / implementierungsdefiniertes Verhalten, das den Code kürzer macht (der endgültige Wert sollte vorzeichenlos sein und ich sollte verschiedene Typen für verschiedene Werte verwenden). Und ich konnte 128-Bit-Werte in C nicht verwenden. Weniger verschleierte 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 [[ Gebrochen ]]

Dies ist allen anderen Hashes (LOOP, XOR, SHIFT, ADD) sehr ähnlich. Komm hol deine Räuberpunkte;) Ich mache eine schwierige Frage, nachdem diese gelöst ist.

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 (erwartet ein Argument in base-16, auch als hexadezimal bezeichnet):

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


1
Ich bin mir auch nicht sicher, ob dieser Eintrag der OP-Spezifikation entspricht, da die Funktion auf meiner Maschine bei großen Eingängen mehrere Sekunden dauert. Beispielsweise H(2**(2**10))dauerte es ungefähr 8 oder 9 Sekunden, während es H(2**(2**12))ungefähr 29 Sekunden und H(2**(2**14))mehr als zwei Minuten dauerte.
Mathmandan

Sie haben völlig Recht, ich hätte natürlich das Timing für größere Eingänge testen sollen. Außerdem habe ich anscheinend vergessen, meinen eigenen Test durchzuführen, nachdem diese Schicht hinzugefügt wurde. Die ursprüngliche Version war ohne Schicht (vor dem Posten) und bestand meinen Test "Keine Kollisionen in den ersten 100000 Ganzzahlen": /
Rätselhafter

1

Python 2.7 - 161 Bytes [[ Gebrochen ]]

Nun, da ich es geschafft habe, meine erste Hash-Funktion vor dem Posten in eine nutzlose Version zu verwandeln, denke ich, dass ich eine andere Version einer ähnlichen Struktur posten werde. Diesmal habe ich es gegen triviale Kollisionen getestet und die meisten möglichen Eingabegrößen auf Geschwindigkeit getestet.

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 (nicht im Bytecount enthalten)

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

Beispiel ausführen (Eingabe ist immer eine Hexadezimalzahl):

$ 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


Gut gemacht jimmy :)
Verwirrt

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

Ein sehr zufälliger Hash-Algorithmus, den ich erfunden habe, ohne mir echte Hashes anzusehen ... keine Ahnung, ob er gut ist. Als Eingabe wird eine Zeichenfolge verwendet.

Verpackung:

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

Könnten Sie bitte den Wrapper bereitstellen, den die Frage erfordert?
Dennis

Was ist das Eingabeformat? Ich habe es mit einer Nummer versucht, aber es heißt comparison of String with 255 failed (ArgumentError).
Jimmy23013

H nimmt einen String, Build string nimmt die vom OP benötigte Nummer und wandelt sie in einen String um.
MegaTom

Ich denke, Sie brauchen eine gets.to_iin der Verpackung.
Jimmy23013



0

PHP, 79 Bytes (geknackt. Mit einem Kommentar):

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

Dies macht eine Menge furchterregender Dinge durch Typkonvertierungen in PHP, was es schwierig macht, dies vorherzusagen;) (oder zumindest hoffe ich es). Dies ist jedoch nicht die kürzeste oder unleserlichste Antwort.

Um es auszuführen, können Sie PHP4 verwenden und Globals registrieren (mit? I = 123) oder die folgende Befehlszeile verwenden:

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

5
Der Ausgabewert des Hashs sieht wie ein Gleitkomma aus. Und es ist das gleiche für 30000000000000000000000000000000000000000001 und 30000000000000000000000000000000000000000000.
Vi.

0

C # - 393 Bytes geknackt

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

Ich habe noch nie Kryptografie oder Hashing in meinem Leben angefasst, also sei vorsichtig :)

Es ist eine einfache Implementierung eines FNV-1a- Hashes mit einem Array, das am Eingang schwenkt. Ich bin mir sicher, dass es einen besseren Weg gibt, aber das ist das Beste, was ich tun kann.

Bei langen Eingaben wird möglicherweise etwas Speicher benötigt.


Cracked: codegolf.stackexchange.com/a/51277/101 Abgesehen von einer fehlerhaften Polsterung ist dies kein kryptografischer Hash, es gibt so viele Möglichkeiten, ihn zu knacken .
aaaaaaaaaaa

0

Python 2, 115 Bytes [Bereits geknackt!]

OK, hier ist meine letzte Anstrengung. Nur 115 Bytes, da die letzte Zeile nicht benötigt wird.

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

Dies ist ein vollständiges Programm, das eine Dezimalzahl in stdin eingibt und einen Dezimal-Hashwert in stdout ausgibt. Zusätzliche führende Nullen führen zu unterschiedlichen Hash-Werten, daher gehe ich einfach davon aus, dass die Eingabe keine hat.

Dies funktioniert, indem 197-stellige Teile der eingegebenen Nummer durch eine modulare Exponentiation gefüllt werden. Im Gegensatz zu einigen Sprachen ist die int()Funktion immer standardmäßig auf Basis 10 eingestelltint('077') 77 und nicht 63.

Beispielausgaben:

$ 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
Die Reihenfolge der Blöcke wurde nicht verwendet ... Gebrochen .
Jimmy23013

Pfui. Ich gebe in :-(
zimperlich ossifrage
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.