-
-
Save 1lann/6604c8d3d8e5fdad0832 to your computer and use it in GitHub Desktop.
-- | |
-- 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)) |
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.
this dose not work do not bother
this dose not work do not bother
it works in computercraft, which is what it is intended for.
Yup doesn't work if not using the textutils or better yet the textutils.unserialize() function.