[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Extending Require
- From: "Jérôme Vuarand" <jerome.vuarand@...>
- Date: Thu, 10 May 2007 02:57:54 -0400
2007/5/9, Jerome Vuarand <jerome.vuarand@ubisoft.com>:
Luís Santos wrote:
> I am trying to extend the new 'modules' feature by allowing the
> 'require' function to load encrypted lua files. I haven´t found any
> clues on how to help the built-in module loading function to load my
> scripts by adding some sort of generic loader function or something
> of the sort, so I have decided to patch the source code to give it
> this capacity. However, I have felt a little unconfortable in doing
> so in a relatively new feature, in fear that I might be updated
> several times in the near future, giving me a little headache.
AFAIK there is no documentation for that aspect of Lua 5.1 module
system. I wrote an article for the upcoming Lua Programming Gems that
will explain all that. But we can discuss that here since the book is
far from being published.
I think that your situation is worth an example. I crafted an sample
module that installs a loader that check for the existence of a hash
file alongside the Lua modules, and verify that the module content
match the hash. It's not real encryption, not even cryptographic
signing, but that's not the point of the example (and you can add
these features easily). The example uses LuaCrypto for hash
computation, but everything else is in pure Lua.
I set up a page on the wiki with the code, and a zip file containing a
complete example. To use the module below simply require it, and then
subsequent requires will look for the hash files.
The page on the wiki :
- http://lua-users.org/wiki/HashedModulesLoader
And the code :
module(..., package.seeall)
local crypto = require 'crypto'
local dtypes = {"md5", "md4", "md2", "sha1", "sha", "sha256", "sha512"}
local function load(modulename)
-- Find source
local filename
local file,hashfile,hashtype
local errmsg = ""
for path in string.gmatch(package.path..";", "([^;]*);") do
filename = string.gsub(path, "%?",
(string.gsub(modulename, "%.", "\\")))
file = io.open(filename, "rb")
-- If we found a module check if it has a hash file
if file then
for _,dtype in ipairs(dtypes) do
hashfile = io.open(filename.."."..dtype, "rb")
if hashfile then
hashtype = dtype
break
end
end
end
if hashfile then
break
end
errmsg = errmsg.."\n\tno file '"..filename.."' (signed)"
end
if not file then
return errmsg
end
-- Read source file
local source = file:read("*a")
-- Read saved hash
local hash = hashfile:read("*a"):gsub("[^%x]", "")
-- Check that the saved hash match the file hash
assert(crypto.evp.digest(hashtype, source)==hash,
"module "..modulename.." (from file '"..filename.."')"..
" does not match its "..hashtype.." hash")
-- Compile and return the module
return assert(loadstring(source, filename))
end
-- Install the loader so that it's called just before the normal Lua
-- loader
table.insert(package.loaders, 2, load)