mirror of
https://github.com/MikaylaFischler/cc-mek-scada.git
synced 2024-08-30 18:22:34 +00:00
249 lines
5.6 KiB
Lua
249 lines
5.6 KiB
Lua
local Array = require("lockbox.util.array");
|
|
local Stream = require("lockbox.util.stream");
|
|
local Queue = require("lockbox.util.queue");
|
|
|
|
local Bit = require("lockbox.util.bit");
|
|
|
|
local AND = Bit.band;
|
|
|
|
local CTR = {};
|
|
|
|
CTR.Cipher = 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
|
|
|
|
local updateIV = function()
|
|
iv[16] = iv[16] + 1;
|
|
if iv[16] <= 0xFF then return; end
|
|
iv[16] = AND(iv[16], 0xFF);
|
|
|
|
iv[15] = iv[15] + 1;
|
|
if iv[15] <= 0xFF then return; end
|
|
iv[15] = AND(iv[15], 0xFF);
|
|
|
|
iv[14] = iv[14] + 1;
|
|
if iv[14] <= 0xFF then return; end
|
|
iv[14] = AND(iv[14], 0xFF);
|
|
|
|
iv[13] = iv[13] + 1;
|
|
if iv[13] <= 0xFF then return; end
|
|
iv[13] = AND(iv[13], 0xFF);
|
|
|
|
iv[12] = iv[12] + 1;
|
|
if iv[12] <= 0xFF then return; end
|
|
iv[12] = AND(iv[12], 0xFF);
|
|
|
|
iv[11] = iv[11] + 1;
|
|
if iv[11] <= 0xFF then return; end
|
|
iv[11] = AND(iv[11], 0xFF);
|
|
|
|
iv[10] = iv[10] + 1;
|
|
if iv[10] <= 0xFF then return; end
|
|
iv[10] = AND(iv[10], 0xFF);
|
|
|
|
iv[9] = iv[9] + 1;
|
|
if iv[9] <= 0xFF then return; end
|
|
iv[9] = AND(iv[9], 0xFF);
|
|
|
|
return;
|
|
end
|
|
|
|
public.update = function(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;
|
|
else
|
|
local out = iv;
|
|
out = blockCipher.encrypt(key, out);
|
|
|
|
out = Array.XOR(out, block);
|
|
Array.writeToQueue(outputQueue, out);
|
|
updateIV();
|
|
end
|
|
end
|
|
byte = messageStream();
|
|
end
|
|
return public;
|
|
end
|
|
|
|
public.finish = function()
|
|
local 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
|
|
|
|
return public;
|
|
|
|
end
|
|
|
|
|
|
CTR.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
|
|
|
|
local updateIV = function()
|
|
iv[16] = iv[16] + 1;
|
|
if iv[16] <= 0xFF then return; end
|
|
iv[16] = AND(iv[16], 0xFF);
|
|
|
|
iv[15] = iv[15] + 1;
|
|
if iv[15] <= 0xFF then return; end
|
|
iv[15] = AND(iv[15], 0xFF);
|
|
|
|
iv[14] = iv[14] + 1;
|
|
if iv[14] <= 0xFF then return; end
|
|
iv[14] = AND(iv[14], 0xFF);
|
|
|
|
iv[13] = iv[13] + 1;
|
|
if iv[13] <= 0xFF then return; end
|
|
iv[13] = AND(iv[13], 0xFF);
|
|
|
|
iv[12] = iv[12] + 1;
|
|
if iv[12] <= 0xFF then return; end
|
|
iv[12] = AND(iv[12], 0xFF);
|
|
|
|
iv[11] = iv[11] + 1;
|
|
if iv[11] <= 0xFF then return; end
|
|
iv[11] = AND(iv[11], 0xFF);
|
|
|
|
iv[10] = iv[10] + 1;
|
|
if iv[10] <= 0xFF then return; end
|
|
iv[10] = AND(iv[10], 0xFF);
|
|
|
|
iv[9] = iv[9] + 1;
|
|
if iv[9] <= 0xFF then return; end
|
|
iv[9] = AND(iv[9], 0xFF);
|
|
|
|
return;
|
|
end
|
|
|
|
public.update = function(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;
|
|
else
|
|
local out = iv;
|
|
out = blockCipher.encrypt(key, out);
|
|
|
|
out = Array.XOR(out, block);
|
|
Array.writeToQueue(outputQueue, out);
|
|
updateIV();
|
|
end
|
|
end
|
|
byte = messageStream();
|
|
end
|
|
return public;
|
|
end
|
|
|
|
public.finish = function()
|
|
local 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
|
|
|
|
return public;
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return CTR;
|
|
|