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