Difference between revisions of "Simple Encryption"
(→Encryptor: always good to pay attention ^^;) |
|||
Line 16: | Line 16: | ||
string text = llGetSubString(hex, digit, digit); | string text = llGetSubString(hex, digit, digit); | ||
value = (value >> 4) & 0xfffFFFF; | value = (value >> 4) & 0xfffFFFF; | ||
integer odd = | integer odd = TRUE; | ||
while(value) | while(value) | ||
{ | { | ||
digit = value & 0xF; | digit = value & 0xF; | ||
text = llGetSubString(hex, digit, digit) + text; | text = llGetSubString(hex, digit, digit) + text; | ||
odd | odd = !odd; | ||
value = value >> 4; | value = value >> 4; | ||
} | } | ||
if(odd | if(odd) | ||
text = "0" + text; | text = "0" + text; | ||
return text; | return text; | ||
Line 31: | Line 31: | ||
{ | { | ||
// get a random value | // get a random value | ||
integer nonce = | integer nonce = (integer)llFrand(0x7FFFFFFF); | ||
// generate digest | // generate digest and prepend it to message | ||
message = llMD5String(message, nonce) + message; | |||
// generate one time pad | // generate one time pad | ||
Line 43: | Line 40: | ||
// append pad until length matches or exceeds message | // append pad until length matches or exceeds message | ||
integer count = (llStringLength(message) - 1) / 32; | |||
oneTimePad += llMD5String(oneTimePad, nonce); | if(count) | ||
do | |||
oneTimePad += llMD5String(oneTimePad, nonce); | |||
while(--count); | |||
// encrypt message | // encrypt message | ||
message = llXorBase64StringsCorrect(llStringToBase64(message), llStringToBase64(oneTimePad)); | |||
// build header | // build header | ||
Line 59: | Line 57: | ||
// append minor version | // append minor version | ||
string | string minor = llList2String(versions, 1); | ||
while(llGetSubString(minor, -1, -1) == "0") | |||
minor = llDeleteSubString(minor, -1, -1); | |||
minor = | |||
header += hex((integer)minor); | header += hex((integer)minor); | ||
// append nonce to header | // append nonce to header | ||
header += llGetSubString("00000000" + hex(nonce), -8, -1); | |||
// return the header and encrypted message | // return the header and encrypted message |
Revision as of 21:12, 28 February 2008
LSL Portal | Functions | Events | Types | Operators | Constants | Flow Control | Script Library | Categorized Library | Tutorials |
Here's a function to pass a secret message from one object to another. Using XOR, this is perhaps the weakest form of encryption. I have taken steps to make it harder to break using random nonce values with the password. If someone is able to decrypt one message, it will be easy for them to decrypt any other message. I've also added version support so that you can upgrade the script later and still have compatibility with older scripts using the same protocol.
Encryptor
<lsl> string ProtocolSignature = "ENC"; // your own signature float ProtocolVersion = 0.3; // can range from 0.0 to 255.255 string Password = "P@ssw0rd"; // change this to your own password integer communicationsChannel = PUBLIC_CHANNEL;
string hex(integer value) {
string hex = "0123456789ABCDEF"; integer digit = value & 0xF; string text = llGetSubString(hex, digit, digit); value = (value >> 4) & 0xfffFFFF; integer odd = TRUE; while(value) { digit = value & 0xF; text = llGetSubString(hex, digit, digit) + text; odd = !odd; value = value >> 4; } if(odd) text = "0" + text; return text;
} string encrypt(string password, string message) {
// get a random value integer nonce = (integer)llFrand(0x7FFFFFFF);
// generate digest and prepend it to message message = llMD5String(message, nonce) + message; // generate one time pad string oneTimePad = llMD5String(password, nonce); // append pad until length matches or exceeds message integer count = (llStringLength(message) - 1) / 32; if(count) do oneTimePad += llMD5String(oneTimePad, nonce); while(--count); // encrypt message message = llXorBase64StringsCorrect(llStringToBase64(message), llStringToBase64(oneTimePad)); // build header string header = ProtocolSignature; // append major version list versions = llParseString2List((string)ProtocolVersion, ["."], []); header += hex(llList2Integer(versions, 0)); // append minor version string minor = llList2String(versions, 1); while(llGetSubString(minor, -1, -1) == "0") minor = llDeleteSubString(minor, -1, -1); header += hex((integer)minor); // append nonce to header header += llGetSubString("00000000" + hex(nonce), -8, -1); // return the header and encrypted message return header + message;
} default {
state_entry() { llSay(communicationsChannel, encrypt(Password, "Hello, Avatar!")); llSay(communicationsChannel, encrypt(Password, "This is a very long text that I hope to be able to create a long one time pad to decrypt for it.")); }
touch_start(integer total_number) { llSay(communicationsChannel, encrypt(Password, "Touched.")); }
} </lsl>
Decryptor
<lsl> string ProtocolSignature = "ENC"; // your own signature float ProtocolVersion = 0.3; // can range from 0.0 to 255.255 string Password = "P@ssw0rd"; // change this to your own password integer communicationsChannel = PUBLIC_CHANNEL; integer Debug = TRUE; // Set this to false for production integer listener;
init() {
if(listener != 0) { llListenRemove(listener); listener = 0; } listener = llListen(communicationsChannel, "", NULL_KEY, "");
} string error(string message) {
if(Debug) llSay(DEBUG_CHANNEL, message); return "";
} string decrypt(string password, string message) {
integer signatureLength = llStringLength(ProtocolSignature); integer headerLength = signatureLength + 12; // version = 4, nonce = 8 // verify length of encrypted message if(llStringLength(message) < signatureLength + 44) // digest = 32 (base64 = 44) + at least one character return error("Too small for secret message."); // look for protocol signature in message header if(llSubStringIndex(message, ProtocolSignature) != 0) return error("Unknown protocol."); // Parse version information from header integer index = signatureLength; // determine where to start parsing string major = "0x" + llGetSubString(message, index, ++index); string minor = "0x" + llGetSubString(message, ++index, ++index); float version = (float)((string)((integer)major) + "." + (string)((integer)minor)); // verify version is supported if(version != ProtocolVersion) return error("Unknown version."); // parse nonce from header integer nonce = (integer)("0x" + llGetSubString(message, ++index, index + 7)); // remove header from message message = llGetSubString(message, headerLength, -1); // create one time pad from password and nonce string oneTimePad = llMD5String(password, nonce); // append pad until length matches or exceeds message while(llStringLength(oneTimePad) < (llStringLength(message) * .666)) oneTimePad += llMD5String(oneTimePad, nonce); // decrypt message oneTimePad = llStringToBase64(oneTimePad); message = llXorBase64StringsCorrect(message, oneTimePad); // decode message message = llBase64ToString(message); // get digest string digest = llGetSubString(message, 0, 31); // remove digest from message message = llGetSubString(message, 32, -1); // verify digest is valid if(llMD5String(message, nonce) != digest) return error("Message digest was not valid."); // return decrypted message return message;
} default {
state_entry() { init(); } on_rez(integer start_param) { init(); } listen(integer channel, string name, key id, string message) { string message = decrypt(Password, message); if(message != "") llSay(0, message); }
} </lsl>
Note: The Hex and Efficient Hex examples were used to create the hex method.