| -- | |
| -- RSA Encryption/Decryption Library | |
| -- By 1lann | |
| -- | |
| -- Refer to license: http://pastebin.com/9gWSyqQt | |
| -- | |
| -- See gists comment at the bottom of the page for FAQ and updates! | |
| -- | |
| -- | |
| -- Start of third-party libraries/helpers | |
| -- | |
| -- two functions to help make Lua act more like C | |
| local function fl(x) | |
| if x < 0 then | |
| return math.ceil(x) + 0 -- make -0 go away | |
| else | |
| return math.floor(x) | |
| end | |
| end | |
| local function cmod(a, b) | |
| local x = a % b | |
| if a < 0 and x > 0 then | |
| x = x - b | |
| end | |
| return x | |
| end | |
| local radix = 2^24 -- maybe up to 2^26 is safe? | |
| local radix_sqrt = fl(math.sqrt(radix)) | |
| local bigintmt -- forward decl | |
| local function alloc() | |
| local bi = {} | |
| setmetatable(bi, bigintmt) | |
| bi.comps = {} | |
| bi.sign = 1; | |
| return bi | |
| end | |
| local function clone(a) | |
| local bi = alloc() | |
| bi.sign = a.sign | |
| local c = bi.comps | |
| local ac = a.comps | |
| for i = 1, #ac do | |
| c[i] = ac[i] | |
| end | |
| return bi | |
| end | |
| local function normalize(bi, notrunc) | |
| local c = bi.comps | |
| local v | |
| -- borrow for negative components | |
| for i = 1, #c - 1 do | |
| v = c[i] | |
| if v < 0 then | |
| c[i+1] = c[i+1] + fl(v / radix) - 1 | |
| v = cmod(v, radix) | |
| if v ~= 0 then | |
| c[i] = v + radix | |
| else | |
| c[i] = v | |
| c[i+1] = c[i+1] + 1 | |
| end | |
| end | |
| end | |
| -- is top component negative? | |
| if c[#c] < 0 then | |
| -- switch the sign and fix components | |
| bi.sign = -bi.sign | |
| for i = 1, #c - 1 do | |
| v = c[i] | |
| c[i] = radix - v | |
| c[i+1] = c[i+1] + 1 | |
| end | |
| c[#c] = -c[#c] | |
| end | |
| -- carry for components larger than radix | |
| for i = 1, #c do | |
| v = c[i] | |
| if v > radix then | |
| c[i+1] = (c[i+1] or 0) + fl(v / radix) | |
| c[i] = cmod(v, radix) | |
| end | |
| end | |
| -- trim off leading zeros | |
| if not notrunc then | |
| for i = #c, 2, -1 do | |
| if c[i] == 0 then | |
| c[i] = nil | |
| else | |
| break | |
| end | |
| end | |
| end | |
| -- check for -0 | |
| if #c == 1 and c[1] == 0 and bi.sign == -1 then | |
| bi.sign = 1 | |
| end | |
| end | |
| local function negate(a) | |
| local bi = clone(a) | |
| bi.sign = -bi.sign | |
| return bi | |
| end | |
| local function compare(a, b) | |
| local ac, bc = a.comps, b.comps | |
| local as, bs = a.sign, b.sign | |
| if ac == bc then | |
| return 0 | |
| elseif as > bs then | |
| return 1 | |
| elseif as < bs then | |
| return -1 | |
| elseif #ac > #bc then | |
| return as | |
| elseif #ac < #bc then | |
| return -as | |
| end | |
| for i = #ac, 1, -1 do | |
| if ac[i] > bc[i] then | |
| return as | |
| elseif ac[i] < bc[i] then | |
| return -as | |
| end | |
| end | |
| return 0 | |
| end | |
| local function lt(a, b) | |
| return compare(a, b) < 0 | |
| end | |
| local function eq(a, b) | |
| return compare(a, b) == 0 | |
| end | |
| local function le(a, b) | |
| return compare(a, b) <= 0 | |
| end | |
| local function addint(a, n) | |
| local bi = clone(a) | |
| if bi.sign == 1 then | |
| bi.comps[1] = bi.comps[1] + n | |
| else | |
| bi.comps[1] = bi.comps[1] - n | |
| end | |
| normalize(bi) | |
| return bi | |
| end | |
| local function add(a, b) | |
| if type(a) == "number" then | |
| return addint(b, a) | |
| elseif type(b) == "number" then | |
| return addint(a, b) | |
| end | |
| local bi = clone(a) | |
| local sign = bi.sign == b.sign | |
| local c = bi.comps | |
| for i = #c + 1, #b.comps do | |
| c[i] = 0 | |
| end | |
| local bc = b.comps | |
| for i = 1, #bc do | |
| local v = bc[i] | |
| if sign then | |
| c[i] = c[i] + v | |
| else | |
| c[i] = c[i] - v | |
| end | |
| end | |
| normalize(bi) | |
| return bi | |
| end | |
| local function sub(a, b) | |
| if type(b) == "number" then | |
| return addint(a, -b) | |
| elseif type(a) == "number" then | |
| a = bigint(a) | |
| end | |
| return add(a, negate(b)) | |
| end | |
| local function mulint(a, b) | |
| local bi = clone(a) | |
| if b < 0 then | |
| b = -b | |
| bi.sign = -bi.sign | |
| end | |
| local bc = bi.comps | |
| for i = 1, #bc do | |
| bc[i] = bc[i] * b | |
| end | |
| normalize(bi) | |
| return bi | |
| end | |
| local function multiply(a, b) | |
| local bi = alloc() | |
| local c = bi.comps | |
| local ac, bc = a.comps, b.comps | |
| for i = 1, #ac + #bc do | |
| c[i] = 0 | |
| end | |
| for i = 1, #ac do | |
| for j = 1, #bc do | |
| c[i+j-1] = c[i+j-1] + ac[i] * bc[j] | |
| end | |
| -- keep the zeroes | |
| normalize(bi, true) | |
| end | |
| normalize(bi) | |
| if bi ~= bigint(0) then | |
| bi.sign = a.sign * b.sign | |
| end | |
| return bi | |
| end | |
| local function kmul(a, b) | |
| local ac, bc = a.comps, b.comps | |
| local an, bn = #a.comps, #b.comps | |
| local bi, bj, bk, bl = alloc(), alloc(), alloc(), alloc() | |
| local ic, jc, kc, lc = bi.comps, bj.comps, bk.comps, bl.comps | |
| local n = fl((math.max(an, bn) + 1) / 2) | |
| for i = 1, n do | |
| ic[i] = (i + n <= an) and ac[i+n] or 0 | |
| jc[i] = (i <= an) and ac[i] or 0 | |
| kc[i] = (i + n <= bn) and bc[i+n] or 0 | |
| lc[i] = (i <= bn) and bc[i] or 0 | |
| end | |
| normalize(bi) | |
| normalize(bj) | |
| normalize(bk) | |
| normalize(bl) | |
| local ik = bi * bk | |
| local jl = bj * bl | |
| local mid = (bi + bj) * (bk + bl) - ik - jl | |
| local mc = mid.comps | |
| local ikc = ik.comps | |
| local jlc = jl.comps | |
| for i = 1, #ikc + n*2 do -- fill it up | |
| jlc[i] = jlc[i] or 0 | |
| end | |
| for i = 1, #mc do | |
| jlc[i+n] = jlc[i+n] + mc[i] | |
| end | |
| for i = 1, #ikc do | |
| jlc[i+n*2] = jlc[i+n*2] + ikc[i] | |
| end | |
| jl.sign = a.sign * b.sign | |
| normalize(jl) | |
| return jl | |
| end | |
| local kthresh = 12 | |
| local function mul(a, b) | |
| if type(a) == "number" then | |
| return mulint(b, a) | |
| elseif type(b) == "number" then | |
| return mulint(a, b) | |
| end | |
| if #a.comps < kthresh or #b.comps < kthresh then | |
| return multiply(a, b) | |
| end | |
| return kmul(a, b) | |
| end | |
| local function divint(numer, denom) | |
| local bi = clone(numer) | |
| if denom < 0 then | |
| denom = -denom | |
| bi.sign = -bi.sign | |
| end | |
| local r = 0 | |
| local c = bi.comps | |
| for i = #c, 1, -1 do | |
| r = r * radix + c[i] | |
| c[i] = fl(r / denom) | |
| r = cmod(r, denom) | |
| end | |
| normalize(bi) | |
| return bi | |
| end | |
| local function multi_divide(numer, denom) | |
| local n = #denom.comps | |
| local approx = divint(numer, denom.comps[n]) | |
| for i = n, #approx.comps do | |
| approx.comps[i - n + 1] = approx.comps[i] | |
| end | |
| for i = #approx.comps, #approx.comps - n + 2, -1 do | |
| approx.comps[i] = nil | |
| end | |
| local rem = approx * denom - numer | |
| if rem < denom then | |
| quotient = approx | |
| else | |
| quotient = approx - multi_divide(rem, denom) | |
| end | |
| return quotient | |
| end | |
| local function multi_divide_wrap(numer, denom) | |
| -- we use a successive approximation method, but it doesn't work | |
| -- if the high order component is too small. adjust if needed. | |
| if denom.comps[#denom.comps] < radix_sqrt then | |
| numer = mulint(numer, radix_sqrt) | |
| denom = mulint(denom, radix_sqrt) | |
| end | |
| return multi_divide(numer, denom) | |
| end | |
| local function div(numer, denom) | |
| if type(denom) == "number" then | |
| if denom == 0 then | |
| error("divide by 0", 2) | |
| end | |
| return divint(numer, denom) | |
| elseif type(numer) == "number" then | |
| numer = bigint(numer) | |
| end | |
| -- check signs and trivial cases | |
| local sign = 1 | |
| local cmp = compare(denom, bigint(0)) | |
| if cmp == 0 then | |
| error("divide by 0", 2) | |
| elseif cmp == -1 then | |
| sign = -sign | |
| denom = negate(denom) | |
| end | |
| cmp = compare(numer, bigint(0)) | |
| if cmp == 0 then | |
| return bigint(0) | |
| elseif cmp == -1 then | |
| sign = -sign | |
| numer = negate(numer) | |
| end | |
| cmp = compare(numer, denom) | |
| if cmp == -1 then | |
| return bigint(0) | |
| elseif cmp == 0 then | |
| return bigint(sign) | |
| end | |
| local bi | |
| -- if small enough, do it the easy way | |
| if #denom.comps == 1 then | |
| bi = divint(numer, denom.comps[1]) | |
| else | |
| bi = multi_divide_wrap(numer, denom) | |
| end | |
| if sign == -1 then | |
| bi = negate(bi) | |
| end | |
| return bi | |
| end | |
| local function intrem(bi, m) | |
| if m < 0 then | |
| m = -m | |
| end | |
| local rad_r = 1 | |
| local r = 0 | |
| local bc = bi.comps | |
| for i = 1, #bc do | |
| local v = bc[i] | |
| r = cmod(r + v * rad_r, m) | |
| rad_r = cmod(rad_r * radix, m) | |
| end | |
| if bi.sign < 1 then | |
| r = -r | |
| end | |
| return r | |
| end | |
| local function intmod(bi, m) | |
| local r = intrem(bi, m) | |
| if r < 0 then | |
| r = r + m | |
| end | |
| return r | |
| end | |
| local function rem(bi, m) | |
| if type(m) == "number" then | |
| return bigint(intrem(bi, m)) | |
| elseif type(bi) == "number" then | |
| bi = bigint(bi) | |
| end | |
| return bi - ((bi / m) * m) | |
| end | |
| local function mod(a, m) | |
| local bi = rem(a, m) | |
| if bi.sign == -1 then | |
| bi = bi + m | |
| end | |
| return bi | |
| end | |
| local printscale = 10000000 | |
| local printscalefmt = string.format("%%.%dd", math.log10(printscale)) | |
| local function makestr(bi, s) | |
| if bi >= bigint(printscale) then | |
| makestr(divint(bi, printscale), s) | |
| end | |
| table.insert(s, string.format(printscalefmt, intmod(bi, printscale))) | |
| end | |
| local function biginttostring(bi) | |
| local s = {} | |
| if bi < bigint(0) then | |
| bi = negate(bi) | |
| table.insert(s, "-") | |
| end | |
| makestr(bi, s) | |
| s = table.concat(s):gsub("^0*", "") | |
| if s == "" then s = "0" end | |
| return s | |
| end | |
| local function biginttonumber(bi) | |
| return tonumber(biginttostring(bi)) | |
| end | |
| bigintmt = { | |
| __add = add, | |
| __sub = sub, | |
| __mul = mul, | |
| __div = div, | |
| __mod = mod, | |
| __unm = negate, | |
| __eq = eq, | |
| __lt = lt, | |
| __le = le, | |
| __tostring = biginttostring, | |
| } | |
| local cache = {} | |
| local ncache = 0 | |
| function bigint(n) | |
| if cache[n] then | |
| return cache[n] | |
| end | |
| local bi | |
| if type(n) == "string" then | |
| local digits = { n:byte(1, -1) } | |
| for i = 1, #digits do | |
| digits[i] = string.char(digits[i]) | |
| end | |
| local start = 1 | |
| local sign = 1 | |
| if digits[i] == '-' then | |
| sign = -1 | |
| start = 2 | |
| end | |
| bi = bigint(0) | |
| for i = start, #digits do | |
| bi = addint(mulint(bi, 10), tonumber(digits[i])) | |
| end | |
| bi = mulint(bi, sign) | |
| else | |
| bi = alloc() | |
| bi.comps[1] = n | |
| normalize(bi) | |
| end | |
| if ncache > 100 then | |
| cache = {} | |
| ncache = 0 | |
| end | |
| cache[n] = bi | |
| ncache = ncache + 1 | |
| return bi | |
| end | |
| -- | |
| -- Start of my code | |
| -- | |
| local powersTwo = { | |
| bigint("2"), | |
| bigint("4"), | |
| bigint("8"), | |
| bigint("16"), | |
| bigint("32"), | |
| bigint("64"), | |
| bigint("128"), | |
| bigint("256"), | |
| bigint("512"), | |
| bigint("1024"), | |
| bigint("2048"), | |
| bigint("4096"), | |
| bigint("8192"), | |
| bigint("16384"), | |
| bigint("32768"), | |
| bigint("65536"), | |
| bigint("131072"), | |
| bigint("262144"), | |
| bigint("524288"), | |
| bigint("1048576"), | |
| bigint("2097152"), | |
| bigint("4194304"), | |
| bigint("8388608"), | |
| bigint("16777216"), | |
| bigint("33554432"), | |
| bigint("67108864"), | |
| bigint("134217728"), | |
| bigint("268435456"), | |
| bigint("536870912"), | |
| bigint("1073741824"), | |
| bigint("2147483648"), | |
| bigint("4294967296"), | |
| bigint("8589934592"), | |
| bigint("17179869184"), | |
| bigint("34359738368"), | |
| bigint("68719476736"), | |
| bigint("137438953472"), | |
| bigint("274877906944"), | |
| bigint("549755813888"), | |
| bigint("1099511627776"), | |
| bigint("2199023255552"), | |
| bigint("4398046511104"), | |
| bigint("8796093022208"), | |
| bigint("17592186044416"), | |
| bigint("35184372088832"), | |
| bigint("70368744177664"), | |
| bigint("140737488355328"), | |
| bigint("281474976710656"), | |
| bigint("562949953421312"), | |
| bigint("1125899906842624"), | |
| bigint("2251799813685248"), | |
| bigint("4503599627370496"), | |
| bigint("9007199254740992"), | |
| bigint("18014398509481984"), | |
| bigint("36028797018963968"), | |
| bigint("72057594037927936"), | |
| bigint("144115188075855872"), | |
| bigint("288230376151711744"), | |
| bigint("576460752303423488"), | |
| bigint("1152921504606846976"), | |
| bigint("2305843009213693952"), | |
| bigint("4611686018427387904"), | |
| bigint("9223372036854775808"), | |
| bigint("18446744073709551616"), | |
| bigint("36893488147419103232"), | |
| bigint("73786976294838206464"), | |
| bigint("147573952589676412928"), | |
| bigint("295147905179352825856"), | |
| bigint("590295810358705651712"), | |
| bigint("1180591620717411303424"), | |
| bigint("2361183241434822606848"), | |
| bigint("4722366482869645213696"), | |
| bigint("9444732965739290427392"), | |
| bigint("18889465931478580854784"), | |
| bigint("37778931862957161709568"), | |
| bigint("75557863725914323419136"), | |
| bigint("151115727451828646838272"), | |
| bigint("302231454903657293676544"), | |
| bigint("604462909807314587353088"), | |
| bigint("1208925819614629174706176"), | |
| bigint("2417851639229258349412352"), | |
| bigint("4835703278458516698824704"), | |
| bigint("9671406556917033397649408"), | |
| bigint("19342813113834066795298816"), | |
| bigint("38685626227668133590597632"), | |
| bigint("77371252455336267181195264"), | |
| bigint("154742504910672534362390528"), | |
| bigint("309485009821345068724781056"), | |
| bigint("618970019642690137449562112"), | |
| bigint("1237940039285380274899124224"), | |
| bigint("2475880078570760549798248448"), | |
| bigint("4951760157141521099596496896"), | |
| bigint("9903520314283042199192993792"), | |
| bigint("19807040628566084398385987584"), | |
| bigint("39614081257132168796771975168"), | |
| bigint("79228162514264337593543950336"), | |
| bigint("158456325028528675187087900672"), | |
| bigint("316912650057057350374175801344"), | |
| bigint("633825300114114700748351602688"), | |
| bigint("1267650600228229401496703205376"), | |
| bigint("2535301200456458802993406410752"), | |
| bigint("5070602400912917605986812821504"), | |
| bigint("10141204801825835211973625643008"), | |
| bigint("20282409603651670423947251286016"), | |
| bigint("40564819207303340847894502572032"), | |
| bigint("81129638414606681695789005144064"), | |
| bigint("162259276829213363391578010288128"), | |
| bigint("324518553658426726783156020576256"), | |
| bigint("649037107316853453566312041152512"), | |
| bigint("1298074214633706907132624082305024"), | |
| bigint("2596148429267413814265248164610048"), | |
| bigint("5192296858534827628530496329220096"), | |
| bigint("10384593717069655257060992658440192"), | |
| bigint("20769187434139310514121985316880384"), | |
| bigint("41538374868278621028243970633760768"), | |
| bigint("83076749736557242056487941267521536"), | |
| bigint("166153499473114484112975882535043072"), | |
| bigint("332306998946228968225951765070086144"), | |
| bigint("664613997892457936451903530140172288"), | |
| bigint("1329227995784915872903807060280344576"), | |
| bigint("2658455991569831745807614120560689152"), | |
| bigint("5316911983139663491615228241121378304"), | |
| bigint("10633823966279326983230456482242756608"), | |
| bigint("21267647932558653966460912964485513216"), | |
| bigint("42535295865117307932921825928971026432"), | |
| bigint("85070591730234615865843651857942052864"), | |
| bigint("170141183460469231731687303715884105728"), | |
| bigint("340282366920938463463374607431768211456"), | |
| bigint("680564733841876926926749214863536422912"), | |
| bigint("1361129467683753853853498429727072845824"), | |
| bigint("2722258935367507707706996859454145691648"), | |
| bigint("5444517870735015415413993718908291383296"), | |
| bigint("10889035741470030830827987437816582766592"), | |
| bigint("21778071482940061661655974875633165533184"), | |
| bigint("43556142965880123323311949751266331066368"), | |
| bigint("87112285931760246646623899502532662132736"), | |
| bigint("174224571863520493293247799005065324265472"), | |
| bigint("348449143727040986586495598010130648530944"), | |
| bigint("696898287454081973172991196020261297061888"), | |
| bigint("1393796574908163946345982392040522594123776"), | |
| bigint("2787593149816327892691964784081045188247552"), | |
| bigint("5575186299632655785383929568162090376495104"), | |
| bigint("11150372599265311570767859136324180752990208"), | |
| bigint("22300745198530623141535718272648361505980416"), | |
| bigint("44601490397061246283071436545296723011960832"), | |
| bigint("89202980794122492566142873090593446023921664"), | |
| bigint("178405961588244985132285746181186892047843328"), | |
| bigint("356811923176489970264571492362373784095686656"), | |
| bigint("713623846352979940529142984724747568191373312"), | |
| bigint("1427247692705959881058285969449495136382746624"), | |
| bigint("2854495385411919762116571938898990272765493248"), | |
| bigint("5708990770823839524233143877797980545530986496"), | |
| bigint("11417981541647679048466287755595961091061972992"), | |
| bigint("22835963083295358096932575511191922182123945984"), | |
| bigint("45671926166590716193865151022383844364247891968"), | |
| bigint("91343852333181432387730302044767688728495783936"), | |
| bigint("182687704666362864775460604089535377456991567872"), | |
| bigint("365375409332725729550921208179070754913983135744"), | |
| bigint("730750818665451459101842416358141509827966271488"), | |
| bigint("1461501637330902918203684832716283019655932542976"), | |
| bigint("2923003274661805836407369665432566039311865085952"), | |
| bigint("5846006549323611672814739330865132078623730171904"), | |
| bigint("11692013098647223345629478661730264157247460343808"), | |
| bigint("23384026197294446691258957323460528314494920687616"), | |
| bigint("46768052394588893382517914646921056628989841375232"), | |
| bigint("93536104789177786765035829293842113257979682750464"), | |
| bigint("187072209578355573530071658587684226515959365500928"), | |
| bigint("374144419156711147060143317175368453031918731001856"), | |
| bigint("748288838313422294120286634350736906063837462003712"), | |
| bigint("1496577676626844588240573268701473812127674924007424"), | |
| bigint("2993155353253689176481146537402947624255349848014848"), | |
| bigint("5986310706507378352962293074805895248510699696029696"), | |
| bigint("11972621413014756705924586149611790497021399392059392"), | |
| bigint("23945242826029513411849172299223580994042798784118784"), | |
| bigint("47890485652059026823698344598447161988085597568237568"), | |
| bigint("95780971304118053647396689196894323976171195136475136"), | |
| bigint("191561942608236107294793378393788647952342390272950272"), | |
| bigint("383123885216472214589586756787577295904684780545900544"), | |
| bigint("766247770432944429179173513575154591809369561091801088"), | |
| bigint("1532495540865888858358347027150309183618739122183602176"), | |
| bigint("3064991081731777716716694054300618367237478244367204352"), | |
| bigint("6129982163463555433433388108601236734474956488734408704"), | |
| bigint("12259964326927110866866776217202473468949912977468817408"), | |
| bigint("24519928653854221733733552434404946937899825954937634816"), | |
| bigint("49039857307708443467467104868809893875799651909875269632"), | |
| bigint("98079714615416886934934209737619787751599303819750539264"), | |
| bigint("196159429230833773869868419475239575503198607639501078528"), | |
| bigint("392318858461667547739736838950479151006397215279002157056"), | |
| bigint("784637716923335095479473677900958302012794430558004314112"), | |
| bigint("1569275433846670190958947355801916604025588861116008628224"), | |
| bigint("3138550867693340381917894711603833208051177722232017256448"), | |
| bigint("6277101735386680763835789423207666416102355444464034512896"), | |
| bigint("12554203470773361527671578846415332832204710888928069025792"), | |
| bigint("25108406941546723055343157692830665664409421777856138051584"), | |
| bigint("50216813883093446110686315385661331328818843555712276103168"), | |
| bigint("100433627766186892221372630771322662657637687111424552206336"), | |
| bigint("200867255532373784442745261542645325315275374222849104412672"), | |
| bigint("401734511064747568885490523085290650630550748445698208825344"), | |
| bigint("803469022129495137770981046170581301261101496891396417650688"), | |
| bigint("1606938044258990275541962092341162602522202993782792835301376"), | |
| bigint("3213876088517980551083924184682325205044405987565585670602752"), | |
| bigint("6427752177035961102167848369364650410088811975131171341205504"), | |
| bigint("12855504354071922204335696738729300820177623950262342682411008"), | |
| bigint("25711008708143844408671393477458601640355247900524685364822016"), | |
| bigint("51422017416287688817342786954917203280710495801049370729644032"), | |
| bigint("102844034832575377634685573909834406561420991602098741459288064"), | |
| bigint("205688069665150755269371147819668813122841983204197482918576128"), | |
| bigint("411376139330301510538742295639337626245683966408394965837152256"), | |
| bigint("822752278660603021077484591278675252491367932816789931674304512"), | |
| bigint("1645504557321206042154969182557350504982735865633579863348609024"), | |
| bigint("3291009114642412084309938365114701009965471731267159726697218048"), | |
| bigint("6582018229284824168619876730229402019930943462534319453394436096"), | |
| bigint("13164036458569648337239753460458804039861886925068638906788872192"), | |
| bigint("26328072917139296674479506920917608079723773850137277813577744384"), | |
| bigint("52656145834278593348959013841835216159447547700274555627155488768"), | |
| bigint("105312291668557186697918027683670432318895095400549111254310977536"), | |
| bigint("210624583337114373395836055367340864637790190801098222508621955072"), | |
| bigint("421249166674228746791672110734681729275580381602196445017243910144"), | |
| bigint("842498333348457493583344221469363458551160763204392890034487820288"), | |
| bigint("1684996666696914987166688442938726917102321526408785780068975640576"), | |
| bigint("3369993333393829974333376885877453834204643052817571560137951281152"), | |
| bigint("6739986666787659948666753771754907668409286105635143120275902562304"), | |
| bigint("13479973333575319897333507543509815336818572211270286240551805124608"), | |
| bigint("26959946667150639794667015087019630673637144422540572481103610249216"), | |
| bigint("53919893334301279589334030174039261347274288845081144962207220498432"), | |
| bigint("107839786668602559178668060348078522694548577690162289924414440996864"), | |
| bigint("215679573337205118357336120696157045389097155380324579848828881993728"), | |
| bigint("431359146674410236714672241392314090778194310760649159697657763987456"), | |
| bigint("862718293348820473429344482784628181556388621521298319395315527974912"), | |
| bigint("1725436586697640946858688965569256363112777243042596638790631055949824"), | |
| bigint("3450873173395281893717377931138512726225554486085193277581262111899648"), | |
| bigint("6901746346790563787434755862277025452451108972170386555162524223799296"), | |
| bigint("13803492693581127574869511724554050904902217944340773110325048447598592"), | |
| bigint("27606985387162255149739023449108101809804435888681546220650096895197184"), | |
| bigint("55213970774324510299478046898216203619608871777363092441300193790394368"), | |
| bigint("110427941548649020598956093796432407239217743554726184882600387580788736"), | |
| bigint("220855883097298041197912187592864814478435487109452369765200775161577472"), | |
| bigint("441711766194596082395824375185729628956870974218904739530401550323154944"), | |
| bigint("883423532389192164791648750371459257913741948437809479060803100646309888"), | |
| bigint("1766847064778384329583297500742918515827483896875618958121606201292619776"), | |
| bigint("3533694129556768659166595001485837031654967793751237916243212402585239552"), | |
| bigint("7067388259113537318333190002971674063309935587502475832486424805170479104"), | |
| bigint("14134776518227074636666380005943348126619871175004951664972849610340958208"), | |
| bigint("28269553036454149273332760011886696253239742350009903329945699220681916416"), | |
| bigint("56539106072908298546665520023773392506479484700019806659891398441363832832"), | |
| bigint("113078212145816597093331040047546785012958969400039613319782796882727665664"), | |
| bigint("226156424291633194186662080095093570025917938800079226639565593765455331328"), | |
| bigint("452312848583266388373324160190187140051835877600158453279131187530910662656"), | |
| bigint("904625697166532776746648320380374280103671755200316906558262375061821325312"), | |
| bigint("1809251394333065553493296640760748560207343510400633813116524750123642650624"), | |
| bigint("3618502788666131106986593281521497120414687020801267626233049500247285301248"), | |
| bigint("7237005577332262213973186563042994240829374041602535252466099000494570602496"), | |
| bigint("14474011154664524427946373126085988481658748083205070504932198000989141204992"), | |
| bigint("28948022309329048855892746252171976963317496166410141009864396001978282409984"), | |
| bigint("57896044618658097711785492504343953926634992332820282019728792003956564819968"), | |
| bigint("115792089237316195423570985008687907853269984665640564039457584007913129639936"), | |
| } | |
| powersTwo[0] = bigint("1") | |
| local bigZero = bigint(0) | |
| local bigOne = bigint(1) | |
| local function numberToBytes(num, bits, byteSize) | |
| if bits > #powersTwo then | |
| error("Too many bits. Must be <= " .. #powersTwo .. ".") | |
| end | |
| num = bigint(num) | |
| local resultBits = {} | |
| resultBits[1] = {} | |
| for i = bits - 1, 0, -1 do | |
| local expVal = powersTwo[i] | |
| local resultant = num - expVal | |
| if expVal <= resultant then | |
| -- Invalid data! | |
| return nil | |
| end | |
| if resultant < bigZero then | |
| -- A zero bit | |
| if #(resultBits[#resultBits]) >= byteSize then | |
| table.insert(resultBits, {0}) | |
| else | |
| table.insert(resultBits[#resultBits], 0) | |
| end | |
| else | |
| -- A one bit | |
| num = resultant | |
| if #(resultBits[#resultBits]) >= byteSize then | |
| table.insert(resultBits, {1}) | |
| else | |
| table.insert(resultBits[#resultBits], 1) | |
| end | |
| end | |
| if num == bigint(0) then | |
| break | |
| end | |
| end | |
| local results = {} | |
| for _, binarySeq in pairs(resultBits) do | |
| local thisResult = 0 | |
| for k, bin in pairs(binarySeq) do | |
| if bin == 1 then | |
| thisResult = thisResult + 2^(byteSize - k) | |
| end | |
| end | |
| table.insert(results, thisResult) | |
| end | |
| return results | |
| end | |
| local function bytesToNumber(bytes, bits, byteSize) | |
| if bits > #powersTwo then | |
| error("Too many bits. Must be <= " .. #powersTwo .. ".") | |
| end | |
| if #bytes > bits/byteSize then | |
| error("Too many bytes to store into the number of bits available. Must be <= " .. | |
| bits/byteSize .. ".") | |
| end | |
| local binary = {} | |
| for _, byte in pairs(bytes) do | |
| for i = byteSize - 1, 0, -1 do | |
| if byte - (2 ^ i) < 0 then | |
| table.insert(binary, 0) | |
| else | |
| table.insert(binary, 1) | |
| byte = byte - (2 ^ i) | |
| end | |
| end | |
| end | |
| local num = bigint(0) | |
| for i = 1, #binary do | |
| if binary[i] == 1 then | |
| num = num + powersTwo[bits - i] | |
| end | |
| end | |
| return tostring(num) | |
| end | |
| local function encodeBigNumbers(numbers) | |
| for k, v in pairs(numbers) do | |
| numbers[k] = tostring(v) | |
| end | |
| return numbers | |
| end | |
| local function stringToBytes(str) | |
| local result = {} | |
| for i = 1, #str do | |
| table.insert(result, string.byte(str, i)) | |
| end | |
| return result | |
| end | |
| local function bytesToString(bytes) | |
| local str = "" | |
| for _, v in pairs(bytes) do | |
| str = str .. string.char(v) | |
| end | |
| return str | |
| end | |
| local function modexp(base, exponent, modulus) | |
| local r = 1 | |
| while true do | |
| if exponent % 2 == bigOne then | |
| r = r * base % modulus | |
| end | |
| exponent = exponent / 2 | |
| if exponent == bigZero then | |
| break | |
| end | |
| base = base * base % modulus | |
| end | |
| return r | |
| end | |
| local function crypt(key, number) | |
| local exp | |
| if key.public then | |
| exp = bigint(key.public) | |
| else | |
| exp = bigint(key.private) | |
| end | |
| return tostring(modexp(bigint(number), exp, bigint(key.shared))) | |
| end | |
| -- | |
| -- END OF LIBRARY | |
| -- | |
| -- DEMO ENCRYPTION AND DECRYPTION | |
| -- | |
| local f = io.open("/public.key", "r") | |
| local publicKey = textutils.unserialize(f:read("*a")) | |
| f:close() | |
| f = io.open("/private.key", "r") | |
| local privateKey = textutils.unserialize(f:read("*a")) | |
| f:close() | |
| local byteSize = 8 | |
| local bits = 256 | |
| local msg = "hello" -- Maximum message size is bits / byteSize | |
| local startTime = os.clock() | |
| -- Encrypting | |
| local res = bytesToNumber(stringToBytes(msg), bits, byteSize) | |
| local encrypted = crypt(publicKey, res) | |
| print("Took " .. os.clock() - startTime .. " seconds to encrypt.") | |
| -- You may transmit "encrypted" in public. "encrypted" is a string. | |
| sleep(0.1) | |
| startTime = os.clock() | |
| -- Decrypting | |
| local decrypted = crypt(privateKey, encrypted) | |
| local decryptedBytes = numberToBytes(decrypted, bits, byteSize) | |
| print("Took " .. os.clock() - startTime .. " seconds to decrypt.") | |
| print(bytesToString(decryptedBytes)) |
Yup doesn't work if not using the textutils or better yet the textutils.unserialize() function.
Unfortunately GitHub doesn't notify you when people comment on gists!
Oh sorry, I was using ComputerCraft which has a built in textutils.serialize/unserialize. You can/should replace this with a JSON encoder/decoder. Alternatively here's the textutils library: https://github.com/SquidDev-CC/CC-Tweaked/blob/master/src/main/resources/assets/computercraft/lua/rom/apis/textutils.lua. You will also need to generate keys using this script: https://pastebin.com/udGZapmD.
Since I wrote a RSA implementation, a EC-DHE implementation was made which is not only faster, but magnitudes more secure (this implementation generates keys which are bruteforcable within 10 minutes on a modern computer), which you can find here: http://www.computercraft.info/forums2/index.php?/topic/29803-elliptic-curve-cryptography/
It unfortunately uses additional bit manipulation libraries that aren't available in standard Lua, (among possible other libraries) the API specification can be found here: https://computercraft.info/wiki/Bit_(API). If you're missing a library, search for it on Google with "ComputerCraft" or look inside the CC-Tweaked repository I linked earlier.
Where can i found textutils.unserialize() etc. ?