SHOW:
|
|
- or go back to the newest paste.
| 1 | -- SHA-256, HMAC and PBKDF2 functions in ComputerCraft | |
| 2 | -- By Anavrins | |
| 3 | -- MIT License | |
| 4 | -- Pastebin: https://pastebin.com/6UV4qfNF | |
| 5 | -- Usage: https://pastebin.com/q2SQ7eRg | |
| 6 | - | -- Last updated: June 30 2024 |
| 6 | + | -- Last updated: March 27 2020 |
| 7 | ||
| 8 | local mod32 = 2^32 | |
| 9 | local band = bit32 and bit32.band or bit.band | |
| 10 | local bnot = bit32 and bit32.bnot or bit.bnot | |
| 11 | local bxor = bit32 and bit32.bxor or bit.bxor | |
| 12 | - | local upack = table.unpack or unpack |
| 12 | + | |
| 13 | local upack = unpack | |
| 14 | ||
| 15 | local function rrotate(n, b) | |
| 16 | local s = n/(2^b) | |
| 17 | - | return (s-f) + f * 2^32 |
| 17 | + | |
| 18 | return (s-f) + f*mod32 | |
| 19 | end | |
| 20 | local function brshift(int, by) | |
| 21 | local s = int / (2^by) | |
| 22 | return s - s%1 | |
| 23 | end | |
| 24 | - | local H = { -- First 32 bits of the fractional parts of the square roots of the first 8 primes 2..19
|
| 24 | + | |
| 25 | local H = {
| |
| 26 | 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, | |
| 27 | 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, | |
| 28 | } | |
| 29 | - | local K = { -- First 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311
|
| 29 | + | |
| 30 | local K = {
| |
| 31 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, | |
| 32 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, | |
| 33 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, | |
| 34 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, | |
| 35 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, | |
| 36 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, | |
| 37 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, | |
| 38 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, | |
| 39 | } | |
| 40 | ||
| 41 | local function counter(incr) | |
| 42 | local t1, t2 = 0, 0 | |
| 43 | if 0xFFFFFFFF - t1 < incr then | |
| 44 | - | t1 = incr - (0xFFFFFFFF - t1) - 1 |
| 44 | + | |
| 45 | t1 = incr - (0xFFFFFFFF - t1) - 1 | |
| 46 | else t1 = t1 + incr | |
| 47 | end | |
| 48 | return t2, t1 | |
| 49 | end | |
| 50 | ||
| 51 | local function BE_toInt(bs, i) | |
| 52 | return blshift((bs[i] or 0), 24) + blshift((bs[i+1] or 0), 16) + blshift((bs[i+2] or 0), 8) + (bs[i+3] or 0) | |
| 53 | end | |
| 54 | ||
| 55 | local function preprocess(data) | |
| 56 | local len = #data | |
| 57 | local proc = {}
| |
| 58 | data[#data+1] = 0x80 | |
| 59 | while #data%64~=56 do data[#data+1] = 0 end | |
| 60 | local blocks = math.ceil(#data/64) | |
| 61 | for i = 1, blocks do | |
| 62 | proc[i] = {}
| |
| 63 | for j = 1, 16 do | |
| 64 | proc[i][j] = BE_toInt(data, 1+((i-1)*64)+((j-1)*4)) | |
| 65 | end | |
| 66 | end | |
| 67 | proc[blocks][15], proc[blocks][16] = counter(len*8) | |
| 68 | return proc | |
| 69 | end | |
| 70 | - | local function digestblock(w, C) |
| 70 | + | |
| 71 | function digestblock(w, C) | |
| 72 | for j = 17, 64 do | |
| 73 | - | local u = w[j-2] |
| 73 | + | |
| 74 | - | local s0 = bxor(rrotate(v, 7), rrotate(v, 18), brshift(v, 3)) |
| 74 | + | local s0 = bxor(rrotate(w[j-15], 7), rrotate(w[j-15], 18), brshift(w[j-15], 3)) |
| 75 | - | local s1 = bxor(rrotate(u, 17), rrotate(u, 19), brshift(u, 10)) |
| 75 | + | local s1 = bxor(rrotate(w[j-2], 17), rrotate(w[j-2], 19),brshift(w[j-2], 10)) |
| 76 | - | w[j] = (w[j-16] + s0 + w[j-7] + s1) % 2^32 |
| 76 | + | w[j] = (w[j-16] + s0 + w[j-7] + s1)%mod32 |
| 77 | end | |
| 78 | local a, b, c, d, e, f, g, h = upack(C) | |
| 79 | for j = 1, 64 do | |
| 80 | local S1 = bxor(rrotate(e, 6), rrotate(e, 11), rrotate(e, 25)) | |
| 81 | local ch = bxor(band(e, f), band(bnot(e), g)) | |
| 82 | - | local temp1 = (h + S1 + ch + K[j] + w[j]) |
| 82 | + | local temp1 = (h + S1 + ch + K[j] + w[j])%mod32 |
| 83 | local S0 = bxor(rrotate(a, 2), rrotate(a, 13), rrotate(a, 22)) | |
| 84 | local maj = bxor(bxor(band(a, b), band(a, c)), band(b, c)) | |
| 85 | - | local temp2 = (S0 + maj) |
| 85 | + | local temp2 = (S0 + maj)%mod32 |
| 86 | - | h, g, f, e, d, c, b, a = g, f, e, (d+temp1) % 2^32, c, b, a, (temp1+temp2) % 2^32 |
| 86 | + | h, g, f, e, d, c, b, a = g, f, e, (d+temp1)%mod32, c, b, a, (temp1+temp2)%mod32 |
| 87 | end | |
| 88 | - | C[1] = (C[1] + a) % 2^32 |
| 88 | + | C[1] = (C[1] + a)%mod32 |
| 89 | - | C[2] = (C[2] + b) % 2^32 |
| 89 | + | C[2] = (C[2] + b)%mod32 |
| 90 | - | C[3] = (C[3] + c) % 2^32 |
| 90 | + | C[3] = (C[3] + c)%mod32 |
| 91 | - | C[4] = (C[4] + d) % 2^32 |
| 91 | + | C[4] = (C[4] + d)%mod32 |
| 92 | - | C[5] = (C[5] + e) % 2^32 |
| 92 | + | C[5] = (C[5] + e)%mod32 |
| 93 | - | C[6] = (C[6] + f) % 2^32 |
| 93 | + | C[6] = (C[6] + f)%mod32 |
| 94 | - | C[7] = (C[7] + g) % 2^32 |
| 94 | + | C[7] = (C[7] + g)%mod32 |
| 95 | - | C[8] = (C[8] + h) % 2^32 |
| 95 | + | C[8] = (C[8] + h)%mod32 |
| 96 | return C | |
| 97 | end | |
| 98 | ||
| 99 | - | local mt = {}
|
| 99 | + | local mt = {
|
| 100 | - | mt = {
|
| 100 | + | __tostring = function(a) return string.char(unpack(a)) end, |
| 101 | - | __tostring = function(a) return string.char(upack(a)) end, |
| 101 | + | |
| 102 | toHex = function(self, s) return ("%02x"):rep(#self):format(unpack(self)) end,
| |
| 103 | - | toHex = function(self) return ("%02x"):rep(#self):format(upack(self)) end,
|
| 103 | + | |
| 104 | if type(t) ~= "table" then return false end | |
| 105 | if #self ~= #t then return false end | |
| 106 | local ret = 0 | |
| 107 | for i = 1, #self do | |
| 108 | ret = bit32.bor(ret, bxor(self[i], t[i])) | |
| 109 | end | |
| 110 | return ret == 0 | |
| 111 | end | |
| 112 | - | end, |
| 112 | + | |
| 113 | - | sub = function(self, a, b) |
| 113 | + | |
| 114 | - | local len = #self+1 |
| 114 | + | |
| 115 | - | local start = a%len |
| 115 | + | function toBytes(t, n) |
| 116 | - | local stop = (b or len-1)%len |
| 116 | + | |
| 117 | - | local ret = {}
|
| 117 | + | |
| 118 | - | local i = 1 |
| 118 | + | |
| 119 | - | for j = start, stop, start<stop and 1 or -1 do |
| 119 | + | |
| 120 | - | ret[i] = self[j] |
| 120 | + | |
| 121 | - | i = i+1 |
| 121 | + | |
| 122 | end | |
| 123 | - | return setmetatable(ret, mt) |
| 123 | + | |
| 124 | - | end, |
| 124 | + | |
| 125 | ||
| 126 | local function digest(data) | |
| 127 | local data = data or "" | |
| 128 | - | local function toBytes(t, n) |
| 128 | + | |
| 129 | ||
| 130 | data = preprocess(data) | |
| 131 | local C = {upack(H)}
| |
| 132 | for i = 1, #data do C = digestblock(data[i], C) end | |
| 133 | return toBytes(C, 8) | |
| 134 | end | |
| 135 | ||
| 136 | function hmac(data, key) | |
| 137 | local data = type(data) == "table" and {upack(data)} or {tostring(data):byte(1,-1)}
| |
| 138 | local key = type(key) == "table" and {upack(key)} or {tostring(key):byte(1,-1)}
| |
| 139 | ||
| 140 | local blocksize = 64 | |
| 141 | ||
| 142 | key = #key > blocksize and digest(key) or key | |
| 143 | ||
| 144 | local ipad = {}
| |
| 145 | local opad = {}
| |
| 146 | local padded_key = {}
| |
| 147 | ||
| 148 | for i = 1, blocksize do | |
| 149 | - | local function hmac(data, key) |
| 149 | + | |
| 150 | opad[i] = bxor(0x5C, key[i] or 0) | |
| 151 | end | |
| 152 | ||
| 153 | for i = 1, #data do | |
| 154 | ipad[blocksize+i] = data[i] | |
| 155 | end | |
| 156 | ||
| 157 | ipad = digest(ipad) | |
| 158 | ||
| 159 | for i = 1, blocksize do | |
| 160 | padded_key[i] = opad[i] | |
| 161 | padded_key[blocksize+i] = ipad[i] | |
| 162 | end | |
| 163 | ||
| 164 | return digest(padded_key) | |
| 165 | end | |
| 166 | ||
| 167 | function pbkdf2(pass, salt, iter, dklen) | |
| 168 | local salt = type(salt) == "table" and salt or {tostring(salt):byte(1,-1)}
| |
| 169 | local hashlen = 32 | |
| 170 | local dklen = dklen or 32 | |
| 171 | local block = 1 | |
| 172 | local out = {}
| |
| 173 | ||
| 174 | while dklen > 0 do | |
| 175 | local ikey = {}
| |
| 176 | local isalt = {upack(salt)}
| |
| 177 | local clen = dklen > hashlen and hashlen or dklen | |
| 178 | ||
| 179 | isalt[#isalt+1] = band(brshift(block, 24), 0xFF) | |
| 180 | - | local function pbkdf2(pass, salt, iter, dklen) |
| 180 | + | |
| 181 | isalt[#isalt+1] = band(brshift(block, 8), 0xFF) | |
| 182 | isalt[#isalt+1] = band(block, 0xFF) | |
| 183 | ||
| 184 | for j = 1, iter do | |
| 185 | isalt = hmac(isalt, pass) | |
| 186 | for k = 1, clen do ikey[k] = bxor(isalt[k], ikey[k] or 0) end | |
| 187 | if j % 200 == 0 then os.queueEvent("PBKDF2", j) coroutine.yield("PBKDF2") end
| |
| 188 | end | |
| 189 | dklen = dklen - clen | |
| 190 | block = block+1 | |
| 191 | for k = 1, clen do out[#out+1] = ikey[k] end | |
| 192 | end | |
| 193 | ||
| 194 | return setmetatable(out, mt) | |
| 195 | end | |
| 196 | ||
| 197 | return {
| |
| 198 | digest = digest, | |
| 199 | hmac = hmac, | |
| 200 | pbkdf2 = pbkdf2, | |
| 201 | } |