On 03/29/2011 03:38 PM, Niels Möller wrote:
Daniel Kahn Gillmor dkg@fifthhorseman.net writes:
this is quite a bit of code duplication across bindings.
Could you be a bit more concrete? Which variant of wrappers and weak-key interface are you thinking about?
sorry -- i meant that it seemed like it would be unnecessary code duplication for me to create a perl_nettle_cipher struct that matched your pike_nettle_cipher.
Before getting into specifics, I'd like to point out that the structs declared in nettle-meta.h are not intended as a fully general algorithm framework (to do that, one could, e.g., implement an interface on the same level of abstraction as libgcrypt's, on top of nettle).
hm, ok, i see your point. it sounds like nettle_cipher might be a reasonable choice for symmetric encryption (where the tools can select reasonable key sizes, etc), but *not* a reasonable choice for symmetric decryption (where we have to cope with arbitrary algorithms and keys foisted on us by the incoming ciphertext).
This works better for hash algorithm (more regular properties than for the ciphers), and in the Pike bindings, I use nettle_hash as is, but I don't use nettle_cipher.
Perhaps what i'm wondering is: can we define an cipher abstraction that exposes the relevant details in C, provides a framework that is suitable for symmetric decryption, and doesn't violate the minimalistic flavor of nettle?
I think having something like this in the canonical sources (instead of implemented outside of nettle) would make it easier to write and maintain language bindings.
Or, as you said about your Pike bindings: "the implementation is maybe a bit too complicated for its own good" -- wouldn't it be better to have the extra implementation complexity in only one place instead of expecting every binding that uses it to duplicate it?
I could consider this, but I'm not convinced that it really solves an important problem. To me, a language-specific wrapper like, e.g.,
void pike_blowfish_set_key(void *ctx, ptrdiff_t length, const char *key, int force) { if (length < BLOWFISH_MIN_KEY_SIZE || length > BLOWFISH_MAX_KEY_SIZE) Pike_error("BLOWFISH_Info: Bad keysize for BLOWFISH.\n"); if (!blowfish_set_key(ctx, length, (const uint8_t *)key) && !force) Pike_error("BLOWFISH_Info: Key is weak.\n"); }
seems more useful than a language agnostic wrapper
int aes_set_encrypt_key_wrapper (struct aes_ctx *ctx, unsigned length, const uint8_t *key) { aes_set_encrypt_key (ctx, length, key); return 1; }
i think you might be comparing apples and oranges here. I agree that language-specific error handling is useful. I'd expect any bindings to report errors in some sort of native form. But that doesn't mean that we shouldn't have a cipher-agnostic interface in C that is capable of reporting all the standard classes of errors. But it would be nice for the authors of the bindings to have a standard way (in C) to get error reports that is cipher-agnostic. Otherwise, we'll end up with a bunch of duplicate cipher-specific code in each binding.
Maybe it's useful to think through what possible errors could come up from a *_set_key function, and come up with a C interface that would cover them all in some sort of distinguishable fashion?
So far, i think the errors i've heard are:
* bad key size
* weak key
Anything else? Do we want a way to report the range of acceptable key sizes for a given cipher?
which lacks adequate error handling for bad key sizes. And if we extend nettle_cipher to include a description of valid key sizes, and/or introduce additional error codes for the set_key functions to signal different types of bad keys, then we get quite far from the current minimalistic flavor of nettle.
And here is "2b", a more involved proposal for (2) -- it's a bigger ABI+API change, but the exposed API becomes more normalized:
I'm not going to do this. The low level cipher interface is not intended to normalize away important differences between ciphers.
That seems reasonable to me. I'm happy to discard proposal 2b.
BTW: There's another easy alternative which we could call (3): Keep nettle_set_key_func as is. Introduce wrappers for des and blowfish which just ignore weak keys, and provide nettle_cipher structs using these wrappers. Then you get des and blowfish sans weak key detection, using the same interface as the other ciphers. I think this would fit reasonably with the nettle design principles. Question is: Would anybody find it useful? For a general language binding, I would expect that one would want to have the possibility to detect weak keys.
Yes, i agree that general language bindings should allow the user to detect weak keys.
--dkg