Rating: 5.0/5. (16 Stimmen) Details
Bitte warten...

Semisecure Login Reimagined ist ein Plugin für WordPress, um die Anmeldung von WordPress über unverschlüsselte Verbindungen zu schützen. Dabei werden die Login-Daten lokal auf dem Client des Anwenders verschlüsselt und erst dann über HTTP an den Server geschickt. Dort entschlüsselt das Plugin die Informationen und leitet sie an die zuständige Instanz weiter. Es ist also möglich ohne SSL/TLS und ohne Zertifikat, welches dennoch dringend empfohlen wird, Daten zu verschlüsseln.

[English:] Semisecure Login Reimagined is a WordPress plugin which encrypt the login through HTTP without SSL requirements. Credentials will be encrypted locally and sent to server whose decrypt data. You don’t need a certificate.

Hinweis
Statt dieses Plugin weiterzuverwenden, empfehle ich Semisecure Login durch Clef Two-Factor Authentication auszutauschen. Es ist davon auszugehen, dass Semisecure nicht mehr weiterentwickelt wird. Clef ersetzt die Passwörter der Anwender durch ein sicheres RSA-Verschlüsselungssystem. Login-Angriffen, Passwort Phising, kompromittierten oder zu einfachen Passwörtern wird so ein Riegel vorgeschoben. Das Übertragen der Passwörter über unverschlüsselte Verbindungen gehört damit auch der Vergangenheit an.

 

Problem

Das Plugin ist nunmehr seit über einem Jahr nicht mehr aktualisiert worden. Doch die Welt dreht sich weiter und mit dem Update auf PHP 5.4 funktioniert das Plugin nicht mehr. Je nach Einstellung des Webservers kommt es zu einem internen Serverfehler (Error Code 500) oder zu folgenden Fehlermeldungen.

[English:] After upgrading to PHP 5.4 you got errors while using like following. 

MARC4 Encryption:

PHP Fatal error: Call-time pass-by-reference has been removed in D:\wordpress\wp-content\plugins\semisecure-login-reimagined\classes\crypto-js\Cryptojs_MARC4.php on line 38

AES Encryption:

PHP Fatal error: Call-time pass-by-reference has been removed in D:\wordpress\wp-content\plugins\semisecure-login-reimagined\classes\crypto-js\Cryptojs_AES.php on line 44

 

 

Ursache / Cause

Seit PHP 5.4 können nun nur noch Variablen und “New”-Ausdrücke per Referenz übergeben werden. Da der Code jedoch längere Zeit nicht mehr angepasst wurde, wird diese Einschränkung nicht berücksichtigt und die Nutzung schlägt eben fehl.

[English:] Since PHP 5.4 it’s not allowed to pass parameters by reference. You can pass a variable or New statements by reference to a function so the function can modify the variable. 


 

Lösung / Solution

Einzig bestehende Alternative ist, den Code selbständig anzupassen. Ich habe sowohl die AES- als auch MARC4-Verschlüsselungsfunktion abgeändert und erfolgreich getestet. Anbei die Änderungen der letzten Version (3.2.0). Zu ändernde Abschnitte wurden hervorgehoben.

Wer das modifizierte Plugin Semisecure Login Reimagined (v 3.2.1) herunterladen möchte, kann den folgenden Abschnitt überspringen.

[English:] See the code that have to change for.  Walk through Download Section to get the modified Semisecure Login Reimagined Plugin (v 3.2.1). 

 

semisecure-login-reimagined\classes\crypto-js\Cryptojs_MARC4.php (Original)


 *   Note: Rabbit currently requires 64-bit PHP (does not work correctly with 32-bit PHP)
 *   Note: SHA-256 and HMAC-SHA256 require 'hash', 'mhash', suhosin, or 3rd-party support
 *
 * Usage:
 *   $crypted = Cryptojs_MARC4::encrypt('message', 'secret passphrase');
 *   $plain   = Cryptojs_MARC4::decrypt($crypted,  'secret passphrase');
 *
 * Original JavaScript version:
 *   Crypto-JS v2.0.0
 *   https://code.google.com/archive/p/crypto-js
 *   Copyright (c) 2009, Jeff Mott. All rights reserved.
 *   https://code.google.com/archive/p/crypto-js/wikis/License.wiki
 */
class Cryptojs_MARC4 {

	function encrypt($message, $password) {
		// Convert to bytes
		$m = Cryptojs_UTF8::stringToBytes($message);

		// Generate random IV
		$iv = Cryptojs_util::randomBytes(16);

		// Generate key
		$k = (!is_array($password)) ?
		     // Derive key from passphrase
		     Cryptojs::PBKDF2($password, $iv, 32, array('asBytes' => true)) :
		     // else, assume byte array representing cryptographic key
		     $password;

		// Encrypt
		Cryptojs_MARC4::_marc4(&$m, $k, 1536);

		// Return ciphertext
		return Cryptojs_util::bytesToBase64(Cryptojs_util::concat($iv, $m));
	}

	function decrypt($ciphertext, $password) {
		// Convert to bytes
		$c = Cryptojs_util::base64ToBytes($ciphertext);

		// Separate IV and message
		$iv = array_splice(&$c, 0, 16);

		// Generate key
		$k = (!is_array($password)) ?
		     // Derive key from passphrase
		     Cryptojs::PBKDF2($password, $iv, 32, array('asBytes' => true)) :
		     // else, assume byte array representing cryptographic key
		     $password;

		// Decrypt
		Cryptojs_MARC4::_marc4(&$c, $k, 1536);

		// Return plaintext
		return Cryptojs_UTF8::bytesToString($c);
	}

