Beiträge von Tion

    Würde eventuell noch ein bisschen mehr Sicherheit einbauen in Deine Queries. Aber sonst sieht es schonmal sehr gut aus ;)
    Weiterhin wünsch ich Dir viel Erfolg ;)

    Ich hatte ja geschriebe, dass das schematisch ist :D
    Ich überprüfe alle Werte natürlich, bevor ich sie in Querys einbaue :D


    Aber danke ;)

    Okay, noch mal eindeutig klären :D

    • Die Zugriffe auf das Spiel waren zu groß
    • Die Zugriffe auf die Datenbank (Accounts, Notifications, Forum, ...) war zu groß
    • Der Datenbankserver war überlastet
    • Wir wurden gesperrt
    • Wir sind auf meinen vServer umgezogen
    • Der vServer ist unterfordert


    Wie man sieht, nicht mal ein load von 0,2 und die CPU dadelt bei nicht mal 20% rum :D


    Und bevor es heißt, ich würde unsauber auf die DB zugreifen, genau das tue ich nicht, sondern benutze verknüpfte Statements

    Spoiler anzeigen
    Wie ich es nicht mache:

    PHP
    SELECT * FROM categories WHERE id = %d$query = mysql_query()if(mysql_num_rows()){  $categorie = mysql_fetch_assoc($query);  SELECT * FROM threads WHERE id = %d  $query = mysql_query($sql);  if(mysql_num_rows())  {    $thread = mysql_fetch_assoc($query);    echo Du bist hier: $categorie['name'] > $thread['name'];  }}

    Spoiler anzeigen
    Wie ich es mache:

    PHP
    SELECT categorie.name AS `categorie`, threads.name AS `thread` FROM categories, threds  WHERE categorie.id = thread.categorie AND thread.id = %s$query = mysql_query();if(mysql_num_rows()){  $stats = mysql_fetch_assoc($query);  echo Du bist hier: $categorie['categorie'] > $thread['thread'];}

    Es gab gerade einen heftigen Börsencrash, nachdem @Mr.Toast mir geraten hat, in Aktien zu investieren X(


    @Mr.Toast, dafür sende ich deinem Clan eine Kriegserklärung :P

    Ach ja, ich glaube, ich habe es hier noch nicht angesprochen, aber ihr könnt jetzt auch das Design wechseln :O


    Zur Auswahl stehen einfach das Retro-Design oder ein noch hässlicheres anderes, wenn meine 3 Leute fertig sind, bekommt ihr noch 3 weitere :thumbup:

    Ist ein vServer von Alvotech.de

    Jep, und die Techniker antworten mir nicht X(
    Habe -selbst als Root- keinen Zugriff auf Datum & Uhrzeit :/


    Formeln versuche ich, so viel wie es geht, geheim zu halten, damit ihr bald nicht alle mit dem Taschenrechner vor dem Computer/Handy hockt ^^

    Liegt daran, dass der Zertifikat nicht richtig installiert ist, und ich bei FB die alte DB nutze...
    Musst du einfach bestätigen, stimmt eigentlich ;)

    //Edit2: Danke Mr.Tion, 37 Yen -....- von 25.000 -.-

    Ingame heiße ich nur "Tion"...
    37 Yen nur ? Ich meine, der Hack vorher waren etwa 13k... Oder warst das nicht du ? ^^


    Ja, aber dazu muss ich doch die IP kennen oder nicht ? Weil wenn ich scan mache dann muss
    ich eine IP eingeben ...

    Nein, bei scan musst du ein Subnetz eingeben, dass du rätst.
    So kannst du z.B. "scan 127.0.0.*" eingeben, und er zählt bei den * immer höher, guckt ob die IP existiert und gibt ja/nein zurück.
    Wenn dein Script hoch genug ist, kannst du auch "scan 127.*.*.*" eingeben, und er findet alle IP's, die mit 127 anfangen.


    In dem Code selber zählt er nicht hoch, das war ein Beispiel ;)


    Konsole geht nicht bei mir Error Hash Session, oder so ähnlich ;(

    Wenn es "ERR_WRONG_SESSION_HASHSUM" ist, lade mal die gesammte Seite neu ;)

    Hey Leute,


    sicherlich kennt der eine oder andere Webentwickler das Problem, dass man eine Software entwickelt hat und sie ausgeben möchte, jedoch meistens keine Lust hat, dass alle sich aus dem Sourcecode bedienen.
    In den letzten Tagen habe ich mich mal an Code-Obfuscation gemacht, was in etwa das "verschleiern von Code" ist. Das bedeutet, dass er für Menschen nur noch sehr schwer zu lesen ist - als Beispiel habe ich mal eine Klasse genommen und sie verschleiert:

    PHP
    // WICHTIGE ANMERKUNG - In dem echten obfuscierten Text steht PHP-Code in 1 Zeile, aus übersichtsgründen ist das hier jetzt eingerückt.<?phpclass c2690851a1 {    private  $v317d37b0e = null;    private  $vcf1e8c14e = null;    private  $v901555fb0 = null;    public  function __construct($vcf1e8c14e, $v901555fb0=7777 ) {        $this-&gt;        vcf1e8c14e = $vcf1e8c14e;        $this-&gt;        v901555fb0 = $v901555fb0;        $this-&gt;        v317d37b0e = fsockopen("udp://" .$this-&gt;        vcf1e8c14e, $this-&gt;        v901555fb0, $v8f90f2980, $vfa5389291, 2 );        socket_set_timeout($this-&gt;        v317d37b0e, 2 );    }    public  function fbced893c4() {        @fwrite($this-&gt;        v317d37b0e, $this-&gt;        feb5c2d1d1("i" ));        fread($this-&gt;        v317d37b0e, 11 );        $v2d5e1b562 = array ();        $v2d5e1b562['password' ] = (integer)  ord(fread($this-&gt;        v317d37b0e, 1 ));        $v2d5e1b562['players' ] = (integer)  $this-&gt;        f9f7fa7b15(fread($this-&gt;        v317d37b0e, 2 ));        $v2d5e1b562['maxplayers' ] = (integer)  $this-&gt;        f9f7fa7b15(fread($this-&gt;        v317d37b0e, 2 ));        $ve1b5fe1db = ord(fread($this-&gt;        v317d37b0e, 4 ));        if (!$ve1b5fe1db) return  -1 ;        $v2d5e1b562['hostname' ] = (string)  fread($this-&gt;        v317d37b0e, $ve1b5fe1db);        $ve1b5fe1db = ord(fread($this-&gt;        v317d37b0e, 4 ));        $v2d5e1b562['gamemode' ] = (string)  fread($this-&gt;        v317d37b0e, $ve1b5fe1db);        $ve1b5fe1db = ord(fread($this-&gt;        v317d37b0e, 4 ));        $v2d5e1b562['map' ] = (string)  fread($this-&gt;        v317d37b0e, $ve1b5fe1db);        return  $v2d5e1b562;    }    public  function f8949d0673() {        @fwrite($this-&gt;        v317d37b0e, $this-&gt;        feb5c2d1d1("c" ));        fread($this-&gt;        v317d37b0e, 11 );        $v17f1559ab = ord(fread($this-&gt;        v317d37b0e, 2 ));        $va2bbabfe7 = array ();        if ($v17f1559ab &gt;        0 ) {            for ($v865c0c0b4 = 0 ;            $v865c0c0b4 &lt;            $v17f1559ab;            ++ $v865c0c0b4) {                $ve1b5fe1db = ord(fread($this-&gt;                v317d37b0e, 1 ));                $va2bbabfe7[$v865c0c0b4] = array  ( "name"  =&gt;                (string)  fread($this-&gt;                v317d37b0e, $ve1b5fe1db), "score"  =&gt;                (integer)  $this-&gt;                f9f7fa7b15(fread($this-&gt;                v317d37b0e, 4 )), );            }        }        return  $va2bbabfe7;    }    public  function ff1133985a() {        @fwrite($this-&gt;        v317d37b0e, $this-&gt;        feb5c2d1d1("d" ));        fread($this-&gt;        v317d37b0e, 11 );        $v17f1559ab = ord(fread($this-&gt;        v317d37b0e, 2 ));        $va2bbabfe7 = array ();        for ($v865c0c0b4 = 0 ;        $v865c0c0b4 &lt;        $v17f1559ab;        ++ $v865c0c0b4) {            $v912af0dff['playerid' ] = (integer)  ord(fread($this-&gt;            v317d37b0e, 1 ));            $ve1b5fe1db = ord(fread($this-&gt;            v317d37b0e, 1 ));            $v912af0dff['nickname' ] = (string)  fread($this-&gt;            v317d37b0e, $ve1b5fe1db);            $v912af0dff['score' ] = (integer)  $this-&gt;            f9f7fa7b15(fread($this-&gt;            v317d37b0e, 4 ));            $v912af0dff['ping' ] = (integer)  $this-&gt;            f9f7fa7b15(fread($this-&gt;            v317d37b0e, 4 ));            $va2bbabfe7[$v865c0c0b4] = $v912af0dff;            unset ($v912af0dff);        }        return  $va2bbabfe7;    }    public  function fb62d56475() {        @fwrite($this-&gt;        v317d37b0e, $this-&gt;        feb5c2d1d1("r" ));        fread($this-&gt;        v317d37b0e, 11 );        $vca703ee63 = ord(fread($this-&gt;        v317d37b0e, 2 ));        $va4f86f7bf = array ();        for ($v865c0c0b4 = 0 ;        $v865c0c0b4&lt;        $vca703ee63;        ++ $v865c0c0b4) {            $ve1b5fe1db = ord(fread($this-&gt;            v317d37b0e, 1 ));            $v981c1e7b3 = (string)  fread($this-&gt;            v317d37b0e, $ve1b5fe1db);            $ve1b5fe1db = ord(fread($this-&gt;            v317d37b0e, 1 ));            $va4f86f7bf[$v981c1e7b3] = (string)  fread($this-&gt;            v317d37b0e, $ve1b5fe1db);        }        return  $va4f86f7bf;    }    public  function f213ecff1a() {        $vdf911f015 = 0 ;        $vceb172632 = microtime(true);        @fwrite($this-&gt;        v317d37b0e, $this-&gt;        feb5c2d1d1("r" ));        fread($this-&gt;        v317d37b0e, 15 );        $va745d640f = microtime(true);        $vdf911f015 = ($va745d640f - $vceb172632) * 1000 ;        return  round($vdf911f015);    }    private  function f9f7fa7b15($vb45cffe08) {        if ($vb45cffe08 ===  "" ) {            return  null;        }        $vfa7153f7e = 0 ;        $vfa7153f7e +=  (ord($vb45cffe08[0 ]));        if (isset ($vb45cffe08[1 ])) {            $vfa7153f7e +=  (ord($vb45cffe08[1 ]) &lt;            &lt;            8 );        }        if (isset ($vb45cffe08[2 ])) {            $vfa7153f7e +=  (ord($vb45cffe08[2 ]) &lt;            &lt;            16 );        }        if (isset ($vb45cffe08[3 ])) {            $vfa7153f7e +=  (ord($vb45cffe08[3 ]) &lt;            &lt;            24 );        }        if ($vfa7153f7e &gt;        =  4294967294 ) {            $vfa7153f7e -=  4294967296 ;        }        return  $vfa7153f7e;    }    private  function feb5c2d1d1($v599dcce29) {        $v9c509e44d = "SAMP" ;        $v9c509e44d .=  chr(strtok($this-&gt;        vcf1e8c14e, "." ));        $v9c509e44d .=  chr(strtok("." ));        $v9c509e44d .=  chr(strtok("." ));        $v9c509e44d .=  chr(strtok("." ));        $v9c509e44d .=  chr($this-&gt;        v901555fb0 & 0xFF );        $v9c509e44d .=  chr($this-&gt;        v901555fb0 &gt;        &gt;        8  & 0xFF );        $v9c509e44d .=  $v599dcce29;        return  $v9c509e44d;    }    public  function fb640a0ce4() {        $v06aa6fa8b = false;        fwrite($this-&gt;        v317d37b0e, $this-&gt;        feb5c2d1d1("p0101" ));        if (fread($this-&gt;        v317d37b0e, 10 )) {            if (fread($this-&gt;            v317d37b0e, 5 ) ==  'p0101' ) {                $v06aa6fa8b = true;            }        }        return  $v06aa6fa8b;    }    public  function f716f6b305() {        @fclose($this-&gt;        v317d37b0e);    }}

    Wer jetzt auf Anhieb errät, was die Klasse macht, ist gut :P
    Wer nicht, für den ist sie hier noch mal:

    PHP
    <?php/** * * @author Edward McKnight (EM-Creations.co.uk) *//* *****************************************************************// SampQuery.class.php// Version 1.0// This class connects to a specific SA-MP server via sockets.// Copyright 2012 Edward McKnight (EM-Creations.co.uk)// Creative Commons Attribution-NoDerivs 3.0 Unported License// http://creativecommons.org/licenses/by-nd/3.0/// Credits to Westie for the original PHP SA-MP API and inspiration for this API.* *****************************************************************/$query = new SampQuery("server.life-of-german.org", 7777);if($query->connect())  echo'Server online';else  echo'Server offline';class SampQuery {    private $sock = null;    private $server = null;    private $port = null;    /**    *	Creates a new SampQuery object.    *	@param $server server hostname    *	@param $port port of the server    */    public function __construct($server, $port=7777)    {        $this->server = $server;        $this->port = $port;        $this->sock = fsockopen("udp://".$this->server, $this->port, $errorNum, $errorString, 2);        socket_set_timeout($this->sock, 2);    }    /**    * Returns an array of server information.     * @return Array[]    * (    *   [password] => 0 or 1    *   [players] => players    *   [maxplayers] => maxPlayers    *   [hostname] => hostName    *   [gamemode] => gamemode    *   [map] => map    * )    */    public function getInfo() {        @fwrite($this->sock, $this->assemblePacket("i"));        fread($this->sock, 11);        $serverInfo = array();        $serverInfo['password'] = (integer) ord(fread($this->sock, 1));        $serverInfo['players'] = (integer) $this->toInt(fread($this->sock, 2));        $serverInfo['maxplayers'] = (integer) $this->toInt(fread($this->sock, 2));        $strLen = ord(fread($this->sock, 4));        if(!$strLen) return -1;        $serverInfo['hostname'] = (string) fread($this->sock, $strLen);        $strLen = ord(fread($this->sock, 4));        $serverInfo['gamemode'] = (string) fread($this->sock, $strLen);        $strLen = ord(fread($this->sock, 4));        $serverInfo['map'] = (string) fread($this->sock, $strLen);        return $serverInfo;    }    /**    * Returns a multidimensional array of basic player information.    * @return Array[]    * (    *   [0] => Array[]    *       (    *           [name] => playerName    *           [score] => score    *       )    *	...    * )    * @see getDetailedPlayers()    */    public function getBasicPlayers() {        @fwrite($this->sock, $this->assemblePacket("c"));        fread($this->sock, 11);        $playerCount = ord(fread($this->sock, 2));        $players = array();        if($playerCount > 0) {            for($i = 0; $i < $playerCount; ++$i) {                $strLen = ord(fread($this->sock, 1));                $players[$i] = array                (                    "name" => (string) fread($this->sock, $strLen),                    "score" => (integer) $this->toInt(fread($this->sock, 4)),                );            }        }        return $players;    }    /**    * Returns a multidimensional array of detailed player information.     * @return Array[]    * (    *   [0] => Array    *	(    *       [playerid] => playerid    *       [nickname] => playername    *       [score] => score    *       [ping] => pinh    *	)    *   ...     * )    * @see getBasicPlayers()    */    public function getDetailedPlayers() {        @fwrite($this->sock, $this->assemblePacket("d"));        fread($this->sock, 11);        $playerCount = ord(fread($this->sock, 2));        $players = array();        for($i = 0; $i < $playerCount; ++$i) {            $player['playerid'] = (integer) ord(fread($this->sock, 1));            $strLen = ord(fread($this->sock, 1));            $player['nickname'] = (string) fread($this->sock, $strLen);            $player['score'] = (integer) $this->toInt(fread($this->sock, 4));            $player['ping'] = (integer) $this->toInt(fread($this->sock, 4));            $players[$i] = $player;            unset($player);        }        return $players;    }    /**    * Returns an array of server rules.    * @return Array[]    * (    *   [gravity] => gravity    *   [mapname] => map    *   [version] => version    *   [weather] => weather    *   [weburl] => weburl    *   [worldtime] => worldtime    * )    */    public function getRules() {        @fwrite($this->sock, $this->assemblePacket("r"));        fread($this->sock, 11);        $ruleCount = ord(fread($this->sock, 2));        $rules = array();        for($i = 0; $i< $ruleCount; ++$i) {            $strLen = ord(fread($this->sock, 1));            $rule = (string) fread($this->sock, $strLen);            $strLen = ord(fread($this->sock, 1));            $rules[$rule] = (string) fread($this->sock, $strLen);        }        return $rules;    }    /**    * Returns the server's ping.    * @return integer    */    public function getPing() {        $ping = 0;        $beforeSend = microtime(true);        @fwrite($this->sock, $this->assemblePacket("r"));        fread($this->sock, 15);        $afterReceive = microtime(true);        $ping = ($afterReceive - $beforeSend) * 1000;        return round($ping);    }    private function toInt($string) {        if($string === "") {            return null;        }        $int = 0;        $int += (ord($string[0]));        if(isset($string[1])) {            $int += (ord($string[1]) << 8);        }        if(isset($string[2])) {            $int += (ord($string[2]) << 16);        }        if(isset($string[3])) {            $int += (ord($string[3]) << 24);        }        if($int >= 4294967294) {            $int -= 4294967296;        }        return $int;    }    private function assemblePacket($type) {        $packet = "SAMP";        $packet .= chr(strtok($this->server, "."));        $packet .= chr(strtok("."));        $packet .= chr(strtok("."));        $packet .= chr(strtok("."));        $packet .= chr($this->port & 0xFF);        $packet .= chr($this->port >> 8 & 0xFF);        $packet .= $type;        return $packet;    }    /**    * Attempts to connect to the server and returns whether it was successful.    * @return boolean    */    public function connect() {        $connected = false;        fwrite($this->sock, $this->assemblePacket("p0101"));        if(fread($this->sock, 10)) {            if(fread($this->sock, 5) == 'p0101') {                $connected = true;            }        }        return $connected;    }    /**    * Closes the connection    */    public function close() {        @fclose($this->sock);    }}

    Das beste daran ist, dass das Script / die Webseite dadurch nicht langsamer und die Dateien kleiner wird - ersteres, weil ja nur alle Variablen und Funktionen umbenannt werden, zweiteres, weil Kommentare und unnötiger Whitespace ( wie Einrückungen ) verschwinden.
    Die SAMP-Query API wurde von 7.122 Bytes auf 4564 Bytes "gschrumpft" ( alleine wegen der Kommentare :O und dem Whitespace ).
    Der Text lässt sich nicht automatisiert zurückverschlüsseln... Und das Nachvollziehen der Datei oben währe wohl sehr schwer gewesen, wenn ihr sie nicht "SampQueryAPI" nennt ;)


    URL zum Obfuscator: https://apps.tionsys.de/encode/


    Wer mir nicht traut, darf gerne auch die halb-offline-Version aus Java benutzen :)
    Sie ist aber noch Alpha und ich konnte sie noch nicht ausreichend testen - deswegen bitte ich euch, Bugs zu berichten ;)
    Update: Die Beta-Version hat nun auch einen Dialog und unterstützt Multi-Threading, was das ganze noch etwas schneller macht.
    Auch kann er nebenbei den CSS-Code etwas "schrumpfen" & verschleiern, indem Kommentare und Whitespace entfernt werden.
    Erlaubnis von Trooper, den Source-Code unter Verschluss zu halten ;)


    Bitte feedbacken, aber nicht trollen - und wer sagt, Ioncube ist besser, dem gebe ich eine Kopfnuss :thumbup:

    Hey Leute,


    ich wollte euch ganz kurz in die Basics der Kryptologie einführen, da scheinbar einige das mit den Passwörtern noch nicht verstanden haben ^^


    Erst einmal klären wir ein paar Fachbegriffe:


    Einwegfunktionen
    Eine "echte" Einwegfunktion verändert einen Wert und lässt ihn (offiziell) nicht wieder zurückrechnen
    Ein (schlechtes) Beispiel ist z.B.

    Code
    neuerwert = (alterwert * 2) ^ (alterwert / 5)

    Aus dem alten Wert lässt sich ruck-zuck ein neuer Wert berechnen, anders herum kann es zu Schwierigkeiten kommen und man müsste mit Raten anfangen...
    Für die, die mir nicht glauben: neuerwert = 4,3125 Wer das zurückrechnet, dem schicke ich per Post einen Lollie :D


    Einwegfunktionen mit Falltür In diesem Beispiel: Public-Key-Verfahren
    Nun gibt es einige Einwegfunktionen, die man doch zurückrechnen kann, aber nicht so, wie man sie berechnet hat.
    Das mag jetzt kompliziert klingen (ist es auch), aber ich stelle das mal bildlich da, erkläre das dann danach:

    • Ihr habt eine Poststelle (o.ä.) an der jeder eine Eisenkasette hat
    • Wollt ihr etwas verschlüsseln, macht ihr die Kasette zu und lasst das Schloss einklicken.
    • Nun kann niemand mehr an den Inhalt rein (außer er nutzt Gewalt, aber wir gehen von netten Leuten aus)
    • Der, dem die Kassette gehört, geht nun in die Poststelle, öffnet die Kasette mit seinem Schlüssel und hat den Inhalt vorliegen


    Ein tägliches Beispiel davon, und genau davon, finden wir täglich: HTTP mit SSL ( https )
    Beim Public-Key-Verfahren gibt es einen Public-Key und einen Private-Key. Der Public-Key ist öffentlich bekannt und das Schloss der Kassette, der Private-Key der Schlüssel.


    Hash
    Ein Hash ist eine Einwegfunktion. Das bedeutet, man kann ihn nicht zurückberechnen, man kann aber "probieren"


    Salts ( Salz )
    Salts sind noch mal ein Aufsatz auf den Hash, weil dabei 2 "Passwörter" existieren - eines wird vom Server bei der ersten Erstellung des Accountes erstellt, das andere kommt von Benutzer.
    Dann werden beide aneinander gehängt und gehasht. Davon der Hash und der Salt werden gespeichert.
    Beispiel:

    Code
    Benutzerpasswort: helloworld
    Salt: kdbjyhbfdxkjyhxdbkjsf
    Vor dem Hash: helloworldkdbjyhbfdxkjyhxdbkjsf
    Gehasht: hdhggksdhfmkfudjdyuhglgfj

    Gespeichert wird der Salt und "Gehasht", dann wird das jedes mal neu zusammengesetzt.
    Der Vorteil von Salts liegt darin, dass ein (hoffentlich nicht) Hacker die Hash-Summen nicht einfach in einer großen Datenbank nachschlägt, da der gesaltete Hash von dem normalen Hash unterscheidet.


    Pepper ( Pfeffer )
    Der Pepper ist im Prinzip ein "globaler Salt", der für alle Accounts gleich ist und, genau wieder Salt, optional alleine oder in Verbindung mit ihm genutzt werden kann. Pfeffer und Salz ergänzen sich prima, da, sollte jemand Zugriff auf die Datenbank haben, er den Pepper nicht kennt, sollte er ihn aber kennen und in den Jahren vor dem Hack eine Datenbank mit dem Pepper angelegt haben über den Salt stolpert. Außerdem macht er den String vor dem Hashen noch etwas länger :whistling:


    Kollisionen
    Kollisionen existieren, wenn 2 Werte den selben Hash haben. Eine Beispiel-Kollision für MD5:

    Nun ist es sehr unwarscheinlich, dass ein anderer Benutzer just dieses Passwort hat, aber wenn man genug Zeit hat kann man zu eigentlich jeden Hash eine Kollision finden


    Verschlüsselung
    Eine Verschlüsselung ist kein Hash !
    Eine Verschlüsselung zeichnet sich dadurch aus, dass man sie wieder entschlüsseln kann - unterschieden wird dabei zwischen symetrisch und asymetrisch. Bei ersteres wird zum Ver- und Entschlüsseln das gleiche Passwort genutzt ( Beispiel: AES ), bei zweiteren sind die Passwörter unterschiedlich ( Beispiel: DES, Public-Key-Verfahren. Natürlich kann man das auch mischen, dass das Passwort asymetrisch gespeichert / gesendet wird und danach auf symetrische verfahren zugegriffen wird ( "Hybride Verschlüsselung" ) - der Vorteil liegt dabei daran, dass man nicht den Geschwindigkeitsverlust von dem asymetrischen Verschlüsselungsverfahren einbüßt, das Passwort sicher übertragen kann und die Verbindung danach auch noch sicher ist.


    Kodierungen
    Eine Kodierung unterscheidet sich von einer Verschlüsselung dadurch, dass die Kodierung kein Passwort hat. Als ein bekanntes Beispiel dient Base64 oder Caesar. Problematisch wird es u.a. bei der Rot-"Verschlüsselung", da dort theoretisch auch ein Passwort genutzt wird, es sich aber schnell erraten lässt - und das Caesar theoretisch auch nur Rot13 ist, könnte man es ja auch als Passwort einstufen :whistling:


    Wie realisiere ich jetzt einen sicheren Login ?

    • Der Benutzer registriert sich und gibt sein Passwort ein.
    • Wir generieren für das Passwort einen Salt und hashen das beides zusammen
    • Gesalteter Hash und Salt kommen in die Datei/Datenbank/...
    • Bei der Passwortabfrage hängen wir an das eingegebene Passwort wieder den Salt an
    • Jetzt hashen wir die zusammenstellung oben und vergleichen das mit dem gesaltenem Hash
    • Stimmt das überein, ist das Passwort richtig

    Als Hilfe dafür habe ich 2 Funktionen definiert (findet ihr gaaaaaanz unten), eine erzeugt einen Salt beliebiger Länge, die andere Hasht den Salt und das Passwort zu beliebiger Länge.
    Beispiel zur Nutzung: new salt[64];
    new pwhash[128];


    GenerateSalt(64, salt); // Wir erstellen einen zufälligen Salt für den Benutzer
    CreateSaltedHash(inputtext, salt, 128, pwhash); // Wir erstellen einen salted Hash des Passwortes ( inputtext <=> Passwort ) Wichtig ist, und das wiederhole ich jetzt noch einmal, dass der Salt mitgespeichert wird.
    Denn ein anderer Salt ergibt ein anderen Hash.
    Vergleichen können wir die Passwörter nun folgendermaßen: new pwhash[128];


    CreateSaltedHash(inputtext, PInfo[playerid][pSalt], 128, pwhash); // Wir erstellen einen salted Hash des Passwortes ( inputtext <=> Passwort )
    if(strcmp(PInfo[playerid][pSaltedHash], pwhash, false) == 0)
    SendClientMessage(playerid, 0xFF00FF, "Du hast dich eingeloggt");
    else
    SendClientMessage(playerid, 0xFFFF00, "Login falsch");


    MD5
    MD5 ist ein Algorithmus, der sich mittlerweile sehr durchgesetzt hat - wie alle anderen Hashfunktionen lässt auch er sich nicht wieder "zurückumwandeln", es ist aber auch hier möglich, den originalen Wert zu "erraten" ( dauert aber etwas ). MD5 gibt unabhängig von dem normalen Passwort einen 32 Byte langen String zurück der die Zeichen 0 - 9 und a - f / A - F hat.
    Hier findet ihr eine Include von Y-Less, mit der ihr MD5 in SA:MP umsetzen könnt. Empfohlen wird aber auch hier, einen Salt hinzuzuschalten, da es für MD5 wesentlich größere Datenbanken gibt. Ein Beispiel ohne Salt währe folgendes: new hash[32];
    hash = MD5_Hash("test"); Und mit dem Salt könnte man es wie folgt umsetzen: new salt[32];
    new password[20 + 32]; // 20 Zeichen + 32 Zeichen vom Salt
    new hash[32];
    GenerateSalt(32, salt);
    format(password, sizeof(password), "%s%s", inputtext, salt);
    hash = MD5_Hash(password); Bei beiden Beispielen haben wir dann in der variable "Hash" den Hash, den wir eintragen. Im Zewiten brauchen wir zusätzlich noch den Salt, den wir speichern ;)


    Auf der Basis meiner Salt- und Hashsysteme unten, die ich übrigens selber geschrieben habe (deswegen hat das auch so lange gedauert :cursing:) könnt ihr übrigens eure eigenen Hashsysteme basteln :)
    Dazu müsst ihr nur das Array erweitern und bei der CreateSaltedHash den 2.ten Operator der Modulorechnung anpassen ;)


    Ich hoffe, ich konnte euch der Passwortsicherheit ein Stücken näher bringen :)


    Tion


    Auch jetzt gilt, wie immer: Fragen sind zum Fragen da, Feedback ist erwünscht (heute auch mal negatives) und Ideen können eingebracht werden



    Hash- und Saltfunktion
    forward GenerateSalt(length, salt[]);
    public GenerateSalt(length, salt[])
    {
    new saltchars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    for(new i = 0; i < length - 1; i++)
    {
    salt[i] = saltchars[random(strlen(saltchars) - 2) + 1];
    }
    salt[length - 1] = 0;
    return true;
    }

    Hash- und Saltfunktion
    forward CreateSaltedHash(string[], salt[], length, dest[]);
    public CreateSaltedHash(string[], salt[], length, dest[])
    {
    new hashchars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

    new c1, c2;
    for(new i = 0; i < length - 1; i++)
    {
    if(c1 >= strlen(string) - 1) c1 = 0;
    if(c2 >= strlen(salt) - 1) c2 = 0;
    dest[i] = hashchars[(string[c1] * salt[c2]) % 63];
    c1++; c2++;
    }
    dest[length - 1] = 0;
    } 100.000 Durchgänge brauchen bei einem 16-stelligen Salt und einem resultierendem 16-Stelligen Hash etwa 3 Sekunden.
    Testscript: #include <a_samp>

    Hash- und Saltfunktion
    #define SALT_LENGTH 16 // Wie lang soll der Salt sein ?
    #define HASH_LENGTH 16 // Wie lang soll der Hash sein ?

    Hash- und Saltfunktion
    public OnGameModeInit()
    {
    new password[20] = "Supersicheres PW";
    new salt[SALT_LENGTH] = "hfgthdgtfhgbdgf";
    new saltedpw[HASH_LENGTH];

    new messungen = 100000;
    new tmp = 0;
    new gesammt = 0;

    for(new i = 0; i < messungen; i+= 10)
    {
    tmp = GetTickCount();
    GenerateSalt(SALT_LENGTH, salt);
    CreateSaltedHash(password, salt, HASH_LENGTH, saltedpw);
    GenerateSalt(SALT_LENGTH, salt);
    CreateSaltedHash(password, salt, HASH_LENGTH, saltedpw);
    GenerateSalt(SALT_LENGTH, salt);
    CreateSaltedHash(password, salt, HASH_LENGTH, saltedpw);
    GenerateSalt(SALT_LENGTH, salt);
    CreateSaltedHash(password, salt, HASH_LENGTH, saltedpw);
    GenerateSalt(SALT_LENGTH, salt);
    CreateSaltedHash(password, salt, HASH_LENGTH, saltedpw);
    GenerateSalt(SALT_LENGTH, salt);
    CreateSaltedHash(password, salt, HASH_LENGTH, saltedpw);
    GenerateSalt(SALT_LENGTH, salt);
    CreateSaltedHash(password, salt, HASH_LENGTH, saltedpw);
    GenerateSalt(SALT_LENGTH, salt);
    CreateSaltedHash(password, salt, HASH_LENGTH, saltedpw);
    GenerateSalt(SALT_LENGTH, salt);
    CreateSaltedHash(password, salt, HASH_LENGTH, saltedpw);
    GenerateSalt(SALT_LENGTH, salt);
    CreateSaltedHash(password, salt, HASH_LENGTH, saltedpw);
    gesammt += GetTickCount() - tmp;
    }

    printf("%50s%5d", "Messungen:", messungen);
    printf("%50s%5d", "Gesammtzeit:", gesammt);
    printf("%50s%5f", "Durchschnitt:", (gesammt / messungen));
    return true;
    }

    Hash- und Saltfunktion
    forward GenerateSalt(length, salt[]);
    public GenerateSalt(length, salt[])
    {
    new saltchars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    for(new i = 0; i < length - 1; i++)
    {
    salt[i] = saltchars[random(strlen(saltchars) - 2) + 1];
    }
    salt[length - 1] = 0;
    return true;
    }

    Hash- und Saltfunktion
    forward CreateSaltedHash(string[], salt[], length, dest[]);
    public CreateSaltedHash(string[], salt[], length, dest[])
    {
    new hashchars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

    new c1, c2;
    for(new i = 0; i < length - 1; i++)
    {
    if(c1 >= strlen(string) - 1) c1 = 0;
    if(c2 >= strlen(salt) - 1) c2 = 0;
    dest[i] = hashchars[(string[c1] * salt[c2]) % 63];
    c1++; c2++;
    }
    dest[length - 1] = 0;
    }