Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Discussion: Strong XTEA Encryption LSL <-> LSL <-> PHP

SleightOf Hand
Registered User
Join date: 4 Apr 2006
Posts: 21
05-22-2007 14:02
Strong XTEA Encryption LSL <-> LSL <-> PHP

This is an XTEA implementation that has both LSL and PHP scripts to allow strong encryption not only inside LSL but also between LSL and a PHP serverscript.

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.

CODE


//************************************************//
//* 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 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx yz0123456789+/";
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.

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 = 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.

CODE

Object whispers: Message to Send = this is a message to send
Object whispers: Message to Server = JSdgCA0FDyhgLlUnSgqMQWkAxz1AzA1vr9zwSEDnCgwJ6GNQ
Object whispers: Web server sent: SVbqNQ5XdkngeUI3bgP+s6eAT6GM4AWnYCYApcfxagrPbxmwiY 7WXA4J+gEQ1AYhRQNvcnEwfZSo/AuKVtIw

Object whispers: Cleaned : SVbqNQ5XdkngeUI3bgP+s6eAT6GM4AWnYCYApcfxagrPbxmwiY 7WXA4J+gEQ1AYhRQNvcnEwfZSo/AuKVtIw
Object whispers: Web server said: SleightOf Hand just said this is a message to send
Nada Epoch
The Librarian
Join date: 4 Nov 2002
Posts: 1,423
Original Thread
05-23-2007 22:22
/15/68/185634/1.html
_____________________
i've got nothing. ;)
Murmandamus Yiyuan
Registered User
Join date: 8 Apr 2007
Posts: 4
05-24-2007 08:09
Just a thought, but wouldn't it be a good idea to use xxtea instead? It's a variable block-size version of xtea that operates directly on arbitrary size text, and requires no mode of operation (its effective block size always equals the size of the plaintext) and no iterations. It's easier to implement and it's supposedly more secure, and faster for >16 char data. I don't have an LSL version of it but here are two links that implement it in JavaScript. Should be fairly straightforward to convert:

http://www.movable-type.co.uk/scripts/tea-block.html
http://www.farfarfar.com/scripts/encrypt/
Talarus Luan
Ancient Archaean Dragon
Join date: 18 Mar 2006
Posts: 4,831
05-24-2007 09:31
Feel free. :)

From looking at the algorithm, it doesn't look like it would be significantly faster in LSL. The majority of time spent with XTEA in LSL is properly preparing and extracting the data to/from formats which can be operated upon by the cipher, not in processing the cipher itself (though it does take a significant amount of time itself).

The problem is that real, secure cryptography operations in LSL are mostly futile academic exercises for now (i.e., "look what I can do!" "Cool! Is it useful for real work?" "No, but it is nifty keen!";). Maybe Mono will change that, maybe not.

For most uses in SL, XTEA is more than strong enough.
SleightOf Hand
Registered User
Join date: 4 Apr 2006
Posts: 21
Fix for HTTP/PHP transfers of encrypted data
05-24-2007 13:24
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.

I have corrected the code posted but this is here to highlight the problem that was fixed and how.

CODE

requestid = llHTTPRequest(url,
[HTTP_METHOD, "POST",
HTTP_MIMETYPE, "application/x-www-form-urlencoded"],
"parameter1=" + llEscapeURL(message));
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
05-25-2007 00:24
From: Murmandamus Yiyuan
Just a thought, but wouldn't it be a good idea to use xxtea instead? It's a variable block-size version of xtea that operates directly on arbitrary size text, and requires no mode of operation (its effective block size always equals the size of the plaintext) and no iterations. It's easier to implement and it's supposedly more secure, and faster for >16 char data. I don't have an LSL version of it but here are two links that implement it in JavaScript. Should be fairly straightforward to convert:

http://www.movable-type.co.uk/scripts/tea-block.html
http://www.farfarfar.com/scripts/encrypt/


The original posting (in another thread) was to do with implementing an LSL XTEA that was compatiable with a PHP version. There are numerous other encryption routines that could be implemented but as Talarus said its mostly a futile but fun exercise given the speed of execution of LSL.
_____________________
I'm back......
SleightOf Hand
Registered User
Join date: 4 Apr 2006
Posts: 21
Bug fix
05-25-2007 09:25
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()

CODE