	function _marc4(&$m, $k, $drop) {
		// State variables
		$i; $j; $s; $temp;

		// Key Setup
		for ($i = 0, $s = array(); $i < 256; $i++) $s[$i] = $i;
		for ($i = 0, $j = 0; $i < 256; $i++) {
			$j = ($j + $s[$i] + $k[$i % count($k)]) % 256;

			// Swap
			$temp = $s[$i];
			$s[$i] = $s[$j];
			$s[$j] = $temp;
		}

		// Clear counters
		$i = $j = 0;

		// Encryption
		for ($k = 0 - $drop; $k < count($m); $k++) {
			$i = ($i + 1) % 256;
			$j = ($j + $s[$i]) % 256;

			// Swap
			$temp = $s[$i];
			$s[$i] = $s[$j];
			$s[$j] = $temp;

			// Stop here if we're still dropping keystream
			if ($k < 0) continue;

			// Encrypt
			$m[$k] ^= $s[($s[$i] + $s[$j]) % 256];
		}
	}
}
endif;
?>

 

semisecure-login-reimagined\classes\crypto-js\Cryptojs_MARC4.php (modifiziert)


 *   Note: Rabbit currently requires 64-bit PHP (does not work correctly with 32-bit PHP)
 *   Note: SHA-256 and HMAC-SHA256 require 'hash', 'mhash', suhosin, or 3rd-party support
 *
 * Usage:
 *   $crypted = Cryptojs_MARC4::encrypt('message', 'secret passphrase');
 *   $plain   = Cryptojs_MARC4::decrypt($crypted,  'secret passphrase');
 *
 * Original JavaScript version:
 *   Crypto-JS v2.0.0
 *   https://code.google.com/archive/p/crypto-js
 *   Copyright (c) 2009, Jeff Mott. All rights reserved.
 *   https://code.google.com/archive/p/crypto-js/wikis/License.wiki
 */
class Cryptojs_MARC4 {

	function encrypt($message, $password) {
		// Convert to bytes
		$m = Cryptojs_UTF8::stringToBytes($message);

		// Generate random IV
		$iv = Cryptojs_util::randomBytes(16);

		// Generate key
		$k = (!is_array($password)) ?
		     // Derive key from passphrase
		     Cryptojs::PBKDF2($password, $iv, 32, array('asBytes' => true)) :
		     // else, assume byte array representing cryptographic key
		     $password;

		// Encrypt
		Cryptojs_MARC4::_marc4($m, $k, 1536);

		// Return ciphertext
		return Cryptojs_util::bytesToBase64(Cryptojs_util::concat($iv, $m));
	}

	function decrypt($ciphertext, $password) {
		// Convert to bytes
		$c = Cryptojs_util::base64ToBytes($ciphertext);

		// Separate IV and message
		$iv = array_splice($c, 0, 16);

		// Generate key
		$k = (!is_array($password)) ?
		     // Derive key from passphrase
		     Cryptojs::PBKDF2($password, $iv, 32, array('asBytes' => true)) :
		     // else, assume byte array representing cryptographic key
		     $password;

		// Decrypt
		Cryptojs_MARC4::_marc4($c, $k, 1536);

		// Return plaintext
		return Cryptojs_UTF8::bytesToString($c);
	}

	function _marc4(&$m, $k, $drop) {
		// State variables
		$i; $j; $s; $temp;

		// Key Setup
		for ($i = 0, $s = array(); $i < 256; $i++) $s[$i] = $i;
		for ($i = 0, $j = 0; $i < 256; $i++) {
			$j = ($j + $s[$i] + $k[$i % count($k)]) % 256;

			// Swap
			$temp = $s[$i];
			$s[$i] = $s[$j];
			$s[$j] = $temp;
		}

		// Clear counters
		$i = $j = 0;

		// Encryption
		for ($k = 0 - $drop; $k < count($m); $k++) {
			$i = ($i + 1) % 256;
			$j = ($j + $s[$i]) % 256;

			// Swap
			$temp = $s[$i];
			$s[$i] = $s[$j];
			$s[$j] = $temp;

			// Stop here if we're still dropping keystream
			if ($k < 0) continue;

			// Encrypt
			$m[$k] ^= $s[($s[$i] + $s[$j]) % 256];
		}
	}
}
endif;
?>

 

semisecure-login-reimagined\classes\crypto-js\Cryptojs_AES.php (Original)


 *   Note: Rabbit currently requires 64-bit PHP (does not work correctly with 32-bit PHP)
 *   Note: SHA-256 and HMAC-SHA256 require 'hash', 'mhash', suhosin, or 3rd-party support
 *
 * Usage:
 *   $crypted = Cryptojs_AES::encrypt('message', 'secret passphrase');
 *   $plain   = Cryptojs_AES::decrypt($crypted,  'secret passphrase');
 *
 * Original JavaScript version:
 *   Crypto-JS v2.0.0
 *   https://code.google.com/archive/p/crypto-js
 *   Copyright (c) 2009, Jeff Mott. All rights reserved.
 *   https://code.google.com/archive/p/crypto-js/wikis/License.wiki
 */
class Cryptojs_AES {

	// Possible todo: check if mcrypt can be used here (probably faster than PHP code)
	function encrypt($message, $password, $options=null) {
		// Convert to bytes
		$m = Cryptojs_UTF8::stringToBytes($message);

		// Generate random IV
		$iv = Cryptojs_util::randomBytes(Cryptojs_AES::_blocksize() * 4);

		// Generate key
		$k = (!is_array($password)) ?
		     // Derive key from passphrase
		     Cryptojs::PBKDF2($password, $iv, 32, array('asBytes' => true)) :
		     // else, assume byte array representing cryptographic key
		     $password;

		// Determine mode
		if (is_array($options) && isset($options['mode']))
			$mode = strtolower($options['mode']);
		if ($mode != 'ofb' && $mode != 'cbc') $mode = 'ofb';

		// Encrypt
		Cryptojs_AES::_init($k, $mode, &$m, $iv, true);

		// Return ciphertext
		return Cryptojs_util::bytesToBase64(Cryptojs_util::concat($iv, $m));
	}

	function decrypt($ciphertext, $password, $options=null) {
		// Cconvert to bytes
		$c = Cryptojs_util::base64ToBytes($ciphertext);

		// Separate IV and message
		$iv = array_splice(&$c, 0, Cryptojs_AES::_blocksize() * 4);

		// Generate key
		$k = (!is_array($password)) ?
		     // Derive key from passphrase
		     Cryptojs::PBKDF2($password, $iv, 32, array('asBytes' => true)) :
		     // else, assume byte array representing cryptographic key
		     $password;

		// Determine mode
		if (is_array($options) && isset($options['mode']))
			$mode = strtolower($options['mode']);
		if ($mode != 'ofb' && $mode != 'cbc') $mode = 'ofb';

		// Decrypt
		Cryptojs_AES::_init($k, $mode, &$c, $iv, false);

		// Return plaintext
		return Cryptojs_UTF8::bytesToString($c);
	}

	function _blocksize() {
		return 4;
	}

	function _init($k, $mode, &$m, $iv, $encrypt) {
		// Precomputed SBOX
		static $SBOX = array( 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
				0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
				0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
				0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
				0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
				0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
				0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
				0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
				0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
				0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
				0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
				0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
				0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
				0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
				0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
				0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
				0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
				0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
				0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
				0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
				0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
				0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
				0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
				0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
				0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
				0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
				0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
				0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
				0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
				0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
				0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
				0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 );
		static $INVSBOX = array();
		if (empty($INVSBOX)) {
			// Compute inverse SBOX lookup table
			for ($i = 0; $i < 256; $i++) $INVSBOX[$SBOX[$i]] = $i;
		}

		// Compute multiplication in GF(2^8) lookup tables
		static $MULT2 = array();
		static $MULT3 = array();
		static $MULT9 = array();
		static $MULTB = array();
		static $MULTD = array();
		static $MULTE = array();
		if (empty($MULT2) || empty($MULT3) || empty($MULT9) || empty($MULTB) || empty($MULTD) || empty($MULTE)) {
			for ($i = 0; $i < 256; $i++) {
				$MULT2[$i] = Cryptojs_AES::_xtime($i,2);
				$MULT3[$i] = Cryptojs_AES::_xtime($i,3);
				$MULT9[$i] = Cryptojs_AES::_xtime($i,9);
				$MULTB[$i] = Cryptojs_AES::_xtime($i,0xB);
				$MULTD[$i] = Cryptojs_AES::_xtime($i,0xD);
				$MULTE[$i] = Cryptojs_AES::_xtime($i,0xE);
			}
		}

		// Precomputed RCon lookup
		static $RCON = array(0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36);

		// Inner state
		static $state = array(array(), array(), array(), array());
		static $keylength;
		static $nrounds;
		static $keyschedule;

		$keylength = count($k) / 4;
		$nrounds = $keylength + 6;
		Cryptojs_AES::_keyexpansion($k, &$keyschedule, $keylength, $nrounds, $SBOX, $RCON);

		if ($mode == 'ofb') {
			Cryptojs_AES::_ofb(&$m, $iv, &$state, $nrounds, $keyschedule, $SBOX, $INVSBOX, $MULT2, $MULT3, $MULT9, $MULTB, $MULTD, $MULTE);
		}
		else { // cbc
			if ($encrypt)
				Cryptojs_AES::_cbcEncrypt(&$m, $iv, &$state, $nrounds, $keyschedule, $SBOX, $INVSBOX, $MULT2, $MULT3, $MULT9, $MULTB, $MULTD, $MULTE);
			else
				Cryptojs_AES::_cbcDecrypt(&$m, $iv, &$state, $nrounds, $keyschedule, $SBOX, $INVSBOX, $MULT2, $MULT3, $MULT9, $MULTB, $MULTD, $MULTE);
		}
	}

	function _encryptblock(&$m, $offset, &$state, $nrounds, $keyschedule, $SBOX, $INVSBOX, $MULT2, $MULT3, $MULT9, $MULTB, $MULTD, $MULTE) {
		// Set input
		for ($row = 0; $row < Cryptojs_AES::_blocksize(); $row++) {
			for ($col = 0; $col < 4; $col++)
				$state[$row][$col] = $m[$offset + $col * 4 + $row];
		}

		// Add round key
		for($row = 0; $row < 4; $row++) {
			for($col = 0; $col < 4; $col++)
				$state[$row][$col] ^= $keyschedule[$col][$row];
		}

		for ($round = 1; $round < $nrounds; $round++) {
			// Sub bytes
			for ($row = 0; $row < 4; $row++) {
				for ($col = 0; $col < 4; $col++)
					$state[$row][$col] = $SBOX[$state[$row][$col]];
			}

			// Shift rows
			$state[1][] = array_shift(&$state[1]);
			$state[2][] = array_shift(&$state[2]);
			$state[2][] = array_shift(&$state[2]);
			array_unshift(&$state[3], array_pop(&$state[3]));

			// Mix columns
			for ($col = 0; $col < 4; $col++) {
				$s0 = $state[0][$col];
				$s1 = $state[1][$col];
				$s2 = $state[2][$col];
				$s3 = $state[3][$col];

				$state[0][$col] = $MULT2[$s0] ^ $MULT3[$s1] ^ $s2 ^ $s3;
				$state[1][$col] = $s0 ^ $MULT2[$s1] ^ $MULT3[$s2] ^ $s3;
				$state[2][$col] = $s0 ^ $s1 ^ $MULT2[$s2] ^ $MULT3[$s3];
				$state[3][$col] = $MULT3[$s0] ^ $s1 ^ $s2 ^ $MULT2[$s3];
			}

			// Add round key
			for ($row = 0; $row < 4; $row++) {
				for ($col = 0; $col < 4; $col++)
					$state[$row][$col] ^= $keyschedule[$round * 4 + $col][$row];
			}
		}

		// Sub byte
		for ($row = 0; $row < 4; $row++) {
			for ($col = 0; $col < 4; $col++)
				$state[$row][$col] = $SBOX[$state[$row][$col]];
		}

		// Shift rows
		$state[1][] = array_shift(&$state[1]);
		$state[2][] = array_shift(&$state[2]);
		$state[2][] = array_shift(&$state[2]);
		array_unshift(&$state[3], array_pop(&$state[3]));

		// Add round key
		for ($row = 0; $row < 4; $row++) {
			for ($col = 0; $col < 4; $col++)
				$state[$row][$col] ^= $keyschedule[$nrounds * 4 + $col][$row];
		}

		// Set output
		for ($row = 0; $row < Cryptojs_AES::_blocksize(); $row++) {
			for ($col = 0; $col < 4; $col++)
				$m[$offset + $col * 4 + $row] = $state[$row][$col];
		}
	}

