An encrypted mode has been proposed by Fred Beckhusen using XTEA.lsl. Currently configuration (key) is via notecard but this is not a long-term solution, eventually the key will need to be in a no-mod script. It adds an integer to the listen protocol.
Fred's solution was to take the XTEA implementation library and add a small link_message wrapper that enables both encryption and decryption via link messages. A channel is supplied with the encryption requests so the cipher text can be sent to that channel via llRegionsSay().
An extension is to return the cipher text via link_message if no channel number is supplied.
The code Fred has in Control is very similar to that in the XTEA LSL <-> PHP section of that wiki page. The proposed implementation differs from Fred's:
These changes allow this script to be distributed in-world as no-modify/no-transfer and not violate any GPL/AGPL requirements. There is still a weakness in this scheme in that the script can be copied into other objects and used to decrypt intercepted communications.
// The name of the XTEA script string XTEA_NAME = "r2-xtea"; // Set to encrypt 'message' and re-send on channel 'id' integer XTEAENCRYPT = 13475896; // Set in the reply to a received XTEAENCRYPT if the passed channel is 0 or "" integer XTEAENCRYPTED = 8303877; // Set to decrypt 'message' and reply vi llMessageLinked() integer XTEADECRYPT = 4690862; // Set in the reply to a received XTEADECRYPT integer XTEADECRYPTED = 3450924; integer haz_xtea = FALSE; integer can_haz_xtea() { // See if the XTEA script is present in object inventory integer count = llGetInventoryNumber(INVENTORY_SCRIPT); while (count--) { if (llGetInventoryName(INVENTORY_SCRIPT, count) == XTEA_NAME) { llOwnerSay("Found XTEA script"); return TRUE; } } return FALSE; } send(string msg) { if (haz_xtea) { llMessageLinked(LINK_THIS, XTEAENCRYPT, msg, (string)r2channel); } else { llSay(r2channel, msg); } if (VERBOSE == 1) { llOwnerSay("S: " + msg); } } // ... default { state_entry() { haz_xtea = can_haz_xtea(); // ... } link_message(integer sender_number, integer number, string message, key id) { if (number == XTEAENCRYPTED) { llOwnerSay("Ciphertext: " + message); } } }
// The name of the XTEA script string XTEA_NAME = "r2-xtea"; // Set to encrypt 'message' and re-send on channel 'id' integer XTEAENCRYPT = 13475896; // Set in the reply to a received XTEAENCRYPT if the passed channel is 0 or "" integer XTEAENCRYPTED = 8303877; // Set to decrypt 'message' and reply vi llMessageLinked() integer XTEADECRYPT = 4690862; // Set in the reply to a received XTEADECRYPT integer XTEADECRYPTED = 3450924; integer haz_xtea = FALSE; integer can_haz_xtea() { // See if the XTEA script is present in object inventory integer count = llGetInventoryNumber(INVENTORY_SCRIPT); while (count--) { if (llGetInventoryName(INVENTORY_SCRIPT, count) == XTEA_NAME) { llOwnerSay("Found XTEA script"); return TRUE; } } return FALSE; } // ... default { state_entry() { haz_xtea = can_haz_xtea(); // ... } listen(integer channel, string name, key id, string message) { if (llGetOwnerKey(id) == llGetOwner()) { if (channel == r2channel) { // Check if message received is cleartext and handle // ... else { if (haz_xtea) { llMessageLinked(LINK_THIS, XTEADECRYPT, message, ""); } } } } link_message(integer sender_number, integer number, string message, key id) { if (number == XTEADECRYPTED) { list cmdargs = llCSV2List(message); string command = llToUpper(llList2String(cmdargs, 0)); // handle decrypted message // ... } } }