Last active
September 17, 2020 07:51
-
-
Save FelixWolf/eb9d61fa2e6d50095c255223eacdb730 to your computer and use it in GitHub Desktop.
Avg code speed: 5ms for "Hello, World"
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//--------------------------------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