Looking for 'real' encryption? Start here.
|
Tobia Forcella
Registered User
Join date: 4 Mar 2007
Posts: 30
|
04-20-2007 05:42
Nobody still working on this project?  
|
Sys Slade
Registered User
Join date: 15 Feb 2007
Posts: 626
|
04-20-2007 05:51
No posts in 24 hours and you think it's dead? /me hands Tobia a glass of patience
Both Robby and Newgate are tackling new languages, and have RL stuff to do. Give it some time.
|
Tobia Forcella
Registered User
Join date: 4 Mar 2007
Posts: 30
|
04-20-2007 06:06
hey no problem Syd, only to know  i'm working on it and can't find a solution; i can pay for it and share with the community! 
|
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
|
04-20-2007 08:06
From: Tobia Forcella Nobody still working on this project?   As has already been posted there are other things demanding my attention I'm afraid. I will however endeavour to revisit this problem when I have a few moments to spare. Can you confirm that the different PHP implementations you have used return the same encrypted values for the same key?
|
Tobia Forcella
Registered User
Join date: 4 Mar 2007
Posts: 30
|
04-20-2007 08:32
From: someone Can you confirm that the different PHP implementations you have used return the same encrypted values for the same key? the mcrypt version of Xtea give a different result than the pear package: word to encrypt: test key: 0123456789abcdef Pear: 03e3fc60351a3fdd mcrypt: 6c302719dd265d3f but i tested it on various server, always the same results. Some posts ago there is the code i used. I can use pear or mcrypt in my project, i don't have a preference  Thank you very much.
|
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
|
04-20-2007 12:46
From: Tobia Forcella the mcrypt version of Xtea give a different result than the pear package: word to encrypt: test key: 0123456789abcdef Pear: 03e3fc60351a3fdd mcrypt: 6c302719dd265d3f but i tested it on various server, always the same results. Some posts ago there is the code i used. I can use pear or mcrypt in my project, i don't have a preference  Thank you very much. Each installation gave the same results with each package, and was platform/os independant? Thats good to know, it shows that the two packages use different implementations of XTEA. Probably just the number of rounds but could also be some other subtle difference like parenthasis. I have a shed load of work that I am commited to finishing this weekend, both RL and SL, but will hopefully have time to play with this problem at some point.
|
jefferey Heart
Registered User
Join date: 25 Jan 2006
Posts: 45
|
Optimized version not working
04-21-2007 08:09
Anyone else get this Optimized version working right?
|
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
|
04-25-2007 00:42
Another thought has occurred to me but I have not had time to test. It was previously mentioned that LSL doesnt allow unsigned ints and also that PHP is teh same. Looking at the posted PHP code it supplies its own functions for shifting and adding to by pass PHP's signed function. I think we may need to implement something similar. In fact I think I will try and implement a near direct translation of the PHP script and see if that works.
|
RobbyRacoon Olmstead
Red warrior is hungry!
Join date: 20 Sep 2006
Posts: 1,821
|
04-25-2007 07:44
From: Newgate Ludd Another thought has occurred to me but I have not had time to test. It was previously mentioned that LSL doesnt allow unsigned ints and also that PHP is teh same. Looking at the posted PHP code it supplies its own functions for shifting and adding to by pass PHP's signed function. I think we may need to implement something similar. In fact I think I will try and implement a near direct translation of the PHP script and see if that works. I was under the impression that the LSL versions did that as well, but it's been a while since I looked at the code and I am not certain. That code bounty I offered is still open if you succeed  .
|
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
|
04-25-2007 08:08
From: RobbyRacoon Olmstead I was under the impression that the LSL versions did that as well, but it's been a while since I looked at the code and I am not certain. That code bounty I offered is still open if you succeed  . The library script referenced in the OP doesnt. If I can clear my current (over due) workload I'll have a play.
|
ViktorScorich Villota
Registered User
Join date: 15 Apr 2007
Posts: 4
|
'Real' Encryption
04-25-2007 08:28
Asymmetric Encryption Anyone? On top of that... Replace llFrand https://wiki.secondlife.com/wiki/LlFrandom https://jira.secondlife.com/browse/SVC-134The Primes and might be an issue....
|
SleightOf Hand
Registered User
Join date: 4 Apr 2006
Posts: 21
|
PHP and LSL compatible XTEA and Code
05-22-2007 00:01
Masakazu Kojima gave a good general method of implimenting the XTEA encryptionm and i based my PHP code from that and modified the LSL code to make it a more relable with Key generation and Compactness of the encrypted String. Following is the LSL, PHP code and Results from both for people to view. //************************************************// //* Masa's XTEA encryption/decryption v3 *// //* Modified by SleightOf Hand for Stability and *// //* intercommunication with PHP version *// //************************************************// // NOTE: This version only encodes 60 bits per 64-bit block! // This code is public domain. // Sleight was here 20070522 // masa was here 20070315 // so was strife 20070315 // // This was Modified by SleightOf Hand to allow // Strong encryption between LSL and PHP. //************************************************// //* XTEA IMPLEMENTATION *// //************************************************// integer XTEA_DELTA = 0x9E3779B9; // (sqrt(5) - 1) * 2^31 integer xtea_num_rounds = 32; list xtea_key = [0, 0, 0, 0]; integer hex2int(string hex) { if(llGetSubString(hex,0,1) == "0x") return (integer)hex; if(llGetSubString(hex,0,0) == "x") return (integer)("0"+hex); return(integer)("0x"+hex); } // Convers any string to a 32 char MD5 string and then to a list of // 4 * 32 bit integers = 128 bit Key. MD5 ensures always a specific // 128 bit key is generated for any string passed. list xtea_key_from_string( string str ) { str = llMD5String(str,0); // Use Nonce = 0 return [ hex2int(llGetSubString( str, 0, 7)), hex2int(llGetSubString( str, 8, 15)), hex2int(llGetSubString( str, 16, 23)), hex2int(llGetSubString( str, 24, 31))]; } // Encipher two integers and return the result as a 12-byte string // containing two base64-encoded integers. string xtea_encipher( integer v0, integer v1 ) { integer num_rounds = xtea_num_rounds; integer sum = 0; do { // LSL does not have unsigned integers, so when shifting right we // have to mask out sign-extension bits. v0 += (((v1 << 4) ^ ((v1 >> 5) & 0x07FFFFFF)) + v1) ^ (sum + llList2Integer(xtea_key, sum & 3)); sum += XTEA_DELTA; v1 += (((v0 << 4) ^ ((v0 >> 5) & 0x07FFFFFF)) + v0) ^ (sum + llList2Integer(xtea_key, (sum >> 11) & 3)); } while( num_rounds = ~-num_rounds ); //return only first 6 chars to remove "=="'s and compact encrypted text. return llGetSubString(llIntegerToBase64(v0),0,5) + llGetSubString(llIntegerToBase64(v1),0,5); } // Decipher two base64-encoded integers and return the FIRST 30 BITS of // each as one 10-byte base64-encoded string. string xtea_decipher( integer v0, integer v1 ) { integer num_rounds = xtea_num_rounds; integer sum = XTEA_DELTA*xtea_num_rounds; do { // LSL does not have unsigned integers, so when shifting right we // have to mask out sign-extension bits. v1 -= (((v0 << 4) ^ ((v0 >> 5) & 0x07FFFFFF)) + v0) ^ (sum + llList2Integer(xtea_key, (sum>>11) & 3)); sum -= XTEA_DELTA; v0 -= (((v1 << 4) ^ ((v1 >> 5) & 0x07FFFFFF)) + v1) ^ (sum + llList2Integer(xtea_key, sum & 3)); } while ( num_rounds = ~-num_rounds ); return llGetSubString(llIntegerToBase64(v0), 0, 4) + llGetSubString(llIntegerToBase64(v1), 0, 4); } // Encrypt a full string using XTEA. string xtea_encrypt_string( string str ) { // encode string str = llStringToBase64(str); // remove trailing =s so we can do our own 0 padding integer i = llSubStringIndex( str, "=" ); if ( i != -1 ) str = llDeleteSubString( str, i, -1 ); // we don't want to process padding, so get length before adding it integer len = llStringLength(str); // zero pad str += "AAAAAAAAAA="; string result; i = 0; do { // encipher 30 (5*6) bits at a time. result += xtea_encipher( llBase64ToInteger(llGetSubString(str, i, i += 4) + "A="), llBase64ToInteger(llGetSubString(str, ++i, i += 4) + "A=") ); } while ( ++i < len ); return result; } // Decrypt a full string using XTEA string xtea_decrypt_string( string str ) { integer len = llStringLength(str); integer i; string result; do { result += xtea_decipher( llBase64ToInteger(llGetSubString(str, i, i += 5) + "=="), llBase64ToInteger(llGetSubString(str, ++i, i += 5) + "==") ); } while ( ++i < len ); // Replace multiple trailing zeroes with a single one i = llStringLength(result); while ( llGetSubString(result, --i, i) == "A" ); result = llGetSubString(result, 0, i); i = llStringLength(result); integer mod = i%4; //Depending on encoded length diffrent appends are needed if(mod == 1) return llBase64ToString(result + "A=="); else if(mod == 2 ){ if((llSubStringIndex(base64,llGetSubString(result, -1,-1))) & 0x0F) return llBase64ToString(result + "A="); else return llBase64ToString(result + "=="); } else if(mod == 3){ if((llSubStringIndex(base64,llGetSubString(result, -1,-1))) & 0x03) return llBase64ToString(result + "A"); return llBase64ToString(result + "="); } return llBase64ToString( result ); } //************************************************// //* TESTS *// //************************************************// integer test_assertions = 0; integer test_failures = 0; test_assert( integer condition, string description ) { ++test_assertions; if ( !condition ) { ++test_failures; llOwnerSay( "ASSERTION FAILED: " + description ); } else llOwnerSay("ASSERTION SUCCEEDED: "); } test_assert_equal( string v1, string v2, string desc ) { test_assert( v1 == v2, desc + "\nACTUAL=" + v1 + "\nEXPECTED=" + v2 ); } test_xtea_encipher() { xtea_num_rounds = 6; xtea_key = [0x74736574, 0x2c676e69, 0x74736574, 0x2e676e69]; test_assert_equal( xtea_encipher(0x62626161, 0x64646363), llIntegerToBase64(0x5117f04b) + llIntegerToBase64(0xb9f38d3c), "xtea_encipher(rounds=6, string=\"aabbccdd\"," + "key=\"testing,testing.\") vs std" ); xtea_num_rounds = 16; xtea_key = [0x24234021, 0x2a265e25, 0x2b5f2928, 0x5d5b7d7b]; test_assert_equal( xtea_encipher(0x74536554, 0x23476e49), llIntegerToBase64(0xe9306ed2) + llIntegerToBase64(0x8f983d5a), "xtea_encipher(rounds=16, string=\"TeStInG#\"," + "key=\"!@#$%^&*()_+{}[]\") vs std" ); xtea_num_rounds = 32; xtea_key = [0x20202020, 0x20202020, 0x20202020, 0x20202020]; test_assert_equal( xtea_encipher(0x20202020, 0x20202020), llIntegerToBase64(0xb63a89e3) + llIntegerToBase64(0x8631c79c), "xtea_encipher(rounds=32, string=\" \"," + "key=\" \") vs std" ); } test_timed_encrypt(integer num_rounds, string str, string k) { string encrypted; string decrypted; integer len = llStringLength(str); string info = "rounds=" + (string)num_rounds + ", len=" + (string)len; xtea_num_rounds = num_rounds; xtea_key = xtea_key_from_string(k); llOwnerSay("Encrypting : " + str); llResetTime(); encrypted = xtea_encrypt_string(str); llOwnerSay( "enc(" + info + "): " + (string)llGetTime() ); llOwnerSay("Encrypted to : " + encrypted); llResetTime(); decrypted = xtea_decrypt_string(encrypted); llOwnerSay( "dec(" + info + "): " + (string)llGetTime() ); llOwnerSay("Decrypted to : " + decrypted ); test_assert( str == decrypted, "test_timed_encrypt(" + (string)num_rounds + "," + "\"" + str + "\", \"" + k + "\") -- \"" + decrypted + "\"" ); } test_xtea_encrypt_string() { test_timed_encrypt(64, llUnescapeURL("%E4%BD%95"), "unicode test"); test_timed_encrypt(64, llUnescapeURL("%E6%94%BF%E5%92%8C%E5%B0%8F%E5%B3%B6"), "unicode test 2" ); test_timed_encrypt(64, "hello", "test"); test_timed_encrypt(64, "small test", "small key"); test_timed_encrypt(64, llEscapeURL(",xaYGp:?iThL *+\"I8!6qGA0eSXCUG1fXxNl'\"T0_" + "Un.P:u/= N{2{!L -]'mg-89p.on9zjfEJ<lZW;gJ;d" + "3:u CFK+|qMqmhaI0"), "here is a key"); test_timed_encrypt(32, "hello", "test"); test_timed_encrypt(32, "small test", "small key"); test_timed_encrypt(32, llEscapeURL(",xaYGp:?iThL *+\"I8!6qGA0eSXCUG1fXxNl'\"T0_" + "Un.P:u/= N{2{!L -]'mg-89p.on9zjfEJ<lZW;gJ;d" + "3:u CFK+|qMqmhaI0"), "here is a key"); test_timed_encrypt( 6, "hello", "test"); test_timed_encrypt( 6, "small test", "small key"); test_timed_encrypt( 6, llEscapeURL(",xaYGp:?iThL *+\"I8!6qGA0eSXCUG1fXxNl'\"T0_" + "Un.P:u/= N{2{!L -]'mg-89p.on9zjfEJ<lZW;gJ;d" + "3:u CFK+|qMqmhaI0"), "here is a key"); } //************************************************// //* TEST DRIVER *// //************************************************// default { state_entry() { // test_xtea_encipher(); test_xtea_encrypt_string(); llOwnerSay( "assertions: " + (string)test_assertions + " / " + "failures: " + (string)test_failures ); llListen(0, "", llGetOwner(), "" ); } listen(integer channel, string name, key id, string msg) { test_timed_encrypt( 64, msg, id ); test_timed_encrypt( 32, msg, id ); test_timed_encrypt( 6, msg, id ); } }
PHP Code: <?php //************************************************// //* Sleight's PHP XTEA encryption/decryption v3 *// //* Modified by SleightOf Hand for Stability and *// //* intercommunication between PHP & LSL *// //************************************************// // NOTE: This version only encodes 60 bits per 64-bit block! // This code is public domain. // Sleight was here 20070522 // masa was here 20070315 // so was strife 20070315 // // This was converted from the LSL version by // SleightOf Hand to allow Strong encryption // between LSL and PHP. If you find this usefull // any donations apreciated. //************************************************// //* XTEA IMPLEMENTATION *// //************************************************// $_XTEA_DELTA = 0x9E3779B9; // (sqrt(5) - 1) * 2^31 $_xtea_num_rounds = 32; $_xtea_key = array(0, 0, 0, 0); $_base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ". "abcdefghijklmnopqrstuvwxyz". "0123456789+/"; // Returns Integer based on 8 byte Base64 Code XXXXXX== (llBase64ToInteger) function base64_integer($str){ global $_base64; if(strlen($str) != 8) return 0; return ((strpos($_base64,$str{0}) << 26)| (strpos($_base64,$str{1}) << 20)| (strpos($_base64,$str{2}) << 14)| (strpos($_base64,$str{3}) << 8) | (strpos($_base64,$str{4}) << 2) | (strpos($_base64,$str{5}) >> 4)); } // Returns 8 Byte Base64 code based on 32 bit integer ((llIntegerToBase64) function integer_base64($int){ global $_base64; if($int != (integer) $int) return 0; return $_base64{($int >> 26 & 0x3F)} . $_base64{($int >> 20 & 0x3F)} . $_base64{($int >> 14 & 0x3F)} . $_base64{($int >> 8 & 0x3F)} . $_base64{($int >> 2 & 0x3F)} . $_base64{($int << 4 & 0x3F)} . "=="; } //strict 32 bit addition using logic function binadd($val1 , $val2){ $ta = $val1 ^ $val2; while($tc = (($val1 & $val2) << 1) & 0x0FFFFFFFF){ $ta = ($val1 = $tc) ^ ($val2 = $ta); } return $ta; // $ta will now be the result so return it }
// Convers any string to a 32 char MD5 string and then to a list of // 4 * 32 bit integers = 128 bit Key. function xtea_key_from_string( $str ) { global $_xtea_key; $str = md5($str . ":0"); // Use nonce = 0 in LSL for same output eval("\$_xtea_key[0] = 0x" . substr($str,0,8) . ";"); eval("\$_xtea_key[1] = 0x" . substr($str,8,8) . ";"); eval("\$_xtea_key[2] = 0x" . substr($str,16,8) . ";"); eval("\$_xtea_key[3] = 0x" . substr($str,24,8) . ";"); } // Encipher two integers and return the result as a 12-byte string // containing two base64-encoded integers. function xtea_encipher( $v0 , $v1 ) { global $_xtea_num_rounds , $_xtea_key , $_XTEA_DELTA; $num_rounds = $_xtea_num_rounds; $sum = 0; do { // LSL only has 32 bit integers. However PHP automaticly changes // 32 bit integers to 64 bit floats as nessesary. This causes // incompatibilities between the LSL Encryption and the PHP // counterpart. I got round this by changing all addition to // binary addition using logical & and ^ and loops to handle bit // carries. This forces the 32 bit integer to remain 32 bits as // I mask out any carry over 32 bits. this bring the output of the // encrypt routine to conform with the output of its LSL counterpart. // LSL does not have unsigned integers, so when shifting right we // have to mask out sign-extension bits. // calculate ((($v1 << 4) ^ (($v1 >> 5) & 0x07FFFFFF)) + $v1) $v0a = binadd((($v1 << 4) ^ (($v1 >> 5) & 0x07FFFFFF)) , $v1); // calculate ($sum + $_xtea_key[$sum & 3]) $v0b = binadd($sum , $_xtea_key[$sum & 3]); // Calculate ($v0 + ((($v1 << 4) ^ (($v1 >> 5) & 0x07FFFFFF)) + $v1) // ^ ($sum + $_xtea_key[$sum & 3])) $v0 = binadd($v0 , ($v0a ^ $v0b)); //Calculate ($sum + $_XTEA_DELTA) $sum = binadd($sum , $_XTEA_DELTA); //Calculate ((($v0 << 4) ^ (($v0 >> 5) & 0x07FFFFFF)) + $v0) $v1a = binadd((($v0 << 4) ^ (($v0 >> 5) & 0x07FFFFFF)) , $v0); // Calculate ($sum + $_xtea_key[($sum >>11) & 3]) $v1b = binadd($sum , $_xtea_key[($sum >>11) & 3]); //Calculate ($v1 + ((($v0 << 4) ^ (($v0 >> 5) & 0x07FFFFFF)) + $v0 // ^ ($sum & $_xtea_key[($sum >>11) & 3])) $v1 = binadd($v1 , ($v1a ^ $v1b)); } while( $num_rounds = ~-$num_rounds ); //return only first 6 chars to remove "=="'s and compact encrypted text. return substr(integer_base64($v0),0,6) . substr(integer_base64($v1),0,6); } // Decipher two base64-encoded integers and return the FIRST 30 BITS of // each as one 10-byte base64-encoded string. function xtea_decipher( $v0, $v1 ) { global $_xtea_num_rounds , $_xtea_key , $_XTEA_DELTA; $num_rounds = $_xtea_num_rounds; $sum = 0; // $_XTEA_DELTA * $_xtea_num_rounds; $tda = $_XTEA_DELTA; do{ // Binary multiplication using binary manipulation if($num_rounds & 1){ $sum = binadd($sum , $tda); } $num_rounds = $num_rounds >> 1; $tda = ($tda << 1) & 0x0FFFFFFFF; }while($num_rounds); $num_rounds = $_xtea_num_rounds; // reset $num_rounds back to its propper setting; do { // LSL only has 32 bit integers. However PHP automaticly changes // 32 bit integers to 64 bit floats as nessesary. This causes // incompatibilities between the LSL Encryption and the PHP // counterpart. I got round this by changing all addition to // binary addition using logical & and ^ and loops to handle bit // carries. This forces the 32 bit integer to remain 32 bits as // I mask out any carry over 32 bits. this bring the output of the // decrypt routine to conform with the output of its LSL counterpart. // Subtrations are handled by using 2's compliment // LSL does not have unsigned integers, so when shifting right we // have to mask out sign-extension bits. // calculate ((($v0 << 4) ^ (($v0 >> 5) & 0x07FFFFFF)) + $v0) $v1a = binadd((($v0 << 4) ^ (($v0 >> 5) & 0x07FFFFFF)) , $v0); // calculate ($sum + $_xtea_key[($sum>>11) & 3]) $v1b = binadd($sum , $_xtea_key[($sum>>11) & 3]); //Calculate 2's compliment of ($v1a ^ $v1b) for subtraction $v1c = binadd((~($v1a ^ $v1b)) , 1); //Calculate ($v1 - ((($v0 << 4) ^ (($v0 >> 5) & 0x07FFFFFF)) + $v0) // ^ ($sum + $_xtea_key[($sum>>11) & 3])) $v1 = binadd($v1 , $v1c); // Calculate new $sum based on $num_rounds - 1 $tnr = $num_rounds - 1; // Temp $num_rounds $sum = 0; // $_XTEA_DELTA * ($num_rounds - 1); $tda = $_XTEA_DELTA; do{ // Binary multiplication using binary manipulation if($tnr & 1){ $sum = binadd($sum , $tda); } $tnr = $tnr >> 1; $tda = ($tda << 1) & 0x0FFFFFFFF; }while($tnr); //Calculate ((($v1 << 4) ^ (($v1 >> 5) & 0x07FFFFFF)) + $v1) $v0a = binadd((($v1 << 4) ^ (($v1 >> 5) & 0x07FFFFFF)) , $v1); //Calculate ($sum + $_xtea_key[$sum & 3]) $v0b = binadd($sum , $_xtea_key[$sum & 3]); //Calculate 2's compliment of ($v0a ^ $v0b) for subtraction $v0c = binadd((~($v0a ^ $v0b)) , 1); //Calculate ($v0 - ((($v1 << 4) ^ (($v1 >> 5) & 0x07FFFFFF)) + $v1 // ^ ($sum + $_xtea_key[$sum & 3])) $v0 = binadd($v0 , $v0c); } while ( $num_rounds = ~-$num_rounds ); return substr(integer_base64($v0), 0, 5) . substr(integer_base64($v1), 0, 5); } // Encrypt a full string using XTEA. function xtea_encrypt_string( $str ) { // encode Binany string to Base64 $str = base64_encode($str); // remove trailing =s so we can do our own 0 padding $i = strpos($str, '=', 0); if ( $i !== FALSE ){ $str = substr( $str, 0, $i); } // we don't want to process padding, so get length before adding it $len = strlen($str); // zero pad $str .= "AAAAAAAAAA="; $result = ""; $i = 0; do { // encipher 30 (5*6) bits at a time. $enc1 = base64_integer(substr($str , $i , 5) . "A=="); $i += 5; $enc2 = base64_integer(substr($str , $i , 5) . "A=="); $i += 5; $result .= xtea_encipher($enc1, $enc2); } while ( $i < $len ); return $result; //Return Encrypted string } // Decrypt a full string using XTEA function xtea_decrypt_string( $str ) { global $_base64 ; $len = strlen($str); $i; $result; do { $dec1 = base64_integer(substr($str , $i , 6)."=="); $i += 6; $dec2 = base64_integer(substr($str , $i , 6)."=="); $i += 6; $result .= xtea_decipher( $dec1, $dec2); } while ( $i < $len ); // Replace multiple trailing zeroes with a single one $i = strlen($result); while ( substr($result, --$i, 1) == "A" ); $result = substr($result, 0, $i+1); $i = strlen($result); $mod = $i%4; //Depending on encoded length diffrent appends are needed if($mod == 1) return base64_decode($result . "A=="); else if($mod == 2 ){ if((strpos($_base64,substr($result, -1,1))) & 0x0F) return base64_decode($result . "A="); else return base64_decode($result . "=="); } else if($mod == 3){ if((strpos($_base64,substr($result, -1,1))) & 0x03) return base64_decode($result . "A"); else return base64_decode($result . "="); } return base64_decode( $result );
} //************************************************// //* TESTS *// //************************************************// $_test_assertions = 0; $_test_failures = 0; function test_assert($condition, $description ) { global $_test_failures , $_test_assertions; ++$_test_assertions; if ( !$condition ) { ++$_test_failures; echo ( "ASSERTION FAILED: " . $description . "<p>"); } else echo ( "ASSERTION SUCCEEDED: <p>" ); } function test_assert_equal( $v1, $v2, $desc ) { test_assert( $v1 == $v2, $desc . "<br>ACTUAL=" . $v1 . "<br>EXPECTED=" . $v2 ); } function test_timed_encrypt($num_rounds, $str, $k) { global $_xtea_num_rounds, $_xtea_key; $encrypted; $decrypted; $len = strlen($str); $info = "rounds=" . (string) $num_rounds . ", len=" . (string) $len; $_xtea_num_rounds = $num_rounds; xtea_key_from_string($k); $CurrTime = time(); echo "Encrypting : " . $str . "<p>"; $encrypted = xtea_encrypt_string($str); echo "Encrypted to : " . $encrypted . "<p>"; $CurrTime = time(); $decrypted = xtea_decrypt_string($encrypted); echo "Decrypted to : " . $decrypted . "<p>"; test_assert( !strcmp($str,$decrypted), "test_timed_encrypt(" . $num_rounds . "," . "\"" . $str . "\", \"" . $k . "\") -- \"" . $decrypted . "\"" ); } function test_xtea_encrypt_string() { test_timed_encrypt(64, urldecode("%E4%BD%95"), "unicode test"); test_timed_encrypt(64, urldecode("%E6%94%BF%E5%92%8C%E5%B0%8F%E5%B3%B6"), "unicode test 2" ); test_timed_encrypt(64, "hello", "test"); test_timed_encrypt(64, "small test", "small key"); test_timed_encrypt(64, urlencode(",xaYGp:?iThL *+\"I8!6qGA0eSXCUG1fXxNl'\"T0_" . "Un.P:u/= N{2{!L -]'mg-89p.on9zjfEJ<lZW;gJ;d" . "3:u CFK+|qMqmhaI0"), "here is a key"); test_timed_encrypt(32, "hello", "test"); test_timed_encrypt(32, "small test", "small key"); test_timed_encrypt(32, urlencode(",xaYGp:?iThL *+\"I8!6qGA0eSXCUG1fXxNl'\"T0_" . "Un.P:u/= N{2{!L -]'mg-89p.on9zjfEJ<lZW;gJ;d" . "3:u CFK+|qMqmhaI0"), "here is a key"); test_timed_encrypt( 6, "hello", "test"); test_timed_encrypt( 6, "small test", "small key"); test_timed_encrypt( 6, urlencode(",xaYGp:?iThL *+\"I8!6qGA0eSXCUG1fXxNl'\"T0_" . "Un.P:u/= N{2{!L -]'mg-89p.on9zjfEJ<lZW;gJ;d" . "3:u CFK+|qMqmhaI0"), "here is a key"); } //************************************************// //* TEST DRIVER *// //************************************************// test_xtea_encrypt_string(); echo ( "assertions: " . (string)$_test_assertions . " / " . "failures: " . (string)($_test_failures )); ?>
Results from LSL : Encrypting : 何 enc(rounds=64, len=1): 2.517058 Encrypted to : 8HwqOQkyYGWA dec(rounds=64, len=1): 2.492023 Decrypted to : 何 ASSERTION SUCCEEDED: Encrypting : 政和小島 enc(rounds=64, len=4): 4.739208 Encrypted to : 1b34tA6OFuLQlcsltAV8MJEw dec(rounds=64, len=4): 4.731294 Decrypted to : 政和小島 ASSERTION SUCCEEDED: Encrypting : hello enc(rounds=64, len=5): 2.335077 Encrypted to : yMYYiQL9v5JQ dec(rounds=64, len=5): 2.429809 Decrypted to : hello ASSERTION SUCCEEDED: Encrypting : small test enc(rounds=64, len=10): 4.581894 Encrypted to : +xuQagkp0FmQFQUtfQHbISsA dec(rounds=64, len=10): 4.835964 Decrypted to : small test ASSERTION SUCCEEDED: Encrypting : %2CxaYGp%3A%3FiThL%20%2A%2B%22I8%216qGA0eSXCUG1fXxNl%27%22T0%5FUn%2EP%3Au%2F%3D%20N%7B2%7B%21L%20%2D%5D%27mg%2D89p%2Eon9zjfEJ%3ClZW%3BgJ%3Bd3%3Au%20CFK%2B%7CqMqmhaI0 enc(rounds=64, len=165): 54.701614 Encrypted to : forJbQQRunRQtRc1xgAKHgwQ7q8QkQrwFtgAbE5RVANKKZLAtDql5QItcjpQP065bgxQ+XcAc3m07QSTZPgAEdEKRQfqwoBQICSOBARzr5LQmw/UHQ0mAK0QEwuoHQ/PbwrQPRXbuwkO51jQwq+uHQt2JS0Q0pCN2A4G73SwjUbvIwWHFVLg3XvRPgCEJiFgE3duuAKwlBqQojEF8Qk6pQeA/8l/cAXtBSVQ92P93wmH762QThu/HApJzfNA0X/VvgSeIfsQ dec(rounds=64, len=165): 54.852505 Decrypted to : %2CxaYGp%3A%3FiThL%20%2A%2B%22I8%216qGA0eSXCUG1fXxNl%27%22T0%5FUn%2EP%3Au%2F%3D%20N%7B2%7B%21L%20%2D%5D%27mg%2D89p%2Eon9zjfEJ%3ClZW%3BgJ%3Bd3%3Au%20CFK%2B%7CqMqmhaI0 ASSERTION SUCCEEDED: Encrypting : hello enc(rounds=32, len=5): 1.166722 Encrypted to : OtvxrQO/zCMQ dec(rounds=32, len=5): 1.516466 Decrypted to : hello ASSERTION SUCCEEDED: Encrypting : small test enc(rounds=32, len=10): 2.642615 Encrypted to : L29pOwiRNMAASDdpZgYOKXtw dec(rounds=32, len=10): 2.712204 Decrypted to : small test ASSERTION SUCCEEDED: Encrypting : %2CxaYGp%3A%3FiThL%20%2A%2B%22I8%216qGA0eSXCUG1fXxNl%27%22T0%5FUn%2EP%3Au%2F%3D%20N%7B2%7B%21L%20%2D%5D%27mg%2D89p%2Eon9zjfEJ%3ClZW%3BgJ%3Bd3%3Au%20CFK%2B%7CqMqmhaI0 enc(rounds=32, len=165): 28.061316 Encrypted to : XAbCDwIM3+Dg3dQB0ApFhWtww3ee0wnn81KgYVh+vgn4LZdQhGqzKgkBziMAOBtFWAntMolg3a/PewDQNYIwwXZZYwjLJJbg8Zx7mAFBcD8wGWAMMQyzUyHQqqT5lwBaxOhgjeigqAB/pz1gmWDvxQhefwKgm6gRAw/JqCIwMr6KEQCfjCEAPK6QoAChnrCA9UGtYwuYxUlAUT3uigp7KhgAxuXSrw92bmSgrXZofwmPZZlgvjLltAH5915wSGWHuw5lWN5Q dec(rounds=32, len=165): 27.892733 Decrypted to : %2CxaYGp%3A%3FiThL%20%2A%2B%22I8%216qGA0eSXCUG1fXxNl%27%22T0%5FUn%2EP%3Au%2F%3D%20N%7B2%7B%21L%20%2D%5D%27mg%2D89p%2Eon9zjfEJ%3ClZW%3BgJ%3Bd3%3Au%20CFK%2B%7CqMqmhaI0 ASSERTION SUCCEEDED: Encrypting : hello enc(rounds=6, len=5): 0.494484 Encrypted to : zBE6gwElLiOQ dec(rounds=6, len=5): 0.618669 Decrypted to : hello ASSERTION SUCCEEDED: Encrypting : small test enc(rounds=6, len=10): 0.940793 Encrypted to : g6Yd4w8iJULAykugogyLKRAA dec(rounds=6, len=10): 1.111868 Decrypted to : small test ASSERTION SUCCEEDED: Encrypting : %2CxaYGp%3A%3FiThL%20%2A%2B%22I8%216qGA0eSXCUG1fXxNl%27%22T0%5FUn%2EP%3Au%2F%3D%20N%7B2%7B%21L%20%2D%5D%27mg%2D89p%2Eon9zjfEJ%3ClZW%3BgJ%3Bd3%3Au%20CFK%2B%7CqMqmhaI0 enc(rounds=6, len=165): 8.037796 Encrypted to : T/F8GAVZe64QM9BrSAfh0tDAKOXyZQiIcqjQVjaoRw5P3l0wqPKbYArc2CjQg+0BQgjbtu9wwJes2gQ9iyfwHamm8AFC4bUw1a4EOgAOwVoQfU/CXQT9j7iQNYh8QAfwy/0g6yYxmQ6emSjA2ZATFgqNmB3g6IqaogFMfn1QRFjq7AiVjK8ApH3MEQ+IFTqwJcxONQgQHZpwdyEl8g6tMq9QmlFzjwnNx8zQRsOVSAXb9y3AW22gaw6eJj7wRBeWbAHS9a6A dec(rounds=6, len=165): 8.228614 Decrypted to : %2CxaYGp%3A%3FiThL%20%2A%2B%22I8%216qGA0eSXCUG1fXxNl%27%22T0%5FUn%2EP%3Au%2F%3D%20N%7B2%7B%21L%20%2D%5D%27mg%2D89p%2Eon9zjfEJ%3ClZW%3BgJ%3Bd3%3Au%20CFK%2B%7CqMqmhaI0 ASSERTION SUCCEEDED: assertions: 11 / failures: 0
and Finaly PHP Results : Discrepencies in the Encrypted strings are a result of diffrences in results from llEscapeURL() and urlencode() in LSL and PHP and not from the actual encryption process. Encrypting : 何 Encrypted to : 8HwqOQkyYGWA Decrypted to : 何 ASSERTION SUCCEEDED: Encrypting : 政和�島 Encrypted to : 1b34tA6OFuLQlcsltAV8MJEw Decrypted to : 政和�島 ASSERTION SUCCEEDED: Encrypting : hello Encrypted to : yMYYiQL9v5JQ Decrypted to : hello ASSERTION SUCCEEDED: Encrypting : small test Encrypted to : +xuQagkp0FmQFQUtfQHbISsA Decrypted to : small test ASSERTION SUCCEEDED: Encrypting : %2CxaYGp%3A%3FiThL+%2A%2B%22I8%216qGA0eSXCUG1fXxNl%27%22T0_Un.P%3Au%2F%3D+N%7B2%7B%21L+-%5D%27mg-89p.on9zjfEJ%3ClZW%3BgJ%3Bd3%3Au+CFK%2B%7CqMqmhaI0 Encrypted to : forJbQQRunRQtRc1xgAKHgwQT3kvlw6dabjANRFqDgwsqBzA2IFQJwn2gueQmGotYQ0U/J+QZfS50wVLhWfg4QDelQ9Vqp5gJb/XOQgA5cowxHEyaQPIIYzA8f4vLwzA4rJglzErCg9nYBqQUmamAQa4HeRAwYevVQXJSNWA8+3gbwP0DB7QIsYpXA4uqmJg5gJcOgpKYTQwdQnN1wIraZyw964mXgdqpmCAJJMbAgE2Ht3w Decrypted to : %2CxaYGp%3A%3FiThL+%2A%2B%22I8%216qGA0eSXCUG1fXxNl%27%22T0_Un.P%3Au%2F%3D+N%7B2%7B%21L+-%5D%27mg-89p.on9zjfEJ%3ClZW%3BgJ%3Bd3%3Au+CFK%2B%7CqMqmhaI0 ASSERTION SUCCEEDED: Encrypting : hello Encrypted to : OtvxrQO/zCMQ Decrypted to : hello ASSERTION SUCCEEDED: Encrypting : small test Encrypted to : L29pOwiRNMAASDdpZgYOKXtw Decrypted to : small test ASSERTION SUCCEEDED: Encrypting : %2CxaYGp%3A%3FiThL+%2A%2B%22I8%216qGA0eSXCUG1fXxNl%27%22T0_Un.P%3Au%2F%3D+N%7B2%7B%21L+-%5D%27mg-89p.on9zjfEJ%3ClZW%3BgJ%3Bd3%3Au+CFK%2B%7CqMqmhaI0 Encrypted to : XAbCDwIM3+Dg3dQB0ApFhWtw1xcNFAbDXjgAWexMRAhd9L9Qygyt7Q8HBA3gnCNE+Qx/cA2QZnrHfgH+JJBgEY5gvgaw6rUAZqcA+QG0J+YAFPhAcwAXXzIANjwa6QccavoQZ/hLpg8e2qNg40XEog7AbDigbQRQNAXXBK8Q48qamQNUJb1QdD0CtQtLZiXwxrp5/gJ3CiXASmn2ngHyoJMgl/sX1g4RhHog6io2LAGr/w7w Decrypted to : %2CxaYGp%3A%3FiThL+%2A%2B%22I8%216qGA0eSXCUG1fXxNl%27%22T0_Un.P%3Au%2F%3D+N%7B2%7B%21L+-%5D%27mg-89p.on9zjfEJ%3ClZW%3BgJ%3Bd3%3Au+CFK%2B%7CqMqmhaI0 ASSERTION SUCCEEDED: Encrypting : hello Encrypted to : zBE6gwElLiOQ Decrypted to : hello ASSERTION SUCCEEDED: Encrypting : small test Encrypted to : g6Yd4w8iJULAykugogyLKRAA Decrypted to : small test ASSERTION SUCCEEDED: Encrypting : %2CxaYGp%3A%3FiThL+%2A%2B%22I8%216qGA0eSXCUG1fXxNl%27%22T0_Un.P%3Au%2F%3D+N%7B2%7B%21L+-%5D%27mg-89p.on9zjfEJ%3ClZW%3BgJ%3Bd3%3Au+CFK%2B%7CqMqmhaI0 Encrypted to : T/F8GAVZe64QM9BrSAfh0tDASwHxSgayh50gnXQtlQIBRo8gyDK27gWYsZKgOXkr5g8rht/wGKH2hw8jQHqAsNSmzQc+SS+QGO+HtgvNcgvwDTYQJwGDYGLgkMoiLwKYoEIgae1mIQhd0mkQ07xjRAn/nwHwCvPSKAissRFgW0gXrwri4XygJGjFRQ3cj9dwYB64tgqrAaEQM2p7nwKK8FigQFUB6wfTr4iwz6vxUwGgsllw Decrypted to : %2CxaYGp%3A%3FiThL+%2A%2B%22I8%216qGA0eSXCUG1fXxNl%27%22T0_Un.P%3Au%2F%3D+N%7B2%7B%21L+-%5D%27mg-89p.on9zjfEJ%3ClZW%3BgJ%3Bd3%3Au+CFK%2B%7CqMqmhaI0 ASSERTION SUCCEEDED: assertions: 11 / failures: 0
|
SleightOf Hand
Registered User
Join date: 4 Apr 2006
Posts: 21
|
Careful with Cut and Paste.
05-22-2007 00:38
I just noticed (and I dont know how it happened as the code I have is correct) but you may want to check for randon spaces in the code that I cut and pasted from my own editor. For example in the $_base64 string there seems to have been inserted a couple of spaces between the "x" and the "y" that should not be there. I will check for others though that is the only one so far that reall stands out and would affect the running of the code. I cant fix this in the editor as the code shows correctly without spaces but still shows with spaces in the post. Contact me if you need the source code directly.
|
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
|
Dont sweat it
05-22-2007 01:48
From: SleightOf Hand I just noticed (and I dont know how it happened as the code I have is correct) but you may want to check for randon spaces in the code that I cut and pasted from my own editor. For example in the $_base64 string there seems to have been inserted a couple of spaces between the "x" and the "y" that should not be there. I will check for others though that is the only one so far that reall stands out and would affect the running of the code. I cant fix this in the editor as the code shows correctly without spaces but still shows with spaces in the post. Contact me if you need the source code directly. The Forum does it all the time.
_____________________
I'm back......
|
ed44 Gupte
Explorer (Retired)
Join date: 7 Oct 2005
Posts: 638
|
05-22-2007 04:16
It might force folk to layout their code with a few more spaces to make it more readable. eg: $_base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/";
Extra readability sometimes allows you to pick errors more easily! This script is great, though!
|
SleightOf Hand
Registered User
Join date: 4 Apr 2006
Posts: 21
|
Strong XTEA Encryption in action LSL <-> PHP
05-22-2007 13:13
For those who want to see this in action with your Web server try these. Be sure that if you edit these that Rounds and Key Phrase are the same in both LSL and PHP versions. LSL - PLACE IN PRIM -- Edit to change URL and tosend text. //************************************************// //* Masa's XTEA encryption/decryption v3 *// //* Modified by SleightOf Hand for Stability and *// //* intercommunication with PHP version *// //************************************************// // NOTE: This version only encodes 60 bits per 64-bit block! // This code is public domain. // Sleight was here 20070522 // masa was here 20070315 // so was strife 20070315 // // This was Modified by SleightOf Hand to allow // Strong encryption between LSL and PHP. //************************************************// //* XTEA IMPLEMENTATION *// //************************************************// integer XTEA_DELTA = 0x9E3779B9; // (sqrt(5) - 1) * 2^31 integer xtea_num_rounds = 6; list xtea_key = [0, 0, 0, 0]; integer hex2int(string hex) { if(llGetSubString(hex,0,1) == "0x") return (integer)hex; if(llGetSubString(hex,0,0) == "x") return (integer)("0"+hex); return(integer)("0x"+hex); } // Convers any string to a 32 char MD5 string and then to a list of // 4 * 32 bit integers = 128 bit Key. MD5 ensures always a specific // 128 bit key is generated for any string passed. list xtea_key_from_string( string str ) { str = llMD5String(str,0); // Use Nonce = 0 return [ hex2int(llGetSubString( str, 0, 7)), hex2int(llGetSubString( str, 8, 15)), hex2int(llGetSubString( str, 16, 23)), hex2int(llGetSubString( str, 24, 31))]; } // Encipher two integers and return the result as a 12-byte string // containing two base64-encoded integers. string xtea_encipher( integer v0, integer v1 ) { integer num_rounds = xtea_num_rounds; integer sum = 0; do { // LSL does not have unsigned integers, so when shifting right we // have to mask out sign-extension bits. v0 += (((v1 << 4) ^ ((v1 >> 5) & 0x07FFFFFF)) + v1) ^ (sum + llList2Integer(xtea_key, sum & 3)); sum += XTEA_DELTA; v1 += (((v0 << 4) ^ ((v0 >> 5) & 0x07FFFFFF)) + v0) ^ (sum + llList2Integer(xtea_key, (sum >> 11) & 3)); } while( num_rounds = ~-num_rounds ); //return only first 6 chars to remove "=="'s and compact encrypted text. return llGetSubString(llIntegerToBase64(v0),0,5) + llGetSubString(llIntegerToBase64(v1),0,5); } // Decipher two base64-encoded integers and return the FIRST 30 BITS of // each as one 10-byte base64-encoded string. string xtea_decipher( integer v0, integer v1 ) { integer num_rounds = xtea_num_rounds; integer sum = XTEA_DELTA*xtea_num_rounds; do { // LSL does not have unsigned integers, so when shifting right we // have to mask out sign-extension bits. v1 -= (((v0 << 4) ^ ((v0 >> 5) & 0x07FFFFFF)) + v0) ^ (sum + llList2Integer(xtea_key, (sum>>11) & 3)); sum -= XTEA_DELTA; v0 -= (((v1 << 4) ^ ((v1 >> 5) & 0x07FFFFFF)) + v1) ^ (sum + llList2Integer(xtea_key, sum & 3)); } while ( num_rounds = ~-num_rounds ); return llGetSubString(llIntegerToBase64(v0), 0, 4) + llGetSubString(llIntegerToBase64(v1), 0, 4); } // Encrypt a full string using XTEA. string xtea_encrypt_string( string str ) { // encode string str = llStringToBase64(str); // remove trailing =s so we can do our own 0 padding integer i = llSubStringIndex( str, "=" ); if ( i != -1 ) str = llDeleteSubString( str, i, -1 ); // we don't want to process padding, so get length before adding it integer len = llStringLength(str); // zero pad str += "AAAAAAAAAA="; string result; i = 0; do { // encipher 30 (5*6) bits at a time. result += xtea_encipher( llBase64ToInteger(llGetSubString(str, i, i += 4) + "A="), llBase64ToInteger(llGetSubString(str, ++i, i += 4) + "A=") ); } while ( ++i < len ); return result; } // Decrypt a full string using XTEA string xtea_decrypt_string( string str ) { integer len = llStringLength(str); integer i; string result; do { result += xtea_decipher( llBase64ToInteger(llGetSubString(str, i, i += 5) + "=="), llBase64ToInteger(llGetSubString(str, ++i, i += 5) + "==") ); } while ( ++i < len ); // Replace multiple trailing zeroes with a single one i = llStringLength(result); while ( llGetSubString(result, --i, i) == "A" ); result = llGetSubString(result, 0, i); i = llStringLength(result); integer mod = i%4; //Depending on encoded length diffrent appends are needed if(mod == 1) return llBase64ToString(result + "A=="); else if(mod == 2 ){ if((llSubStringIndex(base64,llGetSubString(result, -1,-1))) & 0x0F) return llBase64ToString(result + "A="); else return llBase64ToString(result + "=="); } else if(mod == 3){ if((llSubStringIndex(base64,llGetSubString(result, -1,-1))) & 0x03) return llBase64ToString(result + "A"); return llBase64ToString(result + "="); } return llBase64ToString( result ); } key requestid; // just to check if we're getting the result we've asked for; all scripts in the same object get the same replies string base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; string url = "http://<enter your URL here>/test-script.php"; default { touch_start(integer number) { string tosend = "this is a message to send"; llWhisper(0, "Message to Send = " + tosend); xtea_key = xtea_key_from_string("this is a test key"); string message = xtea_encrypt_string(tosend); llWhisper(0, "Message to Server = " + message); requestid = llHTTPRequest(url, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], "parameter1=" + llEscapeURL(message)); } http_response(key request_id, integer status, list metadata, string body) { if (request_id == requestid) llWhisper(0, "Web server sent: " + body); integer clean = 0; string cleanbody = ""; while(~llSubStringIndex(base64,llGetSubString(body,clean,clean))){ cleanbody += llGetSubString(body,clean,clean++); } llWhisper(0, "Cleaned : " + cleanbody); llWhisper(0, "Web server said: " + xtea_decrypt_string( cleanbody )); } }
PHP Code - Place on web server at location that LSL URL will be looking for. <?php //************************************************// //* Sleight's PHP XTEA encryption/decryption v3 *// //* Modified by SleightOf Hand for Stability and *// //* intercommunication between PHP & LSL *// //************************************************// // NOTE: This version only encodes 60 bits per 64-bit block! // This code is public domain. // Sleight was here 20070522 // masa was here 20070315 // so was strife 20070315 // // This was converted from the LSL version by // SleightOf Hand to allow Strong encryption // between LSL and PHP. If you find this usefull // any donations apreciated. //************************************************// //* XTEA IMPLEMENTATION *// //************************************************// $_XTEA_DELTA = 0x9E3779B9; // (sqrt(5) - 1) * 2^31 $_xtea_num_rounds = 6; $_xtea_key = array(0, 0, 0, 0); $_base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ". "abcdefghijklmnopqrstuvwxyz". "0123456789+/"; // Returns Integer based on 8 byte Base64 Code XXXXXX== (llBase64ToInteger) function base64_integer($str){ global $_base64; if(strlen($str) != 8) return 0; return ((strpos($_base64,$str{0}) << 26)| (strpos($_base64,$str{1}) << 20)| (strpos($_base64,$str{2}) << 14)| (strpos($_base64,$str{3}) << 8) | (strpos($_base64,$str{4}) << 2) | (strpos($_base64,$str{5}) >> 4)); } // Returns 8 Byte Base64 code based on 32 bit integer ((llIntegerToBase64) function integer_base64($int){ global $_base64; if($int != (integer) $int) return 0; return $_base64{($int >> 26 & 0x3F)} . $_base64{($int >> 20 & 0x3F)} . $_base64{($int >> 14 & 0x3F)} . $_base64{($int >> 8 & 0x3F)} . $_base64{($int >> 2 & 0x3F)} . $_base64{($int << 4 & 0x3F)} . "=="; } //strict 32 bit addition using logic function binadd($val1 , $val2){ $ta = $val1 ^ $val2; while($tc = (($val1 & $val2) << 1) & 0x0FFFFFFFF){ $ta = ($val1 = $tc) ^ ($val2 = $ta); } return $ta; // $ta will now be the result so return it }
// Convers any string to a 32 char MD5 string and then to a list of // 4 * 32 bit integers = 128 bit Key. function xtea_key_from_string( $str ) { global $_xtea_key; $str = md5($str . ":0"); // Use nonce = 0 in LSL for same output eval("\$_xtea_key[0] = 0x" . substr($str,0,8) . ";"); eval("\$_xtea_key[1] = 0x" . substr($str,8,8) . ";"); eval("\$_xtea_key[2] = 0x" . substr($str,16,8) . ";"); eval("\$_xtea_key[3] = 0x" . substr($str,24,8) . ";"); } // Encipher two integers and return the result as a 12-byte string // containing two base64-encoded integers. function xtea_encipher( $v0 , $v1 ) { global $_xtea_num_rounds , $_xtea_key , $_XTEA_DELTA; $num_rounds = $_xtea_num_rounds; $sum = 0; do { // LSL only has 32 bit integers. However PHP automaticly changes // 32 bit integers to 64 bit floats as nessesary. This causes // incompatibilities between the LSL Encryption and the PHP // counterpart. I got round this by changing all addition to // binary addition using logical & and ^ and loops to handle bit // carries. This forces the 32 bit integer to remain 32 bits as // I mask out any carry over 32 bits. this bring the output of the // encrypt routine to conform with the output of its LSL counterpart. // LSL does not have unsigned integers, so when shifting right we // have to mask out sign-extension bits. // calculate ((($v1 << 4) ^ (($v1 >> 5) & 0x07FFFFFF)) + $v1) $v0a = binadd((($v1 << 4) ^ (($v1 >> 5) & 0x07FFFFFF)) , $v1); // calculate ($sum + $_xtea_key[$sum & 3]) $v0b = binadd($sum , $_xtea_key[$sum & 3]); // Calculate ($v0 + ((($v1 << 4) ^ (($v1 >> 5) & 0x07FFFFFF)) + $v1) // ^ ($sum + $_xtea_key[$sum & 3])) $v0 = binadd($v0 , ($v0a ^ $v0b)); //Calculate ($sum + $_XTEA_DELTA) $sum = binadd($sum , $_XTEA_DELTA); //Calculate ((($v0 << 4) ^ (($v0 >> 5) & 0x07FFFFFF)) + $v0) $v1a = binadd((($v0 << 4) ^ (($v0 >> 5) & 0x07FFFFFF)) , $v0); // Calculate ($sum + $_xtea_key[($sum >>11) & 3]) $v1b = binadd($sum , $_xtea_key[($sum >>11) & 3]); //Calculate ($v1 + ((($v0 << 4) ^ (($v0 >> 5) & 0x07FFFFFF)) + $v0 // ^ ($sum & $_xtea_key[($sum >>11) & 3])) $v1 = binadd($v1 , ($v1a ^ $v1b)); } while( $num_rounds = ~-$num_rounds ); //return only first 6 chars to remove "=="'s and compact encrypted text. return substr(integer_base64($v0),0,6) . substr(integer_base64($v1),0,6); } // Decipher two base64-encoded integers and return the FIRST 30 BITS of // each as one 10-byte base64-encoded string. function xtea_decipher( $v0, $v1 ) { global $_xtea_num_rounds , $_xtea_key , $_XTEA_DELTA; $num_rounds = $_xtea_num_rounds; $sum = 0; // $_XTEA_DELTA * $_xtea_num_rounds; $tda = $_XTEA_DELTA; do{ // Binary multiplication using binary manipulation if($num_rounds & 1){ $sum = binadd($sum , $tda); } $num_rounds = $num_rounds >> 1; $tda = ($tda << 1) & 0x0FFFFFFFF; }while($num_rounds); $num_rounds = $_xtea_num_rounds; // reset $num_rounds back to its propper setting; do { // LSL only has 32 bit integers. However PHP automaticly changes // 32 bit integers to 64 bit floats as nessesary. This causes // incompatibilities between the LSL Encryption and the PHP // counterpart. I got round this by changing all addition to // binary addition using logical & and ^ and loops to handle bit // carries. This forces the 32 bit integer to remain 32 bits as // I mask out any carry over 32 bits. this bring the output of the // decrypt routine to conform with the output of its LSL counterpart. // Subtrations are handled by using 2's compliment // LSL does not have unsigned integers, so when shifting right we // have to mask out sign-extension bits. // calculate ((($v0 << 4) ^ (($v0 >> 5) & 0x07FFFFFF)) + $v0) $v1a = binadd((($v0 << 4) ^ (($v0 >> 5) & 0x07FFFFFF)) , $v0); // calculate ($sum + $_xtea_key[($sum>>11) & 3]) $v1b = binadd($sum , $_xtea_key[($sum>>11) & 3]); //Calculate 2's compliment of ($v1a ^ $v1b) for subtraction $v1c = binadd((~($v1a ^ $v1b)) , 1); //Calculate ($v1 - ((($v0 << 4) ^ (($v0 >> 5) & 0x07FFFFFF)) + $v0) // ^ ($sum + $_xtea_key[($sum>>11) & 3])) $v1 = binadd($v1 , $v1c); // Calculate new $sum based on $num_rounds - 1 $tnr = $num_rounds - 1; // Temp $num_rounds $sum = 0; // $_XTEA_DELTA * ($num_rounds - 1); $tda = $_XTEA_DELTA; do{ // Binary multiplication using binary manipulation if($tnr & 1){ $sum = binadd($sum , $tda); } $tnr = $tnr >> 1; $tda = ($tda << 1) & 0x0FFFFFFFF; }while($tnr); //Calculate ((($v1 << 4) ^ (($v1 >> 5) & 0x07FFFFFF)) + $v1) $v0a = binadd((($v1 << 4) ^ (($v1 >> 5) & 0x07FFFFFF)) , $v1); //Calculate ($sum + $_xtea_key[$sum & 3]) $v0b = binadd($sum , $_xtea_key[$sum & 3]); //Calculate 2's compliment of ($v0a ^ $v0b) for subtraction $v0c = binadd((~($v0a ^ $v0b)) , 1); //Calculate ($v0 - ((($v1 << 4) ^ (($v1 >> 5) & 0x07FFFFFF)) + $v1 // ^ ($sum + $_xtea_key[$sum & 3])) $v0 = binadd($v0 , $v0c); } while ( $num_rounds = ~-$num_rounds ); return substr(integer_base64($v0), 0, 5) . substr(integer_base64($v1), 0, 5); } // Encrypt a full string using XTEA. function xtea_encrypt_string( $str ) { // encode Binany string to Base64 $str = base64_encode($str); // remove trailing =s so we can do our own 0 padding $i = strpos($str, '=', 0); if ( $i !== FALSE ){ $str = substr( $str, 0, $i); } // we don't want to process padding, so get length before adding it $len = strlen($str); // zero pad $str .= "AAAAAAAAAA="; $result = ""; $i = 0; do { // encipher 30 (5*6) bits at a time. $enc1 = base64_integer(substr($str , $i , 5) . "A=="); $i += 5; $enc2 = base64_integer(substr($str , $i , 5) . "A=="); $i += 5; $result .= xtea_encipher($enc1, $enc2); } while ( $i < $len ); return $result; //Return Encrypted string } // Decrypt a full string using XTEA function xtea_decrypt_string( $str ) { global $_base64 ; $len = strlen($str); $i; $result; do { $dec1 = base64_integer(substr($str , $i , 6)."=="); $i += 6; $dec2 = base64_integer(substr($str , $i , 6)."=="); $i += 6; $result .= xtea_decipher( $dec1, $dec2); } while ( $i < $len ); // Replace multiple trailing zeroes with a single one $i = strlen($result); while ( substr($result, --$i, 1) == "A" ); $result = substr($result, 0, $i+1); $i = strlen($result); $mod = $i%4; //Depending on encoded length diffrent appends are needed if($mod == 1) return base64_decode($result . "A=="); else if($mod == 2 ){ if((strpos($_base64,substr($result, -1,1))) & 0x0F) return base64_decode($result . "A="); else return base64_decode($result . "=="); } else if($mod == 3){ if((strpos($_base64,substr($result, -1,1))) & 0x03) return base64_decode($result . "A"); else return base64_decode($result . "="); } return base64_decode( $result );
} // Only works with PHP compiled as an Apache module $headers = apache_request_headers(); $objectName = $headers["X-SecondLife-Object-Name"]; $objectKey = $headers["X-SecondLife-Object-Key"]; $ownerKey = $headers["X-SecondLife-Owner-Key"]; $ownerName = $headers["X-SecondLife-Owner-Name"]; $region = $headers["X-SecondLife-Region"]; // and so on for getting all the other variables ... xtea_key_from_string("this is a test key"); // get things from $_POST[] // Naturally enough, if this is empty, you won't get anything $parameter1 = xtea_decrypt_string($_POST["parameter1"]); echo xtea_encrypt_string($ownerName . " just said " . $parameter1) . "\n"; ?>
This should result in the following output as this is what was output by my object. Object whispers: Message to Send = this is a message to send Object whispers: Message to Server = JSdgCA0FDyhgLlUnSgqMQWkAxz1AzA1vr9zwSEDnCgwJ6GNQ Object whispers: Web server sent: SVbqNQ5XdkngeUI3bgP+s6eAT6GM4AWnYCYApcfxagrPbxmwiY7WXA4J+gEQ1AYhRQNvcnEwfZSo/AuKVtIw Object whispers: Cleaned : SVbqNQ5XdkngeUI3bgP+s6eAT6GM4AWnYCYApcfxagrPbxmwiY7WXA4J+gEQ1AYhRQNvcnEwfZSo/AuKVtIw Object whispers: Web server said: SleightOf Hand just said this is a message to send
|
RobbyRacoon Olmstead
Red warrior is hungry!
Join date: 20 Sep 2006
Posts: 1,821
|
05-22-2007 14:47
Couldn't get it to work quite right, I think I missed something on the formatting (extraneous space or sumthin?), but I went ahead and paid you the bounty I mentioned earlier in this thread  I'm pretty excited about this. It's not hardened security by any means, but it's way better than many of the approaches I've seen and I can see some immediate uses for something like this in non-mission-critical applications. Thanks for taking the time on it  .
|
SleightOf Hand
Registered User
Join date: 4 Apr 2006
Posts: 21
|
Fix for HTTP/PHP transfers of encrypted data
05-22-2007 21:05
Just a quick bug fix. Since HTTP/PHP converts "+" into a " " when transfering parameters like.... "this+is+a+test" would become "this is a test" then the encoded string has to be passed through llEscapeURL to safeguard it from this effect on the +'s that are part of the Base64 string. requestid = llHTTPRequest(url, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], "parameter1=" + llEscapeURL(message));
|
SleightOf Hand
Registered User
Join date: 4 Apr 2006
Posts: 21
|
Alternate binadd() to try with PHP script.
05-23-2007 00:23
Maybe this will be faster for the Binary addition in PHP.... This seems to work very well in practice so far. any comments? function binadd($val1 , $val2){ $ta = $val1 ^ $val2; while($tc = (($val1 & $val2) << 1) & 0x0FFFFFFFF){ $ta = ($val1 = $tc) ^ ($val2 = $ta); } return $ta; // $ta will now be the result so return it }
|
SleightOf Hand
Registered User
Join date: 4 Apr 2006
Posts: 21
|
Bug Fix.
05-25-2007 09:23
Another glitch has come to light within the PHP script. This involves the decoding of the final Base64 string to get the plaintext of the message. Thanks to Tobia Forcella for reporting this bug. It affected charaters with Hex value patern of 0x?0 and was the last charater in the string when the string length was 2,5,8,11, ...etc. In this situation the last charater was not being decoded propery and was being dropped. This was due to the need for me to manualy add the padding charaters to the end of the string to allow PHP to decode to text. the "==" padding did not work in this case. I have worked out a fix for this and have updated my code posts to reflect this. in the "function xtea_decrypt_string() $i = strlen($result); $mod = $i%4; //Depending on encoded length diffrent appends are needed if($mod == 1) return base64_decode($result . "A=="); else if($mod == 2 ){ if(strlen(base64_decode($result . "==")) < strlen(base64_decode($result . "A="))) return base64_decode($result . "A="); else return base64_decode($result . "=="); } else if($mod == 3) return base64_decode($result . "="); return base64_decode( $result );
|
SleightOf Hand
Registered User
Join date: 4 Apr 2006
Posts: 21
|
Another Base64 Decode fix
05-28-2007 16:28
After the discovery of the Base64 Decode bug I decided to test it more thoroughly. I discovered that the decode needed a little more tweaking as it was not handling the control charaters properly (Chars < 0x20). This is another fix I have texted over time with Chars 0x01 > 0x7F on multiple lengh strings. This Fix has to be applied to both the PHP script and the LSL Script. I am also updating my previous posts with this code. PHP Script in the xtea_decrypt_string() function $mod = $i%4; //Depending on encoded length diffrent appends are needed if($mod == 1) return base64_decode($result . "A=="); else if($mod == 2 ){ if((strpos($_base64,substr($result, -1,1))) & 0x0F) return base64_decode($result . "A="); else return base64_decode($result . "=="); } else if($mod == 3){ if((strpos($_base64,substr($result, -1,1))) & 0x03) return base64_decode($result . "A"); else return base64_decode($result . "="); } return base64_decode( $result );
LSL Script in the xtea_decrypt_string() function integer mod = i%4; //Depending on encoded length diffrent appends are needed if(mod == 1) return llBase64ToString(result + "A=="); else if(mod == 2 ){ if((llSubStringIndex(base64,llGetSubString(result, -1,-1))) & 0x0F) return llBase64ToString(result + "A="); else return llBase64ToString(result + "=="); } else if(mod == 3){ if((llSubStringIndex(base64,llGetSubString(result, -1,-1))) & 0x03) return llBase64ToString(result + "A"); return llBase64ToString(result + "="); } return llBase64ToString( result );
|
Bobbyb30 Zohari
SL Mentor Coach
Join date: 11 Nov 2006
Posts: 466
|
03-22-2008 07:05
Is there an optimized version that works? The one on the wiki currently has the decrypt portion broken.=(
|