aboutsummaryrefslogtreecommitdiff
path: root/gamemode/shared/lockbox
diff options
context:
space:
mode:
Diffstat (limited to 'gamemode/shared/lockbox')
-rw-r--r--gamemode/shared/lockbox/array.lua211
-rw-r--r--gamemode/shared/lockbox/base64.lua157
-rw-r--r--gamemode/shared/lockbox/bit.lua11
-rw-r--r--gamemode/shared/lockbox/ecb.lua191
-rw-r--r--gamemode/shared/lockbox/padding.lua21
-rw-r--r--gamemode/shared/lockbox/queue.lua47
-rw-r--r--gamemode/shared/lockbox/stream.lua112
7 files changed, 750 insertions, 0 deletions
diff --git a/gamemode/shared/lockbox/array.lua b/gamemode/shared/lockbox/array.lua
new file mode 100644
index 0000000..7ae89fc
--- /dev/null
+++ b/gamemode/shared/lockbox/array.lua
@@ -0,0 +1,211 @@
+print("Hello from array.lua!")
+local String = string
+local Bit = include("bit.lua");
+
+local XOR = Bit.bxor;
+
+local Array = {};
+
+Array.size = function(array)
+ return #array;
+end
+
+Array.fromString = function(string)
+ local bytes = {};
+
+ local i=1;
+ local byte = String.byte(string,i);
+ while byte ~= nil do
+ bytes[i] = byte;
+ i = i + 1;
+ byte = String.byte(string,i);
+ end
+
+ return bytes;
+
+end
+
+Array.toString = function(bytes)
+ local chars = {};
+ local i=1;
+
+ local byte = bytes[i];
+ while byte ~= nil do
+ chars[i] = String.char(byte);
+ i = i+1;
+ byte = bytes[i];
+ end
+
+ return table.concat(chars,"");
+end
+
+Array.fromStream = function(stream)
+ local array = {};
+ local i=1;
+
+ local byte = stream();
+ while byte ~= nil do
+ array[i] = byte;
+ i = i+1;
+ byte = stream();
+ end
+
+ return array;
+end
+
+Array.readFromQueue = function(queue,size)
+ local array = {};
+
+ for i=1,size do
+ array[i] = queue.pop();
+ end
+
+ return array;
+end
+
+Array.writeToQueue = function(queue,array)
+ local size = Array.size(array);
+
+ for i=1,size do
+ queue.push(array[i]);
+ end
+end
+
+Array.toStream = function(array)
+ local queue = Queue();
+ local i=1;
+
+ local byte = array[i];
+ while byte ~= nil do
+ queue.push(byte);
+ i=i+1;
+ byte = array[i];
+ end
+
+ return queue.pop;
+end
+
+
+local fromHexTable = {};
+for i=0,255 do
+ fromHexTable[String.format("%02X",i)]=i;
+ fromHexTable[String.format("%02x",i)]=i;
+end
+
+Array.fromHex = function(hex)
+ local array = {};
+
+ for i=1,String.len(hex)/2 do
+ local h = String.sub(hex,i*2-1,i*2);
+ array[i] = fromHexTable[h];
+ end
+
+ return array;
+end
+
+
+local toHexTable = {};
+for i=0,255 do
+ toHexTable[i]=String.format("%02X",i);
+end
+
+Array.toHex = function(array)
+ local hex = {};
+ local i = 1;
+
+ local byte = array[i];
+ while byte ~= nil do
+ hex[i] = toHexTable[byte];
+ i=i+1;
+ byte = array[i];
+ end
+
+ return table.concat(hex,"");
+
+end
+
+Array.concat = function(a,b)
+ local concat = {};
+ local out=1;
+
+ local i=1;
+ local byte = a[i];
+ while byte ~= nil do
+ concat[out] = byte;
+ i = i + 1;
+ out = out + 1;
+ byte = a[i];
+ end
+
+ local i=1;
+ local byte = b[i];
+ while byte ~= nil do
+ concat[out] = byte;
+ i = i + 1;
+ out = out + 1;
+ byte = b[i];
+ end
+
+ return concat;
+end
+
+Array.truncate = function(a,newSize)
+ local x = {};
+
+ for i=1,newSize do
+ x[i]=a[i];
+ end
+
+ return x;
+end
+
+Array.XOR = function(a,b)
+ local x = {};
+
+ for k,v in pairs(a) do
+ x[k] = XOR(v,b[k]);
+ end
+
+ return x;
+end
+
+Array.substitute = function(input,sbox)
+ local out = {};
+
+ for k,v in pairs(input) do
+ out[k] = sbox[v];
+ end
+
+ return out;
+end
+
+Array.permute = function(input,pbox)
+ local out = {};
+
+ for k,v in pairs(pbox) do
+ out[k] = input[v];
+ end
+
+ return out;
+end
+
+Array.copy = function(input)
+ local out = {};
+
+ for k,v in pairs(input) do
+ out[k] = v;
+ end
+ return out;
+end
+
+Array.slice = function(input,start,stop)
+ local out = {};
+
+ for i=start,stop do
+ out[i-start+1] = input[i];
+ end
+ return out;
+end
+
+
+return Array;
diff --git a/gamemode/shared/lockbox/base64.lua b/gamemode/shared/lockbox/base64.lua
new file mode 100644
index 0000000..3d9ffc3
--- /dev/null
+++ b/gamemode/shared/lockbox/base64.lua
@@ -0,0 +1,157 @@
+local String = string
+local Bit = include("bit.lua");
+
+local Array = include("array.lua");
+local Stream = include("stream.lua");
+
+local AND = Bit.band;
+local OR = Bit.bor;
+local NOT = Bit.bnot;
+local XOR = Bit.bxor;
+local LROT = Bit.lrotate;
+local RROT = Bit.rrotate;
+local LSHIFT = Bit.lshift;
+local RSHIFT = Bit.rshift;
+
+
+local SYMBOLS = {
+[0]="A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P",
+ "Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f",
+ "g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v",
+ "w","x","y","z","0","1","2","3","4","5","6","7","8","9","+","/"};
+
+local LOOKUP = {};
+
+for k,v in pairs(SYMBOLS) do
+ LOOKUP[k]=v;
+ LOOKUP[v]=k;
+end
+
+
+local Base64 = {};
+
+Base64.fromStream = function(stream)
+ local bits = 0x00;
+ local bitCount = 0;
+ local base64 = {};
+
+ local byte = stream();
+ while byte ~= nil do
+ bits = OR(LSHIFT(bits,8),byte);
+ bitCount = bitCount + 8;
+ while bitCount >= 6 do
+ bitCount = bitCount - 6;
+ local temp = RSHIFT(bits,bitCount);
+ table.insert(base64,LOOKUP[temp]);
+ bits = AND(bits,NOT(LSHIFT(0xFFFFFFFF,bitCount)));
+ end
+ byte = stream();
+ end
+
+ if (bitCount == 4) then
+ bits = LSHIFT(bits,2);
+ table.insert(base64,LOOKUP[bits]);
+ table.insert(base64,"=");
+ elseif (bitCount == 2) then
+ bits = LSHIFT(bits,4);
+ table.insert(base64,LOOKUP[bits]);
+ table.insert(base64,"==");
+ end
+
+ return table.concat(base64,"");
+end
+
+Base64.fromArray = function(array)
+ local bits = 0x00;
+ local bitCount = 0;
+ local base64 = {};
+
+ local ind = 1;
+
+ local byte = array[ind]; ind = ind + 1;
+ while byte ~= nil do
+ bits = OR(LSHIFT(bits,8),byte);
+ bitCount = bitCount + 8;
+ while bitCount >= 6 do
+ bitCount = bitCount - 6;
+ local temp = RSHIFT(bits,bitCount);
+ table.insert(base64,LOOKUP[temp]);
+ bits = AND(bits,NOT(LSHIFT(0xFFFFFFFF,bitCount)));
+ end
+ byte = array[ind]; ind = ind + 1;
+ end
+
+ if (bitCount == 4) then
+ bits = LSHIFT(bits,2);
+ table.insert(base64,LOOKUP[bits]);
+ table.insert(base64,"=");
+ elseif (bitCount == 2) then
+ bits = LSHIFT(bits,4);
+ table.insert(base64,LOOKUP[bits]);
+ table.insert(base64,"==");
+ end
+
+ return table.concat(base64,"");
+end
+
+Base64.fromString = function(string)
+ return Base64.fromArray(Array.fromString(string));
+end
+
+
+
+Base64.toStream = function(base64)
+ return Stream.fromArray(Base64.toArray(base64));
+end
+
+Base64.toArray = function(base64)
+ local bits = 0x00;
+ local bitCount = 0;
+
+ local bytes = {};
+
+ for c in String.gmatch(base64,".") do
+ if (c == "=") then
+ bits = RSHIFT(bits,2); bitCount = bitCount - 2;
+ else
+ bits = LSHIFT(bits,6); bitCount = bitCount + 6;
+ bits = OR(bits,LOOKUP[c]);
+ end
+
+ while(bitCount >= 8) do
+ bitCount = bitCount - 8;
+ local temp = RSHIFT(bits,bitCount);
+ table.insert(bytes,temp);
+ bits = AND(bits,NOT(LSHIFT(0xFFFFFFFF,bitCount)));
+ end
+ end
+
+ return bytes;
+end
+
+Base64.toString = function(base64)
+ local bits = 0x00;
+ local bitCount = 0;
+
+ local chars = {};
+
+ for c in String.gmatch(base64,".") do
+ if (c == "=") then
+ bits = RSHIFT(bits,2); bitCount = bitCount - 2;
+ else
+ bits = LSHIFT(bits,6); bitCount = bitCount + 6;
+ bits = OR(bits,LOOKUP[c]);
+ end
+
+ while(bitCount >= 8) do
+ bitCount = bitCount - 8;
+ local temp = RSHIFT(bits,bitCount);
+ table.insert(chars,String.char(temp));
+ bits = AND(bits,NOT(LSHIFT(0xFFFFFFFF,bitCount)));
+ end
+ end
+
+ return table.concat(chars,"");
+end
+
+return Base64;
diff --git a/gamemode/shared/lockbox/bit.lua b/gamemode/shared/lockbox/bit.lua
new file mode 100644
index 0000000..0ccdb82
--- /dev/null
+++ b/gamemode/shared/lockbox/bit.lua
@@ -0,0 +1,11 @@
+local e = bit
+
+-- Workaround to support Lua 5.2 bit32 API with the LuaJIT bit one
+if e.rol and not e.lrotate then
+ e.lrotate = e.rol
+end
+if e.ror and not e.rrotate then
+ e.rrotate = e.ror
+end
+
+return bit
diff --git a/gamemode/shared/lockbox/ecb.lua b/gamemode/shared/lockbox/ecb.lua
new file mode 100644
index 0000000..67f4514
--- /dev/null
+++ b/gamemode/shared/lockbox/ecb.lua
@@ -0,0 +1,191 @@
+local Array = include("array.lua");
+local Stream = include("stream.lua");
+local Queue = include("queue.lua");
+
+local Bit = include("bit.lua");
+
+local CBC = {};
+
+CBC.Cipher = function()
+
+ local public = {};
+
+ local key;
+ local blockCipher;
+ local padding;
+ local inputQueue;
+ local outputQueue;
+ local iv;
+
+ public.setKey = function(keyBytes)
+ print("Set key to:")
+ print(keyBytes)
+ key = keyBytes;
+ return public;
+ end
+
+ public.setBlockCipher = function(cipher)
+ blockCipher = cipher;
+ return public;
+ end
+
+ public.setPadding = function(paddingMode)
+ padding = paddingMode;
+ return public;
+ end
+
+ public.init = function()
+ inputQueue = Queue();
+ outputQueue = Queue();
+ iv = nil;
+ return public;
+ end
+
+ public.update = function(messageStream)
+ print("Entering update")
+ local byte = messageStream();
+ while (byte ~= nil) do
+ print("processing byte")
+ inputQueue.push(byte);
+ print("inputQueue.size is:" .. inputQueue.size())
+ print("blockCipher.blockSize:" .. blockCipher.blockSize)
+ if(inputQueue.size() >= blockCipher.blockSize) then
+ print("reading from queue")
+ local block = Array.readFromQueue(inputQueue,blockCipher.blockSize);
+ if(iv == nil) then
+ print("iv was nil, iv is now")
+ iv = block;
+ PrintTable(block)
+ else
+ print("iv was not nil, doing thing")
+ local out = Array.XOR(iv,block);
+ print("Calling encrypt with key:")
+ print(key)
+ print("and out")
+ print(out)
+ out = blockCipher.encrypt(key,out);
+ print("Out was:")
+ print(out)
+ Array.writeToQueue(outputQueue,out);
+ iv = out;
+ end
+ end
+ byte = messageStream();
+ end
+ print("Before update returned, blockCipher was ")
+ PrintTable(blockCipher)
+ return public;
+ end
+
+ public.finish = function()
+ paddingStream = padding(blockCipher.blockSize,inputQueue.getHead());
+ public.update(paddingStream);
+
+ return public;
+ end
+
+ public.getOutputQueue = function()
+ return outputQueue;
+ end
+
+ public.asHex = function()
+ print("Outputqueue is:")
+ PrintTable(outputQueue)
+ return Stream.toHex(outputQueue.pop);
+ end
+
+ public.asBytes = function()
+ return Stream.toArray(outputQueue.pop);
+ end
+
+ return public;
+
+end
+
+
+CBC.Decipher = function()
+
+ local public = {};
+
+ local key;
+ local blockCipher;
+ local padding;
+ local inputQueue;
+ local outputQueue;
+ local iv;
+
+ public.setKey = function(keyBytes)
+ key = keyBytes;
+ return public;
+ end
+
+ public.setBlockCipher = function(cipher)
+ blockCipher = cipher;
+ return public;
+ end
+
+ public.setPadding = function(paddingMode)
+ padding = paddingMode;
+ return public;
+ end
+
+ public.init = function()
+ inputQueue = Queue();
+ outputQueue = Queue();
+ iv = nil;
+ return public;
+ end
+
+ public.update = function(messageStream)
+ print("Updateing decipher with messagestream")
+ local byte = messageStream();
+ while (byte ~= nil) do
+ inputQueue.push(byte);
+ if(inputQueue.size() >= blockCipher.blockSize) then
+ local block = Array.readFromQueue(inputQueue,blockCipher.blockSize);
+
+ if(iv == nil) then
+ iv = block;
+ print("Setting iv to ")
+ PrintTable(iv)
+ else
+ local out = block;
+ out = blockCipher.decrypt(key,out);
+ out = Array.XOR(iv,out);
+ Array.writeToQueue(outputQueue,out);
+ iv = block;
+ end
+ end
+ byte = messageStream();
+ end
+ return public;
+ end
+
+ public.finish = function()
+ paddingStream = padding(blockCipher.blockSize,inputQueue.getHead());
+ public.update(paddingStream);
+
+ return public;
+ end
+
+ public.getOutputQueue = function()
+ return outputQueue;
+ end
+
+ public.asHex = function()
+ return Stream.toHex(outputQueue.pop);
+ end
+
+ public.asBytes = function()
+ return Stream.toArray(outputQueue.pop);
+ end
+
+ public.asString = function()
+ return Stream.toString(outputQueue.pop)
+ end
+
+ return public;
+
+end
+
+return CBC;
diff --git a/gamemode/shared/lockbox/padding.lua b/gamemode/shared/lockbox/padding.lua
new file mode 100644
index 0000000..72be077
--- /dev/null
+++ b/gamemode/shared/lockbox/padding.lua
@@ -0,0 +1,21 @@
+local Stream = include("stream.lua");
+
+local ZeroPadding = function(blockSize,byteCount)
+
+ local paddingCount = blockSize - ((byteCount -1) % blockSize) + 1;
+ local bytesLeft = paddingCount;
+
+ local stream = function()
+ if bytesLeft > 0 then
+ bytesLeft = bytesLeft - 1;
+ return 0x00;
+ else
+ return nil;
+ end
+ end
+
+ return stream;
+
+end
+
+return ZeroPadding;
diff --git a/gamemode/shared/lockbox/queue.lua b/gamemode/shared/lockbox/queue.lua
new file mode 100644
index 0000000..55b067d
--- /dev/null
+++ b/gamemode/shared/lockbox/queue.lua
@@ -0,0 +1,47 @@
+local Queue = function()
+ local queue = {};
+ local tail = 0;
+ local head = 0;
+
+ local public = {};
+
+ public.push = function(obj)
+ queue[head] = obj;
+ head = head + 1;
+ return;
+ end
+
+ public.pop = function()
+ if tail < head
+ then
+ local obj = queue[tail];
+ queue[tail] = nil;
+ tail = tail + 1;
+ return obj;
+ else
+ return nil;
+ end
+ end
+
+ public.size = function()
+ return head - tail;
+ end
+
+ public.getHead = function()
+ return head;
+ end
+
+ public.getTail = function()
+ return tail;
+ end
+
+ public.reset = function()
+ queue = {};
+ head = 0;
+ tail = 0;
+ end
+
+ return public;
+end
+
+return Queue;
diff --git a/gamemode/shared/lockbox/stream.lua b/gamemode/shared/lockbox/stream.lua
new file mode 100644
index 0000000..aeb3b18
--- /dev/null
+++ b/gamemode/shared/lockbox/stream.lua
@@ -0,0 +1,112 @@
+local Queue = include("queue.lua");
+local String = string
+
+local Stream = {};
+
+
+Stream.fromString = function(string)
+ local i=0;
+ return function()
+ print("string is:" .. string)
+ print("len is:" .. string.len(string))
+ print("i is:" .. i)
+ i=i+1;
+ if(i <= string.len(string)) then
+ return string.byte(string,i);
+ else
+ return nil;
+ end
+ end
+end
+
+
+Stream.toString = function(stream)
+ local array = {};
+ local i=1;
+
+ local byte = stream();
+ while byte ~= nil do
+ array[i] = String.char(byte);
+ i = i+1;
+ byte = stream();
+ end
+
+ return table.concat(array,"");
+end
+
+
+Stream.fromArray = function(array)
+ local queue = Queue();
+ local i=1;
+
+ local byte = array[i];
+ while byte ~= nil do
+ queue.push(byte);
+ i=i+1;
+ byte = array[i];
+ end
+
+ return queue.pop;
+end
+
+
+Stream.toArray = function(stream)
+ local array = {};
+ local i=1;
+
+ local byte = stream();
+ while byte ~= nil do
+ array[i] = byte;
+ i = i+1;
+ byte = stream();
+ end
+
+ return array;
+end
+
+
+local fromHexTable = {};
+for i=0,255 do
+ fromHexTable[String.format("%02X",i)]=i;
+ fromHexTable[String.format("%02x",i)]=i;
+end
+
+Stream.fromHex = function(hex)
+ local queue = Queue();
+
+ for i=1,String.len(hex)/2 do
+ local h = String.sub(hex,i*2-1,i*2);
+ queue.push(fromHexTable[h]);
+ end
+
+ return queue.pop;
+end
+
+
+
+local toHexTable = {};
+for i=0,255 do
+ toHexTable[i]=String.format("%02X",i);
+end
+
+Stream.toHex = function(stream)
+ print("tohex called with stream")
+ print(stream)
+ local hex = {};
+ local i = 1;
+
+ local byte = stream();
+ print("First byte is")
+ print(byte)
+ while byte ~= nil do
+ print("Createing hex:")
+ print(table.concat(hex,""))
+ hex[i] = toHexTable[byte];
+ i=i+1;
+ byte = stream();
+ end
+
+ return table.concat(hex,"");
+end
+
+return Stream;