local openssl = require'openssl' local io = require'io' local M = {} M["_VERSION"] = "LuaCrypto 0.3.1" M["_COPYRIGHT"] = "Copyright (C) 2014 GeorgeZhao"; M["_DESCRIPTION"] = "crypto is a high level Lua wrapper for OpenSSL based on lua-openssl"; -----------crypto------------------ function M.hex(s) local s = openssl.hex(s) return string.lower(s) end M.digest = openssl.digest local dm = {} dm.__call = function(self,alg,msg,raw) raw = raw or true return M.digest.digest(alg,msg) end setmetatable(M.digest,dm) M.hmac = openssl.hmac -----------crypto encrypt/decrypt compat---------- local cipher = openssl.cipher local C = {} C.__index = { new = function(alg,key,iv) local c = cipher.encrypt_new(alg,key,iv) if c then local I = c:info() if (iv and #iv>I.iv_length) then error('invalid iv') end if(#key>I.key_length) then error('invalid key') end local t = {} t.ctx = c setmetatable(t,C) return t end end, update = function(self,input) return self.ctx:update(input) end, final = function(self) return self.ctx:final() end } C.__call = function(self,alg,input,key,iv) local c = cipher.get(alg) local I = c:info() if (iv and #iv>I.iv_length) then error 'invalid iv' end if(#key>I.key_length) then error 'invalid key' end local ret, msg = cipher.encrypt(alg,input,key,iv) return ret,msg end setmetatable(C,C) M.encrypt = C local D = {} D.__index = { new = function(alg,key,iv) local c = cipher.decrypt_new(alg,key,iv) if c then local I = c:info() if (iv and #iv>I.iv_length) then error('invalid iv') end if(#key>I.key_length) then error('invalid key') end local t = {} t.ctx = c setmetatable(t,D) return t end end, update = function(self,input) return self.ctx:update(input) end, final = function(self) return self.ctx:final() end } D.__call = function(self,alg,input,key,iv) local c = cipher.get(alg) local I = c:info() if (iv and #iv>I.iv_length) then error('invalid iv') end if(#key>I.key_length) then error('invalid key') end local r,s = cipher.decrypt(alg,input,key,iv) return r,s end setmetatable(D,D) M.decrypt = D -----------crypto random compat------------------ local R = {} function R.load(file) return openssl.rand_load(file) end function R.write(file) return openssl.rand_write(file) end function R.cleanup() return openssl.rand_cleanup() end function R.status() return openssl.rand_status() end function R.pseudo_bytes(len) return openssl.random(len,false) end function R.bytes(len) return openssl.random(len,true) end M.rand = R -----------crypto pkey compat------------------ local P = {} local pkey = openssl.pkey local PKEY_M = {} PKEY_M.__index = {} function PKEY_M.__index.to_pem(self,ispriv, israw) israw = israw or false if (ispriv) then return self.evp_pkey:export(true, israw) else return self.evp_pkey:is_private() and self.evp_pkey:get_public():export(true, israw) or self.evp_pkey:export(true, israw) end end function PKEY_M.__index.write(self,pubfile,prifile) local PUB,PRI = self:to_pem(false), self:to_pem(true) local f = io.open(pubfile,'w+') if f then f:write(PUB) f:close() end local f = io.open(prifile,'w+') if f then f:write(PRI) f:close() end end function P.read(file,ispriv) local f = io.open(file,'r') if f then local pem = f:read("*all") f:close() return P.from_pem(pem,ispriv) end end function P.from_pem(pem, ispriv) local k = pkey.read (pem, ispriv,'pem') if k then local key = {} key.evp_pkey = k setmetatable(key,PKEY_M) return key end end function P.generate(alg,bits) local k = pkey.new (alg,bits) if k then local key = {} key.evp_pkey = k setmetatable(key,PKEY_M) return key end end M.pkey = P ------------------------------------------ function M.sign(alg,input,prikey) local pk = prikey.evp_pkey return pkey.sign(pk,input,alg) end function M.verify(alg,input,sig,pubkey) local pk = pubkey.evp_pkey return pkey.verify(pk,input,sig,alg) end -----------------crypto seal/open compat local S = {} S.__index = { new = function(alg,pubkey) local c,key,iv = pkey.seal_init(pubkey.evp_pkey,alg) if c then local t = {} t.ctx = c t.key = key t.iv = iv setmetatable(t,S) return t end end, update = function(self,data) return pkey.seal_update(self.ctx,data) end, final = function(self) local s = pkey.seal_final(self.ctx) return s,self.key,self.iv end, } S.__call = function(self,alg,input,pubkey) local msg, key,iv = pkey.seal(pubkey.evp_pkey, input, alg) return msg,key,iv end setmetatable(S,S) M.seal = S local O = {} O.__index = { new = function(alg,privkey, ekey, iv) local c,key,iv = pkey.open_init(privkey.evp_pkey,ekey,iv,alg) if c then local t = {} t.ctx = c t.key = key t.iv = iv setmetatable(t,O) return t end end, update = function(self,data) return pkey.open_update(self.ctx,data) end, final = function(self) local s = pkey.open_final(self.ctx) return s end, } O.__call = function(self,alg,input,prikey,ek,iv) return pkey.open(prikey.evp_pkey,input,ek,iv,alg) end setmetatable(O,O) M.open = O ----------------crypto pki compat------------ local X = {} X.__index = { add_pem = function(self,pem) local ret,x = pcall(openssl.x509.read,pem) if ret then self[#self+1] = x return x end return nil end, verify_pem = function(self,pem) local ret,x = pcall(openssl.x509.read,pem) if ret then local store = openssl.x509.store.new(self) return x:check(store) end return false end } function M.x509_ca() local t = {} setmetatable(t,X) return t end ---------------------------------------------- return M