struct nettle_cipher for weak-key ciphers
nisse at lysator.liu.se
Tue Mar 29 11:02:03 CEST 2011
Daniel Kahn Gillmor <dkg at fifthhorseman.net> writes:
> I seem to have a few options:
> 0) Crypt::Nettle could write unique interfaces to those ciphers and
> expose them to the user of the perl module as (for example)
> Crypt::Nettle::Cipher::3DES and Crypt::Nettle::Cipher::Blowfish . this
> breaks symmetry with the rest of the interface, though.
> 1) Crypt::Nettle could create its own struct nettle_cipher objects for
> these ciphers, wrapping the weak key checking in some code of that
> belongs to the perl module
> 2) I could propose that nettle to create struct nettle_cipher objects
> for these ciphers directly.
I recommend (1). The way this is done in the Pike bindings (the
implementation is maybe a bit too complicated for its own good), I use a
struct pike_cipher very similar to nettle_cipher,
/* Calls Pike_error on errors */
typedef void (*pike_nettle_set_key_func)(void *ctx,
ptrdiff_t length, const char *key,
/* Force means to use key even
if it is weak */
const char *name;
/* Suggested key size; other sizes are sometimes possible. */
Here, the pike_nettle_set_key_func differs from nettle_set_key_func is
two ways, related to error handling:
1. It checks if the key size is appropriate for the algorithm, and
raises an exception if not (in contrast, a bad key size passed to the
nettle set_key function would abort the process with an assertion
2. The behaviour for weak keys. If the force argument is zero (for Pike
calls, it's an optional argument and omitting it also means zero), a
weak key results in an exception. If the force argument is non-zero,
a weak key is not not considered an error.
In these bindings, unlike yours, each cipher like AES is a single class,
with multiple supported key sizes. So all ciphers need their own set_key
wrapper for proper error checking.
In your case, where you have one separate class per possible key size, I
think you could do something similar and still use the new enumeration
interface for the "normal" algorithms.
If you're fine with either having weak keys always raise an exception or
always be accepted, you could write set_key wrappers for the affected
ciphers which do precisely that and which adhere to the
nettle_set_key_func interface (note that des_set_key and des3_set_key
don't have a key size argument so they need wrappers also for that
reason). If you want it to be configurable, things get a bit more
complicated and you may need your own struct perl_cipher to extend
struct nettle_cipher (you could still enumerate the available
nettle_cipher and convert each to a corresponding perl_cipher). Or you
could just define separate classes with and without weak key checking.
There will be a little code duplication. But there ought to be code
*somewhere* to implements the language-specific pieces of the interface,
such as exception based error handling, and new features, like, e.g.,
the optional force argument above.
> Or, am i barking up the wrong tree entirely? I'm imagining (for
> example) a user who has in their possession a symmetrically-encrypted
> message that they happen to know the key for. The cipher used was one
> of the "weak-key" ciphers, and it's even possible that the key is in
> fact a weak key. The user should still be able to decrypt the message
> using Crypt::Nettle (or any other binding).
I agree that there are certainly cases where you don't want to treat
weak keys as errors. Even though I think it makes sense to have a
default behaviour which treats weak keys as errors.
Niels Möller. PGP-encrypted email is preferred. Keyid C0B98E26.
Internet email is subject to wholesale government surveillance.
More information about the nettle-bugs