nonchip: Kann mir jemand bei der Portierung PHP->JS helfen?

Hallo, ich habe folgende PHP-funktion:

function gentimecode($code,$now){  
  $day=date("d",$now);     //2digits (with leading 0)  
  $month=date("m",$now);   //numerical, 2digits (leading0)  
  $year=date("Y",$now);    //num, 4digits  
  $minute=date("i",$now);  //num, 2digits (l 0)  
  $hour=date("H",$now);    //num, 24h, 2dig (l 0)  
  $second=date("s",$now);  //num, 2dig (l 0)  
  $secretpart="";  
  if($minute % 2 == 0){  
    $secretpart=$year.$month.$day.$hour.$code;  
  }else{  
    $secretpart=$year.$month.$hour.strrev($code).$day;  
  }  
  $coded=md5($secretpart);  
  if($minute % 6 == 0){  
    $coded=strrev($coded);  
  }  
  return strtoupper($second.$coded);  
}

und ich möchte sie nach Javascript portieren, weiß aber nicht, wie ich das tun soll (ich kann nicht so gut javascript). kann mir jemand helfen?
(die PHP-seite per Ajax zu fragen ist leider nicht möglich, da der parameter $code nicht durchs netz übertragen werden darf)

danke im Vorraus
-- Michael "nonchip" Zimmer

  1. 'ǝɯɐu$ ıɥ

    [code lang=php]function gentimecode($code,$now)

    (die PHP-seite per Ajax zu fragen ist leider nicht möglich, da der parameter $code nicht durchs netz übertragen werden darf)

    Häh? Du willst mit JavaScript arbeiten (Clientseitig=im Browser des Nutzers) und deine Funktion benötigt den Parameter $Code (kommt der aus ner DB? oder wird er generiert?), also wird er doch zwangsläufig durchs Netz gescheucht und die ganze Chose würde ohne Javascript nicht funktionieren, ganz davon ab das es sich manipulieren läßt. Sicherheitsrelevante Dinge nur per JavaScript umzusetzen ist äh genauso Sinnvoll wie einen Alkoholiker ein Schnapslager alleine bewachen zu lassen.

    ssnɹƃ
    ʍopɐɥs

    --
    Answers: $1, Short: $5, Correct: $25, dumb looks are still free ...
    1. äh.... nein.
      die idee ist ja, dass die funktion $code vom user bekommt, dann verschlüsselt, und dann per AJAX an ein php-script schickt, das dann testen kann, ob $code korrekt ist. halt um zu verhindern, dass jemand den code abfägt.

      ach und die funktion hat sich inzwichen leicht verändert:

      function gentimecode($code,$now){  
        $day=date("d",$now);     //2digits (with leading 0)  
        $month=date("m",$now);   //numerical, 2digits (leading0)  
        $year=date("Y",$now);    //num, 4digits  
        $minute=date("i",$now);  //num, 2digits (l 0)  
        $hour=date("H",$now);    //num, 24h, 2dig (l 0)  
        $second=date("s",$now);  //num, 2dig (l 0)  
        $secretpart="";  
        if($minute % 2 == 0){  
          $secretpart=$year.$month.$day.$hour.$code;  
        }else{  
          $secretpart=$year.$month.$hour.strrev($code).$day;  
        }  
        $coded=md5($secretpart);  
        $i=0;  
        while($i < $minute+$month-($hour/2)){  
          $i=$i+3;  
          $coded=md5($coded.md5($secretpart));  
        }  
        if($minute % 6 == 0){  
          $coded=strrev($coded);  
        }  
        return strtoupper($second.$coded);  
      }
      
      1. dann reicht ein einfacher md5 hash von $code der dann übertragen wird auch.
        alternativ statt md5 einfach sha-1 verwenden, ist noch ein bisschen sicherer.

        security through obscurity ist nie eine gute idee...

        --
        for your security, this text has been encrypted by ROT13 twice.
        1. dann reicht ein einfacher md5 hash von $code der dann übertragen wird auch.
          alternativ statt md5 einfach sha-1 verwenden, ist noch ein bisschen sicherer.

          security through obscurity ist nie eine gute idee...

          es ist auch kein security through obscurity, weil der code offen ist (siehe http://nonchip.homeip.net/timecode.php).
          es ist eine methode, um $code so zu verschlüsseln, dass er nur maximal eine minute lang von der check-funktion getestet werden kann, und rainbowtables unmöglich werden, bzw aufwändiger als bruteforcen werden (weil man pro minute mindestens eine rainbowtable bräuchte).

          1. es ist eine methode, um $code so zu verschlüsseln, dass er nur maximal eine minute lang von der check-funktion getestet werden kann, und rainbowtables unmöglich werden, bzw aufwändiger als bruteforcen werden (weil man pro minute mindestens eine rainbowtable bräuchte).

            für sowas nimmt man normalerweise ein salt.

            --
            for your security, this text has been encrypted by ROT13 twice.
          2. security through obscurity ist nie eine gute idee...

            es ist auch kein security through obscurity

            Nein, das ist Hütchenspielen ohne Hütchen. Dieses Hin- und Hergejuckel, das du da veranstaltest, ist genau wie die mehrfache md5()-Kodiererei nutzlos. Erstens ist es keine "Verschlüsselung" (in Anführungszeichen!), wenn du das Quelldatum einfach umdrehst _und_ jedem sagst, dass du das getan hast; zweitens ist alles, was einmal durch den md5-Wolf gedreht wurde, nicht wiederherstellbar, es wird nicht noch weniger wiederherstellbar, wenn du's nochmal kodierst, weshalb …

            es ist eine methode, um $code so zu verschlüsseln, dass er nur maximal eine minute lang von der check-funktion getestet werden kann

            … genau dieses dann auch vollkommen reicht: md5(Code + Zeit). Nicht mehr.

            Du solltest davon abgesehen bedenken, dass nicht jeder Server und nicht jeder Rechner die genaue Uhrzeit hat, das kann im Gegenteil durchaus um mehrere Minuten abweichen, ich würde glatt von 10-Minuten-Differenzen ausgehen, um etwas Luft zu haben. Und selbst bei identischer Uhrzeit kann es passieren, dass der Browser um 12:00:59 kodiert und der Server um 12:01:00 dekodiert.
            Deine serverseitige Funktion sollte dies beachten und auf jeden Fall die beiden Zeitblöcke vor und nach dem aktuellen in die Prüfung einbeziehen.
            Wegen der Zeit-Abweichungen sind, je kürzer der Block, desto mehr Blöcke zu prüfen, bei 1-Minuten-Schritten wären das 21 Blöcke. Um diesen Aufwand zu verringern, täte ich allerhöchstens auf Stunden- oder Halbstundenbasis prüfen, aber auch Tagesschritte würden Rainbow-Tabellen noch unbrauchbar machen.

            Genug geschwafelt:

            <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">  
            <html>  
            <head>  
            <title></title>  
              
            <script>
            ~~~~~~javascript
              
              
            var md5 = function(s) {  
            	// http://www.myersdaily.org/joseph/javascript/md5-speed-test.html  
            	if (typeof this.md51 != "function") {  
            		this.md5cycle = function(x, k) {  
            			var a = x[0], b = x[1], c = x[2], d = x[3];  
              
            			a = ff(a, b, c, d, k[0], 7, -680876936);  
            			d = ff(d, a, b, c, k[1], 12, -389564586);  
            			c = ff(c, d, a, b, k[2], 17,  606105819);  
            			b = ff(b, c, d, a, k[3], 22, -1044525330);  
            			a = ff(a, b, c, d, k[4], 7, -176418897);  
            			d = ff(d, a, b, c, k[5], 12,  1200080426);  
            			c = ff(c, d, a, b, k[6], 17, -1473231341);  
            			b = ff(b, c, d, a, k[7], 22, -45705983);  
            			a = ff(a, b, c, d, k[8], 7,  1770035416);  
            			d = ff(d, a, b, c, k[9], 12, -1958414417);  
            			c = ff(c, d, a, b, k[10], 17, -42063);  
            			b = ff(b, c, d, a, k[11], 22, -1990404162);  
            			a = ff(a, b, c, d, k[12], 7,  1804603682);  
            			d = ff(d, a, b, c, k[13], 12, -40341101);  
            			c = ff(c, d, a, b, k[14], 17, -1502002290);  
            			b = ff(b, c, d, a, k[15], 22,  1236535329);  
              
            			a = gg(a, b, c, d, k[1], 5, -165796510);  
            			d = gg(d, a, b, c, k[6], 9, -1069501632);  
            			c = gg(c, d, a, b, k[11], 14,  643717713);  
            			b = gg(b, c, d, a, k[0], 20, -373897302);  
            			a = gg(a, b, c, d, k[5], 5, -701558691);  
            			d = gg(d, a, b, c, k[10], 9,  38016083);  
            			c = gg(c, d, a, b, k[15], 14, -660478335);  
            			b = gg(b, c, d, a, k[4], 20, -405537848);  
            			a = gg(a, b, c, d, k[9], 5,  568446438);  
            			d = gg(d, a, b, c, k[14], 9, -1019803690);  
            			c = gg(c, d, a, b, k[3], 14, -187363961);  
            			b = gg(b, c, d, a, k[8], 20,  1163531501);  
            			a = gg(a, b, c, d, k[13], 5, -1444681467);  
            			d = gg(d, a, b, c, k[2], 9, -51403784);  
            			c = gg(c, d, a, b, k[7], 14,  1735328473);  
            			b = gg(b, c, d, a, k[12], 20, -1926607734);  
              
            			a = hh(a, b, c, d, k[5], 4, -378558);  
            			d = hh(d, a, b, c, k[8], 11, -2022574463);  
            			c = hh(c, d, a, b, k[11], 16,  1839030562);  
            			b = hh(b, c, d, a, k[14], 23, -35309556);  
            			a = hh(a, b, c, d, k[1], 4, -1530992060);  
            			d = hh(d, a, b, c, k[4], 11,  1272893353);  
            			c = hh(c, d, a, b, k[7], 16, -155497632);  
            			b = hh(b, c, d, a, k[10], 23, -1094730640);  
            			a = hh(a, b, c, d, k[13], 4,  681279174);  
            			d = hh(d, a, b, c, k[0], 11, -358537222);  
            			c = hh(c, d, a, b, k[3], 16, -722521979);  
            			b = hh(b, c, d, a, k[6], 23,  76029189);  
            			a = hh(a, b, c, d, k[9], 4, -640364487);  
            			d = hh(d, a, b, c, k[12], 11, -421815835);  
            			c = hh(c, d, a, b, k[15], 16,  530742520);  
            			b = hh(b, c, d, a, k[2], 23, -995338651);  
              
            			a = ii(a, b, c, d, k[0], 6, -198630844);  
            			d = ii(d, a, b, c, k[7], 10,  1126891415);  
            			c = ii(c, d, a, b, k[14], 15, -1416354905);  
            			b = ii(b, c, d, a, k[5], 21, -57434055);  
            			a = ii(a, b, c, d, k[12], 6,  1700485571);  
            			d = ii(d, a, b, c, k[3], 10, -1894986606);  
            			c = ii(c, d, a, b, k[10], 15, -1051523);  
            			b = ii(b, c, d, a, k[1], 21, -2054922799);  
            			a = ii(a, b, c, d, k[8], 6,  1873313359);  
            			d = ii(d, a, b, c, k[15], 10, -30611744);  
            			c = ii(c, d, a, b, k[6], 15, -1560198380);  
            			b = ii(b, c, d, a, k[13], 21,  1309151649);  
            			a = ii(a, b, c, d, k[4], 6, -145523070);  
            			d = ii(d, a, b, c, k[11], 10, -1120210379);  
            			c = ii(c, d, a, b, k[2], 15,  718787259);  
            			b = ii(b, c, d, a, k[9], 21, -343485551);  
              
            			x[0] = add32(a, x[0]);  
            			x[1] = add32(b, x[1]);  
            			x[2] = add32(c, x[2]);  
            			x[3] = add32(d, x[3]);  
            		};  
              
            		this.cmn = function(q, a, b, x, s, t) {  
            			a = add32(add32(a, q), add32(x, t));  
            			return add32((a << s) | (a >>> (32 - s)), b);  
            		};  
              
            		this.ff = function(a, b, c, d, x, s, t) {  
            			return cmn((b & c) | ((~b) & d), a, b, x, s, t);  
            		};  
              
            		this.gg = function(a, b, c, d, x, s, t) {  
            			return cmn((b & d) | (c & (~d)), a, b, x, s, t);  
            		};  
              
            		this.hh = function(a, b, c, d, x, s, t) {  
            		return cmn(b ^ c ^ d, a, b, x, s, t);  
            		};  
              
            		this.ii = function(a, b, c, d, x, s, t) {  
            			return cmn(c ^ (b | (~d)), a, b, x, s, t);  
            		};  
              
            		this.md51 = function(s) {  
            			txt = '';  
            			var n = s.length,  
            			state = [1732584193, -271733879, -1732584194, 271733878], i;  
            			for (i=64; i<=s.length; i+=64) {  
            				md5cycle(state, md5blk(s.substring(i-64, i)));  
            			}  
            			s = s.substring(i-64);  
            			var tail = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0];  
            			for (i=0; i<s.length; i++)  
            				tail[i>>2] |= s.charCodeAt(i) << ((i%4) << 3);  
            			tail[i>>2] |= 0x80 << ((i%4) << 3);  
            			if (i > 55) {  
            				md5cycle(state, tail);  
            				for (i=0; i<16; i++) tail[i] = 0;  
            			}  
            			tail[14] = n*8;  
            			md5cycle(state, tail);  
            			return state;  
            		};  
              
            		/* there needs to be support for Unicode here,  
            		 * unless we pretend that we can redefine the MD-5  
            		 * algorithm for multi-byte characters (perhaps  
            		 * by adding every four 16-bit characters and  
            		 * shortening the sum to 32 bits). Otherwise  
            		 * I suggest performing MD-5 as if every character  
            		 * was two bytes--e.g., 0040 0025 = @%--but then  
            		 * how will an ordinary MD-5 sum be matched?  
            		 * There is no way to standardize text to something  
            		 * like UTF-8 before transformation; speed cost is  
            		 * utterly prohibitive. The JavaScript standard  
            		 * itself needs to look at this: it should start  
            		 * providing access to strings as preformed UTF-8  
            		 * 8-bit unsigned value arrays.  
            		 */  
            		this.md5blk = function(s) { /* I figured global was faster.   */  
            			var md5blks = [], i; /* Andy King said do it this way. */  
            			for (i=0; i<64; i+=4) {  
            				md5blks[i>>2] = s.charCodeAt(i)  
            				+ (s.charCodeAt(i+1) << 8)  
            				+ (s.charCodeAt(i+2) << 16)  
            				+ (s.charCodeAt(i+3) << 24);  
            			}  
            			return md5blks;  
            		};  
              
            		this.hex_chr = '0123456789abcdef'.split('');  
              
            		this.rhex = function(n) {  
            			var s='', j=0;  
            			for(; j<4; j++)  
            			s += hex_chr[(n >> (j * 8 + 4)) & 0x0F]  
            			+ hex_chr[(n >> (j * 8)) & 0x0F];  
            			return s;  
            		};  
              
            		this.hex = function(x) {  
            			for (var i=0; i<x.length; i++)  
            				x[i] = rhex(x[i]);  
            			return x.join('');  
            		};  
              
            		/* this function is much faster,  
            		so if possible we use it. Some IEs  
            		are the only ones I know of that  
            		need the idiotic second function,  
            		generated by an if clause.  */  
              
            		this.add32 = function(a, b) {  
            			return (a + b) & 0xFFFFFFFF;  
            		};  
              
            		if (md5('hello') != '5d41402abc4b2a76b9719d911017c592') {  
            			this.add32 = function(x, y) {  
            				var lsw = (x & 0xFFFF) + (y & 0xFFFF),  
            				msw = (x >> 16) + (y >> 16) + (lsw >> 16);  
            				return (msw << 16) | (lsw & 0xFFFF);  
            			}  
            		}  
            	}  
              
            	if (typeof s == "number" || typeof s == "boolean") {  
            		s = String(s);  
            	}  
            	return hex(md51(s));  
            }  
              
            
            ~~~~~~html
            </script>  
              
            </head>  
              
            <body>  
            <pre>  
            <script>  
            var zeit = new Date(); // aktuelle Uhrzeit  
              
            var block = zeit.getTime() - zeit.getTime() % (30 * 60 * 1000); // aktueller Zeitblock (hier: 30-Minuten-Schritte)  
              
              
            document.write("Uhrzeit:     " + zeit + "\n");  
              
            zeit.setTime(block);  
            document.write("Zeitblock:   " + zeit + "\n");  
              
            document.write("Block (ms):  " + block + "\n");  
            document.write("Block (md5): " + md5(block) + "\n");  
              
            </script>  
            </pre>  
            </body>  
              
            </html>
            
          3. Moin!

            dann reicht ein einfacher md5 hash von $code der dann übertragen wird auch.
            alternativ statt md5 einfach sha-1 verwenden, ist noch ein bisschen sicherer.

            security through obscurity ist nie eine gute idee...

            es ist auch kein security through obscurity, weil der code offen ist (siehe http://nonchip.homeip.net/timecode.php).
            es ist eine methode, um $code so zu verschlüsseln, dass er nur maximal eine minute lang von der check-funktion getestet werden kann, und rainbowtables unmöglich werden, bzw aufwändiger als bruteforcen werden (weil man pro minute mindestens eine rainbowtable bräuchte).

            Das ist eine unsinnige Argumentation.

            Dein Code verwirbelt den Code ganz heftig mit der aktuellen Uhrzeit (die bekannt ist), und am Ende wird als Prüfungs-Indikator die benutzte Sekundenzahl mit an den Hashwert drangehängt. Dein Server kriegt also nur Hash plus Sekunden.

            Ein Angreifer kann dem Code entnehmen, wie er einen Code plus eine anzunehmende Uhrzeit, die in der Zukunft liegt, durch deine Hashfunktion schicken muss, um am Ende einen gültigen Hash-Code zur korrekten Uhrzeit an deinen Server zu schicken. Dein ganzes Hash-Gewirbel ist also vollkommen irrelevant, weil es mit vorhersehbaren bzw. festsetzbaren Informationen arbeitet und transparent Dinge tut.

            Der einzige wirksame Schutz gegen Rainbowtables ist, dem eventuell zu kurzen "Passwort" oder was auch immer einen recht kräftigen Salz-Wert hinzuzufügen. Der macht aus dem kurzen Passwort "123456", was mit Sicherheit in einer MD5-Rainbowtable steht, einen Wert wie "ghjklsdhjkzweurizhuil123456", dessen MD5-Wert nicht in der Rainbowtable steht. Alternativ "123456ghjklsdhjkzweurizhuil". Gute Salzwerte ändern sich pro Hash-Festlegung auch noch, d.h. jedes Passwort ist mit einem anderen Salz-Wert gewürzt - dazu muss man allerdings den Salz-Wert auch noch separat übermitteln.

            - Sven Rautenberg