Advertisement
1lann

Secure Connection Library

Oct 5th, 2014
147
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 21.96 KB | None | 0 0
  1. --    Secure Connection Library used in Firewolf
  2. --    Uses: RC4 (Can use another encoding/encrypting method), SHA-256 and my own Diffie Hellman key-exchange system
  3. --    Includes: SecureConnection library to easily create connections encrypted by a key to send and receive data
  4.  
  5. --    RC4
  6. --    Implementation by AgentE382
  7.  
  8.  
  9. local cryptWrapper = function(plaintext, salt)
  10.         local key = type(salt) == "table" and {unpack(salt)} or {string.byte(salt, 1, #salt)}
  11.         local S = {}
  12.         for i = 0, 255 do
  13.                 S[i] = i
  14.         end
  15.  
  16.         local j, keylength = 0, #key
  17.         for i = 0, 255 do
  18.                 j = (j + S[i] + key[i % keylength + 1]) % 256
  19.                 S[i], S[j] = S[j], S[i]
  20.         end
  21.  
  22.         local i = 0
  23.         j = 0
  24.         local chars, astable = type(plaintext) == "table" and {unpack(plaintext)} or {string.byte(plaintext, 1, #plaintext)}, false
  25.  
  26.         for n = 1, #chars do
  27.                 i = (i + 1) % 256
  28.                 j = (j + S[i]) % 256
  29.                 S[i], S[j] = S[j], S[i]
  30.                 chars[n] = bit.bxor(S[(S[i] + S[j]) % 256], chars[n])
  31.                 if chars[n] > 127 or chars[n] == 13 then
  32.                         astable = true
  33.                 end
  34.         end
  35.  
  36.         return astable and chars or string.char(unpack(chars))
  37. end
  38.  
  39.  
  40. local crypt = function(text, key)
  41.         local resp, msg = pcall(cryptWrapper, text, key)
  42.         if resp then
  43.                 return msg
  44.         else
  45.                 return nil
  46.         end
  47. end
  48.  
  49.  
  50.  
  51. --    Base64
  52. --
  53. --    Base64 Encryption/Decryption
  54. --    By KillaVanilla
  55. --    http://www.computercraft.info/forums2/index.php?/topic/12450-killavanillas-various-apis/
  56. --    http://pastebin.com/rCYDnCxn
  57.  
  58.  
  59. local alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
  60.  
  61.  
  62. local function sixBitToBase64(input)
  63.         return string.sub(alphabet, input+1, input+1)
  64. end
  65.  
  66.  
  67. local function base64ToSixBit(input)
  68.         for i=1, 64 do
  69.                 if input == string.sub(alphabet, i, i) then
  70.                         return i-1
  71.                 end
  72.         end
  73. end
  74.  
  75.  
  76. local function octetToBase64(o1, o2, o3)
  77.         local shifted = bit.brshift(bit.band(o1, 0xFC), 2)
  78.         local i1 = sixBitToBase64(shifted)
  79.         local i2 = "A"
  80.         local i3 = "="
  81.         local i4 = "="
  82.         if o2 then
  83.                 i2 = sixBitToBase64(bit.bor( bit.blshift(bit.band(o1, 3), 4), bit.brshift(bit.band(o2, 0xF0), 4) ))
  84.                 if not o3 then
  85.                         i3 = sixBitToBase64(bit.blshift(bit.band(o2, 0x0F), 2))
  86.                 else
  87.                         i3 = sixBitToBase64(bit.bor( bit.blshift(bit.band(o2, 0x0F), 2), bit.brshift(bit.band(o3, 0xC0), 6) ))
  88.                 end
  89.         else
  90.                 i2 = sixBitToBase64(bit.blshift(bit.band(o1, 3), 4))
  91.         end
  92.         if o3 then
  93.                 i4 = sixBitToBase64(bit.band(o3, 0x3F))
  94.         end
  95.  
  96.         return i1..i2..i3..i4
  97. end
  98.  
  99.  
  100. local function base64ToThreeOctet(s1)
  101.         local c1 = base64ToSixBit(string.sub(s1, 1, 1))
  102.         local c2 = base64ToSixBit(string.sub(s1, 2, 2))
  103.         local c3 = 0
  104.         local c4 = 0
  105.         local o1 = 0
  106.         local o2 = 0
  107.         local o3 = 0
  108.         if string.sub(s1, 3, 3) == "=" then
  109.                 c3 = nil
  110.                 c4 = nil
  111.         elseif string.sub(s1, 4, 4) == "=" then
  112.                 c3 = base64ToSixBit(string.sub(s1, 3, 3))
  113.                 c4 = nil
  114.         else
  115.                 c3 = base64ToSixBit(string.sub(s1, 3, 3))
  116.                 c4 = base64ToSixBit(string.sub(s1, 4, 4))
  117.         end
  118.         o1 = bit.bor( bit.blshift(c1, 2), bit.brshift(bit.band( c2, 0x30 ), 4) )
  119.         if c3 then
  120.                 o2 = bit.bor( bit.blshift(bit.band(c2, 0x0F), 4), bit.brshift(bit.band( c3, 0x3C ), 2) )
  121.         else
  122.                 o2 = nil
  123.         end
  124.         if c4 then
  125.                 o3 = bit.bor( bit.blshift(bit.band(c3, 3), 6), c4 )
  126.         else
  127.                 o3 = nil
  128.         end
  129.         return o1, o2, o3
  130. end
  131.  
  132.  
  133. local function splitIntoBlocks(bytes)
  134.         local blockNum = 1
  135.         local blocks = {}
  136.         for i=1, #bytes, 3 do
  137.                 blocks[blockNum] = {bytes[i], bytes[i+1], bytes[i+2]}
  138.                 blockNum = blockNum+1
  139.         end
  140.         return blocks
  141. end
  142.  
  143.  
  144. function base64Encode(bytes)
  145.         local blocks = splitIntoBlocks(bytes)
  146.         local output = ""
  147.         for i=1, #blocks do
  148.                 output = output..octetToBase64( unpack(blocks[i]) )
  149.         end
  150.         return output
  151. end
  152.  
  153.  
  154. function base64Decode(str)
  155.         local bytes = {}
  156.         local blocks = {}
  157.         local blockNum = 1
  158.  
  159.         for i=1, #str, 4 do
  160.                 blocks[blockNum] = string.sub(str, i, i+3)
  161.                 blockNum = blockNum+1
  162.         end
  163.  
  164.         for i=1, #blocks do
  165.                 local o1, o2, o3 = base64ToThreeOctet(blocks[i])
  166.                 table.insert(bytes, o1)
  167.                 table.insert(bytes, o2)
  168.                 table.insert(bytes, o3)
  169.         end
  170.  
  171.         return bytes
  172. end
  173.  
  174.  
  175.  
  176. --    SHA-256
  177. --
  178. --    Adaptation of the Secure Hashing Algorithm (SHA-244/256)
  179. --    Found Here: http://lua-users.org/wiki/SecureHashAlgorithm
  180. --
  181. --    Using an adapted version of the bit library
  182. --    Found Here: https://bitbucket.org/Boolsheet/bslf/src/1ee664885805/bit.lua
  183.  
  184.  
  185. local MOD = 2^32
  186. local MODM = MOD-1
  187.  
  188.  
  189. local function memoize(f)
  190.         local mt = {}
  191.         local t = setmetatable({}, mt)
  192.         function mt:__index(k)
  193.                 local v = f(k)
  194.                 t[k] = v
  195.                 return v
  196.         end
  197.         return t
  198. end
  199.  
  200.  
  201. local function make_bitop_uncached(t, m)
  202.         local function bitop(a, b)
  203.                 local res,p = 0,1
  204.                 while a ~= 0 and b ~= 0 do
  205.                         local am, bm = a % m, b % m
  206.                         res = res + t[am][bm] * p
  207.                         a = (a - am) / m
  208.                         b = (b - bm) / m
  209.                         p = p * m
  210.                 end
  211.                 res = res + (a + b) * p
  212.                 return res
  213.         end
  214.  
  215.         return bitop
  216. end
  217.  
  218.  
  219. local function make_bitop(t)
  220.         local op1 = make_bitop_uncached(t,2^1)
  221.         local op2 = memoize(function(a)
  222.                 return memoize(function(b)
  223.                         return op1(a, b)
  224.                 end)
  225.         end)
  226.         return make_bitop_uncached(op2, 2 ^ (t.n or 1))
  227. end
  228.  
  229.  
  230. local customBxor1 = make_bitop({[0] = {[0] = 0,[1] = 1}, [1] = {[0] = 1, [1] = 0}, n = 4})
  231.  
  232. local function customBxor(a, b, c, ...)
  233.         local z = nil
  234.         if b then
  235.                 a = a % MOD
  236.                 b = b % MOD
  237.                 z = customBxor1(a, b)
  238.                 if c then
  239.                         z = customBxor(z, c, ...)
  240.                 end
  241.                 return z
  242.         elseif a then
  243.                 return a % MOD
  244.         else
  245.                 return 0
  246.         end
  247. end
  248.  
  249.  
  250. local function customBand(a, b, c, ...)
  251.         local z
  252.         if b then
  253.                 a = a % MOD
  254.                 b = b % MOD
  255.                 z = ((a + b) - customBxor1(a,b)) / 2
  256.                 if c then
  257.                         z = customBand(z, c, ...)
  258.                 end
  259.                 return z
  260.         elseif a then
  261.                 return a % MOD
  262.         else
  263.                 return MODM
  264.         end
  265. end
  266.  
  267.  
  268. local function bnot(x)
  269.         return (-1 - x) % MOD
  270. end
  271.  
  272.  
  273. local function rshift1(a, disp)
  274.         if disp < 0 then
  275.                 return lshift(a, -disp)
  276.         end
  277.         return math.floor(a % 2 ^ 32 / 2 ^ disp)
  278. end
  279.  
  280.  
  281. local function rshift(x, disp)
  282.         if disp > 31 or disp < -31 then
  283.                 return 0
  284.         end
  285.         return rshift1(x % MOD, disp)
  286. end
  287.  
  288.  
  289. local function lshift(a, disp)
  290.         if disp < 0 then
  291.                 return rshift(a, -disp)
  292.         end
  293.         return (a * 2 ^ disp) % 2 ^ 32
  294. end
  295.  
  296.  
  297. local function rrotate(x, disp)
  298.     x = x % MOD
  299.     disp = disp % 32
  300.     local low = customBand(x, 2 ^ disp - 1)
  301.     return rshift(x, disp) + lshift(low, 32 - disp)
  302. end
  303.  
  304.  
  305. local k = {
  306.         0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
  307.         0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
  308.         0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
  309.         0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
  310.         0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
  311.         0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
  312.         0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
  313.         0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
  314.         0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
  315.         0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
  316.         0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
  317.         0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
  318.         0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
  319.         0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
  320.         0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
  321.         0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
  322. }
  323.  
  324.  
  325. local function str2hexa(s)
  326.         return (string.gsub(s, ".", function(c)
  327.                 return string.format("%02x", string.byte(c))
  328.         end))
  329. end
  330.  
  331.  
  332. local function num2s(l, n)
  333.         local s = ""
  334.         for i = 1, n do
  335.                 local rem = l % 256
  336.                 s = string.char(rem) .. s
  337.                 l = (l - rem) / 256
  338.         end
  339.         return s
  340. end
  341.  
  342.  
  343. local function s232num(s, i)
  344.         local n = 0
  345.         for i = i, i + 3 do
  346.                 n = n*256 + string.byte(s, i)
  347.         end
  348.         return n
  349. end
  350.  
  351.  
  352. local function preproc(msg, len)
  353.         local extra = 64 - ((len + 9) % 64)
  354.         len = num2s(8 * len, 8)
  355.         msg = msg .. "\128" .. string.rep("\0", extra) .. len
  356.         assert(#msg % 64 == 0)
  357.         return msg
  358. end
  359.  
  360.  
  361. local function initH256(H)
  362.         H[1] = 0x6a09e667
  363.         H[2] = 0xbb67ae85
  364.         H[3] = 0x3c6ef372
  365.         H[4] = 0xa54ff53a
  366.         H[5] = 0x510e527f
  367.         H[6] = 0x9b05688c
  368.         H[7] = 0x1f83d9ab
  369.         H[8] = 0x5be0cd19
  370.         return H
  371. end
  372.  
  373.  
  374. local function digestblock(msg, i, H)
  375.         local w = {}
  376.         for j = 1, 16 do
  377.                 w[j] = s232num(msg, i + (j - 1)*4)
  378.         end
  379.         for j = 17, 64 do
  380.                 local v = w[j - 15]
  381.                 local s0 = customBxor(rrotate(v, 7), rrotate(v, 18), rshift(v, 3))
  382.                 v = w[j - 2]
  383.                 w[j] = w[j - 16] + s0 + w[j - 7] + customBxor(rrotate(v, 17), rrotate(v, 19), rshift(v, 10))
  384.         end
  385.  
  386.         local a, b, c, d, e, f, g, h = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8]
  387.         for i = 1, 64 do
  388.                 local s0 = customBxor(rrotate(a, 2), rrotate(a, 13), rrotate(a, 22))
  389.                 local maj = customBxor(customBand(a, b), customBand(a, c), customBand(b, c))
  390.                 local t2 = s0 + maj
  391.                 local s1 = customBxor(rrotate(e, 6), rrotate(e, 11), rrotate(e, 25))
  392.                 local ch = customBxor (customBand(e, f), customBand(bnot(e), g))
  393.                 local t1 = h + s1 + ch + k[i] + w[i]
  394.                 h, g, f, e, d, c, b, a = g, f, e, d + t1, c, b, a, t1 + t2
  395.         end
  396.  
  397.         H[1] = customBand(H[1] + a)
  398.         H[2] = customBand(H[2] + b)
  399.         H[3] = customBand(H[3] + c)
  400.         H[4] = customBand(H[4] + d)
  401.         H[5] = customBand(H[5] + e)
  402.         H[6] = customBand(H[6] + f)
  403.         H[7] = customBand(H[7] + g)
  404.         H[8] = customBand(H[8] + h)
  405. end
  406.  
  407.  
  408. local function sha256(msg)
  409.         msg = preproc(msg, #msg)
  410.         local H = initH256({})
  411.         for i = 1, #msg, 64 do
  412.                 digestblock(msg, i, H)
  413.         end
  414.         return str2hexa(num2s(H[1], 4) .. num2s(H[2], 4) .. num2s(H[3], 4) .. num2s(H[4], 4) ..
  415.                 num2s(H[5], 4) .. num2s(H[6], 4) .. num2s(H[7], 4) .. num2s(H[8], 4))
  416. end
  417.  
  418.  
  419. local protocolName = "Firewolf"
  420.  
  421.  
  422.  
  423. --    Cryptography
  424.  
  425.  
  426. local Cryptography = {}
  427. Cryptography.sha = {}
  428. Cryptography.base64 = {}
  429. Cryptography.aes = {}
  430.  
  431.  
  432. function Cryptography.bytesFromMessage(msg)
  433.         local bytes = {}
  434.  
  435.         for i = 1, msg:len() do
  436.                 local letter = string.byte(msg:sub(i, i))
  437.                 table.insert(bytes, letter)
  438.         end
  439.  
  440.         return bytes
  441. end
  442.  
  443.  
  444. function Cryptography.messageFromBytes(bytes)
  445.         local msg = ""
  446.  
  447.         for i = 1, #bytes do
  448.                 local letter = string.char(bytes[i])
  449.                 msg = msg .. letter
  450.         end
  451.  
  452.         return msg
  453. end
  454.  
  455.  
  456. function Cryptography.bytesFromKey(key)
  457.         local bytes = {}
  458.  
  459.         for i = 1, key:len() / 2 do
  460.                 local group = key:sub((i - 1) * 2 + 1, (i - 1) * 2 + 1)
  461.                 local num = tonumber(group, 16)
  462.                 table.insert(bytes, num)
  463.         end
  464.  
  465.         return bytes
  466. end
  467.  
  468.  
  469. function Cryptography.sha.sha256(msg)
  470.         return sha256(msg)
  471. end
  472.  
  473.  
  474. function Cryptography.aes.encrypt(msg, key)
  475.         return base64Encode(crypt(msg, key))
  476. end
  477.  
  478.  
  479. function Cryptography.aes.decrypt(msg, key)
  480.         return crypt(base64Decode(msg), key)
  481. end
  482.  
  483.  
  484. function Cryptography.base64.encode(msg)
  485.         return base64Encode(Cryptography.bytesFromMessage(msg))
  486. end
  487.  
  488.  
  489. function Cryptography.base64.decode(msg)
  490.         return Cryptography.messageFromBytes(base64Decode(msg))
  491. end
  492.  
  493.  
  494. function Cryptography.channel(text)
  495.         local hashed = Cryptography.sha.sha256(text)
  496.  
  497.         local total = 0
  498.  
  499.         for i = 1, hashed:len() do
  500.                 total = total + string.byte(hashed:sub(i, i))
  501.         end
  502.  
  503.         return (total % 55530) + 10000
  504. end
  505.  
  506.  
  507. function Cryptography.sanatize(text)
  508.         local sanatizeChars = {"%", "(", ")", "[", "]", ".", "+", "-", "*", "?", "^", "$"}
  509.  
  510.         for _, char in pairs(sanatizeChars) do
  511.                 text = text:gsub("%"..char, "%%%"..char)
  512.         end
  513.         return text
  514. end
  515.  
  516.  
  517.  
  518. --    Modem
  519.  
  520.  
  521. local Modem = {}
  522. Modem.modems = {}
  523.  
  524.  
  525. function Modem.exists()
  526.         Modem.exists = false
  527.         for _, side in pairs(rs.getSides()) do
  528.                 if peripheral.isPresent(side) and peripheral.getType(side) == "modem" then
  529.                         Modem.exists = true
  530.  
  531.                         if not Modem.modems[side] then
  532.                                 Modem.modems[side] = peripheral.wrap(side)
  533.                         end
  534.                 end
  535.         end
  536.  
  537.         return Modem.exists
  538. end
  539.  
  540.  
  541. function Modem.open(channel)
  542.         if not Modem.exists then
  543.                 return false
  544.         end
  545.  
  546.         for side, modem in pairs(Modem.modems) do
  547.                 modem.open(channel)
  548.                 rednet.open(side)
  549.         end
  550.  
  551.         return true
  552. end
  553.  
  554.  
  555. function Modem.close(channel)
  556.         if not Modem.exists then
  557.                 return false
  558.         end
  559.  
  560.         for side, modem in pairs(Modem.modems) do
  561.                 modem.close(channel)
  562.         end
  563.  
  564.         return true
  565. end
  566.  
  567.  
  568. function Modem.closeAll()
  569.         if not Modem.exists then
  570.                 return false
  571.         end
  572.  
  573.         for side, modem in pairs(Modem.modems) do
  574.                 modem.closeAll()
  575.         end
  576.  
  577.         return true
  578. end
  579.  
  580.  
  581. function Modem.isOpen(channel)
  582.         if not Modem.exists then
  583.                 return false
  584.         end
  585.  
  586.         local isOpen = false
  587.         for side, modem in pairs(Modem.modems) do
  588.                 if modem.isOpen(channel) then
  589.                         isOpen = true
  590.                         break
  591.                 end
  592.         end
  593.  
  594.         return isOpen
  595. end
  596.  
  597.  
  598. function Modem.transmit(channel, msg)
  599.         if not Modem.exists then
  600.                 return false
  601.         end
  602.  
  603.         if not Modem.isOpen(channel) then
  604.                 Modem.open(channel)
  605.         end
  606.  
  607.         for side, modem in pairs(Modem.modems) do
  608.                 modem.transmit(channel, channel, msg)
  609.         end
  610.  
  611.         return true
  612. end
  613.  
  614.  
  615.  
  616. --    Handshake
  617.  
  618.  
  619. local Handshake = {}
  620.  
  621. Handshake.prime = 625210769
  622. Handshake.channel = 54569
  623. Handshake.base = -1
  624. Handshake.secret = -1
  625. Handshake.sharedSecret = -1
  626. Handshake.packetHeader = "["..protocolName.."-Handshake-Packet-Header]"
  627. Handshake.packetMatch = "%["..protocolName.."%-Handshake%-Packet%-Header%](.+)"
  628.  
  629.  
  630. function Handshake.exponentWithModulo(base, exponent, modulo)
  631.         local remainder = base
  632.  
  633.         for i = 1, exponent-1 do
  634.                 remainder = remainder * remainder
  635.                 if remainder >= modulo then
  636.                         remainder = remainder % modulo
  637.                 end
  638.         end
  639.  
  640.         return remainder
  641. end
  642.  
  643.  
  644. function Handshake.clear()
  645.         Handshake.base = -1
  646.         Handshake.secret = -1
  647.         Handshake.sharedSecret = -1
  648. end
  649.  
  650.  
  651. function Handshake.generateInitiatorData()
  652.         Handshake.base = math.random(10,99999)
  653.         Handshake.secret = math.random(10,99999)
  654.         return {
  655.                 type = "initiate",
  656.                 prime = Handshake.prime,
  657.                 base = Handshake.base,
  658.                 moddedSecret = Handshake.exponentWithModulo(Handshake.base, Handshake.secret, Handshake.prime)
  659.         }
  660. end
  661.  
  662.  
  663. function Handshake.generateResponseData(initiatorData)
  664.         local isPrimeANumber = type(initiatorData.prime) == "number"
  665.         local isPrimeMatching = initiatorData.prime == Handshake.prime
  666.         local isBaseANumber = type(initiatorData.base) == "number"
  667.         local isInitiator = initiatorData.type == "initiate"
  668.         local isModdedSecretANumber = type(initiatorData.moddedSecret) == "number"
  669.         local areAllNumbersNumbers = isPrimeANumber and isBaseANumber and isModdedSecretANumber
  670.  
  671.         if areAllNumbersNumbers and isPrimeMatching then
  672.                 if isInitiator then
  673.                         Handshake.base = initiatorData.base
  674.                         Handshake.secret = math.random(10,99999)
  675.                         Handshake.sharedSecret = Handshake.exponentWithModulo(initiatorData.moddedSecret, Handshake.secret, Handshake.prime)
  676.                         return {
  677.                                 type = "response",
  678.                                 prime = Handshake.prime,
  679.                                 base = Handshake.base,
  680.                                 moddedSecret = Handshake.exponentWithModulo(Handshake.base, Handshake.secret, Handshake.prime)
  681.                         }, Handshake.sharedSecret
  682.                 elseif initiatorData.type == "response" and Handshake.base > 0 and Handshake.secret > 0 then
  683.                         Handshake.sharedSecret = Handshake.exponentWithModulo(initiatorData.moddedSecret, Handshake.secret, Handshake.prime)
  684.                         return Handshake.sharedSecret
  685.                 else
  686.                         return false
  687.                 end
  688.         else
  689.                 return false
  690.         end
  691. end
  692.  
  693.  
  694.  
  695. --    Secure Connection
  696.  
  697.  
  698. local SecureConnection = {}
  699. SecureConnection.__index = SecureConnection
  700.  
  701.  
  702. SecureConnection.packetHeaderA = "[" .. protocolName .. "-"
  703. SecureConnection.packetHeaderB = "-SecureConnection-Packet-Header]"
  704. SecureConnection.packetMatchA = "%[" .. protocolName .. "%-"
  705. SecureConnection.packetMatchB = "%-SecureConnection%-Packet%-Header%](.+)"
  706. SecureConnection.connectionTimeout = 0.1
  707. SecureConnection.successPacketTimeout = 0.1
  708.  
  709.  
  710. function SecureConnection.new(secret, key, identifier, distance, isRednet)
  711.         local self = setmetatable({}, SecureConnection)
  712.         self:setup(secret, key, identifier, distance, isRednet)
  713.         return self
  714. end
  715.  
  716.  
  717. function SecureConnection:setup(secret, key, identifier, distance, isRednet)
  718.         local rawSecret
  719.  
  720.         if isRednet then
  721.                 self.isRednet = true
  722.                 self.distance = -1
  723.                 self.rednet_id = distance
  724.                 rawSecret = protocolName .. "|" .. tostring(secret) .. "|" .. tostring(identifier) ..
  725.                 "|" .. tostring(key) .. "|rednet"
  726.         else
  727.                 self.isRednet = false
  728.                 self.distance = distance
  729.                 rawSecret = protocolName .. "|" .. tostring(secret) .. "|" .. tostring(identifier) ..
  730.                 "|" .. tostring(key) .. "|" .. tostring(distance)
  731.         end
  732.  
  733.         self.identifier = identifier
  734.         self.packetMatch = SecureConnection.packetMatchA .. Cryptography.sanatize(identifier) .. SecureConnection.packetMatchB
  735.         self.packetHeader = SecureConnection.packetHeaderA .. identifier .. SecureConnection.packetHeaderB
  736.         self.secret = Cryptography.sha.sha256(rawSecret)
  737.         self.channel = Cryptography.channel(self.secret)
  738.  
  739.         if not self.isRednet then
  740.                 Modem.open(self.channel)
  741.         end
  742. end
  743.  
  744.  
  745. function SecureConnection:verifyHeader(msg)
  746.         if msg:match(self.packetMatch) then
  747.                 return true
  748.         else
  749.                 return false
  750.         end
  751. end
  752.  
  753.  
  754. function SecureConnection:sendMessage(msg, rednetProtocol)
  755.         local rawEncryptedMsg = Cryptography.aes.encrypt(self.packetHeader .. msg, self.secret)
  756.         local encryptedMsg = self.packetHeader .. rawEncryptedMsg
  757.  
  758.         if self.isRednet then
  759.                 rednet.send(self.rednet_id, encryptedMsg, rednetProtocol)
  760.                 return true
  761.         else
  762.                 return Modem.transmit(self.channel, encryptedMsg)
  763.         end
  764. end
  765.  
  766.  
  767. function SecureConnection:decryptMessage(msg)
  768.         if self:verifyHeader(msg) then
  769.                 local encrypted = msg:match(self.packetMatch)
  770.  
  771.                 local unencryptedMsg = nil
  772.                 pcall(function() unencryptedMsg = Cryptography.aes.decrypt(encrypted, self.secret) end)
  773.                 if not unencryptedMsg then
  774.                         return false, "Could not decrypt"
  775.                 end
  776.  
  777.                 if self:verifyHeader(unencryptedMsg) then
  778.                         return true, unencryptedMsg:match(self.packetMatch)
  779.                 else
  780.                         return false, "Could not verify"
  781.                 end
  782.         else
  783.                 return false, "Could not stage 1 verify"
  784.         end
  785. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement