Mistakes Were Made
===================

These are mistakes made early on in the project's history which are difficult to
fix now, but mentioned in the hope they may serve as an example for others.

C++ API
---------

As an implementation language, I still think C++ is the best choice (or at least
the best choice available in early '00s) at offering good performance,
reasonable abstractions, and low overhead. But the user API should have been
pure C with opaque structs (rather like the FFI layer, which was added much
later). Then an expressive C++ API could be built on top of the C API. This
would have given us a stable ABI, allowed C applications to use the library, and
(these days) make it easier to progressively rewrite the library in Rust.

Public Algorithm Specific Classes
------------------------------------

Classes like AES_128 and SHA_256 should never have been exposed to applications.
Intead such operations should have been accessible only via the higher level
interfaces (here BlockCipher and HashFunction). This would substantially reduce
the overall API and ABI surface.

[These interfaces were made internal in 3.0]

Header Directories
-------------------

It would have been better to install all headers as ``X/header.h``
where ``X`` is the base dir in the source, eg ``block/aes128.h``,
``hash/md5.h``, ...

Exceptions
-----------

Constant ABI headaches from this, and it impacts performance and makes APIs
harder to understand. Should have been handled with a result<> type instead.

Alternatively, and possibly more practically, there should have not been any
exception hierarchy (or at least not one visible to users) - instead only the
high level Exception type with contains an error type enum.

Virtual inheritance
---------------------

This was used in the public key interfaces and the hierarchy is a tangle.
Public and private keys should be distinct classes, with a function on private
keys that creates a new object corresponding to the public key.

Cipher Interface
------------------

The cipher interface taking a secure_vector that it reads from and writes to was
an artifact of an earlier design which supported both compression and encryption
in a single API. But it leads to inefficient copies.

(I am hoping this issue can be somewhat fixed by introducing a new cipher API
and implementing the old API in terms of the new one.)

Pipe Interface
----------------

On the surface this API seems very convenient and easy to use. And it is.  But
the downside is it makes the application code totally opaque; some bytes go into
a Pipe object and then come out the end transformed in some way. What happens in
between? Unless the Pipe was built in the same function and you can see the
parameters to the constructor, there is no way to find out.

The problems with the Pipe API are documented, and it is no longer used within
the library itself. But since many people seem to like it and many applications
use it, we are stuck at least with maintaining it as it currently exists.

License
---------

MIT is more widely used and doesn't have the ambiguity surrounding the
various flavors of BSD.