$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 );
Tobia Forcella
Registered User
Join date: 4 Mar 2007
Posts: 30
05-26-2007 06:44
Ok!!! Now it work perfect!!!!!

Thank you for sharing it!!!
SleightOf Hand
Registered User
Join date: 4 Apr 2006
Posts: 21
Not Quite perfect. Another Base64 Decode fix
05-28-2007 16:26
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

CODE

$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

CODE

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 );
ninjafoo Ng
Just me :)
Join date: 11 Feb 2006
Posts: 713
06-09-2007 12:02
just ahad a problem gettng this to work, seems the output from the web server had a leading space, naturally this caused the 'cleanbody' code to fail.

adding the following fixed the problems

http_response(key request_id, integer status, list metadata, string body)
{
if (request_id == requestid)
body = llStringTrim(body,STRING_TRIM);
llWhisper(0, "Web server sent: " + body);
.........
_____________________
FooRoo : clothes,bdsm,cages,houses & scripts

QAvimator (Linux, MacOS X & Windows) : http://qavimator.org/
Alicia Sautereau
if (!social) hide;
Join date: 20 Feb 2007
Posts: 3,125
12-21-2007 13:20
small adition wich made my life slightly easier :)

added functions to collect and send the data as a complete "package", easy fix but hopefully will direct some people who give it a try a nudge in a helpfull direction


string xtea_url = "http://url here to the file.php";
string xtea_body;
string xtea_post;

string xtea_send(string post_option)
{
xtea_key = xtea_key_from_string("your key string here";);
requestid = llHTTPRequest(xtea_url, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], (string)post_option);
xtea_post = "";
return requestid;
}

string xtea_clean(string body)
{
integer clean = 0;
string cleanbody = "";
while(~llSubStringIndex(base64,llGetSubString(body ,clean,clean)))
{
cleanbody += llGetSubString(body,clean,clean++);
}
xtea_body = xtea_decrypt_string(cleanbody);
return xtea_body;
}

string xtea_add(string name, string value)
{
string message = xtea_encrypt_string(value);
if (xtea_post == "";)
{
xtea_post += llEscapeURL(name) + "=" + llEscapeURL(message);
} else {
xtea_post += "&" + llEscapeURL(name) + "=" + llEscapeURL(message);
}
return xtea_post;
}



to add post variables in the script, just add this anywhere:
xtea_add("my_region", llGetRegionName());
xtea_add("no_idea", "clueless";);
xtea_add("varr", "yarrr";);

the xtea_add function will url escape and a simple check to add & or not to it so you can just add at will without worrying

when done collecting all the data anywhere in the script, simply execute it with
xtea_send(xtea_post);

why this way?
i`m using a second xtea_add() function to build a second http post string depending on the return of several http queries and can send any query out with the same send function ( xtea_send(xtea_post_1) xtea_send(xtea_post_2) )


in the php file nothing changed so the same encrypted string is returned as abouve but to parse it every time i just added a function to skip filling the code with the same code in the same script, simply at the top of the http requestid add this:

http_response(key request_id, integer status, list metadata, string body)
{
if (request_id == requestid)
{
xtea_clean(body);

// xtea_body contains the clean decrypted body \\

your code here
}
}



no expert and bad at coding so having repeated stuff stuffed in a function made my reading and learning abit simpler, hope it helps some one out abit :p
_____________________
Bobbyb30 Zohari
SL Mentor Coach
Join date: 11 Nov 2006
Posts: 466
12-21-2007 17:04
Not bad.
_____________________
Alicia Sautereau
if (!social) hide;
Join date: 20 Feb 2007
Posts: 3,125
12-22-2007 07:43
small improvement to the xtea_add function:

string xtea_add(string name, string value)
{
string name = xtea_encrypt_string(name);
string message = xtea_encrypt_string(value);
if (xtea_post == "";)
{
xtea_post += llEscapeURL(name) + "=" + llEscapeURL(message);
} else {
xtea_post += "&" + llEscapeURL(name) + "=" + llEscapeURL(message);
}
return xtea_post;
}


for your php code:

foreach ($_POST as $key => $value) {
$key = xtea_decrypt_string($key);
$value = xtea_decrypt_string($value);
$$key = addslashes(trim($value));
}


hiding the variable and value to hide script operation if managed to sniff it out :)

/* edit
This also works for when redirecting to an URL with the llLoadURL function and use the GET as hidden fields for the page you want to display without revieling anything you pass on trough plain text ;)

example:

LSL:
xtea_add("name", llKey2Name(usrNow));
xtea_add("key", usrNow);
llLoadURL(usrNow, "\n Please follow this link.", "url/file.php?" + xtea_post);
xtea_post = "";

returnes:
http://url/script.php?Nz%2FSVAfp0IPAGGT40QdXActw=PtVjlQ6rt5tApbTZNg3cVEsQOHpYGw0MQ64g&025lig6FhtqQ=EspNFQgMoQkAq9FxEQA4oSzQF1dE3AAAwXzg0D0dRQY2J9SAEoEzxwbibz7w

simple php check with a public viewable page and a form, can add sql queries to extend the check but that`s to much for an easy example to bring over the idea :)