	function _decryptblock(&$c, $offset, &$state, $nrounds, $keyschedule, $SBOX, $INVSBOX, $MULT2, $MULT3, $MULT9, $MULTB, $MULTD, $MULTE) {
		// Set input
		for ($row = 0; $row < Cryptojs_AES::_blocksize(); $row++) {
			for ($col = 0; $col < 4; $col++)
				$state[$row][$col] = $c[$offset + $col * 4 + $row];
		}

		// Add round key
		for ($row = 0; $row < 4; $row++) {
			for ($col = 0; $col < 4; $col++)
				$state[$row][$col] ^= $keyschedule[$nrounds * 4 + $col][$row];
		}

		for ($round = 1; $round < $nrounds; $round++) {
			// Inv shift rows
			array_unshift(&$state[1], array_pop(&$state[1]));
			$state[2][] = array_shift(&$state[2]);
			$state[2][] = array_shift(&$state[2]);
			$state[3][] = array_shift(&$state[3]);

			// Inv sub bytes
			for ($row = 0; $row < 4; $row++) {
				for ($col = 0; $col < 4; $col++)
					$state[$row][$col] = $INVSBOX[$state[$row][$col]];
			}

			// Add round key
			for ($row = 0; $row < 4; $row++) {
				for ($col = 0; $col < 4; $col++)
					$state[$row][$col] ^= $keyschedule[($nrounds - $round) * 4 + $col][$row];
			}

			// Inv mix columns
			for ($col = 0; $col < 4; $col++) {
				$s0 = $state[0][$col];
				$s1 = $state[1][$col];
				$s2 = $state[2][$col];
				$s3 = $state[3][$col];

				$state[0][$col] = $MULTE[$s0] ^ $MULTB[$s1] ^ $MULTD[$s2] ^ $MULT9[$s3];
				$state[1][$col] = $MULT9[$s0] ^ $MULTE[$s1] ^ $MULTB[$s2] ^ $MULTD[$s3];
				$state[2][$col] = $MULTD[$s0] ^ $MULT9[$s1] ^ $MULTE[$s2] ^ $MULTB[$s3];
				$state[3][$col] = $MULTB[$s0] ^ $MULTD[$s1] ^ $MULT9[$s2] ^ $MULTE[$s3];
			}
		}

		// Inv shift rows
		array_unshift(&$state[1], array_pop(&$state[1]));
		$state[2][] = array_shift(&$state[2]);
		$state[2][] = array_shift(&$state[2]);
		$state[3][] = array_shift(&$state[3]);

		// Inv sub bytes
		for ($row = 0; $row < 4; $row++) {
			for ($col = 0; $col < 4; $col++)
				$state[$row][$col] = $INVSBOX[$state[$row][$col]];
		}

		// Add round key
		for ($row = 0; $row < 4; $row++) {
			for ($col = 0; $col < 4; $col++)
				$state[$row][$col] ^= $keyschedule[$col][$row];
		}

		// Set output
		for ($row = 0; $row < Cryptojs_AES::_blocksize(); $row++) {
			for ($col = 0; $col < 4; $col++)
				$c[$offset + $col * 4 + $row] = $state[$row][$col];
		}
	}

	function _keyexpansion($k, &$keyschedule, $keylength, $nrounds, $SBOX, $RCON) {
		$keyschedule = array();

		for ($row = 0; $row < $keylength; $row++) {
			$keyschedule[$row] = array(
				$k[$row * 4],
				$k[$row * 4 + 1],
				$k[$row * 4 + 2],
				$k[$row * 4 + 3]
			);
		}

		for ($row = $keylength; $row < Cryptojs_AES::_blocksize() * ($nrounds + 1); $row++) {
			$temp = array(
				$keyschedule[$row - 1][0],
				$keyschedule[$row - 1][1],
				$keyschedule[$row - 1][2],
				$keyschedule[$row - 1][3]
			);

			if ($row % $keylength == 0) {
				// Rot word
				$temp[] = array_shift(&$temp);

				// Sub word
				$temp[0] = $SBOX[$temp[0]];
				$temp[1] = $SBOX[$temp[1]];
				$temp[2] = $SBOX[$temp[2]];
				$temp[3] = $SBOX[$temp[3]];

				$temp[0] ^= $RCON[$row / $keylength];
			}
			else if ($keylength > 6 && $row % $keylength == 4) {
				// Sub word
				$temp[0] = $SBOX[$temp[0]];
				$temp[1] = $SBOX[$temp[1]];
				$temp[2] = $SBOX[$temp[2]];
				$temp[3] = $SBOX[$temp[3]];
			}

			$keyschedule[$row] = array(
				$keyschedule[$row - $keylength][0] ^ $temp[0],
				$keyschedule[$row - $keylength][1] ^ $temp[1],
				$keyschedule[$row - $keylength][2] ^ $temp[2],
				$keyschedule[$row - $keylength][3] ^ $temp[3]
			);
		}
	}

	function _xtime($a, $b) {
		for ($result = 0, $i = 0; $i < 8; $i++) {
			if ($b & 1) $result ^= $a;
			$hiBitSet = $a & 0x80;
			$a = ($a << 1) & 0xFF;
			if ($hiBitSet) $a ^= 0x1b;
			$b = Cryptojs_util::urs($b, 1);
		}
		return $result;
	}

	/*
	 * Mode specific methods
	 */

	function _cbcEncrypt(&$m, $iv, &$state, $nrounds, $keyschedule, $SBOX, $INVSBOX, $MULT2, $MULT3, $MULT9, $MULTB, $MULTD, $MULTE) {
		$blockSizeInBytes = Cryptojs_AES::_blocksize() * 4;

		// Pad
		$m[] = 0x80;

		// Encrypt each block
		for ($offset = 0; $offset < count($m); $offset += $blockSizeInBytes) {
			if ($offset == 0) {
				// XOR first block using IV
				for ($i = 0; $i < $blockSizeInBytes; $i++)
					$m[$i] ^= $iv[$i];
			}
			else {
				// XOR this block using previous crypted block
				for ($i = 0; $i < $blockSizeInBytes; $i++)
					$m[$offset + $i] ^= $m[$offset + $i - $blockSizeInBytes];
			}

			// Encrypt block
			Cryptojs_AES::_encryptblock(&$m, $offset, &$state, $nrounds, $keyschedule, $SBOX, $INVSBOX, $MULT2, $MULT3, $MULT9, $MULTB, $MULTD, $MULTE);
		}
	}

	function _cbcDecrypt(&$c, $iv, &$state, $nrounds, $keyschedule, $SBOX, $INVSBOX, $MULT2, $MULT3, $MULT9, $MULTB, $MULTD, $MULTE) {
		$blockSizeInBytes = Cryptojs_AES::_blocksize() * 4;

		// Decrypt each block
		for ($offset = 0; $offset < count($c); $offset += $blockSizeInBytes) {
			// Save this crypted block
			$thisCryptedBlock = array_slice(&$c, $offset, $offset + $blockSizeInBytes);

			// Decrypt block
			Cryptojs_AES::_decryptblock(&$c, $offset, &$state, $nrounds, $keyschedule, $SBOX, $INVSBOX, $MULT2, $MULT3, $MULT9, $MULTB, $MULTD, $MULTE);

			if ($offset == 0) {
				// XOR first block using IV
				for ($i = 0; $i < $blockSizeInBytes; $i++)
					$c[$i] ^= $iv[$i];
			}
			else {
				// XOR decrypted block using previous crypted block
				for($i = 0; $i < $blockSizeInBytes; $i++)
					$c[$offset + $i] ^= $prevCryptedBlock[$i];
			}

			// This crypted block is the new previous crypted block
			$prevCryptedBlock = $thisCryptedBlock;
		}

		// Strip padding
		while(array_pop(&$c) != 0x80) {}
	}

	function _ofb(&$m, $iv, &$state, $nrounds, $keyschedule, $SBOX, $INVSBOX, $MULT2, $MULT3, $MULT9, $MULTB, $MULTD, $MULTE) {
		$blockSizeInBytes = Cryptojs_AES::_blocksize() * 4;
		$keystream = array_slice($iv, 0);

		// Encrypt each byte
		for ($i = 0; $i < count($m); $i++) {
			// Generate keystream
			if ($i % $blockSizeInBytes == 0)
				Cryptojs_AES::_encryptblock(&$keystream, 0, &$state, $nrounds, $keyschedule, $SBOX, $INVSBOX, $MULT2, $MULT3, $MULT9, $MULTB, $MULTD, $MULTE);

			// Encrypt byte
			$m[$i] ^= $keystream[$i % $blockSizeInBytes];
		}
	}
}
endif;
?>

 

semisecure-login-reimagined\classes\crypto-js\Cryptojs_AES.php (modifiziert)


 *   Note: Rabbit currently requires 64-bit PHP (does not work correctly with 32-bit PHP)
 *   Note: SHA-256 and HMAC-SHA256 require 'hash', 'mhash', suhosin, or 3rd-party support
 *
 * Usage:
 *   $crypted = Cryptojs_AES::encrypt('message', 'secret passphrase');
 *   $plain   = Cryptojs_AES::decrypt($crypted,  'secret passphrase');
 *
 * Original JavaScript version:
 *   Crypto-JS v2.0.0
 *   https://code.google.com/archive/p/crypto-js
 *   Copyright (c) 2009, Jeff Mott. All rights reserved.
 *   https://code.google.com/archive/p/crypto-js/wikis/License.wiki
 */
class Cryptojs_AES {

