Low-level crypto interface
Bob Deblier
bob@virtual-unlimited.com
Thu, 14 Dec 2000 09:59:37 +0100
"Niels Möller" wrote:
> At the crypto workshop a few months ago, I promised to write up my
> ideas for a low-level crypto library interface. I have a first version
> of that document now, at <URL:
> http://www.lysator.liu.se/~nisse/lsh/doc/crypto-library.txt>.
>
> It also describes an object-oriented interface that can be built on
> top of the low-level interface, and some examples. It's similar to
> (but not exactly the same) the interfaces currently used in lsh.
>
> I hope this is an appropriate place for this. Comments are welcome.
>
> Regards,
> /Niels
Niels,
Thanks for sending this contribution - it was good reading material. Here
are a few comments and thoughts I have about this subject:
I take a slighty different approach in BeeCrypt. I do have a context
structure for every algorithm (even for random generators and hash
functions), but I don't define constants - they make code that uses them
inflexible.
The way I've solved this is by having a table which describes all
algorithms of a certain kind. Every entry in the table describes an
algorithm, has fields that describe its characteristics (including the
name of the algorithm so that the table can be searched), and has
pointers to the actual routines for the algorithm.
For instance my blockcipher structures and table currently look like
this:
typedef void blockCipherParam;
typedef int (*blockCipherSetup )(blockCipherParam*, const uint32*, int,
cipherOperation);
typedef int (*blockCipherSetIV )(blockCipherParam*, const uint32*);
typedef int (*blockCipherEncrypt)(blockCipherParam*, uint32*, const
uint32*);
typedef int (*blockCipherDecrypt)(blockCipherParam*, uint32*, const
uint32*);
typedef struct
{
const char* name;
const unsigned int paramsize; /* in bytes */
const unsigned int blocksize; /* in bytes */
const unsigned int keybitsmin; /* in bits */
const unsigned int keybitsmax; /* in bits */
const unsigned int keybitsinc; /* in bits */
const blockCipherSetup setup;
const blockCipherSetIV setiv;
const blockCipherEncrypt encrypt;
const blockCipherDecrypt decrypt;
const blockMode* mode;
} blockCipher;
static const blockCipher* blockCipherList[] =
{
&blowfish
};
The blowfish structure itself looks like this:
const blockCipher blowfish = {
"Blowfish",
sizeof(blowfishParam),
8,
64,
448,
32,
(const blockCipherSetup) blowfishSetup,
(const blockCipherSetIV) blowfishSetIV,
(const blockCipherEncrypt) blowfishEncrypt,
(const blockCipherDecrypt) blowfishDecrypt,
blowfishModes
};
In this way it is possible to use pretty abstract code, even in C.
For block modes (ECB, CBC, etc.), I have routines that can take a cipher
and its context, and perform the requested operation from a source block
to a destination block. Individual ciphers can have optimized speedups
for each block mode, in addition to the generic code (through the
blockMode pointer, in case you were wondering).
At a later stage I hope to be able to do something similar for assymetric
algorithms. I'll most likely make tables for assymetric ciphers,
signatures, and key agreements.
In the future, I can also make the library more flexible by dynamically
inserting and removing algorithm providers (instead of using the current
static tables).
Offtopic: I'm thinking about starting a new open-source (GPL) project
called 'BeeUtils', of which the first part will be small apps for
computing the cryptographic hash value of a file. Of course the md5sum
utility is available in the GNU textutils, but what about a sha1sum, or
even a sha256sum? Is there a need for utilities that do this?
As above, comments are welcome.
Sincerely,
Bob Deblier
Virtual Unlimited