Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DES: support binary keys/plaintext/ciphertext and PKCS#5 padding, improve efficiency and add test script against OpenSSL #16

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 69 additions & 90 deletions src/ldes56.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,117 +9,96 @@
#include "compat-5.2.h"
#include "ldes56.h"

static int des56_decrypt( lua_State *L )
static char *des56_alloc(lua_State *L, size_t len)
{
char* decypheredText;
keysched KS;
int rel_index, abs_index;
size_t cypherlen;
const char *cypheredText =
luaL_checklstring( L, 1, &cypherlen );
const char *key = luaL_optstring( L, 2, NULL );
int padinfo;

padinfo = cypheredText[cypherlen-1];
cypherlen--;

/* Aloca array */
decypheredText =
(char *) malloc( (cypherlen+1) * sizeof(char));
if(decypheredText == NULL) {
lua_pushstring(L, "Error decrypting file. Not enough memory.");
char *p = (char *) malloc( len * sizeof(char));
if(p == NULL) {
lua_pushstring(L, "des56_alloc: memory allocation failed");
lua_error(L);
}
}
return p;
}

/* Inicia decifragem */
if (key && strlen(key) >= 8)
static int des56_set_key(lua_State *L, const char *key, size_t len, keysched *KS)
{
char k[8];
if (key && len >= 8)
{
char k[8];
int i;

for (i=0; i<8; i++)
k[i] = (unsigned char)key[i];
fsetkey(k, &KS);
memcpy(k, key, 8);
fsetkey(k, KS);
} else {
lua_pushstring(L, "Error decrypting file. Invalid key.");
lua_pushstring(L, "des56_set_key: invalid key");
lua_error(L);
return 0;
}
return 1;
}

rel_index = 0;
abs_index = 0;

while (abs_index < (int) cypherlen)
static int des56_decrypt( lua_State *L )
{
keysched KS;
int i;
size_t cipherLen;
const char *cipherText =
luaL_checklstring( L, 1, &cipherLen );
size_t keyLen;
const char *key =
luaL_checklstring( L, 2, &keyLen );

char* plainText = des56_alloc(L, cipherLen);
if(plainText == NULL)
return 0;
if (des56_set_key(L, key, keyLen, &KS) == 0)
return 0;

// copy the cipherText into the decryption buffer
memcpy(plainText, cipherText, cipherLen);

// loop over the 8-byte blocks and encrypt them
for (i=0; i<(int)cipherLen; i+=8)
{
decypheredText[abs_index] = cypheredText[abs_index];
abs_index++;
rel_index++;
if( rel_index == 8 )
{
rel_index = 0;
fencrypt(&(decypheredText[abs_index - 8]), 1, &KS);
}
fencrypt(&(plainText[i]), 1, &KS);
}
decypheredText[abs_index] = 0;

lua_pushlstring(L, decypheredText, (abs_index-padinfo));
free( decypheredText );
// PKCS#5 padding: last byte in the plainText is the pad length, remove those bytes
lua_pushlstring(L, plainText, cipherLen - plainText[cipherLen-1]);
free( plainText );

return 1;
}