	// Possible todo: check if mcrypt can be used here (probably faster than PHP code)
	function encrypt($message, $password, $options=null) {
		// Convert to bytes
		$m = Cryptojs_UTF8::stringToBytes($message);

		// Generate random IV
		$iv = Cryptojs_util::randomBytes(Cryptojs_AES::_blocksize() * 4);

		// Generate key
		$k = (!is_array($password)) ?
		     // Derive key from passphrase
		     Cryptojs::PBKDF2($password, $iv, 32, array('asBytes' => true)) :
		     // else, assume byte array representing cryptographic key
		     $password;

		// Determine mode
		if (is_array($options) && isset($options['mode']))
			$mode = strtolower($options['mode']);
		if ($mode != 'ofb' && $mode != 'cbc') $mode = 'ofb';

		// Encrypt
		Cryptojs_AES::_init($k, $mode, $m, $iv, true);

		// Return ciphertext
		return Cryptojs_util::bytesToBase64(Cryptojs_util::concat($iv, $m));
	}

	function decrypt($ciphertext, $password, $options=null) {
		// Cconvert to bytes
		$c = Cryptojs_util::base64ToBytes($ciphertext);

		// Separate IV and message
		$iv = array_splice($c, 0, Cryptojs_AES::_blocksize() * 4);

		// Generate key
		$k = (!is_array($password)) ?
		     // Derive key from passphrase
		     Cryptojs::PBKDF2($password, $iv, 32, array('asBytes' => true)) :
		     // else, assume byte array representing cryptographic key
		     $password;

		// Determine mode
		if (is_array($options) && isset($options['mode']))
			$mode = strtolower($options['mode']);
		if ($mode != 'ofb' && $mode != 'cbc') $mode = 'ofb';

		// Decrypt
		Cryptojs_AES::_init($k, $mode, $c, $iv, false);

		// Return plaintext
		return Cryptojs_UTF8::bytesToString($c);
	}

	function _blocksize() {
		return 4;
	}

	function _init($k, $mode, &$m, $iv, $encrypt) {
		// Precomputed SBOX
		static $SBOX = array( 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
				0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
				0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
				0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
				0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
				0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
				0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
				0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
				0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
				0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
				0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
				0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
				0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
				0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
				0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
				0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
				0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
				0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
				0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
				0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
				0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
				0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
				0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
				0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
				0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
				0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
				0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
				0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
				0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
				0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
				0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
				0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 );
		static $INVSBOX = array();
		if (empty($INVSBOX)) {
			// Compute inverse SBOX lookup table
			for ($i = 0; $i < 256; $i++) $INVSBOX[$SBOX[$i]] = $i;
		}

		// Compute multiplication in GF(2^8) lookup tables
		static $MULT2 = array();
		static $MULT3 = array();
		static $MULT9 = array();
		static $MULTB = array();
		static $MULTD = array();
		static $MULTE = array();
		if (empty($MULT2) || empty($MULT3) || empty($MULT9) || empty($MULTB) || empty($MULTD) || empty($MULTE)) {
			for ($i = 0; $i < 256; $i++) {
				$MULT2[$i] = Cryptojs_AES::_xtime($i,2);
				$MULT3[$i] = Cryptojs_AES::_xtime($i,3);
				$MULT9[$i] = Cryptojs_AES::_xtime($i,9);
				$MULTB[$i] = Cryptojs_AES::_xtime($i,0xB);
				$MULTD[$i] = Cryptojs_AES::_xtime($i,0xD);
				$MULTE[$i] = Cryptojs_AES::_xtime($i,0xE);
			}
		}

		// Precomputed RCon lookup
		static $RCON = array(0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36);

		// Inner state
		static $state = array(array(), array(), array(), array());
		static $keylength;
		static $nrounds;
		static $keyschedule;

		$keylength = count($k) / 4;
		$nrounds = $keylength + 6;
		Cryptojs_AES::_keyexpansion($k, $keyschedule, $keylength, $nrounds, $SBOX, $RCON);

		if ($mode == 'ofb') {
			Cryptojs_AES::_ofb($m, $iv, $state, $nrounds, $keyschedule, $SBOX, $INVSBOX, $MULT2, $MULT3, $MULT9, $MULTB, $MULTD, $MULTE);
		}
		else { // cbc
			if ($encrypt)
				Cryptojs_AES::_cbcEncrypt($m, $iv, $state, $nrounds, $keyschedule, $SBOX, $INVSBOX, $MULT2, $MULT3, $MULT9, $MULTB, $MULTD, $MULTE);
			else
				Cryptojs_AES::_cbcDecrypt($m, $iv, $state, $nrounds, $keyschedule, $SBOX, $INVSBOX, $MULT2, $MULT3, $MULT9, $MULTB, $MULTD, $MULTE);
		}
	}