if (!isset($_POST['submit']))
{
if (isset($_GET)){
foreach ($_GET as $key => $value) {
$key = xtea_decrypt_string($key);
$value = xtea_decrypt_string($value);
$$key = addslashes(trim($value));
}
}
if(isset($name)) {
// can add an sql statement here to check the db for the $name befor passing it on to the main variable just to make sure along with the user key
$username = $name;
}

will display after decrypting and checking:
Alicia Sautereau - 66879809-f806-469b-998e-;)


if they try to temper with it, their manual input will be decrypted aswell and will endup as mumbojumbo wich will not pass any checking you`ve done, also without the key they won`t be able to decrypt it
_____________________
Alicia Sautereau
if (!social) hide;
Join date: 20 Feb 2007
Posts: 3,125
12-22-2007 19:34
can`t keep my hands off it so here`s another simple but effective crude addition

global:
list split;


new function:

string xtea_list(integer i)
{
list split = llParseString2List(xtea_body, ["|"],[]);
cmd = llList2String(split, i);
return cmd;
}


so what the hell is up with this? simple!
after making it easy to "stack up" multiple post variables, we might aswell grab several variables back from the web server to cut down on the mess :)

some info u want to send back in the php script:
print xtea_encrypt_string($var1.'|'.$var2.'|'.$var3) . '\n';

if you`ve passed lsl for nubs, you get the idea, if on my level then on we go:

http_response(key request_id, integer status, list metadata, string body)
{
if (request_id == requestid)
{
xtea_clean(body);
else if (xtea_list(0) == "value1";)
{
do some stuff
}
else if (xtea_list(1) == "value2";)
{
do more stuff
}
else if (xtea_list(0) == "var3";)
{
we hate var3
state default; :)
}
}
}

or simply

if (xtea_list(1) == "var2";)
{
do something with var1 and var3
}

can do what you want with it anywhere :)

we parsed the string into a list and as you can see, we`ve split it on the | character
when making up the php respond string, no guessing is needed what variable each piece of lsl will want to use

instead of digging or converting the return string to a list every time, it`s simple done by calling a stupidly simple function :)

xtea_list(0) = var1
xtea_list(1) = var2
xtea_list(2) = var3

as this is an addon, the global xtea_body is still intact, we can now just return a crapload of variables back in 1 time and use what is needed

the created list is global so can be used any where in the script or passed on to linked prims untill a new http query is created (remember, xtea_body is global aswell)

this code can also be used to parse lsl only strings for grabbing different parts in say a listener with text commands ;)

Ali`s nub additions will keep coming as Sleight has made a pritty neat piece of code with wich hopefully my addition will help to ease the learning curve about how to use it at beginners level as it`s very usefull for offworld communication

Thanks Sleight!
_____________________
Alicia Sautereau
if (!social) hide;
Join date: 20 Feb 2007
Posts: 3,125
12-24-2007 09:15
Usefull tip,

IF after making a http request you get empty body replies for unkown reasons (no errors), there is a simple solution for that!

global:
integer sleep_time = 5;

in the state you proccess the reply in:
state_entry()
{
llSay(0, "Contacting server, please wait...";);
llSleep(sleep_time);
}


clicking on the prim to make a http request can take a second or 2 for the request to reach the web server and proccess it (lag!) if it is on a slow connection or on the otherside of the world from the sim server location

some times you need to click it twice and some times it does not return a reply, this will give the poor lil packets abit more time to travel :)
_____________________