Skip to content

Instantly share code, notes, and snippets.

@1lann
Last active April 1, 2024 02:52
Show Gist options
  • Star 30 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • 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))
@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

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