	function _encryptblock(&$m, $offset, &$state, $nrounds, $keyschedule, $SBOX, $INVSBOX, $MULT2, $MULT3, $MULT9, $MULTB, $MULTD, $MULTE) {
		// Set input
		for ($row = 0; $row < Cryptojs_AES::_blocksize(); $row++) {
			for ($col = 0; $col < 4; $col++)
				$state[$row][$col] = $m[$offset + $col * 4 + $row];
		}

		// Add round key
		for($row = 0; $row < 4; $row++) {
			for($col = 0; $col < 4; $col++)
				$state[$row][$col] ^= $keyschedule[$col][$row];
		}

		for ($round = 1; $round < $nrounds; $round++) {
			// Sub bytes
			for ($row = 0; $row < 4; $row++) {
				for ($col = 0; $col < 4; $col++)
					$state[$row][$col] = $SBOX[$state[$row][$col]];
			}

			// Shift rows
			$state[1][] = array_shift($state[1]);
			$state[2][] = array_shift($state[2]);
			$state[2][] = array_shift($state[2]);
			array_unshift($state[3], array_pop($state[3]));

			// Mix columns
			for ($col = 0; $col < 4; $col++) {
				$s0 = $state[0][$col];
				$s1 = $state[1][$col];
				$s2 = $state[2][$col];
				$s3 = $state[3][$col];

				$state[0][$col] = $MULT2[$s0] ^ $MULT3[$s1] ^ $s2 ^ $s3;
				$state[1][$col] = $s0 ^ $MULT2[$s1] ^ $MULT3[$s2] ^ $s3;
				$state[2][$col] = $s0 ^ $s1 ^ $MULT2[$s2] ^ $MULT3[$s3];
				$state[3][$col] = $MULT3[$s0] ^ $s1 ^ $s2 ^ $MULT2[$s3];
			}

			// Add round key
			for ($row = 0; $row < 4; $row++) {
				for ($col = 0; $col < 4; $col++)
					$state[$row][$col] ^= $keyschedule[$round * 4 + $col][$row];
			}
		}

		// Sub byte
		for ($row = 0; $row < 4; $row++) {
			for ($col = 0; $col < 4; $col++)
				$state[$row][$col] = $SBOX[$state[$row][$col]];
		}

		// Shift rows
		$state[1][] = array_shift($state[1]);
		$state[2][] = array_shift($state[2]);
		$state[2][] = array_shift($state[2]);
		array_unshift($state[3], array_pop($state[3]));

		// Add round key
		for ($row = 0; $row < 4; $row++) {
			for ($col = 0; $col < 4; $col++)
				$state[$row][$col] ^= $keyschedule[$nrounds * 4 + $col][$row];
		}

		// Set output
		for ($row = 0; $row < Cryptojs_AES::_blocksize(); $row++) {
			for ($col = 0; $col < 4; $col++)
				$m[$offset + $col * 4 + $row] = $state[$row][$col];
		}
	}

	function _decryptblock(&$c, $offset, &$state, $nrounds, $keyschedule, $SBOX, $INVSBOX, $MULT2, $MULT3, $MULT9, $MULTB, $MULTD, $MULTE) {
		// Set input
		for ($row = 0; $row < Cryptojs_AES::_blocksize(); $row++) {
			for ($col = 0; $col < 4; $col++)
				$state[$row][$col] = $c[$offset + $col * 4 + $row];
		}

		// Add round key
		for ($row = 0; $row < 4; $row++) {
			for ($col = 0; $col < 4; $col++)
				$state[$row][$col] ^= $keyschedule[$nrounds * 4 + $col][$row];
		}

		for ($round = 1; $round < $nrounds; $round++) {
			// Inv shift rows
			array_unshift($state[1], array_pop($state[1]));
			$state[2][] = array_shift($state[2]);
			$state[2][] = array_shift($state[2]);
			$state[3][] = array_shift($state[3]);

			// Inv sub bytes
			for ($row = 0; $row < 4; $row++) {
				for ($col = 0; $col < 4; $col++)
					$state[$row][$col] = $INVSBOX[$state[$row][$col]];
			}

			// Add round key
			for ($row = 0; $row < 4; $row++) {
				for ($col = 0; $col < 4; $col++)
					$state[$row][$col] ^= $keyschedule[($nrounds - $round) * 4 + $col][$row];
			}

			// Inv mix columns
			for ($col = 0; $col < 4; $col++) {
				$s0 = $state[0][$col];
				$s1 = $state[1][$col];
				$s2 = $state[2][$col];
				$s3 = $state[3][$col];

				$state[0][$col] = $MULTE[$s0] ^ $MULTB[$s1] ^ $MULTD[$s2] ^ $MULT9[$s3];
				$state[1][$col] = $MULT9[$s0] ^ $MULTE[$s1] ^ $MULTB[$s2] ^ $MULTD[$s3];
				$state[2][$col] = $MULTD[$s0] ^ $MULT9[$s1] ^ $MULTE[$s2] ^ $MULTB[$s3];
				$state[3][$col] = $MULTB[$s0] ^ $MULTD[$s1] ^ $MULT9[$s2] ^ $MULTE[$s3];
			}
		}

		// Inv shift rows
		array_unshift($state[1], array_pop($state[1]));
		$state[2][] = array_shift($state[2]);
		$state[2][] = array_shift($state[2]);
		$state[3][] = array_shift($state[3]);

		// Inv sub bytes
		for ($row = 0; $row < 4; $row++) {
			for ($col = 0; $col < 4; $col++)
				$state[$row][$col] = $INVSBOX[$state[$row][$col]];
		}

		// Add round key
		for ($row = 0; $row < 4; $row++) {
			for ($col = 0; $col < 4; $col++)
				$state[$row][$col] ^= $keyschedule[$col][$row];
		}

		// Set output
		for ($row = 0; $row < Cryptojs_AES::_blocksize(); $row++) {
			for ($col = 0; $col < 4; $col++)
				$c[$offset + $col * 4 + $row] = $state[$row][$col];
		}
	}

