Skip to content

Instantly share code, notes, and snippets.

@FelixWolf
Last active September 17, 2020 07:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FelixWolf/eb9d61fa2e6d50095c255223eacdb730 to your computer and use it in GitHub Desktop.
Save FelixWolf/eb9d61fa2e6d50095c255223eacdb730 to your computer and use it in GitHub Desktop.
Avg code speed: 5ms for "Hello, World"
//--------------------------------Byte Manipulation--------------------------------
list Base64ToBytes(string base64){
list result = [];
integer i;
integer l = llStringLength(base64);
for(;i<l;i+=4){
integer bytes = (llBase64ToInteger(llGetSubString(base64, i,i+4))>>8)&0xFFFFFF;
result += [bytes>>16, (bytes>>8)&0xFF, bytes&0xFF];
}
//TODO: Potential Speedup
//Instead of doing string comparison, consider checking length of input
//EG: Use l%3, if 0 = No pad, 1 = Two pad, 2 = One pad.
integer padLen = 1;
if(llGetSubString(base64, -2,-1) == "==") padLen = 3;
else if(llGetSubString(base64, -1,-1) == "=") padLen = 2;
return llList2List(result, 0, (3*(l/4))-padLen);
}
string BytesToBase64(list bytes){
string result = "";
integer i;
integer l = llGetListLength(bytes);
for(;i<l;i+=3){
result += llGetSubString(llIntegerToBase64(
((llList2Integer(bytes, i)&0xFF)<<24)
| ((llList2Integer(bytes, i+1)&0xFF)<<16)
| ((llList2Integer(bytes, i+2)&0xFF)<<8)
), 0, 3);
}
//There is probably a better way to do padding.
return llGetSubString(result, 0, llFloor(((l<<2)|2)/3)-1) + llList2String(["","=","=="],l%3);
}
//--------------------------------Byte Conversion--------------------------------
list Int32ToBytes(list array, integer bigEndian){
list result = [];
integer i;
integer l = llGetListLength(array);
for(;i<l;i++){
integer byte = llList2Integer(array, i);
if(bigEndian)
result += [(byte>>24)&0xFF,(byte>>16)&0xFF,(byte>>8)&0xFF,byte&0xFF];
else
result += [byte&0xFF, (byte>>8)&0xFF, (byte>>16)&0xFF, (byte>>24)&0xFF];
}
return result;
}
list BytesToInt32(list array, integer bigEndian){
list result = [];
integer i;
integer l = llGetListLength(array);
for(;i<l;i+=4){
integer byte = llList2Integer(array, i);
if(bigEndian)
result += [
((llList2Integer(array, i)&0xFF)<<24)
| ((llList2Integer(array, i + 1)&0xFF)<<16)
| ((llList2Integer(array, i + 2)&0xFF)<<8)
| (llList2Integer(array, i + 3)&0xFF)
];
else
result += [
(llList2Integer(array, i)&0xFF)
| ((llList2Integer(array, i + 1)&0xFF)<<8)
| ((llList2Integer(array, i + 2)&0xFF)<<16)
| ((llList2Integer(array, i + 3)&0xFF)<<24)
];
}
return result;
}
//--------------------------------TEA Cipher--------------------------------
list TeaEncipher(integer v1, integer v2, integer k1, integer k2, integer k3, integer k4){
integer y = v1;
integer z = v2;
integer sum;
integer delta = 0x9e3779b9;
integer n = 32;
while(n-->0){
sum += delta;
y += ( z << 4 ) + k1 ^ z + sum ^ ( z >> 5 ) + k2;
z += ( y << 4 ) + k3 ^ y + sum ^ ( y >> 5 ) + k4;
}
return [y, z];
}
list TeaDecipher(integer v1, integer v2, integer k1, integer k2, integer k3, integer k4){
integer y = v1;
integer z = v2;
integer sum = 0xc6ef3720;
integer delta = 0x9e3779b9;
integer n = 32;
while(n-->0){
z -= ( y << 4 ) + k3 ^ y + sum ^ ( y >> 5 ) + k4;
y -= ( z << 4 ) + k1 ^ z + sum ^ ( z >> 5 ) + k2;
sum -= delta;
}
return [y, z];
}
//--------------------------------TEA Encryption--------------------------------
//This is a utility function. Should you choose, you can edit this out, and
// switch the TeaEncryption functions to use the commented function.
// UUIDs just make it a bit easier than specifying a list of 4 integers.
list keyToInt32(key input){
input = llDumpList2String(llParseString2List(input, ["-"], []),"");
return [
(integer)("0x"+llGetSubString(input,0,7)),
(integer)("0x"+llGetSubString(input,8,15)),
(integer)("0x"+llGetSubString(input,16,23)),
(integer)("0x"+llGetSubString(input,24,32))
];
}
//string TeaEncrypt(string text, key encryptionKey){
string TeaEncrypt(string text, key encryption){
list encryptionKey = keyToInt32(encryption);
integer k1 = llList2Integer(encryptionKey, 0);
integer k2 = llList2Integer(encryptionKey, 1);
integer k3 = llList2Integer(encryptionKey, 2);
integer k4 = llList2Integer(encryptionKey, 3);
//HACK(Maybe?): There is some sort of padding issue where the cipher just
// dies with the last bits unless padded properly. To fix this, we append
// 3 Int32s. Proper solution would probably figure out how many to append
list data = BytesToInt32(Base64ToBytes(llStringToBase64(text)), FALSE)+[0,0,0];
integer i;
integer l = llGetListLength(data);
for(;i<l;i+=2)
data = llListReplaceList(data, TeaEncipher(llList2Integer(data, i), llList2Integer(data, i+1), k1, k2, k3, k4), i, i+1);
return BytesToBase64(Int32ToBytes(data, FALSE));
}
//string TeaDecrypt(string base64, key encryptionKey){
string TeaDecrypt(string base64, key encryption){
list encryptionKey = keyToInt32(encryption);
integer k1 = llList2Integer(encryptionKey, 0);
integer k2 = llList2Integer(encryptionKey, 1);
integer k3 = llList2Integer(encryptionKey, 2);
integer k4 = llList2Integer(encryptionKey, 3);
list data = BytesToInt32(Base64ToBytes(base64), FALSE);
integer i;
integer l = llGetListLength(data);
for(;i<l;i+=2)
data = llListReplaceList(data, TeaDecipher(llList2Integer(data, i), llList2Integer(data, i+1), k1, k2, k3, k4), i, i+1);
//HACK(Maybe?): PART 2 - Due to mentioned padding issue in TeaEncrypt, we
// have to find the first instance of a zero and delete everything after it.
data = Int32ToBytes(data, FALSE);
return llBase64ToString(BytesToBase64(llList2List(data,0,llListFindList(data,[0]))));
}
default{
state_entry(){
key encryptionKey = llGenerateKey();
string encrypted = TeaEncrypt("Hello, World!", encryptionKey);
llOwnerSay(TeaDecrypt(encrypted, encryptionKey));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment