From c3d52c1aaba0681a911b4da42efc1f07bebfecb4 Mon Sep 17 00:00:00 2001 From: "kepler155c@gmail.com" Date: Fri, 28 Jun 2019 06:33:47 -0400 Subject: [PATCH] crypto cleanup --- sys/apis/crypto/chacha20.lua | 5 +- sys/apis/crypto/ecc/init.lua | 6 +- sys/apis/crypto/sha2.lua | 25 ++-- sys/apis/sha1.lua | 280 ----------------------------------- sys/apps/Overview.lua | 6 +- sys/apps/Welcome.lua | 4 +- sys/apps/password.lua | 4 +- sys/apps/system/password.lua | 6 +- sys/apps/trust.lua | 4 +- sys/autorun/welcome.lua | 1 + 10 files changed, 35 insertions(+), 306 deletions(-) delete mode 100644 sys/apis/sha1.lua diff --git a/sys/apis/crypto/chacha20.lua b/sys/apis/crypto/chacha20.lua index b0763dd..03386a4 100644 --- a/sys/apis/crypto/chacha20.lua +++ b/sys/apis/crypto/chacha20.lua @@ -10,6 +10,7 @@ local bxor = bit32.bxor local band = bit32.band local blshift = bit32.lshift local brshift = bit32.arshift +local os = _G.os local textutils = _G.textutils local mod = 2^32 @@ -91,7 +92,7 @@ end local mt = { __tostring = function(a) return string.char(unpack(a)) end, __index = { - toHex = function(self, s) return ("%02x"):rep(#self):format(unpack(self)) end, + toHex = function(self) return ("%02x"):rep(#self):format(unpack(self)) end, isEqual = function(self, t) if type(t) ~= "table" then return false end if #self ~= #t then return false end @@ -110,7 +111,7 @@ local function crypt(data, key, nonce, cntr, round) assert(#key == 16 or #key == 32, "ChaCha20: Invalid key length ("..#key.."), must be 16 or 32") assert(#nonce == 12, "ChaCha20: Invalid nonce length ("..#nonce.."), must be 12") - local data = type(data) == "table" and {unpack(data)} or {tostring(data):byte(1,-1)} + data = type(data) == "table" and {unpack(data)} or {tostring(data):byte(1,-1)} cntr = tonumber(cntr) or 1 round = tonumber(round) or 20 diff --git a/sys/apis/crypto/ecc/init.lua b/sys/apis/crypto/ecc/init.lua index 51e3b57..f765542 100644 --- a/sys/apis/crypto/ecc/init.lua +++ b/sys/apis/crypto/ecc/init.lua @@ -2,6 +2,8 @@ local fq = require('crypto.ecc.fq') local elliptic = require('crypto.ecc.elliptic') local sha256 = require('crypto.sha2') +local os = _G.os + local q = {1372, 62520, 47765, 8105, 45059, 9616, 65535, 65535, 65535, 65535, 65535, 65532} local sLen = 24 @@ -35,9 +37,7 @@ local function exchange(sk, pk) Z = elliptic.pointScale(Z) local ss = fq.bytes(Z[2]) - local ss = sha256.digest(ss) - - return ss + return sha256.digest(ss) end local function sign(sk, message) diff --git a/sys/apis/crypto/sha2.lua b/sys/apis/crypto/sha2.lua index 162f5cb..a4f29f3 100644 --- a/sys/apis/crypto/sha2.lua +++ b/sys/apis/crypto/sha2.lua @@ -1,7 +1,9 @@ -- SHA-256, HMAC and PBKDF2 functions in ComputerCraft -- By Anavrins -local mod32 = 2^32 +local bit = _G.bit +local os = _G.os +local mod32 = 2^32 local band = bit32 and bit32.band or bit.band local bnot = bit32 and bit32.bnot or bit.bnot local bxor = bit32 and bit32.bxor or bit.bxor @@ -38,7 +40,7 @@ local function counter(incr) local t1, t2 = 0, 0 if 0xFFFFFFFF - t1 < incr then t2 = t2 + 1 - t1 = incr - (0xFFFFFFFF - t1) - 1 + t1 = incr - (0xFFFFFFFF - t1) - 1 else t1 = t1 + incr end return t2, t1 @@ -66,7 +68,7 @@ end local function digestblock(w, C) for j = 17, 64 do - local v = w[j-15] + -- local v = w[j-15] local s0 = bxor(bxor(rrotate(w[j-15], 7), rrotate(w[j-15], 18)), brshift(w[j-15], 3)) local s1 = bxor(bxor(rrotate(w[j-2], 17), rrotate(w[j-2], 19)), brshift(w[j-2], 10)) w[j] = (w[j-16] + s0 + w[j-7] + s1)%mod32 @@ -95,7 +97,7 @@ end local mt = { __tostring = function(a) return string.char(unpack(a)) end, __index = { - toHex = function(self, s) return ("%02x"):rep(#self):format(unpack(self)) end, + toHex = function(self) return ("%02x"):rep(#self):format(unpack(self)) end, isEqual = function(self, t) if type(t) ~= "table" then return false end if #self ~= #t then return false end @@ -120,7 +122,7 @@ local function toBytes(t, n) end local function digest(data) - local data = data or "" + data = data or "" data = type(data) == "table" and {upack(data)} or {tostring(data):byte(1,-1)} data = preprocess(data) @@ -130,8 +132,8 @@ local function digest(data) end local function hmac(data, key) - local data = type(data) == "table" and {upack(data)} or {tostring(data):byte(1,-1)} - local key = type(key) == "table" and {upack(key)} or {tostring(key):byte(1,-1)} + data = type(data) == "table" and {upack(data)} or {tostring(data):byte(1,-1)} + key = type(key) == "table" and {upack(key)} or {tostring(key):byte(1,-1)} local blocksize = 64 @@ -161,9 +163,9 @@ local function hmac(data, key) end local function pbkdf2(pass, salt, iter, dklen) - local salt = type(salt) == "table" and salt or {tostring(salt):byte(1,-1)} + salt = type(salt) == "table" and salt or {tostring(salt):byte(1,-1)} local hashlen = 32 - local dklen = dklen or 32 + dklen = dklen or 32 local block = 1 local out = {} @@ -190,8 +192,13 @@ local function pbkdf2(pass, salt, iter, dklen) return setmetatable(out, mt) end +local function compute(data) + return digest(data):toHex() +end + return { digest = digest, + compute = compute, hmac = hmac, pbkdf2 = pbkdf2, } diff --git a/sys/apis/sha1.lua b/sys/apis/sha1.lua deleted file mode 100644 index 0be5024..0000000 --- a/sys/apis/sha1.lua +++ /dev/null @@ -1,280 +0,0 @@ -local sha1 = { - _VERSION = "sha.lua 0.5.0", - _URL = "https://github.com/kikito/sha.lua", - _DESCRIPTION = [[ - SHA-1 secure hash computation, and HMAC-SHA1 signature computation in Lua (5.1) - Based on code originally by Jeffrey Friedl (http://regex.info/blog/lua/sha1) - And modified by Eike Decker - (http://cube3d.de/uploads/Main/sha1.txt) - ]], - _LICENSE = [[ - MIT LICENSE - - Copyright (c) 2013 Enrique Garcia Cota + Eike Decker + Jeffrey Friedl - - https://opensource.org/licenses/MIT - ]] -} - ------------------------------------------------------------------------------------ - --- loading this file (takes a while but grants a boost of factor 13) -local PRELOAD_CACHE = false - -local BLOCK_SIZE = 64 -- 512 bits - --- local storing of global functions (minor speedup) -local floor,modf = math.floor,math.modf -local char,format,rep = string.char,string.format,string.rep - --- merge 4 bytes to an 32 bit word -local function bytes_to_w32(a,b,c,d) return a*0x1000000+b*0x10000+c*0x100+d end --- split a 32 bit word into four 8 bit numbers -local function w32_to_bytes(i) - return floor(i/0x1000000)%0x100,floor(i/0x10000)%0x100,floor(i/0x100)%0x100,i%0x100 -end - --- shift the bits of a 32 bit word. Don't use negative values for "bits" -local function w32_rot(bits,a) - local b2 = 2^(32-bits) - local a,b = modf(a/b2) - return a+b*b2*(2^(bits)) -end - --- caching function for functions that accept 2 arguments, both of values between --- 0 and 255. The function to be cached is passed, all values are calculated --- during loading and a function is returned that returns the cached values (only) -local function cache2arg(fn) - if not PRELOAD_CACHE then return fn end - local lut = {} - for i=0,0xffff do - local a,b = floor(i/0x100),i%0x100 - lut[i] = fn(a,b) - end - return function(a,b) - return lut[a*0x100+b] - end -end - --- splits an 8-bit number into 8 bits, returning all 8 bits as booleans -local function byte_to_bits(b) - local b = function(n) - local b = floor(b/n) - return b%2==1 - end - return b(1),b(2),b(4),b(8),b(16),b(32),b(64),b(128) -end - --- builds an 8bit number from 8 booleans -local function bits_to_byte(a,b,c,d,e,f,g,h) - local function n(b,x) return b and x or 0 end - return n(a,1)+n(b,2)+n(c,4)+n(d,8)+n(e,16)+n(f,32)+n(g,64)+n(h,128) -end - --- bitwise "and" function for 2 8bit number -local band = cache2arg (function(a,b) - local A,B,C,D,E,F,G,H = byte_to_bits(b) - local a,b,c,d,e,f,g,h = byte_to_bits(a) - return bits_to_byte( - A and a, B and b, C and c, D and d, - E and e, F and f, G and g, H and h) -end) - --- bitwise "or" function for 2 8bit numbers -local bor = cache2arg(function(a,b) - local A,B,C,D,E,F,G,H = byte_to_bits(b) - local a,b,c,d,e,f,g,h = byte_to_bits(a) - return bits_to_byte( - A or a, B or b, C or c, D or d, - E or e, F or f, G or g, H or h) -end) - --- bitwise "xor" function for 2 8bit numbers -local bxor = cache2arg(function(a,b) - local A,B,C,D,E,F,G,H = byte_to_bits(b) - local a,b,c,d,e,f,g,h = byte_to_bits(a) - return bits_to_byte( - A ~= a, B ~= b, C ~= c, D ~= d, - E ~= e, F ~= f, G ~= g, H ~= h) -end) - --- bitwise complement for one 8bit number -local function bnot(x) - return 255-(x % 256) -end - --- creates a function to combine to 32bit numbers using an 8bit combination function -local function w32_comb(fn) - return function(a,b) - local aa,ab,ac,ad = w32_to_bytes(a) - local ba,bb,bc,bd = w32_to_bytes(b) - return bytes_to_w32(fn(aa,ba),fn(ab,bb),fn(ac,bc),fn(ad,bd)) - end -end - --- create functions for and, xor and or, all for 2 32bit numbers -local w32_and = w32_comb(band) -local w32_xor = w32_comb(bxor) -local w32_or = w32_comb(bor) - --- xor function that may receive a variable number of arguments -local function w32_xor_n(a,...) - local aa,ab,ac,ad = w32_to_bytes(a) - for i=1,select('#',...) do - local ba,bb,bc,bd = w32_to_bytes(select(i,...)) - aa,ab,ac,ad = bxor(aa,ba),bxor(ab,bb),bxor(ac,bc),bxor(ad,bd) - end - return bytes_to_w32(aa,ab,ac,ad) -end - --- combining 3 32bit numbers through binary "or" operation -local function w32_or3(a,b,c) - local aa,ab,ac,ad = w32_to_bytes(a) - local ba,bb,bc,bd = w32_to_bytes(b) - local ca,cb,cc,cd = w32_to_bytes(c) - return bytes_to_w32( - bor(aa,bor(ba,ca)), bor(ab,bor(bb,cb)), bor(ac,bor(bc,cc)), bor(ad,bor(bd,cd)) - ) -end - --- binary complement for 32bit numbers -local function w32_not(a) - return 4294967295-(a % 4294967296) -end - --- adding 2 32bit numbers, cutting off the remainder on 33th bit -local function w32_add(a,b) return (a+b) % 4294967296 end - --- adding n 32bit numbers, cutting off the remainder (again) -local function w32_add_n(a,...) - for i=1,select('#',...) do - a = (a+select(i,...)) % 4294967296 - end - return a -end --- converting the number to a hexadecimal string -local function w32_to_hexstring(w) return format("%08x",w) end - -local function hex_to_binary(hex) - return hex:gsub('..', function(hexval) - return string.char(tonumber(hexval, 16)) - end) -end - --- building the lookuptables ahead of time (instead of littering the source code --- with precalculated values) -local xor_with_0x5c = {} -local xor_with_0x36 = {} -for i=0,0xff do - xor_with_0x5c[char(i)] = char(bxor(i,0x5c)) - xor_with_0x36[char(i)] = char(bxor(i,0x36)) -end - ------------------------------------------------------------------------------ - --- calculating the SHA1 for some text -function sha1.sha1(msg) - local H0,H1,H2,H3,H4 = 0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476,0xC3D2E1F0 - local msg_len_in_bits = #msg * 8 - - local first_append = char(0x80) -- append a '1' bit plus seven '0' bits - - local non_zero_message_bytes = #msg +1 +8 -- the +1 is the appended bit 1, the +8 are for the final appended length - local current_mod = non_zero_message_bytes % 64 - local second_append = current_mod>0 and rep(char(0), 64 - current_mod) or "" - - -- now to append the length as a 64-bit number. - local B1, R1 = modf(msg_len_in_bits / 0x01000000) - local B2, R2 = modf( 0x01000000 * R1 / 0x00010000) - local B3, R3 = modf( 0x00010000 * R2 / 0x00000100) - local B4 = 0x00000100 * R3 - - local L64 = char( 0) .. char( 0) .. char( 0) .. char( 0) -- high 32 bits - .. char(B1) .. char(B2) .. char(B3) .. char(B4) -- low 32 bits - - msg = msg .. first_append .. second_append .. L64 - - assert(#msg % 64 == 0) - - local chunks = #msg / 64 - - local W = { } - local start, A, B, C, D, E, f, K, TEMP - local chunk = 0 - - while chunk < chunks do - -- - -- break chunk up into W[0] through W[15] - -- - start,chunk = chunk * 64 + 1,chunk + 1 - - for t = 0, 15 do - W[t] = bytes_to_w32(msg:byte(start, start + 3)) - start = start + 4 - end - - -- - -- build W[16] through W[79] - -- - for t = 16, 79 do - -- For t = 16 to 79 let Wt = S1(Wt-3 XOR Wt-8 XOR Wt-14 XOR Wt-16). - W[t] = w32_rot(1, w32_xor_n(W[t-3], W[t-8], W[t-14], W[t-16])) - end - - A,B,C,D,E = H0,H1,H2,H3,H4 - - for t = 0, 79 do - if t <= 19 then - -- (B AND C) OR ((NOT B) AND D) - f = w32_or(w32_and(B, C), w32_and(w32_not(B), D)) - K = 0x5A827999 - elseif t <= 39 then - -- B XOR C XOR D - f = w32_xor_n(B, C, D) - K = 0x6ED9EBA1 - elseif t <= 59 then - -- (B AND C) OR (B AND D) OR (C AND D - f = w32_or3(w32_and(B, C), w32_and(B, D), w32_and(C, D)) - K = 0x8F1BBCDC - else - -- B XOR C XOR D - f = w32_xor_n(B, C, D) - K = 0xCA62C1D6 - end - - -- TEMP = S5(A) + ft(B,C,D) + E + Wt + Kt; - A,B,C,D,E = w32_add_n(w32_rot(5, A), f, E, W[t], K), - A, w32_rot(30, B), C, D - end - -- Let H0 = H0 + A, H1 = H1 + B, H2 = H2 + C, H3 = H3 + D, H4 = H4 + E. - H0,H1,H2,H3,H4 = w32_add(H0, A),w32_add(H1, B),w32_add(H2, C),w32_add(H3, D),w32_add(H4, E) - end - local f = w32_to_hexstring - return f(H0) .. f(H1) .. f(H2) .. f(H3) .. f(H4) -end - - -function sha1.binary(msg) - return hex_to_binary(sha1.sha1(msg)) -end - -function sha1.hmac(key, text) - assert(type(key) == 'string', "key passed to sha1.hmac should be a string") - assert(type(text) == 'string', "text passed to sha1.hmac should be a string") - - if #key > BLOCK_SIZE then - key = sha1.binary(key) - end - - local key_xord_with_0x36 = key:gsub('.', xor_with_0x36) .. string.rep(string.char(0x36), BLOCK_SIZE - #key) - local key_xord_with_0x5c = key:gsub('.', xor_with_0x5c) .. string.rep(string.char(0x5c), BLOCK_SIZE - #key) - - return sha1.sha1(key_xord_with_0x5c .. sha1.binary(key_xord_with_0x36 .. text)) -end - -function sha1.hmac_binary(key, text) - return hex_to_binary(sha1.hmac(key, text)) -end - -setmetatable(sha1, {__call = function(_,msg) return sha1.sha1(msg) end }) - -return sha1 \ No newline at end of file diff --git a/sys/apps/Overview.lua b/sys/apps/Overview.lua index 1c0fe01..a2692be 100644 --- a/sys/apps/Overview.lua +++ b/sys/apps/Overview.lua @@ -3,7 +3,7 @@ local Config = require('config') local Event = require('event') local NFT = require('nft') local Packages = require('packages') -local SHA1 = require('sha1') +local SHA = require('crypto.sha2') local Tween = require('ui.tween') local UI = require('ui') local Util = require('util') @@ -502,7 +502,7 @@ end function page.editor:updateApplications(app) if not app.key then - app.key = SHA1.sha1(app.title) + app.key = SHA.compute(app.title) end local filename = app.filename or fs.combine(REGISTRY_DIR, app.key) Util.writeTable(filename, app) @@ -571,7 +571,7 @@ end Event.on('overview_shortcut', function(_, app) if not app.key then - app.key = SHA1.sha1(app.title) + app.key = SHA.compute(app.title) end local filename = app.filename or fs.combine(REGISTRY_DIR, app.key) if not fs.exists(filename) then diff --git a/sys/apps/Welcome.lua b/sys/apps/Welcome.lua index 8a4507b..399d0b2 100644 --- a/sys/apps/Welcome.lua +++ b/sys/apps/Welcome.lua @@ -1,6 +1,6 @@ local Ansi = require('ansi') local Security = require('security') -local SHA2 = require('crypto.sha2') +local SHA = require('crypto.sha2') local UI = require('ui') local colors = _G.colors @@ -107,7 +107,7 @@ end function page.wizard.pages.password:validate() if #self.newPass.value > 0 then - Security.updatePassword(SHA2.digest(self.newPass.value):toHex()) + Security.updatePassword(SHA.compute(self.newPass.value)) end --[[ if #self.group.value > 0 then diff --git a/sys/apps/password.lua b/sys/apps/password.lua index 6beb700..be64a0e 100644 --- a/sys/apps/password.lua +++ b/sys/apps/password.lua @@ -1,10 +1,10 @@ local Security = require('security') -local SHA2 = require('crypto.sha2') +local SHA = require('crypto.sha2') local Terminal = require('terminal') local password = Terminal.readPassword('Enter new password: ') if password then - Security.updatePassword(SHA2.digest(password):toHex()) + Security.updatePassword(SHA.compute(password)) print('Password updated') end diff --git a/sys/apps/system/password.lua b/sys/apps/system/password.lua index 7ad5769..ecb7677 100644 --- a/sys/apps/system/password.lua +++ b/sys/apps/system/password.lua @@ -1,5 +1,5 @@ local Security = require('security') -local SHA2 = require('crypto.sha2') +local SHA = require('crypto.sha2') local UI = require('ui') local colors = _G.colors @@ -40,11 +40,11 @@ function passwordTab:eventHandler(event) if #self.newPass.value == 0 then self:emit({ type = 'error_message', message = 'Invalid password' }) - elseif Security.getPassword() and not Security.verifyPassword(SHA2.digest(self.oldPass.value):toHex()) then + elseif Security.getPassword() and not Security.verifyPassword(SHA.compute(self.oldPass.value)) then self:emit({ type = 'error_message', message = 'Passwords do not match' }) else - Security.updatePassword(SHA2.digest(self.newPass.value):toHex()) + Security.updatePassword(SHA.compute(self.newPass.value)) self.oldPass.inactive = false self:emit({ type = 'success_message', message = 'Password updated' }) end diff --git a/sys/apps/trust.lua b/sys/apps/trust.lua index 90c01d4..dbe0b33 100644 --- a/sys/apps/trust.lua +++ b/sys/apps/trust.lua @@ -1,6 +1,6 @@ local Crypto = require('crypto.chacha20') local Security = require('security') -local SHA2 = require('crypto.sha2') +local SHA = require('crypto.sha2') local Socket = require('socket') local Terminal = require('terminal') @@ -35,7 +35,7 @@ end local publicKey = Security.getPublicKey() -socket:write(Crypto.encrypt({ pk = publicKey, dh = os.getComputerID() }, SHA2.digest(password):toHex())) +socket:write(Crypto.encrypt({ pk = publicKey, dh = os.getComputerID() }, SHA.compute(password))) local data = socket:read(2) socket:close() diff --git a/sys/autorun/welcome.lua b/sys/autorun/welcome.lua index e3a7b5a..0ee57d0 100644 --- a/sys/autorun/welcome.lua +++ b/sys/autorun/welcome.lua @@ -2,6 +2,7 @@ local Config = require('config') local Util = require('util') local fs = _G.fs +local os = _G.os local shell = _ENV.shell local config = Config.load('os')