	function _keyexpansion($k, &$keyschedule, $keylength, $nrounds, $SBOX, $RCON) {
		$keyschedule = array();

		for ($row = 0; $row < $keylength; $row++) {
			$keyschedule[$row] = array(
				$k[$row * 4],
				$k[$row * 4 + 1],
				$k[$row * 4 + 2],
				$k[$row * 4 + 3]
			);
		}

		for ($row = $keylength; $row < Cryptojs_AES::_blocksize() * ($nrounds + 1); $row++) {
			$temp = array(
				$keyschedule[$row - 1][0],
				$keyschedule[$row - 1][1],
				$keyschedule[$row - 1][2],
				$keyschedule[$row - 1][3]
			);

			if ($row % $keylength == 0) {
				// Rot word
				$temp[] = array_shift($temp);

				// Sub word
				$temp[0] = $SBOX[$temp[0]];
				$temp[1] = $SBOX[$temp[1]];
				$temp[2] = $SBOX[$temp[2]];
				$temp[3] = $SBOX[$temp[3]];

				$temp[0] ^= $RCON[$row / $keylength];
			}
			else if ($keylength > 6 && $row % $keylength == 4) {
				// Sub word
				$temp[0] = $SBOX[$temp[0]];
				$temp[1] = $SBOX[$temp[1]];
				$temp[2] = $SBOX[$temp[2]];
				$temp[3] = $SBOX[$temp[3]];
			}

			$keyschedule[$row] = array(
				$keyschedule[$row - $keylength][0] ^ $temp[0],
				$keyschedule[$row - $keylength][1] ^ $temp[1],
				$keyschedule[$row - $keylength][2] ^ $temp[2],
				$keyschedule[$row - $keylength][3] ^ $temp[3]
			);
		}
	}

	function _xtime($a, $b) {
		for ($result = 0, $i = 0; $i < 8; $i++) {
			if ($b & 1) $result ^= $a;
			$hiBitSet = $a & 0x80;
			$a = ($a << 1) & 0xFF;
			if ($hiBitSet) $a ^= 0x1b;
			$b = Cryptojs_util::urs($b, 1);
		}
		return $result;
	}

	/*
	 * Mode specific methods
	 */

	function _cbcEncrypt(&$m, $iv, &$state, $nrounds, $keyschedule, $SBOX, $INVSBOX, $MULT2, $MULT3, $MULT9, $MULTB, $MULTD, $MULTE) {
		$blockSizeInBytes = Cryptojs_AES::_blocksize() * 4;

		// Pad
		$m[] = 0x80;

		// Encrypt each block
		for ($offset = 0; $offset < count($m); $offset += $blockSizeInBytes) {
			if ($offset == 0) {
				// XOR first block using IV
				for ($i = 0; $i < $blockSizeInBytes; $i++)
					$m[$i] ^= $iv[$i];
			}
			else {
				// XOR this block using previous crypted block
				for ($i = 0; $i < $blockSizeInBytes; $i++)
					$m[$offset + $i] ^= $m[$offset + $i - $blockSizeInBytes];
			}

			// Encrypt block
			Cryptojs_AES::_encryptblock($m, $offset, $state, $nrounds, $keyschedule, $SBOX, $INVSBOX, $MULT2, $MULT3, $MULT9, $MULTB, $MULTD, $MULTE);
		}
	}

	function _cbcDecrypt(&$c, $iv, &$state, $nrounds, $keyschedule, $SBOX, $INVSBOX, $MULT2, $MULT3, $MULT9, $MULTB, $MULTD, $MULTE) {
		$blockSizeInBytes = Cryptojs_AES::_blocksize() * 4;

		// Decrypt each block
		for ($offset = 0; $offset < count($c); $offset += $blockSizeInBytes) {
			// Save this crypted block
			$thisCryptedBlock = array_slice($c, $offset, $offset + $blockSizeInBytes);

			// Decrypt block
			Cryptojs_AES::_decryptblock($c, $offset, $state, $nrounds, $keyschedule, $SBOX, $INVSBOX, $MULT2, $MULT3, $MULT9, $MULTB, $MULTD, $MULTE);

			if ($offset == 0) {
				// XOR first block using IV
				for ($i = 0; $i < $blockSizeInBytes; $i++)
					$c[$i] ^= $iv[$i];
			}
			else {
				// XOR decrypted block using previous crypted block
				for($i = 0; $i < $blockSizeInBytes; $i++)
					$c[$offset + $i] ^= $prevCryptedBlock[$i];
			}

			// This crypted block is the new previous crypted block
			$prevCryptedBlock = $thisCryptedBlock;
		}

		// Strip padding
		while(array_pop($c) != 0x80) {}
	}

	function _ofb(&$m, $iv, &$state, $nrounds, $keyschedule, $SBOX, $INVSBOX, $MULT2, $MULT3, $MULT9, $MULTB, $MULTD, $MULTE) {
		$blockSizeInBytes = Cryptojs_AES::_blocksize() * 4;
		$keystream = array_slice($iv, 0);

		// Encrypt each byte
		for ($i = 0; $i < count($m); $i++) {
			// Generate keystream
			if ($i % $blockSizeInBytes == 0)
				Cryptojs_AES::_encryptblock($keystream, 0, $state, $nrounds, $keyschedule, $SBOX, $INVSBOX, $MULT2, $MULT3, $MULT9, $MULTB, $MULTD, $MULTE);

			// Encrypt byte
			$m[$i] ^= $keystream[$i % $blockSizeInBytes];
		}
	}
}
endif;
?>

 

 

 

Download Semisecure Login Reimagined 3.2.1 (complete).

 

 


Mac

Mac

Seit über 20 Jahren beschäftige ich mich mit Themen aus dem Bereich IT. Mein Schwerpunkt liegt dabei auf Produkte aus dem Hause Microsoft. Dazu gehören neben Active Directory und Windows Server insbesondere Netzwerkdienste wie DNS, DFS und DHCP. Zudem bin ich ein großer Verfechter des Internet Information Service, also dem Windows Webserver. Berührungspunkte im Bereich Citrix XenApp sowie XenDesktop, als auch VMware runden meinen Erfahrungsschatz ab.

3 Kommentare

Michal · 23. Dezember 2014 um 13:41

Very useful. Big thanks for sharing.

GC · 22. Juli 2014 um 07:12

Wow… thanks for taking care of this and posting a fix!!

Peter · 31. Mai 2012 um 03:23

Danke! This is very helpful.

Schreibe eine Antwort zu MichalAntwort abbrechen

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.