Created
September 12, 2012 07:01
-
-
Save mwgamera/3704830 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
$serverSecret = "The quick fire fox jumps over the lazy server."; | |
require_once 'lib/Twig/Autoloader.php'; | |
Twig_Autoloader::register(); | |
$twig = new Twig_Environment(new Twig_Loader_Filesystem('./')); | |
require_once 'TwigObfuscator.php'; | |
$o = new TwigObfuscator($serverSecret); | |
$twig->addExtension($o); | |
if ($_SERVER['QUERY_STRING']) { | |
$o->seed($_SERVER['QUERY_STRING']); | |
header('Content-type: application/ecmascript; charset=us-ascii'); | |
echo $twig->render('demo_loadkey.js.twig'); | |
} | |
else { | |
echo $twig->render('demo_index.html.twig', array( | |
'people' => array( | |
array( | |
'name' => 'user1', | |
'mail' => '[email protected]', | |
), | |
array( | |
'name' => 'user2', | |
'mail' => '[email protected]', | |
), | |
array( | |
'name' => 'user3', | |
'mail' => '[email protected]' | |
) | |
), | |
'message' => 'Zażółć gęślą jaźń!' | |
)); | |
} | |
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Obfuscator demo</title> | |
<script type="application/ecmascript" src="obfuscator.min.js" defer="defer"></script> | |
<script type="application/ecmascript" src="?{{ obfuscator.seed }}" defer="defer"></script> | |
<script type="application/ecmascript"> | |
window.onload = function() { | |
document.getElementById('message').innerHTML = | |
klg.obfuscator.decode({{ message|obfuscate|json_encode|raw }}); | |
}; | |
</script> | |
</head> | |
<body> | |
<h1>Obfuscator demo</h1> | |
<h2>List of e-mails</h2> | |
<ul> | |
{% for dweeb in people %} | |
<li><a href="" data-xhref="{{ ("mailto:" ~ dweeb.mail)|obfuscate }}" onmouseover="klg.obfuscator.href(this)">{{ dweeb.name }}</a></li> | |
{% endfor %} | |
</ul> | |
<div id="message"></div> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
klg.obfuscator.setKey({{ obfuscator.key|json_encode|raw }}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(j){"use strict";function h(a){for(var a=k(a),b=i,c,e=a[0],f,d,g=2654435769*(0|6+52/a.length);0<g;){f=g>>>2;for(d=a.length-1;0<=d;d--)c=a[(a.length+d-1)%a.length],a[d]-=(c>>>5^e<<2)+(e>>>3^c<<4)^(g^e)+(b[(d^f)&3]^c),e=a[d]&=4294967295;g-=2654435769}c="";for(b=1;b<a.length;b++)c+=String.fromCharCode(a[b]>>>24&255,a[b]>>>16&255,a[b]>>>8&255,a[b]>>>0&255);for(b=c.length-1;0<=b&&!c.charCodeAt(b);)--b;return decodeURIComponent(escape(c.substring(0,b+1)))}var i=void 0,k=function(a){return function(b){var c, | |
e,f,d=[],b=b.replace(/\s+/g,"");for(c=0;c<b.length;c+=5){for(f=0,e=4;0<=e;e--)f*=85,f+=0|a[b.charCodeAt(c+e)];d.push(f)}return d}}(function(){for(var a=[],b=0;85>b;b++)a["0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%()*+,-/:;=?@^_`{|}~".charCodeAt(b)]=b;return a}());return j.obfuscator={setKey:function(a){i=a},decode:h,href:function(a){var b=a.dataset&&a.dataset.a||a.getAttribute("data-xhref")||a.title||a.name;return a.href=h(b)}}})("undefined"!==typeof module&&module.exports|| | |
window.klg||(window.klg={})); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class ObfuscatorUnconfiguredException extends Exception {} | |
class TwigObfuscator extends Twig_Extension { | |
// Tentative name until I get more fluent with | |
// modern conventions and autoloader features. | |
public function getName() { | |
return "obfuscator"; | |
} | |
public function getGlobals() { | |
return array( | |
'obfuscator' => $this | |
); | |
} | |
public function getFilters() { | |
return array( | |
'obfuscate' => new Twig_Filter_Method($this, 'obfuscate', array( | |
'needs_environment' => true, | |
'is_safe' => array('html') | |
)) | |
); | |
} | |
const SEED_LENGTH = 16; | |
const KEY_ROUNDS = 20; | |
const ALPHA85 = | |
'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%()*+,-/:;=?@^_`{|}~'; | |
private $secret; | |
private $seed, $key; | |
public function __construct($secret = null, $seed = null) { | |
$this->secret = (string) $secret; | |
$this->seed = (string) $seed; | |
} | |
/** Set server secret */ | |
public function set_secret($secret) { | |
$this->secret = $secret; | |
$this->key = null; | |
} | |
/** Get and/or set seed used to generate the key. */ | |
public function seed($seed = null) { | |
if ($seed) { | |
$this->seed = (string) $seed; | |
$this->key = null; | |
} | |
if (!$this->seed) | |
$this->seed = self::make_seed(); | |
return $this->seed; | |
} | |
/** Get encryption key. */ | |
public function key() { | |
if (!$this->key) | |
$this->key = self::make_key($this->seed()); | |
return $this->key; | |
} | |
/** Obfuscate a string by encrypting it. */ | |
public function obfuscate(Twig_Environment $env, $value) { | |
if (function_exists('mb_convert_encoding')) | |
$value = mb_convert_encoding($value, 'UTF-8', $env->getCharset()); | |
$k = $this->key(); | |
$d = self::xxtea_enc(self::strpack($value), $k); | |
return self::ascii85($d); | |
} | |
/** Generate a seed. */ | |
private static function make_seed() { | |
$length = (int) ((self::SEED_LENGTH + 3) / 4); | |
$s = ""; | |
while ($length--) | |
$s .= sprintf("%08x", self::sha1rand()); | |
return $s; | |
} | |
/** Derive a key from the seed. */ | |
private function make_key($seed) { | |
if (!$this->secret) | |
throw new ObfuscatorUnconfiguredException("Server secret not set."); | |
$s = $this->secret . $seed . $this->secret; | |
$r = self::KEY_ROUNDS; | |
while ($r-- > 0) | |
$s = $this->secret . sha1($s, true) . $seed; | |
$s = sha1($s); | |
$a = array(); | |
$a[] = 0xffffffff & hexdec(substr($s, 0, 8)); | |
$a[] = 0xffffffff & hexdec(substr($s, 8, 8)); | |
$a[] = 0xffffffff & hexdec(substr($s,16, 8)); | |
$a[] = 0xffffffff & hexdec(substr($s,24, 8)); | |
return $a; | |
} | |
/** Secure-ish PRNG based on the SHA1 primitive. */ | |
private static function sha1rand($more_entropy = false) { | |
static $pad, $ctr = 0; | |
// seeding | |
if (!$ctr) { | |
$pad = @implode("\x1f", @array_values(@fstat(@fopen(__FILE__, 'r')))); | |
$pad.= "\x1e". @implode("\x1f", @array_values($_REQUEST)); | |
$pad.= "\x1e". @implode("\x1f", @array_values($_SERVER)); | |
$more_entropy = true; | |
} | |
if ($more_entropy) { | |
$pad .= "\x1e". microtime() . rand() . uniqid(mt_rand(), true); | |
if ($krng = @fopen('/dev/urandom', 'rb')) { | |
if (function_exists('stream_set_read_buffer')) | |
@stream_set_read_buffer($krng, 0); | |
$pad .= @fread($krng, 20); | |
@fclose($krng); | |
} | |
} | |
// actual PRNG | |
$pad = sha1($pad ."\x1f". ++$ctr, true); | |
return 0xffffffff & hexdec(substr(sha1($pad), 0, 8)); | |
} | |
/** Convert string to array of words for encryption. */ | |
private static function strpack($str) { | |
do $str .= "\0\0\0\0"; | |
while (mt_rand(0,1)); | |
$arr = array_values(unpack('N*', $str)); | |
array_unshift($arr, self::sha1rand()); // 32-bit IV | |
return array_pad($arr, 2, 0); | |
} | |
/** Encrypt block of data with XXTEA algorithm. */ | |
private static function xxtea_enc($data, $key) { | |
$n = count($data); | |
$z = $data[$n-1]; | |
$q = (int) (6 + 52 / count($data)); | |
$s = 0; | |
while ($q-- > 0) { | |
$s = 0xffffffff & ($s + 0x9e3779b9); | |
$e = $s >> 2; | |
for ($p = 0; $p < $n; $p++) { | |
$y = $data[($p+1)%$n]; | |
$a = ($z >> 5 & 0x07ffffff) ^ $y << 2; | |
$b = ($y >> 3 & 0x1fffffff) ^ $z << 4; | |
$a = 0xffffffff & ($a + $b); | |
$b = 0xffffffff & (($s ^ $y) + ($key[($p ^ $e) & 3] ^ $z)); | |
$z = 0xffffffff & ($data[$p] + ($a ^ $b)); | |
$data[$p] = $z; | |
} | |
} | |
return $data; | |
} | |
/** Encode 32b words as safe text. */ | |
private static function ascii85($data) { | |
$str = ''; | |
foreach ($data as $u32) { | |
for ($i = 0; $i < 5; $i++) { | |
$str .= substr(self::ALPHA85, $u32 % 85, 1); | |
$u32 /= 85; | |
} | |
} | |
return $str; | |
} | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment