das wurde in der letzten vorlesung durchgenommen und ist u.a. gegenstand der übungsbeispiele
ich blick da überhaupt nicht durch
kann mir das jemand idiotensicher erklären, was das überhaupt genau ist und wie man es im programm umsetzt bzw. wisst ihr websites, wo das gut erklärt ist?
Hashing
-
-
ein hash ist ein code der bestimmte daten eindeutig identifizieren soll
es gibt etwas das heißt hashalgorithmen von denen MD5 zb ein ganz bekannter ist, diese generieren über eine meist große datenfolge (zb ein bild, eine zeichenkette usw) einen viel kleineren hash der trotzdem die eigenschaft hat dass er einzigartig ist
wenn ich zb den string "das ist ein test!" hashe kommt dabei raus -1100477139
wenn ich nur einen buchstaben änder, zb "das ist kein test!" wird der hash so: -2018157948das ist noch eine eigenschaft von hashes, kleine änderungen im der datenmenge über die er gebildet wird bewirken dass sich der hash überhaupt ganz ändert
wofür werden hashes jetzt vernwendet?
wenn du beispielsweise auf manchen seiten exe files zum runterladen hast sieht du manchmal daneben so nen komischen langen string mit zahlen und buchstaben, das ist ein hash der über die exe gebildet wurde, wenn du die exe file von einem mirror runterladest kannst du selbst einen hash drüberlaufen lassen und wenn der nicht mit dem referenzhash auf der anbieterseite übereinstimmt dann ist es nicht dieselbe exe file (andere version, jemand hat nen virus reingetan etc)eine weitere verwendungsmöglichkeit von hashes währe beispielsweise wenn du ein programm hast das bilder in den speicher ladet, jedesmal wenn du ein bild reinladest hashst du den inhalt und vergleichst den hash mit allen hashes der schon geladenen bilder, wenn es bereits einen hash gibt der gleich ist wie der mit dem du vergleichst weisst du dass das bild schon im speicher ist und ladest es nicht mehr neu rein
es gibt auch etwas das sich hash table nennt, das ist mehr oder weniger ein array dessen elemente immer wertepaare sind, ein paar enthält einen hash (id) und den wert mit dem der hash assoziiert wird dabei müssen nich zwangsläufig wirklich die hashes über den wert gebildet werden sondern als hash/id kann auch einfach eine zahl genommen werden die immer erhöht wird
also ganz kurz gefasst, hash = relativ kleine zahl (bei md5 128 bit) die eine beliebig große datenmenge (beispielsweise eine 10mb große bitmap) eindeutig identifiziert
hashalgorithmus -> wird verwendet um über die datenmenge einen hash zu erzeugen
wenn du das in c# machst gibts beispielsweise für jedes objekt einfach ne methode .GetHashCode() die dir den hash holt, in c/cpp würde ich mal in der std schauen obs da nicht sowas gibt ansonsten gibt es sicher genügend libs die du einfach inkludieren kannst und über ne funktion nen md5 hash über einen char* buffer an daten bilden kannst
alleine würd ich sowas nicht implementieren.. wozu auch wenns das schon tausendfach besser ausgeführt gibt
-
vielen dank, das war echt eine super erklärung
jetzt kapier ich endlich, was ein hash überhaupt ist
selber implementieren müssen wir das auch nicht, nur anwenden und natürlich beim test theoretische fragen dazu beantworten -
hey nanny. ich blick beim übungsblatt 4 überhaupt nicht durch. hast du schon irgendwelche aufgaben gelöst?
-
ich bin total frustriert. beim blatt drei hab ich noch was gekonnt und jetzt bei blatt 4 check ich gar nix. ich versteh nicht, wieso ichs net check. ich versteh ja die theorie des ganzen. aber bei den beispielen blick ich nimmer durch. nicht mal bei den ersten beiden.
- Lesen Sie beliebig viele (max. 50) Zahlen (Abschluss mit dem Wert 0) ein, speichern Sie diese in einem Feld und geben Sie Mittelwert, Median und die Standardabweichung der Zahlen aus. (Bei der Ermittlung der Medians können Sie davon ausgehen, dass die Zahlen schon sortiert sind, vom Benutzer also entweder in aufsteigender oder in fallender Reihenfolge eingegeben werden.)
- Bestimmen Sie alle Primzahlen bis zu einem gegebenen n mit Hilfe des Siebs des Eratosthenes.
-
hallo, ich hab mal das erste beispiel gemacht in c++.. oder eigentlich c... naja c ist es aber nicht weil die std verwendet wird und das ist c++ aber egal..
jedenfalls hab ich keine klassen gemacht oder so sondern nur funktionen und alles in eine .cpp datei reingetan auch ohne .h dateien weil ich nicht wiess wie weit ihr seit
das ganze ist überfüllt mit kommtentaren die wirklich fast jeden mist erklären sollten
ka allerdings wie das zweite beispiel gehen soll weil ich ka hab was dieses siebdings sein soll und auch keine lust, aberwenn ihr rausfinden wollt ob eine zahl eine primzahl ist geht das eigentlich ganz einfach so, vielleicht ist das ja eh gemeint
also irgendwas in die richtig
Code
Alles anzeigenfor(int i=0; i<n; i++) { bool primZahl = true; for(int j=2; j<zahl; j++) { if(zahl % j == 0) { primZahl = false; break; } } if(primZahl == true) { cout << "Primzahl: " << i << "\n"; } else { cout << "Keine Primzahl: " << i << "\n"; } }
irgendwie so müsste das gehen, falls ihr es nicht versteht dann lest euch beispiel #1 durch danach sollte das klar seinCode
Alles anzeigen#include <iostream> #include <windows.h> #include <math.h> //wir verwenden cout und cin für ein und ausgabe, das sind 2 funktionen in der std //was eine standardbibliothek mit klassen und funktionen ist für c++, damit wir //wenn wir schreiben dass wir std::cout verwenden können wir einfach etwas mit //cout << "text"; ausgeben im programm, ansonstne müssten wir immer dem compiler //sagen dass cout in der std ist und über std::cout << "text"; was ausgeben using std::cout; using std::cin; //bevor wir irgendwas machen werden wir mal 3 funktionen deklarieren //die benutzt werden um den druchschnitt, median und stdabweichung //auszurechnen, sie geben alle einen float, also gleitkommazahl zurück //die eben den zb bei der median fkt den median zurückliefert und alle 3 //bekommen erstmal das array mit den zahlen mit und dann einen integer //der angibt wie viele zahlen in dem array stehen die uns interessieren //die funktionen werden hier erstmal nur deklarieren, wir sagen dem compiler also //hey es gibt sie, damit er nicht verwirrt ist wenn er sie in der main() findet, //was drinsteht, also die definition machen wir erst nach der main(), wir könnten //sie aber auch gleich jetzt definieren.... ist egal //oh ja, und wir wollen auch nicht dass die funktionen unsere paramter verpfuschen //indem sie die werte ändern da wir sie ja nach dem aufruf von average noch für median //usw brauchen also sagen wir dass die parameter const also konstant sind, sie können //also nicht verändert werden, so, was das soll? wir schreiben die funktionen ja selber //und wenn wir die parameter nicht verändern wollen dann machen wir es nicht wozu also //so ein const davorschreiben... tja.. so ne programmiereigenart, ich machs eigentich nie //aber hier mal um das konzept zu zeigen, man sollte es machen, oh und noch etwas //funktionsnamen bitte immer mit großem anfangsbuchstaben und variablennamen mit kleinem //anfangsbuchstaben, ich tu immer ein kleines a am anfang bei funktionsparametern hin was //für attribute steht, also aDasIstEinParameter, und da sieht man gleich noch ne stildings //keinsolchenvariablenoderfunktionsnamenschreiben wenn dann SolcheFunktionsNamenZumBeispiel //oder dasIstEineVariablenName variablennamen -.- float Average(const int aNumbers[], const int aNumbersToProcess); float Median(const int aNumbers[], const int aNumbersToProcess); float Deviation(const int aNumbers[], const int aNumbersToProcess); void main() { //erstmal brauchen wir ein array das 50 zahlen halten kann //wir erstellen dafür zuerst mal ne variable der wir sagen //wie groß unser array wird, wenn wir die größe nämlich auf //60 ändern möchten müssen wir nicht überall im ganzen programm //50 auf 60 ändern sondern nur einmal die zuweisung von numbersLength //die länge bleibt auch immer gleich also ist es eine const variable //einmal zugewiesen behält sie immer denselben wert const int numbersLength = 50; //jetzt erstellen wir ein int array mit der größe von numbersLength //nachdem wir das array erstellt haben steht in jedem element 0 drin //das ist bei c++ default mäßig so bei "normalen" variablen wie int int numbers[numbersLength]; //und alles was zu tun bleibt ist zahlen einzulesen, falls ihr nicht //mit for schleifen vertraut seit, die schleife setzt eine variable i //und weist ihr ganz am anfang 0 zu, wie in einer while schleife wird //zuerst geschaut ob die bedingung stimmt und nachdem die schleife einmal //durchlaufen wurde wird i++ ausgeführt, also i um 1 erhöht, im prinzip //ist es eine kurzschreibweise für /* int i=0; while(i < numbersLength) { //TODO i = i + 1; } */ int i; for(i=0; i<numbersLength; i++) { cout << "Zahl " << i << " eingeben - "; cin >> numbers[i]; //wenn die zahl an der stelle an der wir gerade eben eingelesen haben eine 0 //ist kommen wir in das if rein if(numbers[i] == 0) { //und hier ist etwas das ihr vielleicht nicht kennen werdet, ein break ist //nen sehr praktisches keyword welches bedingungslos wenn es erreicht wird //die schleife in der es gerade ist beendet, wird das break also ausgeführt //sind wir an der mit dem X markierten stelle weiter unten break; } } // - X - und hier kommen wir hin wenn das break ausgeführt wurde oder die maximale // anzahl an zahlen eingelesen wurde, ok, da unser zähler (i) immer schön mitgezählt // hat steht jetzt in i drinnen wieviele zahlen das array enthält, alles was jetzt noch zu tun ist // ist die 3 funktionen aufzurufen die uns unseren median und all den mist ausrechnen //bevor wir das tun schauen wir aber überhaupt erst ob der benutzer nicht gleich am anfang eine 0 //eingegeben hat, dann ist der zähler nämlich auf 0 und über 0 elemente können wir keinen durchschnitt //oder so bilden, sollte das der fall sein sagen wir dass wir keine eingabedaten haben und mit return //beenden wir die main() funktion und somit das programm if(i == 0) { cout << "Keine Zahlen eingegeben"; return; } //und wenn wir hier sind dann ist i mindestens 1 float average; float median; float deviation; average = Average(numbers, i); median = Median(numbers, i); deviation = Deviation(numbers, i); cout << "\n\nDurchschnitt: " << average << "\nMedian: " << median << "\nStandardabweichung: " << deviation << "\n"; } //so und da definieren wir erstmal die durchschnittsfunktion float Average(const int aNumbers[], const int aNumbersToProcess) { float average = 0; //was die for schleife hier macht sollte jetzt klar sein //aber halt nochmal zur wiederholung, wir fangen bei 0 an //machen solange weiter bis wir den wert erreicht haben der //in aNumbersToProcess drin steht und i wird _nach_ jedem //schleifendurchlauf um 1 erhöht, was noch anzumerken ist //vorher haben wir int i; deklariert und in der schleife //geschrieben for(i = 0; ...) jetzt schreiben wir direkt //for(int i = 0; ...) das heißt wir definieren i in der for //schleife, der clou dabei ist dass sobald die for schleife //aus ist, der compiler das i nicht mehr kennt, es ist wenn //wir es in dem for mit for(int i = 0; ..) definieren nur innerhlab //der for schleife gültig.. k for(int i=0; i<aNumbersToProcess; i++) { //wir missbrauchen die variable für den durchschnitt erstmal um //die summe über alle elemente aus aNumbers zu bilden, falls ihr //+= nicht kennt, es ist eine kurzschreibweise, wenn ich hab //x += y; heißt das x = x + y; ähnlich wie i++; gleich i = i + 1; ist //ich könnte natürlich auch schreiben i += 1; das ganze geht auch mit // -= *= und /= für minusrechnen, multiplizieren und das vierte, es gibt auch // ein -- für i--; also i = i - 1; nur zur ergänzung, allerdings gibt es kein ** //für i**; irgendwie... i = i²;... ok vergessen wir das mal, also hier bilden //wir die summe über alle elemente in aNumbers indem wir es in der schleife durchlaufen //und immer den wert drin drinsteht zu average dazuaddieren average += aNumbers[i]; } //jetzt wo wir fertig sind haben wir unsere summe über alle elemente die in average drin steht //so, angenommen unser array enthielt die elemente 1, 2, 3, 4, 5, 0, 0, 0, ... 0 //wieso sind da so viele nullen hinten dran?, wir dürfen nicht vergessen, das array ist immer //noch 50 integer lang, wir haben nach der 5 die eingabe mit 0 beendet aber dahinter stehen //trotzdem immer noch lauter 0llen, allerdings sagt uns aNumbersToProcess das wir als parameter //übergeben haben dass uns nur die ersten 5 elemente interessieren, also bilden wir einfach den //durchschnitt mit unserer kurzschreibweise average /= aNumbersToProcess; was heißt // average = average / aNumbersToProcess; average /= aNumbersToProcess; //ganz zum schluss geben wir den durchschnitt als rückgabewert der funktion zurück return average; } //und dann kommt der median, ich hab in wikipedia nageschaut da steht der median ist von nem //sortierten array einfach das mittlere element, und in eurer angabe steht es wird sortiert sein //also müssen wir einfach nur mehr die mitte rausfinden, so einfach? nein der haken ist bei // "1, 2, 3" ist es klar was die mitte ist und zwar 2, aber bei "1, 2, 3, 4" ist der median // (2 + 3) / 2 also der durchschnitt der mittleren beiden elemente, aber es ist trotzdem leicht float Median(const int aNumbers[], const int aNumbersToProcess) { //so und hier lernen wir nen neuen operator kennen falls ihr den nicht eh schon kennt % //der % (modulo) operator schaut wieviel rest zurückbleibt wenn ich eine zahl durch x teile //also 10 % 3 ergibt 1 (3*3 ist 9 und 1 rest auf 10), oder 50 % 26 ergibt 24 (26 geht in 50 1 mal //und es bleibt 24 rest, mit dem operator können wir also ganz einfach rausfinden ob wir ne richtige //mitte haben oder den druchschnitt über die 2 mittleren elemente bilden müssen, wenn ich nämlich //5 elemente habe und 5%2 rechne kommt 1 raus, dh die zahl ist ungerade, und bei 10%2 kommt 0 raus //also ist sie gerade //ist unsere zahl ungerade? if(aNumbersToProcess % 2 == 1) { //wenn ja dann sagen wir mal es sind 9 elemente, wir rechnen einfach 9 / 2, das ergibt 4.5, wir //lassen das 0.5 wegfallen und 4 ist unsere element in der mitte, hier das ganze grafisch untermalt //dabei nicht vergessen das ein array von 0 - n durchnumeriert wird und nicht von 1 bis n, und a-i //sind unsere elemente // 0 1 2 3 4 5 6 7 8 // a b d c e f g h i //wie lasse ich den rest wegfallen? ein int kann nur ganze zahlen speichern, wenn ich 9/2 rechne //wird nicht gerundet sondern die nachkommastelle fällt immer weg //das hier kann vielleicht etwas verwirrend sein, also man könnte es in einzelschritte aufteilen /* int middle; middle = (int)(aNumbersToProcess/2); return aNumbers[middle]; */ //oder wir hauen es einfach gleich in das return statement rein, falls ihr das (int) nicht kennt, das //ist ein cast, ein cast wandelt einen variabentyp in einen anderen um, wenn wir 9 / 2 rechnen zb kommt //ein double dabei raus (nicht float, wenn ihr 5.323 schreibt ist es für den compiler ein double außer //ihr sagt was anderes), in c++ ist es egal weil der compiler das eh automatisch sieht dass ihr die 4.5 //einem int zuweist und er lässt die .5 wegfallen aber andere programmiersprachen wie c# meckern da zb //herum also hab ichs drin gelassen wegen typensicherheit blabla... schöner programmierstil, und da wir //integer in aNumbers haben casten wir auch auf nen float da der rückgabewert float ist return (float)aNumbers[(int)(aNumbersToProcess/2)]; } else { //und wenn wir eine gerade anzahl an elementen haben zb 4 ist das "zweite mittlere element" 4/2, also //element 2, das c, und das erste mittlere element 4/2 - 1, also das b // 0 1 2 3 // a b c d //wenn wir uns das überlegen geht das auch immer, 6 elemente, das erste mittlere ist 6/2 - 1 = 2 und das //zweite 6/2 = 3, also in dem fall wäre element 2 die 4 und element 3 die 6, und der median ist (4+6) / 2 // 0 1 2 3 4 5 // 1 2 4 6 9 9 //weil wir nicht das nicht wieder in 10 zeilen schreiben wollen packen wir alles gleich in eine //aber zur veranschaulichung, es ist im prinzip das /*int middleElement1Position = aNumbersToProcess/2 - 1; int middleElement2Position = aNumbersToProcess/2; int middleElement1 = aNumbers[middleElement1Position]; int middleElement2 = aNumbers[middleElement2Position]; float median = (float) ( (middleElement1 + middleElement2) / 2 ); return median; */ return (float)( (aNumbers[aNumbersToProcess/2 - 1] + aNumbers[aNumbersToProcess/2]) / 2 ); } } //ok und als aller letztes die standardabweichung... ja... ok google sagt //"standardabweichung: die summe aller quadrierten abweichungen der einzelnen //messerwerte vom mittelwert, dividiert durch die anzahl der messwerte, ergibt //die variaz (aha die variaz.. ok), die standardabweichung ist die pos wurzel der //variaz //so toll, da brauchen wir also wurzeln und so, aber es ist trotzdem nicht schwer float Deviation(const int aNumbers[], const int aNumbersToProcess) { float variance = 0; //so, zuerst müssen wir die summe aller quadrierten abweichungen bilden, also bevor //wir anfangen kurz n beispiel so wie ich das verstanden habe, wenn unsere elemente //1, 2, 3, 4, 5 sind dann ist der durchschnitt (1+2+3+4+5)/5 = 3, die varianz ist // ( (1-3)² + (2-3)² + (3-3)² + (4-3)³ + (5-3)² ) / 5, und die standardabweichung ist //dann die wurzel aus der varianz, also zuerst rechnen wir uns den durchschnitt aus //was wir ja von unserer durchschnittfunktion übernehmen lassen können //wir definieren einfach ne neue variable wo wir den durchschnitt reinspeichern, der //rückgabe wert von Average ist einfach ein float mit dem durchschnitt deswegen können //wir das einfach so schreiben als wenn die funktion ein wert wäre, in wirklichkeit //wird die funktion ausgeführt und der rückgabewert wird dann average zugewiesen float average = Average(aNumbers, aNumbersToProcess); //jetzt wo wir den durchschnitt haben bilden wir die varianz for(int i=0; i<aNumbersToProcess; i++) { //so, das ganze += und for zeug kennen wir bereits, pow ist jetzt eine funktion //die in der math.h drin ist und wir verwenden sie genauso wie printf zb, der //erste parameter ist die zahl selbst, und der zweite die potenz, wir wollen //(aNumbers[i] - average) also die abweichung quadrieren also ist das der erste //parameter, der zweite ist 2 weil wir es hoch 2 nehmen wollen, wir könnten natürlich //auch schreiben variance += (aNumbers[i] - average) * (aNumbers[i] - average); aber //wenn sich schon jemand anders die mühe gemacht hat die pow funktion zu schreiben //benutzen wir sie gleich, und wir casten den ersten parameter der fkt auf einen float //da wenn wir aNumbers[i] (ist ein int) - average (ist ein float) rechnen kommt glaube ich //dabei ein double raus, bin mir aber nicht sicher und pow gibt wenn es (double, int) //reinbekommt nen double zurück, wir könenn also entweder //variance += (float)pow((aNumbers[i] - average), 2); schreiben wo wir den double rückgabe //wert auf float zurückcasten oder wir casten gleich den ersten parameter auf nen float //ich hoffe ich erzähle hir keinen mist weil ich mir nicht sicher bin ob ein int - float nen //double ergibt... aber wie gesagt ist es eigentlich egal weil das in c++ sowieso alles //automatisch geht, aber trotzdem, typensicherheit, hoffe das mit dem casten verwirrt nicht so variance += pow((float)(aNumbers[i] - average), 2); } //jetzt müssen wir wie in der angabe von dem varianz zeug den durchschnitt über die abweichungen //bilden also dividieren wir die summe der abweichungen durch die anzahl der elemente variance /= aNumbersToProcess; //und am ende hepp, geben wir die wurzel aus der varianz zurück, casten den rückgabewert hier nicht //weil die qrt funktion wenn sie nen float reinbekommt und variance ist ja ein float auch nen float //rausspuckt, bei pow haben wir als ersten parameter double übergeben und als zweiten einen int, weil //wir gerechnet haben (aNumbers[i] - average) numbers ist ein int und average ein float aber wenn return sqrt(variance); }
achja, und ich wollte euch noch fragen in welchem semester ihr seid und was ihr studiert
wir machen nämlich in eprog 1 semester wo es ja für alle informatik studien gleich ist java und ich würde eigentlich
auch viel lieber c++ machen und das ist ja das informatik studien forum für eprog etc oder bin ich hier falsch?! -
achja, und ich wollte euch noch fragen in welchem semester ihr seid und was ihr studiert
wir machen nämlich in eprog 1 semester wo es ja für alle informatik studien gleich ist java und ich würde eigentlich
auch viel lieber c++ machen und das ist ja das informatik studien forum für eprog etc oder bin ich hier falsch?!studierst du auf der univie: c(++)
studierst du auf der tu: java -
was dieses siebdings sein soll
Unterstufenstoff. -
Geht's hier um "Einführung in die Programmierung, PR" an der Uni Wien?
Wenn ja, dann verschieb ich das dort hin. -
naja es ist ja ganz oben eher eine allgemeine c++ frage
-
ein hash ist ein code der bestimmte daten eindeutig identifizieren soll
hmm.. ich weiß nicht, ob du es so gemeint hast, aber für mich kommt deine formulierung etwas missverständlich herüber.
ein hash-wert ist nicht eindeutig, sondern mehrdeutig. es gibt mehrere inputs, die sich auf ein und denselben hash-wert abbilden lassen. daher kann man einen string, ein file oder einen anderen input nicht an seinem hash-wert identifizieren.hash-werte können dazu genutzt werden die suche nach werten zu beschleunigen, oder datenübertragungsfehler aufzuspüren oder passwörter mehr oder weniger sicher abzuspeichern.
wie hashing funktioniert steht unter anderem hier:
http://en.wikipedia.org/wiki/Hash_functionund zu md5 steht auch etwas:
http://en.wikipedia.org/wiki/Md5 -
ein hash-wert ist nicht eindeutig, sondern mehrdeutig. es gibt mehrere inputs, die sich auf ein und denselben hash-wert abbilden lassen. daher kann man einen string, ein file oder einen anderen input nicht an seinem hash-wert identifizieren.hash-werte können dazu genutzt werden die suche nach werten zu beschleunigen, oder datenübertragungsfehler aufzuspüren oder passwörter mehr oder weniger sicher abzuspeichern.
äh.. ist nicht genau das der punkt bei hashes, dass es keine 2 inputs gibt die denselben hash ergeben, das ist ja der sinn davon
"daher kann man einen string etc nicht an seinem hash wert identifizieren" und nen absatz darauf steht da dass passwörter so sicher abgespeichert werden können
wozu sollte ich ein passwort als hash abspeichern wenn ich
a) ein zweites passwort oder mehrere passwörter hätte die denselben hash ergeben
b) ich das referenzpasswort nicht identifizieren könnte am hashdrum geht es doch überhaupt zb beim CHAP protokoll, der server hat die passworter abgespeichert, er schickt mir ne challenge die ich zum hashen meines pws verwende, verschicke das gehashte pw und der server hasht das pw was er in der datenbank hat ebenfalls mit der challenge und vergleich die hashes
wenn jemand die challenge und den hash mitgesnifft haben sollte nützt ihm das nix weil er den hash nicht rückgängig machen kannalso inwiefern kann man eine datenmenge nicht am hash identifizieren? man hasht sie einfach nochmal und vergleicht die 2 hashes und hat sie identifiziert, man muss nur wissen mit welchem hash algorithmus
---
ich verstehe nicht wieso man an der normalen uni c++ macht und an der tu java.. was ist da der hintergrundgedanke dabei wenn es sowieso derselbe stoff ist ca?
-
äh.. ist nicht genau das der punkt bei hashes, dass es keine 2 inputs gibt die denselben hash ergeben, das ist ja der sinn davon
Nein. Wie auch? Ein MD5-Hash enthält 128 Bits, es gibt also nur 2^128 unterschiedliche Hash-Werte. Wenn ich 2^128 + 1 unterschiedliche Dokumente mit MD5 hashe, müssen zumindest zwei verschiedene den selben Hash-Wert erhalten. (Das bitte als Gedankenexperiment verstehen, ich weiß, daß 2^128 eine sehr große Zahl ist.)Zitat"daher kann man einen string etc nicht an seinem hash wert identifizieren" und nen absatz darauf steht da dass passwörter so sicher abgespeichert werden können
Die Idee bei der Speicherung von Passwörtern als Hash ist, daß erstens das Passwort aus dem Hash nicht in vertretbarer Zeit herausgefunden werden kann, und es zweitens aber mit sehr hoher Wahrscheinlichkeit nicht zu einer Kollision kommt, d.h. zu einem Fall, wo jemand ein falsches Passwort eingibt, das aufgrund des korrekten Hashwerts als richtig akzeptiert wird. Theoretisch möglich ist das aber schon.Hashing von Passwörtern funktioniert in der Praxis seit Jahrzehnten.
Zitatalso inwiefern kann man eine datenmenge nicht am hash identifizieren? man hasht sie einfach nochmal und vergleicht die 2 hashes und hat sie identifiziert, man muss nur wissen mit welchem hash algorithmus
Wie gesagt, das ist probabilistisch: Es ist sehr sehr unwahrscheinlich, daß man zwei unterschiedliche Datenmengen findet, die den selben Hashwert haben. Diese sehr geringe Wahrscheinlichkeit wird für die Praxis als "gut genug" befunden.Ansonsten gäbe es keinen Unterschied zwischen Hashing und Verschlüsselung, hmm?
Zitatich verstehe nicht wieso man an der normalen uni c++ macht und an der tu java.. was ist da der hintergrundgedanke dabei wenn es sowieso derselbe stoff ist ca?
Die Uni Wien kocht halt gern ihr eigenes Süppchen, die TU Wien kocht halt gern ihr eigenes Süppchen, das MIT machts mit Scheme als erster Sprache richtig, aber dort studieren wir halt nicht. -
äh.. ist nicht genau das der punkt bei hashes, dass es keine 2 inputs gibt die denselben hash ergeben, das ist ja der sinn davon
Überlegen wir uns das mal rein intuitiv: Ich lade mir ein CD-Image einer Linux-Distribution mit einer Größe von ungefähr 700 MB herunter. Um sicherzugehen, dass die Datei korrekt übertragen wurde, vergleiche ich die MD5-Summe, die auf der Downloadseite angegeben ist, mit der MD5-Summe, die ich aus dem CD-Image berechne.
Und jetzt überlege mal: Wie viele Möglichkeiten gibt es, 700*10[h]24[/h] Bytes anzuordnen? Jedes Byte kann 256 verschiedene Werte annehmen, also erhalten wir nach Adam Riese 256[h]700*10[h]24[/h][/h] verschiedene Möglichkeiten.
Der MD5-Hashwert ist 128 Bit lang, da hab ich 2[h]128[/h] unterschiedliche Werte, die auftreten können. Das ist etwas weniger als die oben bestimmte Anzahl der Anordnungen der Bytes eines CD-Images. Es ist daher unumgänglich, dass bei der Berechnung der MD5-Summe Kollisionen auftreten, d.h., die Hashfunktion mehrere Eingangswerte auf denselben Ausgangswert abbildet.
Das Interessante an MD5 ist jedoch, dass eine geringfügige Änderung des Funktionsparameters den Hashwert komplett anders aussehen lässt. Wenn also in dem CD-Image irgendwo ein einzelnes Bit umfällt, erkenne ich das sofort am MD5-Hash. Dass genau jene Bits umfallen, die dazu führen, dass ich trotz der Fehler denselben Hashwert erhalte, ist _sehr_ unwahrscheinlich.
Das ist jedoch nicht eigentliche Sinn von Hashing. Hashfunktionen werden für Datenstrukturen eingesetzt, wo ich Werte speichern möchte, die ich an Hand ihres Hashwertes referenzieren kann. Das erfolgt der von dir bereits erwähnten Hashtabelle, in der in die Zeile des Hashwertes der zu speichernde Wert eingetragen wird. Eine Hashfunktion ist jedoch grundsätzlich nicht bijektiv, man rechnet stets damit, dass Kollisionen auftreten. Für den Umgang mit diesen gibt es jedoch eine Reihe von Verfahren. Ich will an dieser Stelle jedoch nicht näher darauf eingehen - ich nehme an, du hast Algodat1 noch nicht gemacht; dort wirst du das dann im Detail lernen.
"daher kann man einen string etc nicht an seinem hash wert identifizieren" und nen absatz darauf steht da dass passwörter so sicher abgespeichert werden können
Passwörter sind um vieles kürzer als die oben erwähnten CD-Images, daher ist die Wahrscheinlichkeit von Kollisionen um vieles geringer, jedoch vorhnaden.
wozu sollte ich ein passwort als hash abspeichern wenn ich
a) ein zweites passwort oder mehrere passwörter hätte die denselben hash ergebenDas ist unwahrscheinlich, siehe oben.
b) ich das referenzpasswort nicht identifizieren könnte am hash
Der Punkt an einer Hashfunktion ist jener, dass sie nicht umkehrbar ist. Wenn du die MD5-Summe eines Passworts kennst, kennst du das Passwort selbst nicht. Du kannst aber überprüfen, ob es sich um den MD5-Hash eines bestimmten eingegebenen Passworts handelt, indem du die MD5-Hashfunktion auf die Eingabe anwendest und die beiden Hashwerte vergleichst - die müssen gleich sein. Es ist nicht möglich, aus dem MD5-Hash das Passwort zu rekonstruieren (du kannst ledigliche vollständige Enumeration über alle möglichen Passwörter anwenden, aber das ist nicht gerade effizient).
Ein weiterer Punkt, der von Wings-of-Glory angesprochen wurde und der Grund für den Einsatz von Hashes beim Speichern von Passwörtern ist, ist jener, dass niemand das Passwort kennt - außer demjenigen, der sich mit dem Passwort authentifiziert. Sonst braucht es auch niemand zu kennen - kein Administrator und auch sonst keiner.
ich verstehe nicht wieso man an der normalen uni c++ macht und an der tu java.. was ist da der hintergrundgedanke dabei wenn es sowieso derselbe stoff ist ca?
Ob du an der "normalen" Uni C++ machst und an der "abnormalen" Uni Java, ist Geschmackssache. Es geht bei den Lehrveranstaltungen beider Unis weniger darum, eine bestimmte Programmiersprache zu lernen, sondern mehr darum, _überhaupt_ Programmieren zu lernen. Auch wenn zwischen den Programmiersprachen vielleicht Welten dazwischen liegen, wenn du bereits eine prozedurale/objektorientierte Programmiersprache gelernt hast, tust du dir viel leichter, eine weitere zu erlernen - die Grundkonzepte bleiben immer dieselben.
Jetzt mitmachen!
Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!