static int des56_crypt( lua_State *L )
{
char *cypheredText;
keysched KS;
int rel_index, pad, abs_index;
size_t plainlen;
const char *plainText = luaL_checklstring( L, 1, &plainlen );
const char *key = luaL_optstring( L, 2, NULL );

cypheredText = (char *) malloc( (plainlen+8) * sizeof(char));
if(cypheredText == NULL) {
lua_pushstring(L, "Error encrypting file. Not enough memory.");
lua_error(L);
}

if (key && strlen(key) >= 8)
int i;
size_t plainLen;
const char *plainText = luaL_checklstring( L, 1, &plainLen );
size_t keyLen;
const char *key = luaL_checklstring( L, 2, &keyLen );
int padLen = (8 - plainLen % 8);

char* cipherText = des56_alloc(L, plainLen + padLen);
if(cipherText == NULL)
return 0;
if (des56_set_key(L, key, keyLen, &KS) == 0)
return 0;

// copy the plainText into the encryption buffer
memcpy(cipherText, plainText, plainLen);

// PKCS#5 padding: add padLen bytes with padLen value (last byte matters)
memset(&(cipherText[plainLen]), padLen, padLen);

// loop over the 8-byte blocks and decrypt them
for (i=0; i<(int)plainLen+1; i+=8)
{
char k[8];
int i;

for (i=0; i<8; i++)
k[i] = (unsigned char)key[i];
fsetkey(k, &KS);
} else {
lua_pushstring(L, "Error encrypting file. Invalid key.");
lua_error(L);
fencrypt(&(cipherText[i]), 0, &KS);
}

rel_index = 0;
abs_index = 0;
while (abs_index < (int) plainlen) {
cypheredText[abs_index] = plainText[abs_index];
abs_index++;
rel_index++;
if( rel_index == 8 ) {
rel_index = 0;
fencrypt(&(cypheredText[abs_index - 8]), 0, &KS);
}
}

pad = 0;
if(rel_index != 0) { /* Pads remaining bytes with zeroes */
while(rel_index < 8)
{
pad++;
cypheredText[abs_index++] = 0;
rel_index++;
}
fencrypt(&(cypheredText[abs_index - 8]), 0, &KS);
}
cypheredText[abs_index] = pad;
// return the encrypted padded string
lua_pushlstring( L, cipherText, plainLen + padLen);
free( cipherText );

lua_pushlstring( L, cypheredText, abs_index+1 );
free( cypheredText );
return 1;
}

Expand Down
35 changes: 35 additions & 0 deletions tests/des.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package.cpath = package.cpath .. ";/opt/local/share/luarocks/lib/lua/5.3/?.so"

local des56 = require 'des56'

if #arg < 3 then
error("usage: des.lua encrypt|decrypt <msg> <key>")
end

local cmd = arg[1]
local msg = arg[2]
local key = arg[3]

local r = nil

function string.to_hex(str)
return (str:gsub('.', function (c)
return string.format('%02x', string.byte(c))
end))
end

function string.from_hex(str)
return (str:gsub('..', function (cc)
return string.char(tonumber(cc, 16))
end))
end

if cmd == 'encrypt' then
r = des56.crypt(msg:from_hex(), key:from_hex())
elseif cmd == 'decrypt' then
r = des56.decrypt(msg:from_hex(), key:from_hex())
else
error("usage: des.lua encrypt|decrypt <msg> <key>")
end

print(r:to_hex())
29 changes: 29 additions & 0 deletions tests/des.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/bin/bash

MAX_MSG=24
LOOPS=100

for i in $(seq 1 ${LOOPS}) ; do
MSG=$(openssl rand -hex $((1 + $RANDOM % ${MAX_MSG})))
KEY=$(openssl rand -hex 8)
echo "$i KEY=${KEY} MSG=${MSG}"
LUA=$(lua des.lua encrypt ${MSG} ${KEY})
SSL=$(echo -n ${MSG} | xxd -r -p | openssl enc -e -des-ecb -K ${KEY} -provider legacy | xxd -p -c 0)
if [[ "${LUA}" != "${SSL}" ]] ; then
echo "ENCRYPTION ERROR: KEY=${KEY} MSG=${MSG}"
echo "${LUA} != ${SSL}"
exit -1
fi
MSG="${LUA}"
LUA=$(lua des.lua decrypt ${MSG} ${KEY})
SSL=$(echo -n ${MSG} | xxd -r -p | openssl enc -d -des-ecb -K ${KEY} -provider legacy | xxd -p -c 0)
if [[ "${LUA}" != "${SSL}" ]] ; then
echo "DECRYPTION ERROR: KEY=${KEY} MSG=${MSG}"
echo "${LUA} != ${SSL}"
exit -1
fi
done

echo "SUCCES"

exit 0