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;