diff --git a/lualib-src/lua-crypt.c b/lualib-src/lua-crypt.c index 6f99d4f6..77ba7c40 100644 --- a/lualib-src/lua-crypt.c +++ b/lualib-src/lua-crypt.c @@ -9,6 +9,10 @@ #include #include +#define PADDING_MODE_ISO7816_4 0 +#define PADDING_MODE_PKCS7 1 +#define PADDING_MODE_COUNT 2 + #define SMALL_CHUNK 256 /* the eight DES S-boxes */ @@ -353,6 +357,97 @@ lrandomkey(lua_State *L) { return 1; } +static void +padding_mode_table(lua_State *L) { + // see macros PADDING_MODE_ISO7816_4, etc. + const char * mode[] = { + "iso7816_4", + "pkcs7", + }; + int n = sizeof(mode) / sizeof(mode[0]); + int i; + lua_createtable(L,0,n); + for (i=0;i= PADDING_MODE_COUNT) + luaL_error(L, "Invalid padding mode %d", mode); +} + +static void +add_padding(lua_State *L, uint8_t buf[8], const uint8_t *src, int offset, int mode) { + check_padding_mode(L, mode); + if (offset >= 8) + luaL_error(L, "Invalid padding"); + memcpy(buf, src, offset); + padding_add_func[mode](buf, offset); +} + +static int +remove_padding(lua_State *L, const uint8_t *last, int mode) { + check_padding_mode(L, mode); + return padding_remove_func[mode](last); +} + static void des_key(lua_State *L, uint32_t SK[32]) { size_t keysz = 0; @@ -371,6 +466,7 @@ ldesencode(lua_State *L) { size_t textsz = 0; const uint8_t * text = (const uint8_t *)luaL_checklstring(L, 2, &textsz); size_t chunksz = (textsz + 8) & ~7; + int padding_mode = luaL_optinteger(L, 3, PADDING_MODE_ISO7816_4); uint8_t tmp[SMALL_CHUNK]; uint8_t *buffer = tmp; if (chunksz > SMALL_CHUNK) { @@ -380,18 +476,8 @@ ldesencode(lua_State *L) { for (i=0;i<(int)textsz-7;i+=8) { des_crypt(SK, text+i, buffer+i); } - int bytes = textsz - i; uint8_t tail[8]; - int j; - for (j=0;j<8;j++) { - if (j < bytes) { - tail[j] = text[i+j]; - } else if (j==bytes) { - tail[j] = 0x80; - } else { - tail[j] = 0; - } - } + add_padding(L, tail, text+i, textsz - i, padding_mode); des_crypt(SK, tail, buffer+i); lua_pushlstring(L, (const char *)buffer, chunksz); @@ -413,6 +499,7 @@ ldesdecode(lua_State *L) { if ((textsz & 7) || textsz == 0) { return luaL_error(L, "Invalid des crypt text length %d", (int)textsz); } + int padding_mode = luaL_optinteger(L, 3, PADDING_MODE_ISO7816_4); uint8_t tmp[SMALL_CHUNK]; uint8_t *buffer = tmp; if (textsz > SMALL_CHUNK) { @@ -421,17 +508,8 @@ ldesdecode(lua_State *L) { for (i=0;i=textsz-8;i--) { - if (buffer[i] == 0) { - padding++; - } else if (buffer[i] == 0x80) { - break; - } else { - return luaL_error(L, "Invalid des crypt text"); - } - } - if (padding > 8) { + int padding = remove_padding(L, buffer + textsz - 1, padding_mode); + if (padding <= 0 || padding > 8) { return luaL_error(L, "Invalid des crypt text"); } lua_pushlstring(L, (const char *)buffer, textsz - padding); @@ -954,6 +1032,7 @@ lxor_str(lua_State *L) { int lsha1(lua_State *L); int lhmac_sha1(lua_State *L); + LUAMOD_API int luaopen_skynet_crypt(lua_State *L) { luaL_checkversion(L); @@ -980,9 +1059,14 @@ luaopen_skynet_crypt(lua_State *L) { { "hmac_sha1", lhmac_sha1 }, { "hmac_hash", lhmac_hash }, { "xor_str", lxor_str }, + { "padding", NULL }, { NULL, NULL }, }; luaL_newlib(L,l); + + padding_mode_table(L); + lua_setfield(L, -2, "padding"); + return 1; } diff --git a/test/testcrypt.lua b/test/testcrypt.lua new file mode 100644 index 00000000..01038b7c --- /dev/null +++ b/test/testcrypt.lua @@ -0,0 +1,24 @@ +local skynet = require "skynet" +local crypt = require "skynet.crypt" + +local text = "hello world" +local key = "12345678" + +local function desencode(key, text, padding) + local c = crypt.desencode(key, text, crypt.padding[padding or "iso7816_4"]) + return crypt.base64encode(c) +end + +local function desdecode(key, text, padding) + text = crypt.base64decode(text) + return crypt.desdecode(key, text, crypt.padding[padding or "iso7816_4"]) +end + +local etext = desencode(key, text) +assert( etext == "KNugLrX23UcGtcVlk9y+LA==") +assert(desdecode(key, etext) == text) + +local etext = desencode(key, text, "pkcs7") +assert(desdecode(key, etext, "pkcs7") == text) + +skynet.start(skynet.exit) \ No newline at end of file