Advertisement
1lann

crypto-utilities

Nov 28th, 2015
165
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 17.78 KB | None | 0 0
  1. local function fl(x)
  2.         if x < 0 then
  3.                 return math.ceil(x) + 0 -- make -0 go away
  4.         else
  5.                 return math.floor(x)
  6.         end
  7. end
  8.  
  9. local function cmod(a, b)
  10.         local x = a % b
  11.         if a < 0 and x > 0 then
  12.                 x = x - b
  13.         end
  14.         return x
  15. end
  16.  
  17.  
  18. local radix = 2^24 -- maybe up to 2^26 is safe?
  19. local radix_sqrt = fl(math.sqrt(radix))
  20.  
  21. local bigintmt -- forward decl
  22.  
  23. local function alloc()
  24.         local bi = {}
  25.         setmetatable(bi, bigintmt)
  26.         bi.comps = {}
  27.         bi.sign = 1;
  28.         return bi
  29. end
  30.  
  31. local function clone(a)
  32.         local bi = alloc()
  33.         bi.sign = a.sign
  34.         local c = bi.comps
  35.         local ac = a.comps
  36.         for i = 1, #ac do
  37.                 c[i] = ac[i]
  38.         end
  39.         return bi
  40. end
  41.  
  42. local function normalize(bi, notrunc)
  43.         local c = bi.comps
  44.         local v
  45.         -- borrow for negative components
  46.         for i = 1, #c - 1 do
  47.                 v = c[i]
  48.                 if v < 0 then
  49.                         c[i+1] = c[i+1] + fl(v / radix) - 1
  50.                         v = cmod(v, radix)
  51.                         if v ~= 0 then
  52.                                 c[i] = v + radix
  53.                         else
  54.                                 c[i] = v
  55.                                 c[i+1] = c[i+1] + 1
  56.                         end
  57.                 end
  58.         end
  59.         -- is top component negative?
  60.         if c[#c] < 0 then
  61.                 -- switch the sign and fix components
  62.                 bi.sign = -bi.sign
  63.                 for i = 1, #c - 1 do
  64.                         v = c[i]
  65.                         c[i] = radix - v
  66.                         c[i+1] = c[i+1] + 1
  67.                 end
  68.                 c[#c] = -c[#c]
  69.         end
  70.         -- carry for components larger than radix
  71.         for i = 1, #c do
  72.                 v = c[i]
  73.                 if v > radix then
  74.                         c[i+1] = (c[i+1] or 0) + fl(v / radix)
  75.                         c[i] = cmod(v, radix)
  76.                 end
  77.         end
  78.         -- trim off leading zeros
  79.         if not notrunc then
  80.                 for i = #c, 2, -1 do
  81.                         if c[i] == 0 then
  82.                                 c[i] = nil
  83.                         else
  84.                                 break
  85.                         end
  86.                 end
  87.         end
  88.         -- check for -0
  89.         if #c == 1 and c[1] == 0 and bi.sign == -1 then
  90.                 bi.sign = 1
  91.         end
  92. end
  93.  
  94. local function negate(a)
  95.         local bi = clone(a)
  96.         bi.sign = -bi.sign
  97.         return bi
  98. end
  99.  
  100. local function compare(a, b)
  101.         local ac, bc = a.comps, b.comps
  102.         local as, bs = a.sign, b.sign
  103.         if ac == bc then
  104.                 return 0
  105.         elseif as > bs then
  106.                 return 1
  107.         elseif as < bs then
  108.                 return -1
  109.         elseif #ac > #bc then
  110.                 return as
  111.         elseif #ac < #bc then
  112.                 return -as
  113.         end
  114.         for i = #ac, 1, -1 do
  115.                 if ac[i] > bc[i] then
  116.                         return as
  117.                 elseif ac[i] < bc[i] then
  118.                         return -as
  119.                 end
  120.         end
  121.         return 0
  122. end
  123.  
  124. local function lt(a, b)
  125.         return compare(a, b) < 0
  126. end
  127.  
  128. local function eq(a, b)
  129.         return compare(a, b) == 0
  130. end
  131.  
  132. local function le(a, b)
  133.         return compare(a, b) <= 0
  134. end
  135.  
  136. local function addint(a, n)
  137.         local bi = clone(a)
  138.         if bi.sign == 1 then
  139.                 bi.comps[1] = bi.comps[1] + n
  140.         else
  141.                 bi.comps[1] = bi.comps[1] - n
  142.         end
  143.         normalize(bi)
  144.         return bi
  145. end
  146.  
  147. local function add(a, b)
  148.         if type(a) == "number" then
  149.                 return addint(b, a)
  150.         elseif type(b) == "number" then
  151.                 return addint(a, b)
  152.         end
  153.         local bi = clone(a)
  154.         local sign = bi.sign == b.sign
  155.         local c = bi.comps
  156.         for i = #c + 1, #b.comps do
  157.                 c[i] = 0
  158.         end
  159.         local bc = b.comps
  160.         for i = 1, #bc do
  161.                 local v = bc[i]
  162.                 if sign then
  163.                         c[i] = c[i] + v
  164.                 else
  165.                         c[i] = c[i] - v
  166.                 end
  167.         end
  168.         normalize(bi)
  169.         return bi
  170. end
  171.  
  172. local function sub(a, b)
  173.         if type(b) == "number" then
  174.                 return addint(a, -b)
  175.         elseif type(a) == "number" then
  176.                 a = bigint(a)
  177.         end
  178.         return add(a, negate(b))
  179. end
  180.  
  181. local function mulint(a, b)
  182.         local bi = clone(a)
  183.         if b < 0 then
  184.                 b = -b
  185.                 bi.sign = -bi.sign
  186.         end
  187.         local bc = bi.comps
  188.         for i = 1, #bc do
  189.                 bc[i] = bc[i] * b
  190.         end
  191.         normalize(bi)
  192.         return bi
  193. end
  194.  
  195. local function multiply(a, b)
  196.         local bi = alloc()
  197.         local c = bi.comps
  198.         local ac, bc = a.comps, b.comps
  199.         for i = 1, #ac + #bc do
  200.                 c[i] = 0
  201.         end
  202.         for i = 1, #ac do
  203.                 for j = 1, #bc do
  204.                         c[i+j-1] = c[i+j-1] + ac[i] * bc[j]
  205.                 end
  206.                 -- keep the zeroes
  207.                 normalize(bi, true)
  208.         end
  209.         normalize(bi)
  210.         if bi ~= bigint(0) then
  211.                 bi.sign = a.sign * b.sign
  212.         end
  213.         return bi
  214. end
  215.  
  216. local function kmul(a, b)
  217.         local ac, bc = a.comps, b.comps
  218.         local an, bn = #a.comps, #b.comps
  219.         local bi, bj, bk, bl = alloc(), alloc(), alloc(), alloc()
  220.         local ic, jc, kc, lc = bi.comps, bj.comps, bk.comps, bl.comps
  221.  
  222.         local n = fl((math.max(an, bn) + 1) / 2)
  223.         for i = 1, n do
  224.                 ic[i] = (i + n <= an) and ac[i+n] or 0
  225.                 jc[i] = (i <= an) and ac[i] or 0
  226.                 kc[i] = (i + n <= bn) and bc[i+n] or 0
  227.                 lc[i] = (i <= bn) and bc[i] or 0
  228.         end
  229.         normalize(bi)
  230.         normalize(bj)
  231.         normalize(bk)
  232.         normalize(bl)
  233.         local ik = bi * bk
  234.         local jl = bj * bl
  235.         local mid = (bi + bj) * (bk + bl) - ik - jl
  236.         local mc = mid.comps
  237.         local ikc = ik.comps
  238.         local jlc = jl.comps
  239.         for i = 1, #ikc + n*2 do -- fill it up
  240.                 jlc[i] = jlc[i] or 0
  241.         end
  242.         for i = 1, #mc do
  243.                 jlc[i+n] = jlc[i+n] + mc[i]
  244.         end
  245.         for i = 1, #ikc do
  246.                 jlc[i+n*2] = jlc[i+n*2] + ikc[i]
  247.         end
  248.         jl.sign = a.sign * b.sign
  249.         normalize(jl)
  250.         return jl
  251. end
  252.  
  253. local kthresh = 12
  254.  
  255. local function mul(a, b)
  256.         if type(a) == "number" then
  257.                 return mulint(b, a)
  258.         elseif type(b) == "number" then
  259.                 return mulint(a, b)
  260.         end
  261.         if #a.comps < kthresh or #b.comps < kthresh then
  262.                 return multiply(a, b)
  263.         end
  264.         return kmul(a, b)
  265. end
  266.  
  267. local function divint(numer, denom)
  268.         local bi = clone(numer)
  269.         if denom < 0 then
  270.                 denom = -denom
  271.                 bi.sign = -bi.sign
  272.         end
  273.         local r = 0
  274.         local c = bi.comps
  275.         for i = #c, 1, -1 do
  276.                 r = r * radix + c[i]
  277.                 c[i] = fl(r / denom)
  278.                 r = cmod(r, denom)
  279.         end
  280.         normalize(bi)
  281.         return bi
  282. end
  283.  
  284. local function multi_divide(numer, denom)
  285.         local n = #denom.comps
  286.         local approx = divint(numer, denom.comps[n])
  287.         for i = n, #approx.comps do
  288.                 approx.comps[i - n + 1] = approx.comps[i]
  289.         end
  290.         for i = #approx.comps, #approx.comps - n + 2, -1 do
  291.                 approx.comps[i] = nil
  292.         end
  293.         local rem = approx * denom - numer
  294.         if rem < denom then
  295.                 quotient = approx
  296.         else
  297.                 quotient = approx - multi_divide(rem, denom)
  298.         end
  299.         return quotient
  300. end
  301.  
  302. local function multi_divide_wrap(numer, denom)
  303.         -- we use a successive approximation method, but it doesn't work
  304.         -- if the high order component is too small.  adjust if needed.
  305.         if denom.comps[#denom.comps] < radix_sqrt then
  306.                 numer = mulint(numer, radix_sqrt)
  307.                 denom = mulint(denom, radix_sqrt)
  308.         end
  309.         return multi_divide(numer, denom)
  310. end
  311.  
  312. local function div(numer, denom)
  313.         if type(denom) == "number" then
  314.                 if denom == 0 then
  315.                         error("divide by 0", 2)
  316.                 end
  317.                 return divint(numer, denom)
  318.         elseif type(numer) == "number" then
  319.                 numer = bigint(numer)
  320.         end
  321.         -- check signs and trivial cases
  322.         local sign = 1
  323.         local cmp = compare(denom, bigint(0))
  324.         if cmp == 0 then
  325.                 error("divide by 0", 2)
  326.         elseif cmp == -1 then
  327.                 sign = -sign
  328.                 denom = negate(denom)
  329.         end
  330.         cmp = compare(numer, bigint(0))
  331.         if cmp == 0 then
  332.                 return bigint(0)
  333.         elseif cmp == -1 then
  334.                 sign = -sign
  335.                 numer = negate(numer)
  336.         end
  337.         cmp = compare(numer, denom)
  338.         if cmp == -1 then
  339.                 return bigint(0)
  340.         elseif cmp == 0 then
  341.                 return bigint(sign)
  342.         end
  343.         local bi
  344.         -- if small enough, do it the easy way
  345.         if #denom.comps == 1 then
  346.                 bi = divint(numer, denom.comps[1])
  347.         else
  348.                 bi = multi_divide_wrap(numer, denom)
  349.         end
  350.         if sign == -1 then
  351.                 bi = negate(bi)
  352.         end
  353.         return bi
  354. end
  355.  
  356. local counter = 0
  357.  
  358. local function activityDot()
  359.         counter = counter + 1
  360.  
  361.         if counter >= 1000 then
  362.                 counter = 0
  363.                 write(".")
  364.                 sleep(0.01)
  365.         end
  366. end
  367.  
  368. local function intrem(bi, m)
  369.         if m < 0 then
  370.                 m = -m
  371.         end
  372.         local rad_r = 1
  373.         local r = 0
  374.         local bc = bi.comps
  375.         for i = 1, #bc do
  376.                 activityDot()
  377.                 local v = bc[i]
  378.                 r = cmod(r + v * rad_r, m)
  379.                 rad_r = cmod(rad_r * radix, m)
  380.         end
  381.         if bi.sign < 1 then
  382.                 r = -r
  383.         end
  384.         return r
  385. end
  386.  
  387. local function intmod(bi, m)
  388.         local r = intrem(bi, m)
  389.         if r < 0 then
  390.                 r = r + m
  391.         end
  392.         return r
  393. end
  394.  
  395. local function rem(bi, m)
  396.         if type(m) == "number" then
  397.                 return bigint(intrem(bi, m))
  398.         elseif type(bi) == "number" then
  399.                 bi = bigint(bi)
  400.         end
  401.  
  402.         return bi - ((bi / m) * m)
  403. end
  404.  
  405. local function mod(a, m)
  406.         local bi = rem(a, m)
  407.         if bi.sign == -1 then
  408.                 bi = bi + m
  409.         end
  410.         return bi
  411. end
  412.  
  413. local printscale = 10000000
  414. local printscalefmt = string.format("%%.%dd", math.log10(printscale))
  415. local function makestr(bi, s)
  416.         if bi >= bigint(printscale) then
  417.                 makestr(divint(bi, printscale), s)
  418.         end
  419.         table.insert(s, string.format(printscalefmt, intmod(bi, printscale)))
  420. end
  421.  
  422. local function biginttostring(bi)
  423.         local s = {}
  424.         if bi < bigint(0) then
  425.                 bi = negate(bi)
  426.                 table.insert(s, "-")
  427.         end
  428.         makestr(bi, s)
  429.         s = table.concat(s):gsub("^0*", "")
  430.         if s == "" then s = "0" end
  431.         return s
  432. end
  433.  
  434. local function biginttonumber(bi)
  435.         return tonumber(biginttostring(bi))
  436. end
  437.  
  438. bigintmt = {
  439.         __add = add,
  440.         __sub = sub,
  441.         __mul = mul,
  442.         __div = div,
  443.         __mod = mod,
  444.         __unm = negate,
  445.         __eq = eq,
  446.         __lt = lt,
  447.         __le = le,
  448.         __tostring = biginttostring,
  449. }
  450.  
  451. local cache = {}
  452. local ncache = 0
  453.  
  454. function bigint(n)
  455.         if cache[n] then
  456.                 return cache[n]
  457.         end
  458.         local bi
  459.         if type(n) == "string" then
  460.                 local digits = { n:byte(1, -1) }
  461.                 for i = 1, #digits do
  462.                         digits[i] = string.char(digits[i])
  463.                 end
  464.                 local start = 1
  465.                 local sign = 1
  466.                 if digits[i] == '-' then
  467.                         sign = -1
  468.                         start = 2
  469.                 end
  470.                 bi = bigint(0)
  471.                 for i = start, #digits do
  472.                         bi = addint(mulint(bi, 10), tonumber(digits[i]))
  473.                 end
  474.                 bi = mulint(bi, sign)
  475.         else
  476.                 bi = alloc()
  477.                 bi.comps[1] = n
  478.                 normalize(bi)
  479.         end
  480.         if ncache > 100 then
  481.                 cache = {}
  482.                 ncache = 0
  483.         end
  484.         cache[n] = bi
  485.         ncache = ncache + 1
  486.         return bi
  487. end
  488.  
  489. --
  490. -- Start of my code
  491. --
  492.  
  493. local bigZero = bigint(0)
  494. local bigOne = bigint(1)
  495.  
  496. local function gcd(a, b)
  497.         if b ~= bigZero then
  498.                 return gcd(b, a % b)
  499.         else
  500.                 return a
  501.         end
  502. end
  503.  
  504. local function modexp(base, exponent, modulus)
  505.         local r = 1
  506.  
  507.         while true do
  508.                 if exponent % 2 == bigOne then
  509.                         r = r * base % modulus
  510.                 end
  511.                 exponent = exponent / 2
  512.  
  513.                 if exponent == bigZero then
  514.                         break
  515.                 end
  516.                 base = base * base % modulus
  517.         end
  518.  
  519.         return r
  520. end
  521.  
  522. local function bigRandomWithLength(length, cap)
  523.         if not cap then
  524.                 cap = 999999999
  525.         end
  526.  
  527.         local randomString = tostring(math.random(100000000, cap))
  528.  
  529.         while true do
  530.                 randomString = randomString ..
  531.                         tostring(math.random(100000000, cap))
  532.                 if #randomString >= length then
  533.                         local finalRandom = randomString:sub(1, length)
  534.                         if finalRandom:sub(-1, -1) == "2" then
  535.                                 return bigint(finalRandom:sub(1, -2) .. "3")
  536.                         elseif finalRandom:sub(-1, -1) == "4" then
  537.                                 return bigint(finalRandom:sub(1, -2) .. "5")
  538.                         elseif finalRandom:sub(-1, -1) == "6" then
  539.                                 return bigint(finalRandom:sub(1, -2) .. "7")
  540.                         elseif finalRandom:sub(-1, -1) == "8" then
  541.                                 return bigint(finalRandom:sub(1, -2) .. "9")
  542.                         elseif finalRandom:sub(-1, -1) == "0" then
  543.                                 return bigint(finalRandom:sub(1, -2) .. "1")
  544.                         else
  545.                                 return bigint(finalRandom)
  546.                         end
  547.                 end
  548.         end
  549. end
  550.  
  551. local function bigRandom(minNum, maxNum)
  552.         if maxNum < bigint(1000000000) then
  553.                 return bigint(math.random(biginttonumber(minNum),
  554.                         biginttonumber(maxNum)))
  555.         end
  556.  
  557.         local maxString = tostring(maxNum)
  558.         local cap = tonumber(tostring(maxNum):sub(1, 9))
  559.         local range = #maxString - #tostring(minNum)
  560.  
  561.         if range == 0 then
  562.                 return bigRandomWithLength(#maxString, cap)
  563.         end
  564.  
  565.         if #maxString > 30 then
  566.                 return bigRandomWithLength(#maxString - 1)
  567.         end
  568.  
  569.         local randomLength = math.random(1, 2^(#maxString - 1))
  570.         for i = 1, #maxString - 1 do
  571.                 if randomLength <= (2^i) then
  572.                         return bigRandomWithLength(i)
  573.                 end
  574.         end
  575. end
  576.  
  577. local function isPrime(n)
  578.         if type(n) == "number" then
  579.                 n = bigint(n)
  580.         end
  581.  
  582.         if n % 2 == bigZero then
  583.                 return false
  584.         end
  585.  
  586.         local s, d = 0, n - bigOne
  587.         while d % 2 == bigZero do
  588.                 s, d = s + 1, d / 2
  589.         end
  590.  
  591.         for i = 1, 3 do
  592.                 local a = bigRandom(bigint(2), n - 2)
  593.                 local x = modexp(a, d, n)
  594.                 if x ~= bigOne and x + 1 ~= n then
  595.                         for j = 1, s do
  596.                                 x = modexp(x, bigint(2), n)
  597.                                 if x == bigOne then
  598.                                         return false
  599.                                 elseif x == n - 1 then
  600.                                         a = bigZero
  601.                                         break
  602.                                 end
  603.                         end
  604.                         if a ~= bigZero then
  605.                                 return false
  606.                         end
  607.                 end
  608.         end
  609.  
  610.         return true
  611. end
  612.  
  613. local function generateLargePrime(length)
  614.         local i = 0
  615.         while true do
  616.                 local randomNumber = bigRandomWithLength(length)
  617.  
  618.                 if isPrime(randomNumber) then
  619.                         return randomNumber
  620.                 end
  621.         end
  622. end
  623.  
  624. local function generatePQ(e)
  625.         local randomPrime
  626.         while true do
  627.                 randomPrime = generateLargePrime()
  628.                 if gcd(e, randomPrime - 1) == bigOne then
  629.                         return randomPrime
  630.                 end
  631.         end
  632. end
  633.  
  634. local function euclidean(a, b)
  635.         local x, y, u, v = bigZero, bigOne, bigOne, bigZero
  636.         while a ~= bigZero do
  637.                 local q, r = b / a, b % a
  638.                 local m, n = x - u * q, y - v * q
  639.                 b, a, x, y, u, v = a, r, u, v, m, n
  640.         end
  641.         return b, x, y
  642. end
  643.  
  644. local function modinv(a, m)
  645.         local gcdnum, x, y = euclidean(a, m)
  646.         if gcdnum ~= bigOne then
  647.                 return nil
  648.         else
  649.                 return x % m
  650.         end
  651. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement