[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[minion-cvs] Improved comments on performance.
Update of /home/minion/cvsroot/src/minion/src
In directory moria.seul.org:/tmp/cvs-serv8424/src
Modified Files:
_minionlib.h crypt.c main.c
Log Message:
Improved comments on performance.
Remove a (futile) optimization from _minionlib.sha1.
Add a (measurably productive) optimization: remember expanded AES keys.
New LIONESS key schedule.
Implement replay prevention.
Fix use of interfaces in ServerProcess.
New tests and benchmarks for the above.
Index: _minionlib.h
===================================================================
RCS file: /home/minion/cvsroot/src/minion/src/_minionlib.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- _minionlib.h 29 May 2002 03:52:13 -0000 1.1
+++ _minionlib.h 29 May 2002 17:46:24 -0000 1.2
@@ -18,6 +18,7 @@
/* Functions from crypt.c */
FUNC_DOC(mm_sha1);
FUNC_DOC(mm_sha1);
+FUNC_DOC(mm_aes_key);
FUNC_DOC(mm_aes_ctr128_crypt);
FUNC_DOC(mm_strxor);
FUNC_DOC(mm_openssl_seed);
Index: crypt.c
===================================================================
RCS file: /home/minion/cvsroot/src/minion/src/crypt.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- crypt.c 29 May 2002 03:52:13 -0000 1.1
+++ crypt.c 29 May 2002 17:46:24 -0000 1.2
@@ -28,27 +28,22 @@
const char mm_sha1__doc__[] =
"sha1(s) -> str\n\n"
- "Computes the SHA-1 hash of a string\n";
+ "Computes the SHA-1 hash of a string.\n";
PyObject*
mm_sha1(PyObject *self, PyObject *args, PyObject *kwdict)
{
- static char *kwlist[] = { "string", "key", NULL};
- unsigned char *cp = NULL, *keyp = NULL;
- int len, keylen;
+ static char *kwlist[] = { "string", NULL};
+ unsigned char *cp = NULL;
+ int len;
SHA_CTX ctx;
PyObject *output;
- if (!PyArg_ParseTupleAndKeywords(args, kwdict, "s#|s#:sha1", kwlist,
- &cp, &len, &keyp, &keylen))
+ if (!PyArg_ParseTupleAndKeywords(args, kwdict, "s#:sha1", kwlist,
+ &cp, &len))
return NULL;
SHA1_Init(&ctx);
- if (keyp)
- SHA1_Update(&ctx,keyp,keylen);
SHA1_Update(&ctx,cp,len);
- if (keyp)
- SHA1_Update(&ctx,keyp,keylen);
-
output = PyString_FromStringAndSize(NULL, SHA_DIGEST_LENGTH);
if (!output) {
PyErr_NoMemory();
@@ -60,36 +55,103 @@
return output;
}
+/* Destructor of PyCObject
+ */
+static void
+aes_destruct(void *obj, void *desc)
+{
+ assert(desc==aes_descriptor);
+ memset(obj, 0, sizeof(AES_KEY));
+ free(obj);
+}
+
+static char aes_descriptor[] = "AES key objects descriptor";
+
+static int
+aes_arg_convert(PyObject *obj, void *adr)
+{
+ if (PyCObject_Check(obj) && PyCObject_GetDesc(obj) == aes_descriptor) {
+ *((AES_KEY**) adr) = (AES_KEY*) PyCObject_AsVoidPtr(obj);
+ return 1;
+ } else {
+ TYPE_ERR("Expected an AES key as an argument.");
+ return 0;
+ }
+}
+
+const char mm_aes_key__doc__[] =
+ "aes_key(str) -> key\n\n"
+ "Converts a 16-byte string to an AES key for use with aes_ctr128_crypt.\n"
+ "\n(The performance advantage to doing so is only significant for small\n"
+ "(<1K) blocks.)\n";
+
+PyObject*
+mm_aes_key(PyObject *self, PyObject *args, PyObject *kwdict)
+{
+ static char *kwlist[] = { "key", NULL };
+ char *key;
+ int keylen;
+ AES_KEY *aes_key = NULL;
+ PyObject *result;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwdict, "s#:aes_key", kwlist,
+ &key, &keylen))
+ return NULL;
+ if (keylen != 16) {
+ TYPE_ERR("aes_key() requires a 128-bit (16 byte) string");
+ return NULL;
+ }
+ aes_key = malloc(sizeof(AES_KEY));
+ if (!aes_key) { PyErr_NoMemory(); goto err; }
+ if (AES_set_encrypt_key(key, keylen*8, aes_key)) {
+ SSL_ERR();
+ goto err;
+ }
+ result = PyCObject_FromVoidPtrAndDesc( (void*) aes_key,
+ (void*) aes_descriptor, aes_destruct );
+ if (!result) { PyErr_NoMemory(); goto err; }
+ return result;
+
+ err:
+ if (aes_key) {
+ memset(aes_key, 0, sizeof(AES_KEY));
+ free(aes_key);
+ }
+ return NULL;
+}
+
+
const char mm_aes_ctr128_crypt__doc__[] =
"aes_ctr128_crypt(key, string, idx=0, prng=0) -> str\n\n"
"Encrypts a string in counter mode. If idx is nonzero, the counter begins\n"
"at idx. If prng is nonzero, ignores string and just produces a stream of\n"
"length prng.\n\n"
- "BUG: only the 32 least significant bits of idx are used.";
+ "BUG: only the 32 least significant bits of idx are used.\n\n"
+ "Performance notes: PRNG mode is much faster (33% @ 32K) than generating\n"
+ "a string of NULs in Python and encrypting it. Encryption, on the other\n"
+ "hand, is only slightly faster (11% @ 32K) than XORing the prng output\n"
+ "with the plaintext.\n";
PyObject*
mm_aes_ctr128_crypt(PyObject *self, PyObject *args, PyObject *kwdict)
{
static char *kwlist[] = { "key", "string", "idx", "prng", NULL };
- unsigned char *key, *input;
- int keylen, inputlen, prng=0;
+ unsigned char *input;
+ int inputlen, prng=0;
long idx=0;
int shortidx;
- AES_KEY aes_key;
+ AES_KEY *aes_key =NULL;
unsigned char *counter;
PyObject *output;
if (!PyArg_ParseTupleAndKeywords(args, kwdict,
- "s#s#|li:aes_ctr128_crypt", kwlist,
- &key, &keylen, &input, &inputlen,
+ "O&s#|li:aes_ctr128_crypt", kwlist,
+ aes_arg_convert, &aes_key,
+ &input, &inputlen,
&idx, &prng))
return NULL;
- if (keylen != 16) {
- TYPE_ERR("AES key wasn\'t 128 bits long");
- return NULL;
- }
if (idx < 0) idx = 0;
if (prng < 0) prng = 0;
@@ -105,20 +167,13 @@
counter[13] = (idx >> 16) & 0xff;
counter[12] = (idx >> 24) & 0xff;
}
- if (AES_set_encrypt_key(key, keylen*8, &aes_key)) {
- SSL_ERR();
- free(counter);
- return NULL;
- }
-
if (prng) {
inputlen = prng;
input = malloc(prng);
if (!input) { PyErr_NoMemory(); return NULL; }
- memset(input, 0, prng);
- output = PyString_FromStringAndSize(NULL, prng);
- } else
- output = PyString_FromStringAndSize(input, inputlen);
+ memset(input, 0, inputlen);
+ }
+ output = PyString_FromStringAndSize(NULL, inputlen);
if (!output) {
PyErr_NoMemory();
free(counter);
@@ -126,14 +181,13 @@
return NULL;
}
- AESCRYPT(input, PyString_AS_STRING(output),
- inputlen, &aes_key,
+ AESCRYPT((const char*)input, PyString_AS_STRING(output),
+ inputlen, aes_key,
counter, &shortidx);
- memset(&aes_key, 0, sizeof(AES_KEY));
free(counter);
- if (prng) free(input);
+ if (prng) free(input);
return output;
}
@@ -160,12 +214,12 @@
return NULL;
}
- output = PyString_FromStringAndSize(s1,s1len);
+ output = PyString_FromStringAndSize(NULL,s1len);
if (! output) { PyErr_NoMemory(); return NULL; }
outp = PyString_AS_STRING(output);
while (s1len--) {
- *(outp++) ^= *(s2++);
+ *(outp++) = *(s1++) ^ *(s2++);
}
return output;
@@ -207,7 +261,8 @@
static char rsa_descriptor[] = "RSA objects descriptor";
static int
-rsa_arg_convert(PyObject *obj, void *adr) {
+rsa_arg_convert(PyObject *obj, void *adr)
+{
if (PyCObject_Check(obj) && PyCObject_GetDesc(obj) == rsa_descriptor) {
*((RSA**) adr) = (RSA*) PyCObject_AsVoidPtr(obj);
return 1;
@@ -221,8 +276,6 @@
#define WRAP_RSA(rsa) (PyCObject_FromVoidPtrAndDesc( (void*) (rsa),\
(void*) rsa_descriptor, rsa_destruct))
-
-
const char mm_rsa_crypt__doc__[]=
"rsa_crypt(key, string, public, encrypt) -> str\n\n"
"Uses RSA to encrypt or decrypt a provided string. If encrypt is true,\n"
Index: main.c
===================================================================
RCS file: /home/minion/cvsroot/src/minion/src/main.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- main.c 29 May 2002 03:52:13 -0000 1.1
+++ main.c 29 May 2002 17:46:24 -0000 1.2
@@ -12,6 +12,7 @@
static struct PyMethodDef _mixcryptlib_functions[] = {
ENTRY(sha1),
+ ENTRY(aes_key),
ENTRY(aes_ctr128_crypt),
ENTRY(strxor),
ENTRY(openssl_seed),