我正在重写 LuaCrypto,使其在 Lua 5.3 上运行并支持 SSL 1.1.0。 (其原始代码运行在 Lua 5.1 上,并支持最高 1.0 的 SSL)。
LuaCrypto 和 Lua 5.3 不兼容的主要原因是加载机制,该机制进行了重大修改,我通过替换所有与加载库相关的函数来使其工作。
LuaCrypto 和 SSL 1.1.0 之间不兼容的主要原因是现在 SSL 结构(特别是 EVP 和 HMAC)是不透明的,并且编译器不再知道这些结构的内部或其大小。
不幸的是,LibCrypto 依赖于了解此类结构的大小来将它们作为用户数据加载到 Lua 状态。显而易见的解决方案是重写该库,以便将 EVP 和 HMAC 结构加载为 lightuserdata,并重写垃圾收集器元方法以调用 SSL free/destroy/whatever,以便在不再需要这些结构时从这些结构中删除内存。
我做到了,只要我一步运行加密/解密/摘要,一切都很有趣和游戏。每当我尝试通过 EVP_UPDATE() 函数增量使用 EVP 时,机器会在调用此函数时卡住,但如果我尝试一步运行解密则不会卡住。
这是有问题的代码:
static HANDLER_EVP *evp_pget(lua_State *L, int i)
{
if (luaL_checkudata(L, i, LUACRYPTO_EVPNAME) == NULL)
luaL_typerror(L, i, LUACRYPTO_EVPNAME);
return lua_touserdata(L, i);
}
void evp_pnew(lua_State *L, HANDLER_EVP *c)
{
lua_pushlightuserdata(L, c);
luaL_getmetatable(L, LUACRYPTO_EVPNAME);
lua_setmetatable(L, -2);
}
static int evp_fnew(lua_State *L)
{
HANDLER_EVP *c = NULL;
const char *s = luaL_checkstring(L, 1);
DIGEST_TYPE type = DIGEST_BY_NAME(s);
if (IS_DIGEST_INVALID(type)) {
luaL_argerror(L, 1, "invalid digest type");
return 0;
}
static int evp_update(lua_State *L)
{
HANDLER_EVP *c = evp_pget(L, 1);
size_t s_len;
const char *s = luaL_checklstring(L, 2, &s_len);
dumpStack(L);
debug(L, "c=%p, s=\"%s\", s_len=%d", c, s, s_len);
EVP_UPDATE(c, s, s_len); // HERE IS THE PROBLEM
debug(L, "I AM HERE"); // never run
lua_settop(L, 1);
return 1;
}
这是 Lua 测试:
for i, t in ipairs({"sha1", "md5", "sha1", "hmac"}) do
print("testing " .. t)
local d
if (t == "hmac") then
d = hmac.new("sha1", "luacrypto")
else
d = evp.new(t)
end
assert(io.input(F))
print("all", d:digest(io.read("*all")), F, t)
d:reset()
assert(io.input(F))
while true do
local c = io.read(1)
if c == nil then break end
d:update(c)
end
print("loop", d:digest(), F, t)
if (t ~= "hmac") then
print("again", d:digest(), F, t)
assert(io.input(F))
print("alone", hmac.digest("sha1", io.read("*all"), "luacrypto"), F, t);
else
assert(io.input(F))
print("alone", hmac.digest("sha1", io.read("*all"), "luacrypto"), F, t);
end
assert(io.input(F))
d:reset()
while true do
local c = io.read(math.random(1, 16))
if c == nil then break end
d:update(c)
end
report("reset", d:digest(d), F, t)
report("known", _G[t .. "_KNOWN"], F, t)
print("")
end
这是输出:
testing sha1
TAG:lua_print LINE:141
c=0xc14a8
TAG:lua_print LINE:141
all d6ed6e26ebeb37ba0792ec75a3d0b4dcec279d25 /mtd0/message sha1
TAG:lua_print LINE:141
estou aqui
TAG:lua_print LINE:141
1: userdata
2: "T"
TAG:lua_print LINE:141
c=0xc14a8, s="T", s_len=1
我错过了什么?
最佳答案
您无法为轻量级用户数据设置元表。
您需要将每个 SSL 结构指针装箱到(大量)用户数据中。
关于c - EVP_UPDATE 永远不会返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42210504/