Don't click here unless you want to be banned.

LSL Wiki : llXorBase64Strings

HomePage :: PageIndex :: RecentChanges :: RecentlyCommented :: UserSettings :: You are
This function has been deprecated in favour of llXorBase64StringsCorrect.

string llXorBase64Strings(string s1, string s2)

Performs an xor on two Base64 strings and returns a Base64 string. s2 repeats if it is shorter than s1.

This function is for encrypting data. Put your data in s1 and your key in s2 to encrypt or put the encrypted data into s1 with the same key in s2 to decrypt again.

Use llStringToBase64 and llBase64ToString for converting to and from Base64 respectively.

While fine for most SL encryption purposes, Xor'ing a string with a password is considered a very weak encryption algorithm. Do not use this for anything that will cost you RL $ if compromised (such as an automated RL - SL currency exchanger). Also, consider carefully how much damage a malicious party might be able to wreak if your encryption is hacked.

This type of encryption is similar to something called a one time pad that is if s2 is the same length as s1, is generated randomly (not pseudo randomly), and s2 is used only once. When used in this way this function is provably unbreakable. However implementing this function in this way is difficult to say the least. However with a little ingenuity and some creative problem solving we might be able to create different variations of this with acceptable reductions in security with minimal resource requirements(execution time, memory). IE have a new key created for each message maybe based on some universally changing constant like the server timestamp.

And as it turns out the quickest way to weaken xor type encryption is to use the key more than once, either by repeating a small key across a longer message or to use the same key on more than one message. It is only strong if the key is used only once. So this type of encryption when used with the same key over and over is supposedly rather trivial to break.

Note: this example code always produces the same result as llXorBase64StringsCorrect, but only the same result as llXorBase64Strings when s2 is longer than s1 (unless s2 is a multiple of 3 bytes in length -see discussion at end of page).

