Skip to content

Instantly share code, notes, and snippets.

@1lann
Last active November 4, 2024 18:01
Show Gist options
  • Save 1lann/6604c8d3d8e5fdad0832 to your computer and use it in GitHub Desktop.
Save 1lann/6604c8d3d8e5fdad0832 to your computer and use it in GitHub Desktop.
RSA encryption and decryption library in pure Lua for ComputerCraft
--
-- 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))
@voidsharp
Copy link

Where can i found textutils.unserialize() etc. ?

@mmaslati
Copy link

Yup doesn't work if not using the textutils or better yet the textutils.unserialize() function.

@1lann
Copy link
Author

1lann commented Apr 26, 2020

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.

@gameplays12303
Copy link

this dose not work do not bother

@Viper-0501
Copy link

this dose not work do not bother

it works in computercraft, which is what it is intended for.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment