add padding mode for DES, see #1179

This commit is contained in:
Cloud Wu
2020-04-23 11:45:35 +08:00
parent 22f25bad55
commit 2389772c73
2 changed files with 130 additions and 22 deletions

View File

@@ -9,6 +9,10 @@
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#define PADDING_MODE_ISO7816_4 0
#define PADDING_MODE_PKCS7 1
#define PADDING_MODE_COUNT 2
#define SMALL_CHUNK 256 #define SMALL_CHUNK 256
/* the eight DES S-boxes */ /* the eight DES S-boxes */
@@ -353,6 +357,97 @@ lrandomkey(lua_State *L) {
return 1; 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<n;i++) {
lua_pushinteger(L, i);
lua_setfield(L, -2, mode[i]);
}
}
typedef void (*padding_add)(uint8_t buf[8], int offset);
typedef int (*padding_remove)(const uint8_t *last);
static void
padding_add_iso7816_4(uint8_t buf[8], int offset) {
buf[offset] = 0x80;
memset(buf+offset+1, 0, 7-offset);
}
static int
padding_remove_iso7816_4(const uint8_t *last) {
int padding = 1;
int i;
for (i=0;i<8;i++,last--) {
if (*last == 0) {
padding++;
} else if (*last == 0x80) {
return padding;
} else {
break;
}
}
// invalid
return 0;
}
static void
padding_add_pkcs7(uint8_t buf[8], int offset) {
uint8_t x = 8-offset;
memset(buf+offset, x, 8-offset);
}
static int
padding_remove_pkcs7(const uint8_t *last) {
int padding = *last;
int i;
for (i=1;i<padding;i++) {
--last;
if (*last != padding)
return 0; // invalid
}
return padding;
}
static padding_add padding_add_func[] = {
padding_add_iso7816_4,
padding_add_pkcs7,
};
static padding_remove padding_remove_func[] = {
padding_remove_iso7816_4,
padding_remove_pkcs7,
};
static inline void
check_padding_mode(lua_State *L, int mode) {
if (mode < 0 || mode >= 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 static void
des_key(lua_State *L, uint32_t SK[32]) { des_key(lua_State *L, uint32_t SK[32]) {
size_t keysz = 0; size_t keysz = 0;
@@ -371,6 +466,7 @@ ldesencode(lua_State *L) {
size_t textsz = 0; size_t textsz = 0;
const uint8_t * text = (const uint8_t *)luaL_checklstring(L, 2, &textsz); const uint8_t * text = (const uint8_t *)luaL_checklstring(L, 2, &textsz);
size_t chunksz = (textsz + 8) & ~7; size_t chunksz = (textsz + 8) & ~7;
int padding_mode = luaL_optinteger(L, 3, PADDING_MODE_ISO7816_4);
uint8_t tmp[SMALL_CHUNK]; uint8_t tmp[SMALL_CHUNK];
uint8_t *buffer = tmp; uint8_t *buffer = tmp;
if (chunksz > SMALL_CHUNK) { if (chunksz > SMALL_CHUNK) {
@@ -380,18 +476,8 @@ ldesencode(lua_State *L) {
for (i=0;i<(int)textsz-7;i+=8) { for (i=0;i<(int)textsz-7;i+=8) {
des_crypt(SK, text+i, buffer+i); des_crypt(SK, text+i, buffer+i);
} }
int bytes = textsz - i;
uint8_t tail[8]; uint8_t tail[8];
int j; add_padding(L, tail, text+i, textsz - i, padding_mode);
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;
}
}
des_crypt(SK, tail, buffer+i); des_crypt(SK, tail, buffer+i);
lua_pushlstring(L, (const char *)buffer, chunksz); lua_pushlstring(L, (const char *)buffer, chunksz);
@@ -413,6 +499,7 @@ ldesdecode(lua_State *L) {
if ((textsz & 7) || textsz == 0) { if ((textsz & 7) || textsz == 0) {
return luaL_error(L, "Invalid des crypt text length %d", (int)textsz); 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 tmp[SMALL_CHUNK];
uint8_t *buffer = tmp; uint8_t *buffer = tmp;
if (textsz > SMALL_CHUNK) { if (textsz > SMALL_CHUNK) {
@@ -421,17 +508,8 @@ ldesdecode(lua_State *L) {
for (i=0;i<textsz;i+=8) { for (i=0;i<textsz;i+=8) {
des_crypt(SK, text+i, buffer+i); des_crypt(SK, text+i, buffer+i);
} }
int padding = 1; int padding = remove_padding(L, buffer + textsz - 1, padding_mode);
for (i=textsz-1;i>=textsz-8;i--) { if (padding <= 0 || padding > 8) {
if (buffer[i] == 0) {
padding++;
} else if (buffer[i] == 0x80) {
break;
} else {
return luaL_error(L, "Invalid des crypt text");
}
}
if (padding > 8) {
return luaL_error(L, "Invalid des crypt text"); return luaL_error(L, "Invalid des crypt text");
} }
lua_pushlstring(L, (const char *)buffer, textsz - padding); lua_pushlstring(L, (const char *)buffer, textsz - padding);
@@ -954,6 +1032,7 @@ lxor_str(lua_State *L) {
int lsha1(lua_State *L); int lsha1(lua_State *L);
int lhmac_sha1(lua_State *L); int lhmac_sha1(lua_State *L);
LUAMOD_API int LUAMOD_API int
luaopen_skynet_crypt(lua_State *L) { luaopen_skynet_crypt(lua_State *L) {
luaL_checkversion(L); luaL_checkversion(L);
@@ -980,9 +1059,14 @@ luaopen_skynet_crypt(lua_State *L) {
{ "hmac_sha1", lhmac_sha1 }, { "hmac_sha1", lhmac_sha1 },
{ "hmac_hash", lhmac_hash }, { "hmac_hash", lhmac_hash },
{ "xor_str", lxor_str }, { "xor_str", lxor_str },
{ "padding", NULL },
{ NULL, NULL }, { NULL, NULL },
}; };
luaL_newlib(L,l); luaL_newlib(L,l);
padding_mode_table(L);
lua_setfield(L, -2, "padding");
return 1; return 1;
} }

24
test/testcrypt.lua Normal file
View File

@@ -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)