default {
    state_entry() {
        string  data = "I like bananas."; // the data we want to encrypt
        string  pass = "monkey"; // the encryption key
        string  crypt;  // for storing the encrypted data
        // convert both data and key to base64 and encrypt the data with the key
        // then store the encrypted data in 'crypt'
        crypt = llXorBase64Strings(llStringToBase64(data), llStringToBase64(pass));
        llSay(0, crypt); // this could now be used to email the data around
        // someone without the correct key wouldn't be able to (easily) get the plaintext
        // decrypt it again, using the same key, and convert back to plaintext
        llSay(0, llBase64ToString(llXorBase64Strings(crypt, llStringToBase64(pass))));
        // as you can see, applying the same key to encrypted data again decrypts it

Tip: If you see an "=" character in the middle of your encrypted string, you probably forgot to first convert your data to Base64.

If you want to exchange data that passed through this function from outside of LSL, the following Python snippet might be helpful to you:

from base64 import b64encode, b64decode

def XorBase64Strings(s1, s2):
	"""Emulates the LSL function llXorBase64Strings:
	Performs an exclusive or on two Base64 strings and returns a Base64 string. s2 repeats if it is shorter than s1."""
	s1 = b64decode(s1)		# internally this works with
	s2 = b64decode(s2)		# the decoded strings
	while len(s2) < len(s1): s2 += s2		# repeat s2 until it's at least as long as s1
	out = ""
	for index in range(len(s1)):		# take each character from s1
		out += chr( ord(s1[index]) ^ ord(s2[index]) )		# and XOR it with one from s2
	return b64encode(out)

data = "I like bananas."		# the data we want to encrypt
ckey = "monkey"		# the encryption key

crypt = XorBase64Strings(b64encode(data), b64encode(ckey))		# encode & encrypt

print crypt	# the base64 encoded result

decrypt = b64decode(XorBase64Strings(crypt, b64encode(ckey)))		# decrypt & decode

print decrypt		# the decrypted and base64 decoded data

# verify
if decrypt == data: print "This function seems to work..."
# this string is from calling the LSL function with the same parameters
if crypt == "JE8CAg4cTQ0PBQQXDBxA": print "... in the same way as the LSL function."

This function does the same thing as the one above, only in PHP:
(The function allows to encrypt urls as well, like some special chars)
function String2XorBase64($s1$s2)
$temp1 base64_encode($s1);
$temp2 base64_encode($s2);
strlen($temp2) < strlen($temp1))
$temp2 $temp2.$temp2;
$s2 $s2.$s2;
strtr(base64_encode($s1 $s2), '+/''-_');
String2XorBase64($_GET[encrypt], "ThePass");   //Encrypt the string with the second string

Use this example to decrypt the data in SL:
(Only the data returned by the php script)
string URL = "";   //Your webserver url and the name of the script with the text to encrypt
string Pass = "ThePass";   //The pass string in the php
               llHTTPRequest(URL, [], "");  //Request the encrypted string from the given URL as GET
           http_response(key ID, integer Status, list Meta, string Data)
                      //Show the encrypted string in the chat
                      llSay(0, Data);
                      //Decrypt the returned string with the given pass
        llSay(0, llBase64ToString(llXorBase64Strings(Data, llStringToBase64(Pass))));
I have used this for a password transfer to a script from my webserver.
It worked with php 5 in SL server ver 1.22.4(90499)
(Simba Fuhr)

'1.9.0(18)' vs 'pre/post-1.9.0(18)' implementation

The 1.9.0(18) Grid update introducted a new implementation of this function. It was re-written to fix a sim crash bug, however, the output deviates from the original pre-update version. The 1.9.0(18) implementation is simpler. The difference is shown below through pseudo-code. The 1.9.0(21) update reverted this function's behavior to the pre-1.9.0(18) behavior and introduced a new llXorBase64StringsCorrect with the 1.9.0(18) behavior.

1.9.0(18) implementation

1. Decode s1 and s2 from Base64 into byte strings
2. Bit-wise XOR corresponding bytes of s1 and s2 in sequence. If s2 is shorter than s1, it is simply repeated (i.e. the index into s2 is the index into s1 % length of s2).
3. Re-encode the result byte string into Base64 encoding and return as result

Pre/Post-1.9.0(18) implementation

This function's original implementation is more efficient, but gives a different result than the new one, only if s2 is shorter than s1 and s2 isn't a multiple of 3 bytes/chars long. As of 1.9.0(21), this is the behavior of this function.

1. Convert the Base64 encoding of s1 and s2 into a sequence of 6bit values. (by converting each Base64 character into its 6bit index - see Wikipedia Base64).
2. Bit-wise XOR corresponding 6bit values of s1 and s2 in sequence. If s2 is shorter than s1, it is simply repeated (i.e. the index into s2 is the index into s1 % length of s2).
3. Re-convert the resulting sequence of 6bit values into their Base64 characters (by using the 6bit values as indices into the Base64 character set)

The reason this differs from the new implemenation, is that the length of the byte string represented by s2 may not be a multiple of 3 bytes long. The initial encoding of s2 into Base64 form involves taking each set of 3 bytes (3x8=24bits) 6 bits at a time and converting to 4 Base64 characters (4x6=24bits). However, if not a multiple of 3 bytes there would have been either 2bytes (16bits) or 1byte(8bits) left over at the end. The Base64 encoding scheme dictates padding to a multiple of 6bits with a 0 bit to obtain the final Base64 character. Hence the Base64 encoded form of s2 may have either 4bits (16 - 6x2) or 2 bits (8 - 1x6) of 0 padding at its end. This padding is included when s2 is repeated above in the case when s2 is shorter than s1. Hence the different output.

Here is an example of different output.

If you XOR these two strings using llXorBase64Strings:
llXorBase64Strings("OnAxODcyMzRhYmNkZWZnaGkgYWJjZEBlZmdoLmlqa2wubW5v", "QUJDREVGR0hJSktMTQ==")

the 'pre/post-1.9.0(18)' implementation will produce

the '1.9.0(18)' implementation gave:

(which is the same result you'll get from the new llXorBase64StringsCorrect function)

(If you really need code compatible with the current ('pre/post-1.9.0(18)') implementation of llXorBase64Strings, IM Cenji Neutra for a C# implementation)

This article wasn't helpful for you? Maybe the related article at the LSL Portal is able to bring enlightenment.

Functions | DeprecatedFunctions | Crypto | Communications
Comments [Hide comments/form]
I still dont understand the purpose of this function. I see wayyy too many copy-paste explanations of functions up here. I thought the wiki was supposed to be user-created documentation, not user-ripped and reused documentation...
-- ChristopherOmega (2004-04-01 15:22:09)
Instead of bitching about it, you could improve it instead. You know, thats what a wiki is about :-P
-- EzharFairlight (2004-04-02 02:46:15)
There :P
-- EzharFairlight (2004-04-02 07:18:59)
The wiki is intended to expand upon the existing documentation. Most of it's accurate, it's just woefully incomplete. :)
-- CatherineOmega (2004-04-03 06:40:54)
Hey! If I would have understanded it, I would have expanded upon it myself :)
The original was just copyed and pasted to the wiki, thats what I dont like.
-- ChristopherOmega (2004-04-21 12:01:28)
Thanks much for revising it Cat and Ezhar. I didnt even know it could be used for encryption :D
-- ChristopherOmega (2004-04-21 12:04:49)
In the absense of anything better, the copy and pasted docs are preferable. At the very least it provides a starting point for expanding that documentation. The only possible exception is due to copy right infringement issues but seeing as the wiki provides immense value to LL I don't see how they could object.
-- GordonPrior (2006-01-27 14:55:23)
I believe a new function called llXorBase64StringsCorrect is rolling out with tomorrows update.
-- DedricMauriac (2006-04-04 23:17:49)
From Release Notes for 1.9.0(21)

* Reverted llXorBase64Strings to previous (pre-1.9.0) functionality
This call is deprecated, but restoring the old behavior allows exising content to continue to function
* Implemented llXorBase64StringsCorrect
This new call properly implements the Xor function on two Base 64 strings
Performs an exclusive or on two Base 64 strings and returns a Base 64 string
* s2 repeats if it is shorter than s1
-- BasicerSL (2006-04-05 11:56:27)
Attach a comment to this page: