summaryrefslogtreecommitdiffstats
path: root/old/botan/doc
diff options
context:
space:
mode:
Diffstat (limited to 'old/botan/doc')
-rw-r--r--old/botan/doc/api.pdfbin0 -> 254607 bytes
-rw-r--r--old/botan/doc/api.tex3103
-rw-r--r--old/botan/doc/architecture.pdfbin0 -> 463402 bytes
-rw-r--r--old/botan/doc/building.pdfbin0 -> 84582 bytes
-rw-r--r--old/botan/doc/building.tex398
-rw-r--r--old/botan/doc/credits.txt78
-rw-r--r--old/botan/doc/examples/GNUmakefile21
-rw-r--r--old/botan/doc/examples/asn1.cpp312
-rw-r--r--old/botan/doc/examples/base.cpp44
-rw-r--r--old/botan/doc/examples/base64.cpp82
-rw-r--r--old/botan/doc/examples/bench.cpp98
-rw-r--r--old/botan/doc/examples/benchmark.cpp41
-rw-r--r--old/botan/doc/examples/bzip.cpp108
-rw-r--r--old/botan/doc/examples/ca.cpp74
-rw-r--r--old/botan/doc/examples/checksum.cpp31
-rw-r--r--old/botan/doc/examples/cms_dec.cpp116
-rw-r--r--old/botan/doc/examples/cms_enc.cpp53
-rw-r--r--old/botan/doc/examples/cryptobox.cpp50
-rw-r--r--old/botan/doc/examples/decrypt.cpp158
-rw-r--r--old/botan/doc/examples/dh.cpp59
-rw-r--r--old/botan/doc/examples/dsa_kgen.cpp66
-rw-r--r--old/botan/doc/examples/dsa_sign.cpp83
-rw-r--r--old/botan/doc/examples/dsa_ver.cpp92
-rw-r--r--old/botan/doc/examples/eax_test.cpp241
-rw-r--r--old/botan/doc/examples/eax_tv.txt461
-rw-r--r--old/botan/doc/examples/ecdsa.cpp57
-rw-r--r--old/botan/doc/examples/encrypt.cpp179
-rw-r--r--old/botan/doc/examples/encrypt2.cpp55
-rw-r--r--old/botan/doc/examples/factor.cpp144
-rw-r--r--old/botan/doc/examples/gen_certs.cpp124
-rw-r--r--old/botan/doc/examples/gtk/dsa.cpp556
-rw-r--r--old/botan/doc/examples/gtk/gtk_ui.cpp78
-rw-r--r--old/botan/doc/examples/gtk/gtk_ui.h25
-rw-r--r--old/botan/doc/examples/gtk/readme.txt18
-rw-r--r--old/botan/doc/examples/hash.cpp64
-rw-r--r--old/botan/doc/examples/hash_fd.cpp71
-rw-r--r--old/botan/doc/examples/hash_quickly.cpp90
-rw-r--r--old/botan/doc/examples/hasher.cpp58
-rw-r--r--old/botan/doc/examples/hasher2.cpp72
-rw-r--r--old/botan/doc/examples/make_prime.cpp73
-rw-r--r--old/botan/doc/examples/passhash.cpp86
-rw-r--r--old/botan/doc/examples/pkcs10.cpp73
-rw-r--r--old/botan/doc/examples/pqg_gen.cpp116
-rw-r--r--old/botan/doc/examples/readme.txt77
-rw-r--r--old/botan/doc/examples/ressol.cpp80
-rw-r--r--old/botan/doc/examples/rng_test.cpp143
-rw-r--r--old/botan/doc/examples/row_encryptor.cpp143
-rw-r--r--old/botan/doc/examples/rsa_dec.cpp127
-rw-r--r--old/botan/doc/examples/rsa_enc.cpp151
-rw-r--r--old/botan/doc/examples/rsa_kgen.cpp65
-rw-r--r--old/botan/doc/examples/rsa_manykey.cpp36
-rw-r--r--old/botan/doc/examples/self_sig.cpp79
-rw-r--r--old/botan/doc/examples/sig_gen.cpp90
-rw-r--r--old/botan/doc/examples/stack.cpp86
-rw-r--r--old/botan/doc/examples/test_es.cpp115
-rw-r--r--old/botan/doc/examples/x509info.cpp154
-rw-r--r--old/botan/doc/examples/xor_ciph.cpp96
-rw-r--r--old/botan/doc/fips140.tex156
-rw-r--r--old/botan/doc/indent.el57
-rw-r--r--old/botan/doc/insito_manual.pdfbin0 -> 150405 bytes
-rw-r--r--old/botan/doc/internals.tex179
-rw-r--r--old/botan/doc/license.txt40
-rw-r--r--old/botan/doc/log.txt1323
-rw-r--r--old/botan/doc/pgpkeys.asc83
-rw-r--r--old/botan/doc/scripts/comba.py65
-rw-r--r--old/botan/doc/scripts/combine_bmarks.pl120
-rw-r--r--old/botan/doc/scripts/dist.sh64
-rw-r--r--old/botan/doc/scripts/primes.py63
-rw-r--r--old/botan/doc/scripts/print_deps.py70
-rw-r--r--old/botan/doc/scripts/update_deps.py41
-rw-r--r--old/botan/doc/thanks.txt49
-rw-r--r--old/botan/doc/tutorial.pdfbin0 -> 115992 bytes
-rw-r--r--old/botan/doc/tutorial.tex883
73 files changed, 12343 insertions, 0 deletions
diff --git a/old/botan/doc/api.pdf b/old/botan/doc/api.pdf
new file mode 100644
index 0000000..a9939f2
--- /dev/null
+++ b/old/botan/doc/api.pdf
Binary files differ
diff --git a/old/botan/doc/api.tex b/old/botan/doc/api.tex
new file mode 100644
index 0000000..556e76a
--- /dev/null
+++ b/old/botan/doc/api.tex
@@ -0,0 +1,3103 @@
+\documentclass{article}
+
+\setlength{\textwidth}{6.5in}
+\setlength{\textheight}{9in}
+
+\setlength{\headheight}{0in}
+\setlength{\topmargin}{0in}
+\setlength{\headsep}{0in}
+
+\setlength{\oddsidemargin}{0in}
+\setlength{\evensidemargin}{0in}
+
+\title{\textbf{Botan API Reference}}
+\author{}
+\date{2009/2/19}
+
+\newcommand{\filename}[1]{\texttt{#1}}
+\newcommand{\manpage}[2]{\texttt{#1}(#2)}
+
+\newcommand{\macro}[1]{\texttt{#1}}
+
+\newcommand{\function}[1]{\textbf{#1}}
+\newcommand{\keyword}[1]{\texttt{#1}}
+\newcommand{\type}[1]{\texttt{#1}}
+\renewcommand{\arg}[1]{\textsl{#1}}
+\newcommand{\namespace}[1]{\texttt{#1}}
+
+\newcommand{\url}[1]{\texttt{#1}}
+
+\newcommand{\ie}[0]{\emph{i.e.}}
+\newcommand{\eg}[0]{\emph{e.g.}}
+
+\begin{document}
+
+\maketitle
+
+\tableofcontents
+
+\parskip=5pt
+
+\pagebreak
+\section{Introduction}
+
+Botan is a C++ library that attempts to provide the most common
+cryptographic algorithms and operations in an easy to use, efficient,
+and portable way. It runs on a wide variety of systems, and can be
+used with a number of different compilers.
+
+The base library is written in ISO C++, so it can be ported with
+minimal fuss, but Botan also supports a modules system. This system
+exposes system dependent code to the library through portable
+interfaces, extending the set of services available to users.
+
+\subsection{Targets}
+
+Botan's primary targets (system-wise) are 32 and 64-bit CPUs, with a
+flat memory address space of at least 32 bits. Generally, given the
+choice between optimizing for 32-bit systems and 64-bit systems, Botan
+is written to prefer 64-bit, simply on the theory that where
+performance is a real concern, modern 64-bit processors are the
+obvious choice. However in most cases this is not an issue, as many
+algorithms are specified in terms of 32-bit operations precisely to
+target commodity processors.
+
+Smaller handhelds, set-top boxes, and the bigger smart phones and smart
+cards, are also capable of using Botan. However, Botan uses a fairly
+large amount of code space (up to several megabytes, depending upon
+the compiler and options used), which could be prohibitive in some
+systems. Usage of RAM is fairly modest, usually under 64K.
+
+Botan's design makes it quite easy to remove unused algorithms in such
+a way that applications do not need to be recompiled to work, even
+applications that use the algorithms in question. They can simply ask
+Botan if the algorithm exists, and if Botan says yes, ask the library
+to give them such an object for that algorithm.
+
+\subsection{Why Botan?}
+
+Botan may be the perfect choice for your application. Or it might be a
+terribly bad idea. This section will make clear what Botan is
+and is not.
+
+First, let's cover the major strengths:
+
+\begin{list}{$\cdot$}
+ \item Support is (usually) quickly available on the project mailing lists.
+ Commercial support licenses are available for those that desire them.
+
+ \item
+ \item Is written in a (fairly) clean object-oriented style, and the usual
+ API works in terms of reasonably high-level abstractions.
+
+ \item Supports a huge variety of algorithms, including most of the major
+ public key algorithms and standards (such as IEEE 1363, PKCS, and
+ X.509v3).
+
+ \item Supports a name-based lookup scheme, so you can get a hold of any
+ algorithm on the fly.
+
+ \item You can easily extend much of the system at application compile time or
+ at run time.
+
+ \item Works well with a wide variety of compilers, operating systems, and
+ CPUs, and more all the time.
+
+ \item Is the only open source crypto library (that I know of) that has
+ support for memory allocation techniques that prevent an attacker from
+ reading swap in an attempt to gain access to keys or other secrets. In
+ fact several different such methods are supported, depending on the
+ system (two methods for Unix, another for Windows).
+
+ \item Has (optional) support for Zlib and Bzip2 compression/decompression
+ integrated completely into the system -- it only takes a line or two of
+ code to add compression to your application.
+\end{list}
+
+\noindent
+And the major downsides and deficiencies are:
+
+\begin{list}{$\cdot$}
+ \item It's written in C++. If your application isn't, Botan is probably
+ going to be more pain than it's worth.
+ \item
+
+ \item Botan doesn't directly support higher-level protocols and
+ formats like SSL or OpenPGP. SSH support is available from a
+ third-party, and there is an alpha-level SSL/TLS library
+ currently available.
+
+ \item Doesn't currently support any very high level 'envelope' style
+ processing - support for this will probably be added once support for
+ CMS is available, so code using the high level interface will produce
+ data readable by many other libraries.
+\end{list}
+
+\pagebreak
+\section{Getting Started}
+
+\subsection{Basic Conventions}
+
+With a very small number of exceptions, declarations in the library
+are contained within the namespace \namespace{Botan}. Botan declares
+several typedef'ed types to help buffer it against changes in machine
+architecture. These types are used extensively in the interface,
+thus it would be often be convenient to use them without the
+\namespace{Botan} prefix. You can do so by \keyword{using} the
+namespace \namespace{Botan::types} (this way you can use the type
+names without the namespace prefix, but the remainder of the library
+stays out of the global namespace). The included types are \type{byte}
+and \type{u32bit}, which are unsigned integer types.
+
+The headers for Botan are usually available in the form
+\filename{botan/headername.h}. For brevity in this documentation,
+headers are always just called \filename{headername.h}, but they
+should be used with the \filename{botan/} prefix in your actual code.
+
+\subsection{Initializing the Library}
+
+There is a set of core services that the library needs access to
+while it is performing requests. To ensure these are set up, you must
+create a \type{LibraryInitializer} object (usually called 'init' in
+Botan example code; 'botan\_library' or 'botan\_init' may make more
+sense in real applications) prior to making any calls to Botan. This
+object's lifetime must exceed that of all other Botan objects your
+application creates; for this reason the best place to create the
+\type{LibraryInitializer} is at the start of your \function{main}
+function, since this guarantees that it will be created first and
+destroyed last (via standard C++ RAII rules). The initializer does
+things like setting up the memory allocation system and algorithm
+lookup tables, finding out if there is a high resolution timer
+available to use, and similar such matters. With no arguments, the
+library is initialized with various default settings. So most of the
+time (unless you are writing threaded code; see below), all you need
+is:
+
+\texttt{Botan::LibraryInitializer init;}
+
+at the start of your \texttt{main}.
+
+The constructor takes an optional string that specifies arguments.
+Currently the only possible argument is ``thread\_safe'', which must
+have an Boolean argument (for instance ``thread\_safe=false'' or
+``thread\_safe=true''). If ``thread\_safe'' is specified as true the
+library will attempt to register a mutex type to properly guard access
+to shared resources. However these locks do not protect individual
+Botan objects: explicit locking must be used in this case.
+
+If you do not create a \type{LibraryInitializer} object, pretty much
+any Botan operation will fail, because it will be unable to do basic
+things like allocate memory or get random bits. Note too, that you
+should be careful to only create one such object.
+
+It is not strictly necessary to create a \type{LibraryInitializer};
+the actual code performing the initialization and shutdown are in
+static member functions of \type{LibraryInitializer}, called
+\function{initialize} and \function{deinitialize}. A
+\type{LibraryInitializer} merely provides a convenient RAII wrapper
+for the operations (thus for the internal library state as well).
+
+\subsection{Pitfalls}
+
+There are a few things to watch out for to prevent problems when using Botan.
+
+Never allocate any kind of Botan object globally. The problem with
+doing this is that the constructor for such an object will be called
+before the library is initialized. Many Botan objects will, in their
+constructor, make one or more calls into the library global state
+object. Access to this object is checked, so an exception should be
+thrown (rather than a memory access violation or undetected
+uninitialized object access). A rough equivalent that will work is to
+keep a global pointer to the object, initializing it after creating
+your \type{LibraryInitializer}. Merely making the
+\type{LibraryInitializer} also global will probably not help, because
+C++ does not make very strong guarantees about the order that such
+objects will be created.
+
+The same rule applies for making sure the destructors of all your
+Botan objects are called before the \type{LibraryInitializer} is
+destroyed. This implies you can't have static variables that are Botan
+objects inside functions or classes (since in most C++ runtimes, these
+objects will be destroyed after main has returned). This is inelegant,
+but seems to not cause many problems in practice.
+
+Botan's memory object classes (\type{MemoryVector},
+\type{SecureVector}, \type{SecureBuffer}) are extremely primitive, and
+do not (currently) meet the requirements for an STL container
+object. After Botan starts adopting C++0x features, they will be
+replaced by typedefs of \type{std::vector} with a custom allocator.
+
+Use a \function{try}/\function{catch} block inside your
+\function{main} function, and catch any \type{std::exception} throws
+(remember to catch by reference, as \type{std::exception}'s
+\function{what} method is polymorphic). This is not strictly required,
+but if you don't, and Botan throws an exception, the runtime will call
+\function{std::terminate}, which usually calls \function{abort} or
+something like it, leaving you (or worse, a user of your application)
+wondering what went wrong.
+
+\subsection{Information Flow: Pipes and Filters}
+
+Many common uses of cryptography involve processing one or more
+streams of data (be it from sockets, files, or a hardware device).
+Botan provides services that make setting up data flows through
+various operations, such as compression, encryption, and base64
+encoding. Each of these operations is implemented in what are called
+\emph{filters} in Botan. A set of filters are created and placed into
+a \emph{pipe}, and information ``flows'' through the pipe until it
+reaches the end, where the output is collected for retrieval. If
+you're familiar with the Unix shell environment, this design will
+sound quite familiar.
+
+Here is an example that uses a pipe to base64 encode some strings:
+
+\begin{verbatim}
+ Pipe pipe(new Base64_Encoder); // pipe owns the pointer
+ pipe.start_msg();
+ pipe.write(``message 1'');
+ pipe.end_msg(); // flushes buffers, increments message number
+
+ // process_msg(x) is start_msg() && write(x) && end_msg()
+ pipe.process_msg(``message2'');
+
+ std::string m1 = pipe.read_all_as_string(0); // ``message1''
+ std::string m2 = pipe.read_all_as_string(1); // ``message2''
+\end{verbatim}
+
+Bytestreams in the pipe are grouped into messages; blocks of data that
+are processed in an identical fashion (\ie, with the same sequence of
+\type{Filter}s). Messages are delimited by calls to
+\function{start\_msg} and \function{end\_msg}. Each message in a pipe
+has its own identifier, which currently is an integer that increments
+up from zero.
+
+As you can see, the \type{Base64\_Encoder} was allocated using
+\keyword{new}; but where was it deallocated? When a filter object is
+passed to a \type{Pipe}, the pipe takes ownership of the object, and
+will deallocate it when it is no longer needed.
+
+There are two different ways to make use of messages. One is to send
+several messages through a \type{Pipe} without changing the
+\type{Pipe}'s configuration, so you end up with a sequence of
+messages; one use of this would be to send a sequence of identically
+encrypted UDP packets, for example (note that the \emph{data} need not
+be identical; it is just that each is encrypted, encoded, signed, etc
+in an identical fashion). Another is to change the filters that are
+used in the \type{Pipe} between each message, by adding or removing
+\type{Filter}s; functions that let you do this are documented in the
+Pipe API section.
+
+Most operations in Botan have a corresponding filter for use in Pipe.
+Here's code that encrypts a string with AES-128 in CBC mode:
+
+\begin{verbatim}
+ AutoSeeded_RNG rng,
+ SymmetricKey key(rng, 16); // a random 128-bit key
+ InitializationVector iv(rng, 16); // a random 128-bit IV
+
+ // Notice the algorithm we want is specified by a string
+ Pipe pipe(get_cipher(``AES-128/CBC'', key, iv, ENCRYPTION));
+
+ pipe.process_msg(``secrets'');
+ pipe.process_msg(``more secrets'');
+
+ MemoryVector<byte> c1 = pipe.read_all(0);
+
+ byte c2[4096] = { 0 };
+ u32bit got_out = pipe.read(c2, sizeof(c2), 1);
+ // use c2[0...got_out]
+\end{verbatim}
+
+Note the use of \type{AutoSeeded\_RNG}, which is a random number
+generator. If you want to, you can explicitly set up the random number
+generators and entropy sources you want to, however for 99\% of cases
+\type{AutoSeeded\_RNG} is preferable.
+
+\type{Pipe} also has convenience methods for dealing with
+\type{std::iostream}s. Here is an example of those, using the
+\type{Bzip\_Compression} filter (included as a module; if you have
+bzlib available, check \filename{building.pdf} for how to enable it)
+to compress a file:
+
+\begin{verbatim}
+ std::ifstream in(``data.bin'', std::ios::binary)
+ std::ofstream out(``data.bin.bz2'', std::ios::binary)
+
+ Pipe pipe(new Bzip_Compression);
+
+ pipe.start_msg();
+ in >> pipe;
+ pipe.end_msg();
+ out << pipe;
+\end{verbatim}
+
+However there is a hitch to the code above; the complete contents of
+the compressed data will be held in memory until the entire message
+has been compressed, at which time the statement \verb|out << pipe| is
+executed, and the data is freed as it is read from the pipe and
+written to the file. But if the file is very large, we might not have
+enough physical memory (or even enough virtual memory!) for that to be
+practical. So instead of storing the compressed data in the pipe for
+reading it out later, we divert it directly to the file:
+
+\begin{verbatim}
+ std::ifstream in(``data.bin'', std::ios::binary)
+ std::ofstream out(``data.bin.bz2'', std::ios::binary)
+
+ Pipe pipe(new Bzip_Compression, new DataSink_Stream(out));
+
+ pipe.start_msg();
+ in >> pipe;
+ pipe.end_msg();
+\end{verbatim}
+
+This is the first code we've seen so far that uses more than one
+filter in a pipe. The output of the compressor is sent to the
+\type{DataSink\_Stream}. Anything written to a \type{DataSink\_Stream}
+is written to a file; the filter produces no output. As soon as the
+compression algorithm finishes up a block of data, it will send it along,
+at which point it will immediately be written to disk; if you were to
+call \verb|pipe.read_all()| after \verb|pipe.end_msg()|, you'd get an
+empty vector out.
+
+Here's an example using two computational filters:
+
+\begin{verbatim}
+ AutoSeeded_RNG rng,
+ SymmetricKey key(rng, 32);
+ InitializationVector iv(rng, 16);
+
+ Pipe encryptor(get_cipher("AES/CBC/PKCS7", key, iv, ENCRYPTION),
+ new Base64_Encoder);
+
+ encryptor.start_msg();
+ file >> encryptor;
+ encryptor.end_msg(); // flush buffers, complete computations
+ std::cout << encryptor;
+\end{verbatim}
+
+\subsection{Fork}
+
+It is fairly common that you might receive some data and want to
+perform more than one operation on it (\ie, encrypt it with Serpent
+and calculate the SHA-256 hash of the plaintext at the same
+time). That's where \type{Fork} comes in. \type{Fork} is a filter that
+takes input and passes it on to \emph{one or more} \type{Filter}s
+that are attached to it. \type{Fork} changes the nature of the pipe
+system completely. Instead of being a linked list, it becomes a tree.
+
+Each \type{Filter} in the fork is given its own output buffer, and
+thus its own message. For example, if you had previously written two
+messages into a \type{Pipe}, then you start a new one with a
+\type{Fork} that has three paths of \type{Filter}'s inside it, you
+add three new messages to the \type{Pipe}. The data you put into the
+\type{Pipe} is duplicated and sent into each set of \type{Filter}s,
+and the eventual output is placed into a dedicated message slot in the
+\type{Pipe}.
+
+Messages in the \type{Pipe} are allocated in a depth-first manner. This is only
+interesting if you are using more than one \type{Fork} in a single \type{Pipe}.
+As an example, consider the following:
+
+\begin{verbatim}
+ Pipe pipe(new Fork(
+ new Fork(
+ new Base64_Encoder,
+ new Fork(
+ NULL,
+ new Base64_Encoder
+ )
+ ),
+ new Hex_Encoder
+ )
+ );
+\end{verbatim}
+
+In this case, message 0 will be the output of the first \type{Base64\_Encoder},
+message 1 will be a copy of the input (see below for how \type{Fork} interprets
+NULL pointers), message 2 will be the output of the second
+\type{Base64\_Encoder}, and message 3 will be the output of the
+\type{Hex\_Encoder}. As you can see, this results in message numbers being
+allocated in a top to bottom fashion, when looked at on the screen. However,
+note that there could be potential for bugs if this is not anticipated. For
+example, if your code is passed a \type{Filter}, and you assume it is a
+``normal'' one that only uses one message, your message offsets would be
+wrong, leading to some confusion during output.
+
+If Fork's first argument is a null pointer, but a later argument is
+not, then Fork will feed a copy of its input directly through. Here's
+a case where that is useful:
+
+\begin{verbatim}
+ // have std::string ciphertext, auth_code, key, iv, mac_key;
+
+ Pipe pipe(new Base64_Decoder,
+ get_cipher(``AES-128'', key, iv, DECRYPTION),
+ new Fork(
+ 0
+ new MAC_Filter(``HMAC(SHA-1)'', mac_key)
+ )
+ );
+
+ pipe.process_msg(ciphertext);
+ std::string plaintext = pipe.read_all_as_string(0);
+ SecureVector<byte> mac = pipe.read_all(1);
+
+ if(mac != auth_code)
+ error();
+\end{verbatim}
+
+Here we wanted to not only decrypt the message, but send the decrypted
+text through an additional computation, in order to compute the
+authentication code.
+
+Any \type{Filter}s that are attached to the \type{Pipe} after the
+\type{Fork} are implicitly attached onto the first branch created by
+the fork. For example, let's say you created this \type{Pipe}:
+
+\begin{verbatim}
+Pipe pipe(new Fork(new Hash_Filter("MD5"), new Hash_Filter("SHA-1")),
+ new Hex_Encoder);
+\end{verbatim}
+
+And then called \function{start\_msg}, inserted some data, then
+\function{end\_msg}. Then \arg{pipe} would contain two messages. The
+first one (message number 0) would contain the MD5 sum of the input in
+hex encoded form, and the other would contain the SHA-1 sum of the
+input in raw binary. However, it's much better to use a \type{Chain}
+instead.
+
+\subsubsection{Chain}
+
+A \type{Chain} filter creates a chain of \type{Filter}s and
+encapsulates them inside a single filter (itself). This allows a
+sequence of filters to become a single filter, to be passed into or
+out of a function, or to a \type{Fork} constructor.
+
+You can call \type{Chain}'s constructor with up to 4 \type{Filter*}s
+(they will be added in order), or with an array of \type{Filter*}s and
+a \type{u32bit} that tells \type{Chain} how many \type{Filter*}s are
+in the array (again, they will be attached in order). Here's the
+example from the last section, using chain instead of relying on the
+obscure rule that version used.
+
+\begin{verbatim}
+ Pipe pipe(new Fork(
+ new Chain(new Hash_Filter("MD5"), new Hex_Encoder),
+ new Hash_Filter("SHA-1")
+ )
+ );
+\end{verbatim}
+
+\subsection{The Pipe API}
+
+\subsubsection{Initializing Pipe}
+
+By default, \type{Pipe} will do nothing at all; any input placed into
+the \type{Pipe} will be read back unchanged. Obviously, this has
+limited utility, and presumably you want to use one or more
+\type{Filter}s to somehow process the data. First, you can choose a
+set of \type{Filter}s to initialize the \type{Pipe} via the
+constructor. You can pass it either a set of up to 4 \type{Filter*}s,
+or a pre-defined array and a length:
+
+\begin{verbatim}
+ Pipe pipe1(new Filter1(/*args*/), new Filter2(/*args*/),
+ new Filter3(/*args*/), new Filter4(/*args*/));
+ Pipe pipe2(new Filter1(/*args*/), new Filter2(/*args*/));
+
+ Filter* filters[5] = {
+ new Filter1(/*args*/), new Filter2(/*args*/), new Filter3(/*args*/),
+ new Filter4(/*args*/), new Filter5(/*args*/) /* more if desired... */
+ };
+ Pipe pipe3(filters, 5);
+\end{verbatim}
+
+This is by far the most common way to initialize a \type{Pipe}. However,
+occasionally a more flexible initialization strategy is necessary; this is
+supported by 4 member functions: \function{prepend}(\type{Filter*}),
+\function{append}(\type{Filter*}), \function{pop}(), and \function{reset}().
+These functions may only be used while the \type{Pipe} in question is not in
+use; that is, either before calling \function{start\_msg}, or after
+\function{end\_msg} has been called (and no new calls to \function{start\_msg}
+have been made yet).
+
+The function \function{reset}() simply removes all the \type{Filter}s
+that the \type{Pipe} is currently using~--~it is reset to an
+initialize, ``empty'' state. Any data that is being retained by the
+\type{Pipe} is retained after a \function{reset}(), and
+\function{reset}() does not affect the message numbers (discussed
+later).
+
+Calling \function{prepend} and \function{append} will either prepend
+or append the passed \type{Filter} object to the list of
+transformations. For example, if you \function{prepend} a
+\type{Filter} implementing encryption, and the \type{Pipe} already had
+a \type{Filter} that hex encoded the input, then the next set of
+input would be first encrypted, then hex encoded. Alternately, if you
+called \function{append}, then the input would be first be hex
+encoded, and then encrypted (which is not terribly useful in this
+particular example).
+
+Finally, calling \function{pop}() will remove the first transformation
+of the \type{Pipe}. Say we had called \function{prepend} to put an
+encryption \type{Filter} into a \type{Pipe}; calling \function{pop}()
+would remove this \type{Filter} and return the \type{Pipe} to its
+state before we called \function{prepend}.
+
+\subsubsection{Giving Data to a Pipe}
+
+Input to a \type{Pipe} is delimited into messages, which can be read from
+independently (\ie, you can read 5 bytes from one message, and then all of
+another message, without either read affecting any other messages). The
+messages are delimited by calls to \function{start\_msg} and
+\function{end\_msg}. In between these two calls, you can write data into a
+\type{Pipe}, and it will be processed by the \type{Filter}(s) that it
+contains. Writes at any other time are invalid, and will result in an
+exception.
+
+As to writing, you can call any of the functions called \function{write}(),
+that can take any of: a \type{byte[]}/\type{u32bit} pair, a
+\type{SecureVector<byte>}, a \type{std::string}, a \type{DataSource\&}, or a
+single \type{byte}.
+
+Sometimes, you may want to do only a single write per message. In this case,
+you can use the \function{process\_msg} series of functions, which start a
+message, write their argument into the \type{Pipe}, and then end the
+message. In this case you would not make any explicit calls to
+\function{start\_msg}/\function{end\_msg}. The version of \function{write}
+that takes a single \type{byte} is not supported by \function{process\_msg},
+but all the other variants are.
+
+\type{Pipe} can also be used with the \verb|>>| operator, and will accept a
+\type{std::istream}, (or on Unix systems with the \verb|fd_unix| module), a
+Unix file descriptor. In either case, the entire contents of the file will be
+read into the \type{Pipe}.
+
+\subsubsection{Getting Output from a Pipe}
+
+Retrieving the processed data from a \type{Pipe} is a bit more complicated, for
+various reasons. In particular, because \type{Pipe} will separate each message
+into a separate buffer, you have to be able to retrieve data from each message
+independently. Each of \type{Pipe}'s read functions has a final parameter that
+specifies what message to read from (as a 32-bit integer). If this parameter is
+set to \type{Pipe::DEFAULT\_MESSAGE}, it will read the current default message
+(\type{DEFAULT\_MESSAGE} is also the default value of this parameter). The
+parameter will not be mentioned in further discussion of the reading API, but
+it is always there (unless otherwise noted).
+
+Reading is done with a variety of functions. The most basic are \type{u32bit}
+\function{read}(\type{byte} \arg{out}[], \type{u32bit} \arg{len}) and
+\type{u32bit} \function{read}(\type{byte\&} \arg{out}). Each reads into
+\arg{out} (either up to \arg{len} bytes, or a single byte for the one taking a
+\type{byte\&}), and returns the total number of bytes read. There is a variant
+of these functions, all named \function{peek}, which performs the same
+operations, but does not remove the bytes from the message (reading is a
+destructive operation with a \type{Pipe}).
+
+There are also the functions \type{SecureVector<byte>} \function{read\_all}(),
+and \type{std::string} \function{read\_all\_as\_string}(), which return the
+entire contents of the message, either as a memory buffer, or a
+\type{std::string} (which is generally only useful if the \type{Pipe} has
+encoded the message into a text string, such as when a \type{Base64\_Encoder}
+is used).
+
+To determine how many bytes are left in a message, call \type{u32bit}
+\function{remaining}() (which can also take an optional message
+number). Finally, there are some functions for managing the default message
+number: \type{u32bit} \function{default\_msg}() will return the current default
+message, \type{u32bit} \function{message\_count}() will return the total number
+of messages (0...\function{message\_count}()-1), and
+\function{set\_default\_msg}(\type{u32bit} \arg{msgno}) will set a new default
+message number (which must be a valid message number for that \type{Pipe}). The
+ability to set the default message number is particularly important in the case
+of using the file output operations (\verb|<<| with a \type{std::ostream} or
+Unix file descriptor), because there is no way to specify it explicitly when
+using the output operator.
+
+\subsection{A Filter Example}
+
+Here is some code that takes one or more filenames in \arg{argv} and
+calculates the result of several hash functions for each file. The complete
+program can be found as \filename{hasher.cpp} in the Botan distribution. For
+brevity, most error checking has been removed.
+
+\begin{verbatim}
+ string name[3] = { "MD5", "SHA-1", "RIPEMD-160" };
+ Botan::Filter* hash[3] = {
+ new Botan::Chain(new Botan::Hash_Filter(name[0]),
+ new Botan::Hex_Encoder),
+ new Botan::Chain(new Botan::Hash_Filter(name[1]),
+ new Botan::Hex_Encoder),
+ new Botan::Chain(new Botan::Hash_Filter(name[2]),
+ new Botan::Hex_Encoder) };
+
+ Botan::Pipe pipe(new Botan::Fork(hash, COUNT));
+
+ for(u32bit j = 1; argv[j] != 0; j++)
+ {
+ ifstream file(argv[j]);
+ pipe.start_msg();
+ file >> pipe;
+ pipe.end_msg();
+ file.close();
+ for(u32bit k = 0; k != 3; k++)
+ {
+ pipe.set_default_msg(3*(j-1)+k);
+ cout << name[k] << "(" << argv[j] << ") = " << pipe << endl;
+ }
+ }
+\end{verbatim}
+
+
+\subsection{Filter Catalog}
+
+This section contains descriptions of every \type{Filter} included in
+the portable sections of Botan. \type{Filter}s provided by modules
+are documented elsewhere.
+
+\subsubsection{Keyed Filters}
+
+A few sections ago, it was mentioned that \type{Pipe} can process multiple
+messages, treating each of them exactly the same. Well, that was a bit of a
+lie. There are some algorithms (in particular, block ciphers not in ECB mode,
+and all stream ciphers) that change their state as data is put through them.
+
+Naturally, you might well want to reset the keys or (in the case of block
+cipher modes) IVs used by such filters, so multiple messages can be processed
+using completely different keys, or new IVs, or new keys and IVs, or whatever.
+And in fact, even for a MAC or an ECB block cipher, you might well want to
+change the key used from message to message.
+
+Enter \type{Keyed\_Filter}, which acts as an abstract interface for
+any filter that is uses keys: block cipher modes, stream ciphers,
+MACs, and so on. It has two functions, \function{set\_key} and
+\function{set\_iv}. Calling \function{set\_key} will, naturally, set
+(or reset) the key used by the algorithm. Setting the IV only makes
+sense in certain algorithms -- a call to \function{set\_iv} on an
+object that doesn't support IVs will be ignored. You \emph{must} call
+\function{set\_key} before calling \function{set\_iv}: while not all
+\type{Keyed\_Filter} objects require this, you should assume it is
+required anytime you are using a \type{Keyed\_Filter}.
+
+Here's a example:
+
+\begin{verbatim}
+ Keyed_Filter *cast, *hmac;
+ Pipe pipe(new Base64_Decoder,
+ // Note the assignments to the cast and hmac variables
+ cast = new CBC_Decryption("CAST-128", "PKCS7", cast_key, iv),
+ new Fork(
+ 0, // Read the section 'Fork' to understand this
+ new Chain(
+ hmac = new MAC_Filter("HMAC(SHA-1)", mac_key, 12),
+ new Base64_Encoder
+ )
+ )
+ );
+ pipe.start_msg();
+ [use pipe for a while, decrypt some stuff, derive new keys and IVs]
+ pipe.end_msg();
+
+ cast->set_key(cast_key2);
+ cast->set_iv(iv2);
+ hmac->set_key(mac_key2);
+
+ pipe.start_msg();
+ [use pipe for some other things]
+ pipe.end_msg();
+\end{verbatim}
+
+There are some requirements to using \type{Keyed\_Filter} that you must
+follow. If you call \function{set\_key} or \function{set\_iv} on a filter that
+is owned by a \type{Pipe}, you must do so while the \type{Pipe} is
+``unlocked''. This refers to the times when no messages are being processed by
+\type{Pipe} -- either before \type{Pipe}'s \function{start\_msg} is called, or
+after \function{end\_msg} is called (and no new call to \function{start\_msg}
+has happened yet). Doing otherwise will result in undefined behavior, probably
+silently getting invalid output.
+
+And remember: if you're resetting both values, reset the key \emph{first}.
+
+\subsubsection{Cipher Filters}
+
+Getting a hold of a \type{Filter} implementing a cipher is very easy. Simply
+make sure you're including the header \filename{lookup.h}, and call
+\function{get\_cipher}. Generally you will pass the return value directly into
+a \type{Pipe}. There are actually a couple different functions, which do pretty
+much the same thing:
+
+\function{get\_cipher}(\type{std::string} \arg{cipher\_spec},
+ \type{SymmetricKey} \arg{key},
+ \type{InitializationVector} \arg{iv},
+ \type{Cipher\_Dir} \arg{dir});
+
+\function{get\_cipher}(\type{std::string} \arg{cipher\_spec},
+ \type{SymmetricKey} \arg{key},
+ \type{Cipher\_Dir} \arg{dir});
+
+The version that doesn't take an IV is useful for things that don't use them,
+like block ciphers in ECB mode, or most stream ciphers. If you specify a
+\arg{cipher\_spec} that does want a IV, and you use the version that doesn't
+take one, an exception will be thrown. The \arg{dir} argument can be either
+\type{ENCRYPTION} or \type{DECRYPTION}. In a few cases, like most (but not all)
+stream ciphers, these are equivalent, but even then it provides a way of
+showing the ``intent'' of the operation to readers of your code.
+
+The \arg{cipher\_spec} is a string that specifies what cipher is to be
+used. The general syntax for \arg{cipher\_spec} is ``STREAM\_CIPHER'',
+``BLOCK\_CIPHER/MODE'', or ``BLOCK\_CIPHER/MODE/PADDING''. In the case of
+stream ciphers, no mode is necessary, so just the name is sufficient. A block
+cipher requires a mode of some sort, which can be ``ECB'', ``CBC'', ``CFB(n)'',
+``OFB'', ``CTR-BE'', or ``EAX(n)''. The argument to CFB mode is how many bits
+of feedback should be used. If you just use ``CFB'' with no argument, it will
+default to using a feedback equal to the block size of the cipher. EAX mode
+also takes an optional bit argument, which tells EAX how large a tag size to
+use~--~generally this is the size of the block size of the cipher, which is the
+default if you don't specify any argument.
+
+In the case of the ECB and CBC modes, a padding method can also be
+specified. If it is not supplied, ECB defaults to not padding, and CBC defaults
+to using PKCS \#5/\#7 compatible padding. The padding methods currently
+available are ``NoPadding'', ``PKCS7'', ``OneAndZeros'', and ``CTS''. CTS
+padding is currently only available for CBC mode, but the others can also be
+used in ECB mode.
+
+Some example \arg{cipher\_spec} arguments are: ``DES/CFB(32)'',
+``TripleDES/OFB'', ``Blowfish/CBC/CTS'', ``SAFER-SK(10)/CBC/OneAndZeros'',
+``AES/EAX'', ``ARC4''
+
+``CTR-BE'' refers to counter mode where the counter is incremented as if it
+were a big-endian encoded integer. This is compatible with most other
+implementations, but it is possible some will use the incompatible little
+endian convention. This version would be denoted as ``CTR-LE'' if it were
+supported.
+
+``EAX'' is a new cipher mode designed by Wagner, Rogaway, and Bellare. It is an
+authenticated cipher mode (that is, no separate authentication is needed), has
+provable security, and is free from patent entanglements. It runs about half as
+fast as most of the other cipher modes (like CBC, OFB, or CTR), which is not
+bad considering you don't need to use an authentication code.
+
+\subsubsection{Hashes and MACs}
+
+Hash functions and MACs don't need anything special when it comes to
+filters. Both just take their input and produce no output until
+\function{end\_msg()} is called, at which time they complete the hash or MAC
+and send that as output.
+
+These \type{Filter}s take a string naming the type to be used. If for some
+reason you name something that doesn't exist, an exception will be thrown.
+
+\noindent
+\function{Hash\_Filter}(\type{std::string} \arg{hash},
+ \type{u32bit} \arg{outlength}):
+
+This type hashes its input with \arg{hash}. When \function{end\_msg} is called
+on the owning \type{Pipe}, the hash is completed and the digest is sent on to
+the next thing in the pipe. The argument \arg{outlength} specifies how much of
+the output of the hash will be passed along to the next filter when
+\function{end\_msg} is called. By default, it will pass the entire hash.
+
+Examples of names for \function{Hash\_Filter} are ``SHA-1'' and ``Whirlpool''.
+
+\noindent
+\function{MAC\_Filter}(\type{std::string} \arg{mac},
+ \type{const SymmetricKey\&} \arg{key},
+ \type{u32bit} \arg{outlength}):
+
+The constructor for a \type{MAC\_Filter} takes a key, used in calculating the
+MAC, and a length parameter, which has semantics exactly the same as the one
+passed to \type{Hash\_Filter}s constructor.
+
+Examples for \arg{mac} are ``HMAC(SHA-1)'', ``CMAC(AES-128)'', and the
+exceptionally long, strange, and probably useless name
+``CMAC(Lion(Tiger(20,3),MARK-4,1024))''.
+
+\subsubsection{PK Filters}
+
+There are four classes in this category, \type{PK\_Encryptor\_Filter},
+\type{PK\_Decryptor\_Filter}, \type{PK\_Signer\_Filter}, and
+\type{PK\_Verifier\_Filter}. Each takes a pointer to an object of the
+appropriate type (\type{PK\_Encryptor}, \type{PK\_Decryptor}, etc) that is
+deleted by the destructor. These classes are found in \filename{pk\_filts.h}.
+
+Three of these, for encryption, decryption, and signing are pretty much
+identical conceptually. Each of them buffers its input until the end of the
+message is marked with a call to the \function{end\_msg} function. Then they
+encrypt, decrypt, or sign their input and send the output (the ciphertext, the
+plaintext, or the signature) into the next filter.
+
+Signature verification works a little differently, because it needs to know
+what the signature is in order to check it. You can either pass this in along
+with the constructor, or call the function \function{set\_signature} -- with
+this second method, you need to keep a pointer to the filter around so you can
+send it this command. In either case, after \function{end\_msg} is called, it
+will try to verify the signature (if the signature has not been set by either
+method, an exception will be thrown here). It will then send a single byte onto
+the next filter -- a 1 or a 0, which specifies whether the signature verified
+or not (respectively).
+
+For more information about PK algorithms (including creating the appropriate
+objects to pass to the constructors), read the section ``Public Key
+Cryptography'' in this manual.
+
+\subsubsection{Encoders}
+
+Often you want your data to be in some form of text (for sending over channels
+that aren't 8-bit clean, printing it, etc). The filters \type{Hex\_Encoder}
+and \type{Base64\_Encoder} will convert arbitrary binary data into hex or
+base64 formats. Not surprisingly, you can use \type{Hex\_Decoder} and
+\type{Base64\_Decoder} to convert it back into its original form.
+
+Both of the encoders can take a few options about how the data should be
+formatted (all of which have defaults). The first is a \type{bool} which simply
+says if the encoder should insert line breaks. This defaults to
+false. Line breaks don't matter either way to the decoder, but it makes the
+output a bit more appealing to the human eye, and a few transport mechanisms
+(notably some email systems) limit the maximum line length.
+
+The second encoder option is an integer specifying how long such lines will be
+(obviously this will be ignored if line-breaking isn't being used). The default
+tends to be in the range of 60-80 characters, but is not specified exactly. If
+you want a specific value, set it. Otherwise the default should be fine.
+
+Lastly, \type{Hex\_Encoder} takes an argument of type \type{Case}, which can be
+\type{Uppercase} or \type{Lowercase} (default is \type{Uppercase}). This
+specifies what case the characters A-F should be output as. The base64 encoder
+has no such option, because it uses both upper and lower case letters for its
+output.
+
+The decoders both take a single option, which tells it how the object should
+behave in the case of invalid input. The enum (called \type{Decoder\_Checking})
+can take on any of three values: \type{NONE}, \type{IGNORE\_WS}, and
+\type{FULL\_CHECK}. With \type{NONE} (the default, for compatibility with
+previous releases), invalid input (for example, a ``z'' character in supposedly
+hex input) will simply be ignored. With \type{IGNORE\_WS}, whitespace will be
+ignored by the decoder, but receiving other non-valid data will raise an
+exception. Finally, \type{FULL\_CHECK} will raise an exception for \emph{any}
+characters not in the encoded character set, including whitespace.
+
+You can find the declarations for these types in \filename{hex.h} and
+\filename{base64.h}.
+
+\subsection{Rolling Your Own}
+
+The system of filters and pipes was designed in an attempt to make it
+as simple as possible to write new \type{Filter} objects. There are
+essentially four functions that need to be implemented by an object
+deriving from \type{Filter}:
+
+\noindent
+\type{void} \function{write}(\type{byte} \arg{input}[], \type{u32bit}
+\arg{length}):
+
+The \function{write} function is what is called when a filter receives input
+for it to process. The filter is \emph{not} required to process it right away;
+many filters buffer their input before producing any output. A filter will
+usually have \function{write} called many times during its lifetime.
+
+\noindent
+\type{void} \function{send}(\type{byte} \arg{output}[], \type{u32bit}
+\arg{length}):
+
+Eventually, a filter will want to produce some output to send along to the next
+filter in the pipeline. It does so by calling \function{send} with whatever it
+wants to send along to the next filter. There is also a version of
+\function{send} taking a single byte argument, as a convenience.
+
+\noindent
+\type{void} \function{start\_msg()}:
+
+This function is optional. Implement it if your \type{Filter} would like to do
+some processing or setup at the start of each message (for an example, see the
+Zlib compression module).
+
+\noindent
+\type{void} \function{end\_msg()}:
+
+Implementing the \function{end\_msg} function is optional. It is called when it
+has been requested that filters finish up their computations. Note that they
+must \emph{not} deallocate their resources; this should be done by their
+destructor. They should simply finish up with whatever computation they have
+been working on (for example, a compressing filter would flush the compressor
+and \function{send} the final block), and empty any buffers in preparation for
+processing a fresh new set of input. It is essentially the inverse of
+\function{start\_msg}.
+
+Additionally, if necessary, filters can define a constructor that takes any
+needed arguments, and a destructor to deal with deallocating memory, closing
+files, etc.
+
+There is also a \type{BufferingFilter} class (in \filename{buf\_filt.h}) that
+will take a message and split it up into an initial block that can be of any
+size (including zero), a sequence of fixed sized blocks of any non-zero size,
+and last (possibly zero-sized) final block. This might make a useful base class
+for your filters, depending on what you have in mind.
+
+
+\pagebreak
+\section{Public Key Cryptography}
+
+Let's create a 1024-bit RSA private key, encode the public key as a
+PKCS \#1 file with PEM encoding (which can be understood by many other
+cryptographic programs)
+
+\begin{verbatim}
+// everyone does:
+AutoSeeded_RNG rng;
+
+// Alice
+RSA_PrivateKey priv_rsa(rng, 1024 /* bits */);
+
+std::string alice_pem = X509::PEM_encode(priv_rsa);
+
+// send alice_pem to Bob, who does
+
+// Bob
+std::auto_ptr<X509_PublicKey> alice(load_key(alice_pem));
+
+RSA_PublicKey* alice_rsa = dynamic_cast<RSA_PublicKey>(alice);
+if(alice_rsa)
+ {
+ /* ... */
+ }
+
+\end{verbatim}
+
+\subsection{Creating PK Algorithm Key Objects}
+
+The library has interfaces for encryption, signatures, etc that do not require
+knowing the exact algorithm in use (for example RSA and Rabin-Williams
+signatures are handled by the exact same code path).
+
+One place where we \emph{do} need to know exactly what kind of algorithm is in
+use is when we are creating a key (\emph{But}: read the section ``Importing and
+Exporting PK Keys'', later in this manual).
+
+There are (currently) two kinds of public key algorithms in Botan: ones based
+on integer factorization (RSA and Rabin-Williams), and ones based on the
+discrete logarithm problem (DSA, Diffie-Hellman, Nyberg-Rueppel, and
+ElGamal). Since discrete logarithm parameters (primes and generators) can be
+shared among many keys, there is the notion of these being a combined type
+(called \type{DL\_Group}).
+
+There are two ways to create a DL private key (such as
+\type{DSA\_PrivateKey}). One is to pass in just a \type{DL\_Group} object -- a
+new key will automatically be generated. The other involves passing in a group
+to use, along with both the public and private values (private value first).
+
+Since in integer factorization algorithms, the modulus used isn't shared by
+other keys, we don't use this notion. You can create a new key by passing in a
+\type{u32bit} telling how long (in bits) the key should be, or you can copy an
+pre-existing key by passing in the appropriate parameters (primes, exponents,
+etc). For RSA and Rabin-Williams (the two IF schemes in Botan), the parameters
+are all \type{BigInt}s: prime 1, prime 2, encryption exponent, decryption
+exponent, modulus. The last two are optional, since they can easily be derived
+from the first three.
+
+\subsubsection{Creating a DL\_Group}
+
+There are quite a few ways to get a \type{DL\_Group} object. The best is to use
+the function \function{get\_dl\_group}, which takes a string naming a group; it
+will either return that group, if it knows about it, or throw an
+exception. Names it knows about include ``IETF-n'' where n is 768, 1024, 1536,
+2048, 3072, or 4096, and ``DSA-n'', where n is 512, 768, or 1024. The IETF
+groups are the ones specified for use with IPSec, and the DSA ones are the
+default DSA parameters specified by Java's JCE. For DSA and Nyberg-Rueppel, you
+should only use the ``DSA-n'' groups, while Diffie-Hellman and ElGamal can use
+either type (keep in mind that some applications/standards require DH/ELG to
+use DSA-style primes, while others require strong prime groups).
+
+You can also generate a new random group. This is not recommend, because it is
+quite slow, especially for safe primes.
+
+\subsection{Key Checking}
+
+Most public key algorithms have limitations or restrictions on their
+parameters. For example RSA requires an odd exponent, and algorithms based on
+the discrete logarithm problem need a generator $> 1$.
+
+Each low-level public key type has a function named \function{check\_key} that
+takes a \type{bool}. This function returns a Boolean value that declares
+whether or not the key is valid (from an algorithmic standpoint). For example,
+it will check to make sure that the prime parameters of a DSA key are, in fact,
+prime. It does not have anything to do with the validity of the key for any
+particular use, nor does it have anything to do with certificates that link a
+key (which, after all, is just some numbers) with a user or other entity. If
+\function{check\_key}'s argument is \type{true}, then it does ``strong''
+checking, which includes fairly expensive operations like primality checking.
+
+Keys are always checked when they are loaded or generated, so typically there
+is no reason to use this function directly. However, you can disable or reduce
+the checks for particular cases (public keys, loaded private keys, generated
+private keys) by setting the right config toggle (see the section on the
+configuration subsystem for details).
+
+\subsection{Getting a PK algorithm object}
+
+The key types, like \type{RSA\_PrivateKey}, do not implement any kind
+of padding or encoding (which is generally necessary for security). To
+get an object like this, the easiest thing to do is call the functions
+found in \filename{look\_pk.h}. Generally these take a key, followed
+by a string that specified what hashing and encoding method(s) to
+use. Examples of such strings are ``EME1(SHA-256)'' for OAEP
+encryption and ``EMSA4(SHA-256)'' for PSS signatures (where the
+message is hashed using SHA-256).
+
+Here are some basic examples (using an RSA key) to give you a feel for the
+possibilities. These examples assume \type{rsakey} is an
+\type{RSA\_PrivateKey}, since otherwise we would not be able to create a
+decryption or signature object with it (you can create encryption or signature
+verification objects with public keys, naturally). Remember to delete these
+objects when you're done with them.
+
+\begin{verbatim}
+ // PKCS #1 v2.0 / IEEE 1363 compatible encryption
+ PK_Encryptor* rsa_enc1 = get_pk_encryptor(rsakey, "EME1(RIPEMD-160)");
+ // PKCS #1 v1.5 compatible encryption
+ PK_Encryptor* rsa_enc2 = get_pk_encryptor(rsakey, "PKCS1v15");
+
+ // Raw encryption: no padding, input is directly encrypted by the key
+ // Don't use this unless you know what you're doing
+ PK_Encryptor* rsa_enc3 = get_pk_encryptor(rsakey, "Raw");
+
+ // This object can decrypt things encrypted by rsa_enc1
+ PK_Decryptor* rsa_dec1 = get_pk_decryptor(rsakey, "EME1(RIPEMD-160)");
+
+ // PKCS #1 v1.5 compatible signatures
+ PK_Signer* rsa_sig = get_pk_signer(rsakey, "EMSA3(MD5)");
+ PK_Verifier* rsa_verify = get_pk_verifier(rsakey, "EMSA3(MD5)");
+
+ // PKCS #1 v2.1 compatible signatures
+ PK_Signer* rsa_sig2 = get_pk_signer(rsakey, "EMSA4(SHA-1)");
+ PK_Verifier* rsa_verify2 = get_pk_verifier(rsakey, "EMSA4(SHA-1)");
+
+ // Hash input with SHA-1, but don't pad the input in any way; usually
+ // used with DSA/NR, not RSA
+ PK_Signer* rsa_sig = get_pk_signer(rsakey, "EMSA1(SHA-1)");
+\end{verbatim}
+
+\subsection{Encryption}
+
+The \type{PK\_Encryptor} and \type{PK\_Decryptor} classes are the interface for
+encryption and decryption, respectively.
+
+Calling \function{encrypt} with a \type{byte} array, a length
+parameter, and an RNG object will return the input encrypted with
+whatever scheme is being used. Calling the similar \function{decrypt}
+will perform the inverse operation. You can also do these operations
+with \type{SecureVector<byte>}s. In all cases, the output is returned
+via a \type{SecureVector<byte>}.
+
+If you attempt an operation with a larger size than the key can
+support (this limit varies based on the algorithm, the key size, and
+the padding method used (if any)), an exception will be
+thrown. Alternately, you can call \function{maximum\_input\_size},
+that will return the maximum size you can safely encrypt. In fact,
+you can often encrypt an object that is one byte longer, but only if
+enough of the high bits of the leading byte are set to zero. Since
+this is pretty dicey, it's best to stick with the advertised maximum.
+
+Available public key encryption algorithms in Botan are RSA and ElGamal. The
+encoding methods are EME1, denoted by ``EME1(HASHNAME)'', PKCS \#1 v1.5,
+called ``PKCS1v15'' or ``EME-PKCS1-v1\_5'', and raw encoding (``Raw'').
+
+For compatibility reasons, PKCS \#1 v1.5 is recommend for use with
+ElGamal (most other implementations of ElGamal do not support any
+other encoding format). RSA can also be used with PKCS \# 1 encoding,
+but because of various possible attacks, EME1 is the preferred
+encoding. EME1 requires the use of a hash function: unless a competent
+applied cryptographer tells you otherwise, you should use SHA-256 or
+SHA-512.
+
+Don't use ``Raw'' encoding unless you need it for backward
+compatibility with old protocols. There are many possible attacks
+against both ElGamal and RSA when they are used in this way.
+
+\subsection{Signatures}
+
+The signature algorithms look quite a bit like the hash functions. You
+can repeatedly call \function{update}, giving more and more of a
+message you wish to sign, and then call \function{signature}, which
+will return a signature for that message. If you want to do it all in
+one shot, call \function{sign\_message}, which will just call
+\function{update} with its argument and then return whatever
+\function{signature} returns. Generating a signature requires random
+numbers with some schemes, so \function{signature} and
+\function{sign\_message} both take a \type{RandomNumberGenerator\&}.
+
+You can validate a signature by updating the verifier class, and finally seeing
+the if the value returned from \function{check\_signature} is true (you pass
+the supposed signature to the \function{check\_signature} function as a byte
+array and a length or as a \type{MemoryRegion<byte>}). There is another
+function, \function{verify\_message}, which takes a pair of byte array/length
+pairs (or a pair of \type{MemoryRegion<byte>} objects), the first of which is
+the message, the second being the (supposed) signature. It returns true if the
+signature is valid and false otherwise.
+
+Available public key signature algorithms in Botan are RSA, DSA,
+Nyberg-Rueppel, and Rabin-Williams. Signature encoding methods include EMSA1,
+EMSA2, EMSA3, EMSA4, and Raw. All of them, except Raw, take a parameter naming
+a message digest function to hash the message with. Raw actually signs the
+input directly; if the message is too big, the signing operation will fail. Raw
+is not useful except in very specialized applications.
+
+There are various interactions that make certain encoding schemes and signing
+algorithms more or less useful.
+
+EMSA2 is the usual method for encoding Rabin-William signatures, so for
+compatibility with other implementations you may have to use that. EMSA4 (also
+called PSS), also works with Rabin-Williams. EMSA1 and EMSA3 do \emph{not} work
+with Rabin-Williams.
+
+RSA can be used with any of the available encoding methods. EMSA4 is by far the
+most secure, but is not (as of now) widely implemented. EMSA3 (also called
+``EMSA-PKCS1-v1\_5'') is commonly used with RSA (for example in SSL). EMSA1
+signs the message digest directly, without any extra padding or encoding. This
+may be useful, but is not as secure as either EMSA3 or EMSA4. EMSA2 may be used
+but is not recommended.
+
+For DSA and Nyberg-Rueppel, you should use EMSA1. None of the other encoding
+methods are particularly useful for these algorithms.
+
+\subsection{Key Agreement}
+
+You can get a hold of a \type{PK\_Key\_Agreement\_Scheme} object by calling
+\function{get\_pk\_kas} with a key that is of a type that supports key
+agreement (such as a Diffie-Hellman key stored in a \type{DH\_PrivateKey}
+object), and the name of a key derivation function. This can be ``Raw'',
+meaning the output of the primitive itself is returned as the key, or
+``KDF1(hash)'' or ``KDF2(hash)'' where ``hash'' is any string you happen to
+like (hopefully you like strings like ``SHA-256'' or ``RIPEMD-160''), or
+``X9.42-PRF(keywrap)'', which uses the PRF specified in ANSI X9.42. It takes
+the name or OID of the key wrap algorithm that will be used to encrypt a
+content encryption key.
+
+How key agreement generally works is that you trade public values with some
+other party, and then each of you runs a computation with the other's value and
+your key (this should return the same result to both parties). This computation
+can be called by using \function{derive\_key} with either a byte array/length
+pair, or a \type{SecureVector<byte>} than holds the public value of the other
+party. The last argument to either call is a number that specifies how long a
+key you want.
+
+Depending on the key derivation function you're using, you many not
+\emph{actually} get back a key of that size. In particular, ``Raw'' will return
+a number about the size of the Diffie-Hellman modulus, and KDF1 can only return
+a key that is the same size as the output of the hash. KDF2, on the other
+hand, will always give you a key exactly as long as you request, regardless of
+the underlying hash used with it. The key returned is a \type{SymmetricKey},
+ready to pass to a block cipher, MAC, or other symmetric algorithm.
+
+The public value that should be used can be obtained by calling
+\function{public\_data}, which exists for any key that is associated with a
+key agreement algorithm. It returns a \type{SecureVector<byte>}.
+
+``KDF2(SHA-256)'' is by far the preferred algorithm for key derivation
+in new applications. The X9.42 algorithm may be useful in some
+circumstances, but unless you need X9.42 compatibility, KDF2 is easier
+to use.
+
+There is a Diffie-Hellman example included in the distribution, which you may
+want to examine.
+
+\subsection{Importing and Exporting PK Keys}
+
+[This section mentions \type{Pipe} and \type{DataSource}, which is not covered
+until later in the manual. Please read those sections for more about
+\type{Pipe} and \type{DataSource} and their uses.]
+
+There are many, many different (often conflicting) standards surrounding public
+key cryptography. There is, thankfully, only two major standards surrounding
+the representation of a public or private key: X.509 (for public keys), and
+PKCS \#8 (for private keys). Other crypto libraries, like OpenSSL and B-SAFE,
+also support these formats, so you can easily exchange keys with software that
+doesn't use Botan.
+
+In addition to ``plain'' public keys, Botan also supports X.509 certificates.
+These are documented in the section ``Certificate Handling'', later in this
+manual.
+
+\subsubsection{Public Keys}
+
+The interfaces for doing either of these are quite similar. Let's look at the
+X.509 stuff first:
+\begin{verbatim}
+namespace X509 {
+ void encode(const X509_PublicKey& key, Pipe& out, X509_Encoding enc = PEM);
+ std::string PEM_encode(const X509_PublicKey& out);
+
+ X509_PublicKey* load_key(DataSource& in);
+ X509_PublicKey* load_key(const std::string& file);
+ X509_PublicKey* load_key(const SecureVector<byte>& buffer);
+}
+\end{verbatim}
+
+Basically, \function{X509::encode} will take an \type{X509\_PublicKey}
+(as of now, that's any RSA, DSA, or Diffie-Hellman key) and encodes it
+using \arg{enc}, which can be either \type{PEM} or
+\type{RAW\_BER}. Using \type{PEM} is \emph{highly} recommended for
+many reasons, including compatibility with other software, for
+transmission over 8-bit unclean channels, because it can be identified
+by a human without special tools, and because it sometimes allows more
+sane behavior of tools that process the data. It will place the
+encoding into \arg{out}. Remember that if you have just created the
+\type{Pipe} that you are passing to \function{X509::encode}, you need
+to call \function{start\_msg} first. Particularly with public keys,
+about 99\% of the time you just want to PEM encode the key and then
+write it to a file or something. In this case, it's probably easier to
+use \function{X509::PEM\_encode}. This function will simply return the
+PEM encoding of the key as a \type{std::string}.
+
+For loading a public key, the preferred method is one of the variants
+of \function{load\_key}. This function will return a newly allocated
+key based on the data from whatever source it is using (assuming, of
+course, the source is in fact storing a representation of a public
+key). The encoding used (PEM or BER) need not be specified; the format
+will be detected automatically. The key is allocated with
+\function{new}, and should be released with \function{delete} when you
+are done with it. The first takes a generic \type{DataSource} that
+you have to allocate~--~the others are simple wrapper functions that
+take either a filename or a memory buffer.
+
+So what can you do with the return value of \function{load\_key}? On
+its own, a \type{X509\_PublicKey} isn't particularly useful; you can't
+encrypt messages or verify signatures, or much else. But, using
+\function{dynamic\_cast}, you can figure out what kind of operations
+the key supports. Then, you can cast the key to the appropriate type
+and pass it to a higher-level class. For example:
+
+\begin{verbatim}
+ /* Might be RSA, might be ElGamal, might be ... */
+ X509_PublicKey* key = X509::load_key("pubkey.asc");
+ /* You MUST use dynamic_cast to convert, because of virtual bases */
+ PK_Encrypting_Key* enc_key = dynamic_cast<PK_Encrypting_Key*>(key);
+ if(!enc_key)
+ throw Some_Exception();
+ PK_Encryptor* enc = get_pk_encryptor(*enc_key, "EME1(SHA-256)");
+ SecureVector<byte> cipher = enc->encrypt(some_message, size_of_message);
+\end{verbatim}
+
+\subsubsection{Private Keys}
+
+There are two different options for private key import/export. The first is a
+plaintext version of the private key. This is supported by the following
+functions:
+
+\begin{verbatim}
+namespace PKCS8 {
+ void encode(const PKCS8_PrivateKey& key, Pipe& to, X509_Encoding enc = PEM);
+
+ std::string PEM_encode(const PKCS8_PrivateKey& key);
+}
+\end{verbatim}
+
+These functions are basically the same as the X.509 functions described
+previously. The only difference is that they take a \type{PKCS8\_PrivateKey}
+type (which, again, can be either RSA, DSA, or Diffie-Hellman, but this time
+the key must be a private key). In most situations, using these is a bad idea,
+because anyone can come along and grab the private key without having to know
+any passwords or other secrets. Unless you have very particular security
+requirements, always use the versions that encrypt the key based on a
+passphrase. For importing, the same functions can be used for encrypted and
+unencrypted keys.
+
+The other way to export a PKCS \#8 key is to first encode it in the same manner
+as done above, then encrypt it (using a passphrase and the techniques of PKCS
+\#5), and store the whole thing into another structure. This method is
+definitely preferred, since otherwise the private key is unprotected. The
+following functions support this technique:
+
+\begin{verbatim}
+namespace PKCS8 {
+ void encrypt_key(const PKCS8_PrivateKey& key, Pipe& out,
+ std::string passphrase, std::string pbe = "",
+ X509_Encoding enc = PEM);
+
+ std::string PEM_encode(const PKCS8_PrivateKey& key, std::string passphrase,
+ std::string pbe = "");
+}
+\end{verbatim}
+
+To export an encrypted private key, call \function{PKCS8::encrypt\_key}. The
+\arg{key}, \arg{out}, and \arg{enc} arguments are similar in usage to the ones
+for \function{PKCS8::encode}. As you might notice, there are two new arguments
+for \function{PKCS8::encrypt\_key}, however. The first is a passphrase (which
+you presumably got from a user somehow). This will be used to encrypt the key.
+The second new argument is \arg{pbe}; this specifies a particular password
+based encryption (or PBE) algorithm.
+
+The \function{PEM\_encode} version shown here is similar to the one that
+doesn't take a passphrase. Essentially it encrypts the key (using the default
+PBE algorithm), and then returns a C++ string with the PEM encoding of the key.
+
+If \arg{pbe} is blank, then the default algorithm (controlled by the
+``base/default\_pbe'' option) will be used. As shipped, this default is
+``PBE-PKCS5v20(SHA-1,TripleDES/CBC)'' . This is among the more secure options
+of PKCS \#5, and is widely supported among implementations of PKCS \#5 v2.0. It
+offers 168 bits of security against attacks, which should be more that
+sufficient. If you need compatibility with systems that only support PKCS \#5
+v1.5, pass ``PBE-PKCS5v15(MD5,DES/CBC)'' as \arg{pbe}. However, be warned that
+this PBE algorithm only has 56 bits of security against brute force attacks. As
+of 1.4.5, all three keylengths of AES are also available as options, which can
+be used with by specifying a PBE algorithm of
+``PBE-PKCS5v20(SHA-1,AES-256/CBC)'' (or ``AES-128'' or ``AES-192''). Support
+for AES is slightly non-standard, and some applications or libraries might not
+handle it. It is known that OpenSSL (0.9.7 and later) do handle AES for private
+key encryption.
+
+There may be some strange programs out there that support the v2.0 extensions
+to PBES1 but not PBES2; if you need to inter-operate with a program like that,
+use ``PBE-PKCS5v15(MD5,RC2/CBC)''. For example, OpenSSL supports this format
+(though since it also supports the v2.0 schemes, there is no reason not to just
+use TripleDES or AES). This scheme uses a 64-bit key that, while
+significantly better than a 56-bit key, is a bit too small for comfort.
+
+Last but not least, there are some functions that are basically identical to
+\function{X509::load\_key} that will load, and possibly decrypt, a PKCS \#8
+private key:
+
+\begin{verbatim}
+namespace PKCS8 {
+ PKCS8_PrivateKey* load_key(DataSource& in,
+ RandomNumberGenerator& rng,
+ const User_Interface& ui);
+ PKCS8_PrivateKey* load_key(DataSource& in,
+ RandomNumberGenerator& rng,
+ std::string passphrase = "");
+
+ PKCS8_PrivateKey* load_key(const std::string& filename,
+ RandomNumberGenerator& rng,
+ const User_Interface& ui);
+ PKCS8_PrivateKey* load_key(const std::string& filename,
+ RandomNumberGenerator& rng,
+ const std::string& passphrase = "");
+}
+\end{verbatim}
+
+The versions that take \type{std::string} \arg{passphrase}s are primarily for
+compatibility, but they are useful in limited circumstances. The
+\type{User\_Interface} versions are how \function{load\_key} is actually
+implemented, and provides for much more flexibility. Essentially, if the
+passphrase given to the function is not correct, then an exception is thrown
+and that is that. However, if you pass in an UI object instead, then the UI
+object can keep asking the user for the passphrase until they get it right (or
+until they cancel the action, though the UI interface). A
+\type{User\_Interface} has very little to do with talking to users; it's just a
+way to glue together Botan and whatever user interface you happen to be
+using. You can think of it as a user interface interface. The default
+\type{User\_Interface} is actually very dumb, and effectively acts just like
+the versions taking the \type{std::string}.
+
+All versions need access to a \type{RandomNumberGenerator} in order to
+perform probabilistic tests on the loaded key material.
+
+After loading a key, you can use \function{dynamic\_cast} to find out what
+operations it supports, and use it appropriately. Remember to \function{delete}
+it once you are done with it.
+
+\subsubsection{Limitations}
+
+As of now Nyberg-Rueppel and Rabin-Williams keys cannot be imported or
+exported, because they have no official ASN.1 OID or definition. ElGamal keys
+can (as of Botan 1.3.8) be imported and exported, but the only other
+implementation that supports the format is Peter Gutmann's Cryptlib. If you
+can help it, stick to RSA and DSA.
+
+\emph{Note}: Currently NR and RW are given basic ASN.1 key formats (which
+mirror DSA and RSA, respectively), which means that, if they are assigned an
+OID, they can be imported and exported just as easily as RSA and DSA. You can
+assign them an OID by putting a line in a Botan configuration file, calling
+\function{OIDS::add\_oid}, or editing \filename{src/policy.cpp}. Be warned that
+it is possible that a future version will use a format that is different from
+the current one (\ie, a newly standardized format).
+
+\pagebreak
+\section{Certificate Handling}
+
+A certificate is essentially a binding between some identifying information of
+a person or other entity (called a \emph{subject}) and a public key. This
+binding is asserted by a signature on the certificate, which is placed there by
+some authority (the \emph{issuer}) that at least claims that it knows the
+subject named in the certificate really ``owns'' the private key
+corresponding to the public key in the certificate.
+
+The major certificate format in use today is X.509v3, designed by ISO and
+further hacked on by dozens (hundreds?) of other organizations.
+
+When working with certificates, the main class to remember is
+\type{X509\_Certificate}. You can read an object of this type, but you can't
+create one on the fly; a CA object is necessary for actually making a new
+certificate. So for the most part, you only have to worry about reading them
+in, verifying the signatures, and getting the bits of data in them (most
+commonly the public key, and the information about the user of that key). An
+X.509v3 certificate can contain a literally infinite number of items related to
+all kinds of things. Botan doesn't support a lot of them, simply because nobody
+uses them and they're an impossible mess to work with. This section only
+documents the most commonly used ones of the ones that are supported; for the
+rest, read \filename{x509cert.h} and \filename{asn1\_obj.h} (which has the
+definitions of various common ASN.1 constructs used in X.509).
+
+\subsection{So what's in an X.509 certificate?}
+
+Obviously, you want to be able to get the public key. This is achieved by
+calling the member function \function{subject\_public\_key}, which will return
+a \type{X509\_PublicKey*}. As to what to do with this, read about
+\function{load\_key} in the section ``Importing and Exporting PK Keys''. In the
+general case, this could be any kind of public key, though 99\% of the time it
+will be an RSA key. However, Diffie-Hellman and DSA keys are also supported, so
+be careful about how you treat this. It is also a wise idea to examine the
+value returned by \function{constraints}, to see what uses the public key is
+approved for.
+
+The second major piece of information you'll want is the name/email/etc of the
+person to whom this certificate is assigned. Here is where things get a little
+nasty. X.509v3 has two (well, mostly just two $\ldots$) different places where
+you can stick information about the user: the \emph{subject} field, and in an
+extension called \emph{subjectAlternativeName}. The \emph{subject} field is
+supposed to only included the following information: country, organization
+(possibly), an organizational sub-unit name (possibly), and a so-called common
+name. The common name is usually the name of the person, or it could be a title
+associated with a position of some sort in the organization. It may also
+include fields for state/province and locality. What exactly a locality is,
+nobody knows, but it's usually given as a city name.
+
+Botan doesn't currently support any of the Unicode variants used in ASN.1
+(UTF-8, UCS-2, and UCS-4), any of which could be used for the fields in the
+DN. This could be problematic, particularly in Asia and other areas where
+non-ASCII characters are needed for most names. The UTF-8 and UCS-2 string
+types \emph{are} accepted (in fact, UTF-8 is used when encoding much of the
+time), but if any of the characters included in the string are not in ISO
+8859-1 (\ie 0 \ldots 255), an exception will get thrown. Currently the
+\type{ASN1\_String} type holds its data as ISO 8859-1 internally (regardless
+of local character set); this would have to be changed to hold UCS-2 or UCS-4
+in order to support Unicode (also, many interfaces in the X.509 code would have
+to accept or return a \type{std::wstring} instead of a \type{std::string}).
+
+Like the distinguished names, subject alternative names can contain a lot of
+things that Botan will flat out ignore (most of which you would never actually
+want to use). However, there are three very useful pieces of information that
+this extension might hold: an email address (``person@site1.com''), a DNS name
+(``somehost.site2.com''), or a URI (``http://www.site3.com'').
+
+So, how to get the information? Simply call \function{subject\_info} with the
+name of the piece of information you want, and it will return a
+\type{std::string} that is either empty (signifying that the certificate
+doesn't have this information), or has the information requested. There are
+several names for each possible item, but the most easily readable ones are:
+``Name'', ``Country'', ``Organization'', ``Organizational Unit'', ``Locality'',
+``State'', ``RFC822'', ``URI'', and ``DNS''. These values are returned as a
+\type{std::string}.
+
+You can also get information about the issuer of the certificate in the same
+way, using \function{issuer\_info}.
+
+\subsubsection{X.509v3 Extensions}
+
+X.509v3 specifies a large number of possible extensions. Botan supports some,
+but by no means all of them. This section lists which ones are supported, and
+notes areas where there may be problems with the handling. You have to be
+pretty familiar with X.509 in order to understand what this is talking about.
+
+\begin{list}{$\cdot$}
+ \item Key Usage and Extended Key Usage: No problems known.
+ \item
+
+ \item Basic Constraints: No problems known. The default for a v1/v2
+ certificate is assume it's a CA if and only if the option
+ ``x509/default\_to\_ca'' is set. A v3 certificate is marked as a CA if
+ (and only if) the basic constraints extension is present and set for a
+ CA cert.
+
+ \item Subject Alternative Names: Only the ``rfc822Name'', ``dNSName'', and
+ ``uniformResourceIdentifier'' fields will be stored; all others are
+ ignored.
+
+ \item Issuer Alternative Names: Same restrictions as the Subject Alternative
+ Names extension. New certificates generated by Botan never include the
+ issuer alternative name.
+
+ \item Authority Key Identifier: Only the version using KeyIdentifier is
+ supported. If the GeneralNames version is used and the extension is
+ critical, an exception is thrown. If both the KeyIdentifier and
+ GeneralNames versions are present, then the KeyIdentifier will be
+ used, and the GeneralNames ignored.
+
+ \item Subject Key Identifier: No problems known.
+\end{list}
+
+\subsubsection{Revocation Lists}
+
+It will occasionally happen that a certificate must be revoked before its
+expiration date. Examples of this happening include the private key being
+compromised, or the user to which it has been assigned leaving an
+organization. Certificate revocation lists are an answer to this problem
+(though online certificate validation techniques are starting to become
+somewhat more popular). Essentially, every once in a while the CA will release
+a CRL, listing all certificates that have been revoked. Also included is
+various pieces of information like what time a particular certificate was
+revoked, and for what reason. In most systems, it is wise to support some form
+of certificate revocation, and CRLs handle this fairly easily.
+
+For most users, processing a CRL is quite easy. All you have to do is call the
+constructor, which will take a filename (or a \type{DataSource\&}). The CRLs
+can either be in raw BER/DER, or in PEM format; the constructor will figure out
+which format without any extra information. For example:
+
+\begin{verbatim}
+ X509_CRL crl1("crl1.der");
+
+ DataSource_Stream in("crl2.pem");
+ X509_CRL crl2(in);
+\end{verbatim}
+
+After that, pass the \type{X509\_CRL} object to a \type{X509\_Store} object
+with \type{X509\_Code} \function{add\_crl}(\type{X509\_CRL}), and all future
+verifications will take into account the certificates listed, assuming
+\function{add\_crl} returns \type{VERIFIED}. If it doesn't return
+\type{VERIFIED}, then the return value is an error code signifying that the CRL
+could not be processed due to some problem (which could range from the issuing
+certificate not being found, to the CRL having some format problem). For more
+about the \type{X509\_Store} API, read the section later in this chapter.
+
+\subsection{Reading Certificates}
+
+\type{X509\_Certificate} has two constructors, each of which takes a source of
+data; a filename to read, and a \type{DataSource\&}.
+
+\subsection{Storing and Using Certificates}
+
+If you read a certificate, you probably want to verify the signature on
+it. However, consider that to do so, we may have to verify the signature on the
+certificate that we used to verify the first certificate, and on and on until
+we hit the top of the certificate tree somewhere. It would be a might huge pain
+to have to handle all of that manually in every application, so there is
+something that does it for you: \type{X509\_Store}.
+
+This is a pretty easy thing to use. The basic operations are: put certificates
+and CRLs into it, search for certificates, and attempt to verify
+certificates. That's about it. In the future, there will be support for online
+retrieval of certificates and CRLs (\eg with the HTTP cert-store interface
+currently under consideration by PKIX).
+
+\subsubsection{Adding Certificates}
+
+You can add new certificates to a certificate store using any of these
+functions:
+
+\function{add\_cert}(\type{const X509\_Certificate\&} \arg{cert},
+ \type{bool} \arg{trusted} \type{= false})
+
+\function{add\_certs}(\type{DataSource\&} \arg{source})
+
+\function{add\_trusted\_certs}(\type{DataSource\&} \arg{source})
+
+The versions that take a \type{DataSource\&} will add all the certificates
+that it can find in that source.
+
+All of them add the cert(s) to the store. The 'trusted' certificates are the
+ones that you have some reason to trust are genuine. For example, say your
+application is working with certificates that are owned by employees of some
+company, and all of their certificates are signed by the company CA, whose
+certificate is in turned signed by a commercial root CA. What you would then do
+is include the certificate of the commercial CA with your application, and read
+it in as a trusted certificate. From there, you could verify the company CA's
+certificate, and then use that to verify the end user's certificates. Only
+self-signed certificates may be considered trusted.
+
+\subsubsection{Adding CRLs}
+
+\type{X509\_Code} \function{add\_crl}(\type{const X509\_CRL\&} \arg{crl});
+
+This will process the CRL and mark the revoked certificates. This will also
+work if a revoked certificate is added to the store sometime after the CRL is
+processed. The function can return an error code (listed later), or will return
+\type{VERIFIED} if everything completed successfully.
+
+\subsubsection{Storing Certificates}
+
+You can output a set of certificates by calling \function{PEM\_encode}, which
+will return a \type{std::string} containing each of the certificates in the
+store, PEM encoded and concatenated. This simple format can easily be read by
+both Botan and other libraries/applications.
+
+\subsubsection{Searching for Certificates}
+
+You can find certificates in the store with a series of functions contained
+in the \function{X509\_Store\_Search} namespace:
+
+\begin{verbatim}
+namespace X509_Store_Search {
+std::vector<X509_Certificate> by_email(const X509_Store& store,
+ const std::string& email_addr);
+std::vector<X509_Certificate> by_name(const X509_Store& store,
+ const std::string& name);
+std::vector<X509_Certificate> by_dns(const X509_Store&,
+ const std::string& dns_name);
+}
+\end{verbatim}
+
+These functions will return a (possibly empty) vector of certificates from
+\arg{store} matching your search criteria. The email address and DNS name
+searches are case-insensitive but are sensitive to extra whitespace and so
+on. The name search will do case-insensitive substring matching, so, for
+example, calling \function{X509\_Store\_Search::by\_name}(\arg{your\_store},
+``dob'') will return certificates for ``J.R. 'Bob' Dobbs'' and
+``H. Dobbertin'', assuming both of those certificates are in \arg{your\_store}.
+
+You could then display the results to a user, and allow them to select the
+appropriate one. Searching using an email address as the key is usually more
+effective than the name, since email addresses are rarely shared.
+
+\subsubsection{Certificate Stores}
+
+An object of type \type{Certificate\_Store} is a generalized interface to an
+external source for certificates (and CRLs). Examples of such a store would be
+one that looked up the certificates in a SQL database, or by contacting a CGI
+script running on a HTTP server. There are currently three mechanisms for
+looking up a certificate, and one for retrieving CRLs. By default, most of
+these mechanisms will simply return an empty \type{std::vector} of
+\type{X509\_Certificate}. This storage mechanism is \emph{only} queried when
+doing certificate validation: it allows you to distribute only the root key
+with an application, and let some online method handle getting all the other
+certificates that are needed to validate an end entity certificate. In
+particular, the search routines will not attempt to access the external
+database.
+
+The three certificate lookup methods are \function{by\_SKID} (Subject Key
+Identifier), \function{by\_name} (the CommonName DN entry), and
+\function{by\_email} (stored in either the distinguished name, or in a
+subjectAlternativeName extension). The name and email versions take a
+\type{std::string}, while the SKID version takes a \type{SecureVector<byte>}
+containing the subject key identifier in raw binary. You can choose not to
+implement \function{by\_name} or \function{by\_email}, but \function{by\_SKID}
+is mandatory to implement, and, currently, is the only version that is used by
+\type{X509\_Store}.
+
+Finally, there is a method for finding CRLs, called \function{get\_crls\_for},
+that takes an \type{X509\_Certificate} object, and returns a
+\type{std::vector} of \type{X509\_CRL}. While generally there will be only one
+CRL, the use of the vector makes it easy to return no CRLs (\eg, if the
+certificate store doesn't support retrieving them), or return multiple ones
+(for example, if the certificate store can't determine precisely which key was
+used to sign the certificate). Implementing the function is optional, and by
+default will return no CRLs. If it is available, it will be used by
+\type{X509\_CRL}.
+
+As for actually using such a store, you have to tell \type{X509\_Store} about
+it, by calling the \type{X509\_Store} member function
+
+\function{add\_new\_certstore}(\type{Certificate\_Store}* \arg{new\_store})
+
+The argument, \arg{new\_store}, will be deleted by \type{X509\_Store}'s
+destructor, so make sure to allocate it with \function{new}.
+
+\subsubsection{Verifying Certificates}
+
+There is a single function in \type{X509\_Store} related to verifying a
+certificate:
+
+\type{X509\_Code}
+\function{validate\_cert}(\type{const X509\_Certificate\&} \arg{cert},
+ \type{Cert\_Usage} \arg{usage} = \type{ANY})
+
+To sum things up simply, it returns \type{VERIFIED} if the certificate can
+safely be considered valid for the usage(s) described by \arg{usage}, and an
+error code if it is not. Naturally, things are a bit more complicated than
+that. The enum \type{Cert\_Usage} is defined inside the \type{X509\_Store}
+class, it (currently) can take on any of the values \type{ANY} (any usage is
+OK), \type{TLS\_SERVER} (for SSL/TLS server authentication), \type{TLS\_CLIENT}
+(for SSL/TLS client authentication), \type{CODE\_SIGNING},
+\type{EMAIL\_PROTECTION} (email encryption, usually this means S/MIME),
+\type{TIME\_STAMPING} (in theory any time stamp application, usually IETF
+PKIX's Time Stamp Protocol), or \type{CRL\_SIGNING}. Note that Microsoft's code
+signing system, certainly the most widely used, uses a completely different
+(and basically undocumented) method for marking certificates for code signing.
+
+First, how does it know if a certificate is valid? Basically, a certificate is
+valid if both of the following hold: a) the signature in the certificate can be
+verified using the public key in the issuer's certificate, and b) the issuer's
+certificate is a valid CA certificate. Note that this definition is
+recursive. We get out of this by ``bottoming out'' when we reach a certificate
+that we consider trusted. In general this will either be a commercial root CA,
+or an organization or application specific CA.
+
+There are actually a few other restrictions (validity periods, key usage
+restrictions, etc), but the above summarizes the major points of the validation
+algorithm. In theory, Botan implements the certificate path validation
+algorithm given in RFC 2459, but in practice it does not (yet), because we
+don't support the X.509v3 policy or name constraint extensions.
+
+Possible values for \arg{usage} are \type{TLS\_SERVER}, \type{TLS\_CLIENT},
+\type{CODE\_SIGNING}, \type{EMAIL\_PROTECTION}, \type{CRL\_SIGNING}, and
+\type{TIME\_STAMPING}, and \type{ANY}. The default \type{ANY} does not mean
+valid for any use, it means ``is valid for some usage''. This is generally
+fine, and in fact requiring that a random certificate support a particular
+usage will likely result in a lot of failures, unless your application is very
+careful to always issue certificates with the proper extensions, and you never
+use certificates generated by other apps.
+
+Return values for \function{validate\_cert} (and \function{add\_crl}) include:
+
+\begin{list}{$\cdot$}
+ \item VERIFIED: The certificate is valid for the specified use.
+ \item
+ \item INVALID\_USAGE: The certificate cannot be used for the specified use.
+
+ \item CANNOT\_ESTABLISH\_TRUST: The root certificate was not marked as
+ trusted.
+ \item CERT\_CHAIN\_TOO\_LONG: The certificate chain exceeded the length
+ allowed by a basicConstraints extension.
+ \item SIGNATURE\_ERROR: An invalid signature was found
+ \item POLICY\_ERROR: Some problem with the certificate policies was found.
+
+ \item CERT\_FORMAT\_ERROR: Some format problem was found in a certificate.
+ \item CERT\_ISSUER\_NOT\_FOUND: The issuer of a certificate could not be
+ found.
+ \item CERT\_NOT\_YET\_VALID: The certificate is not yet valid.
+ \item CERT\_HAS\_EXPIRED: The certificate has expired.
+ \item CERT\_IS\_REVOKED: The certificate has been revoked.
+
+ \item CRL\_FORMAT\_ERROR: Some format problem was found in a CRL.
+ \item CRL\_ISSUER\_NOT\_FOUND: The issuer of a CRL could not be found.
+ \item CRL\_NOT\_YET\_VALID: The CRL is not yet valid.
+ \item CRL\_HAS\_EXPIRED: The CRL has expired.
+
+ \item CA\_CERT\_CANNOT\_SIGN: The CA certificate found does not have an
+ contain a public key that allows signature verification.
+ \item CA\_CERT\_NOT\_FOR\_CERT\_ISSUER: The CA cert found is not allowed to
+ issue certificates.
+ \item CA\_CERT\_NOT\_FOR\_CRL\_ISSUER: The CA cert found is not allowed to
+ issue CRLs.
+
+ \item UNKNOWN\_X509\_ERROR: Some other error occurred.
+
+\end{list}
+
+\subsection{Certificate Authorities}
+
+Setting up a CA for X.509 certificates is actually probably the easiest thing
+to do related to X.509. A CA is represented by the type \type{X509\_CA}, which
+can be found in \filename{x509\_ca.h}. A CA always needs its own certificate,
+which can either be a self-signed certificate (see below on how to create one)
+or one issued by another CA (see the section on PKCS \#10 requests). Creating
+a CA object is done by the following constructor:
+
+\begin{verbatim}
+ X509_CA(const X509_Certificate& cert, const PKCS8_PrivateKey& key);
+\end{verbatim}
+
+The private key is the private key corresponding to the public key in the
+CA's certificate.
+
+Generally, requests for new certificates are supplied to a CA in the form on
+PKCS \#10 certificate requests (called a \type{PKCS10\_Request} object in
+Botan). These are decoded in a similar manner to
+certificates/CRLs/etc. Generally, a request is vetted by humans (who somehow
+verify that the name in the request corresponds to the name of the person who
+requested it), and then signed by a CA key, generating a new certificate.
+
+\begin{verbatim}
+ X509_Certificate sign_request(const PKCS10_Request&) const;
+\end{verbatim}
+
+\subsubsection{Generating CRLs}
+
+As mentioned previously, the ability to process CRLs is highly important in
+many PKI systems. In fact, according to strict X.509 rules, you must not
+validate any certificate if the appropriate CRLs are not available (though
+hardly any systems are that strict). In any case, a CA should have a valid CRL
+available at all times.
+
+Of course, you might be wondering what to do if no certificates have been
+revoked. In fact, CRLs can be issued without any actually revoked certificates
+- the list of certs will simply be empty. To generate a new, empty CRL, just
+call \type{X509\_CRL}
+\function{X509\_CA::new\_crl}(\type{u32bit}~\arg{seconds}~=~0)~--~it will
+create a new, empty, CRL. If \arg{seconds} is the default 0, then the normal
+default CRL next update time (the value of the ``x509/crl/next\_update'') will
+be used. If not, then \arg{seconds} specifies how long (in seconds) it will be
+until the CRL's next update time (after this time, most clients will reject the
+CRL as too old).
+
+On the other hand, you may have issued a CRL before. In that case, you will
+want to issue a new CRL that contains all previously revoked
+certificates, along with any new ones. This is done by calling the
+\type{X509\_CA} member function
+\function{update\_crl}(\type{X509\_CRL}~\arg{old\_crl},
+\type{std::vector<CRL\_Entry>}~\arg{new\_revoked},
+\type{u32bit}~\arg{seconds}~=~0), where \type{X509\_CRL} is the last CRL this
+CA issued, and \arg{new\_revoked} is a list of any newly revoked certificates.
+The function returns a new \type{X509\_CRL} to make available for clients. The
+semantics for the \arg{seconds} argument is the same as \function{new\_crl}.
+
+The \type{CRL\_Entry} type is a structure that contains, at a minimum, the
+serial number of the revoked certificate. As serial numbers are never repeated,
+the pairing of an issuer and a serial number (should) distinctly identify any
+certificate. In this case, we represent the serial number as a
+\type{SecureVector<byte>} called \arg{serial}. There are two additional
+(optional) values, an enumeration called \type{CRL\_Code} that specifies the
+reason for revocation (\arg{reason}), and an object that represents the time
+that the certificate became invalid (if this information is known).
+
+If you wish to remove an old entry from the CRL, insert a new entry for the
+same cert, with a \arg{reason} code of \type{DELETE\_CRL\_ENTRY}. For example,
+if a revoked certificate has expired 'normally', there is no reason to continue
+to explicitly revoke it, since clients will reject the cert as expired in any
+case.
+
+\subsubsection{Self-Signed Certificates}
+
+Generating a new self-signed certificate can often be useful, for example when
+setting up a new root CA, or for use in email applications. In this case,
+the solution is summed up simply as:
+
+\begin{verbatim}
+namespace X509 {
+ X509_Certificate create_self_signed_cert(const X509_Cert_Options& opts,
+ const PKCS8_PrivateKey& key);
+}
+\end{verbatim}
+
+Where \arg{key} is obviously the private key you wish to use (the public key,
+used in the certificate itself, is extracted from the private key), and
+\arg{opts} is an structure that has various bits of information that will be
+used in creating the certificate (this structure, and its use, is discussed
+below). This function is found in the header \filename{x509self.h}. There is an
+example of using this function in the \filename{self\_sig} example.
+
+\subsubsection{Creating PKCS \#10 Requests}
+
+Also in \filename{x509self.h}, there is a function for generating new PKCS \#10
+certificate requests.
+
+\begin{verbatim}
+namespace X509 {
+ PKCS10_Request create_cert_req(const X509_Cert_Options&,
+ const PKCS8_PrivateKey&);
+}
+\end{verbatim}
+
+This function acts quite similarly to \function{create\_self\_signed\_cert},
+except it instead returns a PKCS \#10 certificate request. After creating it,
+one would typically transmit it to a CA, who signs it and returns a freshly
+minted X.509 certificate. There is an example of using this function in the
+\filename{pkcs10} example.
+
+\subsubsection{Certificate Options}
+
+So what is this \type{X509\_Cert\_Options} thing we've been passing around?
+Basically, it's a bunch of information that will end up being stored into the
+certificate. This information comes in 3 major flavors: information about the
+subject (CA or end-user), the validity period of the certificate, and
+restrictions on the usage of the certificate.
+
+First and foremost is a number of \type{std::string} members, which contains
+various bits of information about the user: \arg{common\_name},
+\arg{serial\_number}, \arg{country}, \arg{organization}, \arg{org\_unit},
+\arg{locality}, \arg{state}, \arg{email}, \arg{dns\_name}, and \arg{uri}. As
+many of these as possible should be filled it (especially an email address),
+though the only required ones are \arg{common\_name} and \arg{country}.
+
+There is another value that is only useful when creating a PKCS \#10 request,
+which is called \arg{challenge}. This is a challenge password, which you can
+later use to request certificate revocation (\emph{if} the CA supports doing
+revocations in this manner).
+
+Then there is the validity period; these are set with \function{not\_before}
+and \function{not\_after}. Both of these functions also take a
+\type{std::string}, which specifies when the certificate should start being
+valid, and when it should stop being valid. If you don't set the starting
+validity period, it will automatically choose the current time. If you don't
+set the ending time, it will choose the starting time plus a default time
+period. The arguments to these functions specify the time in the following
+format: ``2002/11/27 1:50:14''. The time is in 24-hour format, and the date is
+encoded as year/month/day. The date must be specified, but you can omit the
+time or trailing parts of it, for example ``2002/11/27 1:50'' or
+``2002/11/27''.
+
+Lastly, you can set constraints on a key. The one you're mostly likely to want
+to use is to create (or request) a CA certificate, which can be done by calling
+the member function \function{CA\_key}. This should only be used when needed.
+
+Other constraints can be set by calling the member functions
+\function{add\_constraints} and \function{add\_ex\_constraints}. The first
+takes a \type{Key\_Constraints} value, and replaces any previously set
+value. If no value is set, then the certificate key is marked as being valid
+for any usage. You can set it to any of the following (for more than one
+usage, OR them together): \type{DIGITAL\_SIGNATURE}, \type{NON\_REPUDIATION},
+\type{KEY\_ENCIPHERMENT}, \type{DATA\_ENCIPHERMENT}, \type{KEY\_AGREEMENT},
+\type{KEY\_CERT\_SIGN}, \type{CRL\_SIGN}, \type{ENCIPHER\_ONLY},
+\type{DECIPHER\_ONLY}. Many of these have quite special semantics, so you
+should either consult the appropriate standards document (such as RFC 3280), or
+simply not call \function{add\_constraints}, in which case the appropriate
+values will be chosen for you.
+
+The second function, \function{add\_ex\_constraints}, allows you to specify an
+OID that has some meaning with regards to restricting the key to particular
+usages. You can, if you wish, specify any OID you like, but there is a set of
+standard ones that other applications will be able to understand. These are
+the ones specified by the PKIX standard, and are named ``PKIX.ServerAuth'' (for
+TLS server authentication), ``PKIX.ClientAuth'' (for TLS client
+authentication), ``PKIX.CodeSigning'', ``PKIX.EmailProtection'' (most likely
+for use with S/MIME), ``PKIX.IPsecUser'', ``PKIX.IPsecTunnel'',
+``PKIX.IPsecEndSystem'', and ``PKIX.TimeStamping''. You can call
+\function{add\_ex\_constraints} any number of times~--~each new OID will be
+added to the list to include in the certificate.
+
+\pagebreak
+\section{The Low-Level Interface}
+
+Botan has two different interfaces. The one documented in this section is meant
+more for implementing higher-level types (see the section on filters, earlier in
+this manual) than for use by applications. Using it safely requires a solid
+knowledge of encryption techniques and best practices, so unless you know, for
+example, what CBC mode and nonces are, and why PKCS \#1 padding is important,
+you should avoid this interface in favor of something working at a higher level
+(such as the CMS interface).
+
+\subsection{Basic Algorithm Abilities}
+
+There are a small handful of functions implemented by most of Botan's
+algorithm objects. Among these are:
+
+\noindent
+\type{std::string} \function{name}():
+
+Returns a human-readable string of the name of this algorithm. Examples of
+names returned are ``Blowfish'' and ``HMAC(MD5)''. You can turn names back into
+algorithm objects using the functions in \filename{lookup.h}.
+
+\noindent
+\type{void} \function{clear}():
+
+Clear out the algorithm's internal state. A block cipher object will ``forget''
+its key, a hash function will ``forget'' any data put into it, etc. Basically,
+the object will look exactly as it did when you initially allocated it.
+
+\noindent
+\function{clone}():
+
+This function is central to Botan's name-based interface. The \function{clone}
+has many different return types, such as \type{BlockCipher*} and
+\type{HashFunction*}, depending on what kind of object it is called on. Note
+that unlike Java's clone, this returns a new object in a ``pristine'' state;
+that is, operations done on the initial object before calling \function{clone}
+do not affect the initial state of the new clone.
+
+Cloned objects can (and should) be deallocated with the C++ \texttt{delete}
+operator.
+
+\subsection{Keys and IVs}
+
+Both symmetric keys and initialization values can simply be considered byte (or
+octet) strings. These are represented by the classes \type{SymmetricKey} and
+\type{InitializationVector}, which are subclasses of \type{OctetString}.
+
+Since often it's hard to distinguish between a key and IV, many things (such as
+key derivation mechanisms) return \type{OctetString} instead of
+\type{SymmetricKey} to allow its use as a key or an IV.
+
+\noindent
+\function{OctetString}(\type{u32bit} \arg{length}):
+
+This constructor creates a new random key of size \arg{length}.
+
+\noindent
+\function{OctetString}(\type{std::string} \arg{str}):
+
+The argument \arg{str} is assumed to be a hex string; it is converted to binary
+and stored. Whitespace is ignored.
+
+\noindent
+\function{OctetString}(\type{const byte} \arg{input}[], \type{u32bit}
+\arg{length}):
+
+This constructor simply copies its input.
+
+\subsection{Symmetrically Keyed Algorithms}
+
+Block ciphers, stream ciphers, and MACs all handle keys in pretty much the same
+way. To make this similarity explicit, all algorithms of those types are
+derived from the \type{SymmetricAlgorithm} base class. This type has three
+functions:
+
+\noindent
+\type{void} \function{set\_key}(\type{const byte} \arg{key}[], \type{u32bit}
+\arg{length}):
+
+Most algorithms only accept keys of certain lengths. If you attempt to call
+\function{set\_key} with a key length that is not supported, the exception
+\type{Invalid\_Key\_Length} will be thrown. There is also another version of
+\function{set\_key} that takes a \type{SymmetricKey} as an argument.
+
+\noindent
+\type{bool} \function{valid\_keylength}(\type{u32bit} \arg{length}) const:
+
+This function returns true if a key of the given length will be accepted by
+the cipher.
+
+There are also three constant data members of every \type{SymmetricAlgorithm}
+object, which specify exactly what limits there are on keys which that object
+can accept:
+
+MAXIMUM\_KEYLENGTH: The maximum length of a key. Usually, this is at most 32
+(256 bits), even if the algorithm actually supports more. In a few rare cases
+larger keys will be supported.
+
+MINIMUM\_KEYLENGTH: The minimum length of a key. This is at least 1.
+
+KEYLENGTH\_MULTIPLE: The length of the key must be a multiple of this value.
+
+In all cases, \function{set\_key} must be called on an object before any data
+processing (encryption, decryption, etc) is done by that object. If this is not
+done, the results are undefined -- that is to say, Botan reserves the right in
+this situation to do anything from printing a nasty, insulting message on the
+screen to dumping core.
+
+\subsection{Block Ciphers}
+
+Block ciphers implement the interface \type{BlockCipher}, found in
+\filename{base.h}, as well as the \type{SymmetricAlgorithm} interface.
+
+\noindent
+\type{void} \function{encrypt}(\type{const byte} \arg{in}[BLOCK\_SIZE],
+ \type{byte} \arg{out}[BLOCK\_SIZE]) const
+
+\noindent
+\type{void} \function{encrypt}(\type{byte} \arg{block}[BLOCK\_SIZE]) const
+
+These functions apply the block cipher transformation to \arg{in} and
+place the result in \arg{out}, or encrypts \arg{block} in place
+(\arg{in} may be the same as \arg{out}). BLOCK\_SIZE is a constant
+member of each class, which specifies how much data a block cipher can
+process at one time. Note that BLOCK\_SIZE is not a static class
+member, meaning you can (given a \type{BlockCipher*} named
+\arg{cipher}), call \verb|cipher->BLOCK_SIZE| to get the block size of
+that particular object. \type{BlockCipher}s have similar functions
+\function{decrypt}, which perform the inverse operation.
+
+\begin{verbatim}
+AES_128 cipher;
+SymmetricKey key(cipher.MAXIMUM_KEYLENGTH); // randomly created
+cipher.set_key(key);
+
+byte in[16] = { /* secrets */ };
+byte out[16];
+cipher.encrypt(in, out);
+\end{verbatim}
+
+\subsection{Stream Ciphers}
+
+Stream ciphers are somewhat different from block ciphers, in that encrypting
+data results in changing the internal state of the cipher. Also, you may
+encrypt any length of data in one go (in byte amounts).
+
+\noindent
+\type{void} \function{encrypt}(\type{const byte} \arg{in}[], \type{byte}
+\arg{out}[], \type{u32bit} \arg{length})
+
+\noindent
+\type{void} \function{encrypt}(\type{byte} \arg{data}[], \type{u32bit}
+\arg{length}):
+
+These functions encrypt the arbitrary length (well, less than 4 gigabyte long)
+string \arg{in} and place it into \arg{out}, or encrypts it in place in
+\arg{data}. The \function{decrypt} functions look just like
+\function{encrypt}.
+
+Stream ciphers implement the \type{SymmetricAlgorithm} interface.
+
+Some stream ciphers support random access to any point in their cipher
+stream. For such ciphers, calling \type{void} \function{seek}(\type{u32bit}
+\arg{byte}) will change the cipher's state so that it is as if the cipher had been
+keyed as normal, then encrypted \arg{byte} -- 1 bytes of data (so the next byte
+in the cipher stream is byte number \arg{byte}).
+
+\subsection{Hash Functions / Message Authentication Codes}
+
+Hash functions take their input without producing any output, only producing
+anything when all input has already taken place. MACs are very similar, but are
+additionally keyed. Both of these are derived from the base class
+\type{BufferedComputation}, which has the following functions.
+
+\noindent
+\type{void} \function{update}(\type{const byte} \arg{input}[], \type{u32bit}
+\arg{length})
+
+\noindent
+\type{void} \function{update}(\type{byte} \arg{input})
+
+\noindent
+\type{void} \function{update}(\type{const std::string \&} \arg{input})
+
+Updates the hash/mac calculation with \arg{input}.
+
+\noindent
+\type{void} \function{final}(\type{byte} \arg{out}[OUTPUT\_LENGTH])
+
+\noindent
+\type{SecureVector<byte>} \function{final}():
+
+Complete the hash/MAC calculation and place the result into \arg{out}.
+OUTPUT\_LENGTH is a public constant in each object that gives the length of the
+hash in bytes. After you call \function{final}, the hash function is reset to
+its initial state, so it may be reused immediately.
+
+The second method of using final is to call it with no arguments at all, as
+shown in the second prototype. It will return the hash/mac value in a memory
+buffer, which will have size OUTPUT\_LENGTH.
+
+There is also a pair of functions called \function{process}. They are
+essentially a combination of a single \function{update}, and \function{final}.
+Both versions return the final value, rather than placing it an array. Calling
+\function{process} with a single byte value isn't available, mostly because it
+would rarely be useful.
+
+A MAC can be viewed (in most cases) as simply a keyed hash function, so classes
+that are derived from \type{MessageAuthenticationCode} have \function{update}
+and \function{final} classes just like a \type{HashFunction} (and like a
+\type{HashFunction}, after \function{final} is called, it can be used to make a
+new MAC right away; the key is kept around).
+
+A MAC has the \type{SymmetricAlgorithm} interface in addition to the
+\type{BufferedComputation} interface.
+
+\pagebreak
+\section{Random Number Generators}
+
+The random number generators provided in Botan are meant for creating keys,
+IVs, padding, nonces, and anything else that requires 'random' data. It is
+important to remember that the output of these classes will vary, even if they
+are supplied with exactly the same seed (\ie, two \type{Randpool} objects with
+similar initial states will not produce the same output, because the value of
+high resolution timers is added to the state at various points).
+
+To ensure good quality output, a PRNG needs to be seeded with truly random data
+(such as that produced by a hardware RNG). Typically, you will use an
+\type{EntropySource} (see below). To add entropy to a PRNG, you can use
+\type{void} \function{add\_entropy}(\type{const byte} \arg{data}[],
+\type{u32bit} \arg{length}) or (better), use the \type{EntropySource}
+interface.
+
+Once a PRNG has been initialized, you can get a single byte of random data by
+calling \type{byte} \function{random()}, or get a large block by calling
+\type{void} \function{randomize}(\type{byte} \arg{data}[], \type{u32bit}
+\arg{length}), which will put random bytes into each member of the array from
+indexes 0 $\ldots$ \arg{length} -- 1.
+
+You can avoid all the problems inherent in seeding the PRNG by using the
+globally shared PRNG, described later in this section.
+
+\subsection{Randpool}
+
+\type{Randpool} is the primary PRNG within Botan. In recent versions all uses
+of it have been wrapped by an implementation of the X9.31 PRNG (see below). If
+for some reason you should have cause to create a PRNG instead of using the
+``global'' one owned by the library, it would be wise to consider the same on
+the grounds of general caution; while \type{Randpool} is designed with known
+attacks and PRNG weaknesses in mind, it is not an standard/official PRNG. The
+remainder of this section is a (fairly technical, though high-level) description
+of the algorithms used in this PRNG. Unless you have a specific interest in
+this subject, the rest of this section might prove somewhat uninteresting.
+
+\type{Randpool} has an internal state called pool, which is 512 bytes
+long. This is where entropy is mixed into and extracted from. There is also a
+small output buffer (called buffer), which holds the data which has already
+been generated but has just not been output yet.
+
+It is based around a MAC and a block cipher (which are currently HMAC(SHA-256)
+and AES-256). Where a specific size is mentioned, it should be taken as a
+multiple of the cipher's block size. For example, if a 256-bit block cipher
+were used instead of AES, all the sizes internally would double. Every time
+some new output is needed, we compute the MAC of a counter and a high
+resolution timer. The resulting MAC is XORed into the output buffer (wrapping
+as needed), and the output buffer is then encrypted with AES, producing 16
+bytes of output.
+
+After 8 blocks (or 128 bytes) have been produced, we mix the pool. To do this,
+we first rekey both the MAC and the cipher; the new MAC key is the MAC of the
+current pool under the old MAC key, while the new cipher key is the MAC of the
+current pool under the just-chosen MAC key. We then encrypt the entire pool in
+CBC mode, using the current (unused) output buffer as the IV. We then generate
+a new output buffer, using the mechanism described in the previous paragraph.
+
+To add randomness to the PRNG, we compute the MAC of the input and XOR the
+output into the start of the pool. Then we remix the pool and produce a new
+output buffer. The initial MAC operation should make it very hard for chosen
+inputs to harm the security of \type{Randpool}, and as HMAC should be able to
+hold roughly 256 bits of state, it is unlikely that we are wasting much input
+entropy (or, if we are, it doesn't matter, because we have a very abundant
+supply).
+
+\subsection{ANSI X9.31}
+
+\type{ANSI\_X931\_PRNG} is the standard issue X9.31 Appendix A.2.4 PRNG, though
+using AES-256 instead of 3DES as the block cipher. This PRNG implementation has
+been checked against official X9.31 test vectors.
+
+Internally, the PRNG holds a pointer to another PRNG (typically
+Randpool). This internal PRNG generates the key and seed used by the
+X9.31 algorithm, as well as the date/time vectors. Each time an X9.31
+PRNG object receives entropy, it simply passes it along to the PRNG it
+is holding, and then pulls out some random bits to generate a new key
+and seed. This PRNG considers itself seeded as soon as the internal
+PRNG is seeded.
+
+As of version 1.4.7, the X9.31 PRNG is by default used for all random number
+generation.
+
+\subsection{Entropy Sources}
+
+An \type{EntropySource} is an abstract representation of some method of gather
+``real'' entropy. This tends to be very system dependent. The \emph{only} way
+you should use an \type{EntropySource} is to pass it to a PRNG that will
+extract entropy from it -- never use the output directly for any kind of key or
+nonce generation!
+
+\type{EntropySource} has a pair of functions for getting entropy from some
+external source, called \function{fast\_poll} and \function{slow\_poll}. These
+pass a buffer of bytes to be written; the functions then return how many bytes
+of entropy were actually gathered. \type{EntropySource}s are usually used to
+seed the global PRNG using the functions found in the \namespace{Global\_RNG}
+namespace.
+
+Note for writers of \type{EntropySource}s: it isn't necessary to use any kind
+of cryptographic hash on your output. The data produced by an EntropySource is
+only used by an application after it has been hashed by the
+\type{RandomNumberGenerator} that asked for the entropy, thus any hashing
+you do will be wasteful of both CPU cycles and possibly entropy.
+
+\pagebreak
+\section{User Interfaces}
+
+Botan has recently changed some infrastructure to better accommodate more
+complex user interfaces, in particular ones that are based on event
+loops. Primary among these was the fact that when doing something like loading
+a PKCS \#8 encoded private key, a passphrase might be needed, but then again it
+might not (a PKCS \#8 key doesn't have to be encrypted). Asking for a
+passphrase to decrypt an unencrypted key is rather pointless. Not only that,
+but the way to handle the user typing the wrong passphrase was complicated,
+undocumented, and inefficient.
+
+So now Botan has an object called \type{UI}, which provides a simple interface
+for the aspects of user interaction the library has to be concerned
+with. Currently, this means getting a passphrase from the user, and that's it
+(\type{UI} will probably be extended in the future to support other operations
+as they are needed). The base \type{UI} class is very stupid, because the
+library can't directly assume anything about the environment that it's running
+under (for example, if there will be someone sitting at the terminal, if the
+application is even \emph{attached} to a terminal, and so on). But since you
+can subclass \type{UI} to use whatever method happens to be appropriate for
+your application, this isn't a big deal.
+
+There is (currently) a single function that can be overridden by subclasses of
+\type{UI} (the \type{std::string} arguments are actually \type{const
+std::string\&}, but shown as simply \type{std::string} to keep the line from
+wrapping):
+
+\noindent
+\type{std::string} \function{get\_passphrase}(\type{std::string} \arg{what},
+ \type{std::string} \arg{source},
+ \type{UI\_Result\&} \arg{result}) const;
+
+The \arg{what} argument specifies what the passphrase is needed for (for
+example, PKCS \#8 key loading passes \arg{what} as ``PKCS \#8 private
+key''). This lets you provide the user with some indication of \emph{why} your
+application is asking for a passphrase; feel free to pass the string through
+\function{gettext(3)} or moral equivalent for i18n purposes. Similarly,
+\arg{source} specifies where the data in question came from, if available (for
+example, a file name). If the source is not available for whatever reason, then
+\arg{source} will be an empty string; be sure to account for this possibility
+when writing a \type{UI} subclass.
+
+The function returns the passphrase as the return value, and a status code in
+\arg{result} (either \type{OK} or \type{CANCEL\_ACTION}). If
+\type{CANCEL\_ACTION} is returned in \arg{result}, then the return value will
+be ignored, and the caller will take whatever action is necessary (typically,
+throwing an exception stating that the passphrase couldn't be determined). In
+the specific case of PKCS \#8 key decryption, a \type{Decoding\_Error}
+exception will be thrown; your UI should assume this can happen, and provide
+appropriate error handling (such as putting up a dialog box informing the user
+of the situation, and canceling the operation in progress).
+
+There is an example \type{UI} that uses GTK+ available on the web site. The
+\type{GTK\_UI} code is cleanly separated from the rest of the example, so if
+you happen to be using GTK+, you can copy (and/or adapt) that code for your
+application. If you write a \type{UI} object for another windowing system
+(Win32, Qt, wxWidgets, FOX, etc), and would like to make it available to users
+in general (ideally under a permissive license such as public domain or
+MIT/BSD), feel free to send in a copy.
+
+\pagebreak
+\section{Botan's Modules}
+
+Botan comes with a variety of modules that can be compiled into the system.
+These will not be available on all installations of the library, but you can
+check for their availability based on whether or not certain macros are
+defined.
+
+\subsection{Pipe I/O for Unix File Descriptors}
+
+This is a fairly minor feature, but it comes in handy sometimes. In all
+installations of the library, Botan's \type{Pipe} object overloads the
+\keyword{<<} and \keyword{>>} operators for C++ iostream objects, which is
+usually more than sufficient for doing I/O.
+
+However, there are cases where the iostream hierarchy does not map well to
+local 'file types', so there is also the ability to do I/O directly with Unix
+file descriptors. This is most useful when you want to read from or write to
+something like a TCP or Unix-domain socket, or a pipe, since for simple file
+access it's usually easier to just use C++'s file streams.
+
+If \macro{BOTAN\_EXT\_PIPE\_UNIXFD\_IO} is defined, then you can use the
+overloaded I/O operators with Unix file descriptors. For an example of this,
+check out the \filename{hash\_fd} example, included in the Botan distribution.
+
+\subsection{Entropy Sources}
+
+All of these are used by the \function{Global\_RNG::seed} function if they are
+available. Since this function is called by the \type{LibraryInitializer} class
+when it is created, it is fairly rare that you will need to deal with any of
+these classes directly. Even in the case of a long-running server that needs to
+renew its entropy poll, it is easier to simply call
+\function{Global\_RNG::seed} (see the section entitled ``The Global PRNG'' for
+more details).
+
+\noindent
+\type{EGD\_EntropySource}: Query an EGD socket. If the macro
+\macro{BOTAN\_EXT\_ENTROPY\_SRC\_EGD} is defined, it can be found in
+\filename{es\_egd.h}. The constructor takes a \type{std::vector<std::string>}
+that specifies the paths to look for an EGD socket.
+
+\noindent
+\type{Unix\_EntropySource}: This entropy source executes programs common on
+Unix systems (such as \filename{uptime}, \filename{vmstat}, and \filename{df})
+and adds it to a buffer. It's quite slow due to process overhead, and (roughly)
+1 bit of real entropy is in each byte that is output. It is declared in
+\filename{es\_unix.h}, if \macro{BOTAN\_EXT\_ENTROPY\_SRC\_UNIX} is
+defined. If you don't have \filename{/dev/urandom} \emph{or} EGD, this is
+probably the thing to use. For a long-running process on Unix, keep on object
+of this type around and run fast polls ever few minutes.
+
+\noindent
+\type{FTW\_EntropySource}: Walk through a filesystem (the root to start
+searching is passed as a string to the constructor), reading files. This tends
+to only be useful on things like \filename{/proc} that have a great deal of
+variability over time, and even then there is only a small amount of entropy
+gathered: about 1 bit of entropy for every 16 bits of output (and many hundreds
+of bits are read in order to get that 16 bits). It is declared in
+\filename{es\_ftw.h}, if \macro{BOTAN\_EXT\_ENTROPY\_SRC\_FTW} is defined. Only
+use this as a last resort. I don't really trust it, and neither should you.
+
+\noindent
+\type{Win32\_CAPI\_EntropySource}: This routines gathers entropy from a Win32
+CAPI module. It takes an optional \type{std::string} that will specify what
+type of CAPI provider to use. Generally the CAPI RNG is always the same
+software-based PRNG, but there are a few that may use a hardware RNG. By
+default it will use the first provider listed in the option
+``rng/ms\_capi\_prov\_type'' that is available on the machine (currently the
+providers ``RSA\_FULL'', ``INTEL\_SEC'', ``FORTEZZA'', and ``RNG'' are
+recognized).
+
+\noindent
+\type{BeOS\_EntropySource}: Query system statistics using various BeOS-specific
+APIs.
+
+\noindent
+\type{Pthread\_EntropySource}: Attempt to gather entropy based on jitter
+between a number of threads competing for a single mutex. This entropy source
+is \emph{very} slow, and highly questionable in terms of security. However, it
+provides a worst-case fallback on systems that don't have Unix-like features,
+but do support POSIX threads. This module is currently unavailable due to
+problems on some systems.
+
+\subsection{Compressors}
+
+There are two compression algorithms supported by Botan, Zlib and Bzip2 (Gzip
+and Zip encoding will be supported in future releases). Only lossless
+compression algorithms are currently supported by Botan, because they tend to
+be the most useful for cryptography. However, it is very reasonable to consider
+supporting something like GSM speech encoding (which is lossy), for use in
+encrypted voice applications.
+
+You should always compress \emph{before} you encrypt, because encryption seeks
+to hide the redundancy that compression is supposed to try to find and remove.
+
+\subsubsection{Bzip2}
+
+To test for Bzip2, check to see if \macro{BOTAN\_EXT\_COMPRESSOR\_BZIP2} is
+defined. If so, you can include \filename{bzip2.h}, which will declare a pair
+of \type{Filter} objects: \type{Bzip2\_Compression} and
+\type{Bzip2\_Decompression}.
+
+You should be prepared to take an exception when using the decompressing
+filter, for if the input is not valid Bzip2 data, that is what you will
+receive. You can specify the desired level of compression to
+\type{Bzip2\_Compression}'s constructor as an integer between 1 and 9, 1
+meaning worst compression, and 9 meaning the best. The default is to use 9,
+since small values take the same amount of time, just use a little less memory.
+
+The Bzip2 module was contributed by Peter J. Jones.
+
+\subsubsection{Zlib}
+
+Zlib compression works pretty much like Bzip2 compression. The only differences
+in this case are that the macro is \macro{BOTAN\_EXT\_COMPRESSOR\_ZLIB}, the
+header you need to include is called \filename{botan/zlib.h} (remember that you
+shouldn't just \verb|#include <zlib.h>|, or you'll get the regular zlib API,
+which is not what you want). The Botan classes for Zlib
+compression/decompression are called \type{Zlib\_Compression} and
+\type{Zlib\_Decompression}.
+
+Like Bzip2, a \type{Zlib\_Decompression} object will throw an exception if
+invalid (in the sense of not being in the Zlib format) data is passed into it.
+
+In the case of zlib's algorithm, a worse compression level will be faster than
+a very high compression ratio. For this reason, the Zlib compressor will
+default to using a compression level of 6. This tends to give a good trade off
+in terms of time spent to compression achieved. There are several factors you
+need to consider in order to decide if you should use a higher compression
+level:
+
+\begin{list}{$\cdot$}
+ \item Better security: the less redundancy in the source text, the harder it
+ is to attack your ciphertext. This is not too much of a concern,
+ because with decent algorithms using sufficiently long keys, it doesn't
+ really matter \emph{that} much (but it certainly can't hurt).
+ \item
+
+ \item Decreasing returns. Some simple experiments by the author showed
+ minimal decreases in the size between level 6 and level 9 compression
+ with large (1 to 3 megabyte) files. There was some difference, but it
+ wasn't that much.
+
+ \item CPU time. Level 9 zlib compression is often two to four times as slow
+ as level 6 compression. This can make a substantial difference in the
+ overall runtime of a program.
+\end{list}
+
+While the zlib compression library uses the same compression algorithm as the
+gzip and zip programs, the format is different. The zlib format is defined in
+RFC 1950.
+
+\subsubsection{Data Sources}
+
+A \type{DataSource} is a simple abstraction for a thing that stores bytes. This
+type is used fairly heavily in the areas of the API related to ASN.1
+encoding/decoding. The following types are \type{DataSource}s: \type{Pipe},
+\type{SecureQueue}, and a couple of special purpose ones:
+\type{DataSource\_Memory} and \type{DataSource\_Stream}.
+
+You can create a \type{DataSource\_Memory} with an array of bytes and a length
+field. The object will make a copy of the data, so you don't have to worry
+about keeping that memory allocated. This is mostly for internal use, but if it
+comes in handy, feel free to use it.
+
+A \type{DataSource\_Stream} is probably more useful than the memory based
+one. Its constructors take either a \type{std::istream} or a
+\type{std::string}. If it's a stream, the data source will use the
+\type{istream} to satisfy read requests (this is particularly useful to use
+with \type{std::cin}). If the string version is used, it will attempt to open
+up a file with that name and read from it.
+
+\subsubsection{Data Sinks}
+
+A \type{DataSink} (in \filename{data\_snk.h}) is a \type{Filter} that takes
+arbitrary amounts of input, and produces no output. Generally, this means it's
+doing something with the data outside the realm of what
+\type{Filter}/\type{Pipe} can handle, for example, writing it to a file (which
+is what the \type{DataSink\_Stream} does). There is no need for
+\type{DataSink}s that write to a \type{std::string} or memory buffer, because
+\type{Pipe} can handle that by itself.
+
+Here's a quick example of using a \type{DataSink}, which encrypts
+\filename{in.txt} and sends the output to \filename{out.txt}. There is
+no explicit output operation; the writing of \filename{out.txt} is
+implicit.
+
+\begin{verbatim}
+ DataSource_Stream in("in.txt");
+ Pipe pipe(new CBC_Encryption("Blowfish", "PKCS7", key, iv),
+ new DataSink_Stream("out.txt"));
+ pipe.process_msg(in);
+\end{verbatim}
+
+A real advantage of this is that even if ``in.txt'' is large, only as
+much memory is needed for internal I/O buffers will actually be used.
+
+\subsection{Writing Modules}
+
+It's a lot simpler to write modules for Botan that it is to write code
+in the core library, for several reasons. First, a module can rely on
+external libraries and services beyond the base ISO C++ libraries, and
+also machine dependent features. Also, the code can be added at
+configuration time on the user's end with very little effort (\ie the
+code can be distributed separately, and included by the user without
+needing to patch any existing source files).
+
+Each module lives in a subdirectory of the \filename{modules}
+directory, which exists at the top-level of the Botan source tree. The
+``short name'' of the module is the same as the name of this
+directory. The only required file in this directory is
+\filename{info.txt}, which contains directives that specify what a
+particular module does, what systems it runs on, and so on. Comments
+in \filename{info.txt} start with a \verb|#| character and continue
+to end of line.
+
+Recognized directives include:
+
+\newcommand{\directive}[2]{
+ \vskip 4pt
+ \noindent
+ \texttt{#1}: #2
+}
+
+\directive{realname <name>}{Specify that the 'real world' name of this module
+ is \texttt{<name>}.}
+
+\directive{note <note>}{Add a note that will be seen by the end-user at
+configure time if the module is included into the library.}
+
+\directive{require\_version <version>}{Require at configure time that
+the version of Botan in use be at least \texttt{<version>}.}
+
+\directive{define <macro>[,<macro>[,...]]}{Cause the macro
+ \macro{BOTAN\_EXT\_<macro>} (for each instance of \macro{<macro>}
+ in the directive) to be defined in \filename{build.h}. This should
+ only be used if the module creates user-visible changes. There is a
+ set of conventions that should be followed in deciding what to call
+ this macro (where xxx denotes some descriptive and distinguishing
+ characteristic of the thing implemented, such as
+ \macro{ALLOC\_MLOCK} or \macro{MUTEX\_PTHREAD}):
+
+\begin{itemize}
+\item Allocator: \macro{ALLOC\_xxx}
+\item Compressors: \macro{COMPRESSOR\_xxx}
+\item EntropySource: \macro{ENTROPY\_SRC\_xxx}
+\item Engines: \macro{ENGINE\_xxx}
+\item Mutex: \macro{MUTEX\_xxx}
+\item Timer: \macro{TIMER\_xxx}
+\end{itemize}
+}
+
+\directive{<libs> / </libs>}{This specifies any extra libraries to be
+linked in. It is a mapping from OS to library name, for example
+\texttt{linux -> rt}, which means that on Linux librt should be linked
+in. You can also use ``all'' to force the library to be linked in on
+all systems.}
+
+\directive{<add> / </add>}{Tell the configuration script to add the
+ files named between these two tags into the source tree. All these
+ files must exist in the current module directory.}
+
+\directive{<ignore> / </ignore>}{Tell the configuration script to
+ ignore the files named in the main source tree. This is useful, for
+ example, when replacing a C++ implementation with a pure assembly
+ version.}
+
+\directive{<replace> / </replace>}{Tell the configuration script to
+ ignore the file given in the main source tree, and instead use the
+ one in the module's directory.}
+
+Additionally, the module file can contain blocks, delimited by the
+following pairs:
+
+\texttt{<os> / </os>}, \texttt{<arch> / </arch>}, \texttt{<cc> / </cc>}
+
+\noindent
+For example, putting ``alpha'' and ``ia64'' in a \texttt{<arch>} block will
+make the configuration script only allow the module to be compiled on those
+architectures. Not having a block means any value is acceptable.
+
+\pagebreak
+\section{Miscellaneous}
+
+This section has documentation for anything that just didn't fit into any of
+the major categories. Many of them (Timers, Allocators) will rarely be used in
+actual application code, but others, like the S2K algorithms, have a wide
+degree of applicability.
+
+\subsection{S2K Algorithms}
+
+There are various procedures (usually fairly ad-hoc) for turning a passphrase
+into a (mostly) arbitrary length key for a symmetric cipher. A general
+interface for such algorithms is presented in \filename{s2k.h}. The main
+function is \function{derive\_key}, which takes a passphrase, and the desired
+length of the output key, and returns a key of that length, deterministically
+produced from the passphrase. If an algorithm can't produce a key of that size,
+it will throw an exception (most notably, PKCS \#5's PBKDF1 can only produce
+strings between 1 and $n$ bytes, where $n$ is the output size of the underlying
+hash function).
+
+Most such algorithms allow the use of a ``salt'', which provides some extra
+randomness and helps against dictionary attacks on the passphrase. Simply call
+\function{change\_salt} (there are variations of it for most of the ways you
+might wish to specify a salt, check the header for details) with a block of
+random data. You can also have the class generate a new salt for you with
+\function{new\_random\_salt}; the salt that was generated can be retrieved with
+\function{current\_salt}.
+
+Additionally some algorithms allow you to set some sort of iteration
+count, which will make the algorithm take longer to compute the final
+key (reducing the speed of brute-force attacks of various kinds). This
+can be changed with the \function{set\_iterations} function. Most
+standards recommend an iteration count of at least 1000. Currently
+defined S2K algorithms are ``PBKDF1(digest)'', ``PBKDF2(digest)'', and
+``OpenPGP-S2K(digest)''; you can retrieve any of these using the
+\function{get\_s2k}, found in \filename{lookup.h}. As of this writing,
+``PBKDF2(SHA-256)'' with 10000 iterations and an 8 byte salt is
+recommend for new applications.
+
+\subsubsection{OpenPGP S2K}
+
+There are some oddities about OpenPGP's S2K algorithms that are documented
+here. For one thing, it uses the iteration count in a strange manner; instead
+of specifying how many times to iterate the hash, it tells how many
+\emph{bytes} should be hashed in total (including the salt). So the exact
+iteration count will depend on the size of the salt (which is fixed at 8 bytes
+by the OpenPGP standard, though the implementation will allow any salt size)
+and the size of the passphrase.
+
+To get what OpenPGP calls ``Simple S2K'', set iterations to 0 (the default for
+OpenPGP S2K), and do not specify a salt. To get ``Salted S2K'', again leave the
+iteration count at 0, but give an 8-byte salt. ``Salted and Iterated S2K''
+requires an 8-byte salt and some iteration count (this should be significantly
+larger than the size of the longest passphrase that might reasonably be used;
+somewhere from 1024 to 65536 would probably be about right). Using both a
+reasonably sized salt and a large iteration count is highly recommended to
+prevent password guessing attempts.
+
+\subsection{Checksums}
+
+Checksums are very similar to hash functions, and in fact share the same
+interface. But there are some significant differences, the major ones being
+that the output size is very small (usually in the range of 2 to 4 bytes), and
+is not cryptographically secure. But for their intended purpose (error
+checking), they perform very well. Some examples of checksums included in Botan
+are the Adler32 and CRC32 checksums.
+
+\subsection{Exceptions}
+
+Sooner or later, something is going to go wrong. Botan's behavior when
+something unusual occurs, like most C++ software, is to throw an exception.
+Exceptions in Botan are derived from the \type{Exception} class. You can see
+most of the major varieties of exceptions used in Botan by looking at
+\filename{exceptn.h}. The only function you really need to concern yourself
+with is \type{const char*} \function{what()}. This will return an error message
+relevant to the error that occurred. For example:
+
+\begin{verbatim}
+try {
+ // various Botan operations
+ }
+catch(Botan::Exception& e)
+ {
+ cout << "Botan exception caught: " << e.what() << endl;
+ // error handling, or just abort
+ }
+\end{verbatim}
+
+Botan's exceptions are derived from \type{std::exception}, so you don't need
+to explicitly check for Botan exceptions if you're already catching the ISO
+standard ones.
+
+\subsection{Threads and Mutexes}
+
+Botan includes a mutex system, which is used internally to lock some shared
+data structures that must be kept shared for efficiency reasons (mostly, these
+are in the allocation systems~--~handing out 1000 separate allocators hurts
+performance and makes caching memory blocks useless). This system is supported
+by the \texttt{mux\_pthr} module, implementing the \type{Mutex} interface for
+systems that have POSIX threads.
+
+If your application is using threads, you \emph{must} add the option
+``thread\_safe'' to the options string when you create the
+\type{LibraryInitializer} object. If you specify this option and no mutex type
+is available, an exception is thrown, since otherwise you would probably be
+facing a nasty crash.
+
+\subsection{Secure Memory}
+
+A major concern with mixing modern multiuser OSes and cryptographic
+code is that at any time the code (including secret keys) could be
+swapped to disk, where it can later be read by an attacker. Botan
+stores almost everything (and especially anything sensitive) in memory
+buffers that a) clear out their contents when their destructors are
+called, and b) have easy plugins for various memory locking functions,
+such as the \function{mlock}(2) call on many Unix systems.
+
+Two of the allocation method used (``malloc'' and ``mmap'') don't
+require any extra privileges on Unix, but locking memory does. At
+startup, each allocator type will attempt to allocate a few blocks
+(typically totaling 128k), so if you want, you can run your
+application \texttt{setuid} \texttt{root}, and then drop privileges
+immediately after creating your \type{LibraryInitializer}. If you end
+up using more than what's been allocated, some of your sensitive data
+might end up being swappable, but that beats running as \texttt{root}
+all the time. BTW, I would note that, at least on Linux, you can use a
+kernel module to give your process extra privileges (such as the
+ability to call \function{mlock}) without being root. For example,
+check out my Capability Override LSM
+(\url{http://www.randombit.net/projects/cap\_over/}), which makes this
+pretty easy to do.
+
+These classes should also be used within your own code for storing sensitive
+data. They are only meant for primitive data types (int, long, etc): if you
+want a container of higher level Botan objects, you can just use a
+\verb|std::vector|, since these objects know how to clear themselves when they
+are destroyed. You cannot, however, have a \verb|std::vector| (or any other
+container) of \type{Pipe}s or \type{Filter}s, because these types have pointers
+to other \type{Filter}s, and implementing copy constructors for these types
+would be both hard and quite expensive (vectors of pointers to such objects is
+fine, though).
+
+These types are not described in any great detail: for more information,
+consult the definitive sources~--~the header files \filename{secmem.h} and
+\filename{allocate.h}.
+
+\type{SecureBuffer} is a simple array type, whose size is specified at compile
+time. It will automatically convert to a pointer of the appropriate type, and
+has a number of useful functions, including \function{clear()}, and
+\type{u32bit} \function{size()}, which returns the length of the array. It is a
+template that takes as parameters a type, and a constant integer which is how
+long the array is (for example: \verb|SecureBuffer<byte, 8> key;|).
+
+\type{SecureVector} is a variable length array. Its size can be increased or
+decreased as need be, and it has a wide variety of functions useful for copying
+data into its buffer. Like \type{SecureBuffer}, it implements \function{clear}
+and \function{size}.
+
+\subsection{Allocators}
+
+The containers described above get their memory from allocators. As a user of
+the library, you can add new allocator methods at run time for containers,
+including the ones used internally by the library, to use. The interface to
+this is in \filename{allocate.h}. Basically how it works is that code needing
+an allocator uses \function{get\_allocator}, which returns a pointer to an
+allocator. This pointer should not be freed: the caller does not own the
+allocator (it is shared among multiple users, and locks itself as needed). It
+is possible to call \function{get\_allocator} with a specific name to request a
+particular type of allocator, otherwise, a default allocator type is returned.
+
+At start time, the only allocator known is a \type{Default\_Allocator}, which
+just allocates memory using \function{malloc}, and \function{memset}s it to 0
+when the memory is released. It is known by the name ``malloc''. If you ask for
+another type of allocator (``locking'' and ``mmap'' are currently used), and it
+is not available, some other allocator will be returned.
+
+You can add in a new allocator type using \function{add\_allocator\_type}. This
+function takes a string and a pointer to an allocator. The string gives this
+allocator type a name to which it can be referred when one is requesting it
+with \function{get\_allocator}. If an error occurs (such as the name being
+already registered), this function returns false. It will return true if the
+allocator was successfully registered. If you ask it to,
+\type{LibraryInitializer} will do this for you.
+
+Finally, you can set the default allocator type that will be returned using
+the policy setting ``default\_alloc'' to the name of any previously registered
+allocator.
+
+\subsection{BigInt}
+
+\type{BigInt} is Botan's implementation of a multiple-precision
+integer. Thanks to C++'s operator overloading features, using \type{BigInt} is
+often quite similar to using a native integer type. The number of functions
+related to \type{BigInt} is quite large. You can find most of them in
+\filename{bigint.h} and \filename{numthry.h}.
+
+Due to the sheer number of functions involved, only a few, which a regular user
+of the library might have to deal with, are mentioned here. Fully documenting
+the MPI library would take a significant while, so if you need to use it now,
+the best way to learn is to look at the headers.
+
+Probably the most important are the encoding/decoding functions, which
+transform the normal representation of a \type{BigInt} into some other form,
+such as a decimal string. The most useful of these functions are
+
+\type{SecureVector<byte>} \function{BigInt::encode}(\type{BigInt},
+\type{Encoding})
+
+\noindent
+and
+
+\type{BigInt} \function{BigInt::decode}(\type{SecureVector<byte>},
+\type{Encoding})
+
+\type{Encoding} is an enum that has values \type{Binary}, \type{Octal},
+\type{Decimal}, and \type{Hexadecimal}. The parameter will default to
+\type{Binary}. These functions are static member functions, so they would be
+called like this:
+
+\begin{verbatim}
+ BigInt n1; // some number
+ SecureVector<byte> n1_encoded = BigInt::encode(n1);
+ BigInt n2 = BigInt::decode(n1_encoded);
+ // now n1 == n2
+\end{verbatim}
+
+There are also C++-style I/O operators defined for use with \type{BigInt}. The
+input operator understands negative numbers, hexadecimal numbers (marked with a
+leading ``0x''), and octal numbers (marked with a leading '0'). The '-' must
+come before the ``0x'' or '0' marker. The output operator will never adorn the
+output; for example, when printing a hexadecimal number, there will not be a
+leading ``0x'' (though a leading '-' will be printed if the number is
+negative). If you want such things, you'll have to do them yourself.
+
+\type{BigInt} has constructors that can create a \type{BigInt} from an unsigned
+integer or a string. You can also decode a \type{byte}[] / length pair into a
+BigInt. There are several other \type{BigInt} constructors, which I would
+seriously recommend you avoid, as they are only intended for use internally by
+the library, and may arbitrarily change, or be removed, in a future release.
+
+An essentially random sampling of \type{BigInt} related functions:
+
+\type{u32bit} \function{BigInt::bytes}(): Return the size of this \type{BigInt}
+in bytes.
+
+\type{BigInt} \function{random\_prime(\type{u32bit} \arg{b})}: Return a prime
+number \arg{b} bits long.
+
+\type{BigInt} \function{gcd}(\type{BigInt} \arg{x}, \type{BigInt} \arg{y}):
+Returns the greatest common divisor of \arg{x} and \arg{y}. Uses the binary
+GCD algorithm.
+
+\type{bool} \function{is\_prime}(\type{BigInt} \arg{x}): Returns true if
+\arg{x} is a (possible) prime number. Uses the Miller-Rabin probabilistic
+primality test with fixed bases. For higher assurance, use
+\function{verify\_prime}, which uses more rounds and randomized 48-bit bases.
+
+\subsubsection{Efficiency Hints}
+
+If you can, always use expressions of the form \verb|a += b| over
+\verb|a = a + b|. The difference can be \emph{very} substantial, because the
+first form prevents at least one needless memory allocation, and possibly as
+many as three.
+
+If you're doing repeated modular exponentiations with the same modulus, create
+a \type{BarrettReducer} ahead of time. If the exponent or base is a constant,
+use the classes in \filename{mod\_exp.h}. This stuff is all handled for you by
+the normal high-level interfaces, of course.
+
+Never use the low-level MPI functions (those that begin with
+\texttt{bigint\_}). These are completely internal to the library, and
+may make arbitrarily strange and undocumented assumptions about their
+inputs, and don't check to see if they are actually true, on the
+assumption that only the library itself calls them, and that the
+library knows what the assumptions are. The interfaces for these
+functions can change completely without notice.
+
+\pagebreak
+\section{Algorithms}
+
+\subsection{Recommended Algorithms}
+
+This section is by no means the last word on selecting which algorithms to use.
+However, Botan includes a sometimes bewildering array of possible algorithms,
+and unless you're familiar with the latest developments in the field, it can be
+hard to know what is secure and what is not. The following attributes of the
+algorithms were evaluated when making this list: security, standardization,
+patent status, support by other implementations, and efficiency (in roughly
+that order).
+
+It is intended as a set of simple guidelines for developers, and nothing more.
+It's entirely possible that there are algorithms in Botan that will turn out to
+be more secure than the ones listed, but the algorithms listed here are
+(currently) thought to be safe.
+
+\begin{list}{$\cdot$}
+ \item Block ciphers: AES or Serpent in CBC or CTR mode
+
+ \item Hash functions: SHA-256, SHA-512
+
+ \item MACs: HMAC with any recommended hash function
+
+ \item Public Key Encryption: RSA with ``EME1(SHA-256)''
+
+ \item Public Key Signatures: RSA with EMSA4 and any recommended hash, or DSA
+ with ``EMSA1(SHA-256)''
+
+ \item Key Agreement: Diffie-Hellman, with ``KDF2(SHA-256)''
+\end{list}
+
+\subsection{Compliance with Standards}
+
+Botan is/should be at least roughly compatible with many cryptographic
+standards, including the following:
+
+\newcommand{\standard}[2]{
+ \vskip 4pt
+ * #1: \textbf{#2}
+}
+
+\standard{RSA}{PKCS \#1 v2.1, ANSI X9.31}
+
+\standard{DSA}{ANSI X9.30, FIPS 186-2}
+
+\standard{Diffie-Hellman}{ANSI X9.42, PKCS \#3}
+
+\standard{Certificates}{ITU X.509, RFC 3280/3281 (PKIX), PKCS \#9 v2.0,
+PKCS \#10}
+
+\standard{Private Key Formats}{PKCS \#5 v2.0, PKCS \#8}
+
+\standard{DES/DES-EDE}{FIPS 46-3, ANSI X3.92, ANSI X3.106}
+
+\standard{SHA-1}{FIPS 180-2}
+
+\standard{HMAC}{ANSI X9.71, FIPS 198}
+
+\standard{ANSI X9.19 MAC}{ANSI X9.9, ANSI X9.19}
+
+\vskip 8pt
+\noindent
+There is also support for the very general standards of \textbf{IEEE 1363-2000}
+and \textbf{1363a}. Most of the contents of such are included in the standards
+mentioned above, in various forms (usually with extra restrictions that 1363
+does not impose).
+
+\subsection{Algorithms Listing}
+
+Botan includes a very sizable number of cryptographic algorithms. In
+nearly all cases, you never need to know the header file or type name
+to use them. However, you do need to know what string (or strings) are
+used to identify that algorithm. Generally, these names conform to
+those set out by SCAN (Standard Cryptographic Algorithm Naming), which
+is a document that specifies how strings are mapped onto algorithm
+objects, which is useful for a wide variety of crypto APIs (SCAN is
+oriented towards Java, but Botan and several other non-Java libraries
+also make at least some use of it). For full details, read the SCAN
+document, which can be found at
+\url{http://www.users.zetnet.co.uk/hopwood/crypto/scan/}
+
+Many of these algorithms can take options (such as the number of
+rounds in a block cipher, the output size of a hash function,
+etc). These are shown in the following list; all of them default to
+reasonable values (unless otherwise marked). There are
+algorithm-specific limits on most of them. When you see something like
+``HASH'' or ``BLOCK'', that means you should insert the name of some
+algorithm of that type. There are no defaults for those options.
+
+A few very obscure algorithms are skipped; if you need one of them,
+you'll know it, and you can look in the appropriate header to see what
+that classes' \function{name} function returns (the names tend to
+match that in SCAN, if it's defined there).
+
+\begin{list}{$\cdot$}
+ \item ROUNDS: The number of rounds in a block cipher.
+ \item
+ \item OUTSZ: The output size of a hash function or MAC
+ \item PASS: The number of passes in a hash function (more passes generally
+ means more security).
+\end{list}
+
+\vskip .05in
+\noindent
+\textbf{Block Ciphers:} ``AES'', ``Blowfish'', ``CAST-128'',
+``CAST-256'', ``DES'', ``DESX'', ``TripleDES'', ``GOST'', ``IDEA'',
+``MARS'', ``MISTY1(ROUNDS)'', ``RC2'', ``RC5(ROUNDS)'', ``RC6'',
+``SAFER-SK(ROUNDS)'', ``SEED'', ``Serpent'', ``Skipjack'', ``Square'',
+``TEA'', ``Twofish'', ``XTEA''
+
+\noindent
+\textbf{Stream Ciphers:} ``ARC4'', ``MARK4'', ``Turing'', ``WiderWake4+1-BE''
+
+\noindent
+\textbf{Hash Functions:} ``FORK-256'', ``HAS-160'', ``GOST-34.11'',
+``MD2'', ``MD4'', ``MD5'', ``RIPEMD-128'', ``RIPEMD-160'',
+``SHA-160'', ``SHA-256'', ``SHA-384'', ``SHA-512'', ``Skein-512'',
+``Tiger(OUTSZ,PASS)'', ``Whirlpool''
+
+\noindent
+\textbf{MACs:} ``HMAC(HASH)'', ``CMAC(BLOCK)'', ``X9.19-MAC''
+
+\subsection{Compatibility}
+
+Generally, cryptographic algorithms are well standardized, thus
+compatibility between implementations is relatively simple (of course, not all
+algorithms are supported by all implementations). But there are a few
+algorithms that are poorly specified, and these should be avoided if you wish
+your data to be processed in the same way by another implementation (including
+future versions of Botan).
+
+The block cipher GOST has a particularly poor specification: there are no
+standard Sboxes, and the specification does not give test vectors even for
+sample boxes, which leads to issues of endian conventions, etc.
+
+If you wish maximum portability between different implementations of an
+algorithm, it's best to stick to strongly defined and well standardized
+algorithms, TripleDES, AES, HMAC, and SHA-256 all being good examples.
+
+\pagebreak
+\section{Support and Further Information}
+
+\subsection{Patents}
+
+Some of the algorithms implemented by Botan may be covered by patents in some
+locations. Algorithms known to have patent claims on them in the United States
+and that are not available in a license-free/royalty-free manner include:
+IDEA, MISTY1, RC5, RC6, and Nyberg-Rueppel.
+
+You must not assume that, just because an algorithm is not listed here, it is
+not encumbered by patents. If you have any concerns about the patent status of
+any algorithm you are considering using in an application, please discuss it
+with your attorney.
+
+\subsection{Recommended Reading}
+
+It's a very good idea if you have some knowledge of cryptography prior
+to trying to use this stuff. You really should read one or more of
+these books before seriously using the library (note that the Handbook
+of Applied Cryptography is available for free online):
+
+\setlength{\parskip}{5pt}
+
+\noindent
+\textit{Handbook of Applied Cryptography}, Alfred J. Menezes,
+Paul C. Van Oorschot, and Scott A. Vanstone; CRC Press
+
+\noindent
+\textit{Security Engineering -- A Guide to Building Dependable Distributed
+Systems}, Ross Anderson; Wiley
+
+\noindent
+\textit{Cryptography: Theory and Practice}, Douglas R. Stinson; CRC Press
+
+\noindent
+\textit{Applied Cryptography, 2nd Ed.}, Bruce Schneier; Wiley
+
+\noindent
+Once you've got the basics down, these are good things to at least take a look
+at: IEEE 1363 and 1363a, SCAN, NESSIE, PKCS \#1 v2.1, the security related FIPS
+documents, and the CFRG RFCs.
+
+\subsection{Support}
+
+Questions or problems you have with Botan can be directed to the
+development mailing list. Joining this list is highly recommended if
+you're going to be using Botan, since often advance notice of upcoming
+changes is sent there. ``Philosophical'' bug reports, announcements of
+programs using Botan, and basically anything else having to do with
+Botan are also welcome.
+
+The lists can be found at
+\url{http://lists.randombit.net/mailman/listinfo/}.
+
+\subsection{Contact Information}
+
+A PGP key with a fingerprint of
+\verb|621D AF64 11E1 851C 4CF9 A2E1 6211 EBF1 EFBA DFBC| is used to sign all
+Botan releases. This key can be found in the file \filename{doc/pgpkeys.asc};
+PGP keys for the developers are also stored there.
+
+\vskip 5pt \noindent
+Web Site: \url{http://botan.randombit.net}
+
+\subsection{License}
+
+Copyright \copyright 2000-2008, Jack Lloyd
+
+Licensed under the same terms as the Botan source
+
+\end{document}
diff --git a/old/botan/doc/architecture.pdf b/old/botan/doc/architecture.pdf
new file mode 100644
index 0000000..f0edc3f
--- /dev/null
+++ b/old/botan/doc/architecture.pdf
Binary files differ
diff --git a/old/botan/doc/building.pdf b/old/botan/doc/building.pdf
new file mode 100644
index 0000000..9b7d45a
--- /dev/null
+++ b/old/botan/doc/building.pdf
Binary files differ
diff --git a/old/botan/doc/building.tex b/old/botan/doc/building.tex
new file mode 100644
index 0000000..aa4435c
--- /dev/null
+++ b/old/botan/doc/building.tex
@@ -0,0 +1,398 @@
+\documentclass{article}
+
+\setlength{\textwidth}{6.5in}
+\setlength{\textheight}{9in}
+
+\setlength{\headheight}{0in}
+\setlength{\topmargin}{0in}
+\setlength{\headsep}{0in}
+
+\setlength{\oddsidemargin}{0in}
+\setlength{\evensidemargin}{0in}
+
+\title{\textbf{Botan Build Guide}}
+\author{Jack Lloyd \\
+ \texttt{lloyd@randombit.net}}
+\date{2008-11-24}
+
+\newcommand{\filename}[1]{\texttt{#1}}
+\newcommand{\module}[1]{\texttt{#1}}
+
+\newcommand{\type}[1]{\texttt{#1}}
+\newcommand{\function}[1]{\textbf{#1}}
+\newcommand{\macro}[1]{\texttt{#1}}
+
+\begin{document}
+
+\maketitle
+
+\tableofcontents
+
+\parskip=5pt
+\pagebreak
+
+\section{Introduction}
+
+This document describes how to build Botan on Unix/POSIX and MS
+Windows systems. The POSIX oriented descriptions should apply to most
+common Unix systems (including MacOS X), along with POSIX-ish systems
+like BeOS, QNX, and Plan 9. Currently, systems other than Windows and
+POSIX (such as VMS, MacOS 9, OS/390, OS/400, ...) are not supported by
+the build system, primarily due to lack of access. Please contact the
+maintainer if you would like to build Botan on such a system.
+
+Botan's build is controlled by configure.pl, which is a Perl
+script. Perl 5.6 or later is required.
+
+\section{For the Impatient}
+
+\begin{verbatim}
+$ ./configure.pl [--prefix=/some/directory]
+$ make
+$ make install
+\end{verbatim}
+
+Or using \verb|nmake|, if you're compiling on Windows with Visual
+C++. On platforms that do not understand the '\#!' convention for
+beginning script files, or that have Perl installed in an unusual
+spot, you might need to prefix the \texttt{configure.pl} command with
+\texttt{perl} or \texttt{/path/to/perl}.
+
+\section{Building the Library}
+
+The first step is to run \filename{configure.pl}, which is a Perl
+script that creates various directories, config files, and a Makefile
+for building everything. The script requires at least Perl 5.6; any
+later version should also work.
+
+The script will attempt to guess what kind of system you are trying
+to compile for (and will print messages telling you what it guessed).
+You can override this process by passing the options \verb|--cc|,
+\verb|--os|, and \verb|--cpu| -- acceptable values are printed if
+you run \verb|configure.pl| with \verb|--help|.
+
+You can pass basically anything reasonable with \verb|--cpu|: the
+script knows about a large number of different architectures, their
+sub-models, and common aliases for them. The script does not display
+all the possibilities in its help message because there are simply too
+many entries. You should only select the 64-bit version of a CPU (such
+as ``sparc64'' or ``mips64'') if your operating system knows how to
+handle 64-bit object code -- a 32-bit kernel on a 64-bit CPU will
+generally not like 64-bit code.
+
+By default the script tries to figure out what will work on your
+system, and use that. It will print a display at the end showing
+which algorithms have and have not been abled. For instance on one
+system we might see the line:
+
+\begin{verbatim}
+ (loading): entropy: [beos_stats] buf_es [cryptoapi_rng]
+ dev_random egd proc_walk unix_procs [win32_stats]
+\end{verbatim}
+
+The names listed in brackets are disabled, the others are
+enabled. Here we see the list of entropy sources which are going to be
+compiled into Botan. Since this particular line comes when Botan was
+configuring for a Linux system, the Win32 and BeOS specific modules
+were disabled, while modules that use Unix APIs and /dev/random are
+built.
+
+You can control which algorithms and modules are built using the
+options ``\verb|--enable-modules=MODS|'' and
+``\verb|--disable-modules=MODS|'', for instance \\
+``\verb|--enable-modules=blowfish,md5,rsa,zlib --disable-modules=arc4,cmac|''.
+Modules not listed on the command line will simply be loaded if needed
+or if configured to load by default.
+
+Not all OSes or CPUs have specific support in
+\filename{configure.pl}. If the CPU architecture of your system isn't
+supported by \filename{configure.pl}, use 'generic'. This setting
+disables machine-specific optimization flags. Similarly, setting OS to
+'generic' disables things which depend greatly on OS support
+(specifically, shared libraries).
+
+However, it's impossible to guess which options to give to a system
+compiler. Thus, if you want to compile Botan with a compiler which
+\filename{configure.pl} does not support, you will need to tell it how
+that compiler works. This is done by adding a new file in the
+directory \filename{src/build-data/cc}; the existing files should put you
+in the right direction.
+
+The script tries to guess what kind of makefile to generate, and it
+almost always guesses correctly (basically, Visual C++ uses NMAKE with
+Windows commands, and everything else uses Unix make with POSIX
+commands). Just in case, you can override it with
+\verb|--make-style=somestyle|. The styles Botan currently knows about
+are 'unix' (normal Unix makefiles), and 'nmake', the make variant
+commonly used by Windows compilers. To add a new variant (eg, a build
+script for VMS), you will need to create a new template file in
+\filename{src/build-data/makefile}.
+
+\pagebreak
+
+\subsection{POSIX / Unix}
+
+The basic build procedure on Unix and Unix-like systems is:
+
+\begin{verbatim}
+ $ ./configure.pl [--enable-modules=<list>] [--cc=CC]
+ $ make
+ # You may need to set your LD_LIBRARY_PATH or equivalent for ./check to run
+ $ make check # optional, but a good idea
+ $ make install
+\end{verbatim}
+
+This will probably default to using GCC, depending on what can be
+found within your PATH.
+
+The \verb|make install| target has a default directory in which it
+will install Botan (typically \verb|/usr/local|). You can override
+this by using the \texttt{--prefix} argument to
+\filename{configure.pl}, like so:
+
+\verb|./configure.pl --prefix=/opt <other arguments>|
+
+On some systems shared libraries might not be immediately visible to
+the runtime linker. For example, on Linux you may have to edit
+\filename{/etc/ld.so.conf} and run \texttt{ldconfig} (as root) in
+order for new shared libraries to be picked up by the linker. An
+alternative is to set your \texttt{LD\_LIBRARY\_PATH} shell variable
+to include the directory that the Botan libraries were installed into.
+
+\subsection{MS Windows}
+
+The situation is not much different here. We'll assume you're using Visual C++
+(for Cygwin, the Unix instructions are probably more relevant). You need to
+have a copy of Perl installed, and have both Perl and Visual C++ in your path.
+
+\begin{verbatim}
+ > perl configure.pl --cc=msvc (or --cc=gcc for MinGW) [--cpu=CPU]
+ > nmake
+ > nmake check # optional, but recommended
+\end{verbatim}
+
+For Win95 pre OSR2, the \verb|cryptoapi_rng| module will not work,
+because CryptoAPI didn't exist. And all versions of NT4 lack the
+ToolHelp32 interface, which is how \verb|win32_stats| does its slow
+polls, so a version of the library built with that module will not
+load under NT4. Later systems (98/ME/2000/XP) support both methods, so
+this shouldn't be much of an issue.
+
+Unfortunately, there currently isn't an install script usable on
+Windows. Basically all you have to do is copy the newly created
+\filename{libbotan.lib} to someplace where you can find it later (say,
+\verb|C:\botan\|). Then copy the entire \verb|build\include\botan|
+directory, which was constructed when you built the library, into the
+same directory.
+
+When building your applications, all you have to do is tell the
+compiler to look for both include files and library files in
+\verb|C:\botan|, and it will find both. Or you can move them to a
+place where they will be in the default compiler search paths (consult
+your documentation and/or local expert for details).
+
+\pagebreak
+
+\subsection{Configuration Parameters}
+
+There are some configuration parameters which you may want to tweak
+before building the library. These can be found in
+\filename{config.h}. This file is overwritten every time the configure
+script is run (and does not exist until after you run the script for
+the first time).
+
+Also included in \filename{build/build.h} are macros which are defined
+if one or more extensions are available. All of them begin with
+\verb|BOTAN_HAS_|. For example, if \verb|BOTAN_HAS_COMPRESSOR_BZIP2|
+is defined, then an application using Botan can include
+\filename{<botan/bzip2.h>} and use the Bzip2 filters.
+
+\macro{BOTAN\_MP\_WORD\_BITS}: This macro controls the size of the
+words used for calculations with the MPI implementation in Botan. You
+can choose 8, 16, 32, or 64, with 32 being the default. You can use 8,
+16, or 32 bit words on any CPU, but the value should be set to the
+same size as the CPU's registers for best performance. You can only
+use 64-bit words if an assembly module (such as \module{mp\_ia32} or
+\module{mp\_asm64}) is used. If the appropriate module is available,
+64 bits are used, otherwise this is set to 32. Unless you are building
+for a 8 or 16-bit CPU, this isn't worth messing with.
+
+\macro{BOTAN\_VECTOR\_OVER\_ALLOCATE}: The memory container
+\type{SecureVector} will over-allocate requests by this amount (in
+elements). In several areas of the library, we grow a vector fairly often. By
+over-allocating by a small amount, we don't have to do allocations as often
+(which is good, because the allocators can be quite slow). If you \emph{really}
+want to reduce memory usage, set it to 0. Otherwise, the default should be
+perfectly fine.
+
+\macro{BOTAN\_DEFAULT\_BUFFER\_SIZE}: This constant is used as the size of
+buffers throughout Botan. A good rule of thumb would be to use the page size of
+your machine. The default should be fine for most, if not all, purposes.
+
+\macro{BOTAN\_GZIP\_OS\_CODE}: The OS code is included in the Gzip header when
+compressing. The default is 255, which means 'Unknown'. You can look in RFC
+1952 for the full list; the most common are Windows (0) and Unix (3). There is
+also a Macintosh (7), but it probably makes more sense to use the Unix code on
+OS X.
+
+\subsection{Multiple Builds}
+
+It may be useful to run multiple builds with different
+configurations. Specify \verb|--build-dir=<dir>| to set up a build
+environment in a different directory.
+
+\subsection{Local Configuration}
+
+You may want to do something peculiar with the configuration; to
+support this there is a flag to \filename{configure.pl} called
+\texttt{--with-local-config=<file>}. The contents of the file are
+inserted into \filename{build/build.h} which is (indirectly) included
+into every Botan header and source file.
+
+\pagebreak
+
+\section{Modules}
+
+There are a fairly large number of modules included with Botan. Some
+of these are extremely useful, while others are only necessary in very
+unusual circumstances. The modules included with this release are:
+
+\newcommand{\mod}[2]{\textbf{#1}: #2}
+
+\begin{list}{$\cdot$}
+ \item \mod{alloc\_mmap}{Allocates memory using memory mappings of temporary
+ files. This means that if the OS swaps all or part of the application,
+ the sensitive data will be swapped to where we can later clean it,
+ rather than somewhere in the swap partition.}
+
+ \item \mod{bzip2}{Enables an application to perform bzip2 compression
+ and decompression using the library. Available on any system that has
+ bzip2.}
+
+ \item \mod{zlib}{Enables an application to perform zlib compression and
+ decompression using the library. Available on any system that has
+ zlib.}
+
+ %\item \mod{eng\_aep}{An engine that uses any available AEP accelerator card
+ % to speed up PK operations. You have to have the AEP drivers installed
+ % for this to link correctly, but you don't have to have a card
+ % installed - it will automatically be enabled if a card is detected at
+ % run time.}
+
+ \item \mod{gnump}{An engine that uses GNU MP to speed up PK operations.
+ GNU MP 4.1 or later is required.}
+
+ \item \mod{openssl}{An engine that uses OpenSSL to speed up public key
+ operations and some ciphers/hashes. OpenSSL 0.9.7 or
+ later is required.}
+
+ \item \mod{beos\_stats}{An entropy source that uses BeOS-specific
+ APIs to gather (hopefully unpredictable) data from the system.}
+
+ \item \mod{cryptoapi\_rng}{An entropy source that uses the Win32
+ CryptoAPI function \texttt{CryptGenRandom} to gather
+ entropy. Supported on NT4, Win95 OSR2, and all later Windows
+ systems.}
+
+ \item \mod{egd}{An entropy source that accesses EGD (the entropy
+ gathering daemon). Common on Unix systems that don't have
+ \texttt{/dev/random}.}
+
+ \item \mod{proc\_walk}{Gather entropy by reading files from a particular file
+ tree. Usually used with \texttt{/proc}; most other file trees don't
+ have sufficient variability over time to be useful.}
+
+ \item \mod{unix\_procs}{Gather entropy by running various Unix programs, like
+ \texttt{arp} and \texttt{vmstat}, and reading their output in the
+ hopes that at least some of it will be unpredictable to an attacker.}
+
+ \item \mod{win32\_stats}{Gather entropy by walking through various pieces of
+ information about processes running on the system. Does not run on
+ NT4, but should run on all other Win32 systems.}
+
+ \item \mod{fd\_unix}{Let the users of \texttt{Pipe} perform I/O with Unix
+ file descriptors in addition to \texttt{iostream} objects.}
+
+ \item \mod{pthread}{Add support for using \texttt{pthread} mutexes to
+ lock internal data structures. Important if you are using threads
+ with the library.}
+
+ \item \mod{qt\_mutex}{Add support for using Qt mutexes to lock internal data
+ structures.}
+
+ \item \mod{cpu\_counter}{Use the contents of the CPU cycle counter when
+ generating random bits to further randomize the results. Works on x86
+ (Pentium and up), Alpha, and SPARCv9.}
+
+ \item \mod{posix\_rt}{Use the POSIX realtime clock as a high-resolution
+ timer.}
+
+ \item \mod{gettimeofday}{Use the traditional Unix
+ \texttt{gettimeofday} as a high resolution timer.}
+
+ \item \mod{win32\_query\_perf\_ctr}{Use Win32's
+ \texttt{QueryPerformanceCounter} as a high resolution timer.}
+
+\end{list}
+
+\pagebreak
+
+\section{Building Applications}
+
+\subsection{Unix}
+
+Botan usually links in several different system libraries (such as
+\texttt{librt} and \texttt{libz}), depending on which modules are
+configured at compile time. In many environments, particularly ones
+using static libraries, an application has to link against the same
+libraries as Botan for the linking step to succeed. But how does it
+figure out what libraries it \emph{is} linked against?
+
+The answer is to ask the \filename{botan-config} script. This
+basically solves the same problem all the other \filename{*-config}
+scripts solve, and in basically the same manner.
+
+There are 4 options:
+
+\texttt{--prefix[=DIR]}: If no argument, print the prefix where Botan
+is installed (such as \filename{/opt} or \filename{/usr/local}). If an
+argument is specified, other options given with the same command will
+execute as if Botan as actually installed at \filename{DIR} and not
+where it really is; or at least where \filename{botan-config} thinks
+it really is. I should mention that it
+
+\texttt{--version}: Print the Botan version number.
+
+\texttt{--cflags}: Print options that should be passed to the compiler
+whenever a C++ file is compiled. Typically this is used for setting
+include paths.
+
+\texttt{--libs}: Print options for which libraries to link to (this includes
+\texttt{-lbotan}).
+
+Your \filename{Makefile} can run \filename{botan-config} and get the
+options necessary for getting your application to compile and link,
+regardless of whatever crazy libraries Botan might be linked against.
+
+Botan also by default installs a file for \texttt{pkg-config},
+namespaced by the major and minor versions. So it can be used,
+for instance, as
+
+\begin{verbatim}
+$ pkg-config botan-1.8 --modversion
+1.8.0
+$ pkg-config botan-1.8 --cflags
+-I/usr/local/include
+$ pkg-config botan-1.8 --libs
+-L/usr/local/lib -lbotan -lm -lbz2 -lpthread -lrt
+\end{verbatim}
+
+\subsection{MS Windows}
+
+No special help exists for building applications on Windows. However,
+given that typically Windows software is distributed as binaries, this
+is less of a problem - only the developer needs to worry about it. As
+long as they can remember where they installed Botan, they just have
+to set the appropriate flags in their Makefile/project file.
+
+\end{document}
diff --git a/old/botan/doc/credits.txt b/old/botan/doc/credits.txt
new file mode 100644
index 0000000..ef2ee6b
--- /dev/null
+++ b/old/botan/doc/credits.txt
@@ -0,0 +1,78 @@
+ This is the credits file of people that have contributed to Botan. It uses
+ the same format as the Linux credits file. Please keep it sorted by last
+ name.
+
+ The fields are:
+ N - name
+ E - email
+ W - web URL
+ P - PGP fingerprint
+ D - description
+ S - meatspace location
+----------
+
+N - Charles Brockman
+W - http://www.securitygenetics.com/
+D - documentation editing
+S - Oregon, USA
+
+N: Martin Doering
+E: doering@cdc.informatik.tu-darmstadt.de
+D: GF(p) arithmetic
+
+N: Matthew Gregan
+D: Binary file I/O support, allocator fixes
+
+N: Hany Greiss
+D: Windows porting
+
+N: Manuel Hartl
+E: hartl@flexsecure.de
+W: http://www.flexsecure.de/
+D: ECDSA, ECKAEG
+
+N: Yves Jerschow
+E: yves.jerschow@uni-duesseldorf.de
+D: Optimizations for memory load/store and HMAC
+D: Support for IPv4 addresses in X.509 alternative names
+S: Germany
+
+N: Matt Johnston
+D: Allocator fixes and optimizations, decompressor fixes
+
+N: Peter J. Jones
+E: pjones@pmade.org
+D: Bzip2 compression module
+S: Colorado, USA
+
+N: Justin Karneges
+D: Qt support modules (mutexes and types), X.509 API design
+
+N: Jack Lloyd
+E: lloyd@randombit.net
+W: http://www.randombit.net/
+P: 3F69 2E64 6D92 3BBE E7AE 9258 5C0F 96E8 4EC1 6D6B
+D: Original designer/author, maintainer 2001-current
+S: Vermont, USA
+
+N: Joel Low
+D: DLL symbol visibility
+
+N: Christoph Ludwig
+E: ludwig@fh-worms.de
+D: GP(p) arithmetic
+
+N: Vaclav Ovsik
+E: vaclav.ovsik@i.cz
+D: Perl XS module
+
+N: Luca Piccarreta
+E: luca.piccarreta@gmail.com
+D: x86/amd64 assembler, BigInt optimizations, Win32 mutex module
+S: Italy
+
+N: Falko Strenzke
+E: strenzke@flexsecure.de
+W: http://www.flexsecure.de/
+D: GF(p) arithmetic, CVC, Shanks-Tonelli algorithm
+S: Darmstadt, Germany
diff --git a/old/botan/doc/examples/GNUmakefile b/old/botan/doc/examples/GNUmakefile
new file mode 100644
index 0000000..d854c81
--- /dev/null
+++ b/old/botan/doc/examples/GNUmakefile
@@ -0,0 +1,21 @@
+
+BOTAN_CONFIG = botan-config
+
+CXX = g++
+CFLAGS = -O2 -ansi -W -Wall $(shell $(BOTAN_CONFIG) --cflags)
+LIBS = $(shell $(BOTAN_CONFIG) --libs)
+
+SRCS=$(wildcard *.cpp)
+
+PROGS=$(patsubst %.cpp,%,$(SRCS))
+
+all: $(PROGS)
+
+clean:
+ @rm -f $(PROGS)
+
+%: %.cpp
+ $(CXX) $(CFLAGS) $? $(LIBS) -o $@
+
+eax_test: eax_test.cpp
+ $(CXX) $(CFLAGS) $? $(LIBS) -lboost_regex -o $@
diff --git a/old/botan/doc/examples/asn1.cpp b/old/botan/doc/examples/asn1.cpp
new file mode 100644
index 0000000..e8fc015
--- /dev/null
+++ b/old/botan/doc/examples/asn1.cpp
@@ -0,0 +1,312 @@
+/*
+ A simple ASN.1 parser, similiar to 'dumpasn1' or 'openssl asn1parse', though
+ without some of the bells and whistles of those. Primarily used for testing
+ the BER decoder. The output format is modeled loosely on 'asn1parse -i'
+
+ The output is actually less precise than the other decoders named, because
+ the underlying BER_Decoder hides quite a bit from userspace, such as the use
+ of indefinite length encodings (and the EOC markers). At some point it will
+ also hide the constructed string types from the user, but right now you'll
+ seem them as-is.
+
+ Written by Jack Lloyd, November 9-10, 2003
+ - Nov 22: Updated to new BER_Object format (tag -> class_tag/type_tag)
+ - Nov 25: Much improved BIT STRING output
+ Can deal with non-constructed taggings
+ Can produce UTF-8 output
+
+ This file is in the public domain.
+*/
+
+/*******************************************************************/
+
+// Set this if your terminal understands UTF-8; otherwise output is in Latin-1
+#define UTF8_TERMINAL 1
+
+/*
+ What level the outermost layer of stuff is at. Probably 0 or 1; asn1parse
+ uses 0 as the outermost, while 1 makes more sense to me. 2+ doesn't make
+ much sense at all.
+*/
+#define INITIAL_LEVEL 0
+
+/*******************************************************************/
+
+#include <botan/botan.h>
+#include <botan/bigint.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/asn1_obj.h>
+#include <botan/oids.h>
+#include <botan/pem.h>
+#include <botan/charset.h>
+using namespace Botan;
+
+#include <stdio.h>
+#include <ctype.h>
+
+void decode(BER_Decoder&, u32bit);
+void emit(const std::string&, u32bit, u32bit, const std::string& = "");
+std::string type_name(ASN1_Tag);
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 2)
+ {
+ printf("Usage: %s <file>\n", argv[0]);
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ try {
+ DataSource_Stream in(argv[1]);
+
+ if(!PEM_Code::matches(in))
+ {
+ BER_Decoder decoder(in);
+ decode(decoder, INITIAL_LEVEL);
+ }
+ else
+ {
+ std::string label; // ignored
+ BER_Decoder decoder(PEM_Code::decode(in, label));
+ decode(decoder, INITIAL_LEVEL);
+ }
+
+ }
+ catch(std::exception& e)
+ {
+ printf("%s\n", e.what());
+ return 1;
+ }
+ return 0;
+ }
+
+void decode(BER_Decoder& decoder, u32bit level)
+ {
+ BER_Object obj = decoder.get_next_object();
+
+ while(obj.type_tag != NO_OBJECT)
+ {
+ const ASN1_Tag type_tag = obj.type_tag;
+ const ASN1_Tag class_tag = obj.class_tag;
+ const u32bit length = obj.value.size();
+
+ /* hack to insert the tag+length back in front of the stuff now
+ that we've gotten the type info */
+ DER_Encoder encoder;
+ encoder.add_object(type_tag, class_tag, obj.value, obj.value.size());
+ SecureVector<byte> bits = encoder.get_contents();
+
+ BER_Decoder data(bits);
+
+ if(class_tag & CONSTRUCTED)
+ {
+ BER_Decoder cons_info(obj.value);
+ if(type_tag == SEQUENCE)
+ {
+ emit("SEQUENCE", level, length);
+ decode(cons_info, level+1);
+ }
+ else if(type_tag == SET)
+ {
+ emit("SET", level, length);
+ decode(cons_info, level+1);
+ }
+ else
+ {
+ std::string name;
+
+ if((class_tag & APPLICATION) || (class_tag & CONTEXT_SPECIFIC) ||
+ (class_tag & PRIVATE))
+ {
+ name = "cons [" + to_string(type_tag) + "]";
+
+ if(class_tag & APPLICATION)
+ name += " appl";
+ if(class_tag & CONTEXT_SPECIFIC)
+ name += " context";
+ if(class_tag & PRIVATE)
+ name += " private";
+ }
+ else
+ name = type_name(type_tag) + " (cons)";
+
+ emit(name, level, length);
+ decode(cons_info, level+1);
+ }
+ }
+ else if(class_tag == APPLICATION || class_tag == CONTEXT_SPECIFIC ||
+ class_tag == PRIVATE)
+ {
+ bool not_text = false;
+
+ for(u32bit j = 0; j != bits.size(); j++)
+ if(!isgraph(bits[j]) && !isspace(bits[j]))
+ not_text = true;
+
+ Pipe pipe(((not_text) ? new Hex_Encoder : 0));
+ pipe.process_msg(bits);
+ emit("[" + to_string(type_tag) + "]", level, length,
+ pipe.read_all_as_string());
+ }
+ else if(type_tag == OBJECT_ID)
+ {
+ OID oid;
+ data.decode(oid);
+
+ std::string out = OIDS::lookup(oid);
+ if(out != oid.as_string())
+ out += " [" + oid.as_string() + "]";
+
+ emit(type_name(type_tag), level, length, out);
+ }
+ else if(type_tag == INTEGER)
+ {
+ BigInt number;
+ data.decode(number);
+
+ SecureVector<byte> rep;
+
+ /* If it's small, it's probably a number, not a hash */
+ if(number.bits() <= 16)
+ rep = BigInt::encode(number, BigInt::Decimal);
+ else
+ rep = BigInt::encode(number, BigInt::Hexadecimal);
+
+ std::string str;
+ for(u32bit j = 0; j != rep.size(); j++)
+ str += (char)rep[j];
+
+ emit(type_name(type_tag), level, length, str);
+ }
+ else if(type_tag == BOOLEAN)
+ {
+ bool boolean;
+ data.decode(boolean);
+ emit(type_name(type_tag),
+ level, length, (boolean ? "true" : "false"));
+ }
+ else if(type_tag == NULL_TAG)
+ {
+ emit(type_name(type_tag), level, length);
+ }
+ else if(type_tag == OCTET_STRING)
+ {
+ SecureVector<byte> bits;
+ data.decode(bits, type_tag);
+ bool not_text = false;
+
+ for(u32bit j = 0; j != bits.size(); j++)
+ if(!isgraph(bits[j]) && !isspace(bits[j]))
+ not_text = true;
+
+ Pipe pipe(((not_text) ? new Hex_Encoder : 0));
+ pipe.process_msg(bits);
+ emit(type_name(type_tag), level, length, pipe.read_all_as_string());
+ }
+ else if(type_tag == BIT_STRING)
+ {
+ SecureVector<byte> bits;
+ data.decode(bits, type_tag);
+
+ std::vector<bool> bit_set;
+
+ for(u32bit j = 0; j != bits.size(); j++)
+ for(u32bit k = 0; k != 8; k++)
+ bit_set.push_back((bool)((bits[bits.size()-j-1] >> (7-k)) & 1));
+
+ std::string bit_str;
+ for(u32bit j = 0; j != bit_set.size(); j++)
+ {
+ bool the_bit = bit_set[bit_set.size()-j-1];
+
+ if(!the_bit && bit_str.size() == 0)
+ continue;
+ bit_str += (the_bit ? "1" : "0");
+ }
+
+ emit(type_name(type_tag), level, length, bit_str);
+ }
+ else if(type_tag == PRINTABLE_STRING ||
+ type_tag == NUMERIC_STRING ||
+ type_tag == IA5_STRING ||
+ type_tag == T61_STRING ||
+ type_tag == VISIBLE_STRING ||
+ type_tag == UTF8_STRING ||
+ type_tag == BMP_STRING)
+ {
+ ASN1_String str;
+ data.decode(str);
+ if(UTF8_TERMINAL)
+ emit(type_name(type_tag), level, length,
+ Charset::transcode(str.iso_8859(),
+ LATIN1_CHARSET, UTF8_CHARSET));
+ else
+ emit(type_name(type_tag), level, length, str.iso_8859());
+ }
+ else if(type_tag == UTC_TIME || type_tag == GENERALIZED_TIME)
+ {
+ X509_Time time;
+ data.decode(time);
+ emit(type_name(type_tag), level, length, time.readable_string());
+ }
+ else
+ fprintf(stderr, "Unknown tag: class=%02X, type=%02X\n",
+ class_tag, type_tag);
+
+ obj = decoder.get_next_object();
+ }
+ }
+
+void emit(const std::string& type, u32bit level, u32bit length,
+ const std::string& value)
+ {
+ const u32bit LIMIT = 128;
+ const u32bit BIN_LIMIT = 64;
+
+ int written = 0;
+ written += printf(" d=%2d, l=%4d: ", level, length);
+ for(u32bit j = INITIAL_LEVEL; j != level; j++)
+ written += printf(" ");
+ written += printf("%s ", type.c_str());
+
+ bool should_skip = false;
+ if(value.length() > LIMIT) should_skip = true;
+ if((type == "OCTET STRING" || type == "BIT STRING") &&
+ value.length() > BIN_LIMIT)
+ should_skip = true;
+
+ if(value != "" && !should_skip)
+ {
+ if(written % 2 == 0) printf(" ");
+ while(written < 50) written += printf(" ");
+ printf(":%s\n", value.c_str());
+ }
+ else
+ printf("\n");
+ }
+
+std::string type_name(ASN1_Tag type)
+ {
+ if(type == PRINTABLE_STRING) return "PRINTABLE STRING";
+ if(type == NUMERIC_STRING) return "NUMERIC STRING";
+ if(type == IA5_STRING) return "IA5 STRING";
+ if(type == T61_STRING) return "T61 STRING";
+ if(type == UTF8_STRING) return "UTF8 STRING";
+ if(type == VISIBLE_STRING) return "VISIBLE STRING";
+ if(type == BMP_STRING) return "BMP STRING";
+
+ if(type == UTC_TIME) return "UTC TIME";
+ if(type == GENERALIZED_TIME) return "GENERALIZED TIME";
+
+ if(type == OCTET_STRING) return "OCTET STRING";
+ if(type == BIT_STRING) return "BIT STRING";
+
+ if(type == INTEGER) return "INTEGER";
+ if(type == NULL_TAG) return "NULL";
+ if(type == OBJECT_ID) return "OBJECT";
+ if(type == BOOLEAN) return "BOOLEAN";
+ return "(UNKNOWN)";
+ }
diff --git a/old/botan/doc/examples/base.cpp b/old/botan/doc/examples/base.cpp
new file mode 100644
index 0000000..eca0ccf
--- /dev/null
+++ b/old/botan/doc/examples/base.cpp
@@ -0,0 +1,44 @@
+/*
+ A simple template for Botan applications, showing startup, etc
+*/
+#include <botan/botan.h>
+using namespace Botan;
+
+/* This is how you can do compile-time version checking */
+
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,6,3)
+ #error Your Botan installation is too old; upgrade to 1.6.3 or later
+#endif
+
+#include <iostream>
+
+int main(int argc, char* argv[])
+ {
+ Botan::LibraryInitializer init;
+
+ try
+ {
+ /* Put it inside the try block so exceptions at startup/shutdown will
+ get caught.
+
+ It will be initialized with default options
+ */
+
+ if(argc > 2)
+ {
+ std::cout << "Usage: " << argv[0] << "[initializer args]\n";
+ return 2;
+ }
+
+ std::string args = (argc == 2) ? argv[1] : "";
+
+ LibraryInitializer init(args);
+ // your operations here
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
diff --git a/old/botan/doc/examples/base64.cpp b/old/botan/doc/examples/base64.cpp
new file mode 100644
index 0000000..d35aaf5
--- /dev/null
+++ b/old/botan/doc/examples/base64.cpp
@@ -0,0 +1,82 @@
+/*
+An Botan example application which emulates a poorly written version of
+"uuencode -m"
+
+Written by Jack Lloyd (lloyd@randombit.net), in maybe an hour scattered
+over 2000/2001
+
+This file is in the public domain
+*/
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <vector>
+#include <cstring>
+#include <cstdlib>
+#include <botan/botan.h>
+
+int main(int argc, char* argv[])
+ {
+ if(argc < 2)
+ {
+ std::cout << "Usage: " << argv[0] << " [-w] [-c n] [-e|-d] files...\n"
+ " -e : Encode input to base64 strings (default) \n"
+ " -d : Decode base64 input\n"
+ " -w : Wrap lines\n"
+ " -c n: Wrap lines at column n, default 78\n";
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ int column = 78;
+ bool wrap = false;
+ bool encoding = true;
+ std::vector<std::string> files;
+
+ for(int j = 1; argv[j] != 0; j++)
+ {
+ std::string this_arg = argv[j];
+
+ if(this_arg == "-w")
+ wrap = true;
+ else if(this_arg == "-e");
+ else if(this_arg == "-d")
+ encoding = false;
+ else if(this_arg == "-c")
+ {
+ if(argv[j+1])
+ { column = atoi(argv[j+1]); j++; }
+ else
+ {
+ std::cout << "No argument for -c option" << std::endl;
+ return 1;
+ }
+ }
+ else files.push_back(argv[j]);
+ }
+
+ for(unsigned int j = 0; j != files.size(); j++)
+ {
+ std::istream* stream;
+ if(files[j] == "-") stream = &std::cin;
+ else stream = new std::ifstream(files[j].c_str());
+
+ if(!*stream)
+ {
+ std::cout << "ERROR, couldn't open " << files[j] << std::endl;
+ continue;
+ }
+
+ Botan::Pipe pipe((encoding) ?
+ ((Botan::Filter*)new Botan::Base64_Encoder(wrap, column)) :
+ ((Botan::Filter*)new Botan::Base64_Decoder));
+ pipe.start_msg();
+ *stream >> pipe;
+ pipe.end_msg();
+ pipe.set_default_msg(j);
+ std::cout << pipe;
+ if(files[j] != "-") delete stream;
+ }
+ return 0;
+ }
diff --git a/old/botan/doc/examples/bench.cpp b/old/botan/doc/examples/bench.cpp
new file mode 100644
index 0000000..37ef110
--- /dev/null
+++ b/old/botan/doc/examples/bench.cpp
@@ -0,0 +1,98 @@
+#include <botan/benchmark.h>
+#include <botan/init.h>
+#include <botan/auto_rng.h>
+#include <botan/libstate.h>
+
+using namespace Botan;
+
+#include <iostream>
+
+double best_speed(const std::string& algorithm,
+ u32bit milliseconds,
+ RandomNumberGenerator& rng,
+ Timer& timer)
+ {
+ std::map<std::string, double> speeds =
+ algorithm_benchmark(algorithm, milliseconds,
+ timer, rng,
+ global_state().algorithm_factory());
+
+ double best_time = 0;
+
+ for(std::map<std::string, double>::const_iterator i = speeds.begin();
+ i != speeds.end(); ++i)
+ if(i->second > best_time)
+ best_time = i->second;
+
+ return best_time;
+ }
+
+const std::string algos[] = {
+ "AES-128",
+ "AES-192",
+ "AES-256",
+ "Blowfish",
+ "CAST-128",
+ "CAST-256",
+ "DES",
+ "DESX",
+ "TripleDES",
+ "GOST",
+ "IDEA",
+ "KASUMI",
+ "Lion(SHA-256,Turing,8192)",
+ "Luby-Rackoff(SHA-512)",
+ "MARS",
+ "MISTY1",
+ "Noekeon",
+ "RC2",
+ "RC5(12)",
+ "RC5(16)",
+ "RC6",
+ "SAFER-SK(10)",
+ "SEED",
+ "Serpent",
+ "Skipjack",
+ "Square",
+ "TEA",
+ "Twofish",
+ "XTEA",
+ "Adler32",
+ "CRC32",
+ "FORK-256",
+ "GOST-34.11",
+ "HAS-160",
+ "HAS-V",
+ "MD2",
+ "MD4",
+ "MD5",
+ "RIPEMD-128",
+ "RIPEMD-160",
+ "SHA-160",
+ "SHA-256",
+ "SHA-384",
+ "SHA-512",
+ "Skein-512",
+ "Tiger",
+ "Whirlpool",
+ "CMAC(AES-128)",
+ "HMAC(SHA-1)",
+ "X9.19-MAC",
+ "",
+};
+
+int main()
+ {
+ LibraryInitializer init;
+
+ u32bit milliseconds = 1000;
+ AutoSeeded_RNG rng;
+ Default_Benchmark_Timer timer;
+
+ for(u32bit i = 0; algos[i] != ""; ++i)
+ {
+ std::string algo = algos[i];
+ std::cout << algo << ' '
+ << best_speed(algo, milliseconds, rng, timer) << "\n";
+ }
+ }
diff --git a/old/botan/doc/examples/benchmark.cpp b/old/botan/doc/examples/benchmark.cpp
new file mode 100644
index 0000000..d046e8d
--- /dev/null
+++ b/old/botan/doc/examples/benchmark.cpp
@@ -0,0 +1,41 @@
+#include <botan/botan.h>
+#include <botan/benchmark.h>
+
+#include <iostream>
+#include <string>
+#include <map>
+#include <cstdlib>
+
+int main(int argc, char* argv[])
+ {
+ if(argc <= 2)
+ {
+ std::cout << "Usage: " << argv[0] << " seconds <algo1> <algo2> ...\n";
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ Botan::AutoSeeded_RNG rng;
+ Botan::Default_Benchmark_Timer timer;
+
+ Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory();
+
+ double ms = 1000 * std::atof(argv[1]);
+
+ for(size_t i = 2; argv[i]; ++i)
+ {
+ std::string algo = argv[i];
+
+ std::map<std::string, double> results =
+ Botan::algorithm_benchmark(algo, ms, timer, rng, af);
+
+ std::cout << algo << ":\n";
+ for(std::map<std::string, double>::iterator r = results.begin();
+ r != results.end(); ++r)
+ {
+ std::cout << " " << r->first << ": " << r->second << " MiB/s\n";
+ }
+ std::cout << "\n";
+ }
+ }
diff --git a/old/botan/doc/examples/bzip.cpp b/old/botan/doc/examples/bzip.cpp
new file mode 100644
index 0000000..02252fb
--- /dev/null
+++ b/old/botan/doc/examples/bzip.cpp
@@ -0,0 +1,108 @@
+/*
+An Botan example application which emulates a poorly written version of bzip2
+
+Written by Jack Lloyd (lloyd@randombit.net), Jun 9, 2001
+
+This file is in the public domain
+*/
+#include <string>
+#include <cstring>
+#include <vector>
+#include <fstream>
+#include <iostream>
+#include <botan/botan.h>
+
+#if defined(BOTAN_HAS_COMPRESSOR_BZIP2)
+ #include <botan/bzip2.h>
+#endif
+
+const std::string SUFFIX = ".bz2";
+
+int main(int argc, char* argv[])
+ {
+ if(argc < 2)
+ {
+ std::cout << "Usage: " << argv[0]
+ << " [-s] [-d] [-1...9] <filenames>" << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ std::vector<std::string> files;
+ bool decompress = false, small = false;
+ int level = 9;
+
+ for(int j = 1; argv[j] != 0; j++)
+ {
+ if(std::strcmp(argv[j], "-d") == 0) { decompress = true; continue; }
+ if(std::strcmp(argv[j], "-s") == 0) { small = true; continue; }
+ if(std::strcmp(argv[j], "-1") == 0) { level = 1; continue; }
+ if(std::strcmp(argv[j], "-2") == 0) { level = 2; continue; }
+ if(std::strcmp(argv[j], "-3") == 0) { level = 3; continue; }
+ if(std::strcmp(argv[j], "-4") == 0) { level = 4; continue; }
+ if(std::strcmp(argv[j], "-5") == 0) { level = 5; continue; }
+ if(std::strcmp(argv[j], "-6") == 0) { level = 6; continue; }
+ if(std::strcmp(argv[j], "-7") == 0) { level = 7; continue; }
+ if(std::strcmp(argv[j], "-8") == 0) { level = 8; continue; }
+ if(std::strcmp(argv[j], "-9") == 0) { level = 9; continue; }
+ files.push_back(argv[j]);
+ }
+
+ try {
+
+ Botan::Filter* bzip = 0;
+#ifdef BOTAN_HAS_COMPRESSOR_BZIP2
+ if(decompress)
+ bzip = new Botan::Bzip_Decompression(small);
+ else
+ bzip = new Botan::Bzip_Compression(level);
+#endif
+
+ if(!bzip)
+ {
+ std::cout << "Sorry, support for bzip2 not compiled into Botan\n";
+ return 1;
+ }
+
+ Botan::Pipe pipe(bzip);
+
+ for(unsigned int j = 0; j != files.size(); j++)
+ {
+ std::string infile = files[j], outfile = files[j];
+ if(!decompress)
+ outfile = outfile += SUFFIX;
+ else
+ outfile = outfile.replace(outfile.find(SUFFIX),
+ SUFFIX.length(), "");
+
+ std::ifstream in(infile.c_str());
+ std::ofstream out(outfile.c_str());
+ if(!in)
+ {
+ std::cout << "ERROR: could not read " << infile << std::endl;
+ continue;
+ }
+ if(!out)
+ {
+ std::cout << "ERROR: could not write " << outfile << std::endl;
+ continue;
+ }
+
+ pipe.start_msg();
+ in >> pipe;
+ pipe.end_msg();
+ pipe.set_default_msg(j);
+ out << pipe;
+
+ in.close();
+ out.close();
+ }
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception caught: " << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
diff --git a/old/botan/doc/examples/ca.cpp b/old/botan/doc/examples/ca.cpp
new file mode 100644
index 0000000..41dd409
--- /dev/null
+++ b/old/botan/doc/examples/ca.cpp
@@ -0,0 +1,74 @@
+/*
+ Implement the functionality of a simple CA: read in a CA certificate,
+ the associated private key, and a PKCS #10 certificate request. Sign the
+ request and print out the new certificate.
+
+ File names are hardcoded for simplicity.
+ cacert.pem: The CA's certificate (perhaps created by self_sig)
+ caprivate.pem: The CA's private key
+ req.pem: The user's PKCS #10 certificate request
+
+ Written by Jack Lloyd, May 19, 2003
+
+ This file is in the public domain.
+*/
+
+#include <botan/botan.h>
+#include <botan/x509_ca.h>
+#include <botan/util.h>
+using namespace Botan;
+
+#include <iostream>
+#include <memory>
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 5)
+ {
+ std::cout << "Usage: " << argv[0] << " <passphrase> "
+ << "<ca cert> <ca key> <pkcs10>" << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ try
+ {
+ const std::string arg_passphrase = argv[1];
+ const std::string arg_ca_cert = argv[2];
+ const std::string arg_ca_key = argv[3];
+ const std::string arg_req_file = argv[4];
+
+ AutoSeeded_RNG rng;
+
+ X509_Certificate ca_cert(arg_ca_cert);
+
+ std::auto_ptr<PKCS8_PrivateKey> privkey(
+ PKCS8::load_key(arg_ca_key, rng, arg_passphrase)
+ );
+
+ X509_CA ca(ca_cert, *privkey);
+
+ // got a request
+ PKCS10_Request req(arg_req_file);
+
+ // you would insert checks here, and perhaps modify the request
+ // (this example should be extended to show how)
+
+ // now sign the request
+ X509_Time start_time(system_time());
+ X509_Time end_time(system_time() + 365 * 60 * 60 * 24);
+
+ X509_Certificate new_cert = ca.sign_request(req, rng,
+ start_time, end_time);
+
+ // send the new cert back to the requestor
+ std::cout << new_cert.PEM_encode();
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
diff --git a/old/botan/doc/examples/checksum.cpp b/old/botan/doc/examples/checksum.cpp
new file mode 100644
index 0000000..232be05
--- /dev/null
+++ b/old/botan/doc/examples/checksum.cpp
@@ -0,0 +1,31 @@
+#include <botan/botan.h>
+#include <botan/filters.h>
+
+#include <iostream>
+
+using namespace Botan;
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 2)
+ {
+ std::cout << "Usage: " << argv[0] << " filename\n";
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ Pipe pipe(new Fork(
+ new Chain(new Hash_Filter("CRC24"), new Hex_Encoder),
+ new Chain(new Hash_Filter("CRC32"), new Hex_Encoder),
+ new Chain(new Hash_Filter("Adler32"), new Hex_Encoder)
+ ));
+
+ DataSource_Stream in(argv[1]);
+
+ pipe.process_msg(in);
+
+ std::cout << pipe.read_all_as_string(0) << "\n";
+ std::cout << pipe.read_all_as_string(1) << "\n";
+ std::cout << pipe.read_all_as_string(2) << "\n";
+ }
diff --git a/old/botan/doc/examples/cms_dec.cpp b/old/botan/doc/examples/cms_dec.cpp
new file mode 100644
index 0000000..3fa2853
--- /dev/null
+++ b/old/botan/doc/examples/cms_dec.cpp
@@ -0,0 +1,116 @@
+#include <botan/botan.h>
+#include <botan/pkcs8.h>
+#include <botan/cms_dec.h>
+using namespace Botan;
+
+#include <iostream>
+#include <memory>
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 2)
+ {
+ printf("Usage: %s <filename>\n", argv[0]);
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ try {
+ AutoSeeded_RNG rng;
+
+ X509_Certificate mycert("mycert.pem");
+ PKCS8_PrivateKey* mykey = PKCS8::load_key("mykey.pem", rng, "cut");
+
+ X509_Certificate yourcert("yourcert.pem");
+ X509_Certificate cacert("cacert.pem");
+ X509_Certificate int_ca("int_ca.pem");
+
+ X509_Store store;
+ store.add_cert(mycert);
+ store.add_cert(yourcert);
+ store.add_cert(cacert, true);
+ store.add_cert(int_ca);
+
+ DataSource_Stream message(argv[1]);
+
+ User_Interface ui;
+
+ CMS_Decoder decoder(message, store, ui, mykey);
+
+ while(decoder.layer_type() != CMS_Decoder::DATA)
+ {
+ CMS_Decoder::Status status = decoder.layer_status();
+ CMS_Decoder::Content_Type content = decoder.layer_type();
+
+ if(status == CMS_Decoder::FAILURE)
+ {
+ std::cout << "Failure reading CMS data" << std::endl;
+ break;
+ }
+
+ if(content == CMS_Decoder::DIGESTED)
+ {
+ std::cout << "Digested data, hash = " << decoder.layer_info()
+ << std::endl;
+ std::cout << "Hash is "
+ << ((status == CMS_Decoder::GOOD) ? "good" : "bad")
+ << std::endl;
+ }
+
+ if(content == CMS_Decoder::SIGNED)
+ {
+ // how to handle multiple signers? they can all exist within a
+ // single level...
+
+ std::cout << "Signed by " << decoder.layer_info() << std::endl;
+ //std::cout << "Sign time: " << decoder.xxx() << std::endl;
+ std::cout << "Signature is ";
+ if(status == CMS_Decoder::GOOD)
+ std::cout << "valid";
+ else if(status == CMS_Decoder::BAD)
+ std::cout << "bad";
+ else if(status == CMS_Decoder::NO_KEY)
+ std::cout << "(cannot check, no known cert)";
+ std::cout << std::endl;
+ }
+ if(content == CMS_Decoder::ENVELOPED ||
+ content == CMS_Decoder::COMPRESSED ||
+ content == CMS_Decoder::AUTHENTICATED)
+ {
+ if(content == CMS_Decoder::ENVELOPED)
+ std::cout << "Enveloped";
+ if(content == CMS_Decoder::COMPRESSED)
+ std::cout << "Compressed";
+ if(content == CMS_Decoder::AUTHENTICATED)
+ std::cout << "MACed";
+
+ std::cout << ", algo = " << decoder.layer_info() << std::endl;
+
+ if(content == CMS_Decoder::AUTHENTICATED)
+ {
+ std::cout << "MAC status is ";
+ if(status == CMS_Decoder::GOOD)
+ std::cout << "valid";
+ else if(status == CMS_Decoder::BAD)
+ std::cout << "bad";
+ else if(status == CMS_Decoder::NO_KEY)
+ std::cout << "(cannot check, no key)";
+ std::cout << std::endl;
+ }
+ }
+ decoder.next_layer();
+ }
+
+ if(decoder.layer_type() == CMS_Decoder::DATA)
+ std::cout << "Message is \"" << decoder.get_data()
+ << '"' << std::endl;
+ else
+ std::cout << "No data anywhere?" << std::endl;
+ }
+ catch(std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
+ return 0;
+ }
diff --git a/old/botan/doc/examples/cms_enc.cpp b/old/botan/doc/examples/cms_enc.cpp
new file mode 100644
index 0000000..de16bba
--- /dev/null
+++ b/old/botan/doc/examples/cms_enc.cpp
@@ -0,0 +1,53 @@
+#include <botan/botan.h>
+#include <botan/cms_enc.h>
+using namespace Botan;
+
+#include <iostream>
+#include <fstream>
+#include <memory>
+
+int main()
+ {
+ Botan::LibraryInitializer init;
+
+ try {
+
+ X509_Certificate mycert("mycert.pem");
+ X509_Certificate mycert2("mycert2.pem");
+ X509_Certificate yourcert("yourcert.pem");
+ X509_Certificate cacert("cacert.pem");
+ X509_Certificate int_ca("int_ca.pem");
+
+ AutoSeeded_RNG rng;
+
+ X509_Store store;
+ store.add_cert(mycert);
+ store.add_cert(mycert2);
+ store.add_cert(yourcert);
+ store.add_cert(int_ca);
+ store.add_cert(cacert, true);
+
+ const std::string msg = "prioncorp: we don't toy\n";
+
+ CMS_Encoder encoder(msg);
+
+ encoder.compress("Zlib");
+ encoder.digest();
+ encoder.encrypt(rng, mycert);
+
+ /*
+ PKCS8_PrivateKey* mykey = PKCS8::load_key("mykey.pem", rng, "cut");
+ encoder.sign(store, *mykey);
+ */
+
+ SecureVector<byte> raw = encoder.get_contents();
+ std::ofstream out("out.der");
+
+ out.write((const char*)raw.begin(), raw.size());
+ }
+ catch(std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
+ return 0;
+ }
diff --git a/old/botan/doc/examples/cryptobox.cpp b/old/botan/doc/examples/cryptobox.cpp
new file mode 100644
index 0000000..0a769b0
--- /dev/null
+++ b/old/botan/doc/examples/cryptobox.cpp
@@ -0,0 +1,50 @@
+/*
+* Cryptobox example
+*/
+#include <botan/botan.h>
+#include <botan/cryptobox.h>
+#include <fstream>
+#include <iostream>
+#include <vector>
+
+using namespace Botan;
+
+int main(int argc, char* argv[])
+ {
+ LibraryInitializer init;
+
+ AutoSeeded_RNG rng;
+
+ if(argc != 3)
+ {
+ std::cout << "Usage: cryptobox pass filename\n";
+ return 1;
+ }
+
+ std::string pass = argv[1];
+ std::string filename = argv[2];
+
+ std::ifstream input(filename.c_str());
+
+ std::vector<byte> file_contents;
+ while(input.good())
+ {
+ byte filebuf[4096] = { 0 };
+ input.read((char*)filebuf, sizeof(filebuf));
+ size_t got = input.gcount();
+
+ file_contents.insert(file_contents.end(), filebuf, filebuf+got);
+ }
+
+ std::string ciphertext = CryptoBox::encrypt(&file_contents[0],
+ file_contents.size(),
+ pass, rng);
+
+ std::cout << ciphertext;
+
+ /*
+ std::cout << CryptoBox::decrypt((const byte*)&ciphertext[0],
+ ciphertext.length(),
+ pass);
+ */
+ }
diff --git a/old/botan/doc/examples/decrypt.cpp b/old/botan/doc/examples/decrypt.cpp
new file mode 100644
index 0000000..68d5f89
--- /dev/null
+++ b/old/botan/doc/examples/decrypt.cpp
@@ -0,0 +1,158 @@
+/*
+Decrypt files encrypted with the 'encrypt' example application.
+
+I'm being lazy and writing the output to stdout rather than stripping off the
+".enc" suffix and writing it there. So all diagnostics go to stderr so there is
+no confusion.
+
+Written by Jack Lloyd (lloyd@randombit.net) on August 5, 2002
+
+This file is in the public domain
+*/
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <vector>
+#include <cstring>
+#include <memory>
+
+#include <botan/botan.h>
+
+#if defined(BOTAN_HAS_COMPRESSOR_ZLIB)
+ #include <botan/zlib.h>
+#endif
+
+using namespace Botan;
+
+SecureVector<byte> b64_decode(const std::string&);
+
+int main(int argc, char* argv[])
+ {
+ if(argc < 2)
+ {
+ std::cout << "Usage: " << argv[0] << " [-p passphrase] file\n"
+ << " -p : Use this passphrase to decrypt\n";
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ std::string filename, passphrase;
+
+ for(int j = 1; argv[j] != 0; j++)
+ {
+ if(std::strcmp(argv[j], "-p") == 0)
+ {
+ if(argv[j+1])
+ {
+ passphrase = argv[j+1];
+ j++;
+ }
+ else
+ {
+ std::cout << "No argument for -p option" << std::endl;
+ return 1;
+ }
+ }
+ else
+ {
+ if(filename != "")
+ {
+ std::cout << "You can only specify one file at a time\n";
+ return 1;
+ }
+ filename = argv[j];
+ }
+ }
+
+ if(passphrase == "")
+ {
+ std::cout << "You have to specify a passphrase!" << std::endl;
+ return 1;
+ }
+
+ std::ifstream in(filename.c_str());
+ if(!in)
+ {
+ std::cout << "ERROR: couldn't open " << filename << std::endl;
+ return 1;
+ }
+
+ std::string algo;
+
+ try {
+ std::string header, salt_str, mac_str;
+ std::getline(in, header);
+ std::getline(in, algo);
+ std::getline(in, salt_str);
+ std::getline(in, mac_str);
+
+ if(header != "-------- ENCRYPTED FILE --------")
+ {
+ std::cout << "ERROR: File is missing the usual header" << std::endl;
+ return 1;
+ }
+
+ if(!have_block_cipher(algo))
+ {
+ std::cout << "Don't know about the block cipher \"" << algo << "\"\n";
+ return 1;
+ }
+
+ const u32bit key_len = max_keylength_of(algo);
+ const u32bit iv_len = block_size_of(algo);
+
+ std::auto_ptr<S2K> s2k(get_s2k("PBKDF2(SHA-1)"));
+ s2k->set_iterations(8192);
+ s2k->change_salt(b64_decode(salt_str));
+
+ SymmetricKey bc_key = s2k->derive_key(key_len, "BLK" + passphrase);
+ InitializationVector iv = s2k->derive_key(iv_len, "IVL" + passphrase);
+ SymmetricKey mac_key = s2k->derive_key(16, "MAC" + passphrase);
+
+ Pipe pipe(new Base64_Decoder,
+ get_cipher(algo + "/CBC", bc_key, iv, DECRYPTION),
+#ifdef BOTAN_HAS_COMPRESSOR_ZLIB
+ new Zlib_Decompression,
+#endif
+ new Fork(
+ 0,
+ new Chain(new MAC_Filter("HMAC(SHA-1)", mac_key),
+ new Base64_Encoder)
+ )
+ );
+
+ pipe.start_msg();
+ in >> pipe;
+ pipe.end_msg();
+
+ std::string our_mac = pipe.read_all_as_string(1);
+ if(our_mac != mac_str)
+ std::cout << "WARNING: MAC in message failed to verify\n";
+
+ std::cout << pipe.read_all_as_string(0);
+ }
+ catch(Algorithm_Not_Found)
+ {
+ std::cout << "Don't know about the block cipher \"" << algo << "\"\n";
+ return 1;
+ }
+ catch(Decoding_Error)
+ {
+ std::cout << "Bad passphrase or corrupt file\n";
+ return 1;
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception caught: " << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
+
+SecureVector<byte> b64_decode(const std::string& in)
+ {
+ Pipe pipe(new Base64_Decoder);
+ pipe.process_msg(in);
+ return pipe.read_all();
+ }
diff --git a/old/botan/doc/examples/dh.cpp b/old/botan/doc/examples/dh.cpp
new file mode 100644
index 0000000..c808928
--- /dev/null
+++ b/old/botan/doc/examples/dh.cpp
@@ -0,0 +1,59 @@
+/*
+ A simple DH example
+
+ Written by Jack Lloyd (lloyd@randombit.net), on December 24, 2003
+
+ This file is in the public domain
+*/
+#include <botan/botan.h>
+#include <botan/dh.h>
+#include <botan/rng.h>
+using namespace Botan;
+
+#include <iostream>
+#include <memory>
+
+int main()
+ {
+ Botan::LibraryInitializer init;
+
+ try
+ {
+ AutoSeeded_RNG rng;
+
+ // Alice creates a DH key and sends (the public part) to Bob
+ DH_PrivateKey private_a(rng, DL_Group("modp/ietf/1024"));
+ DH_PublicKey public_a = private_a; // Bob gets this
+
+ // Bob creates a key with a matching group
+ DH_PrivateKey private_b(rng, public_a.get_domain());
+
+ // Bob sends the key back to Alice
+ DH_PublicKey public_b = private_b; // Alice gets this
+
+ // Both of them create a key using their private key and the other's
+ // public key
+ SymmetricKey alice_key = private_a.derive_key(public_b);
+ SymmetricKey bob_key = private_b.derive_key(public_a);
+
+ if(alice_key == bob_key)
+ {
+ std::cout << "The two keys matched, everything worked\n";
+ std::cout << "The shared key was: " << alice_key.as_string() << "\n";
+ }
+ else
+ {
+ std::cout << "The two keys didn't match!\n";
+ std::cout << "Alice's key was: " << alice_key.as_string() << "\n";
+ std::cout << "Bob's key was: " << bob_key.as_string() << "\n";
+ }
+
+ // Now Alice and Bob hash the key and use it for something
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
diff --git a/old/botan/doc/examples/dsa_kgen.cpp b/old/botan/doc/examples/dsa_kgen.cpp
new file mode 100644
index 0000000..4669cf7
--- /dev/null
+++ b/old/botan/doc/examples/dsa_kgen.cpp
@@ -0,0 +1,66 @@
+/*
+Generate a 1024 bit DSA key and put it into a file. The public key format is
+that specified by X.509, while the private key format is PKCS #8.
+
+The domain parameters are the ones specified as the Java default DSA
+parameters. There is nothing special about these, it's just the only 1024-bit
+DSA parameter set that's included in Botan at the time of this writing. The
+application always reads/writes all of the domain parameters to/from the file,
+so a new set could be used without any problems. We could generate a new set
+for each key, or read a set of DSA params from a file and use those, but they
+mostly seem like needless complications.
+
+Written by Jack Lloyd (lloyd@randombit.net), August 5, 2002
+ Updated to use X.509 and PKCS #8 formats, October 21, 2002
+
+This file is in the public domain
+*/
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <botan/botan.h>
+#include <botan/dsa.h>
+#include <botan/rng.h>
+using namespace Botan;
+
+#include <memory>
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 1 && argc != 2)
+ {
+ std::cout << "Usage: " << argv[0] << " [passphrase]" << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ std::ofstream priv("dsapriv.pem");
+ std::ofstream pub("dsapub.pem");
+ if(!priv || !pub)
+ {
+ std::cout << "Couldn't write output files" << std::endl;
+ return 1;
+ }
+
+ try
+ {
+ AutoSeeded_RNG rng;
+
+ DL_Group group(rng, DL_Group::DSA_Kosherizer, 2048, 256);
+
+ DSA_PrivateKey key(rng, group);
+
+ pub << X509::PEM_encode(key);
+ if(argc == 1)
+ priv << PKCS8::PEM_encode(key);
+ else
+ priv << PKCS8::PEM_encode(key, rng, argv[1]);
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception caught: " << e.what() << std::endl;
+ }
+ return 0;
+ }
diff --git a/old/botan/doc/examples/dsa_sign.cpp b/old/botan/doc/examples/dsa_sign.cpp
new file mode 100644
index 0000000..caf0503
--- /dev/null
+++ b/old/botan/doc/examples/dsa_sign.cpp
@@ -0,0 +1,83 @@
+/*
+Decrypt an encrypted DSA private key. Then use that key to sign a message.
+
+Written by Jack Lloyd (lloyd@randombit.net), August 5, 2002
+ Updated to use X.509 and PKCS #8 format keys, October 21, 2002
+
+This file is in the public domain
+*/
+
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include <string>
+#include <memory>
+
+#include <botan/botan.h>
+#include <botan/look_pk.h>
+#include <botan/dsa.h>
+using namespace Botan;
+
+const std::string SUFFIX = ".sig";
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 4)
+ {
+ std::cout << "Usage: " << argv[0] << " keyfile messagefile passphrase"
+ << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ try {
+ std::string passphrase(argv[3]);
+
+ std::ifstream message(argv[2]);
+ if(!message)
+ {
+ std::cout << "Couldn't read the message file." << std::endl;
+ return 1;
+ }
+
+ std::string outfile = argv[2] + SUFFIX;
+ std::ofstream sigfile(outfile.c_str());
+ if(!sigfile)
+ {
+ std::cout << "Couldn't write the signature to "
+ << outfile << std::endl;
+ return 1;
+ }
+
+ AutoSeeded_RNG rng;
+
+ std::auto_ptr<PKCS8_PrivateKey> key(
+ PKCS8::load_key(argv[1], rng, passphrase)
+ );
+
+ DSA_PrivateKey* dsakey = dynamic_cast<DSA_PrivateKey*>(key.get());
+
+ if(!dsakey)
+ {
+ std::cout << "The loaded key is not a DSA key!\n";
+ return 1;
+ }
+
+ PK_Signer signer(*dsakey, get_emsa("EMSA1(SHA-1)"));
+
+ DataSource_Stream in(message);
+ byte buf[4096] = { 0 };
+ while(u32bit got = in.read(buf, sizeof(buf)))
+ signer.update(buf, got);
+
+ Pipe pipe(new Base64_Encoder);
+ pipe.process_msg(signer.signature(rng));
+ sigfile << pipe.read_all_as_string() << std::endl;
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception caught: " << e.what() << std::endl;
+ }
+ return 0;
+ }
diff --git a/old/botan/doc/examples/dsa_ver.cpp b/old/botan/doc/examples/dsa_ver.cpp
new file mode 100644
index 0000000..3b7ea02
--- /dev/null
+++ b/old/botan/doc/examples/dsa_ver.cpp
@@ -0,0 +1,92 @@
+/*
+Grab an DSA public key from the file given as an argument, grab a signature
+from another file, and verify the message (which, suprise, is also in a file).
+
+The signature format isn't particularly standard, but it's not bad. It's simply
+the IEEE 1363 signature format, encoded into base64 with a trailing newline
+
+Written by Jack Lloyd (lloyd@randombit.net), August 5, 2002
+ Updated to use X.509 format keys, October 21, 2002
+
+This file is in the public domain
+*/
+
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include <cstdlib>
+#include <string>
+#include <memory>
+
+#include <botan/botan.h>
+#include <botan/look_pk.h>
+#include <botan/dsa.h>
+using namespace Botan;
+
+SecureVector<byte> b64_decode(const std::string& in)
+ {
+ Pipe pipe(new Base64_Decoder);
+ pipe.process_msg(in);
+ return pipe.read_all();
+ }
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 4)
+ {
+ std::cout << "Usage: " << argv[0]
+ << " keyfile messagefile sigfile" << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ std::ifstream message(argv[2]);
+ if(!message)
+ {
+ std::cout << "Couldn't read the message file." << std::endl;
+ return 1;
+ }
+
+ std::ifstream sigfile(argv[3]);
+ if(!sigfile)
+ {
+ std::cout << "Couldn't read the signature file." << std::endl;
+ return 1;
+ }
+
+ try {
+ std::string sigstr;
+ getline(sigfile, sigstr);
+
+ std::auto_ptr<X509_PublicKey> key(X509::load_key(argv[1]));
+ DSA_PublicKey* dsakey = dynamic_cast<DSA_PublicKey*>(key.get());
+ if(!dsakey)
+ {
+ std::cout << "The loaded key is not a DSA key!\n";
+ return 1;
+ }
+
+ SecureVector<byte> sig = b64_decode(sigstr);
+
+ std::auto_ptr<PK_Verifier> ver(get_pk_verifier(*dsakey, "EMSA1(SHA-1)"));
+
+ DataSource_Stream in(message);
+ byte buf[4096] = { 0 };
+ while(u32bit got = in.read(buf, sizeof(buf)))
+ ver->update(buf, got);
+
+ bool ok = ver->check_signature(sig);
+
+ if(ok)
+ std::cout << "Signature verified\n";
+ else
+ std::cout << "Signature did NOT verify\n";
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception caught: " << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
diff --git a/old/botan/doc/examples/eax_test.cpp b/old/botan/doc/examples/eax_test.cpp
new file mode 100644
index 0000000..283e335
--- /dev/null
+++ b/old/botan/doc/examples/eax_test.cpp
@@ -0,0 +1,241 @@
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include <boost/regex.hpp>
+
+#include <botan/botan.h>
+#include <botan/eax.h>
+
+using namespace Botan;
+
+unsigned to_string(const std::string& s)
+ {
+ std::istringstream stream(s);
+ unsigned n;
+ stream >> n;
+ return n;
+ }
+
+std::string seq(unsigned n)
+ {
+ std::string s;
+
+ for(unsigned i = 0; i != n; ++i)
+ {
+ unsigned char b = (i & 0xFF);
+
+ const char bin2hex[] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+ s += bin2hex[(b >> 4)];
+ s += bin2hex[(b & 0x0f)];
+ }
+
+ return s;
+ }
+
+void eax_test(const std::string& algo,
+ const std::string& key_str,
+ const std::string& nonce_str,
+ const std::string& header_str,
+ const std::string& tag_str,
+ const std::string& plaintext_str,
+ const std::string& ciphertext)
+ {
+ /*
+ printf("EAX(algo=%s key=%s nonce=%s header=%s tag=%s pt=%s ct=%s)\n",
+ algo.c_str(), key_str.c_str(), nonce_str.c_str(), header_str.c_str(), tag_str.c_str(),
+ plaintext_str.c_str(), ciphertext.c_str());
+ */
+
+ SymmetricKey key(key_str);
+ InitializationVector iv(nonce_str);
+
+ EAX_Encryption* enc;
+
+ Pipe pipe(new Hex_Decoder,
+ enc = new EAX_Encryption(get_block_cipher(algo)),
+ new Hex_Encoder);
+
+ enc->set_key(key);
+ enc->set_iv(iv);
+
+ OctetString header(header_str);
+
+ enc->set_header(header.begin(), header.length());
+
+ pipe.start_msg();
+ pipe.write(plaintext_str);
+ pipe.end_msg();
+
+ std::string out = pipe.read_all_as_string();
+
+ if(out != ciphertext + tag_str)
+ {
+ printf("BAD enc %s '%s' != '%s%s'\n", algo.c_str(),
+ out.c_str(), ciphertext.c_str(), tag_str.c_str());
+ }
+ else
+ printf("OK enc %s\n", algo.c_str());
+
+ try
+ {
+ EAX_Decryption* dec;
+ Pipe pipe2(new Hex_Decoder,
+ dec = new EAX_Decryption(get_block_cipher(algo)),
+ new Hex_Encoder);
+
+ dec->set_key(key);
+ dec->set_iv(iv);
+
+ dec->set_header(header.begin(), header.length());
+
+ pipe2.start_msg();
+ pipe2.write(ciphertext);
+ pipe2.write(tag_str);
+ pipe2.end_msg();
+
+ std::string out2 = pipe2.read_all_as_string();
+
+ if(out2 != plaintext_str)
+ {
+ printf("BAD decrypt %s '%s'\n", algo.c_str(), out2.c_str());
+ }
+ else
+ printf("OK decrypt %s\n", algo.c_str());
+ }
+ catch(std::exception& e)
+ {
+ printf("%s\n", e.what());
+ }
+
+ }
+
+std::pair<std::string, int> translate_algo(const std::string& in)
+ {
+ if(in == "aes (16 byte key)")
+ return std::make_pair("AES-128", 16);
+
+ if(in == "blowfish (8 byte key)")
+ return std::make_pair("Blowfish", 8);
+
+ if(in == "rc2 (8 byte key)")
+ return std::make_pair("RC2", 8);
+
+ if(in == "rc5 (8 byte key)")
+ return std::make_pair("RC5", 8);
+
+ if(in == "rc6 (16 byte key)")
+ return std::make_pair("RC6", 16);
+
+ if(in == "safer-sk128 (16 byte key)")
+ return std::make_pair("SAFER-SK(10)", 16);
+
+ if(in == "twofish (16 byte key)")
+ return std::make_pair("Twofish", 16);
+
+ if(in == "des (8 byte key)")
+ return std::make_pair("DES", 8);
+
+ if(in == "3des (24 byte key)")
+ return std::make_pair("TripleDES", 24);
+
+ // These 3 are disabled due to differences in base algorithm.
+
+#if 0
+ // XTEA: LTC uses little endian, Botan (and Crypto++) use big-endian
+ // I swapped to LE in XTEA and the vectors did match
+ if(in == "xtea (16 byte key)")
+ return std::make_pair("XTEA", 16);
+
+ // Skipjack: LTC uses big-endian, Botan (and Crypto++) use
+ // little-endian I am not sure if that was the full difference
+ // though, was unable to replicate LTC's EAX vectors with Skipjack
+ if(in == "skipjack (10 byte key)")
+ return std::make_pair("Skipjack", 10);
+
+ // Noekeon: unknown cause, though LTC's lone test vector does not
+ // match Botan
+
+ if(in == "noekeon (16 byte key)")
+ return std::make_pair("Noekeon", 16);
+
+#endif
+
+ return std::make_pair("", 0);
+ }
+
+std::string rep(const std::string& s_in, unsigned n)
+ {
+ std::string s_out;
+
+ for(unsigned i = 0; i != n; ++i)
+ s_out += s_in[i % s_in.size()];
+
+ return s_out;
+ }
+
+void run_tests(std::istream& in)
+ {
+ std::string algo;
+ std::string key;
+
+ while(in.good())
+ {
+ std::string line;
+
+ std::getline(in, line);
+
+ if(line == "")
+ continue;
+
+ if(line.size() > 5 && line.substr(0, 4) == "EAX-")
+ {
+ std::pair<std::string, int> name_and_keylen =
+ translate_algo(line.substr(4));
+
+ algo = name_and_keylen.first;
+ key = seq(name_and_keylen.second);
+ }
+ else if(algo != "")
+ {
+ boost::regex vec_regex("^([ 0-9]{3}): (.*), (.*)$");
+
+ boost::smatch what;
+
+ if(boost::regex_match(line, what, vec_regex, boost::match_extra))
+ {
+ unsigned n = to_string(what[1]);
+ std::string ciphertext = what[2];
+ std::string tag = what[3];
+
+ std::string plaintext = seq(n);
+ std::string header = seq(n);
+ std::string nonce = seq(n);
+
+ eax_test(algo, key, nonce, header, tag,
+ plaintext, ciphertext);
+
+ key = rep(tag, key.size()); // repeat as needed
+ }
+ }
+ }
+
+
+ }
+
+int main()
+ {
+ std::ifstream in("eax_tv.txt");
+
+ Botan::LibraryInitializer init;
+
+ if(!in)
+ {
+ std::cerr << "Couldn't read input file\n";
+ return 1;
+ }
+
+ run_tests(in);
+
+ }
diff --git a/old/botan/doc/examples/eax_tv.txt b/old/botan/doc/examples/eax_tv.txt
new file mode 100644
index 0000000..95cd7c1
--- /dev/null
+++ b/old/botan/doc/examples/eax_tv.txt
@@ -0,0 +1,461 @@
+EAX Test Vectors. Uses the 00010203...NN-1 pattern for header/nonce/plaintext/key. The outputs
+are of the form ciphertext,tag for a given NN. The key for step N>1 is the tag of the previous
+step repeated sufficiently.
+
+EAX-aes (16 byte key)
+ 0: , 9AD07E7DBFF301F505DE596B9615DFFF
+ 1: 47, 57C4AC75A42D05260AFA093ACD4499ED
+ 2: C4E2, 26C5AB00325306772E6F6E4C8093F3D2
+ 3: 16177B, 852260F91F27898D4FC176E311F6E1D1
+ 4: F09F68BE, 700766CA231643B5D60C3B91B1B700C1
+ 5: 8472705EDF, AC4C3359326EEA4CF71FC03E0E0292F2
+ 6: 14C25EB5FD0D, 8DBD749CA79CCF11C1B370F8C975858C
+ 7: F6A37F60670A85, AFBD1D5921557187504ADE61014C9622
+ 8: 1AACFEAE8FBAD833, 82F477325D6F76BB81940AE25F9801C2
+ 9: 069414324EC293697C, B980E21C09CA129B69E9032D980A9DC5
+ 10: D8174DE9A2FC92B7DA9C, 1E42CC58BA2C8BFD83806444EA29DB61
+ 11: 2C087DEA30F8B7EE510990, 83DB400A080C4D43CAA6EC3F1085A923
+ 12: F36B93C272A703D3422C6A11, 1370C3AF2F3392916364BBBCC2C62EC1
+ 13: A0F33477BAE2E28E6747AA3193, B626DC719528CAC65DB0EF94E35422CE
+ 14: FCF5193506052E8BFA095C1A5205, F5BD02E0B3C91CC7D6FAAA8A9A76CE6A
+ 15: 3797D7F8599B8EEAB39C56241880DC, 0B70003E77146B903F06EF294FECD517
+ 16: C4BAD0E0356FFD369110C048D45D81BE, DE7C2B1D83BE2CC8EA402ABE1038BB79
+ 17: AF5C358BD31CDCAC2F0EA5252F1C3BE1E4, 2D700986F93B22DFE6695C2A243B4E42
+ 18: 7DEF9056FBDAF491D7206B26B19DEF617AA1, E71A7D00BE972D85C77931D7591B2151
+ 19: 6E9B2C0A90BF9D38A6EA3B5D2B9B2D97F938EB, 5B483D7F15C39602C2918181E57DA341
+ 20: 7C5F68DEE9BBA3B04F11D5FC7C9C7FE6E8B5025C, 0AE6A12D37A9C10BB1A494E16705DC05
+ 21: AF0A886BF673BC72045FC074F06A0176C96105E2E6, 06B2DC9A2868C23F86D710E01E37E07B
+ 22: 5F228A986DFE4301EDBAF07A02E114F1B30932995CD1, 74EBF68627C78B1FD024A59B56B2A8FA
+ 23: 911322F60555118CBECD8DD82F186AC19514316E8D48BA, B6A8BAF2F175CD0C71B63B1EF37E185E
+ 24: E7F52730CFB808EFDB376A5D5DF31A7EF8292DC5FC37E9BC, BA2AD158A2D2E5CE01296402B592E1DB
+ 25: B3F8D7CA47D8D86E94D670AFBAFA3B8D9E186C97DC029D4705, 709D2D2B9975D4729C19D4EAC430E65E
+ 26: 7178FEC027AFADDC2C03518E75CF34D207CAC2EB1537A0DBA520, A315F034CE5E66601444402520F55DE2
+ 27: FC230B2B8522F53459D0B968421469BBA7E683ACB0190393B2870F, 48679A78E470E175CF3D3E9B46CEDFCE
+ 28: 35A641127C78C721ECDC50866C21637FDC9515E41CE60F09015EA713, 0062987222F6412B7AAF8A9ABF6FBF98
+ 29: 3D42D6C113421743C08A6F682CFA0E517D5531BB66241C02EC4DCC26F7, B1AAFE11FA2D6E0C870177DDD7F98FF0
+ 30: DAD065B4669B7C59C8392D8E7BD7E64BC01CEFFF27E335B25A328D356F0E, 8973B9B9ECF26DAB58CCF0787EE928E5
+ 31: EBE626F9E241FD233D9781C359430C982667AA26921B62E98FAEC502C01B0B, 2AC0D7052A2CDCCE8E26FEA7595198AA
+ 32: 64D842B66796A797C2B4C6905742FDF2148FFC445E192F9E03B53810C082F788, 9778B345EC12D222DCC6DBABD2651750
+
+EAX-blowfish (8 byte key)
+ 0: , D8C4C23A6AC0B7B7
+ 1: 2A, 5E0E4BDDB60772FB
+ 2: 7695, 7581B16CCC9C45F1
+ 3: EB14C8, 6223A121CFA216C7
+ 4: 5A5C809C, 4A47658796337D6A
+ 5: 8BC2041181, E1FBA8DBA00571FC
+ 6: 89C666F015FA, 2B4A76A0E699FCFE
+ 7: 86C1FA92484AF6, 31B3B738A261D6F5
+ 8: D1F401C145C9328B, 4C4A045EB489F59C
+ 9: 70C9C7753698324A73, AB298B5B20567EB4
+ 10: A50D9D88DC101B6DC8D2, 529DFCBFD13B8E6C
+ 11: 7CC2885C2BE79C44F28FF2, 566255022B40C81C
+ 12: 6902D58347C29250EE07981C, 34619AF18E14C690
+ 13: AB6C3C4AD3EC45143392B642DA, E6D2DD323DA175BB
+ 14: 7065B28BA8AB67B2FB7B6D5E3FAF, AEDCAA54F4B0772F
+ 15: CBBA14A74AD4ADC0EF036EDAE42D51, F2BFFA4D81BAC034
+ 16: 60A315193F58144F5701D547C79FEEED, 912FDBDB05467DF5
+
+EAX-xtea (16 byte key)
+ 0: , 86881D824E3BC561
+ 1: EE, 4C3505F04611D9C2
+ 2: 80C8, 6A3428BEEAD60738
+ 3: BF88E7, 04F1E99E9F5906C2
+ 4: E06574B7, 33B0153AAEF9776F
+ 5: 42D950AF63, 4A0F415640322FDF
+ 6: C30F6AD46EC9, 9646FE909D2B95CB
+ 7: A0049FCA856A14, A0257289C6BBF278
+ 8: 2814B0C1358440E0, C4B0A2354925E887
+ 9: BF4F062B52C1E489CF, B56442A3CA57A041
+ 10: 63DF433956831B8780FC, ADF9ED0B46DCA19E
+ 11: C317FD079817F50E0E8A16, 2EA0EC993FC603AE
+ 12: 2BD12FDDD81EB11660346D2A, FBC6F69125BBA88D
+ 13: 85D356536FE2843C6BBE60EDBC, BB2FEFD04F230E79
+ 14: 22493009DB01B4746F4927A8C4FB, 64CC08471D93C9AC
+ 15: C0F3C0DB08DC93FBA725D1E02DE084, 77B762213DDCCFFE
+ 16: 568B66D3112556BD98FF9339E9C002E5, C8355F508219FE0C
+
+EAX-rc5 (8 byte key)
+ 0: , 169C7954341EF44D
+ 1: 22, DABFDA9A0B0BA067
+ 2: 2E54, 6A3D6D9AA5877C5A
+ 3: 2A6ECF, 2A34A3AF5DE8919E
+ 4: 9CC5F84F, D3F673EDAF75E3B5
+ 5: FF5611756C, CC647FAAC8D49BF1
+ 6: 74C939BEB31C, C335999CCFE8F5FA
+ 7: 7976B6F7709B5F, 2A7969C5FD063A88
+ 8: 421EEC5022276174, 2C9BFB1EAC3C54A2
+ 9: 6A4761CD266B1C0ECB, 3EA3CCEBC85FAC4E
+ 10: 7C09201098E764239A2E, 8043ABA9BF4D5AEE
+ 11: 8CE26277562F646DE33C88, D72AED48895E3B40
+ 12: 52150F44D37D121560DA87F6, 58E865E22B485906
+ 13: BA0A73B45F93ECFBFC3AB3D8D0, 683D52FA47FB1A52
+ 14: 96546CBE01054AD24CC95DB54724, D80D0D530E5D1DDE
+ 15: 61E654BB18CD26FC36C09F874DC2C7, C65884CB9D9FEC1E
+ 16: 1D77B8BF02CDEAB4A707C07628826D5B, F18D1730C3D64701
+
+EAX-rc6 (16 byte key)
+ 0: , 1DF8B0B92A3F0C951C425AF4830E63FD
+ 1: 1A, 8A2959EBBE90180999994DEB7036DB85
+ 2: 435D, 7EF00CB57DB7B4155DB530D75CE6B025
+ 3: 08A6CF, 2ED6AF0F2D5BAB05F623D389480A01F2
+ 4: A86E54D3, FC69547C8BD922A5BF2F7B26C4D20F98
+ 5: ED0822E439, 0007A3C6DEFC6C912C0E5B853B520368
+ 6: 7BEFC7FD4054, D32C43A4D1086D57C5BCFAEE04EBC600
+ 7: 5235E58E79287C, A27E9C781327C0FC7C55410EB0C828A9
+ 8: CEB5EE99BE521F4D, 547F46383987F2A3582A81A3BCF9B280
+ 9: 0358B063D5F99C3770, C0A73730512CDA6AD49599775D59EDA1
+ 10: 434B9AEE07DFADD0A332, 499BD88881E558E09A8E822BE27D2496
+ 11: D47849E650F350BB622D74, 638E37A84E7FAAF8F5D77F1B061773DC
+ 12: 814592F568284085E79A024B, 9EB1405E8422FE50BC0D88D837A2C650
+ 13: 6F2B55EC91B591082053AF692E, C48F91EF01AA43A1EE3B36D233DDD48B
+ 14: 506CBDD2901838EE2F178B6953DA, 03778957F536509BFCA577B23A18F726
+ 15: 446EE435D3D1848B51BB8C5F7BE4A1, 1129EAEAADE534940546D43242A4C839
+ 16: FB9D2B150C42465B1685D8F069CC06DB, 41E2940F5DC63CB4E2FBEC25ED8A31E6
+ 17: 9684F683260107BE8FEBBEE1D3EEDAA7BD, BAE7C116F7FF96631F4ACEE95C65CEF3
+ 18: 5082B1FE48CD3AB58F63C2DCFDD4069AC736, 19AC7B8EE315CBB7131A283851B32266
+ 19: 8C72AE495B6F003A3C784D144E84E88885F78E, FA4CEC023740A8D670E351FBCF62C1CB
+ 20: 815D6361C7AE34C9D796ADF9C71ABC46AEF88BC9, 9A1F7288C61A6623B9A82748137ED7CC
+ 21: 904A853E2E96BD2B85AAB3F5DFB900E9B3642EE667, 9AA90DBDD461CAD20495DCFBCB513DD2
+ 22: 79D738A462F727B3D3C529ED999B6FDCCD991D1C5A4D, BF0987BEDDE650D73CAE7D380FED3431
+ 23: B2DEFDB7D503A84E83155A04B8DE8C8DBB68C2FC475007, B7CE900CF43CD518024123C76F6DA328
+ 24: 9E723E15439E12F6C46DF8A309AE1E97B6FD18436259CFB0, DF8B6E1E23512CC4CF5FF531A1908F69
+ 25: A7F0AD03CEBCC9202718AA164886E1026975306A664C5AC7A9, 4A771BF8B9A4325705C85E5499FD98E9
+ 26: A53A92AD1C6835F28E04EF591E783D36F3D76E489B31B87BEB7A, AA263B52A6E6A043DE4D7029D4DC73F5
+ 27: 79BE3C38291A7F77E932C8A9DEAC08DE6442EA9B3895B101A14E7B, 33B84DE06342E675E019CD0237292ED0
+ 28: FA108123C5A69571CFDFE8C3D00535121FDE3096DDC0D700F8F26A5A, 764025D7CA1A3F2C54D28956423B0C77
+ 29: 36EC2D67FD977BD2B73DB6D8EB756B3EADA13690E1B6DFC12A4781B34B, 4BC6B38DE3B02283D92F4DF19A5C48C5
+ 30: 96D3243C945905C9732B5927E46F00886D511463B38C86002FC26B65AB8C, 5B5511CDEC35687AB8425AB22D58B4F1
+ 31: 9CF83B87BEA3374AF7722E999863E3DABB858B0383383EAC7757F5B80FD44B, 1E0CBC961940FDA93B73A92DACFD67F3
+ 32: CE3BC3C9FA5EF4AFE5272B3EDD24B1B003FED2C2E501528CFF44D3FABFF52CB4, DC94FDDC78AAB2B7CAA1E1EF149AC355
+
+EAX-safer+ (16 byte key)
+ 0: , B120C7B37450C46189712E4DFD1F0C44
+ 1: CA, 82BA1869C5FF1EF2A4F6ADC1E7DC1F1D
+ 2: DD20, 6BD5601B16C9943A84AC1F99A176E6D1
+ 3: C1C09F, 0911DC63AA414C004E2BD825BECDC93B
+ 4: 27E43F59, BD858F084B082F76814DC385E1FB20D1
+ 5: 2A9A92F246, 5ADC4A32491934AC0BD00FCE686B26F1
+ 6: 52C78C0CD6F4, F35886F46C03EDCA10B3D01CF07B1E0A
+ 7: 23E0D3CED3795F, FE33D96FC98B78A30C0A412C60E93992
+ 8: CD3FC9961559F239, 9982364A61609FC41068260267231EE9
+ 9: 6EA46CB7AD7505C1BC, BB15053EF0F78B9091B3064118F3E9BF
+ 10: 05D9BA230A56CCA0703A, 1338E68E3DC992B6EB2685C668E75869
+ 11: 7AAD6049DFDCA6771AE42B, 35267E431051E1812495615324C4CBE6
+ 12: 8695091532B83B23C296F620, 7B2EEA861E9A91E6B6A911E10FC3FDD1
+ 13: D909DA4BC7372ACAEA78E6A0EE, EA6C1CD16180DF0B07F4E204A4B4FACB
+ 14: 7DEC8443600D0563AEFE87A2064F, DA454728069B3B409889664783588189
+ 15: C042FE656742CD2FE5D9C212D18C6C, 5929E4AECC2CA047BAE948E7023FE4D0
+ 16: 0B84D3CF59EEF7319633F4A397D47CF8, 31F892FFDB7535DF5D9143456E404163
+ 17: 8C9E57AAFA7969B142742B63AB73286600, C418231C44F96660DDBA8C26B3BB3681
+ 18: E9EED66D370A3A6A39C7E0E570D96F807EAC, A4AFE8D1D3C31B956A3BDBD043E7A665
+ 19: 1A5D47992DA5597D1449B4C8DD47B7404C7657, F3ECEE5182014FC3365FDBC4C33CC06A
+ 20: E7C7945FD1AFD3F5DCE666D8A5A2E8A3C11A7A5F, 86D78B2FBA7597B8806BED505B52BDF6
+ 21: 9E2165B47B29CBC4ACD50660E011D691F061209969, E9B1E860BD02085177E1A94E1EE6F3F0
+ 22: 48EA2945C8DD3FE09407BAC8973A861DB15B788C8FFD, 502926712EDB1B3DD13806052C6C75D7
+ 23: F37D46B35B60819EA52B00457D79155C04B55972D0DFA9, BB2B7D210BF0570F422640BF81F39B9E
+ 24: 12E85C0C78227205CC682360C79E35BF58EC6551CF8FE2D0, 042990D7A58D458C570A15DD375DB4E7
+ 25: 4F6C15109DE980DD14A7F4C27F48671E4787C53A564232F427, B097A5990D8067DD89C21473150C070F
+ 26: AAC472E49DB101B564A8A01E2C80C0C6AE9065D332C2DE79FAB6, ACDD587A7DB86542E195DF73AF1C1CBC
+ 27: B9912CE18019C31692A1F7E11D9CCB20297ACCB9DC62C47C01D2C2, B0ACBF028CA5B15E0035D2EB8CA916BE
+ 28: B4F2B1FE14A1ECDC9C8EA1A0120395E6ED1E69D3FC85DD0F3F90F350, 9A561EBC769369B95B9CB74FC6AC27D3
+ 29: 3FE397C8AD02689B7437A37861F0907AF1F6014A293B46419348771C5A, 6B7BEB9BD5018FECD71BE5081C7C2544
+ 30: 5019089142199F7207E1B7731B8B247A18A685B231499DF12A73F5D67D37, 307E93446777005BA1B088F178A0DB6E
+ 31: EAE8F9F02F8DB3D70B78B08CFB0949D99F1A86C958A8E3823736BCEAB86BE1, 6C94F48591C18BF9C450515B73379973
+ 32: B9C795F7A87305B4AD36DBA10B3B1C70B329D29E49C8C6A932D96A74334AEE4A, D18E6E233FEFD6E5C7148BDC1504299C
+
+EAX-twofish (16 byte key)
+ 0: , DB0C02CB069E3773296D3BD4A87A381B
+ 1: 99, 7D21D19E9C440F68E99F1F2EA2668694
+ 2: 0696, EA590EC417C88E23FD23917F9ECFB0C6
+ 3: B9B082, 82D4C9B68DDB02C906496413E13A2D68
+ 4: D6B29D74, 5BCE5CA4F662E883BF7FCAAE5FB2CE01
+ 5: A59C9CB009, CBFB04226D1029A7EC9D64A48A6729BE
+ 6: F4924FE3E355, 3D85B3900DECA0528C815F1447A1F209
+ 7: 679C88D52FB519, 931C7A863C3701D8015FDBD8696C6C30
+ 8: 26DA41C0D115375E, 7627E23E791A4DCB0FA5ED71B1ED2288
+ 9: 8FEC6EB7016AD2B178, F65ED0286A724F0CB2EA317D5022B0D8
+ 10: B5F22415B1334133C531, 87C4F3A8991BBB85984BC4D3305A5CF1
+ 11: 23E1D0ED2E820AFE7DA2FE, 100499F1093FAB2ECF73B643594E98E3
+ 12: 79519ABA91F46B8DAD6D5335, FBDCD1FCDB20AB99135F28A714C6992F
+ 13: 5968D0B4198A0AAD3D0395018F, 781F22E2DA98F83398FCF911B2010057
+ 14: 4E55B14432B601E3EF2EF567CB15, 8BF6E53D7657E56EA3DA1BFD9C9EC06E
+ 15: 6ED89651CE19B3DD1EE5C8780B5015, 131CFD657D32D4E1B35140ADDCA0E13A
+ 16: 2295A968B4D072D12757756247554850, F35FAC95C2AA4155450EAAA6E2E789B5
+ 17: F9B2AA2AA502EA79BBA0C5EAD932B8E1EE, 0ED81AA40B9BF39A9AAEDDDB7A04BEA6
+ 18: 385055F1C1C26C0472A504B4CD225DCA55FE, 24831680B56368231AC54227D737F582
+ 19: 771529585C741A3F8B1C973709892F255A99EE, 2A132B4BF96FD5109DB04459103F5E84
+ 20: E7A2197D9FAA8AB8B303B5EC71AE34AD5EC5DD66, CCAB6518371EC8E0A9E9EE4F7CA5878B
+ 21: 279E54F755EAC6B57375B9EC4406E43DB3139D740C, 7B6F26F2C0ECC9F2DF4EDD7513E6E0B7
+ 22: 27816AA94CBA2BF98E49E595AF5B3FAD12BF1D6F1AC6, D04876C5492D275F15C834E3CF794F0E
+ 23: B5658DC148855F68B282211D879F688F3C142FE555CF81, 4539CDA8A65DB9047AAD76B421B81120
+ 24: 72F0BD4F939C2C9B4FA734DCB0AE4FB9BD342BC8459ED2FE, CEA8469BC0457EBF3418C1114288C904
+ 25: 70568245E6E6BD5D11AD0C74030D7AE08BA05057DEA0FBF4AD, 71554FDE6B87477A51EE4499D78783D2
+ 26: 8702D35BE07D7ADF70684046CC6C72FBBBF821E0BBCCBC973601, 33CC6FBFDA15E306919E0C3BB2E22BB6
+ 27: 0BA23F4A6174165D4A8BA80B7C875340B0F8B2A6967D34E106BC22, 00E6679496714236EECEC84B9AF3072E
+ 28: B9E25ABA84C6BD95B5149E7616FE2E1D6FAACEAAD77A636C60279176, 8D8AD0B9D4C709E1DA370EE01611482A
+ 29: 74759711F6D542581F9F83498FB616638D092732BA07109BF4B5BE045C, 71A40DC777BD09F75362F7B20E0B7576
+ 30: ADBF7E98926484BA2C7F6CD7CD9734FC19265F68AF3BFCAEB025F6296E37, 8DF15B5F69B67F7DABE44E3666B55047
+ 31: 2DC26D449379997D110309B2A0DC2760FCE8CADB4B14ED580F86C70F69C9BA, EFCB60EB2B25737E256BC76700B198EF
+ 32: 2B1890EB9FC0B8293E45D42D2126F4072754AA54E220C853C5F20FBA86BE0795, 1A1B15BBC287372FB9AF035FB124B6A1
+
+EAX-safer-k64 (8 byte key)
+ 0: , 9065118C8F6F7842
+ 1: A1, 1926B3F5112C33BA
+ 2: 2E9A, 5FA6078A0AA7B7C8
+ 3: 56FCE2, 984E385F9441FEC8
+ 4: C33ACE8A, 24AC1CBBCCD0D00A
+ 5: 24307E196B, DD2D52EFCA571B68
+ 6: 31471EAA5155, EB41C2B36FAAA774
+ 7: 03D397F6CFFF62, 7DFBC8485C8B169B
+ 8: 8FA39E282C21B5B2, 2C7EC769966B36D7
+ 9: FEA5402D9A8BE34946, A058E165B5FFB556
+ 10: 6CDEF76554CA845193F0, FED516001FFE039A
+ 11: DC50D19E98463543D94820, 8F9CCF32394498A1
+ 12: 42D8DC34F1974FB4EB2535D7, 77F648526BCBB5AF
+ 13: B75F1299EF6211A6318F6A8EAA, C5086AEA1BE7640B
+ 14: 1E28D68373330829DD1FFC5D083E, 33EDA06A7B5929A2
+ 15: 85529CF87C4706751B0D47CC89CEA6, D031905D6141CBED
+ 16: FE5CB61BAF93B30ED3C296EE85F51864, CC484888F0ABD922
+
+EAX-safer-sk64 (8 byte key)
+ 0: , 5254AB3079CDCB78
+ 1: 75, 798DCF14FEF8F4D1
+ 2: 0300, D5FCA75DAC97849C
+ 3: 520F98, 10E357957CE20898
+ 4: 80E2764D, 5C7F46656C6A46EA
+ 5: C48960CDAA, 3CCF44BD41F01CA8
+ 6: E0E60BD9AA2C, EBB493983FCEE79D
+ 7: D13D8804906A1B, 6EDDCA919978F0B6
+ 8: B7AE14C37A343BFB, 2369E38A9B686747
+ 9: 5DE326BBCC7D0D35E9, 041E5EE8568E941C
+ 10: 13494F5B0635BA3D6E53, EAEEA8AFA55141DD
+ 11: A9BB35B14C831FDA0D83F7, 4002A696F1363987
+ 12: E242043A1C355409819FABFC, 63A085B8886C5FDC
+ 13: 204598B889272C6FE694BDBB4D, 194A1530138EFECE
+ 14: EE3F39E0823A82615679C664DEBF, 1EFF8134C8BEFB3A
+ 15: 8579D87FD3B5E2780BC229665F1D1B, A832CD3E1C1C2289
+ 16: 74D7290D72DA67C4A9EAD434AE3A0A85, 96BAA615A5253CB5
+
+EAX-safer-k128 (16 byte key)
+ 0: , 7E32E3F943777EE7
+ 1: D1, BA00336F561731A7
+ 2: F6D7, 8E3862846CD1F482
+ 3: 5323B5, BD1B8C27B061969B
+ 4: A3EC3416, 170BBB9CE17D1D62
+ 5: 0C74D66716, 7BD024B890C5CE01
+ 6: 6158A630EB37, B5C5BD0652ACB712
+ 7: 17F2D0E019947D, F9FF81E2638EC21C
+ 8: 68E135CC154509C8, AA9EAEF8426886AA
+ 9: EDB1ABE0B486749C21, 355C99E4651C0400
+ 10: DB0C30E9367A72E8F5B2, 631B5671B8A1DB9A
+ 11: D4E5453D9A4C9DB5170FCE, 75A2DF0042E14D82
+ 12: 3F429CC9A550CBDA44107AA7, 2C2977EA13FEBD45
+ 13: A7CA22A97C2361171B415E7083, BFE81185F31727A8
+ 14: 170F79D8B0E3F77299C44208C5B1, D5ED9F9459DF9C22
+ 15: 2E24312D2AE5D5F09D5410900A4BBA, 2FC865CA96EA5A7E
+ 16: 8F3C49A316BA27067FF2C6D99EC8C846, 9D840F40CDB62E4B
+
+EAX-safer-sk128 (16 byte key)
+ 0: , 22D90A75BBA5F298
+ 1: 3F, 98C31AB2DE61DE82
+ 2: 584D, F4701D4A1A09928C
+ 3: B9DEAD, 6E221A98505153DA
+ 4: 06D4A6EB, 0E57C51B96BA13B6
+ 5: 7B58B441CA, E28CCF271F5D0A29
+ 6: 7950E0D1EC24, 2ACDDE6E38180C07
+ 7: 65A4F4E098D7C6, 7DC1C9E9602BACF2
+ 8: FEBE4E72BAA0848F, C4607EA3F138BAD9
+ 9: 9B7BD6D6D655985AA3, 8B2C58A9530EA6AC
+ 10: 60C92F925D1478470203, 51E6F5F6DC996F84
+ 11: 7B40769370E651F64AA654, 74F1F8A8D3F4B9AF
+ 12: 7215832C2FB9C54DF7A9C686, 9BF9AEF14F9151D1
+ 13: AD0F9C79008572AB8AE2466EFF, F375D0583D921B69
+ 14: C05076E2C330A0D25D7CEC80597F, 843C12F84B00A8E0
+ 15: D18F0563AB0278140B0CD9A9B07B34, 262B1688E16A171E
+ 16: 650747091F5C532EE37D2D78EE1EC605, 1BAC36144F9A0E8D
+
+EAX-rc2 (8 byte key)
+ 0: , D6CC8632EEE0F46B
+ 1: 4C, EA19572CB8970CB4
+ 2: 5537, 3EDD3253F6D0C1A8
+ 3: 206FA6, 20FA88F03F240D31
+ 4: 17EE8B40, 702E8194F1FCBFDE
+ 5: 2A89287136, 31C5534786E15FB3
+ 6: 3A6AEDC7066B, 3C663A4081E1D243
+ 7: 8BC5203947A644, 6AAC806C92BFBD6E
+ 8: 2E0274BBE14D21A3, CEB0E0CB73C3664C
+ 9: 9C4B292B0CF17E3A29, F23CD535559023EC
+ 10: 8E322734308F85662877, 46363D7EFC322821
+ 11: C413C405767FF5F98E3667, E7BA35D8F3678E7E
+ 12: D77806B7A218098B1569EADC, BA67C306E5C0181B
+ 13: 4BE5EF74F9E9799A4D636FEA9F, 4C511C44ADBA4030
+ 14: 7E19969170C2C8D8AEBA8C7FBC2C, 54CC6D466A2DF6DA
+ 15: 2EF1CEDC1DD3403CF440FC5561BE33, 61C6FB277E93701F
+ 16: DE052719153EBACE9D7B19F52AC4282F, 4AC2A96F2FA8634C
+
+EAX-des (8 byte key)
+ 0: , 44048B7F240B6F5F
+ 1: 0A, 37009B7D4E09953A
+ 2: 03BA, BFD2FD7758961728
+ 3: 37EE10, 16A6AF96DE888A19
+ 4: 07F44290, 100CA84AA0EDAA1D
+ 5: 389EF0023B, 9614FB800A533268
+ 6: 3F4DBA8AA01C, EFA6B55B7ED5E40F
+ 7: 8C7B837896EAE7, C113CE8F664CE3D4
+ 8: 7011D993D8EDB0C7, B4C370A919F60497
+ 9: 0DEB30A31351B13D7B, 00ABC82DC5F3A1AF
+ 10: 8D3897B2CBE323D6EE1C, 7A2D15627CA1441B
+ 11: DBC002C817DEBFB419F94B, D8EB87F86D6ACDEF
+ 12: 17048E2976FA85AA849E9A80, 229FCD1C9D1E3B9C
+ 13: 30B989EF646544885A478AC198, C1B7EB4F799105C8
+ 14: 5C2E12A7F118A08D6FD585F9C839, C358679FEE6FE7D7
+ 15: 8D1A1E888BBB8648E638C4E74E11B8, 685E006C441448B8
+ 16: 93AE906B8BE4EAC8ED6D8F48F04A7AFF, 71DD7AF752FE28FB
+
+EAX-3des (24 byte key)
+ 0: , 8914311BB990B725
+ 1: D8, 2094EDC5D03E54B1
+ 2: FEE5, 781CFB0EBE3895CA
+ 3: DECF5E, 59918E8A5C4B459B
+ 4: BD583AAD, 2013BEEBEEA795A1
+ 5: 2BC01C6C78, 0B1134DBBEAB5D3F
+ 6: 4D5EAF01A895, AB4D17516ECBA50A
+ 7: AF229F90614480, D3113C0A9D133CD4
+ 8: BCA6F375DF4568E0, 8E9EAEC8E77786BC
+ 9: 575F34219E6DD8DB4C, B40C75139E5D1860
+ 10: A199B8AC433B615EC96F, 774AF803698ADE3D
+ 11: 718A2975DD9A872A68AE10, 3B9460F849CBA7FB
+ 12: AB38E148180F6E2FFBB96F91, E3EE3B8FC50DADBC
+ 13: EB10E0233507459D4A6C29EE80, 8D90B46BB1EAB27E
+ 14: EB48559C320DFB056C37458E19B5, 9315F0C4AF8500EB
+ 15: 9E8C73EADA105749B5D8D97392EDC3, 2E749EE66C1E6A16
+ 16: 600FA4149AF252C87B828C780AEFF8BC, 33D7D11DCDC19936
+
+EAX-cast5 (8 byte key)
+ 0: , 382FB8F7E9F69FDC
+ 1: 99, 20DA959849B3F7AB
+ 2: C54B, D05547C6AFA3484A
+ 3: 579836, AAA92B2321FC50C5
+ 4: FEB7AE55, 639EDF01C4FB965D
+ 5: EA8A6023FA, 01274B3ED5CE102C
+ 6: B7C4E995121F, 712BFE27CAFF6DDE
+ 7: F44236660B0004, FAC51D1DF8EC7093
+ 8: 01CD7E3D0BF29E8A, 049C47A45D868D0B
+ 9: DAB170493DFD6E0365, 6F3AEDD9A3ECF4FD
+ 10: 82C9EEC4803D9CD11FA8, 32683C0A9128C6EA
+ 11: 324AC59E87B244ECE0F32F, F6B095AAB49353CF
+ 12: DBDDAB11D02C9CA5843C406E, EA728FC46DDD3B04
+ 13: D67376C2A4AD92E7DD80E39303, CAF72B7E7C237EB3
+ 14: F2B9BBEF08036C2982C6DDD06918, 70A29D780C22752C
+ 15: 96E3D9141F8EBF520540C2BC9A9C23, CEFC86A1CD48203D
+ 16: 70CABBA983179106AE7FCD5F1F31D5C3, BF7F9168F4F82F56
+
+EAX-noekeon (16 byte key)
+ 0: , 556805EEA595CFB9A30FAD196103D7FD
+ 1: F5, 0A7DAEDFB656526CEF4DDBA8087A227A
+ 2: 7B8C, 249895D79962D5B4D18FE07366281B72
+ 3: ACFF15, DCC489D24832EB106F576AE6B6EB957A
+ 4: 08ADE7DB, 0D3215999E9960EDAB29B78744C7F139
+ 5: 66139213F6, 505E1E7141D043E903C26EE0959EEECD
+ 6: 078B79F880A8, 35B7EB326A55E50332866EEDB682EC20
+ 7: 2809E34D9667D4, FFDEC555F68524A09A6ABACA372077D9
+ 8: 93D267DE1EC635D3, 4FF3561990A56E4B374618722EF850FF
+ 9: F377A4D93FF32F4A51, 91D4070423A90FC54D305169C03F49ED
+ 10: 6244B717E082993EB7A1, 2E3A8A354AFA9473667ED7FDD46BE9FC
+ 11: E917559625D25E6E5F2EDA, 19295C37A70314CC9A1D11FDE8D23C92
+ 12: 1E6DF2EE112A893AB14DFA92, 12C4A89D4CD65F8116A03A135AFD3701
+ 13: 47B18CD762E011770E203CF605, 434909A97E118B20D3AEDC79AFE33A9E
+ 14: 72D9A1A7DA6F33D5E0B927F9F32C, 779C23714FCAA2B2321EC7FB5B03E222
+ 15: DA8B830FFCB3DB274807F780D33240, EDC2F1C8A401F328A53392597730B007
+ 16: B53DD2BB840AD933D36A7B5FFDCCFBBB, 4EC0E6D1F916BF633869239B672B37A1
+ 17: 42936BB9A936C30408660855F4F47F3314, F0DAA6DDA15585E1697ABBB4790B15B5
+ 18: 00372E47F5BA016F1B2A1E680B76AB02052A, CDBF3D241BF7FF96D3DFBEDDB872E901
+ 19: 8AA236B0C8BEF6F67A97C2DF90628F6E5838FF, 731DCD61F7F26004C03519F9500EA824
+ 20: 55338647812FC9D86CBDDCED7120268A4D43F8BA, 0E61B3C835CAD95FD49FEF002C014E72
+ 21: 435820B28E52154B47A04D5E635D8FE37FA47FC985, F6A96DCE4917E8D7C610923627E80970
+ 22: 0D30C15B6FEB4A48B14DD15D41A4B25D442AA677B25C, 28E15CCB74AE992C68BDDC8D87802050
+ 23: D9D701F9AD6B0E13D2CDDA15A5194E7CE8BD2C02137391, 2DB9A15884E9C996C3D6B5BDA44B9598
+ 24: E2390AC5CE10CCFBC72106A52C7F180CB477E3C193CBACA8, 22D3F7DCD6947EA4E78DF57A8E1A9A59
+ 25: ADEFB7D9500658D34996AF6BE6336CD78891064EA1DB8E9785, F239D67D039A15C620A7CD4BE4796B3F
+ 26: 89964C90ABF54A6DF9F13C3681E70C702D80A17BE79F8160F30E, 6336F729ECE1ED7368669D75B7E2DCBA
+ 27: 576B2813CECDA4F905BD5D58349EF070FF41B7EB6BB2B01B061B0B, 125324CBF2ACF1011A44A99A11EC8AFC
+ 28: 430B957481748519A60494F0B5F698F34B1A8235B00AC0D1F0A4442E, 1E80A7FCEBBB8E1E12D6831906154485
+ 29: E781BFE5FCDE0BFC056CC86C4A0B9DD3B815BE8CA678204CF47289B5B5, 190D5AAA9EC1CB4CC86FACE53BF1201B
+ 30: 78BFAC07A9B7B2AE9329BF9F9BF18A1A49DD9587001EFCA00E9AD9752764, 4FB5ECBEEB0995C150EBC66508FA19C1
+ 31: 7D6C20694109DE21F7955855A8FF832347518DD496C2A114DF142C68ACDEAA, B25D4BB34056DC091A7A3950D46C32EC
+ 32: 3E1E4395DEC1AFEA9212B95F37E679B6E2D14DF23C5DE49018C2C8038CC4AD45, 9A6DE7BD41A21918AD504490EF4E581D
+
+EAX-skipjack (10 byte key)
+ 0: , 85F74B6AFFB10ACD
+ 1: 3F, 604DF8BDD98A0B3F
+ 2: EA87, 792374FE07588BF9
+ 3: 0169CA, 489AB8AF69DA3306
+ 4: A7AC3EB1, 428DAF508E24B583
+ 5: AA9028D5B3, C0A44EDA71FB2C86
+ 6: DA97BA88A061, DA2EC34077F42585
+ 7: 7E25FAA41CEBC8, 36D4987551E06D5B
+ 8: F662DA6C9001CBFE, B7DEF76680C316A9
+ 9: 6D3F73EC716E1DA897, 5F0F83BAE4D3513B
+ 10: 2A300F585BEE9C889743, F4756C24DEB72A9C
+ 11: 80518B010DD77C82D19106, 50FF5CAA365F4A70
+ 12: 6E579A2173C861B6F37B4CD3, 81E3E5ABBA8F0292
+ 13: 5B04829880A72C38871C7021F3, 6B26F463708A3294
+ 14: 934177878E9A9A9FB4DEB3895922, EBC1C32F0A2A3E96
+ 15: 07AF486D1C458AAB2DBF13C3243FAD, 87288E41A9E64089
+ 16: 84059283DF9A2A8563E7AF69235F26DF, 351652A0DBCE9D6E
+
+EAX-anubis (16 byte key)
+ 0: , 8E20F19D9BA22ABA09FB86FDE6B9EF38
+ 1: 3B, F4201E546A9160F989191942EC8FD1D3
+ 2: 9F38, 4E3CEAE3E1CB954E021A10E814B71732
+ 3: 4F4769, 3E8F35A6A5B11200E9F1AA38590066CD
+ 4: AB41F5FC, EC4C97A8892AAF5433106D4AC8A49843
+ 5: 414F95D61B, BF831E34D1E3FECB973A8C730ECA2E6D
+ 6: 4798322F06D1, 005BBC30BFEDBE6463536C4F80D1A071
+ 7: F256B6CD1BF4F5, 468A28F0661884B846B191B530C8D064
+ 8: 90906F27A633ADDE, 6D9200A37A7F6A456CB103673184C2E5
+ 9: 16CD3C17C9B4EAB135, 6D716E23D7B35109F55B036EDFA7742E
+ 10: 7AD1C22F1F06298DFB25, B076990F8193543C8F3185D3792BCE56
+ 11: 0476F2ABCD057FE6FEE39D, BB2876DB18C00038FADBBD9B264ACC3C
+ 12: B69EDE336407DBC2EE735857, AB63E5906116A8BE22C52B5DA31B1839
+ 13: C3864C1354065A56470669E602, C72BFD3A0BC73BFF051C9AB2F0DFED93
+ 14: 296D8F183A59020D33890420DD7B, C9D90B9EB42C32EDCF6223587D1598A6
+ 15: 256ED8E9D982616680559979BDF2E9, 179FE4E7BA7E966050D35900317E9916
+ 16: D4ED8F30FF9C0470D75B3B16750A3AE4, 5D50F05BB270A292DFF9F67A3BA84675
+ 17: 40CDEB6388274143CA3C4F6020BD9A4875, B27C7DFB1BFBB3FCCEE0171852C7924E
+ 18: 54EF262EC1801D505C7629D038654EBA0594, 9D2060FCD0A2C577511C7752ADE60BBE
+ 19: F39EE54A37F16DD38B624D7AB8F0D9CBD4B981, BC056C7D2C09D813703CDD63C1C69F44
+ 20: F4E7AD474FCA153ABD670E43081ED09EB2C4CC1A, F244BD4D630272F0D98FCA04226C04F1
+ 21: 039ECC36A0A16273E7246CA1FF19D213AC87B53F29, 3056DB6916C925DF220B6C9980EE141A
+ 22: 7DE1DCDEF01447CA2FE83375A48DD84E4A7CB7C01992, 79AFEA4816EAF8DAC8A5E93960F1594F
+ 23: A886C4B914BF0983003272F226F9B2197EF2DC05ACDDE0, B59D85A0FDA5FA4422F7203C055B97A9
+ 24: 00B3E1E91448E250AAFB695C0643A6577AB453EFECFABF53, 4A7EFF1CBC1AB535122A017203616D85
+ 25: 85E972E774D66D0531E40B8FE9E264A77B50FA883AB0943080, B18E164BF89B7E7AB0DC256DFEC7C72F
+ 26: 004849E39334969B392CB0CF3FDEFB3D792DCBBC15F8328C7EDC, 3C51295711F5F878DE8F0B2B5A26A227
+ 27: A0BAD6C2264AB1578993BA49E59D4598822FFED20A57D88F756FF1, 2EB9D525697A419A10DB2A84AEEA5FBC
+ 28: C34DD806EAB5AD823D78BCA78A7709A705FC94ECC521A367D76C9588, 3C57580C7903039D645C06DBAF07B477
+ 29: C447EC77512938CF7862388C32AF22ACE6B5E4CBAA998BE4F5CBC4D215, 43425D09B7ACFD90371C08953946A955
+ 30: 2C16993AAE624CBA4CDAF34FE3D368559E6BE548292B281439866375013B, 3B7360C3FA8FB1C15D19F567153CB46C
+ 31: 538E5DFAF14854A786851E4165F2E01CDDA963E318FCE4FB58E31A6B5CFC33, 2F8EA13B7A6873FE556CA535ABA0968B
+ 32: 5E29CDB7D9695A110043E9C260104BDF020A3A2A139D4112E918AB584BDD7EDA, 9133213AA7BCF062D2BD37F866683D3F
+
+EAX-khazad (16 byte key)
+ 0: , 75968E54452F6781
+ 1: 95, ADAF5949F09B5A22
+ 2: 6B8F, A06B201947424A11
+ 3: 5BE668, 3251416625DF347A
+ 4: 5A92E82B, 33E25772427D9786
+ 5: 62F9F2ABCC, DE714F5F5D17D6D0
+ 6: 0E3CD825BD8D, A7991C8CB8975ED9
+ 7: 4AD0D999503AAD, 53A827D7886F7227
+ 8: BB08E6FAED1DAEE8, 91A118749B7AB9F3
+ 9: 16E30CB12E20D18495, F8F8B8C1280158F9
+ 10: 616DBCC6346959D89E4A, 506BF35A70297D53
+ 11: F86B022D4B28FDB1F0B7D3, EA42220C805FD759
+ 12: 9B8A3D9CDBADD9BBCCCD2B28, BB478D3CE9A229C9
+ 13: CDC4AB4EF2D5B46E87827241F0, 658EDB9497A91823
+ 14: 1A113D96B21B4AEBDB13E34C381A, 63AD0C4084AC84B0
+ 15: 14DA751E5AF7E01F35B3CE74EE1ACF, 3C76AB64E1724DCE
+ 16: A13BBC7E408D2C550634CBC64690B8FE, 3D4BBC0C76536730
+
diff --git a/old/botan/doc/examples/ecdsa.cpp b/old/botan/doc/examples/ecdsa.cpp
new file mode 100644
index 0000000..065203a
--- /dev/null
+++ b/old/botan/doc/examples/ecdsa.cpp
@@ -0,0 +1,57 @@
+#include <botan/botan.h>
+#include <botan/ecdsa.h>
+#include <botan/pubkey.h>
+#include <botan/look_pk.h>
+
+#include <memory>
+#include <iostream>
+
+using namespace Botan;
+
+int main()
+ {
+ Botan::LibraryInitializer init;
+
+ try
+ {
+ AutoSeeded_RNG rng;
+
+ EC_Domain_Params params = get_EC_Dom_Pars_by_oid("1.3.132.0.8");
+
+ ECDSA_PrivateKey ecdsa(rng, params);
+
+ ECDSA_PublicKey ecdsa_pub = ecdsa;
+
+ /*
+ std::cout << params.get_curve().get_p() << "\n";
+ std::cout << params.get_order() << "\n";
+ std::cout << X509::PEM_encode(ecdsa);
+ std::cout << PKCS8::PEM_encode(ecdsa);
+ */
+
+ std::auto_ptr<PK_Signer> signer(get_pk_signer(ecdsa, "EMSA1(SHA-256)"));
+
+ const char* message = "Hello World";
+
+ signer->update((const byte*)message, strlen(message));
+
+ SecureVector<byte> sig = signer->signature(rng);
+
+ std::cout << sig.size() << "\n";
+
+ std::auto_ptr<PK_Verifier> verifier(
+ get_pk_verifier(ecdsa_pub, "EMSA1(SHA-256)"));
+
+ verifier->update((const byte*)message, strlen(message));
+
+ bool ok = verifier->check_signature(sig);
+ if(ok)
+ std::cout << "Signature valid\n";
+ else
+ std::cout << "Bad signature\n";
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << "\n";
+ }
+ }
diff --git a/old/botan/doc/examples/encrypt.cpp b/old/botan/doc/examples/encrypt.cpp
new file mode 100644
index 0000000..348ee8d
--- /dev/null
+++ b/old/botan/doc/examples/encrypt.cpp
@@ -0,0 +1,179 @@
+/*
+Encrypt a file using a block cipher in CBC mode. Compresses the plaintext
+with Zlib, MACs with HMAC(SHA-1). Stores the block cipher used in the file,
+so you don't have to specify it when decrypting.
+
+What a real application would do (and what this example should do), is test for
+the presence of the Zlib module, and use it only if it's available. Then add
+some marker to the stream so the other side knows whether or not the plaintext
+was compressed. Bonus points for supporting multiple compression schemes.
+
+Another flaw is that is stores the entire ciphertext in memory, so if the file
+you're encrypting is 1 Gb... you better have a lot of RAM.
+
+Based on the base64 example, of all things
+
+Written by Jack Lloyd (lloyd@randombit.net) on August 5, 2002
+
+This file is in the public domain
+*/
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <vector>
+#include <cstring>
+#include <memory>
+
+#include <botan/botan.h>
+
+#if defined(BOTAN_HAS_COMPRESSOR_ZLIB)
+ #include <botan/zlib.h>
+#endif
+
+using namespace Botan;
+
+std::string b64_encode(const SecureVector<byte>&);
+
+int main(int argc, char* argv[])
+ {
+ if(argc < 2)
+ {
+ std::cout << "Usage: " << argv[0] << " [-c algo] -p passphrase file\n"
+ " -p : Use this passphrase to encrypt\n"
+ " -c : Encrypt with block cipher 'algo' (default 3DES)\n";
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ std::string algo = "TripleDES";
+ std::string filename, passphrase;
+
+ // Holy hell, argument processing is a PITA
+ for(int j = 1; argv[j] != 0; j++)
+ {
+ if(std::strcmp(argv[j], "-c") == 0)
+ {
+ if(argv[j+1])
+ {
+ algo = argv[j+1];
+ j++;
+ }
+ else
+ {
+ std::cout << "No argument for -c option" << std::endl;
+ return 1;
+ }
+ }
+ else if(std::strcmp(argv[j], "-p") == 0)
+ {
+ if(argv[j+1])
+ {
+ passphrase = argv[j+1];
+ j++;
+ }
+ else
+ {
+ std::cout << "No argument for -p option" << std::endl;
+ return 1;
+ }
+ }
+ else
+ {
+ if(filename != "")
+ {
+ std::cout << "You can only specify one file at a time\n";
+ return 1;
+ }
+ filename = argv[j];
+ }
+ }
+
+ if(passphrase == "")
+ {
+ std::cout << "You have to specify a passphrase!" << std::endl;
+ return 1;
+ }
+
+ std::ifstream in(filename.c_str());
+ if(!in)
+ {
+ std::cout << "ERROR: couldn't open " << filename << std::endl;
+ return 1;
+ }
+
+ std::string outfile = filename + ".enc";
+ std::ofstream out(outfile.c_str());
+ if(!out)
+ {
+ std::cout << "ERROR: couldn't open " << outfile << std::endl;
+ return 1;
+ }
+
+ try
+ {
+ if(!have_block_cipher(algo))
+ {
+ std::cout << "Don't know about the block cipher \"" << algo << "\"\n";
+ return 1;
+ }
+
+ const u32bit key_len = max_keylength_of(algo);
+ const u32bit iv_len = block_size_of(algo);
+
+ AutoSeeded_RNG rng;
+
+ std::auto_ptr<S2K> s2k(get_s2k("PBKDF2(SHA-1)"));
+ s2k->set_iterations(8192);
+ s2k->new_random_salt(rng, 8);
+
+ SymmetricKey bc_key = s2k->derive_key(key_len, "BLK" + passphrase);
+ InitializationVector iv = s2k->derive_key(iv_len, "IVL" + passphrase);
+ SymmetricKey mac_key = s2k->derive_key(16, "MAC" + passphrase);
+
+ // Just to be all fancy we even write a (simple) header.
+ out << "-------- ENCRYPTED FILE --------" << std::endl;
+ out << algo << std::endl;
+ out << b64_encode(s2k->current_salt()) << std::endl;
+
+ Pipe pipe(new Fork(
+ new Chain(new MAC_Filter("HMAC(SHA-1)", mac_key),
+ new Base64_Encoder
+ ),
+ new Chain(
+#ifdef BOTAN_HAS_COMPRESSOR_ZLIB
+ new Zlib_Compression,
+#endif
+ get_cipher(algo + "/CBC", bc_key, iv, ENCRYPTION),
+ new Base64_Encoder(true)
+ )
+ )
+ );
+
+ pipe.start_msg();
+ in >> pipe;
+ pipe.end_msg();
+
+ out << pipe.read_all_as_string(0) << std::endl;
+ out << pipe.read_all_as_string(1);
+
+ }
+ catch(Algorithm_Not_Found)
+ {
+ std::cout << "Don't know about the block cipher \"" << algo << "\"\n";
+ return 1;
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception caught: " << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
+
+std::string b64_encode(const SecureVector<byte>& in)
+ {
+ Pipe pipe(new Base64_Encoder);
+ pipe.process_msg(in);
+ return pipe.read_all_as_string();
+ }
diff --git a/old/botan/doc/examples/encrypt2.cpp b/old/botan/doc/examples/encrypt2.cpp
new file mode 100644
index 0000000..4af0cf0
--- /dev/null
+++ b/old/botan/doc/examples/encrypt2.cpp
@@ -0,0 +1,55 @@
+#include <botan/botan.h>
+#include <botan/pbkdf2.h>
+#include <botan/hmac.h>
+#include <botan/sha160.h>
+
+#include <fstream>
+
+using namespace Botan;
+
+int main()
+ {
+ Botan::LibraryInitializer init;
+
+ AutoSeeded_RNG rng;
+
+ std::string passphrase = "secret";
+
+ std::ifstream infile("readme.txt");
+ std::ofstream outfile("readme.txt.enc");
+
+ PKCS5_PBKDF2 pbkdf2(new HMAC(new SHA_160));
+
+ pbkdf2.set_iterations(4096);
+ pbkdf2.new_random_salt(rng, 8);
+ SecureVector<byte> the_salt = pbkdf2.current_salt();
+
+ SecureVector<byte> master_key = pbkdf2.derive_key(48, passphrase).bits_of();
+
+ KDF* kdf = get_kdf("KDF2(SHA-1)");
+
+ SymmetricKey key = kdf->derive_key(20, master_key, "cipher key");
+ SymmetricKey mac_key = kdf->derive_key(20, master_key, "hmac key");
+ InitializationVector iv = kdf->derive_key(8, master_key, "cipher iv");
+
+ Pipe pipe(new Fork(
+ new Chain(
+ get_cipher("Blowfish/CBC/PKCS7", key, iv, ENCRYPTION),
+ new Base64_Encoder,
+ new DataSink_Stream(outfile)
+ ),
+ new Chain(
+ new MAC_Filter("HMAC(SHA-1)", mac_key),
+ new Hex_Encoder)
+ )
+ );
+
+ outfile.write((const char*)the_salt.begin(), the_salt.size());
+
+ pipe.start_msg();
+ infile >> pipe;
+ pipe.end_msg();
+
+ SecureVector<byte> hmac = pipe.read_all(1);
+ outfile.write((const char*)hmac.begin(), hmac.size());
+ }
diff --git a/old/botan/doc/examples/factor.cpp b/old/botan/doc/examples/factor.cpp
new file mode 100644
index 0000000..ff3c23c
--- /dev/null
+++ b/old/botan/doc/examples/factor.cpp
@@ -0,0 +1,144 @@
+/*
+ Factor integers using a combination of trial division by small primes,
+ and Pollard's Rho algorithm
+*/
+#include <botan/botan.h>
+#include <botan/reducer.h>
+#include <botan/numthry.h>
+using namespace Botan;
+
+#include <algorithm>
+#include <iostream>
+#include <memory>
+
+// Pollard's Rho algorithm, as described in the MIT algorithms book
+
+// We use (x^2+x) mod n instead of (x*2-1) mod n as the random function,
+// it _seems_ to lead to faster factorization for the values I tried.
+
+BigInt rho(const BigInt& n, RandomNumberGenerator& rng)
+ {
+ BigInt x = BigInt::random_integer(rng, 0, n-1);
+ BigInt y = x;
+ BigInt d = 0;
+
+ Modular_Reducer mod_n(n);
+
+ u32bit i = 1, k = 2;
+ while(true)
+ {
+ i++;
+
+ if(i == 0) // overflow, bail out
+ break;
+
+ x = mod_n.multiply((x + 1), x);
+
+ d = gcd(y - x, n);
+ if(d != 1 && d != n)
+ return d;
+
+ if(i == k)
+ {
+ y = x;
+ k = 2*k;
+ }
+ }
+ return 0;
+ }
+
+// Remove (and return) any small (< 2^16) factors
+std::vector<BigInt> remove_small_factors(BigInt& n)
+ {
+ std::vector<BigInt> factors;
+
+ while(n.is_even())
+ {
+ factors.push_back(2);
+ n /= 2;
+ }
+
+ for(u32bit j = 0; j != PRIME_TABLE_SIZE; j++)
+ {
+ if(n < PRIMES[j])
+ break;
+
+ BigInt x = gcd(n, PRIMES[j]);
+
+ if(x != 1)
+ {
+ n /= x;
+
+ u32bit occurs = 0;
+ while(x != 1)
+ {
+ x /= PRIMES[j];
+ occurs++;
+ }
+
+ for(u32bit k = 0; k != occurs; k++)
+ factors.push_back(PRIMES[j]);
+ }
+ }
+
+ return factors;
+ }
+
+std::vector<BigInt> factorize(const BigInt& n_in,
+ RandomNumberGenerator& rng)
+ {
+ BigInt n = n_in;
+ std::vector<BigInt> factors = remove_small_factors(n);
+
+ while(n != 1)
+ {
+ if(is_prime(n, rng))
+ {
+ factors.push_back(n);
+ break;
+ }
+
+ BigInt a_factor = 0;
+ while(a_factor == 0)
+ a_factor = rho(n, rng);
+
+ std::vector<BigInt> rho_factored = factorize(a_factor, rng);
+ for(u32bit j = 0; j != rho_factored.size(); j++)
+ factors.push_back(rho_factored[j]);
+
+ n /= a_factor;
+ }
+ return factors;
+ }
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 2)
+ {
+ std::cerr << "Usage: " << argv[0] << " integer\n";
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ try
+ {
+ BigInt n(argv[1]);
+
+ AutoSeeded_RNG rng;
+
+ std::vector<BigInt> factors = factorize(n, rng);
+ std::sort(factors.begin(), factors.end());
+
+ std::cout << n << ": ";
+ for(u32bit j = 0; j != factors.size(); j++)
+ std::cout << factors[j] << " ";
+ std::cout << "\n";
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
diff --git a/old/botan/doc/examples/gen_certs.cpp b/old/botan/doc/examples/gen_certs.cpp
new file mode 100644
index 0000000..f635e1c
--- /dev/null
+++ b/old/botan/doc/examples/gen_certs.cpp
@@ -0,0 +1,124 @@
+/*
+* Generate a root CA plus httpd, dovecot, and postfix certs/keys
+*
+*/
+
+#include <botan/botan.h>
+#include <botan/rsa.h>
+#include <botan/util.h>
+#include <botan/x509self.h>
+#include <botan/x509_ca.h>
+
+using namespace Botan;
+
+#include <iostream>
+#include <fstream>
+
+void fill_commoninfo(X509_Cert_Options& opts)
+ {
+ opts.country = "US";
+ opts.organization = "randombit.net";
+ opts.email = "admin@randombit.net";
+ opts.locality = "Vermont";
+ }
+
+X509_Certificate make_ca_cert(RandomNumberGenerator& rng,
+ const Private_Key& priv_key,
+ const X509_Time& now,
+ const X509_Time& later)
+ {
+ X509_Cert_Options opts;
+ fill_commoninfo(opts);
+ opts.common_name = "randombit.net CA";
+ opts.start = now;
+ opts.end = later;
+ opts.CA_key();
+
+ return X509::create_self_signed_cert(opts, priv_key, rng);
+ }
+
+PKCS10_Request make_server_cert_req(const Private_Key& key,
+ const std::string& hostname,
+ RandomNumberGenerator& rng)
+ {
+ X509_Cert_Options opts;
+ opts.common_name = hostname;
+ fill_commoninfo(opts);
+
+ opts.add_ex_constraint("PKIX.ServerAuth");
+
+ return X509::create_cert_req(opts, key, rng);
+ }
+
+void save_pair(const std::string& name,
+ const std::string& password,
+ const X509_Certificate& cert,
+ const Private_Key& key,
+ RandomNumberGenerator& rng)
+ {
+ std::string cert_fsname = name + "_cert.pem";
+ std::string key_fsname = name + "_key.pem";
+
+ std::ofstream cert_out(cert_fsname.c_str());
+ cert_out << cert.PEM_encode() << "\n";
+ cert_out.close();
+
+ std::ofstream key_out(key_fsname.c_str());
+ if(password != "")
+ key_out << PKCS8::PEM_encode(key, rng, password);
+ else
+ key_out << PKCS8::PEM_encode(key);
+ key_out.close();
+ }
+
+int main()
+ {
+ const u32bit seconds_in_a_year = 31556926;
+
+ const u32bit current_time = system_time();
+
+ X509_Time now = X509_Time(current_time);
+ X509_Time later = X509_Time(current_time + 4*seconds_in_a_year);
+
+ LibraryInitializer init;
+
+ AutoSeeded_RNG rng;
+
+ RSA_PrivateKey ca_key(rng, 2048);
+
+ X509_Certificate ca_cert = make_ca_cert(rng, ca_key, now, later);
+
+ const std::string ca_password = "sekrit";
+
+ save_pair("ca", ca_password, ca_cert, ca_key, rng);
+
+ X509_CA ca(ca_cert, ca_key);
+
+ RSA_PrivateKey httpd_key(rng, 1536);
+ X509_Certificate httpd_cert = ca.sign_request(
+ make_server_cert_req(httpd_key, "www.randombit.net", rng),
+ rng, now, later);
+
+ save_pair("httpd", "", httpd_cert, httpd_key, rng);
+
+ RSA_PrivateKey bugzilla_key(rng, 1536);
+ X509_Certificate bugzilla_cert = ca.sign_request(
+ make_server_cert_req(bugzilla_key, "bugs.randombit.net", rng),
+ rng, now, later);
+
+ save_pair("bugzilla", "", bugzilla_cert, bugzilla_key, rng);
+
+ RSA_PrivateKey postfix_key(rng, 1536);
+ X509_Certificate postfix_cert = ca.sign_request(
+ make_server_cert_req(postfix_key, "mail.randombit.net", rng),
+ rng, now, later);
+
+ save_pair("postfix", "", postfix_cert, postfix_key, rng);
+
+ RSA_PrivateKey dovecot_key(rng, 1536);
+ X509_Certificate dovecot_cert = ca.sign_request(
+ make_server_cert_req(dovecot_key, "imap.randombit.net", rng),
+ rng, now, later);
+
+ save_pair("dovecot", "", dovecot_cert, dovecot_key, rng);
+ }
diff --git a/old/botan/doc/examples/gtk/dsa.cpp b/old/botan/doc/examples/gtk/dsa.cpp
new file mode 100644
index 0000000..dff5477
--- /dev/null
+++ b/old/botan/doc/examples/gtk/dsa.cpp
@@ -0,0 +1,556 @@
+/*
+ This shows some of the details involved in a GUI application that uses
+ Botan. Actually most of the code is just dealing with GTK+, but it shows how
+ the password callback and pulse function stuff works. (See gtk_ui.cpp for the
+ acutal password callback code.)
+
+ The major points of interest (assuming what you care about is how to use
+ Botan from a GUI, and not looking at my terrible GTK code) are gtk_ui.cpp
+ and, in this file, GTK_Pulse, gen_key(), and get_key():
+
+ gtk_ui.cpp and get_key() show how to get a passphrase from a user for
+ decrypting (well, in theory, anything), but in this case, PKCS #8 private
+ keys. Which is coincidentally the only thing Botan currently uses UI
+ objects for, though that will probably change eventually. GTK_UI does
+ double duty, for getting passphrases for encryption as well (in
+ do_save_key).
+
+ gen_key() and GTK_Pulse show how to do an activity meter while doing a
+ long-term operation inside Botan. Since, typically, the only operations
+ which take a long time and can't be broken up into smaller parts are prime
+ generation/testing, that is currently where the pulse hooks are
+ called. It's certainly not the most general callback method in the world,
+ but it's general enough that it's usable without getting in the way too
+ much. The callbacks will eventually be extended to other parts of the
+ library (Pipe, maybe) where it's useful.
+
+ This program is in the public domain.
+*/
+#include <fstream>
+#include <iostream>
+#include <memory>
+
+#include <botan/botan.h>
+#include <botan/libstate.h>
+#include <botan/look_pk.h>
+#include <botan/filters.h>
+#include <botan/dsa.h>
+// we don't have a 'using namespace' here, so it's easy to grep for code that
+// is actually dealing with the library (rather than messing around with GTK).
+
+#include <gtk/gtk.h>
+#include "gtk_ui.h"
+
+/*************************************************
+* Pop up an message box *
+*************************************************/
+static void show_dialog(const std::string& about_message,
+ const std::string& dialog_name)
+ {
+ GtkDialogFlags flags =
+ (GtkDialogFlags)(GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL);
+
+ GtkWidget* dialog = gtk_dialog_new_with_buttons(dialog_name.c_str(),
+ NULL, flags,
+ GTK_STOCK_OK,
+ GTK_RESPONSE_NONE,
+ NULL);
+ GtkWidget* label = gtk_label_new(NULL);
+ gtk_label_set_markup(GTK_LABEL(label), about_message.c_str());
+ gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
+
+ g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
+ G_CALLBACK(gtk_widget_destroy),
+ GTK_OBJECT(dialog));
+
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
+ gtk_widget_show_all(dialog);
+ }
+
+/*************************************************
+* Pop up an About box *
+*************************************************/
+static void show_about()
+ {
+ const std::string about_message =
+ "<big>DSA Utility</big>\n"
+ "\n"
+ "A simple application showing how to use Botan within a GUI.\n"
+ "It lets you generate or load keys, and sign text files.\n"
+ "\n"
+ "Send comments/questions to <tt>lloyd@randombit.net</tt>";
+
+ show_dialog(about_message, "About");
+ }
+
+/*************************************************
+* Pop up a help box *
+*************************************************/
+static void show_help()
+ {
+ const std::string help_message =
+ "<big>DSA Utility Help</big>\n"
+ "\n"
+ "Simply, this is a (very) simple text editor, with the added ability\n"
+ "of being able to generate or read a DSA private key, and sign the\n"
+ "text buffer using that key.\n"
+ "\n"
+ "You can load, edit, and save text files as you would normally. If a\n"
+ "key is loaded (done using the commands in the Keys menu), you can\n"
+ "also use the Sign command (in the Signing menu) to generate a\n"
+ "signature for the current file. It will be displayed at the bottom\n"
+ "of the screen (if it has been calculated for the current buffer\n"
+ "contents), and can be saved using the \"Save Sig\" command.\n"
+ "\n"
+ "Signatures generated by this program can be verified using a the\n"
+ "<tt>dsa_ver</tt> example included in the Botan distribution.\n";
+
+ show_dialog(help_message, "Help");
+ }
+
+/*************************************************
+* Get and return a filename from the user *
+*************************************************/
+static std::string get_filename(const std::string& title)
+ {
+ GtkWidget* dialog = gtk_file_selection_new(title.c_str());
+
+ /* Some window managers don't display the titles of transient windows,
+ put a message elsewhere for those people.
+ */
+ GtkWidget* label = gtk_label_new(title.c_str());
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
+
+ std::string fsname;
+
+ gtk_widget_show(label); /* dialog_run won't show sub-widgets */
+ if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
+ fsname = gtk_file_selection_get_filename(GTK_FILE_SELECTION(dialog));
+ gtk_widget_destroy(dialog);
+
+ /* If it's a directory, that's no good */
+ if(fsname.size() && fsname[fsname.size()-1] == '/')
+ return "";
+
+ return fsname;
+ }
+
+/*************************************************
+* Global state *
+*************************************************/
+static Botan::DSA_PrivateKey* key = 0; // our key
+static GtkTextBuffer* buffer = 0; // the text buffer
+static std::string buffer_source;
+ // what file (if any) the buffer's data came from
+static GtkWidget* sig_view = 0; // the signature
+
+/*************************************************
+* Zap the currently set signature (if any) *
+*************************************************/
+static void zap_sig()
+ {
+ gtk_editable_delete_text(GTK_EDITABLE(sig_view), 0, -1);
+ }
+
+/*************************************************
+* Save the current key *
+*************************************************/
+static void do_save_key(const std::string& title)
+ {
+ if(key == 0)
+ return;
+
+ std::string filename = get_filename(title.c_str());
+
+ if(filename != "")
+ {
+ const std::string msg = "Select a passphrase to encrypt the key:";
+
+ std::ofstream out_priv(filename.c_str());
+
+ GTK_UI ui;
+ Botan::User_Interface::UI_Result result;
+ std::string passphrase = ui.get_passphrase(msg, result);
+
+ if(result == Botan::User_Interface::OK)
+ out_priv << Botan::PKCS8::PEM_encode(*key, passphrase);
+ else
+ out_priv << Botan::PKCS8::PEM_encode(*key);
+
+ // for testing
+ //std::cout << X509::PEM_encode(*key);
+ }
+ }
+
+/*************************************************
+* Generate a signature for the text buffer *
+*************************************************/
+static void sign_buffer()
+ {
+ /* No key? Ignore request. */
+ if(key == 0)
+ return;
+
+ /* same format as the text-mode dsa_sign example */
+ Botan::Pipe pipe(new Botan::PK_Signer_Filter(
+ Botan::get_pk_signer(*key, "EMSA1(SHA-1)")
+ ),
+ new Botan::Base64_Encoder
+ );
+
+ /* It would probably be smart to do this a little bit at a time */
+ GtkTextIter start, end;
+ gtk_text_buffer_get_bounds(buffer, &start, &end);
+ gchar* bits = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
+ size_t length = strlen(bits);
+
+ pipe.start_msg();
+ pipe.write((unsigned char*)bits, length);
+ pipe.end_msg();
+
+ std::string sig = pipe.read_all_as_string();
+
+ zap_sig();
+
+ gint position = 0;
+ gtk_editable_insert_text(GTK_EDITABLE(sig_view), sig.c_str(), sig.length(),
+ &position);
+
+ g_free(bits);
+ }
+
+/*************************************************
+* GTK+ pulse callback *
+*************************************************/
+class GTK_Pulse : public Botan::Library_State::UI
+ {
+ public:
+ void pulse(Botan::Pulse_Type);
+ };
+
+void GTK_Pulse::pulse(Botan::Pulse_Type)
+ {
+ /* We need this to flush the updates, otherwise GTK+ will wait until we're
+ done with the computation before doing any updates (generally the right
+ thing, but not with a progress bar).
+ */
+
+ while(gtk_events_pending())
+ gtk_main_iteration();
+ }
+
+/*************************************************
+* Actual do the pulse (as a GTK+ timeout func) *
+*************************************************/
+static gboolean gtk_pulse_timeout(void* pbar)
+ {
+ GtkWidget* progress_bar = (GtkWidget*)pbar;
+ gtk_progress_bar_pulse(GTK_PROGRESS_BAR(progress_bar));
+ return TRUE; /* keep calling us */
+ }
+
+/*************************************************
+* Generate a new key *
+*************************************************/
+static void gen_key()
+ {
+ /* This gives a nice smooth progress bar, though we do use up quite a bit of
+ CPU for it. Keep in mind that if PULSE_INTERVAL is significantly less
+ than the average time between pulses from the library, the progress bar
+ will jerk around going slower or faster. Keep it at at least 50ms.
+ */
+ const double PROGRESS_PER_PULSE = .01; /* % of bar */
+ const guint32 PULSE_INTERVAL = 30; /* ms */
+
+ delete key;
+
+ GtkDialogFlags flags =
+ (GtkDialogFlags)(GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL);
+
+ GtkWidget* dialog =
+ gtk_dialog_new_with_buttons("Generating Key", NULL, flags, NULL);
+
+ GtkWidget* label = gtk_label_new(" Generating new key, please wait... \n");
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
+
+ GtkWidget* progress_bar = gtk_progress_bar_new();
+ gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(progress_bar),
+ PROGRESS_PER_PULSE);
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), progress_bar);
+
+ guint timer_id = gtk_timeout_add(PULSE_INTERVAL, gtk_pulse_timeout,
+ progress_bar);
+
+ gtk_widget_show_all(dialog);
+
+ while(gtk_events_pending())
+ gtk_main_iteration();
+
+ /* Register gtk_pulse so it will be called every so often when we embark
+ on our prime generation quest...
+ */
+ /* this just updates the GUI; the GTK+ timeout function actually updates
+ the progress bar. That's because the amount of time between pulses
+ from the library is rather irregular, so the progress bar looks jerky.
+ */
+ Botan::global_state().set_ui(new GTK_Pulse);
+
+ /* Not generally recommended, since it's slow and there's not much point.
+ However, *because* it's slow, we'll want to put up a progress bar or
+ something, and part of this whole thing is to show how to do that and get
+ the pulse functions to do the right thing.
+ */
+ Botan::DL_Group group(1024, Botan::DL_Group::DSA_Kosherizer);
+ key = new Botan::DSA_PrivateKey(group);
+
+ gtk_timeout_remove(timer_id);
+ Botan::global_state().set_ui(0); // unset the pulse function
+
+ gtk_widget_destroy(dialog);
+
+ do_save_key("Save New Key");
+
+ /* new key, any old sigs are no longer useful */
+ zap_sig();
+ }
+
+/*************************************************
+* Load up a key *
+*************************************************/
+static void get_key()
+ {
+ std::string fsname = get_filename("Select a DSA Key");
+
+ if(fsname != "")
+ {
+ try {
+ delete key;
+ key = 0;
+ zap_sig();
+
+ /*
+ A GTK_UI is a subclass of User_Interface that pops up a dialog that
+ asks the user for a passphrase. It actually works quite well,
+ though the fixed upper limit on the passphrase size is not
+ ideal. Feel free to use it as-is or modify it however you like
+ (gtk_ui.* is public domain).
+ */
+ GTK_UI ui;
+ Botan::PKCS8_PrivateKey* p8_key = Botan::PKCS8::load_key(fsname, ui);
+ key = dynamic_cast<Botan::DSA_PrivateKey*>(p8_key);
+ if(!key)
+ show_dialog("The key in " + fsname + " is not a DSA key",
+ "Failure");
+ }
+ catch(std::exception)
+ {
+ key = 0; // make sure it's not something random
+ show_dialog("Loading the key from " + fsname + " failed.", "Failure");
+ }
+ }
+ }
+
+static void really_sign_buffer()
+ {
+ /* No key? Ask the user for one. */
+ if(key == 0)
+ get_key();
+ sign_buffer();
+ }
+
+/*************************************************
+* Clear the text buffer *
+*************************************************/
+static void new_buffer()
+ {
+ /*
+ In theory, it would be nice to check if this was unsaved text and prompt
+ to save it. However, this really isn't supposed to be a GTK+ example, so
+ we won't.
+ */
+ gtk_text_buffer_set_text(buffer, "", -1);
+ buffer_source = "";
+ }
+
+/*************************************************
+* Put the contents of a file into the buffer *
+*************************************************/
+static void open_buffer()
+ {
+ std::string filename = get_filename("Select File");
+
+ if(filename == "")
+ return;
+
+ std::ifstream in(filename.c_str());
+
+ new_buffer();
+ buffer_source = filename;
+
+ while(in.good())
+ {
+ char buf[1024] = { 0 };
+
+ in.read(buf, 1024);
+ size_t got = in.gcount();
+
+ GtkTextIter iter;
+ gtk_text_buffer_get_end_iter(buffer, &iter);
+ gtk_text_buffer_insert(buffer, &iter, buf, got);
+ }
+ }
+
+/*************************************************
+* Save the signature to a file *
+*************************************************/
+static void save_sig()
+ {
+ std::string sig_file = buffer_source;
+
+ /* No sig, nothing to save */
+ const gchar* sig = gtk_entry_get_text(GTK_ENTRY(sig_view));
+ if(strlen(sig) == 0)
+ return;
+
+ if(sig_file == "")
+ sig_file = get_filename("Select Signature Output File");
+ else
+ sig_file += ".sig";
+
+ std::ofstream out(sig_file.c_str());
+ out << sig << std::endl;
+ }
+
+/*************************************************
+* Save the current key *
+*************************************************/
+static void save_key()
+ {
+ do_save_key("Save Current Key");
+ }
+
+/*************************************************
+* Common case of Save/Save As *
+*************************************************/
+static void do_save(const std::string& filename)
+ {
+ std::ofstream out(filename.c_str());
+
+ GtkTextIter start, end;
+ gtk_text_buffer_get_bounds(buffer, &start, &end);
+ gchar* bits = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
+ out.write(bits, strlen(bits));
+ g_free(bits);
+ buffer_source = filename;
+ }
+
+/*************************************************
+* Save the buffer *
+*************************************************/
+static void save_buffer_as()
+ {
+ std::string filename = get_filename("Select Output File");
+ if(filename != "")
+ do_save(filename);
+ }
+
+/*************************************************
+* Save the buffer *
+*************************************************/
+static void save_buffer()
+ {
+ if(buffer_source != "")
+ do_save(buffer_source);
+ else
+ save_buffer_as();
+ }
+
+/*************************************************
+* Make a menubar for the app *
+*************************************************/
+static GtkWidget* make_menubar(GtkWidget *window)
+ {
+ static GtkItemFactoryEntry menu_items[] = {
+ { "/_File", NULL, NULL, 0, "<Branch>", NULL },
+ { "/File/_New", "<control>N", new_buffer, 0, NULL, NULL },
+ { "/File/_Open", "<control>O", open_buffer, 0, NULL, NULL },
+ { "/File/_Save", "<control>S", save_buffer, 0, NULL, NULL },
+ { "/File/Save _As", NULL, save_buffer_as, 0, NULL, NULL },
+ { "/File/sep1", NULL, NULL, 0, "<Separator>", NULL },
+ { "/File/Save Sig", NULL, save_sig, 0, NULL, NULL },
+ { "/File/sep2", NULL, NULL, 0, "<Separator>", NULL },
+ { "/File/_Quit", "<control>Q", gtk_main_quit, 0, NULL, NULL },
+
+ { "/_Keys", NULL, NULL, 0, "<Branch>", NULL },
+ { "/Keys/Open", NULL, get_key, 0, NULL, NULL },
+ { "/Keys/_Generate", NULL, gen_key, 0, NULL, NULL },
+ { "/Keys/Save Current", NULL, save_key, 0, NULL, NULL },
+
+ { "/Signing", NULL, NULL, 0, "<Branch>", NULL },
+ { "/Signing/Sign", NULL, really_sign_buffer, 0, NULL, NULL },
+
+ { "/_Help", NULL, NULL, 0, "<LastBranch>", NULL },
+ { "/Help/Help", NULL, show_help, 0, NULL, NULL },
+ { "/Help/sep1", NULL, NULL, 0, "<Separator>", NULL },
+ { "/Help/About", NULL, show_about, 0, NULL, NULL },
+ };
+
+ GtkAccelGroup* accel_group = gtk_accel_group_new();
+ GtkItemFactory* item_factory =
+ gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group);
+ const gint nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
+ gtk_item_factory_create_items(item_factory, nmenu_items, menu_items, NULL);
+ gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
+ return gtk_item_factory_get_widget(item_factory, "<main>");
+ }
+
+int main(int argc, char *argv[])
+ {
+ gtk_init(&argc, &argv);
+
+ try {
+ Botan::LibraryInitializer init;
+
+ /* Create a new top-level window */
+ GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title(GTK_WINDOW(window), "DSA Utility");
+ gtk_signal_connect(GTK_OBJECT(window), "delete_event",
+ gtk_main_quit, NULL);
+
+ /* Create the vbox to hold our stuff */
+ GtkWidget* vbox = gtk_vbox_new(FALSE, 0);
+ gtk_container_border_width(GTK_CONTAINER(vbox), 1);
+ gtk_container_add(GTK_CONTAINER(window), vbox);
+
+ /* Create the menu bar */
+ GtkWidget *menubar = make_menubar(window);
+
+ /* Create the entry that holds the signature */
+ sig_view = gtk_entry_new();
+ gtk_editable_set_editable(GTK_EDITABLE(sig_view), FALSE);
+
+ /* Create the text box */
+ GtkWidget* view = gtk_text_view_new();
+ buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
+
+ gtk_widget_set_size_request(view, 640, 480);
+ gtk_text_buffer_set_text(buffer, "Some initial contents.", -1);
+
+ // Resign it on each change: fast enough, but probably not really useful
+ //g_signal_connect(G_OBJECT(buffer), "changed", sign_buffer, 0);
+ g_signal_connect(G_OBJECT(buffer), "changed", zap_sig, 0);
+
+ gtk_container_add(GTK_CONTAINER(vbox), menubar);
+ gtk_container_add(GTK_CONTAINER(vbox), view);
+ gtk_container_add(GTK_CONTAINER(vbox), sig_view);
+
+ gtk_widget_show_all(window);
+
+ gtk_main();
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << std::endl;
+ }
+ return 0;
+ }
diff --git a/old/botan/doc/examples/gtk/gtk_ui.cpp b/old/botan/doc/examples/gtk/gtk_ui.cpp
new file mode 100644
index 0000000..515fbc5
--- /dev/null
+++ b/old/botan/doc/examples/gtk/gtk_ui.cpp
@@ -0,0 +1,78 @@
+/*************************************************
+* GTK+ User Interface Source File *
+*************************************************/
+
+#include "gtk_ui.h"
+
+/*************************************************
+* GTK+ Callback *
+*************************************************/
+void GTK_UI::callback(GtkWidget* entry, gpointer passphrase_ptr)
+ {
+ const gchar *entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
+ char* passphrase = (char*)passphrase_ptr;
+ strcpy(passphrase, entry_text);
+ }
+
+/*************************************************
+* Get a passphrase from the user *
+*************************************************/
+std::string GTK_UI::get_passphrase(const std::string& what,
+ const std::string& source,
+ UI_Result& result) const
+ {
+ std::string msg = "A passphrase is needed to access the " + what;
+ if(source != "") msg += "\nin " + source;
+ return get_passphrase(msg, result);
+ }
+
+/*************************************************
+* Get a passphrase from the user *
+*************************************************/
+std::string GTK_UI::get_passphrase(const std::string& label_text,
+ UI_Result& result) const
+ {
+ const int MAX_PASSPHRASE = 64;
+
+ GtkDialogFlags flags =
+ (GtkDialogFlags)(GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL);
+
+ GtkWidget* dialog = gtk_dialog_new_with_buttons(
+ "Enter Passphrase",
+ NULL, flags,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ NULL);
+
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
+
+ GtkWidget* label = gtk_label_new(label_text.c_str());
+
+ GtkWidget* entry = gtk_entry_new();
+ gtk_entry_set_visibility(GTK_ENTRY(entry), 0);
+ gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
+ gtk_entry_set_max_length(GTK_ENTRY(entry), MAX_PASSPHRASE);
+
+ char passphrase_buf[MAX_PASSPHRASE + 1] = { 0 };
+
+ gtk_signal_connect(GTK_OBJECT(entry), "activate",
+ GTK_SIGNAL_FUNC(callback), passphrase_buf);
+
+ GtkWidget* vbox = gtk_vbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, FALSE, 0);
+
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox, TRUE, TRUE, 0);
+ gtk_widget_show_all(vbox);
+
+ /* Block until we get something back */
+ result = CANCEL_ACTION;
+ if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
+ result = OK;
+
+ gtk_widget_destroy(dialog);
+
+ if(result == OK)
+ return std::string(passphrase_buf);
+ return "";
+ }
diff --git a/old/botan/doc/examples/gtk/gtk_ui.h b/old/botan/doc/examples/gtk/gtk_ui.h
new file mode 100644
index 0000000..9ced83a
--- /dev/null
+++ b/old/botan/doc/examples/gtk/gtk_ui.h
@@ -0,0 +1,25 @@
+/*************************************************
+* GTK+ User Interface Header File *
+*************************************************/
+
+#ifndef BOTAN_EXT_GTK_UI__
+#define BOTAN_EXT_GTK_UI__
+
+#include <botan/ui.h>
+#include <gtk/gtk.h>
+
+/*************************************************
+* GTK+ Passphrase Callback Object *
+*************************************************/
+class GTK_UI : public Botan::User_Interface
+ {
+ public:
+ std::string get_passphrase(const std::string&, const std::string&,
+ UI_Result&) const;
+
+ std::string get_passphrase(const std::string&, UI_Result&) const;
+
+ static void callback(GtkWidget*, gpointer);
+ };
+
+#endif
diff --git a/old/botan/doc/examples/gtk/readme.txt b/old/botan/doc/examples/gtk/readme.txt
new file mode 100644
index 0000000..4f36911
--- /dev/null
+++ b/old/botan/doc/examples/gtk/readme.txt
@@ -0,0 +1,18 @@
+
+This is an example of how to use Botan in a GUI. You need at least
+Botan 1.6.0.
+
+You'll also need GTK+ 2.x (tested with GTK+ 2.10; should work with
+most versions). Keep in mind that I was learning GTK as I was writing
+this code, so it is not exactly the best GTK code you're likely to
+see.
+
+dsa.cpp is the main GTK+ driver. It has some comments at the top which
+point out major areas of interest.
+
+gtk_ui.* implement a User_Interface object that opens up a GTK+ dialog
+box that asks the user for their passphrase. It works pretty well, the
+only major deficiency is a fixed upper limit on the size of the
+passphrase (currently 64). You may want to use this in your own code,
+assuming you use GTK. If not, it should at least provide an outline
+for writing a version for your favorite windowing system.
diff --git a/old/botan/doc/examples/hash.cpp b/old/botan/doc/examples/hash.cpp
new file mode 100644
index 0000000..a97cd60
--- /dev/null
+++ b/old/botan/doc/examples/hash.cpp
@@ -0,0 +1,64 @@
+/*
+Prints the message digest of files, using an arbitrary hash function
+chosen by the user. This is less flexible that I might like, for example:
+ ./hash sha1 some_file [or md5 or sha-1 or ripemd160 or ...]
+will not work, cause the name lookup is case-sensitive. Oh well...
+
+Written by Jack Lloyd (lloyd@randombit.net), on August 4, 2002
+ - December 16, 2003: "Fixed" to accept "sha1" or "md5" as a hash name
+
+This file is in the public domain
+*/
+
+#include <iostream>
+#include <fstream>
+#include <botan/botan.h>
+
+int main(int argc, char* argv[])
+ {
+ if(argc < 3)
+ {
+ std::cout << "Usage: " << argv[0] << " digest <filenames>" << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ std::string hash = argv[1];
+ /* a couple of special cases, kind of a crock */
+ if(hash == "sha1") hash = "SHA-1";
+ if(hash == "md5") hash = "MD5";
+
+ try {
+ if(!Botan::have_hash(hash))
+ {
+ std::cout << "Unknown hash \"" << argv[1] << "\"" << std::endl;
+ return 1;
+ }
+
+ Botan::Pipe pipe(new Botan::Hash_Filter(hash),
+ new Botan::Hex_Encoder);
+
+ int skipped = 0;
+ for(int j = 2; argv[j] != 0; j++)
+ {
+ std::ifstream file(argv[j]);
+ if(!file)
+ {
+ std::cout << "ERROR: could not open " << argv[j] << std::endl;
+ skipped++;
+ continue;
+ }
+ pipe.start_msg();
+ file >> pipe;
+ pipe.end_msg();
+ pipe.set_default_msg(j-2-skipped);
+ std::cout << pipe << " " << argv[j] << std::endl;
+ }
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception caught: " << e.what() << std::endl;
+ }
+ return 0;
+ }
diff --git a/old/botan/doc/examples/hash_fd.cpp b/old/botan/doc/examples/hash_fd.cpp
new file mode 100644
index 0000000..82ca2c3
--- /dev/null
+++ b/old/botan/doc/examples/hash_fd.cpp
@@ -0,0 +1,71 @@
+/*
+Written by Jack Lloyd (lloyd@randombit.net), on Prickle-Prickle,
+the 10th of Bureaucracy, 3167.
+
+This file is in the public domain
+
+This is just like the normal hash application, but uses the Unix I/O system
+calls instead of C++ iostreams. Previously, this version was much faster and
+smaller, but GCC 3.1's libstdc++ seems to have been improved enough that the
+difference is now fairly minimal.
+
+Nicely enough, doing the change required changing only about 3 lines of code.
+
+Note that this requires you to be on a machine running some sort of Unix. Well,
+I guess any POSIX.1 compliant OS (in theory).
+*/
+
+#include <iostream>
+#include <botan/botan.h>
+
+#if !defined(BOTAN_HAS_PIPE_UNIXFD_IO)
+ #error "You didn't compile the pipe_unixfd module into Botan"
+#endif
+
+#include <fcntl.h>
+#include <unistd.h>
+
+int main(int argc, char* argv[])
+ {
+ if(argc < 3)
+ {
+ std::cout << "Usage: " << argv[0] << " digest <filenames>" << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ try
+ {
+ Botan::Pipe pipe(new Botan::Hash_Filter(argv[1]),
+ new Botan::Hex_Encoder);
+
+ int skipped = 0;
+ for(int j = 2; argv[j] != 0; j++)
+ {
+ int file = open(argv[j], O_RDONLY);
+ if(file == -1)
+ {
+ std::cout << "ERROR: could not open " << argv[j] << std::endl;
+ skipped++;
+ continue;
+ }
+ pipe.start_msg();
+ file >> pipe;
+ pipe.end_msg();
+ close(file);
+ pipe.set_default_msg(j-2-skipped);
+ std::cout << pipe << " " << argv[j] << std::endl;
+ }
+ }
+ catch(Botan::Algorithm_Not_Found)
+ {
+ std::cout << "Don't know about the hash function \"" << argv[1] << "\""
+ << std::endl;
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception caught: " << e.what() << std::endl;
+ }
+ return 0;
+ }
diff --git a/old/botan/doc/examples/hash_quickly.cpp b/old/botan/doc/examples/hash_quickly.cpp
new file mode 100644
index 0000000..e719a71
--- /dev/null
+++ b/old/botan/doc/examples/hash_quickly.cpp
@@ -0,0 +1,90 @@
+#include <botan/botan.h>
+#include <botan/benchmark.h>
+#include <botan/filters.h>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <map>
+#include <cstdlib>
+
+/*
+Try to find the fastest SHA-1 implementation and use it to hash
+files. In most programs this isn't worth the bother and
+overhead. However with large amount of input, it is worth it. On tests
+on a Core2 system with the SHA-1 SSE2 code enabled, over a few hundred
+Mb or so the overhead paid for itself.
+
+Of course you could also just do this once and save it as an
+application config, which is probably the smart thing to do.
+*/
+
+void set_fastest_implementation(const std::string& algo,
+ Botan::RandomNumberGenerator& rng,
+ double ms = 30)
+ {
+ Botan::Default_Benchmark_Timer timer;
+
+ Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory();
+
+ std::map<std::string, double> results =
+ Botan::algorithm_benchmark(algo, ms, timer, rng, af);
+
+ std::string fastest_provider = "";
+ double best_res = 0;
+
+ for(std::map<std::string, double>::iterator r = results.begin();
+ r != results.end(); ++r)
+ {
+ std::cout << r->first << " @ " << r->second << " MiB/sec\n";
+
+ if(fastest_provider == "" || r->second > best_res)
+ {
+ fastest_provider = r->first;
+ best_res = r->second;
+ }
+ }
+
+ std::cout << "Using " << fastest_provider << "\n";
+
+ af.set_preferred_provider(algo, fastest_provider);
+ }
+
+int main(int argc, char* argv[])
+ {
+ if(argc <= 1)
+ {
+ std::cout << "Usage: " << argv[0] << " <file> <file> ...\n";
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+ Botan::AutoSeeded_RNG rng;
+
+ const std::string hash = "SHA-1";
+
+ set_fastest_implementation(hash, rng);
+
+ // Here we intentionally use the 'old style' lookup interface
+ // which will also respect the provider settings. Or can use:
+ // global_state().algorithm_factory().make_hash_function(hash)
+ Botan::Pipe pipe(
+ new Botan::Hash_Filter(Botan::get_hash(hash)),
+ new Botan::Hex_Encoder
+ );
+
+ for(size_t i = 1; argv[i]; ++i)
+ {
+ std::ifstream in(argv[i]);
+ if(!in)
+ continue;
+
+ pipe.start_msg();
+ in >> pipe;
+ pipe.end_msg();
+
+ std::cout << argv[i] << " = "
+ << pipe.read_all_as_string(Botan::Pipe::LAST_MESSAGE) << "\n";
+
+ }
+ }
diff --git a/old/botan/doc/examples/hasher.cpp b/old/botan/doc/examples/hasher.cpp
new file mode 100644
index 0000000..5ba982f
--- /dev/null
+++ b/old/botan/doc/examples/hasher.cpp
@@ -0,0 +1,58 @@
+/*
+A Botan example application which emulates a
+poorly written version of "gpg --print-md"
+
+Written by Jack Lloyd (lloyd@randombit.net), quite a while ago (as of June
+2001)
+
+This file is in the public domain
+*/
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <botan/botan.h>
+
+int main(int argc, char* argv[])
+ {
+ if(argc < 2)
+ {
+ std::cout << "Usage: " << argv[0] << " <filenames>" << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ const int COUNT = 3;
+ std::string name[COUNT] = { "MD5", "SHA-1", "RIPEMD-160" };
+
+ for(int j = 1; argv[j] != 0; j++)
+ {
+ Botan::Filter* hash[COUNT] = {
+ new Botan::Chain(new Botan::Hash_Filter(name[0]),
+ new Botan::Hex_Encoder),
+ new Botan::Chain(new Botan::Hash_Filter(name[1]),
+ new Botan::Hex_Encoder),
+ new Botan::Chain(new Botan::Hash_Filter(name[2]),
+ new Botan::Hex_Encoder)
+ };
+
+ Botan::Pipe pipe(new Botan::Fork(hash, COUNT));
+
+ std::ifstream file(argv[j]);
+ if(!file)
+ {
+ std::cout << "ERROR: could not open " << argv[j] << std::endl;
+ continue;
+ }
+ pipe.start_msg();
+ file >> pipe;
+ pipe.end_msg();
+ file.close();
+ for(int k = 0; k != COUNT; k++)
+ {
+ pipe.set_default_msg(k);
+ std::cout << name[k] << "(" << argv[j] << ") = " << pipe << std::endl;
+ }
+ }
+ return 0;
+ }
diff --git a/old/botan/doc/examples/hasher2.cpp b/old/botan/doc/examples/hasher2.cpp
new file mode 100644
index 0000000..12d3c85
--- /dev/null
+++ b/old/botan/doc/examples/hasher2.cpp
@@ -0,0 +1,72 @@
+/*
+Identical to hasher.cpp, but uses Pipe in a different way.
+
+Note this tends to be much less efficient than hasher.cpp, because it does
+three passes over the file. For a small file, it doesn't really matter. But for
+a large file, or for something you can't re-read easily (socket, stdin, ...)
+this is a bad idea.
+
+Written by Jack Lloyd (lloyd@randombit.net), Feb 8 2001
+
+This file is in the public domain
+*/
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <botan/botan.h>
+
+int main(int argc, char* argv[])
+ {
+ if(argc < 2)
+ {
+ std::cout << "Usage: " << argv[0] << " <filenames>" << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ const int COUNT = 3;
+ std::string name[COUNT] = { "MD5", "SHA-1", "RIPEMD-160" };
+
+ Botan::Pipe pipe;
+
+ int skipped = 0;
+ for(int j = 1; argv[j] != 0; j++)
+ {
+ Botan::Filter* hash[COUNT] = {
+ new Botan::Hash_Filter(name[0]),
+ new Botan::Hash_Filter(name[1]),
+ new Botan::Hash_Filter(name[2]),
+ };
+
+ std::ifstream file(argv[j]);
+ if(!file)
+ {
+ std::cout << "ERROR: could not open " << argv[j] << std::endl;
+ skipped++;
+ continue;
+ }
+ for(int k = 0; k != COUNT; k++)
+ {
+ pipe.reset();
+ pipe.append(hash[k]);
+ pipe.append(new Botan::Hex_Encoder);
+ pipe.start_msg();
+
+ // trickiness: the >> op reads until EOF, but seekg won't work
+ // unless we're in the "good" state (which EOF is not).
+ file.clear();
+ file.seekg(0, std::ios::beg);
+ file >> pipe;
+ pipe.end_msg();
+ }
+ file.close();
+ for(int k = 0; k != COUNT; k++)
+ {
+ std::string out = pipe.read_all_as_string(COUNT*(j-1-skipped) + k);
+ std::cout << name[k] << "(" << argv[j] << ") = " << out << std::endl;
+ }
+ }
+
+ return 0;
+ }
diff --git a/old/botan/doc/examples/make_prime.cpp b/old/botan/doc/examples/make_prime.cpp
new file mode 100644
index 0000000..0c90b2b
--- /dev/null
+++ b/old/botan/doc/examples/make_prime.cpp
@@ -0,0 +1,73 @@
+#include <botan/numthry.h>
+#include <botan/auto_rng.h>
+#include <botan/botan.h>
+
+using namespace Botan;
+
+#include <set>
+#include <iostream>
+#include <iterator>
+#include <map>
+
+int main()
+ {
+ Botan::LibraryInitializer init;
+ AutoSeeded_RNG rng;
+
+ std::set<BigInt> primes;
+
+ std::map<int, int> bit_count;
+
+ int not_new = 0;
+
+ while(primes.size() < 10000)
+ {
+ u32bit start_cnt = primes.size();
+
+ u32bit bits = 18;
+
+ if(rng.next_byte() % 128 == 0)
+ bits -= rng.next_byte() % (bits-2);
+
+ bit_count[bits]++;
+
+ //std::cout << "random_prime(" << bits << ")\n";
+
+ BigInt p = random_prime(rng, bits);
+
+ if(p.bits() != bits)
+ {
+ std::cout << "Asked for " << bits << " got " << p
+ << " " << p.bits() << " bits\n";
+ return 1;
+ }
+
+ primes.insert(random_prime(rng, bits));
+
+ if(primes.size() != start_cnt)
+ std::cout << primes.size() << "\n";
+ else
+ not_new++;
+
+ //std::cout << "miss: " << not_new << "\n";
+
+ if(not_new % 100000 == 0)
+ {
+ for(std::map<int, int>::iterator i = bit_count.begin();
+ i != bit_count.end(); ++i)
+ std::cout << "bit_count[" << i->first << "] = "
+ << i->second << "\n";
+ std::copy(primes.begin(), primes.end(),
+ std::ostream_iterator<BigInt>(std::cout, " "));
+ }
+ }
+
+ std::cout << "Generated all? primes\n";
+ /*
+ for(u32bit j = 0; j != PRIME_TABLE_SIZE; ++j)
+ {
+ if(primes.count(PRIMES[j]) != 1)
+ std::cout << "Missing " << PRIMES[j] << "\n";
+ }
+ */
+ }
diff --git a/old/botan/doc/examples/passhash.cpp b/old/botan/doc/examples/passhash.cpp
new file mode 100644
index 0000000..7f5bbc2
--- /dev/null
+++ b/old/botan/doc/examples/passhash.cpp
@@ -0,0 +1,86 @@
+#include <botan/botan.h>
+#include <botan/pbkdf2.h>
+#include <botan/hmac.h>
+#include <botan/sha160.h>
+#include <iostream>
+#include <memory>
+
+using namespace Botan;
+
+std::string password_hash(const std::string& pass,
+ RandomNumberGenerator& rng);
+bool password_hash_ok(const std::string& pass, const std::string& hash);
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 2 && argc != 3)
+ {
+ std::cerr << "Usage: " << argv[0] << " password\n";
+ std::cerr << "Usage: " << argv[0] << " password hash\n";
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ try
+ {
+
+ if(argc == 2)
+ {
+ AutoSeeded_RNG rng;
+
+ std::cout << "H('" << argv[1] << "') = "
+ << password_hash(argv[1], rng) << '\n';
+ }
+ else
+ {
+ bool ok = password_hash_ok(argv[1], argv[2]);
+ if(ok)
+ std::cout << "Password and hash match\n";
+ else
+ std::cout << "Password and hash do not match\n";
+ }
+ }
+ catch(std::exception& e)
+ {
+ std::cerr << e.what() << '\n';
+ return 1;
+ }
+ return 0;
+ }
+
+std::string password_hash(const std::string& pass,
+ RandomNumberGenerator& rng)
+ {
+ PKCS5_PBKDF2 kdf(new HMAC(new SHA_160));
+
+ kdf.set_iterations(10000);
+ kdf.new_random_salt(rng, 6); // 48 bits
+
+ Pipe pipe(new Base64_Encoder);
+ pipe.start_msg();
+ pipe.write(kdf.current_salt());
+ pipe.write(kdf.derive_key(12, pass).bits_of());
+ pipe.end_msg();
+
+ return pipe.read_all_as_string();
+ }
+
+bool password_hash_ok(const std::string& pass, const std::string& hash)
+ {
+ Pipe pipe(new Base64_Decoder);
+ pipe.start_msg();
+ pipe.write(hash);
+ pipe.end_msg();
+
+ SecureVector<byte> hash_bin = pipe.read_all();
+
+ PKCS5_PBKDF2 kdf(new HMAC(new SHA_160));
+
+ kdf.set_iterations(10000);
+ kdf.change_salt(hash_bin, 6);
+
+ SecureVector<byte> cmp = kdf.derive_key(12, pass).bits_of();
+
+ return same_mem(cmp.begin(), hash_bin.begin() + 6, 12);
+ }
diff --git a/old/botan/doc/examples/pkcs10.cpp b/old/botan/doc/examples/pkcs10.cpp
new file mode 100644
index 0000000..d719baf
--- /dev/null
+++ b/old/botan/doc/examples/pkcs10.cpp
@@ -0,0 +1,73 @@
+/*
+Generate a 1024 bit RSA key, and then create a PKCS #10 certificate request for
+that key. The private key will be stored as an encrypted PKCS #8 object, and
+stored in another file.
+
+Written by Jack Lloyd (lloyd@randombit.net), April 7, 2003
+
+This file is in the public domain
+*/
+#include <botan/init.h>
+#include <botan/auto_rng.h>
+#include <botan/x509self.h>
+#include <botan/rsa.h>
+#include <botan/dsa.h>
+using namespace Botan;
+
+#include <iostream>
+#include <fstream>
+#include <memory>
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 6)
+ {
+ std::cout << "Usage: " << argv[0] <<
+ " passphrase name country_code organization email" << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ try
+ {
+ AutoSeeded_RNG rng;
+
+ RSA_PrivateKey priv_key(rng, 1024);
+ // If you want a DSA key instead of RSA, comment out the above line and
+ // uncomment this one:
+ //DSA_PrivateKey priv_key(DL_Group("dsa/jce/1024"));
+
+ std::ofstream key_file("private.pem");
+ key_file << PKCS8::PEM_encode(priv_key, rng, argv[1]);
+
+ X509_Cert_Options opts;
+
+ opts.common_name = argv[2];
+ opts.country = argv[3];
+ opts.organization = argv[4];
+ opts.email = argv[5];
+
+ /* Some hard-coded options, just to give you an idea of what's there */
+ opts.challenge = "a fixed challenge passphrase";
+ opts.locality = "Baltimore";
+ opts.state = "MD";
+ opts.org_unit = "Testing";
+ opts.add_ex_constraint("PKIX.ClientAuth");
+ opts.add_ex_constraint("PKIX.IPsecUser");
+ opts.add_ex_constraint("PKIX.EmailProtection");
+
+ opts.xmpp = "someid@xmpp.org";
+
+ PKCS10_Request req = X509::create_cert_req(opts, priv_key, rng);
+
+ std::ofstream req_file("req.pem");
+ req_file << req.PEM_encode();
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
diff --git a/old/botan/doc/examples/pqg_gen.cpp b/old/botan/doc/examples/pqg_gen.cpp
new file mode 100644
index 0000000..e4b9598
--- /dev/null
+++ b/old/botan/doc/examples/pqg_gen.cpp
@@ -0,0 +1,116 @@
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+#include <map>
+#include <memory>
+
+#include <botan/botan.h>
+#include <botan/auto_rng.h>
+#include <botan/look_pk.h>
+#include <botan/dsa.h>
+#include <botan/numthry.h>
+#include <botan/dl_group.h>
+using namespace Botan;
+
+bool check(RandomNumberGenerator& rng,
+ std::map<std::string, std::string>);
+
+int main()
+ {
+ try {
+ Botan::LibraryInitializer init("use_engines");
+
+ AutoSeeded_RNG rng;
+
+ std::ifstream in("PQGGen.rsp");
+ if(!in)
+ throw Exception("Can't open response file");
+
+ std::map<std::string, std::string> inputs;
+
+ while(in.good())
+ {
+ std::string line;
+ std::getline(in, line);
+
+ if(line == "" || line[0] == '[' || line[0] == '#')
+ continue;
+
+ std::vector<std::string> name_and_val = split_on(line, '=');
+
+ if(name_and_val.size() != 2)
+ throw Decoding_Error("Unexpected input: " + line);
+
+ name_and_val[0].erase(name_and_val[0].size()-1);
+ name_and_val[1].erase(0, 1);
+
+ std::string name = name_and_val[0], value = name_and_val[1];
+
+ inputs[name] = value;
+
+ if(name == "H")
+ {
+ bool result = check(rng, inputs);
+ std::cout << "." << std::flush;
+ if(result == false)
+ {
+ std::cout << " Check failed\n";
+
+ std::map<std::string, std::string>::const_iterator i;
+
+ for(i = inputs.begin(); i != inputs.end(); i++)
+ std::cout << i->first << " = " << i->second << "\n";
+
+ std::cout << "\n";
+ }
+
+ inputs.clear();
+ }
+ }
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
+
+bool check(RandomNumberGenerator& rng,
+ std::map<std::string, std::string> inputs)
+ {
+ BigInt p("0x"+inputs["P"]),
+ q("0x"+inputs["Q"]),
+ g("0x"+inputs["G"]),
+ h("0x"+inputs["H"]);
+
+ if(h < 1 || h >= p-1) return false;
+
+ //u32bit c = to_u32bit(inputs["c"]);
+
+ Pipe pipe(new Hex_Decoder);
+ pipe.process_msg(inputs["Seed"]);
+ SecureVector<byte> seed = pipe.read_all();
+
+ BigInt our_p, our_q;
+
+ u32bit qbits = (p.bits() <= 1024) ? 160 : 256;
+
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ bool found = generate_dsa_primes(rng, af, our_p, our_q,
+ p.bits(), qbits, seed);
+
+ if(!found) /* bad seed */
+ return false;
+
+ if(our_p != p) return false;
+ if(our_q != q) return false;
+
+ BigInt our_g = power_mod(h, (p-1)/q, p);
+
+ if(our_g != g) return false;
+
+ return true;
+ }
diff --git a/old/botan/doc/examples/readme.txt b/old/botan/doc/examples/readme.txt
new file mode 100644
index 0000000..48686db
--- /dev/null
+++ b/old/botan/doc/examples/readme.txt
@@ -0,0 +1,77 @@
+This directory contains some simple example applications for the Botan crypto
+library. If you want to see something a bit more complicated, check out the
+stuff in the checks/ directory. Both it and the files in this directory are in
+the public domain, and you may do with them however you please.
+
+The makefile assumes that you built the library with g++; you'll have to change
+it if this assumption proves incorrect.
+
+Some of these examples will not build on all configurations of the library,
+particularly 'bzip', 'encrypt', 'decrypt', and 'hash_fd', as they require
+various extensions.
+
+The examples are fairly small (50-150 lines). And that's with argument
+processing, I/O, error checking, etc (which counts for 40% or more of most of
+them). This is partially to make them easy to understand, and partially because
+I'm lazy. For the most part, the examples cover the stuff a 'regular'
+application might need.
+
+Feel free to contribute new examples. You too can gain fame and fortune by
+writing example apps for obscure libraries!
+
+The examples are:
+
+* X.509 examples
+--------
+ca: A (very) simple CA application
+
+x509info: Prints some information about an X.509 certificate
+
+pkcs10: Generates a PKCS #10 certificate request for a 1024 bit RSA key
+
+self_sig: Generates a self-signed X.509v3 certificate with a 1024 bit RSA key
+--------
+
+* RSA examples (also uses X.509, PKCS #8, block ciphers, MACs, S2K algorithms)
+--------
+rsa_kgen: Generate an RSA key, encrypt the private key with a passphrase,
+ output the keys to a pair of files
+rsa_enc: Take a public key (generated by rsa_kgen) and encrypt a file
+ using CAST-128, MAC it with HMAC(SHA-1)
+rsa_dec: Decrypt a file encrypted by rsa_enc
+
+* DSA examples (also uses X.509, PKCS #8)
+--------
+dsa_kgen: Generates a DSA key, encrypts the private key with a passphrase
+ and stores it in PKCS #8 format.
+dsa_sign: Produce a DSA signature for a file. Uses SHA-1
+dsa_ver: Verify a message signed with dsa_sign
+
+* Encryption examples
+--------
+encrypt: Encrypt a file in CBC mode with a block cipher of your choice. Adds
+ a MAC for authentication, and compresses the plaintext with Zlib.
+
+decrypt: Decrypt the result of 'encrypt'
+
+xor_ciph: Shows how to add a new algorithm from application code
+
+* Hash function examples (also shows different methods of using Pipe)
+--------
+hash: Print digests of files, using any chosen hash function
+
+hash_fd: Same as hash, except that it uses Unix file I/O. Requires the
+ pipe_unixfd extension
+
+hasher: Print MD5, SHA-1, and RIPEMD-160 digests of files
+
+hasher2: Same as hasher, just shows an alternate method
+
+stack: A demonstration of some more advanced Pipe functionality. Prints
+ MD5 hashes
+
+* Misc examples
+--------
+base64: Simple base64 encoding/decoding tool
+
+bzip: Bzip2 compression/decompression.
diff --git a/old/botan/doc/examples/ressol.cpp b/old/botan/doc/examples/ressol.cpp
new file mode 100644
index 0000000..43bb68d
--- /dev/null
+++ b/old/botan/doc/examples/ressol.cpp
@@ -0,0 +1,80 @@
+#include <botan/numthry.h>
+#include <botan/auto_rng.h>
+#include <botan/botan.h>
+
+using namespace Botan;
+
+#include <iostream>
+
+void test_ressol(const BigInt& p, RandomNumberGenerator& rng)
+ {
+ std::cout << p << std::endl;
+
+ // const BigInt p_16 = p / 16;
+
+ int noroot = 0, false_result = 0;
+
+ for(int j = 0; j != 1000; ++j)
+ {
+ BigInt x = BigInt::random_integer(rng, 0, p);
+ //if(x % p_16 == 0)
+ //std::cout << "p = " << p << " x = " << x << "\n";
+
+ BigInt sqrt_x = ressol(x, p);
+
+ if(sqrt_x < 0)
+ {
+ ++noroot;
+ continue;
+ }
+
+ BigInt check = square(sqrt_x) % p;
+
+ if(check != x % p)
+ {
+ std::cout << "FAIL "
+ << "x = " << x << "; "
+ << "p = " << p << "; "
+ << "s = " << sqrt_x << "; "
+ << "s^2%p = " << check << "\n";
+ ++false_result;
+ }
+ }
+ /*
+ std::cout << "nomatch=" << nomatch << " "
+ << "noroot=" << noroot << " "
+ << "false=" << false_result << "\n";
+ */
+ }
+
+int main()
+ {
+ Botan::LibraryInitializer init;
+ AutoSeeded_RNG rng;
+
+#if 0
+ std::cout << ressol(8, 17) << "\n";
+ std::cout << ressol_orig(8, 17) << "\n";
+#endif
+
+#if 1
+ for(int j = 16; j != 1024; ++j)
+ {
+ std::cout << "Round " << j << "\n";
+ BigInt p = random_prime(rng, j);
+ test_ressol(p, rng);
+ //printf("%d\n", j);
+
+
+ }
+#endif
+ /*
+ for(u32bit j = 9; j != PRIME_TABLE_SIZE; ++j)
+ {
+ std::cout << "PRIME[" << j << "] == " << PRIMES[j] << std::endl;
+ //printf("%d - ", PRIMES[j]);
+ test_ressol(PRIMES[j], rng);
+ //printf("\n");
+ }
+ */
+ }
diff --git a/old/botan/doc/examples/rng_test.cpp b/old/botan/doc/examples/rng_test.cpp
new file mode 100644
index 0000000..8d4253a
--- /dev/null
+++ b/old/botan/doc/examples/rng_test.cpp
@@ -0,0 +1,143 @@
+#include <botan/botan.h>
+#include <botan/x931_rng.h>
+#include <botan/filters.h>
+#include <botan/lookup.h>
+
+#include <iostream>
+#include <fstream>
+#include <boost/algorithm/string.hpp>
+#include <stdexcept>
+
+using namespace Botan;
+
+std::vector<std::pair<std::string, std::string> > read_file(const std::string&);
+
+SecureVector<byte> decode_hex(const std::string& in)
+ {
+ SecureVector<byte> result;
+
+ try {
+ Botan::Pipe pipe(new Botan::Hex_Decoder);
+ pipe.process_msg(in);
+ result = pipe.read_all();
+ }
+ catch(std::exception& e)
+ {
+ result.destroy();
+ }
+ return result;
+ }
+
+std::string hex_encode(const byte in[], u32bit len)
+ {
+ Botan::Pipe pipe(new Botan::Hex_Encoder);
+ pipe.process_msg(in, len);
+ return pipe.read_all_as_string();
+ }
+
+class Fixed_Output_RNG : public RandomNumberGenerator
+ {
+ public:
+ bool is_seeded() const { return !buf.empty(); }
+
+ byte random()
+ {
+ if(buf.empty())
+ throw std::runtime_error("Out of bytes");
+
+ byte out = buf.front();
+ buf.pop_front();
+ return out;
+ }
+
+ void randomize(byte out[], u32bit len) throw()
+ {
+ for(u32bit j = 0; j != len; j++)
+ out[j] = random();
+ }
+
+ std::string name() const { return "Fixed_Output_RNG"; }
+
+ void reseed(u32bit) {}
+
+ void clear() throw() {}
+
+ void add_entropy(const byte in[], u32bit len)
+ {
+ buf.insert(buf.end(), in, in + len);
+ }
+
+ void add_entropy_source(EntropySource* es) { delete es; }
+
+ Fixed_Output_RNG() {}
+ private:
+ std::deque<byte> buf;
+ };
+
+void x931_tests(std::vector<std::pair<std::string, std::string> > vecs,
+ const std::string& cipher)
+ {
+ for(size_t j = 0; j != vecs.size(); ++j)
+ {
+ const std::string result = vecs[j].first;
+ const std::string input = vecs[j].second;
+
+ ANSI_X931_RNG prng(get_block_cipher(cipher),
+ new Fixed_Output_RNG);
+
+ SecureVector<byte> x = decode_hex(input);
+ prng.add_entropy(x.begin(), x.size());
+
+ SecureVector<byte> output(result.size() / 2);
+ prng.randomize(output, output.size());
+
+ if(decode_hex(result) != output)
+ std::cout << "FAIL";
+ else
+ std::cout << "PASS";
+
+ std::cout << " Seed " << input << " "
+ << "Got " << hex_encode(output, output.size()) << " "
+ << "Exp " << result << "\n";
+ }
+
+ }
+
+int main()
+ {
+ Botan::LibraryInitializer init;
+
+ x931_tests(read_file("ANSI931_AES128VST.txt.vst"), "AES-128");
+ x931_tests(read_file("ANSI931_AES192VST.txt.vst"), "AES-192");
+ x931_tests(read_file("ANSI931_AES256VST.txt.vst"), "AES-256");
+ x931_tests(read_file("ANSI931_TDES2VST.txt.vst"), "TripleDES");
+ x931_tests(read_file("ANSI931_TDES3VST.txt.vst"), "TripleDES");
+ }
+
+
+std::vector<std::pair<std::string, std::string> >
+read_file(const std::string& fsname)
+ {
+ std::ifstream in(fsname.c_str());
+
+ std::vector<std::pair<std::string, std::string> > out;
+
+ while(in.good())
+ {
+ std::string line;
+ std::getline(in, line);
+
+ if(line == "")
+ break;
+
+ std::vector<std::string> l;
+ boost::split(l, line, boost::is_any_of(":"));
+
+ if(l.size() != 2)
+ throw std::runtime_error("Bad line " + line);
+
+ out.push_back(std::make_pair(l[0], l[1]));
+ }
+
+ return out;
+ }
diff --git a/old/botan/doc/examples/row_encryptor.cpp b/old/botan/doc/examples/row_encryptor.cpp
new file mode 100644
index 0000000..1dac82f
--- /dev/null
+++ b/old/botan/doc/examples/row_encryptor.cpp
@@ -0,0 +1,143 @@
+#include <string>
+#include <memory>
+#include <sstream>
+#include <iostream>
+#include <stdexcept>
+
+#include <botan/botan.h>
+#include <botan/filters.h>
+#include <botan/eax.h>
+
+using namespace Botan;
+
+/**
+Encrypt and decrypt small rows
+*/
+class Row_Encryptor
+ {
+ public:
+ Row_Encryptor(const std::string& passphrase,
+ RandomNumberGenerator& rng);
+
+ std::string encrypt(const std::string& input,
+ const MemoryRegion<byte>& salt);
+
+ std::string decrypt(const std::string& input,
+ const MemoryRegion<byte>& salt);
+
+ private:
+ Row_Encryptor(const Row_Encryptor&) {}
+ Row_Encryptor& operator=(const Row_Encryptor&) { return (*this); }
+
+ Pipe enc_pipe, dec_pipe;
+ EAX_Encryption* eax_enc; // owned by enc_pipe
+ EAX_Decryption* eax_dec; // owned by dec_pipe;
+ };
+
+Row_Encryptor::Row_Encryptor(const std::string& passphrase,
+ RandomNumberGenerator& rng)
+ {
+ std::auto_ptr<S2K> s2k(get_s2k("PBKDF2(SHA-160)"));
+
+ s2k->set_iterations(10000);
+
+ s2k->new_random_salt(rng, 10); // 10 bytes == 80 bits
+
+ SecureVector<byte> key = s2k->derive_key(32, passphrase).bits_of();
+
+ /*
+ Save pointers to the EAX objects so we can change the IV as needed
+ */
+
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ const BlockCipher* proto = af.prototype_block_cipher("Serpent");
+
+ if(!proto)
+ throw std::runtime_error("Could not get a Serpent proto object");
+
+ enc_pipe.append(eax_enc = new EAX_Encryption(proto->clone()));
+ dec_pipe.append(eax_dec = new EAX_Decryption(proto->clone()));
+
+ eax_enc->set_key(key);
+ eax_dec->set_key(key);
+ }
+
+std::string Row_Encryptor::encrypt(const std::string& input,
+ const MemoryRegion<byte>& salt)
+ {
+ eax_enc->set_iv(salt);
+
+ enc_pipe.start_msg();
+ enc_pipe.write(input);
+ enc_pipe.end_msg();
+
+ return enc_pipe.read_all_as_string(Pipe::LAST_MESSAGE);
+ }
+
+std::string Row_Encryptor::decrypt(const std::string& input,
+ const MemoryRegion<byte>& salt)
+ {
+ eax_dec->set_iv(salt);
+
+ dec_pipe.start_msg();
+ dec_pipe.write(input);
+ dec_pipe.end_msg();
+
+ return dec_pipe.read_all_as_string(Pipe::LAST_MESSAGE);
+ }
+
+/*************************
+ Test code follows:
+*/
+
+#include <botan/loadstor.h>
+
+int main()
+ {
+ Botan::LibraryInitializer init;
+
+ AutoSeeded_RNG rng;
+
+ Row_Encryptor encryptor("secret passphrase", rng);
+
+ std::vector<std::string> original_inputs;
+
+ for(u32bit i = 0; i != 15000; ++i)
+ {
+ std::ostringstream out;
+
+ // This will actually generate variable length inputs (when
+ // there are leading 0s, which are skipped), which is good
+ // since it assures performance is OK across a mix of lengths
+ // TODO: Maybe randomize the length slightly?
+
+ for(u32bit j = 0; j != 32; ++j)
+ out << std::hex << (int)rng.next_byte();
+
+ original_inputs.push_back(out.str());
+ }
+
+ std::vector<std::string> encrypted_values;
+ MemoryVector<byte> salt(4); // keep out of loop to avoid excessive dynamic allocation
+
+ for(u32bit i = 0; i != original_inputs.size(); ++i)
+ {
+ std::string input = original_inputs[i];
+ store_le(i, salt);
+
+ encrypted_values.push_back(encryptor.encrypt(input, salt));
+ }
+
+ for(u32bit i = 0; i != encrypted_values.size(); ++i)
+ {
+ std::string ciphertext = encrypted_values[i];
+ store_le(i, salt); // NOTE: same salt value as previous loop (index value)
+
+ std::string output = encryptor.decrypt(ciphertext, salt);
+
+ if(output != original_inputs[i])
+ std::cout << "BOOM " << i << "\n";
+ }
+
+ }
diff --git a/old/botan/doc/examples/rsa_dec.cpp b/old/botan/doc/examples/rsa_dec.cpp
new file mode 100644
index 0000000..25ce33f
--- /dev/null
+++ b/old/botan/doc/examples/rsa_dec.cpp
@@ -0,0 +1,127 @@
+/*
+Decrypt an encrypted RSA private key. Then use that key to decrypt a
+message. This program can decrypt messages generated by rsa_enc, and uses the
+same key format as that generated by rsa_kgen.
+
+Written by Jack Lloyd (lloyd@randombit.net), June 3-5, 2002
+
+This file is in the public domain
+*/
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <memory>
+
+#include <botan/botan.h>
+#include <botan/look_pk.h> // for get_kdf
+#include <botan/rsa.h>
+using namespace Botan;
+
+SecureVector<byte> b64_decode(const std::string&);
+SymmetricKey derive_key(const std::string&, const SymmetricKey&, u32bit);
+
+const std::string SUFFIX = ".enc";
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 4)
+ {
+ std::cout << "Usage: " << argv[0] << " keyfile messagefile passphrase"
+ << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ try
+ {
+ AutoSeeded_RNG rng;
+
+ std::auto_ptr<PKCS8_PrivateKey> key(
+ PKCS8::load_key(argv[1], rng, argv[3]));
+
+ RSA_PrivateKey* rsakey = dynamic_cast<RSA_PrivateKey*>(key.get());
+ if(!rsakey)
+ {
+ std::cout << "The loaded key is not a RSA key!\n";
+ return 1;
+ }
+
+ std::ifstream message(argv[2]);
+ if(!message)
+ {
+ std::cout << "Couldn't read the message file." << std::endl;
+ return 1;
+ }
+
+ std::string outfile(argv[2]);
+ outfile = outfile.replace(outfile.find(SUFFIX), SUFFIX.length(), "");
+
+ std::ofstream plaintext(outfile.c_str());
+ if(!plaintext)
+ {
+ std::cout << "Couldn't write the plaintext to "
+ << outfile << std::endl;
+ return 1;
+ }
+
+ std::string enc_masterkey_str;
+ std::getline(message, enc_masterkey_str);
+ std::string mac_str;
+ std::getline(message, mac_str);
+
+ SecureVector<byte> enc_masterkey = b64_decode(enc_masterkey_str);
+
+ std::auto_ptr<PK_Decryptor> decryptor(get_pk_decryptor(*rsakey,
+ "EME1(SHA-1)"));
+ SecureVector<byte> masterkey = decryptor->decrypt(enc_masterkey);
+
+ SymmetricKey cast_key = derive_key("CAST", masterkey, 16);
+ InitializationVector iv = derive_key("IV", masterkey, 8);
+ SymmetricKey mac_key = derive_key("MAC", masterkey, 16);
+
+ Pipe pipe(new Base64_Decoder,
+ get_cipher("CAST-128/CBC/PKCS7", cast_key, iv, DECRYPTION),
+ new Fork(
+ 0,
+ new Chain(
+ new MAC_Filter("HMAC(SHA-1)", mac_key, 12),
+ new Base64_Encoder
+ )
+ )
+ );
+
+ pipe.start_msg();
+ message >> pipe;
+ pipe.end_msg();
+
+ std::string our_mac = pipe.read_all_as_string(1);
+
+ if(our_mac != mac_str)
+ std::cout << "WARNING: MAC in message failed to verify\n";
+
+ plaintext << pipe.read_all_as_string(0);
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception caught: " << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
+
+SecureVector<byte> b64_decode(const std::string& in)
+ {
+ Pipe pipe(new Base64_Decoder);
+ pipe.process_msg(in);
+ return pipe.read_all();
+ }
+
+SymmetricKey derive_key(const std::string& param,
+ const SymmetricKey& masterkey,
+ u32bit outputlength)
+ {
+ std::auto_ptr<KDF> kdf(get_kdf("KDF2(SHA-1)"));
+ return kdf->derive_key(outputlength, masterkey.bits_of(), param);
+ }
diff --git a/old/botan/doc/examples/rsa_enc.cpp b/old/botan/doc/examples/rsa_enc.cpp
new file mode 100644
index 0000000..f9b8c55
--- /dev/null
+++ b/old/botan/doc/examples/rsa_enc.cpp
@@ -0,0 +1,151 @@
+/*
+ Grab an RSA public key from the file given as an argument, grab a message
+ from another file, and encrypt the message.
+
+ Algorithms used:
+ RSA with EME1(SHA-1) padding to encrypt the master key
+ CAST-128 in CBC mode with PKCS#7 padding to encrypt the message.
+ HMAC with SHA-1 is used to authenticate the message
+
+ The keys+IV used are derived from the master key (the thing that's encrypted
+ with RSA) using KDF2(SHA-1). The 3 outputs of KDF2 are parameterized by P,
+ where P is "CAST", "IV" or "MAC", in order to make each key/IV unique.
+
+ The format is:
+ 1) First line is the master key, encrypted with the recipients public key
+ using EME1(SHA-1), and then base64 encoded.
+ 2) Second line is the first 96 bits (12 bytes) of the HMAC(SHA-1) of
+ the _plaintext_
+ 3) Following lines are base64 encoded ciphertext (CAST-128 as described),
+ each broken after ~72 characters.
+
+Written by Jack Lloyd (lloyd@randombit.net), June 3, 2002
+ Updated to use KDF2, September 8, 2002
+ Updated to read X.509 keys, October 21, 2002
+
+This file is in the public domain
+*/
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <memory>
+
+#include <botan/botan.h>
+#include <botan/look_pk.h>
+#include <botan/rsa.h>
+using namespace Botan;
+
+std::string b64_encode(const SecureVector<byte>&);
+SymmetricKey derive_key(const std::string&, const SymmetricKey&, u32bit);
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 3)
+ {
+ std::cout << "Usage: " << argv[0] << " keyfile messagefile" << std::endl;
+ return 1;
+ }
+
+ std::ifstream message(argv[2]);
+ if(!message)
+ {
+ std::cout << "Couldn't read the message file." << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ std::string output_name(argv[2]);
+ output_name += ".enc";
+ std::ofstream ciphertext(output_name.c_str());
+ if(!ciphertext)
+ {
+ std::cout << "Couldn't write the ciphertext to " << output_name
+ << std::endl;
+ return 1;
+ }
+
+ try {
+ std::auto_ptr<X509_PublicKey> key(X509::load_key(argv[1]));
+ RSA_PublicKey* rsakey = dynamic_cast<RSA_PublicKey*>(key.get());
+ if(!rsakey)
+ {
+ std::cout << "The loaded key is not a RSA key!\n";
+ return 1;
+ }
+
+ AutoSeeded_RNG rng;
+
+ std::auto_ptr<PK_Encryptor> encryptor(get_pk_encryptor(*rsakey,
+ "EME1(SHA-1)"));
+
+ /* Generate the master key (the other keys are derived from this)
+
+ Basically, make the key as large as can be encrypted by this key, up
+ to a limit of 256 bits. For 512 bit keys, the master key will be >160
+ bits. A >600 bit key will use the full 256 bit master key.
+
+ In theory, this is not enough, because we derive 16+16+8=40 bytes of
+ secrets (if you include the IV) using the master key, so they are not
+ statistically indepedent. Practically speaking I don't think this is
+ a problem.
+ */
+ SymmetricKey masterkey(rng,
+ std::min(32U, encryptor->maximum_input_size()));
+
+ SymmetricKey cast_key = derive_key("CAST", masterkey, 16);
+ SymmetricKey mac_key = derive_key("MAC", masterkey, 16);
+ SymmetricKey iv = derive_key("IV", masterkey, 8);
+
+ SecureVector<byte> encrypted_key =
+ encryptor->encrypt(masterkey.bits_of(), rng);
+
+ ciphertext << b64_encode(encrypted_key) << std::endl;
+
+ Pipe pipe(new Fork(
+ new Chain(
+ get_cipher("CAST-128/CBC/PKCS7", cast_key, iv,
+ ENCRYPTION),
+ new Base64_Encoder(true) // true == do linebreaking
+ ),
+ new Chain(
+ new MAC_Filter("HMAC(SHA-1)", mac_key, 12),
+ new Base64_Encoder
+ )
+ )
+ );
+
+ pipe.start_msg();
+ message >> pipe;
+ pipe.end_msg();
+
+ /* Write the MAC as the second line. That way we can pull it off right
+ from the start, and feed the rest of the file right into a pipe on the
+ decrypting end.
+ */
+
+ ciphertext << pipe.read_all_as_string(1) << std::endl;
+ ciphertext << pipe.read_all_as_string(0);
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception: " << e.what() << std::endl;
+ }
+ return 0;
+ }
+
+std::string b64_encode(const SecureVector<byte>& in)
+ {
+ Pipe pipe(new Base64_Encoder);
+ pipe.process_msg(in);
+ return pipe.read_all_as_string();
+ }
+
+SymmetricKey derive_key(const std::string& param,
+ const SymmetricKey& masterkey,
+ u32bit outputlength)
+ {
+ std::auto_ptr<KDF> kdf(get_kdf("KDF2(SHA-1)"));
+ return kdf->derive_key(outputlength, masterkey.bits_of(), param);
+ }
diff --git a/old/botan/doc/examples/rsa_kgen.cpp b/old/botan/doc/examples/rsa_kgen.cpp
new file mode 100644
index 0000000..b7e90ef
--- /dev/null
+++ b/old/botan/doc/examples/rsa_kgen.cpp
@@ -0,0 +1,65 @@
+/*
+Generate an RSA key of a specified bitlength, and put it into a pair of key
+files. One is the public key in X.509 format (PEM encoded), the private key is
+in PKCS #8 format (also PEM encoded).
+
+Written by Jack Lloyd (lloyd@randombit.net), June 2-3, 2002
+ Updated to use X.509 and PKCS #8 on October 21, 2002
+
+This file is in the public domain
+*/
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cstdlib>
+#include <memory>
+
+#include <botan/botan.h>
+#include <botan/rsa.h>
+using namespace Botan;
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 2 && argc != 3)
+ {
+ std::cout << "Usage: " << argv[0] << " bitsize [passphrase]"
+ << std::endl;
+ return 1;
+ }
+
+ u32bit bits = std::atoi(argv[1]);
+ if(bits < 1024 || bits > 4096)
+ {
+ std::cout << "Invalid argument for bitsize" << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ std::ofstream pub("rsapub.pem");
+ std::ofstream priv("rsapriv.pem");
+ if(!priv || !pub)
+ {
+ std::cout << "Couldn't write output files" << std::endl;
+ return 1;
+ }
+
+ try
+ {
+ AutoSeeded_RNG rng;
+
+ RSA_PrivateKey key(rng, bits);
+ pub << X509::PEM_encode(key);
+
+ if(argc == 2)
+ priv << PKCS8::PEM_encode(key);
+ else
+ priv << PKCS8::PEM_encode(key, rng, argv[2]);
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception caught: " << e.what() << std::endl;
+ }
+ return 0;
+ }
diff --git a/old/botan/doc/examples/rsa_manykey.cpp b/old/botan/doc/examples/rsa_manykey.cpp
new file mode 100644
index 0000000..4122bc8
--- /dev/null
+++ b/old/botan/doc/examples/rsa_manykey.cpp
@@ -0,0 +1,36 @@
+/*
+Generate a whole sequence of keys (for benchmarking)
+*/
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cstdlib>
+#include <memory>
+
+#include <botan/botan.h>
+#include <botan/rsa.h>
+#include <botan/parsing.h>
+using namespace Botan;
+
+int main()
+ {
+ Botan::LibraryInitializer init;
+
+ AutoSeeded_RNG rng;
+
+ for(u32bit j = 512; j <= 8192; j += 256)
+ {
+ std::cout << j << "...";
+
+ RSA_PrivateKey key(rng, j);
+
+ std::ofstream priv(("rsa/" + to_string(j) + ".pem").c_str());
+ priv << PKCS8::PEM_encode(key);
+ priv.close();
+
+ std::cout << " done" << std::endl;
+ }
+
+ return 0;
+ }
diff --git a/old/botan/doc/examples/self_sig.cpp b/old/botan/doc/examples/self_sig.cpp
new file mode 100644
index 0000000..0bf17e3
--- /dev/null
+++ b/old/botan/doc/examples/self_sig.cpp
@@ -0,0 +1,79 @@
+/*
+Generate a 1024 bit RSA key, and then create a self-signed X.509v3 certificate
+with that key. If the do_CA variable is set to true, then it will be marked for
+CA use, otherwise it will get extensions appropriate for use with a client
+certificate. The private key is stored as an encrypted PKCS #8 object in
+another file.
+
+Written by Jack Lloyd (lloyd@randombit.net), April 7, 2003
+
+This file is in the public domain
+*/
+#include <botan/botan.h>
+#include <botan/x509self.h>
+#include <botan/rsa.h>
+#include <botan/dsa.h>
+using namespace Botan;
+
+#include <iostream>
+#include <fstream>
+#include <memory>
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 7)
+ {
+ std::cout << "Usage: " << argv[0]
+ << " passphrase [CA|user] name country_code organization email"
+ << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ std::string CA_flag = argv[2];
+ bool do_CA = false;
+
+ if(CA_flag == "CA") do_CA = true;
+ else if(CA_flag == "user") do_CA = false;
+ else
+ {
+ std::cout << "Bad flag for CA/user switch: " << CA_flag << std::endl;
+ return 1;
+ }
+
+ try
+ {
+ AutoSeeded_RNG rng;
+
+ RSA_PrivateKey key(rng, 1024);
+
+ std::ofstream priv_key("private.pem");
+ priv_key << PKCS8::PEM_encode(key, rng, argv[1]);
+
+ X509_Cert_Options opts;
+
+ opts.common_name = argv[3];
+ opts.country = argv[4];
+ opts.organization = argv[5];
+ opts.email = argv[6];
+ /* Fill in other values of opts here */
+
+ //opts.xmpp = "lloyd@randombit.net";
+
+ if(do_CA)
+ opts.CA_key();
+
+ X509_Certificate cert = X509::create_self_signed_cert(opts, key, rng);
+
+ std::ofstream cert_file("cert.pem");
+ cert_file << cert.PEM_encode();
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception: " << e.what() << std::endl;
+ return 1;
+ }
+
+ return 0;
+ }
diff --git a/old/botan/doc/examples/sig_gen.cpp b/old/botan/doc/examples/sig_gen.cpp
new file mode 100644
index 0000000..6dd7490
--- /dev/null
+++ b/old/botan/doc/examples/sig_gen.cpp
@@ -0,0 +1,90 @@
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+#include <map>
+#include <memory>
+
+#include <botan/botan.h>
+#include <botan/look_pk.h>
+#include <botan/dsa.h>
+using namespace Botan;
+
+bool check(std::map<std::string, std::string>);
+
+int main()
+ {
+ try {
+ Botan::LibraryInitializer init;
+
+ std::ifstream in("SigGen.rsp");
+ if(!in)
+ throw Exception("Can't open response file");
+
+ std::map<std::string, std::string> inputs;
+
+ while(in.good())
+ {
+ std::string line;
+ std::getline(in, line);
+
+ if(line == "" || line[0] == '[' || line[0] == '#')
+ continue;
+
+ std::vector<std::string> name_and_val = split_on(line, '=');
+
+ if(name_and_val.size() != 2)
+ throw Decoding_Error("Unexpected input: " + line);
+
+ name_and_val[0].erase(name_and_val[0].size()-1);
+ name_and_val[1].erase(0, 1);
+
+ std::string name = name_and_val[0], value = name_and_val[1];
+
+ inputs[name] = value;
+
+ if(name == "S")
+ {
+ bool result = check(inputs);
+ if(result == false)
+ {
+ std::cout << " Check failed\n";
+
+ std::map<std::string, std::string>::const_iterator i;
+
+ for(i = inputs.begin(); i != inputs.end(); i++)
+ std::cout << i->first << " = " << i->second << "\n";
+ }
+ inputs["Msg"] = inputs["R"] = inputs["S"] = "";
+ }
+ }
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
+
+bool check(std::map<std::string, std::string> inputs)
+ {
+ BigInt p("0x"+inputs["P"]),
+ q("0x"+inputs["Q"]),
+ g("0x"+inputs["G"]),
+ y("0x"+inputs["Y"]);
+
+ DSA_PublicKey key(DL_Group(p, q, g), y);
+
+ Pipe pipe(new Hex_Decoder);
+
+ pipe.process_msg(inputs["Msg"]);
+ pipe.start_msg();
+ pipe.write(inputs["R"]);
+ pipe.write(inputs["S"] );
+ pipe.end_msg();
+
+ std::auto_ptr<PK_Verifier> verify(get_pk_verifier(key, "EMSA1(SHA-1)"));
+
+ return verify->verify_message(pipe.read_all(0), pipe.read_all(1));
+ }
diff --git a/old/botan/doc/examples/stack.cpp b/old/botan/doc/examples/stack.cpp
new file mode 100644
index 0000000..1522b05
--- /dev/null
+++ b/old/botan/doc/examples/stack.cpp
@@ -0,0 +1,86 @@
+/*
+An Botan example application showing how to use the pop and prepend functions
+of Pipe. Based on the md5 example. It's output should always be identical to
+such.
+
+Written by Jack Lloyd (lloyd@randombit.net), Feb 3, 2002
+
+This file is in the public domain
+*/
+
+#include <iostream>
+#include <fstream>
+#include <botan/botan.h>
+
+int main(int argc, char* argv[])
+ {
+ if(argc < 2)
+ {
+ std::cout << "Usage: " << argv[0] << " <filenames>" << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ // this is a pretty vacuous example, but it's useful as a test
+ Botan::Pipe pipe;
+
+ // CPS == Current Pipe Status, ie what Filters are set up
+
+ pipe.prepend(new Botan::Hash_Filter("MD5"));
+ // CPS: MD5
+
+ pipe.prepend(new Botan::Hash_Filter("RIPEMD-160"));
+ // CPS: RIPEMD-160 | MD5
+
+ pipe.prepend(new Botan::Chain(
+ new Botan::Hash_Filter("RIPEMD-160"),
+ new Botan::Hash_Filter("RIPEMD-160")));
+ // CPS: (RIPEMD-160 | RIPEMD-160) | RIPEMD-160 | MD5
+
+ pipe.pop(); // will pop everything inside the Chain as well as Chain itself
+ // CPS: RIPEMD-160 | MD5
+
+ pipe.pop(); // will get rid of the RIPEMD-160 Hash_Filter
+ // CPS: MD5
+
+ pipe.prepend(new Botan::Hash_Filter("SHA-1"));
+ // CPS: SHA-1 | MD5
+
+ pipe.append(new Botan::Hex_Encoder);
+ // CPS: SHA-1 | MD5 | Hex_Encoder
+
+ pipe.prepend(new Botan::Hash_Filter("SHA-1"));
+ // CPS: SHA-1 | SHA-1 | MD5 | Hex_Encoder
+
+ pipe.pop(); // Get rid of the Hash_Filter(SHA-1)
+ pipe.pop(); // Get rid of the other Hash_Filter(SHA-1)
+ // CPS: MD5 | Hex_Encoder
+ // The Hex_Encoder is safe because it is at the end of the Pipe,
+ // and pop() pulls off the Filter that is at the start.
+
+ pipe.prepend(new Botan::Hash_Filter("RIPEMD-160"));
+ // CPS: RIPEMD-160 | MD5 | Hex_Encoder
+
+ pipe.pop(); // Get rid of that last prepended Hash_Filter(RIPEMD-160)
+ // CPS: MD5 | Hex_Encoder
+
+ int skipped = 0;
+ for(int j = 1; argv[j] != 0; j++)
+ {
+ std::ifstream file(argv[j]);
+ if(!file)
+ {
+ std::cout << "ERROR: could not open " << argv[j] << std::endl;
+ skipped++;
+ continue;
+ }
+ pipe.start_msg();
+ file >> pipe;
+ pipe.end_msg();
+ file.close();
+ pipe.set_default_msg(j-1-skipped);
+ std::cout << pipe << " " << argv[j] << std::endl;
+ }
+ return 0;
+ }
diff --git a/old/botan/doc/examples/test_es.cpp b/old/botan/doc/examples/test_es.cpp
new file mode 100644
index 0000000..951d51a
--- /dev/null
+++ b/old/botan/doc/examples/test_es.cpp
@@ -0,0 +1,115 @@
+#include <botan/botan.h>
+#include <stdio.h>
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_DEVICE)
+ #include <botan/es_dev.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_EGD)
+ #include <botan/es_egd.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_UNIX)
+ #include <botan/es_unix.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_BEOS)
+ #include <botan/es_beos.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_CAPI)
+ #include <botan/es_capi.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_WIN32)
+ #include <botan/es_win32.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_FTW)
+ #include <botan/es_ftw.h>
+#endif
+
+
+using namespace Botan;
+
+class Saver_Of_Bytes : public Entropy_Accumulator
+ {
+ public:
+ Saver_Of_Bytes(u32bit bits) :
+ Entropy_Accumulator(bits), outbuf(64), written(0) {}
+
+ void add_bytes(const byte in[], u32bit length)
+ {
+ for(size_t i = 0; i != length; ++i)
+ outbuf[i % outbuf.size()] ^= in[i];
+
+ written += length;
+ }
+
+ void trunc() { if(written < 64) outbuf.resize(written); }
+
+ std::vector<byte> outbuf;
+ u32bit written;
+ };
+
+void test_entropy_source(EntropySource* es)
+ {
+ // sometimes iostreams really is just a pain
+
+ printf("Polling '%s':\n", es->name().c_str());
+
+ Saver_Of_Bytes accum(128);
+
+ es->poll(accum);
+
+ accum.trunc();
+
+ printf("Got %d bytes\n", accum.written);
+ for(size_t i = 0; i != accum.outbuf.size(); ++i)
+ printf("%02X", accum.outbuf[i]);
+ printf("\n");
+
+ delete es;
+ }
+
+int main()
+ {
+ Botan::LibraryInitializer init;
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_DEVICE)
+ test_entropy_source(
+ new Device_EntropySource(
+ split_on("/dev/random:/dev/srandom:/dev/urandom", ':')
+ )
+ );
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_EGD)
+ test_entropy_source(
+ new EGD_EntropySource(split_on("/var/run/egd-pool:/dev/egd-pool", ':'))
+ );
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_CAPI)
+ test_entropy_source(new Win32_CAPI_EntropySource);
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_FTW)
+ test_entropy_source(new FTW_EntropySource("/proc"));
+#endif
+
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_WIN32)
+ test_entropy_source(new Win32_EntropySource);
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_BEOS)
+ test_entropy_source(new BeOS_EntropySource);
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_UNIX)
+ test_entropy_source(
+ new Unix_EntropySource(split_on("/bin:/sbin:/usr/bin:/usr/sbin", ':'))
+ );
+#endif
+ }
diff --git a/old/botan/doc/examples/x509info.cpp b/old/botan/doc/examples/x509info.cpp
new file mode 100644
index 0000000..0e34f2f
--- /dev/null
+++ b/old/botan/doc/examples/x509info.cpp
@@ -0,0 +1,154 @@
+/*
+ Read an X.509 certificate, and print various things about it
+
+ Written by Jack Lloyd, March 23 2003
+ - October 31, 2003: Prints the public key
+ - November 1, 2003: Removed the -d flag; it can tell automatically now
+
+ This file is in the public domain
+*/
+#include <botan/botan.h>
+#include <botan/x509cert.h>
+#include <botan/oids.h>
+using namespace Botan;
+
+#include <iostream>
+#include <iterator>
+#include <algorithm>
+
+std::string to_hex(const SecureVector<byte>& bin)
+ {
+ Pipe pipe(new Hex_Encoder);
+ pipe.process_msg(bin);
+ if(pipe.remaining())
+ return pipe.read_all_as_string();
+ else
+ return "(none)";
+ }
+
+void do_print(const std::string& what,
+ const std::vector<std::string>& vals)
+ {
+ if(vals.size() == 0)
+ return;
+
+ std::cout << " " << what << ": ";
+ std::copy(vals.begin(), vals.end(),
+ std::ostream_iterator<std::string>(std::cout, " "));
+ std::cout << "\n";
+ }
+
+void do_subject(const X509_Certificate& cert, const std::string& what)
+ {
+ do_print(what, cert.subject_info(what));
+ }
+
+void do_issuer(const X509_Certificate& cert, const std::string& what)
+ {
+ do_print(what, cert.issuer_info(what));
+ }
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 2)
+ {
+ std::cout << "Usage: " << argv[0] << " <x509cert>\n";
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ try {
+ X509_Certificate cert(argv[1]);
+
+ std::cout << "Version: " << cert.x509_version() << std::endl;
+
+ std::cout << "Subject" << std::endl;
+ do_subject(cert, "Name");
+ do_subject(cert, "Email");
+ do_subject(cert, "Organization");
+ do_subject(cert, "Organizational Unit");
+ do_subject(cert, "Locality");
+ do_subject(cert, "State");
+ do_subject(cert, "Country");
+ do_subject(cert, "IP");
+ do_subject(cert, "DNS");
+ do_subject(cert, "URI");
+ do_subject(cert, "PKIX.XMPPAddr");
+
+ std::cout << "Issuer" << std::endl;
+ do_issuer(cert, "Name");
+ do_issuer(cert, "Email");
+ do_issuer(cert, "Organization");
+ do_issuer(cert, "Organizational Unit");
+ do_issuer(cert, "Locality");
+ do_issuer(cert, "State");
+ do_issuer(cert, "Country");
+ do_issuer(cert, "IP");
+ do_issuer(cert, "DNS");
+ do_issuer(cert, "URI");
+
+ std::cout << "Validity" << std::endl;
+
+ std::cout << " Not before: " << cert.start_time() << std::endl;
+ std::cout << " Not after: " << cert.end_time() << std::endl;
+
+ std::cout << "Constraints" << std::endl;
+ Key_Constraints constraints = cert.constraints();
+ if(constraints == NO_CONSTRAINTS)
+ std::cout << "No constraints" << std::endl;
+ else
+ {
+ if(constraints & DIGITAL_SIGNATURE)
+ std::cout << " Digital Signature\n";
+ if(constraints & NON_REPUDIATION)
+ std::cout << " Non-Repuidation\n";
+ if(constraints & KEY_ENCIPHERMENT)
+ std::cout << " Key Encipherment\n";
+ if(constraints & DATA_ENCIPHERMENT)
+ std::cout << " Data Encipherment\n";
+ if(constraints & KEY_AGREEMENT)
+ std::cout << " Key Agreement\n";
+ if(constraints & KEY_CERT_SIGN)
+ std::cout << " Cert Sign\n";
+ if(constraints & CRL_SIGN)
+ std::cout << " CRL Sign\n";
+ }
+
+ std::vector<std::string> policies = cert.policies();
+ if(policies.size())
+ {
+ std::cout << "Policies: " << std::endl;
+ for(u32bit j = 0; j != policies.size(); j++)
+ std::cout << " " << policies[j] << std::endl;
+ }
+
+ std::vector<std::string> ex_constraints = cert.ex_constraints();
+ if(ex_constraints.size())
+ {
+ std::cout << "Extended Constraints: " << std::endl;
+ for(u32bit j = 0; j != ex_constraints.size(); j++)
+ std::cout << " " << ex_constraints[j] << std::endl;
+ }
+
+ std::cout << "Signature algorithm: " <<
+ OIDS::lookup(cert.signature_algorithm().oid) << std::endl;
+
+ std::cout << "Serial: "
+ << to_hex(cert.serial_number()) << std::endl;
+ std::cout << "Authority keyid: "
+ << to_hex(cert.authority_key_id()) << std::endl;
+ std::cout << "Subject keyid: "
+ << to_hex(cert.subject_key_id()) << std::endl;
+
+ X509_PublicKey* pubkey = cert.subject_public_key();
+ std::cout << "Public Key:\n" << X509::PEM_encode(*pubkey);
+ delete pubkey;
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
diff --git a/old/botan/doc/examples/xor_ciph.cpp b/old/botan/doc/examples/xor_ciph.cpp
new file mode 100644
index 0000000..6a914b1
--- /dev/null
+++ b/old/botan/doc/examples/xor_ciph.cpp
@@ -0,0 +1,96 @@
+/*
+ An implementation of the highly secure (not) XOR cipher. AKA, how to write
+ and use your own cipher object. DO NOT make up your own ciphers. Please.
+
+ Written by Jack Lloyd (lloyd@randombit.net) on Feb 17, 2004
+ Update November 21 2008 for new algorithm factory in 1.8
+
+ This file is in the public domain
+*/
+
+#include <botan/stream_cipher.h>
+#include <botan/init.h>
+using namespace Botan;
+
+class XOR_Cipher : public StreamCipher
+ {
+ public:
+ void clear() throw() { mask.destroy(); mask_pos = 0; }
+
+ // what we want to call this cipher
+ std::string name() const { return "XOR"; }
+
+ // return a new object of this type
+ StreamCipher* clone() const { return new XOR_Cipher; }
+
+ XOR_Cipher() : StreamCipher(1, 32) { mask_pos = 0; }
+ private:
+ void cipher(const byte[], byte[], u32bit);
+ void key_schedule(const byte[], u32bit);
+
+ SecureVector<byte> mask;
+ u32bit mask_pos;
+ };
+
+void XOR_Cipher::cipher(const byte in[], byte out[], u32bit length)
+ {
+ for(u32bit j = 0; j != length; j++)
+ {
+ out[j] = in[j] ^ mask[mask_pos];
+ mask_pos = (mask_pos + 1) % mask.size();
+ }
+ }
+
+void XOR_Cipher::key_schedule(const byte key[], u32bit length)
+ {
+ mask.set(key, length);
+ }
+
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <vector>
+#include <cstring>
+
+#include <botan/lookup.h>
+#include <botan/filters.h>
+#include <botan/libstate.h>
+
+int main()
+ {
+
+ Botan::LibraryInitializer init;
+
+ global_state().algorithm_factory().add_stream_cipher(new XOR_Cipher, "app");
+
+ // a hex key value
+ SymmetricKey key("010203040506070809101112AAFF");
+
+ /*
+ Since stream ciphers are typically additive, the encryption and
+ decryption ops are the same, so this isn't terribly interesting.
+
+ If this where a block cipher you would have to add a cipher mode and
+ padding method, such as "/CBC/PKCS7".
+ */
+ Pipe enc(get_cipher("XOR", key, ENCRYPTION), new Hex_Encoder);
+ Pipe dec(new Hex_Decoder, get_cipher("XOR", key, DECRYPTION));
+
+ // I think the pigeons are actually asleep at midnight...
+ std::string secret = "The pigeon flys at midnight.";
+
+ std::cout << "The secret message is '" << secret << "'" << std::endl;
+
+ enc.process_msg(secret);
+ std::string cipher = enc.read_all_as_string();
+
+ std::cout << "The encrypted secret message is " << cipher << std::endl;
+
+ dec.process_msg(cipher);
+ secret = dec.read_all_as_string();
+
+ std::cout << "The decrypted secret message is '"
+ << secret << "'" << std::endl;
+
+ return 0;
+ }
diff --git a/old/botan/doc/fips140.tex b/old/botan/doc/fips140.tex
new file mode 100644
index 0000000..8b20045
--- /dev/null
+++ b/old/botan/doc/fips140.tex
@@ -0,0 +1,156 @@
+\documentclass{article}
+
+\setlength{\textwidth}{6.5in}
+\setlength{\textheight}{9in}
+
+\setlength{\headheight}{0in}
+\setlength{\topmargin}{0in}
+\setlength{\headsep}{0in}
+
+\setlength{\oddsidemargin}{0in}
+\setlength{\evensidemargin}{0in}
+
+\title{\textbf{Botan FIPS 140-2 Security Policy}}
+\author{Jack Lloyd \\
+ \texttt{lloyd@randombit.net}}
+\date{}
+
+\newcommand{\filename}[1]{\texttt{#1}}
+\newcommand{\module}[1]{\texttt{#1}}
+
+\newcommand{\type}[1]{\texttt{#1}}
+\newcommand{\function}[1]{\textbf{#1}}
+\newcommand{\macro}[1]{\texttt{#1}}
+
+\begin{document}
+
+\maketitle
+
+\tableofcontents
+
+\parskip=5pt
+%\baselineskip=15pt
+
+\pagebreak
+
+\section{Introduction}
+
+\emph{Note that this is a draft, and almost certainly does not comply with what
+FIPS 140-2 wants (also it's incomplete). In any case, there is no way for me to
+afford paying the validation lab, so this is all theoretical.}
+
+\emph{I would welcome comments from people who are familiar with the FIPS 140
+process. I am currently basing this off a few dozen other security policies and
+the FIPS itself.}
+
+\subsection{Purpose}
+
+This document is a security policy for the Botan C++ crypto library for use in
+a FIPS 140-2 Level 1 validation process. It describes how to configure and use
+the library to comply with the requirements of FIPS 140-2.
+
+This document is non-proprietary, and may be freely reproduced and distributed
+in unmodified form.
+
+\subsection{Product Description}
+
+The Botan C++ crypto library (hereafter ``Botan'' or ``the library'') is an
+open source C++ class library providing a general-purpose interface to a wide
+variety of cryptographic algorithms and formats (such as X.509v3 and PKCS
+\#10). It runs on most Win32 and POSIX-like systems, including Windows
+NT/2000/XP, MacOS X, Linux, Solaris, FreeBSD, and QNX. However, only versions
+running on \emph{(goal:)} Windows XP, Linux, and Solaris have been validated by
+FIPS 140-2 at this time.
+
+\subsection{Algorithms}
+
+The library contains the following FIPS Approved algorithms: RSA, DSA, DES,
+TripleDES, Skipjack, AES, SHA-1, HMAC, the X9.19 DES MAC, and the FIPS 186-2
+SHA-1 RNG. Other (non-Approved) algorithms, such as MD5 and Diffie-Hellman, are
+also included.
+
+\section{Initialization}
+
+Certain tests are only performed if the flag ``fips140'' is passed as part of
+the initialization process to the library (the argument to
+\type{LibraryInitializer} or \function{Init::initialize}). Known answer tests
+and key generation self-checks for RSA and DSA are always performed, regardless
+of this setting. This flag must be passed by any application which desires
+using the FIPS 140 mode of operation.
+
+\section{Roles and Services}
+
+Botan supports two roles, the User and the Crypto Officer. Authentication is
+not performed by the module; all authentication is implicitly done by the
+operating system.
+
+\subsection{User Role}
+
+The user has the ability to access the services of the module. This role is
+implicitly selected whenever the module's services are accessed.
+
+\subsection{Crypto Officer Role}
+
+The crypto officer has all of the powers of the user, and in addition has the
+power to install and uninstall the module and to configure the operating
+system. This role is implicitly selected whenever these actions are performed.
+
+\section{Key Management}
+
+\subsection{Key Import/Export}
+
+Symmetric keys can be imported and exported in either unencrypted, encrypted,
+or split-knowledge forms, as the application desires. Private keys for
+asymmetric algorithms can be imported and exported as either encrypted or
+unencrypted PKCS \#8 structures. The library natively supports PKCS \#5
+encryption with TripleDES for encrypting private keys.
+
+\subsection{Key Storage}
+
+In no case does the library itself import or export keys from/to an external
+storage device; all such operations are done explicitly by the application. It
+is the responsibly of the operator to ensure than any such operations comply
+with the requirements of FIPS 140-2 Level 1.
+
+\subsection{Key Generation}
+
+Keys for symmetric algorithms (such as DES, AES, and HMAC) are generated by an
+Approved RNG, by generating a random byte string of the appropriate size, and
+using it as a key.
+
+DSA keys are generated as specified in FIPS 186-2 (or not?). RSA keys are
+generated as specified in ANSI X9.31 (\emph{I think...}). Diffie-Hellman keys
+are generated in a manner compatible with ANSI X9.42. All newly created DSA and
+RSA keys are checked with a pairwise consistency test before being returned to
+the caller. A pairwise consistency check can be performed on any RSA, DSA, or
+Diffie-Hellman key by calling the \function{check\_key} member function with
+an argument of \type{true}.
+
+\subsection{Key Establishment}
+
+Botan supports using RSA or Diffie-Hellman to establish keys. RSA can be used
+with PKCS \#1 v1.5 or OAEP padding. None of these methods are FIPS Approved,
+but Annex D of FIPS 140-2 allows for their use until such time as a FIPS
+Approved asymmetric key establishment method is established.
+
+\subsection{Key Protection / Zeroization}
+
+Keys are protected against external access by the operating system's memory and
+process protection mechanisms. If the library is used by multiple processes at
+once, the OS virtual memory mechanisms ensure that each version will have it's
+own data space (and thus, keys are not shared among multiple processes).
+
+All keys and other sensitive materials are zeroed in memory before being
+released to the system.
+
+On Windows systems the \function{VirtualLock} system call is used to notify the
+operating system that the memory containing potentially sensitive keying
+material is not swapped to disk, preventing an attacker from applying disk
+forenistics techniques to recovery data.
+
+On Unix systems, Botan allocates memory from file-backed memory mappings, which
+are thoroughly erased when the memory is freed.
+
+\section{References}
+
+\end{document}
diff --git a/old/botan/doc/indent.el b/old/botan/doc/indent.el
new file mode 100644
index 0000000..9811bf8
--- /dev/null
+++ b/old/botan/doc/indent.el
@@ -0,0 +1,57 @@
+; This Emacs Lips code defines the indentation style used in Botan. If doesn't
+; get everything perfectly correct, but it's pretty close. Copy this code into
+; your .emacs file, or use M-x eval-buffer. Make sure to also set
+; indent-tabs-mode to nil so spaces are inserted instead.
+
+; This style is basically Whitesmiths style with 3 space indents (the Emacs
+; "whitesmith" style seems more like a weird Whitesmiths/Allman mutant style).
+
+; To activate using this style, open the file you want to edit and run this:
+; M-x c-set-style <RET> and then enter "botan". Alternately, put something
+; like this in your .emacs file to make it the default style:
+
+; (add-hook 'c++-mode-common-hook
+; (function (lambda()
+; (c-add-style "botan" botan t))))
+
+(setq botan '(
+ (c-basic-offset . 3)
+ (c-comment-only-line-offset . 0)
+ (c-offsets-alist
+ (c . 0)
+ (comment-intro . 0)
+
+ (statement-block-intro . 0)
+ (statement-cont . +)
+
+ (substatement . +)
+ (substatement-open . +)
+
+ (block-open . +)
+ (block-close . 0)
+
+ (defun-open . +)
+ (defun-close . 0)
+ (defun-block-intro . 0)
+ (func-decl-cont . +)
+
+ (class-open . +)
+ (class-close . +)
+ (inclass . +)
+ (access-label . -)
+ (inline-open . +)
+ (inline-close . 0)
+
+ (extern-lang-open . 0)
+ (extern-lang-close . 0)
+ (inextern-lang . 0)
+
+ (statement-case-open +)
+
+ (namespace-open . 0)
+ (namespace-close . 0)
+ (innamespace . 0)
+
+ (label . 0)
+ )
+))
diff --git a/old/botan/doc/insito_manual.pdf b/old/botan/doc/insito_manual.pdf
new file mode 100644
index 0000000..b071469
--- /dev/null
+++ b/old/botan/doc/insito_manual.pdf
Binary files differ
diff --git a/old/botan/doc/internals.tex b/old/botan/doc/internals.tex
new file mode 100644
index 0000000..5b1650f
--- /dev/null
+++ b/old/botan/doc/internals.tex
@@ -0,0 +1,179 @@
+\documentclass{article}
+
+\setlength{\textwidth}{6.75in} % 1 inch side margins
+\setlength{\textheight}{9in} % ~1 inch top and bottom margins
+
+\setlength{\headheight}{0in}
+\setlength{\topmargin}{0in}
+\setlength{\headsep}{0in}
+
+\setlength{\oddsidemargin}{0in}
+\setlength{\evensidemargin}{0in}
+
+\title{Botan Internals}
+\author{Jack Lloyd (lloyd@randombit.net)}
+\date{August 20, 2006}
+
+\newcommand{\filename}[1]{\texttt{#1}}
+\newcommand{\manpage}[2]{\texttt{#1}(#2)}
+
+\newcommand{\function}[1]{\textbf{#1}}
+\newcommand{\type}[1]{\texttt{#1}}
+\renewcommand{\arg}[1]{\textsl{#1}}
+
+\begin{document}
+
+\maketitle
+
+\tableofcontents
+
+\parskip=5pt
+
+\section{Introduction}
+
+This document is intended to document some of the trickier and/or more
+complicated parts of Botan. This is not going to be terribly useful if
+you just want to use the library, but for people wishing to understand
+how it works, or contribute new code to it, it will hopefully prove
+helpful.
+
+I've realized that a lot of things Botan does internally are pretty
+hard to understand, and that a lot of things are only inside my head,
+which is a bad place for them to be (things tend to get lost in there,
+not to mention the possibility that I'll get hit by a truck next
+week).
+
+This document is currently very incomplete. I'll be working on it as I
+have time.
+
+\pagebreak
+
+\section{Filter}
+
+\type{Filter} is one of the core abstractions of the library. It is
+used to represent any sort of transformation. Nearly all
+\type{Filter}s are linear; they take input from a single source and
+send their output (if any) to another single \type{Filter}. The one
+exception is \type{Fanout\_Filter}, which uses friend access to
+\type{Filter} in order to allow for multiple \type{Filter}s to attach
+to its output. This special access is used by the Chain and Fork
+filters; Chain encapsulates one or more \type{Filter}s into a single
+Filter, and Fork sends its input to a set of several \type{Filter}
+objects.
+
+The majority of the relations between filters is maintained by the
+\type{Pipe} object which ``owns'' the \type{Filter}s.
+
+\section{Pipe}
+
+\type{Pipe} is, conceptually, a tree structure of \type{Filter}
+objects. There is a single unique top, and an arbitrary number of
+leaves (which are \type{SecureQueue} objects). \type{SecureQueue} is a
+simple \type{Filter} that buffers its input.
+
+Writing into the pipe writes into the top of the tree. The filter at
+the top of the tree writes its output into the next \type{Filter}, and
+so on until eventually data trickles down into the bottommost
+\type{Filter}s, where the data is stored for later retrieval.
+
+When a new message is started, \type{Pipe} searches through the tree
+of \type{Filter}s and finds places where the \arg{next} field of the
+\type{Filter} is NULL. This implies that it was the lowest layer of
+the \type{Filter} tree that the user added. It then adds
+\type{SecureQueue} objects onto these \type{Filter}s. These queues are
+also stored in an deque; this is so \type{Pipe} can read from them
+later without doing a tree traversal each time.
+
+\type{Pipe} will, if asked, destroy the existing tree structure, in
+order to create a new one. However, the queue objects are not deleted,
+because \type{Pipe} might be asked to read from them later (while
+\type{Pipe} could delete all the messages in this case, the principle
+of least astonishment suggested keeping them).
+
+What I wrote about \type{Pipe} keeing the queues in a deque is a
+lie. Sort of. It keeps them in an object called
+\type{Output\_Buffers}, which keeps them in a
+deque. \type{Output\_Buffers} is intended to abstract away how message
+queues are stored from \type{Pipe}. After a queue has been added to
+the output buffers object, \type{Pipe} keeps no references to it
+whatsoever; all access is mediated by the \type{Output\_Buffers}.
+This allows queues which have been read to be deleted, rather than
+leaving empty queue objects all over the place.
+
+\section{Library Initialization}
+
+WRITEME
+
+\section{Lookup Mechanism}
+
+Most objects know their name, and they know how to create a new copy
+of themselves. We build mapping tables that map from an algorithm name
+into a single instance of that algorithm. The tables themselves can be
+found in \filename{src/lookup.cpp}.
+
+There are a set of functions named \function{add\_algorithm} that can
+be used to populate the tables. We get something out of the table with
+\function{retrieve\_x}, where x is the name of a type
+(\texttt{block\_cipher}, \texttt{hash}, etc). This returns a const
+pointer to the single unique instance of the algorithm that the lookup
+tables know about. If it doesn't know about it, it falls back on
+calling a function called \function{try\_to\_get\_x}. These functions
+live in \filename{src/algolist.cpp}. They are mostly used to handle
+algorithms which need (or at least can have) arguments passed to them,
+like \type{HMAC} and \type{SAFER\_SK}. It will return NULL if it can't
+find the algorithm at all.
+
+When it's asked for an algorithm it doesn't know about (ie, isn't in
+the mapping tables), the retrieval functions will ask the try-to-get
+functions if \emph{they} know about it. If they do, then the object
+returned will be stored into the table for later retrieval.
+
+The functions \function{get\_x} call the retrieval functions. If we
+get back NULL, an exception is thrown. Otherwise it will call the
+\function{clone} method to get a new copy of the algorithm, which it
+returns.
+
+The various functions like \function{output\_length\_of} call the
+retrieval function for each type of object that the parameter in
+question (in this case, \texttt{OUTPUT\_LENGTH}) might be meaningful
+for. If it manages to get back an object, it will return (in this
+case) the \texttt{OUTPUT\_LENGTH} field of the object. No allocations
+are required to call this function: all of its operations work
+directly on the copies living in the lookup tables.
+
+\section{Allocators}
+
+A big (slow) mess.
+
+\section{BigInt}
+
+Read ``Handbook of Applied Cryptography''.
+
+\section{PEM/BER Identification}
+
+We have a specific algorithm for figuring out if something is PEM or
+BER. Previous versions (everything before 1.3.0) requried that the
+caller specify which one it was, and they had to be right. Now we use
+a hueristic (aka, an algorithm that sometimes doesn't work right) to
+figure it out. If the first character is not 0x30 (equal to ASCII
+'0'), then it can't possibly be BER (because everything we care about
+is enclosed in an ASN.1 SEQUENCE, which for BER/DER is encoded as
+beginning with 0x30). Roughly 99.9% of PEM blocks \emph{won't} have a
+random 0 character in front of them, so we are mostly safe (unless
+someone does it on purpose, in which case, please hit them for me).
+But to be sure, if there is a 0, then we search the first \emph{N}
+bytes of the block for the string ``-----BEGIN ``, which marks the
+typical start of a PEM block. The specific \emph{N} depends on the
+variable ``base/pem\_search'', which defaults to 4 kilobytes.
+
+So, you can actually fool it either way: that a PEM file is really
+BER, or that a BER file is actually PEM. To fool it that a BER file is
+PEM, just have the string ``-----BEGIN `` somewhere (I can't imagine
+this string shows up in certificates or CRLs too often, so if it is
+there it means somebody is being a jerk). If a file starts with 0 and
+has at least ``base/pem\_search'' byte more junk in the way, it won't
+notice that its PEM at all. In either case, of course, the loading
+will fail, and you'll get a nice exception saying that the decoding
+failed.
+
+\end{document}
diff --git a/old/botan/doc/license.txt b/old/botan/doc/license.txt
new file mode 100644
index 0000000..9d1067c
--- /dev/null
+++ b/old/botan/doc/license.txt
@@ -0,0 +1,40 @@
+Botan (http://botan.randombit.net/) is distributed under these terms:
+
+Copyright (C) 1999-2009 Jack Lloyd
+ 2001 Peter J Jones
+ 2004-2007 Justin Karneges
+ 2005 Matthew Gregan
+ 2005-2006 Matt Johnston
+ 2006 Luca Piccarreta
+ 2007 Yves Jerschow
+ 2007-2008 FlexSecure GmbH
+ 2007-2008 Technische Universitat Darmstadt
+ 2007-2008 Falko Strenzke
+ 2007-2008 Martin Doering
+ 2007 Manuel Hartl
+ 2007 Christoph Ludwig
+ 2007 Patrick Sona
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain the above copyright
+notice, this list of conditions, and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions, and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) "AS IS" AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/old/botan/doc/log.txt b/old/botan/doc/log.txt
new file mode 100644
index 0000000..97476c3
--- /dev/null
+++ b/old/botan/doc/log.txt
@@ -0,0 +1,1323 @@
+
+* 1.8.8, 2009-11-03
+ - Alter Skein-512 to match the tweaked 1.2 specification
+ - Fix use of inline asm for access to x86 bswap function
+ - Allow building the library without AES enabled
+ - Add 'powerpc64' alias to ppc64 arch for Gentoo ebuild
+
+* 1.8.7, 2009-09-09
+ - Fix processing multiple messages in XTS mode
+ - Add --no-autoload option to configure.py, for minimized builds
+
+* 1.8.6, 2009-08-13
+ - Add Cryptobox, a set of simple password-based encryption routines
+ - Only read world-readable files when walking /proc for entropy
+ - Fix building with TR1 disabled
+ - Fix x86 bswap support for Visual C++
+ - Fixes for compilation under Sun C++
+ - Add support for Dragonfly BSD (contributed by Patrick Georgi)
+ - Add support for the Open64 C++ compiler
+ - Build fixes for MIPS systems running Linux
+ - Minor changes to license, now equivalent to the FreeBSD/NetBSD license
+
+* 1.8.5, 2009-07-23
+ - Change configure.py to work on stock Python 2.4
+ - Avoid a crash in Skein_512::add_data processing a zero-length input
+ - Small build fixes for SPARC, ARM, and HP-PA processors
+ - The test suite now returns an error code from main() if any tests failed
+
+* 1.8.4, 2009-07-12
+ - Fix a bug in nonce generation in the Miller-Rabin test
+
+* 1.8.3, 2009-07-11
+ - Add a new Python configuration script
+ - Add the Skein-512 SHA-3 candidate hash function
+ - Add the XTS block cipher mode from IEEE P1619
+ - Fix random_prime when generating a prime of less than 7 bits
+ - Improve handling of low-entropy situations during PRNG seeding
+ - Change random device polling to prefer /dev/urandom over /dev/random
+ - Use an input insensitive implementation of same_mem instead of memcmp
+ - Correct DataSource::discard_next to return the number of discarded bytes
+ - Provide a default value for AutoSeeded_RNG::reseed
+ - Fix Gentoo bug 272242
+
+* 1.8.2, 2009-04-07
+ - Make entropy polling more flexible and in most cases faster
+ - GOST 28147 now supports multiple sbox parameters
+ - Added the GOST 34.11 hash function
+ - Fix botan-config problems on MacOS X
+
+* 1.8.1, 2009-01-20
+ - Avoid a valgrind warning in es_unix.cpp on 32-bit Linux
+ - Fix memory leak in PKCS8 load_key and encrypt_key
+ - Relicense api.tex from CC-By-SA 2.5 to BSD
+ - Fix botan-config on MacOS X, Solaris
+
+* 1.8.0, 2008-12-08
+ - Fix compilation on Solaris with GCC
+
+* 1.7.24, 2008-12-01
+ - Fix a compatibility problem with SHA-512/EMSA3 signature padding
+ - Fix bug preventing EGD/PRNGD entropy poller from working
+ - Fix integer overflow in Pooling_Allocator::get_more_core (bug id #27)
+ - Add EMSA3_Raw, a variant of EMSA3 called CKM_RSA_PKCS in PKCS #11
+ - Add support for SHA-224 in EMSA2 and EMSA3 PK signature padding schemes
+ - Add many more test vectors for RSA with EMSA2, EMSA3, and EMSA4
+ - Wrap private structs in SSE2 SHA-1 code in anonymous namespace
+ - Change configure.pl's CPU autodetection output to be more consistent
+ - Disable using OpenSSL's AES due to crashes of unknown cause
+ - Fix warning in /proc walking entropy poller
+ - Fix compilation with IBM XLC for Cell 0.9-200709
+
+* 1.7.23, 2008-11-23
+ - Change to use TR1 (thus enabling ECDSA) with GCC and ICC
+ - Optimize almost all hash functions, especially MD4 and Tiger
+ - Add configure.pl options --{with,without}-{bzip2,zlib,openssl,gnump}
+ - Change Timer to be pure virtual, and add ANSI_Clock_Timer
+ - Cache socket descriptors in the EGD entropy source
+ - Avoid bogging down startup in /proc walking entropy source
+ - Remove Buffered_EntropySource helper class
+ - Add a Default_Benchmark_Timer typedef in benchmark.h
+ - Add examples using benchmark.h and Algorithm_Factory
+ - Add ECC tests from InSiTo
+ - Minor documentation updates
+
+* 1.7.22, 2008-11-17
+ - Add provider preferences to Algorithm_Factory
+ - Fix memory leaks in PBE_PKCS5v20 and get_pbe introduced in 1.7.21
+ - Optimize AES encryption and decryption (about 10% faster)
+ - Enable SSE2 optimized SHA-1 implementation on Intel Prescott CPUs
+ - Fix nanoseconds overflow in benchmark code
+ - Remove Engine::add_engine
+
+* 1.7.21, 2008-11-11
+ - Make algorithm lookup much more configuable
+ - Add facilities for runtime performance testing of algorithms
+ - Drop use of entropy estimation in the PRNGs
+ - Increase intervals between HMAC_RNG automatic reseeding
+ - Drop InitializerOptions class, all options but thread safety
+
+* 1.7.20, 2008-11-09
+ - Namespace pkg-config file by major and minor versions
+ - Cache device descriptors in Device_EntropySource
+ - Split base.h into {block_cipher,stream_cipher,mac,hash}.h
+ - Removed get_mgf function from lookup.h
+
+* 1.7.19, 2008-11-06
+ - Add HMAC_RNG, based on a design by Hugo Krawczyk
+ - Optimized the Turing stream cipher (about 20% faster on x86-64)
+ - Modify Randpool's reseeding algorithm to poll more sources
+ - Add a new AutoSeeded_RNG in auto_rng.h
+ - OpenPGP_S2K changed to take hash object instead of name
+ - Add automatic identification for Intel's Prescott processors
+
+* 1.7.18, 2008-10-22
+ - Add Doxygen comments from InSiTo
+ - Add ECDSA and ECKAEG benchmarks
+ - Add configure.pl switch --with-tr1-implementation
+ - Fix configure.pl's --with-endian and --with-unaligned-mem options
+ - Added support for pkg-config
+ - Optimize byteswap with x86 inline asm for Visual C++ by Yves Jerschow
+ - Use const references to avoid copying overhead in CurveGFp, GFpModulus
+
+* 1.7.17, 2008-10-12
+ - Add missing ECDSA object identifiers
+ - Fix error in x86 and x86-64 assembler affecting GF(p) math
+ - Remove Boost dependency from GF(p) math
+ - Modify botan-config to not print -L/usr/lib or -L/usr/local/lib
+ - Add BOTAN_DLL macro to over 30 classes missing it
+ - Rename the two SHA-2 base classes for consistency
+
+* 1.7.16, 2008-10-09
+ - Add several missing pieces needed for ECDSA and ECKAEG
+ - Add Card Verifiable Certificates from InSiTo
+ - Add SHA-224 from InSiTo
+ - Add BSI variant of EMSA1 from InSiTo
+ - Add GF(p) and ECDSA tests from InSiTo
+ - Split ECDSA and ECKAEG into distinct modules
+ - Allow OpenSSL and GNU MP engines to be built with public key algos disabled
+ - Rename sha256.h to sha2_32.h and sha_64.h to sha2_64.h
+
+* 1.7.15, 2008-10-07
+ - Add GF(p) arithmetic from InSiTo
+ - Add ECDSA and ECKAEG implementations from InSiTo
+ - Minimize internal dependencies, allowing for smaller build configurations
+ - Add new User Manual and Architecture Guide from FlexSecure GmbH
+ - Alter configure.pl options for better autotools compatibility
+ - Update build instructions for recent changes to configure.pl
+ - Fix CPU detection using /proc/cpuinfo
+
+* 1.7.14, 2008-09-30
+ - Split library into parts allowing modular builds
+ - Add (very preliminary) CMS support to the main library
+ - Some constructors now require object pointers instead of names
+ - Support multiple implementations of the same algorithm
+ - Build support for Pentium-M processors, from Derek Scherger
+ - Build support for MinGW/MSYS, from Zbigniew Zagorski
+ - Use inline assembly for bswap on 32-bit x86
+
+* 1.7.13, 2008-09-27
+ - Add SSLv3 MAC, SSLv3 PRF, and TLS v1.0 PRF from Ajisai
+ - Allow all examples to compile even if compression not enabled
+ - Make CMAC's polynomial doubling operation a public class method
+ - Use the -m64 flag when compiling with Sun Forte on x86-64
+ - Clean up and slightly optimize CMAC::final_result
+
+* 1.7.12, 2008-09-18
+ - Add x86 assembly for Visual Studio C++, by Luca Piccarreta
+ - Add a Perl XS module, by Vaclav Ovsik
+ - Add SWIG-based wrapper for Botan
+ - Add SSE2 implementation of SHA-1, by Dean Gaudet
+ - Remove the BigInt::sig_words cache due to bugs
+ - Combined the 4 Blowfish sboxes, suggested by Yves Jerschow
+ - Changed BigInt::grow_by and BigInt::grow_to to be non-const
+ - Add private assignment operators to classes that don't support assignment
+ - Benchmark RSA encryption and signatures
+ - Added test programs for random_prime and ressol
+ - Add high resolution timers for IA-64, HP-PA, S390x
+ - Reduce use of the RNG during benchmarks
+ - Fix builds on STI Cell PPU
+ - Add support for IBM's XLC compiler
+ - Add IETF 8192 bit MODP group
+
+* 1.7.11, 2008-09-11
+ - Added the Salsa20 stream cipher
+ - Optimized Montgomery reduction, Karatsuba squaring
+ - Added 16x16->32 word Comba multiplication and squaring
+ - Use a much larger Karatsuba cutoff point
+ - Remove bigint_mul_add_words
+ - Inlined several BigInt functions
+ - Add useful information to the generated build.h
+ - Rename alg_{ia32,amd64} modules to asm_{ia32,amd64}
+ - Fix the Windows build
+
+* 1.7.10, 2008-09-05
+ - Public key benchmarks run using a selection of random keys
+ - New benchmark timer options are clock_gettime, gettimeofday, times, clock
+ - Including reinterpret_cast optimization for xor_buf in default header
+ - Split byte swapping and word rotation functions into distinct headers
+ - Add IETF modp 6144 group and 2048 and 3072 bit DSS groups
+ - Optimizes BigInt right shift
+ - Add aliases in DL_Group::Format enum
+ - BigInt now caches the significant word count
+
+* 1.7.9, 2008-08-27
+ - Make clear() in most algorithm base classes a pure virtual
+ - Add noexec stack marker for GNU linker in assembly code
+ - Avoid string operations in ressol
+ - Compilation fixes for MinGW and Visual Studio C++ 2008
+ - Some autoconfiguration fixes for Windows
+
+* 1.6.5, 2008-08-27
+ - Add noexec stack marker for GNU linker in assembly code
+ - Fix autoconfiguration problem on x86 with GCC 4.2 and 4.3
+
+* 1.7.8, 2008-07-15
+ - Added the block cipher Noekeon
+ - Remove global deref_alias function
+ - X509_Store takes timeout options as constructor arguments
+ - Add Shanks-Tonelli algorithm, contributed by FlexSecure GmbH
+ - Extend random_prime() for generating primes of any bit length
+ - Remove Config class
+ - Allow adding new entropy via base RNG interface
+ - Reseeding a X9.31 PRNG also reseeds the underlying PRNG
+
+* 1.7.7, 2008-06-28
+ - Remove the global PRNG object
+ - The PK filter objects were removed
+ - Add a test suite for the ANSI X9.31 PRNG
+ - Much cleaner and (mostly) thread-safe reimplementation of es_ftw
+ - Remove both default arguments to ANSI_X931_RNG's constructor
+ - Remove the randomizing version of OctetString::change
+ - Make the cipher and MAC to use in Randpool configurable
+ - Move RandomNumberGenerator declaration to rng.h
+ - RSA_PrivateKey will not generate keys smaller than 1024 bits
+ - Fix an error decoding BER UNIVERSAL types with special taggings
+
+* 1.7.6, 2008-05-05
+ - Initial support for Windows DLLs, from Joel Low
+ - Reset the position pointer when a new block is generated in X9.32 PRNG
+ - Timer objects are now treated as entropy sources
+ - Moved several ASN.1-related enums from enums.h to an appropriate header
+ - Removed the AEP module, due to inability to test
+ - Removed Global_RNG and rng.h
+ - Removed system_clock
+ - Removed Library_State::UI and the pulse callback logic
+
+* 1.7.5, 2008-04-12
+ - The API of X509_CA::sign_request was altered to avoid race conditions
+ - New type Pipe::message_id to represent the Pipe message number
+ - Remove the Named_Mutex_Holder for a small performance gain
+ - Removed several unused or rarely used functions from Config
+ - Ignore spaces inside of a decimal string in BigInt::decode
+ - Allow using a std::istream to initialize a DataSource_Stream object
+ - Fix compilation problem in zlib compression module
+ - The chunk sized used by Pooling_Allocator is now a compile time setting
+ - The size of random blinding factors is now a compile time setting
+ - The install target no longer tries to set a particular owner/group
+
+* 1.7.4, 2008-03-10
+ - Use unaligned memory read/writes on systems that allow it, for performance
+ - Assembly for x86-64 for accessing the bswap instruction
+ - Use larger buffers in ARC4 and WiderWAKE for significant throughput increase
+ - Unroll loops in SHA-160 for a few percent increase in performance
+ - Fix compilation with GCC 3.2 in es_ftw and es_unix
+ - Build fix for NetBSD systems
+ - Prevent es_dev from being built except on Unix systems
+
+* 1.6.4, 2008-03-08
+ - Fix a compilation problem with Visual Studio C++ 2003
+
+* 1.7.3, 2008-01-23
+ - New invocation syntax for configure.pl with several new options
+ - Support for IPv4 addresses in a subject alternative name
+ - New fast poll for the generic Unix entropy source (es_unix)
+ - The es_file entropy source has been replaced by the es_dev module
+ - The malloc allocator does not inherit from Pooling_Allocator anymore
+ - The path that es_unix will search in are now fully user-configurable
+ - Truncate X9.42 PRF output rather than allow counter overflow
+ - PowerPC is now assumed to be big-endian
+
+* 1.7.2, 2007-10-13
+ - Initialize the global library state lazily
+ - Add plain CBC-MAC for backwards compatibility with old systems
+ - Clean up some of the self test code
+ - Throw a sensible exception if a DL_Group is not found
+ - Truncate KDF2 output rather than allowing counter overflow
+ - Add newly assigned OIDs for SHA-2 and DSA with SHA-224/256
+ - Fix a Visual Studio compilation problem in x509stat.cpp
+
+* 1.6.3, 2007-07-23
+ - Fix a race condition in the algorithm lookup cache
+ - Fix problems building the memory pool on some versions of Visual C++
+
+* 1.7.1, 2007-07-23
+ - Fix a race condition in the algorithm object cache
+ - HMAC key schedule optimization
+ - The build header sets a macro defining endianness, if known
+ - New word load/store abstraction allowing further optimization
+ - Modify most of the library to avoid use the C-style casts
+ - Use higher resolution timers in symmetric benchmarks
+
+* 1.7.0, 2007-05-19
+ - DSA parameter generation now follows FIPS 186-3
+ - Added OIDs for Rabin-Williams and Nyberg-Rueppel
+ - Somewhat better support for out of tree builds
+ - Minor optimizations for RC2 and Tiger
+ - Documentation updates
+ - Update the todo list
+
+* 1.6.2, 2007-03-24
+ - Fix autodection on Athlon64s running Linux
+ - Fix builds on QNX and compilers using STLport
+ - Remove a call to abort() that crept into production
+
+* 1.6.1, 2007-01-20
+ - Fix some base64 decoder bugs
+ - Add a new option to base64 encoding, to always append a newline
+ - Fix some build problems under Visual Studio with debug enabled
+ - Fix a bug in BER_Decoder that was triggered under some compilers
+
+* 1.6.0, 2006-12-17
+ - Minor cleanups versus 1.5.13
+
+* 1.5.13, 2006-12-10
+ - Compilation fixes for the bzip2, zlib, and GNU MP modules
+ - Better support for Intel C++ and EKOpath C++ on x86-64
+
+* 1.5.12, 2006-10-27
+ - Cleanups in the initialization routines
+ - Add some x86-64 assembly for multiply-add
+ - Fix problems generating very small (below 384 bit) RSA keys
+ - Support out of tree builds
+ - Bring some of the documentation up to date
+ - More improvements to the Python bindings
+
+* 1.5.11, 2006-09-10
+ - Removed the Algorithm base class
+ - Various cleanups in the public key inheritance hierarchy
+ - Major overhaul of the configure/build setup
+ - Added x86 assembler implementations of Serpent and low-level MPI code
+ - Optimizations for the SHA-1 x86 assembler
+ - Various improvements to the Python wrappers
+ - Work around a Visual Studio compiler bug
+
+* 1.5.10, 2006-08-13
+ - Add x86 assembler versions of MD4, MD5, and SHA-1
+ - Expand InitializerOptions' language to support on/off switches
+ - Fix definition of OID 2.5.4.8; was accidentally changed in 1.5.9
+ - Fix possible resource leaks in the mmap allocator
+ - Slightly optimized buffering in MDx_HashFunction
+ - Initialization failures are dealt with somewhat better
+ - Add an example implementing Pollard's Rho algorithm
+ - Better option handling in the test/benchmark tool
+ - Expand the xor_ciph example to support longer keys
+ - Some updates to the documentation
+
+* 1.5.9, 2006-07-12
+ - Fixed bitrot in the AEP engine
+ - Fix support for marking certificate/CRL extensions as critical
+ - Significant cleanups in the library state / initialization code
+ - LibraryInitializer takes an explicit InitializerOptions object
+ - Make Mutex_Factory an abstract class, add Default_Mutex_Factory
+ - Change configuration access to using global_state()
+ - Add support for global named mutexes throughout the library
+ - Add some STL wrappers for the delete operator
+ - Change how certificates are created to be more flexible and general
+
+* 1.5.8, 2006-06-23
+ - Many internal cleanups to the X.509 cert/CRL code
+ - Allow for application code to support new X.509 extensions
+ - Change the return type of X509_Certificate::{subject,issuer}_info
+ - Allow for alternate character set handling mechanisms
+ - Fix a bug that was slowing squaring performance somewhat
+ - Fix a very hard to hit overflow bug in the C version of word3_muladd
+ - Minor cleanups to the assembler modules
+ - Disable es_unix module on FreeBSD due to build problem on FreeBSD 6.1
+ - Support for GCC 2.95.x has been dropped in this release
+
+* 1.5.7, 2006-05-28
+ - Further, major changes to the BER/DER coding system
+ - Updated the Qt mutex module to use Mutex_Factory
+ - Moved the library global state object into an anonymous namespace
+ - Drop the Visual C++ x86 assembly module due to bugs
+
+* 1.5.6, 2006-03-01
+ - The low-level DER/BER coding system was redesigned and rewritten
+ - Portions of the certificate code were cleaned up internally
+ - Use macros to substantially clean up the GCC assembly code
+ - Added 32-bit x86 assembly for Visual C++ (by Luca Piccarreta)
+ - Avoid a couple of spurious warnings under Visual C++
+ - Some slight cleanups in X509_PublicKey::key_id
+
+* 1.5.5, 2006-02-04
+ - Fixed a potential infinite loop in the memory pool code (Matt Johnston)
+ - Made Pooling_Allocator::Memory_Block an actual class of sorts
+ - Some small optimizations to the division and modulo computations
+ - Cleaned up the implementation of some of the BigInt operators
+ - Reduced use of dynamic memory allocation in low-level BigInt functions
+ - A few simplifications in the Randpool mixing function
+ - Removed power(), as it was not particularly useful (or fast)
+ - Fixed some annoying bugs in the benchmark code
+ - Added a real credits file
+
+* 1.5.4, 2006-01-29
+ - Integrated x86 and amd64 assembly code, contributed by Luca Piccarreta
+ - Fixed a memory access off-by-one in the Karatsuba code
+ - Changed Pooling_Allocator's free list search to a log(N) algorithm
+ - Merged ModularReducer with its only subclass, Barrett_Reducer
+ - Fixed sign-handling bugs in some of the division and modulo code
+ - Renamed the module description files to modinfo.txt
+ - Further cleanups in the initialization code
+ - Removed BigInt::add and BigInt::sub
+ - Merged all the division-related functions into just divide()
+ - Modified the <mp_asmi.h> functions to allow for better optimizations
+ - Made the number of bits polled from an EntropySource user configurable
+ - Avoid including <algorithm> in <botan/secmem.h>
+ - Fixed some build problems with Sun Forte
+ - Removed some dead code from bigint_modop
+ - Fix the definition of same_mem
+
+* 1.5.3, 2006-01-24
+ - Many optimizations in the low-level multiple precision integer code
+ - Added hooks for assembly implementations of the MPI code
+ - Support for the X.509 issuer alternative name extension in new certs
+ - Fixed a bug in the decompression modules; found and patched by Matt Johnston
+ - New Windows mutex module (mux_win32), by Luca Piccarreta
+ - Changed the Windows timer module to use QueryPerformanceCounter
+ - mem_pool.cpp was using std::set iterators instead of std::multiset ones
+ - Fixed a bug in X509_CA preventing users from disabling particular extensions
+ - Fixed the mp_asm64 module, which was entirely broken in 1.5.2
+ - Fixed some module build problems on FreeBSD and Tru64
+
+* 1.4.12, 2006-01-15
+ - Fixed an off-by-one memory read in MISTY1::key()
+ - Fixed a nasty memory leak in Output_Buffers::retire()
+ - Changed maximum HMAC keylength to 1024 bits
+ - Fixed a build problem in the hardware timer module on 64-bit PowerPC
+
+* 1.5.2, 2006-01-15
+ - Fixed an off-by-one memory read in MISTY1::key()
+ - Fixed a nasty memory leak in Output_Buffers::retire()
+ - Reimplemented the memory allocator from scratch
+ - Improved memory caching in Montgomery exponentiation
+ - Optimizations for multiple precision addition and subtraction
+ - Fixed a build problem in the hardware timer module on 64-bit PowerPC
+ - Changed default Karatsuba cutoff to 12 words (was 14)
+ - Removed MemoryRegion::bits(), which was unused and incorrect
+ - Changed maximum HMAC keylength to 1024 bits
+ - Various minor Makefile and build system changes
+ - Avoid using std::min in <secmem.h> to bypass Windows libc macro pollution
+ - Switched checks/clock.cpp back to using clock() by default
+ - Enabled the symmetric algorithm tests, which were accidentally off in 1.5.1
+ - Removed the Default_Mutex's unused clone() member function
+
+* 1.5.1, 2006-01-08
+ - Implemented Montgomery exponentiation
+ - Implemented generalized Karatsuba multiplication and squaring
+ - Implemented Comba squaring for 4, 6, and 8 word inputs
+ - Added new Modular_Exponentiator and Power_Mod classes
+ - Removed FixedBase_Exp and FixedExponent_Exp
+ - Fixed a performance regression in get_allocator introduced in 1.5.0
+ - Engines can now offer S2K algorithms and block cipher padding methods
+ - Merged the remaining global 'algolist' code into Default_Engine
+ - The low-level MPI code is linked as C again
+ - Replaced BigInt's get_nibble with the more general get_substring
+ - Some documentation updates
+
+* 1.5.0, 2006-01-01
+ - Moved all global/shared library state into a single object
+ - Mutex objects are created through mutex factories instead of a global
+ - Removed ::get_mutex(), ::initialize_mutex(), and Mutex::clone()
+ - Removed the RNG_Quality enum entirely
+ - There is now only a single global-use PRNG
+ - Removed the no_aliases and no_oids options for LibraryInitializer
+ - Removed the deprecated algorithms SEAL, ISAAC, and HAVAL
+ - Change es_ftw to use unbuffered I/O
+
+* 1.4.11, 2005-12-31
+ - Changed Whirlpool diffusion matrix to match updated algorithm spec
+ - Fixed several engine module build errors introduced in 1.4.10
+ - Fixed two build problems in es_capi; reported by Matthew Gregan
+ - Added a constructor to DataSource_Memory taking a std::string
+ - Placing the same Filter in multiple Pipes triggers an exception
+ - The configure script accepts --docdir and --libdir
+ - Merged doc/rngs.txt into the main API document
+ - Thanks to Joel Low for several bug reports on early tarballs of 1.4.11
+
+* 1.4.10, 2005-12-18
+ - Added an implementation of KASUMI, the block cipher used in 3G phones
+ - Refactored Pipe; output queues are now managed by a distinct class
+ - Made certain Filter facilities only available to subclasses of Fanout_Filter
+ - There is no longer any overhead in Pipe for a message that has been read out
+ - It is now possible to generate RSA keys as small as 128 bits
+ - Changed some of the core classes to derive from Algorithm as a virtual base
+ - Changed Randpool to use HMAC instead of a plain hash as the mixing function
+ - Fixed a bug in the allocators; found and fixed by Matthew Gregan
+ - Enabled the use of binary file I/O, when requested by the application
+ - The OpenSSL engine's block cipher code was missing some deallocation calls
+ - Disabled the es_ftw module on NetBSD, due to header problems there
+ - Fixed a problem preventing tm_hard from building on MacOS X on PowerPC
+ - Some cleanups for the modules that use inline assembler
+ - config.h is now stored in build/ instead of build/include/botan/
+ - The header util.h was split into bit_ops.h, parsing.h, and util.h
+ - Cleaned up some redundant include directives
+
+* 1.4.9, 2005-11-06
+ - Added the IBM-created AES candidate algorithm MARS
+ - Added the South Korean block cipher SEED
+ - Added the stream cipher Turing
+ - Added the new hash function FORK-256
+ - Deprecated the ISAAC stream cipher
+ - Twofish and RC6 are significantly faster with GCC
+ - Much better support for 64-bit PowerPC
+ - Added support for high-resolution PowerPC timers
+ - Fixed a bug in the configure script causing problems on FreeBSD
+ - Changed ANSI X9.31 to support arbitrary block ciphers
+ - Make the configure script a bit less noisy
+ - Added more test vectors for some algorithms, including all the AES finalists
+ - Various cosmetic source code cleanups
+
+* 1.4.8, 2005-10-16
+ - Resolved a bad performance problem in the allocators; fix by Matt Johnston
+ - Worked around a Visual Studio 2003 compilation problem introduced in 1.4.7
+ - Renamed OMAC to CMAC to match the official NIST naming
+ - Added single byte versions of update() to PK_Signer and PK_Verifier
+ - Removed the unused reverse_bits and reverse_bytes functions
+
+* 1.4.7, 2005-09-25
+ - Fixed major performance problems with recent versions of GNU C++
+ - Added an implementation of the X9.31 PRNG
+ - Removed the X9.17 and FIPS 186-2 PRNG algorithms
+ - Changed defaults to use X9.31 PRNGs as global PRNG objects
+ - Documentation updates to reflect the PRNG changes
+ - Some cleanups related to the engine code
+ - Removed two useless headers, base_eng.h and secalloc.h
+ - Removed PK_Verifier::valid_signature
+ - Fixed configure/build system bugs affecting MacOS X builds
+ - Added support for the EKOPath x86-64 compiler
+ - Added missing destructor for BlockCipherModePaddingMethod
+ - Fix some build problems with Visual C++ 2005 beta
+ - Fix some build problems with Visual C++ 2003 Workshop
+
+* 1.4.6, 2005-03-13
+ - Fix an error in the shutdown code introduced in 1.4.5
+ - Setting base/pkcs8_tries to 0 disables the builtin fail-out
+ - Support for XMPP identifiers in X.509 certificates
+ - Duplicate entries in X.509 DNs are removed
+ - More fixes for Borland C++, from Friedemann Kleint
+ - Add a workaround for buggy iostreams
+
+* 1.4.5, 2005-02-26
+ - Add support for AES encryption of private keys
+ - Minor fixes for PBES2 parameter decoding
+ - Internal cleanups for global state variables
+ - GCC 3.x version detection was broken in non-English locales
+ - Work around a Sun Forte bug affecting mem_pool.h
+ - Several fixes for Borland C++ 5.5, from Friedemann Kleint
+ - Removed inclusion of init.h into base.h
+ - Fixed a major bug in reading from certificate stores
+ - Cleaned up a couple of mutex leaks
+ - Removed some left-over debugging code
+ - Removed SSL3_MAC, SSL3_PRF, and TLS_PRF
+
+* 1.4.4, 2004-12-02
+ - Further tweaks to the pooling allocator
+ - Modified EMSA3 to support SSL/TLS signatures
+ - Changes to support Qt/QCA, from Justin Karneges
+ - Moved mux_qt module code into mod_qt
+ - Fixes for HP-UX from Mike Desjardins
+
+* 1.4.3, 2004-11-06
+ - Split up SecureAllocator into Allocator and Pooling_Allocator
+ - Memory locking allocators are more likely to be used
+ - Fixed the placement of includes in some modules
+ - Fixed broken installation procedure
+ - Fixes in configure script to support alternate install programs
+ - Modules can specify the minimum version they support
+
+* 1.4.2, 2004-10-31
+ - Fixed a major CRL handling bug
+ - Cipher and hash operations can be offloaded to engines
+ - Added support for cipher and hash offload in OpenSSL engine
+ - Improvements for 64-bit CPUs without a widening multiply instruction
+ - Support for SHA2-* and Whirlpool with EMSA2
+ - Fixed a long-standing build problem with conflicting include files
+ - Fixed some examples that hadn't been updated for 1.4.x
+ - Portability fixes for Solaris, *BSD, HP-UX, and others
+ - Lots of fixes and cleanups in the configure script
+ - Updated the Gentoo ebuild file
+
+* 1.4.1, 2004-10-10
+ - Fixed major errors in the X.509 and PKCS #8 copy_key functions
+ - Added a LAST_MESSAGE meta-message number for Pipe
+ - Added new aliases (3DES and DES-EDE) for Triple-DES
+ - Added some new functions to PK_Verifier
+ - Cleaned up the KDF interface
+ - Disabled tm_posix on *BSD due to header issues
+ - Fixed a build problem on PowerPC with GNU C++ pre-3.4
+
+* 1.4.0, 2004-06-26
+ - Added the FIPS 186 RNG back
+ - Added copy_key functions for X.509 public keys and PKCS #8 private keys
+ - Fixed PKCS #1 signatures with RIPEMD-128
+ - Moved some code around to avoid warnings with Sun ONE compiler
+ - Fixed a bug in botan-config affecting OpenBSD
+ - Fixed some build problems on Tru64, HP-UX
+ - Fixed compile problems with Intel C++, Compaq C++
+
+* 1.3.14, 2004-06-12
+ - Added support for AEP's AEP1000/AEP2000 crypto cards
+ - Added a Mutex module using Qt, from Justin Karneges
+ - Added support for engine loading in LibraryInitializer
+ - Tweaked SecureAllocator, giving 20% better performance under heavy load
+ - Added timer and memory locking modules for Win32 (tm_win32, ml_win32)
+ - Renamed PK_Engine to Engine_Core
+ - Improved the Karatsuba cutoff points
+ - Fixes for compiling with GCC 3.4 and Sun C++ 5.5
+ - Fixes for Linux/s390, OpenBSD, and Solaris
+ - Added support for Linux/s390x
+ - The configure script was totally broken for 'generic' OS
+ - Removed Montgomery reduction due to bugs
+ - Removed an unused header, pkcs8alg.h
+ - check --validate returns an error code if any tests failed
+ - Removed duplicate entry in Unix command list for es_unix
+ - Moved the Cert_Usage enumeration into X509_Store
+ - Added new timing methods for PK benchmarks, clock_gettime and RDTSC
+ - Fixed a few minor bugs in the configure script
+ - Removed some deprecated functions from x509cert.h and pkcs10.h
+ - Removed the 'minimal' module, has to be updated for Engine support
+ - Changed MP_WORD_BITS macro to BOTAN_MP_WORD_BITS to clean up namespace
+ - Documentation updates
+
+* 1.3.13, 2004-05-15
+ - Major fixes for Cygwin builds
+ - Minor MacOS X install fixes
+ - The configure script is a little better at picking the right modules
+ - Removed ml_unix from the 'unix' module set for Cygwin compatibility
+ - Fixed a stupid compile problem in pkcs10.h
+
+* 1.3.12, 2004-05-02
+ - Added ability to remove old entries from CRLs
+ - Swapped the first two arguments of X509_CA::update_crl()
+ - Added an < operator for MemoryRegion, so it can be used as a std::map key
+ - Changed X.509 searching by DNS name from substring to full string compares
+ - Renamed a few X509_Certificate and PKCS10_Request member functions
+ - Fixed a problem when decoding some PKCS #10 requests
+ - Hex_Decoder would not check inputs, reported by Vaclav Ovsik
+ - Changed default CRL expire time from 30 days to 7 days
+ - X509_CRL's default PEM header is now "X509 CRL", for OpenSSL compatibility
+ - Corrected errors in the API doc, fixes from Ken Perano
+ - More documentation about the Pipe/Filter code
+
+* 1.3.11, 2004-04-01
+ - Fixed two show-stopping bugs in PKCS10_Request
+ - Added some sanity checks in Pipe/Filter
+ - The DNS and URI entries would get swapped in subjectAlternativeNames
+ - MAC_Filter is now willing to not take a key at creation time
+ - Setting the expiration times of certs and CRLs is more flexible
+ - Fixed problems building on AIX with GCC
+ - Fixed some problems in the tutorial pointed out by Dominik Vogt
+ - Documentation updates
+
+* 1.3.10, 2004-03-27
+ - Added support for OpenPGP's ASCII armor format
+ - Cleaned up the RNG system; seeding is much more flexible
+ - Added simple autoconfiguration abilities to configure.pl
+ - Fixed a GCC 2.95.x compile problem
+ - Updated the example configuration file
+ - Documentation updates
+
+* 1.3.9, 2004-03-07
+ - Added an engine using OpenSSL (requires 0.9.7 or later)
+ - X509_Certificate would lose email addresses stored in the DN
+ - Fixed a missing initialization in a BigInt constructor
+ - Fixed several Visual C++ compile problems
+ - Fixed some BeOS build problems
+ - Fixed the WiderWake benchmark
+
+* 1.3.8, 2003-12-30
+ - Internal changes to PK algorithms to divide data and algorithms
+ - DSA/DH/NR/ElGamal constructors accept taking just the private key again
+ - ElGamal keys now support being imported/exported as ASN.1 objects
+ - Much more consistent and complete error checking in PK algorithms
+ - Support for arbitrary backends (engines) for PK operations
+ - Added Montgomery reductions
+ - Added an engine that uses GNU MP (requires 4.1 or later)
+ - Removed the obsolete mp_gmp module
+ - Moved several initialization/shutdown functions to init.h
+ - Major refactoring of the memory containers
+ - New non-locking container, MemoryVector
+ - Fixed 64-bit problems in BigInt::set_bit/clear_bit
+ - Renamed PK_Key::check_params() to check_key()
+ - Some incompatible changes to OctetString
+ - Added version checking macros in version.h
+ - Removed the fips140 module pending rewrite
+ - Added some functions and hooks to help GUIs
+ - Moved more shared code into MDx_HashFunction
+ - Added a policy hook for specifying the encoding of X.509 strings
+
+* 1.3.7, 2003-12-12
+ - Fixed a big security problem in es_unix
+ - Fixed several stability problems in es_unix
+ - Expanded the list of programs es_unix will try to use
+ - SecureAllocator now only preallocates blocks in special cases
+ - Added a special case in Global_RNG::seed for forcing a full poll
+ - Removed the FIPS 186 RNG added in 1.3.5 pending further testing
+ - Configure updates for PowerPC CPUs
+ - Removed the (never tested) VAX support
+ - Added support for S/390 Linux
+
+* 1.3.6, 2003-12-07
+ - Added a new module 'minimal', which disables most algorithms
+ - SecureAllocator allocates a few blocks at startup
+ - A few minor MPI cleanups
+ - RPM spec file cleanups and fixes
+
+* 1.3.5, 2003-11-30
+ - Major improvements in ASN.1 string handling
+ - Added partial support for ASN.1 UTF8 STRINGs and BMP STRINGs
+ - Added partial support for the X.509v3 certificate policies extension
+ - Centralized the handling of character set information
+ - Added FIPS 140-2 startup self tests
+ - Added a module (fips140) for doing extra FIPS 140-2 tests
+ - Added FIPS 186-2 RNG
+ - Improved ASN.1 BIT STRING handling
+ - Removed a memory leak in PKCS10_Request
+ - The encoding of DirectoryString now follows PKIX guidelines
+ - Fixed some of the character set dependencies
+ - Fixed a DER encoding error for tags greater than 30
+ - The BER decoder can now handle tags larger than 30
+ - Fixed tm_hard.cpp to recognize SPARC on more systems
+ - Workarounds for a GCC 2.95.x bug in x509find.cpp
+ - RPM changed to install into /usr instead of /usr/local
+ - Added support for QNX
+
+* 1.2.8, 2003-11-21
+ - Merged several important bug fixes from 1.3.x
+
+* 1.3.4, 2003-11-21
+ - Added a module that does certain MPI operations using GNU MP
+ - Added the X9.42 Diffie-Hellman PRF
+ - The Zlib and Bzip2 objects now use custom allocators
+ - Added member functions for directly hashing/MACing SecureVectors
+ - Minor optimizations to the MPI addition and subtraction algorithms
+ - Some cleanups in the low-level MPI code
+ - Created separate AES-{128,192,256} objects
+
+* 1.3.3, 2003-11-17
+ - The library can now be repeatedly initialized and shutdown without crashing
+ - Fixed an off-by-one error in the CTS code
+ - Fixed an error in the EMSA4 verification code
+ - Fixed a memory leak in mutex.cpp (pointed out by James Widener)
+ - Fixed a memory leak in Pthread_Mutex
+ - Fixed several memory leaks in the testing code
+ - Bulletproofed the EMSA/EME/KDF/MGF retrieval functions
+ - Minor cleanups in SecureAllocator
+ - Removed a needless mutex guarding the (stateless) global timer
+ - Fixed a piece of bash-specific code in botan-config
+ - X.509 objects report more information about decoding errors
+ - Cleaned up some of the exception handling
+ - Updated the example config file with new OIDSs
+ - Moved the build instructions into a separate document, building.tex
+
+* 1.3.2, 2003-11-13
+ - Fixed a bug preventing DSA signatures from verifying on X.509 objects
+ - Made the X509_Store search routines more efficient and flexible
+ - Added a function to X509_PublicKey to do easy public/private key matching
+ - Added support for decoding indefinite length BER data
+ - Changed Pipe's peek() to take an offset
+ - Removed Filter::set_owns in favor of the new incr_owns function
+ - Removed BigInt::zero() and BigInt::one()
+ - Renamed the PEM related options from base/pem_* to pem/*
+ - Added an option to specify the line width when encoding PEM
+ - Removed the "rng/safe_longterm" option; it's always on now
+ - Changed the cipher used for RNG super-encryption from ARC4 to WiderWake4+1
+ - Cleaned up the base64/hex encoders and decoders
+ - Added an ASN.1/BER decoder as an example
+ - AES had its internals marked 'public' in previous versions
+ - Changed the value of the ASN.1 NO_OBJECT enum
+ - Various new hacks in the configure script
+ - Removed the already nominal support for SunOS
+
+* 1.3.1, 2003-11-04
+ - Generalized a few pieces of the DER encoder
+ - PKCS8::load_key would fail if handed an unencrypted key
+ - Added a failsafe so PKCS #8 key decoding can't go into an infinite loop
+
+* 1.3.0, 2003-11-02
+ - Major redesign of the PKCS #8 private key import/export system
+ - Added a small amount of UI interface code for getting passphrases
+ - Added heuristics that tell if a key, cert, etc is stored as PEM or BER
+ - Removed CS-Cipher, SHARK, ThreeWay, MD5-MAC, and EMAC
+ - Removed certain deprecated constructors of RSA, DSA, DH, RW, NR
+ - Made PEM decoding more forgiving of extra text before the header
+
+* 1.2.7, 2003-10-31
+ - Added support for reading configuration files
+ - Added constructors so NR and RW keys can be imported easily
+ - Fixed mp_asm64, which was completely broken in 1.2.6
+ - Removed tm_hw_ia32 module; replaced by tm_hard
+ - Added support for loading certain oddly formed RSA certificates
+ - Fixed spelling of NON_REPUDIATION enum
+ - Renamed the option default_to_ca to v1_assume_ca
+ - Fixed a minor bug in X.509 certificate generation
+ - Fixed a latent bug in the OID lookup code
+ - Updated the RPM spec file
+ - Added to the tutorial
+
+* 1.2.6, 2003-07-04
+ - Major performance increase for PK algorithms on most 64-bit systems
+ - Cleanups in the low-level MPI code to support asm implementations
+ - Fixed build problems with some versions of Compaq's C++ compiler
+ - Removed useless constructors for NR public and private keys
+ - Removed support for the patch_file directive in module files
+ - Removed several deprecated functions
+
+* 1.2.5, 2003-06-22
+ - Fixed a tricky and long-standing memory leak in Pipe
+ - Major cleanups and fixes in the memory allocation system
+ - Removed alloc_mlock, which has been superseded by the ml_unix module
+ - Removed a denial of service vulnerability in X509_Store
+ - Fixed compilation problems with VS .NET 2003 and Codewarrior 8
+ - Added another variant of PKCS8::load_key, taking a memory buffer
+ - Fixed various minor/obscure bugs which occurred when MP_WORD_BITS != 32
+ - BigInt::operator%=(word) was a no-op if the input was a power of 2
+ - Fixed portability problems in BigInt::to_u32bit
+ - Fixed major bugs in SSL3-MAC
+ - Cleaned up some messes in the PK algorithms
+ - Cleanups and extensions for OMAC and EAX
+ - Made changes to the entropy estimation function
+ - Added a 'beos' module set for use on BeOS
+ - Officially deprecated a few X509:: and PKCS8:: functions
+ - Moved the contents of primes.h to numthry.h
+ - Moved the contents of x509opt.h to x509self.h
+ - Removed the (empty) desx.h header
+ - Documentation updates
+
+* 1.2.4, 2003-05-29
+ - Fixed a bug in EMSA1 affecting NR signature verification
+ - Fixed a few latent bugs in BigInt related to word size
+ - Removed an unused function, mp_add2_nc, from the MPI implementation
+ - Reorganized the core MPI files
+
+* 1.2.3, 2003-05-20
+ - Fixed a bug that prevented DSA/NR key generation
+ - Fixed a bug that prevented importing some root CA certs
+ - Fixed a bug in the BER decoder when handing optional bit or byte strings
+ - Fixed the encoding of authorityKeyIdentifier in X509_CA
+ - Added a sanity check in PBKDF2 for zero length passphrases
+ - Added versions of X509::load_key and PKCS8::load_key that take a file name
+ - X509_CA generates 128 bit serial numbers now
+ - Added tests to check PK key generation
+ - Added a simplistic X.509 CA example
+ - Cleaned up some of the examples
+
+* 1.2.2, 2003-05-13
+ - Add checks to prevent any BigInt bugs from revealing an RSA or RW key
+ - Changed the interface of Global_RNG::seed
+ - Major improvements for the es_unix module
+ - Added another Win32 entropy source, es_win32
+ - The Win32 CryptoAPI entropy source can now poll multiple providers
+ - Improved the BeOS entropy source
+ - Renamed pipe_unixfd module to fd_unix
+ - Fixed a file descriptor leak in the EGD module
+ - Fixed a few locking bugs
+
+* 1.2.1, 2003-05-06
+ - Added ANSI X9.23 compatible CBC padding
+ - Added an entropy source using Win32 CryptoAPI
+ - Removed the Pipe I/O operators taking a FILE*
+ - Moved the BigInt encoding/decoding functions into the BigInt class
+ - Integrated several fixes for VC++ 7 (from Hany Greiss)
+ - Fixed the configure.pl script for Windows builds
+
+* 1.2.0, 2003-04-28
+ - Tweaked the Karatsuba cut-off points
+ - Increased the allowed keylength of HMAC and Blowfish
+ - Removed the 'mpi_ia32' module, pending rewrite
+ - Workaround a GCC 2.95.x bug in eme1.cpp
+
+* 1.1.13, 2003-04-22
+ - Added OMAC
+ - Added EAX authenticated cipher mode
+ - Diffie-Hellman would not do blinding in some cases
+ - Optimized the OFB and CTR modes
+ - Corrected Skipjack's word ordering, as per NIST clarification
+ - Support for all subject/issuer attribute types required by RFC 3280
+ - The removeFromCRL CRL reason code is now handled correctly
+ - Increased the flexibility of the allocators
+ - Renamed Rijndael to AES, created aes.h, deleted rijndael.h
+ - Removed support for the 'no_timer' LibraryInitializer option
+ - Removed 'es_pthr' module, pending further testing
+ - Cleaned up get_ciph.cpp
+
+* 1.1.12, 2003-04-15
+ - Fixed a ASN.1 string encoding bug
+ - Fixed a pair of X509_DN encoding problems
+ - Base64_Decoder and Hex_Decoder can now validate input
+ - Removed support for the LibraryInitializer option 'egd_path'
+ - Added tests for DSA X.509 and PKCS #8 key formats
+ - Removed a long deprecated feature of DH_PrivateKey's constructor
+ - Updated the RPM .spec file
+ - Major documentation updates
+
+* 1.1.11, 2003-04-07
+ - Added PKCS #10 certificate requests
+ - Changed X509_Store searching interface to be more flexible
+ - Added a generic Certificate_Store interface
+ - Added a function for generating self-signed X.509 certs
+ - Cleanups and changes to X509_CA
+ - New examples for PKCS #10 and self-signed certificates
+ - Some documentation updates
+
+* 1.1.10, 2003-04-03
+ - X509_CA can now generate new X.509 CRLs
+ - Added blinding for RSA, RW, DH, and ElGamal to prevent timing attacks
+ - More certificate and CRL extensions/attributes are supported
+ - Better DN handling in X.509 certificates/CRLs
+ - Added a DataSink hierarchy (suggested by Jim Darby)
+ - Consolidated SecureAllocator and ManagedAllocator
+ - Many cleanups and generalizations
+ - Added a (slow) pthreads based EntropySource
+ - Fixed some threading bugs
+
+* 1.1.9, 2003-02-25
+ - Added support for using X.509v2 CRLs
+ - Fixed several bugs in the path validation algorithm
+ - Certificates can be verified for a particular usage
+ - Algorithm for comparing distinguished names now follows X.509
+ - Cleaned up the code for the es_beos, es_ftw, es_unix modules
+ - Documentation updates
+
+* 1.1.8, 2003-01-29
+ - Fixes for the certificate path validation algorithm in X509_Store
+ - Fixed a bug affecting X509_Certificate::is_ca_cert()
+ - Added a general configuration interface for policy issues
+ - Cleanups and API changes in the X.509 CA, cert, and store code
+ - Made various options available for X509_CA users
+ - Changed X509_Time's interface to work around time_t problems
+ - Fixed a theoretical weakness in Randpool's entropy mixing function
+ - Fixed problems compiling with GCC 2.95.3 and GCC 2.96
+ - Fixed a configure bug (reported by Jon Wilson) affecting MinGW
+
+* 1.1.7, 2003-01-12
+ - Fixed an obscure but dangerous bug in SecureVector::swap
+ - Consolidated SHA-384 and SHA-512 to save code space
+ - Added SSL3-MAC and SSL3-PRF
+ - Documentation updates, including a new tutorial
+
+* 1.0.2, 2003-01-12
+ - Fixed an obscure SEGFAULT causing bug in Pipe
+ - Fixed an obscure but dangerous bug in SecureVector::swap
+
+* 1.1.6, 2002-12-10
+ - Initial support for X.509v3 certificates and CAs
+ - Major redesign/rewrite of the ASN.1 encoding/decoding code
+ - Added handling for DSA/NR signatures encoded as DER SEQUENCEs
+ - Documented the generic cipher lookup interface
+ - Added an (untested) entropy source for BeOS
+ - Various cleanups and bug fixes
+
+* 1.1.5, 2002-11-17
+ - Added the discrete logarithm integrated encryption system (DLIES)
+ - Various optimizations for BigInt
+ - Added support for assembler optimizations in modules
+ - Added BigInt x86 optimizations module (mpi_ia32)
+
+* 1.1.4, 2002-11-10
+ - Speedup of 15-30% for PK algorithms
+ - Implemented the PBES2 encryption scheme
+ - Fixed a potential bug in decoding RSA and RW private keys
+ - Changed the DL_Group class interface to handle different formats better
+ - Added support for PKCS #3 encoded DH parameters
+ - X9.42 DH parameters use a PEM label of 'X942 DH PARAMETERS'
+ - Added key pair consistency checking
+ - Fixed a compatibility problem with gcc 2.96 (pointed out by Hany Greiss)
+ - A botan-config script is generated at configure time
+ - Documentation updates
+
+* 1.1.3, 2002-11-03
+ - Added a generic public/private key loading interface
+ - Fixed a small encoding bug in RSA, RW, and DH
+ - Changed the PK encryption/decryption interface classes
+ - ECB supports using padding methods
+ - Added a function-based interface for library initialization
+ - Added support for RIPEMD-128 and Tiger PKCS#1 v1.5 signatures
+ - The cipher mode benchmarks now use 128-bit AES instead of DES
+ - Removed some obsolete typedefs
+ - Removed OpenCL support (opencl.h, the OPENCL_* macros, etc)
+ - Added tests for PKCS #8 encoding/decoding
+ - Added more tests for ECB and CBC
+
+* 1.1.2, 2002-10-21
+ - Support for PKCS #8 encoded RSA, DSA, and DH private keys
+ - Support for Diffie-Hellman X.509 public keys
+ - Major reorganization of how X.509 keys are handled
+ - Added PKCS #5 v2.0's PBES1 encryption scheme
+ - Added a generic cipher lookup interface
+ - Added the WiderWake4+1 stream cipher
+ - Added support for sync-able stream ciphers
+ - Added a 'paranoia level' option for the LibraryInitializer
+ - More security for RNG output meant for long term keys
+ - Added documentation for some of the new 1.1.x features
+ - CFB's feedback argument is now specified in bits
+ - Renamed CTR class to CTR_BE
+ - Updated the RSA and DSA examples to use X.509 and PKCS #8 key formats
+
+* 1.1.1, 2002-10-15
+ - Added the Korean hash function HAS-160
+ - Partial support for RSA and DSA X.509 public keys
+ - Added a mostly functional BER encoder/decoder
+ - Added support for non-deterministic MAC functions
+ - Initial support for PEM encoding/decoding
+ - Internal cleanups in the PK algorithms
+ - Several new convenience functions in Pipe
+ - Fixed two nasty bugs in Pipe
+ - Messed with the entropy sources for es_unix
+ - Discrete logarithm groups are checked for safety more closely now
+ - For compatibility with GnuPG, ElGamal now supports DSA-style groups
+
+* 1.1.0, 2002-09-14
+ - Added entropy estimation to the RNGs
+ - Improved the overall design of both Randpool and ANSI_X917_RNG
+ - Added a separate RNG for nonce generation
+ - Added window exponentiation support in power_mod
+ - Added a get_s2k function and the PKCS #5 S2K algorithms
+ - Added the TLSv1 PRF
+ - Replaced BlockCipherModeIV typedef with InitializationVector class
+ - Renamed PK_Key_Agreement_Scheme to PK_Key_Agreement
+ - Renamed SHA1 -> SHA_160 and SHA2_x -> SHA_x
+ - Added support for RIPEMD-160 PKCS#1 v1.5 signatures
+ - Changed the key agreement scheme interface
+ - Changed the S2K and KDF interfaces
+ - Better SCAN compatibility for HAVAL, Tiger, MISTY1, SEAL, RC5, SAFER-SK
+ - Added support for variable-pass Tiger
+ - Major speedup for Rabin-Williams key generation
+
+* 1.0.1, 2002-09-14
+ - Fixed a minor bug in Randpool::random()
+ - Added some new aliases and typedefs for 1.1.x compatibility
+ - The 4096-bit RSA benchmark key was decimal instead of hex
+ - EMAC was returning an incorrect name
+
+* 1.0.0, 2002-08-26
+ - Octal I/O of BigInt is now supported
+ - Fixed portability problems in the es_egd module
+ - Generalized IV handling in the block cipher modes
+ - Added Karatsuba multiplication and k-ary exponentiation
+ - Fixed a problem in the multiplication routines
+
+* 0.9.2, 2002-08-18
+ - DH_PrivateKey::public_value() was returning the wrong value
+ - Various BigInt optimizations
+ - The filters.h header now includes hex.h and base64.h
+ - Moved Counter mode to ctr.h
+ - Fixed a couple minor problems with VC++ 7
+ - Fixed problems with the RPM spec file
+
+* 0.9.1, 2002-08-10
+ - Grand rename from OpenCL to Botan
+ - Major optimizations for the PK algorithms
+ - Added ElGamal encryption
+ - Added Whirlpool
+ - Tweaked memory allocation parameters
+ - Improved the method of seeding the global RNG
+ - Moved pkcs1.h to eme_pkcs.h
+ - Added more test vectors for some algorithms
+ - Fixed error reporting in the BigInt tests
+ - Removed Default_Timer, it was pointless
+ - Added some new example applications
+ - Removed some old examples that weren't that interesting
+ - Documented the compression modules
+
+* 0.9.0, 2002-08-03
+ - EMSA4 supports variable salt size
+ - PK_* can take a string naming the encoding method to use
+ - Started writing some internals documentation
+
+* 0.8.7, 2002-07-30
+ - Fixed bugs in EME1 and EMSA4
+ - Fixed a potential crash at shutdown
+ - Cipher modes returned an ill-formed name
+ - Removed various deprecated types and headers
+ - Cleaned up the Pipe interface a bit
+ - Minor additions to the documentation
+ - First stab at a Visual C++ makefile (doc/Makefile.vc7)
+
+* 0.8.6, 2002-07-25
+ - Added EMSA4 (aka PSS)
+ - Brought the manual up to date; many corrections and additions
+ - Added a parallel hash function construction
+ - Lookup supports all available algorithms now
+ - Lazy initialization of the lookup tables
+ - Made more discrete logarithm groups available through get_dl_group()
+ - StreamCipher_Filter supports seeking (if the underlying cipher does)
+ - Minor optimization for GCD calculations
+ - Renamed SAFER_SK128 to SAFER_SK
+ - Removed many previously deprecated functions
+ - Some now-obsolete functions, headers, and types have been deprecated
+ - Fixed some bugs in DSA prime generation
+ - DL_Group had a constructor for DSA-style prime gen but it wasn't defined
+ - Reversed the ordering of the two arguments to SEAL's constructor
+ - Fixed a threading problem in the PK algorithms
+ - Fixed a minor memory leak in lookup.cpp
+ - Fixed pk_types.h (it was broken in 0.8.5)
+ - Made validation tests more verbose
+ - Updated the check and example applications
+
+* 0.8.5, 2002-07-21
+ - Major changes to constructors for DL-based cryptosystems (DSA, NR, DH)
+ - Added a DL_Group class
+ - Reworking of the pubkey internals
+ - Support in lookup for aliases and PK algorithms
+ - Renamed CAST5 to CAST_128 and CAST256 to CAST_256
+ - Added EMSA1
+ - Reorganization of header files
+ - LibraryInitializer will install new allocator types if requested
+ - Fixed a bug in Diffie-Hellman key generation
+ - Did a workaround in pipe.cpp for GCC 2.95.x on Linux
+ - Removed some debugging code from init.cpp that made FTW ES useless
+ - Better checking for invalid arguments in the PK algorithms
+ - Reduced Base64 and Hex default line length (if line breaking is used)
+ - Fixes for HP's aCC compiler
+ - Cleanups in BigInt
+
+* 0.8.4, 2002-07-14
+ - Added Nyberg-Rueppel signatures
+ - Added Diffie-Hellman key exchange (kex interface is subject to change)
+ - Added KDF2
+ - Enhancements to the lookup API
+ - Many things formerly taking pointers to algorithms now take names
+ - Speedups for prime generation
+ - LibraryInitializer has support for seeding the global RNG
+ - Reduced SAFER-SK128 memory consumption
+ - Reversed the ordering of public and private key values in DSA constructor
+ - Fixed serious bugs in MemoryMapping_Allocator
+ - Fixed memory leak in Lion
+ - FTW_EntropySource was not closing the files it read
+ - Fixed line breaking problem in Hex_Encoder
+
+* 0.8.3, 2002-06-09
+ - Added DSA and Rabin-Williams signature schemes
+ - Added EMSA3
+ - Added PKCS#1 v1.5 encryption padding
+ - Added Filters for PK algorithms
+ - Added a Keyed_Filter class
+ - LibraryInitializer processes arguments now
+ - Major revamp of the PK interface classes
+ - Changed almost all of the Filters for non-template operation
+ - Changed HMAC, Lion, Luby-Rackoff to non-template classes
+ - Some fairly minor BigInt optimizations
+ - Added simple benchmarking for PK algorithms
+ - Added hooks for fixed base and fixed exponent modular exponentiation
+ - Added some examples for using RSA
+ - Numerous bugfixes and cleanups
+ - Documentation updates
+
+* 0.8.2, 2002-05-18
+ - Added an (experimental) algorithm lookup interface
+ - Added code for directly testing BigInt
+ - Added SHA2-384
+ - Optimized SHA2-512
+ - Major optimization for Adler32 (thanks to Dan Nicolaescu)
+ - Various minor optimizations in BigInt and related areas
+ - Fixed two bugs in X9.19 MAC, both reported by Darren Starsmore
+ - Fixed a bug in BufferingFilter
+ - Made a few fixes for MacOS X
+ - Added a workaround in configure.pl for GCC 2.95.x
+ - Better support for PowerPC, ARM, and Alpha
+ - Some more cleanups
+
+* 0.8.1, 2002-05-06
+ - Major code cleanup (check doc/deprecated.txt)
+ - Various bugs fixed, including several portability problems
+ - Renamed MessageAuthCode to MessageAuthenticationCode
+ - A replacement for X917 is in x917_rng.h
+ - Changed EMAC to non-template class
+ - Added ANSI X9.19 compatible CBC-MAC
+ - TripleDES now supports 128 bit keys
+
+* 0.8.0, 2002-04-24
+ - Merged BigInt: many bugfixes and optimizations since alpha2
+ - Added RSA (rsa.h)
+ - Added EMSA2 (emsa2.h)
+ - Lots of new interface code for public key algorithms (pk_base.h, pubkey.h)
+ - Changed some interfaces, including SymmetricKey, to support the global rng
+ - Fixed a serious bug in ManagedAllocator
+ - Renamed RIPEMD128 to RIPEMD_128 and RIPEMD160 to RIPEMD_160
+ - Removed some deprecated stuff
+ - Added a global random number generator (rng.h)
+ - Added clone functions to most of the basic algorithms
+ - Added a library initializer class (init.h)
+ - Version macros in version.h
+ - Moved the base classes from opencl.h to base.h
+ - Renamed the bzip2 module to comp_bzip2 and zlib to comp_zlib
+ - Documentation updates for the new stuff (still incomplete)
+ - Many new deprecated things: check doc/deprecated.txt
+
+* 0.7.10, 2002-04-07
+ - Added EGD_EntropySource module (es_egd)
+ - Added a file tree walking EntropySource (es_ftw)
+ - Added MemoryLocking_Allocator module (alloc_mlock)
+ - Renamed the pthr_mux, unix_rnd, and mmap_mem modules
+ - Changed timer mechanism; the clock method can be switched on the fly.
+ - Renamed MmapDisk_Allocator to MemoryMapping_Allocator
+ - Renamed ent_file.h to es_file.h (ent_file.h is around, but deprecated)
+ - Fixed several bugs in MemoryMapping_Allocator
+ - Added more default sources for Unix_EntropySource
+ - Changed SecureBuffer to use same allocation methods as SecureVector
+ - Added bigint_divcore into mp_core to support BigInt alpha2 release
+ - Removed some Pipe functions deprecated since 0.7.8
+ - Some fixes for the configure program
+
+* 0.7.9, 2002-03-19
+ - Memory allocation substantially revamped
+ - Added memory allocation method based on mmap(2) in the mmap_mem module
+ - Added ECB and CTS block cipher modes (ecb.h, cts.h)
+ - Added a Mutex interface (mutex.h)
+ - Added module pthr_mux, implementing the Mutex interface
+ - Added Threaded Filter interface (thr_filt.h)
+ - All algorithms can now by keyed with SymmetricKey objects
+ - More testing occurs with --validate (expected failures)
+ - Fixed two bugs reported by Hany Greiss, in Luby-Rackoff and RC6
+ - Fixed a buffering bug in Bzip_Decompress and Zlib_Decompress
+ - Made X917 safer (and about 1/3 as fast)
+ - Documentation updates
+
+* 0.7.8, 2002-02-28
+ - More capabilities for Pipe, inspired by SysV STREAMS, including peeking,
+ better buffering, and stack ops. NOT BACKWARDS COMPATIBLE: SEE DOCUMENTATION
+ - Added a BufferingFilter class
+ - Added popen() based EntropySource for generic Unix systems (unix_rnd)
+ - Moved 'devrand' module into main distribution (ent_file.h), renamed to
+ File_EntropySource, and changed interface somewhat.
+ - Made Randpool somewhat more conservative and also 25% faster
+ - Minor fixes and updates for the configure script
+ - Added some tweaks for memory allocation
+ - Documentation updates for the new Pipe interface
+ - Fixed various minor bugs
+ - Added a couple of new example programs (stack and hasher2)
+
+* 0.7.7, 2001-11-24
+ - Filter::send now works in the constructor of a Filter subclass
+ - You may now have to include <opencl/pipe.h> explicitly in some code
+ - Added preliminary PK infrastructure classes in pubkey.h and pkbase.h
+ - Enhancements to SecureVector (append, destroy functions)
+ - New infrastructure for secure memory allocation
+ - Added IEEE P1363 primitives MGF1, EME1, KDF1
+ - Rijndael optimizations and cleanups
+ - Changed CipherMode<B> to BlockCipherMode(B*)
+ - Fixed a nasty bug in pipe_unixfd
+ - Added portions of the BigInt code into the main library
+ - Support for VAX, SH, POWER, PowerPC-64, Intel C++
+
+* 0.7.6, 2001-10-14
+ - Fixed several serious bugs in SecureVector created in 0.7.5
+ - Square optimizations
+ - Fixed shared objects on MacOS X and HP-UX
+ - Fixed static libs for KCC 4.0; works with KCC 3.4g as well
+ - Full support for Athlon and K6 processors using GCC
+ - Added a table of prime numbers < 2**16 (primes.h)
+ - Some minor documentation updates
+
+* 0.7.5, 2001-08-19
+ - Split checksum.h into adler32.h, crc24.h, and crc32.h
+ - Split modes.h into cbc.h, cfb.h, and ofb.h
+ - CBC_wPadding* has been replaced by CBC_Encryption and CBC_Decryption
+ - Added OneAndZeros and NoPadding methods for CBC
+ - Added Lion, a very fast block cipher construction
+ - Added an S2K base class (s2k.h) and an OpenPGP_S2K class (pgp_s2k.h)
+ - Basic types (ciphers, hashes, etc) know their names now (call name())
+ - Changed the EntropySource type somewhat
+ - Big speed-ups for ISAAC, Adler32, CRC24, and CRC32
+ - Optimized CAST-256, DES, SAFER-SK, Serpent, SEAL, MD2, and RIPEMD-160
+ - Some semantics of SecureVector have changed slightly
+ - The mlock module has been removed for the time being
+ - Added string handling functions for hashes and MACs
+ - Various non-user-visible cleanups
+ - Shared library soname is now set to the full version number
+
+* 0.7.4, 2001-07-15
+ - New modules: Zlib, gettimeofday and x86 RTC timers, Unix I/O for Pipe
+ - Fixed a vast number of errors in the config script/makefile/specfile
+ - Pipe now has a stdio(3) interface as well as C++ iostreams
+ - ARC4 supports skipping the first N bytes of the cipher stream (ala MARK4)
+ - Bzip2 supports decompressing multiple concatenated streams, and flushing
+ - Added a simple 'overall average' score to the benchmarks
+ - Fixed a small bug in the POSIX timer module
+ - Removed a very-unlikely-to-occur bug in most of the hash functions
+ - filtbase.h now includes <iosfwd>, not <iostream>
+ - Minor documentation updates
+
+* 0.7.3, 2001-06-08
+ - Fix build problems on Solaris/SPARC
+ - Fix build problems with Perl versions < 5.6
+ - Fixed some stupid code that broke on a few compilers
+ - Added string handling functions to Pipe
+ - MISTY1 optimizations
+
+* 0.7.2, 2001-06-03
+ - Build system supports modules
+ - Added modules for mlock, a /dev/random EntropySource, POSIX1.b timers
+ - Added Bzip2 compression filter, contributed by Peter Jones
+ - GNU make no longer required (tested with 4.4BSD pmake and Solaris make)
+ - Fixed minor bug in several of the hash functions
+ - Various other minor fixes and changes
+ - Updates to the documentation
+
+* 0.7.1, 2001-05-16
+ - Rewrote configure script: more consistent and complete
+ - Made it easier to find out parameters of types at run time (opencl.h)
+ - New functions for finding the version being used (version.h)
+ - New SymmetricKey interface for Filters (symkey.h)
+ - InvalidKeyLength now records what the invalid key length was
+ - Optimized DES, CS-Cipher, MISTY1, Skipjack, XTEA
+ - Changed GOST to use correct S-box ordering (incompatible change)
+ - Benchmark code was almost totally rewritten
+ - Many more entries in the test vector file
+ - Fixed minor and idiotic bug in check.cpp
+
+* 0.7.0, 2001-03-01
+ - First public release
+
diff --git a/old/botan/doc/pgpkeys.asc b/old/botan/doc/pgpkeys.asc
new file mode 100644
index 0000000..378230f
--- /dev/null
+++ b/old/botan/doc/pgpkeys.asc
@@ -0,0 +1,83 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2.0.9 (GNU/Linux)
+
+mQGiBDqZbS4RBACH3vOrWo72lWh/lbECfIfGdtl+YDgyGMB2BiGDJG7Kzbg9IB2e
+no0Du+omligWpgWlYdkiJ+/wpCJlBxd/P3rEegp822aeV1eD3E03wxWUvhyWgy+8
+I8POrcCjC9RkrTGTl5RiFdaRVCG93vzmJFUJoI1Kt0F5AnTJXJm4VgNo0wCg4F/M
+jN7YfhrUroE8ksTGPiCeNocD/R6wGZ0FFtYHdK5W19u/vM9JfAXxoK+OmDheFSVL
+oIWVCXacwvbVQ15MfdQxaRyZmkWD9jgm2Omr8II6iK12B3WLRb96bkQzC0Sd25Xm
+2tLKUDBwK0meG/8cRj3hE4WFF6VBdhWNtRhbby6Le9JHC+ylMrHwMy+HHXl5a2gf
+ycCmA/9LU5GukTKfaBz9OPrVkMf2n0RbdBgn5hxtDeZ5iV6JMosEGobMnZ77n44M
+VdGk6NWlMZqmwy6tJg2CdKPiQtjJaPuIR6qM0rtc8tpnhJSqq2c3KNOcaTennJsc
+H3MNtT6FeZH1pZOhcmLjs7wb267NgR89vBQd2l46qWYSaBCASbQWQm90YW4gRGlz
+dHJpYnV0aW9uIEtleYhiBBMRAgAaBQsHCgMEAxUDAgMWAgECF4ACGQEFAkkXKWoA
+EgdlR1BHAAEBCRCmPyy9+gL7zKhdAKCfZvYBJeZaVW+Cq8S463bbw9vtJACg29tp
+zrPhPtU4baw3ngVFUjUcLCyJAhwEEAECAAYFAkkq4q8ACgkQXA+W6E7BbWuJmg/+
+NTxLCg0I527bNowv/pEBrN26Aghwu3/Gn6QrRz2bFQ1A/8LNw2w8eKY0w/b5ieiC
+kYy/DmkcDFkspmtaVvA0A+hK/NIIEbFqllKnTQ2BK5EdqQxS+OuBZN4BbJJ2XzKD
+6bUcmIEpzymVah/r49D09VG7TQeBequcER9DumSuKhDM10Jt594tkjUo8E7BO8Np
+54T2MXX3Nk839eZLihnSh5Cnj6pmLlr/4Tx8iXQTuk2CKkOWxCXaE1CJlUnaXTTy
+T16na7PdWPKUR1x2cNY9uL+r5RwSRebV2iV3620MzFHYIAbFYrRdew8HnBnzrwgE
+gk4z8fFFSDwIkkGVIkZMqchyWQySJ8UIQpUPVM0/EA+ejgMbLx/Xt6ONIZQiq9Cc
+8AaPsoEXFlQHRFN65BB8GIYUdraw/yHwTWX4UNtyNNTq6zgwnsvik6ZJN7RNdgea
+rZavW8svXsDZgwEVDI3ps19B1yD0AxC/IJ9uqxqTKn+dYciiZJCMBUTITb6lVs6b
+SnMNqdllE2z591cQH02rInHH25WiMjoPeboUozLZ7tyWZtv7/CP4a+IcNqB7LmET
+qNTWki3cAnLw5UfPVYrnunI5jHG2eFCjHk3cGAM/AcWRs+wqRfUAqzjs/rRUH8QD
+n4vADnCuKHle3dRFq3Dy+fCZe/7yEmeAyJ8FbmSQRgOZAgsEQX8lLwEQALecnQ3J
+k1iajTjKoUryWAs8orDTBxiOkYQuwD1g01Geu5XMcDx0ykqPPer1688QN2P/4Lc6
+zN4B0h3SNn8zmz9MI9afCaL3DPynogKX4/zPvSSAITiSytClKNbpSRoqjpdXeoUU
+cW7gs8+d81bYJtgBtATtVHDZXzDO32wbPT1Zi+IdI+19R84tgWZBDgLYdQIaUa+G
++j14Gdubc4nFfP6h/UmWC7r6xo0TeQsNLUv2c9nyMeUUKeKZwBar0349sWKihjLf
+ne9TXPgdEpg0C9fYAlxTOBa+hIbESVie/4BxtvSHk+wWFpRZtBkS43SDF5qZY0TX
+uZJmt3YhiX/zlRut1nhLtqxzNVMIZtNZkD4MrMl7+mHManITkCMBS5NmpmXdlBES
+Si+cPVMD91fEAuILczJj/VCUl1pn83kIlD9wxDNQcFdMzuicvFneEszW7UCdvPUC
+3UcFQcsxAuYUEPr/H9Qraogm8/UE7+fTb8pTSt06KsZR3nMLLMKICcgLpraDQENZ
+GCcK8js82FsB+6ccQ5WB1nMDfdDbYNyRKv/bgPmKxOw74jo24wSeio4zFHBzVXYQ
+CLleO52H+w5jz4vEXhC3IEqoLhJHAIW41yl3pqx1qeZ0XwOfGP67nQzI+YhUn59+
+OBngAVQ8rdfWxopzVTI7oRlQafFbTyN/sReTAAYptC5KYWNrIExsb3lkIChTaWdu
+aW5nIEtleSkgPGxsb3lkQHJhbmRvbWJpdC5uZXQ+iQIuBBMBAgAYAhsDAh4BAheA
+BQJBgDp5AwsJAgQVAgMIAAoJEFwPluhOwW1roTQP+QFzRSVwJYzHUebr1nQSS65b
+/9EeX3tSI8ZnKEMAIAYn3YvnYhZxKwdFvCWKZJXfPcaJqv+xWEvArsYEbj6n4AJw
+73V27USLqvqNnBleeQluM1nm8AYvmukHXUDmTOCRhqL1rK70DKTRB3Q08sgnmuRF
+8sMuG6TRPm8zk9N87zI8fYbT7hWxoO6E9wXPOr+4cYirmtbPY0Ni5bWvd/JrRzWa
+2e/UVrpvoBE6kPaF6mxK8oDTGmRr+yKjEsxsTKYQJbguzDYtjEvjoDxScYfegk7n
+5PdOGyhjDV/EjC/I7HcJNDVg72szmNLaNskoiHZaEiiTKD60gWFRwQJfNRYiZk0J
+x1707wNZCzjKVkeD5U8x4uWchkWjXft0XdCYsKdZQ/GTepcIwz683wicdCVAMcUt
+vy43i5DaPelOV22TqL6coLoelso1AURHAwfgBc/cqCsweUVotNA8SvsYMTaXuNMm
+578Cs44AEXrWY0sLFCYEu6rA47HV7FXoaruK7Qjo/IopqsLd42g7HBR993tEl7j5
+3lK0VGHdFI0I4kw/tWSVXqH5vK12WLg0mc+21KGoLjkGSdPsKNUP2xhZaiK8fAB9
+2WonnGMAVUXwQ4Tu9gGzA4KzjZv5RLWvOnbRc8Vh1ppXXoSrlRkHJXT6wHfNDrvf
+ZJuOruFauUJmw1CEQcKyiQEiBBABAgAMBQJBugFKBQMAEnUAAAoJEJcQuJvKV618
+KrcIAJ0f1Js973k2ednThL7Fy1B68KZ/DOpbWqB8R53oJ/aaIU0TpXqKFN+amy1N
+qrC2lLh7DebBJkan+UNJ6l/uj6cR0q+D1VeDjrFKgS9D7WwjXthik6Ph/nMnd9jz
+TH7+8CxN3h0BAlaysxbM/gXjPYd/z05yYdtMayE/hnUhG1ysKrWdVzZv68qBesi+
+h0Z5b7IsfdlTtBi+0Y/wNDiOl8dg7UIkNjYveNgv02yR6InQEnAW6ESEiJ5/p4fi
+CPtyTk3Hz8biM4I7oTKPNYhnpp7LxVMQbeWck3mb9Yjr2uqjNMiFuBHslmAZvtBn
+hj55BU0GwM7ukMNkQLWICfftXGmIRgQTEQIABgUCQjkXLAAKCRBG+5XZXjRWKC0P
+AKCHLrGe1Lz/4sxvKhROPiGFAEOPoACfRYNAzEZJ2iqeb6JxQuu3gxH3XVuZAQsE
+QYPWPQEIAMfE8mQ9yMkT7gOWKzHaFVzQOPokjUxIuuQzxH7Zs6FVRJ96vE9PUQw+
+F+sB04dMCWjK9FOEnO2dmw0qp8svj0YZwEt0QYBU2SzWkbftN7N7kvHVci7MkWuj
+MvayoHLkLqcekWB3W1wPrxFqHbCnS7ZxH2jBd/Uiop0R+6jrrX4xO/vBMHXiEpXv
+mcHtk7rrvpIRlEgtgz7tEnAoAoSYQ8lzqER/3hVef15w3NpOUeBiSOHP11ss53eh
+31e+5TD4sxHV3AGozFu9H3QyJeNt50MSRsCtxkH1g4Ai8Rf+ULeppbhcm3iLAdaX
+9hVkR8Aty9DLB7YIOsfmE7v3jB30ykEABim0FkJvdGFuIERpc3RyaWJ1dGlvbiBL
+ZXmJATQEEwECAB4FAkGD1j0CGwMGCwkIBwMCAxUCAwMWAgECHgECF4AACgkQYhHr
+8e+637yzmAf/VTzFHTY/JoehmaXmoQflhDT2gvHCRi1cWv0g1nxPMLAgN44KHRQp
+ckgO8edO6QYI9zTxwa+WQxt+WqX8qv8/MAKjhqsLIB/XBF2+FwW6RXcO9t7gwKDY
+6ufUuN7Lju0CIZrXYVUqSdwLzwG6MiTc170aYranq1riRtmtRwhubvIMRo3bkxZX
+RPWHpm535h7Cfos7AKj+kq/Q3IlBhnmuSLS2H05rceLQ37VHi/xJOqqRZiJndSPy
+gP3uKII1fOaLu74YKGSerXeWtCzzA5XzCZRov0z74CnTRKwT5u5hf4zp9doMi+DV
+sjtXTqXDHM8snA2tvPASNW67uK+v7WnZmYkCHAQTAQIABgUCQYPWUgAKCRBcD5bo
+TsFta+r9EACWVis7YcaGkKKgRB/5ox8rM36XVhMXdh/hnnGHt5rapbbRRkRHRcWU
+8WIcFO1A59+TfwNNd8gN1MEt/5aX5KHWVKHBDexJgIxm6Dm1pisYHf/dnYQPM18h
+mqqwNlKY97hFkPpHd7enrtc/SvGbQhhLXYlpwBrdMl76e9xJLnnrRQksxegGPo8c
+r+C9HTs1Lwa8zzBxyBwYBYX+0moDkDShEhuXx6mEOXrGvQanJuIvpoIwGH+62E65
+MbJGlwWpw/MAtm2jFhBIhGV0bqJCFp9zIgdNgfskBaPr0oilbuJQZqP0Iqe/6CCt
+4XkS51yWZqxjLAFpEpvDec4PGw3witKf/koGon9X8C035+nEjLBrWy18Q91vw2US
+yLI+mm9diMAS8pY2gomfxBO2VwYHJryZykjCYQkccRA1tHteRj4gqTObo0Ak47y5
+MnplTWwi40oP7K2cfhCRBmMioxmYES4xsHEupfRBo3xr1Jq9q0t688WTT1NXHPMP
+oueF9mKZCf2pa9aHsqBmWTm3sCaNQKGubCDBEUmJUyndmSatJyYM7NVYoUp6EfqM
+ACFuTNdBsjKMh7aWVikQpbJDfA1BIU3lZeqgjgrghVAWkEOBfhG0IVZj+RVCJpsq
+oTJ8asY2VreArSCyr/VnLEnfuH/QpgvCiCbepo3E34DJt4SaAOO2Zg==
+=QyrG
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/old/botan/doc/scripts/comba.py b/old/botan/doc/scripts/comba.py
new file mode 100644
index 0000000..ce3cfed
--- /dev/null
+++ b/old/botan/doc/scripts/comba.py
@@ -0,0 +1,65 @@
+#!/usr/bin/python
+
+import sys
+
+def comba_indexes(N):
+
+ indexes = []
+
+ for i in xrange(0, 2*N):
+ x = []
+
+ for j in xrange(max(0, i-N+1), min(N, i+1)):
+ x += [(j,i-j)]
+ indexes += [sorted(x)]
+
+ return indexes
+
+def comba_sqr_indexes(N):
+
+ indexes = []
+
+ for i in xrange(0, 2*N):
+ x = []
+
+ for j in xrange(max(0, i-N+1), min(N, i+1)):
+ if j < i-j:
+ x += [(j,i-j)]
+ else:
+ x += [(i-j,j)]
+ indexes += [sorted(x)]
+
+ return indexes
+
+def comba_multiply_code(N):
+ indexes = comba_indexes(N)
+
+ for (i,idx) in zip(range(0, len(indexes)), indexes):
+ for pair in idx:
+ print "word3_muladd(&w2, &w1, &w0, x[%2d], y[%2d]);" % (pair)
+ print "z[%2d] = w0; w0 = w1; w1 = w2; w2 = 0;" % (i)
+
+def comba_square_code(N):
+ indexes = comba_sqr_indexes(N)
+
+ for (rnd,idx) in zip(range(0, len(indexes)), indexes):
+ for (i,pair) in zip(range(0, len(idx)), idx):
+ if pair[0] == pair[1]:
+ print " word3_muladd(&w2, &w1, &w0, x[%2d], x[%2d]);" % (pair)
+ elif i % 2 == 0:
+ print " word3_muladd_2(&w2, &w1, &w0, x[%2d], x[%2d]);" % (pair[0], pair[1])
+ if rnd < len(idx)-2:
+ print " z[%2d] = w0; w0 = w1; w1 = w2; w2 = 0;\n" % (rnd)
+ elif rnd == len(idx)-1:
+ print " z[%2d] = w0;\n" % (rnd)
+ else:
+ print " z[%2d] = w1;\n" % (rnd)
+
+def main(args = None):
+ if args is None:
+ args = sys.argv
+ #comba_square_code(int(args[1]))
+ comba_multiply_code(int(args[1]))
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/old/botan/doc/scripts/combine_bmarks.pl b/old/botan/doc/scripts/combine_bmarks.pl
new file mode 100644
index 0000000..b643649
--- /dev/null
+++ b/old/botan/doc/scripts/combine_bmarks.pl
@@ -0,0 +1,120 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+my %results;
+my %pk;
+
+my %pk_algos;
+my %algos;
+
+my %filename_to_desc;
+
+for my $filename (@ARGV) {
+
+ open IN, "<$filename" or die "Couldn't read $filename ($!)\n";
+
+ my $desc = <IN>;
+ chomp $desc;
+
+ $results{$desc} = {};
+
+ while(<IN>) {
+ if(/(.*): +(.*) Mbytes\/sec/) {
+ $results{$desc}{$1} = $2;
+ $algos{$1} = undef;
+ }
+ if(/(.*): (.*) ops \/ second \((.*)\)/) {
+ my $alg = "$1";
+ $alg = "$alg $3" if defined($3);
+ $pk{$desc}{$alg} = $2;
+ $pk_algos{$alg} = undef;
+ }
+ }
+}
+
+
+sub print_table {
+ my @columns = sort keys %results;
+
+ print "\n<P>All results are in MiB / second:\n";
+ print "<TABLE BORDER CELLSPACING=1>\n<THEAD>\n";
+
+ my %col_index = ();
+
+ my $line = "<TR><TH>Algorithm ";
+
+ foreach my $col (@columns) {
+ $col_index{$col} = length($line);
+ $line .= "<TH>" . $col . " ";
+ }
+
+ $line .= "\n<TBODY>\n";
+
+ print $line;
+
+ $line = '';
+
+ foreach my $algo (sort keys %algos) {
+ $line = " <TR><TH>$algo ";
+
+ for my $col (@columns) {
+ my $result = $results{$col}{$algo};
+ $result = "-" if not defined($result);
+
+ $result = "<TH>$result";
+
+ $line .= ' ' while(length($line) < ($col_index{$col}));
+ $line .= $result;
+
+ }
+
+ print $line, "\n";
+ $line = '';
+ }
+
+ print "</TABLE>\n";
+}
+
+
+sub print_pk_table {
+ my @columns = sort keys %pk;
+
+ print "\n<P>All results are in operations per second:\n";
+ print "<TABLE BORDER CELLSPACING=1>\n<THEAD>\n";
+
+ my %col_index = ();
+
+ my $line = "<TR><TH>Algorithm ";
+
+ foreach my $col (@columns) {
+ $col_index{$col} = length($line);
+ $line .= "<TH>" . $col . " ";
+ }
+
+ $line .= "\n<TBODY>\n";
+
+ print $line;
+
+ foreach my $algo (sort keys %pk_algos) {
+ my $line = " <TR><TH>$algo ";
+
+ for my $col (@columns) {
+ my $result = $pk{$col}{$algo};
+ $result = '-' if not defined($result);
+
+ $result = "<TH>$result";
+
+ $line .= ' ' while(length($line) < ($col_index{$col}));
+ $line .= $result;
+
+ }
+
+ print $line, "\n";
+ }
+
+ print "</TABLE>\n";
+}
+
+print_table();
+print_pk_table();
diff --git a/old/botan/doc/scripts/dist.sh b/old/botan/doc/scripts/dist.sh
new file mode 100644
index 0000000..9629446
--- /dev/null
+++ b/old/botan/doc/scripts/dist.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+
+# This is probably only useful if run on my machine, which is not
+# exactly ideal
+
+SELECTOR=h:net.randombit.botan.1_8
+KEY_ID=EFBADFBC
+MTN_DB=/storage/mtn/botan.mtn
+WEB_DIR=~/projects/www
+DIST_DIR=~/Botan-dist
+
+# You shouldn't have to change anything after this
+mkdir -p $DIST_DIR
+cd $DIST_DIR
+
+mtn -d $MTN_DB checkout -r $SELECTOR Botan
+
+VERSION=$(Botan/configure.py --version)
+
+mv Botan Botan-$VERSION
+
+cd Botan-$VERSION
+rm -rf _MTN
+rm -f .mtn-ignore
+
+# Build docs
+cd doc
+
+for doc in api tutorial building
+do
+ latex $doc.tex
+ latex $doc.tex
+ dvips $doc.dvi -o
+ pdflatex $doc.tex
+ pdflatex $doc.tex
+ cp $doc.pdf $DIST_DIR
+ mv $doc.ps $DIST_DIR
+ # Clean up after TeX
+ rm -f $doc.aux $doc.log $doc.dvi $doc.toc
+done
+
+cp log.txt ../..
+
+cd .. # topdir
+cd .. # now in DIST_DIR
+
+tar -cf Botan-$VERSION.tar Botan-$VERSION
+
+bzip2 -9 -k Botan-$VERSION.tar
+gzip -9 Botan-$VERSION.tar
+
+rm -rf Botan-$VERSION
+
+mv Botan-$VERSION.tar.gz Botan-$VERSION.tgz
+mv Botan-$VERSION.tar.bz2 Botan-$VERSION.tbz
+
+echo "*****************************************************"
+read -a PASSWORD -p "Enter PGP password (or ^C to skip signatures): "
+
+echo $PASSWORD | gpg --batch --armor -b --passphrase-fd 0 -u $KEY_ID Botan-$VERSION.tgz
+echo $PASSWORD | gpg --batch --armor -b --passphrase-fd 0 -u $KEY_ID Botan-$VERSION.tbz
+
+mv Botan-$VERSION.tgz* $WEB_DIR/files/botan/v1.8
+mv Botan-$VERSION.tbz* $WEB_DIR/files/botan/v1.8
diff --git a/old/botan/doc/scripts/primes.py b/old/botan/doc/scripts/primes.py
new file mode 100644
index 0000000..cf4d139
--- /dev/null
+++ b/old/botan/doc/scripts/primes.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+
+import sys
+
+def gcd(x,y):
+ if x <= 0 or y <= 0:
+ raise ValueError, "Arguments must be positive integers"
+ g = y
+ while x > 0:
+ g = x
+ x = y % x
+ y = g
+ return g
+
+
+def gen_primes():
+ primes = [2,3,5,7,11]
+
+ # Primes < 11351 fit into less than 256x64 bits
+ for i in xrange(1+primes[-1], 11351+1):
+ for prime in primes:
+ if gcd(i, prime) != 1:
+ break
+ else:
+ primes.append(i)
+
+ return primes
+
+def extract_product(primes):
+ product = 1
+
+ used = set()
+
+ for prime in sorted(primes, reverse=True):
+ if product * prime < 2**64:
+ product *= prime
+ used.add(prime)
+
+ primes -= used
+
+ return product
+
+def main():
+ primes = gen_primes()
+
+ primes.sort()
+ primes.reverse()
+
+ primes = set(primes)
+
+ while len(primes):
+ print "0x%016X, " % extract_product(primes)
+
+ #product = 1
+ #for prime in primes:
+ # product *= prime
+
+ # if product >= 2**64:
+ # print "%016X" % (product/prime)
+ # product = prime
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/old/botan/doc/scripts/print_deps.py b/old/botan/doc/scripts/print_deps.py
new file mode 100644
index 0000000..b92c433
--- /dev/null
+++ b/old/botan/doc/scripts/print_deps.py
@@ -0,0 +1,70 @@
+#!/usr/bin/python
+
+"""
+Analyze the botan source tree and print the module interdependencies
+
+(C) 2009 Jack Lloyd
+Distributed under the terms of the Botan license
+"""
+
+import os
+import os.path
+import sys
+import re
+
+def find_deps_in(filename):
+ # By convention #include's with spaces before them are
+ # always wrapped in #ifdef blocks
+ regexp = re.compile('^#include <botan/(.*)>')
+
+ for line in open(filename).readlines():
+ match = regexp.match(line)
+ if match != None:
+ yield match.group(1)
+
+def get_dependencies(dirname):
+ all_dirdeps = {}
+ file_homes = {}
+
+ is_sourcefile = re.compile('\.(cpp|h|S)$')
+
+ for (dirpath, dirnames, filenames) in os.walk('src'):
+ dirdeps = set()
+ for filename in filenames:
+ if is_sourcefile.search(filename) != None:
+ file_homes[filename] = os.path.basename(dirpath)
+
+ for dep in find_deps_in(os.path.join(dirpath, filename)):
+ if dep not in filenames and dep != 'build.h':
+ dirdeps.add(dep)
+
+ dirdeps = sorted(dirdeps)
+ if dirdeps != []:
+ all_dirdeps[dirpath] = dirdeps
+
+ return (all_dirdeps, file_homes)
+
+def main():
+ (all_dirdeps, file_homes) = get_dependencies('src')
+
+ def interesting_dep_for(dirname):
+ def interesting_dep(dep):
+ if dep == 'utils':
+ return False # everything depends on it
+
+ # block/serpent depends on block, etc
+ if dirname.find('/%s/' % (dep)) > 0:
+ return False
+ return True
+ return interesting_dep
+
+ for dirname in sorted(all_dirdeps.keys()):
+ depdirs = sorted(set(map(lambda x: file_homes[x], all_dirdeps[dirname])))
+
+ depdirs = filter(interesting_dep_for(dirname), depdirs)
+
+ if depdirs != []:
+ print "%s: %s" % (dirname, ' '.join(depdirs))
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/old/botan/doc/scripts/update_deps.py b/old/botan/doc/scripts/update_deps.py
new file mode 100644
index 0000000..61aa887
--- /dev/null
+++ b/old/botan/doc/scripts/update_deps.py
@@ -0,0 +1,41 @@
+#!/usr/bin/python
+
+import sys
+import re
+import os.path
+
+def update_requires(dir, deps):
+ lines = map(lambda x: x.strip(),
+ open(os.path.join(dir, 'info.txt')).readlines())
+
+ if '<requires>' in lines:
+ start = lines.index('<requires>')
+
+ while lines.pop(start) != '</requires>':
+ pass
+
+ while lines[-1] == '':
+ lines = lines[:-1]
+
+ if len(deps) > 0:
+ lines.append('')
+ lines.append('<requires>')
+ for dep in deps:
+ lines.append(dep)
+ lines.append('</requires>')
+ lines.append('')
+
+ lines = "\n".join(lines).replace("\n\n\n", "\n\n")
+
+ output = open(os.path.join(dir, 'info.txt'), 'w')
+ output.write(lines)
+ output.close()
+
+def main():
+ for line in sys.stdin.readlines():
+ (dirname, deps) = line.split(':')
+ deps = deps.strip().split(' ')
+ update_requires(dirname, deps)
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/old/botan/doc/thanks.txt b/old/botan/doc/thanks.txt
new file mode 100644
index 0000000..caa2fb5
--- /dev/null
+++ b/old/botan/doc/thanks.txt
@@ -0,0 +1,49 @@
+
+The following people (sorted alphabetically) contributed bug reports, useful
+information, or were generally just helpful people to talk to:
+
+Jeff B
+Rickard Bondesson
+Mike Desjardins
+Matthew Gregan
+Hany Greiss
+Friedemann Kleint
+Ying-Chieh Liao
+Dan Nicolaescu
+Vaclav Ovsik
+Ken Perano
+Darren Starsmore
+Kaushik Veeraraghavan
+Dominik Vogt
+James Widener
+
+Cerulean Studios, creators of the Trillian instant messaging client,
+has provided financial assistance to the project.
+
+Barry Kavanagh of AEP Systems Ltd kindly provided an AEP2000 crypto card and
+drivers, enabling the creation of Botan's AEP engine module.
+
+In addition, the following people have unknowingly contributed help:
+
+ Dean Gaudet <dean@arctic.org> wrote the SSE2 implementation of SHA-1
+
+ The implementation of DES is based off a public domain implementation by Phil
+ Karn from 1994 (he, in turn, credits Richard Outerbridge and Jim Gillogly).
+
+ Rijndael and Square are based on the reference implementations written by
+ the inventors, Joan Daemen and Vincent Rijmen.
+
+ The Serpent S-boxes used were discovered by Dag Arne Osvik and detailed in
+ his paper "Speeding Up Serpent".
+
+ Matthew Skala's public domain twofish.c (as given in GnuPG 0.9.8) provided
+ the basis for my Twofish code (particularly the key schedule).
+
+ Some of the hash functions (MD5, SHA-1, etc) use an optimized implementation
+ of one of the boolean functions, which was discovered by Colin Plumb.
+
+ The design of Randpool takes some of it's design principles from those
+ suggested by Eric A. Young in his SSLeay documentation, Peter Gutmann's paper
+ "Software Generation of Practically Strong Random Numbers", and the paper
+ "Cryptanalytic Attacks on Pseudorandom Number Generators", by Kelsey,
+ Schneier, Wagner, and Hall.
diff --git a/old/botan/doc/tutorial.pdf b/old/botan/doc/tutorial.pdf
new file mode 100644
index 0000000..2a68d62
--- /dev/null
+++ b/old/botan/doc/tutorial.pdf
Binary files differ
diff --git a/old/botan/doc/tutorial.tex b/old/botan/doc/tutorial.tex
new file mode 100644
index 0000000..9229cb8
--- /dev/null
+++ b/old/botan/doc/tutorial.tex
@@ -0,0 +1,883 @@
+\documentclass{article}
+
+\setlength{\textwidth}{6.5in} % 1 inch side margins
+\setlength{\textheight}{9in} % ~1 inch top and bottom margins
+
+\setlength{\headheight}{0in}
+\setlength{\topmargin}{0in}
+\setlength{\headsep}{0in}
+
+\setlength{\oddsidemargin}{0in}
+\setlength{\evensidemargin}{0in}
+
+\title{\textbf{Botan Tutorial}}
+\author{Jack Lloyd \\
+ \texttt{lloyd@randombit.net}}
+\date{2009/07/08}
+
+\newcommand{\filename}[1]{\texttt{#1}}
+\newcommand{\manpage}[2]{\texttt{#1}(#2)}
+
+\newcommand{\macro}[1]{\texttt{#1}}
+
+\newcommand{\function}[1]{\textbf{#1}}
+\newcommand{\type}[1]{\texttt{#1}}
+\renewcommand{\arg}[1]{\textsl{#1}}
+\newcommand{\variable}[1]{\textsl{#1}}
+
+\begin{document}
+
+\maketitle
+
+\tableofcontents
+
+\parskip=5pt
+\pagebreak
+
+\section{Introduction}
+
+This document essentially sets up various simple scenarios and then
+shows how to solve the problems using Botan. It's fairly simple, and
+doesn't cover many of the available APIs and algorithms, especially
+the more obscure or unusual ones. It is a supplement to the API
+documentation and the example applications, which are included in the
+distribution.
+
+To quote the Perl man page: '``There's more than one way to do it.''
+Divining how many more is left as an exercise to the reader.'
+
+This is \emph{not} a general introduction to cryptography, and most simple
+terms and ideas are not explained in any great detail.
+
+Finally, most of the code shown in this tutorial has not been tested, it was
+just written down from memory. If you find errors, please let me know.
+
+\section{Initializing the Library}
+
+The first step to using Botan is to create a \type{LibraryInitializer} object,
+which handles creating various internal structures, and also destroying them at
+shutdown. Essentially:
+
+\begin{verbatim}
+#include <botan/botan.h>
+/* include other headers here */
+
+int main()
+ {
+ LibraryInitializer init;
+ /* now do stuff */
+ return 0;
+ }
+\end{verbatim}
+
+\section{Hashing a File}
+
+\section{Symmetric Cryptography}
+
+\subsection{Encryption with a passphrase}
+
+Probably the most common crypto problem is encrypting a file (or some data that
+is in-memory) using a passphrase. There are a million ways to do this, most of
+them bad. In particular, you have to protect against weak passphrases,
+people reusing a passphrase many times, accidental and deliberate modification,
+and a dozen other potential problems.
+
+We'll start with a simple method that is commonly used, and show the problems
+that can arise. Each subsequent solution will modify the previous one to
+prevent one or more common problems, until we arrive at a good version.
+
+In these examples, we'll always use Serpent in Cipher-Block Chaining
+(CBC) mode. Whenever we need a hash function, we'll use SHA-256, since
+that is a common and well-known hash that is thought to be secure.
+
+In all examples, we choose to derive the Initialization Vector (IV) from the
+passphrase. Another (probably more common) alternative is to generate the IV
+randomly and include it at the beginning of the message. Either way is
+acceptable, and can be secure. The method used here was chosen to make for more
+interesting examples (because it's harder to get right), and may not be an
+appropriate choice for some environments.
+
+First, some notation. The passphrase is stored as a \type{std::string} named
+\variable{passphrase}. The input and output files (\variable{infile} and
+\variable{outfile}) are of types \type{std::ifstream} and \type{std::ofstream}
+(respectively).
+
+\subsubsection{First try}
+
+We hash the passphrase with SHA-256, and use the resulting hash to key
+Serpent. To generate the IV, we prepend a single '0' character to the
+passphrase, hash it, and truncate it to 16 bytes (which is Serpent's
+block size).
+
+\begin{verbatim}
+ HashFunction* hash = get_hash("SHA-256");
+
+ SymmetricKey key = hash->process(passphrase);
+ SecureVector<byte> raw_iv = hash->process('0' + passphrase);
+ InitializationVector iv(raw_iv, 16);
+
+ Pipe pipe(get_cipher("Serpent/CBC/PKCS7", key, iv, ENCRYPTION));
+
+ pipe.start_msg();
+ infile >> pipe;
+ pipe.end_msg();
+ outfile << pipe;
+\end{verbatim}
+
+\subsubsection{Problem 1: Buffering}
+
+There is a problem with the above code, if the input file is fairly large as
+compared to available memory. Specifically, all the encrypted data is stored
+in memory, and then flushed to \variable{outfile} in a single go at the very
+end. If the input file is big (say, a gigabyte), this will be most problematic.
+
+The solution is to use a \type{DataSink} to handle the output for us (writing
+to \arg{outfile} will be implicit with writing to the \type{Pipe}). We can do
+this by replacing the last few lines with:
+
+\begin{verbatim}
+ Pipe pipe(get_cipher("Serpent/CBC/PKCS7", key, iv, ENCRYPTION),
+ new DataSink_Stream(outfile));
+
+ pipe.start_msg();
+ infile >> pipe;
+ pipe.end_msg();
+\end{verbatim}
+
+\subsubsection{Problem 2: Deriving the key and IV}
+
+Hash functions like SHA-256 are deterministic; if the same passphrase
+is supplied twice, then the key (and in our case, the IV) will be the
+same. This is very dangerous, and could easily open the whole system
+up to attack. What we need to do is introduce a salt (or nonce) into
+the generation of the key from the passphrase. This will mean that the
+key will not be the same each time the same passphrase is typed in by
+a user.
+
+There is another problem with using a bare hash function to derive
+keys. While it's inconceivable (based on our current understanding of
+thermodynamics and theories of computation) that an attacker could
+brute-force a 256-bit key, it would be fairly simple for them to
+compute the SHA-256 hashes of various common passwords ('password',
+the name of the dog, the significant other's middle name, favorite
+sports team) and try those as keys. So we want to slow the attacker
+down if we can, and an easy way to do that is to iterate the hash
+function a bunch of times (say, 1024 to 4096 times). This will involve
+only a small amount of effort for a legitimate user (since they only
+have to compute the hashes once, when they type in their passphrase),
+but an attacker, trying out a large list of potential passphrases,
+will be seriously annoyed (and slowed down) by this.
+
+In this iteration of the example, we'll kill these two birds with one
+stone, and derive the key from the passphrase using a S2K (string to
+key) algorithm (these are also often called PBKDF algorithms, for
+Password-Based Key Derivation Function). In this example, we use
+PBKDF2 with Hash Message Authentication Code (HMAC(SHA-256)), which is
+specified in PKCS \#5. We replace the first four lines of code from
+the first example with:
+
+\begin{verbatim}
+ S2K* s2k = get_s2k("PBKDF2(SHA-256)");
+ // hard-coded iteration count for simplicity; should be sufficient
+ s2k->set_iterations(4096);
+ // 8 octets == 64-bit salt; again, good enough
+ s2k->new_random_salt(8);
+ SecureVector<byte> the_salt = s2k->current_salt();
+
+ // 48 octets == 32 for key + 16 for IV
+ SecureVector<byte> key_and_IV = s2k->derive_key(48, passphrase).bits_of();
+
+ SymmetricKey key(key_and_IV, 32);
+ InitializationVector iv(key_and_IV + 32, 16);
+\end{verbatim}
+
+To complete the example, we have to remember to write out the salt (stored in
+\variable{the\_salt}) at the beginning of the file. The receiving side needs to
+know this value in order to restore it (by calling the \variable{s2k} object's
+\function{change\_salt} function) so it can derive the same key and IV from the
+passphrase.
+
+\subsubsection{Problem 3: Protecting against modification}
+
+As it is, an attacker can undetectably alter the message while it is
+in transit. It is vital to remember that encryption does not imply
+authentication (except when using special modes that are specifically
+designed to provide authentication along with encryption, like OCB and
+EAX). For this purpose, we will append a message authentication code
+to the encrypted message. Specifically, we will generate an extra 256
+bits of key data, and use it to key the ``HMAC(SHA-256)'' MAC
+function. We don't want to have the MAC and the cipher to share the
+same key; that is very much a no-no.
+
+\begin{verbatim}
+ // 80 octets == 32 for cipher key + 16 for IV + 32 for hmac key
+ SecureVector<byte> keys_and_IV = s2k->derive_key(80, passphrase);
+
+ SymmetricKey key(keys_and_IV, 32);
+ InitializationVector iv(keys_and_IV + 32, 16);
+ SymmetricKey mac_key(keys_and_IV + 32 + 16, 32);
+
+ Pipe pipe(new Fork(
+ new Chain(
+ get_cipher("Serpent/CBC/PKCS7", key, iv, ENCRYPTION),
+ new DataSink_Stream(outfile)
+ ),
+ new MAC_Filter("HMAC(SHA-256)", mac_key)
+ )
+ );
+
+ pipe.start_msg();
+ infile >> pipe;
+ pipe.end_msg();
+
+ // now read the MAC from message #2. Message numbers start from 0
+ SecureVector<byte> hmac = pipe.read_all(1);
+ outfile.write((const char*)hmac.ptr(), hmac.size());
+\end{verbatim}
+
+The receiver can check the size of the file (in bytes), and since it knows how
+long the MAC is, can figure out how many bytes of ciphertext there are. Then it
+reads in that many bytes, sending them to a Serpent/CBC decryption object
+(which could be obtained by calling \verb|get_cipher| with an argument of
+\type{DECRYPTION} instead of \type{ENCRYPTION}), and storing the final bytes to
+authenticate the message with.
+
+\subsubsection{Problem 4: Cleaning up the key generation}
+
+The method used to derive the keys and IV is rather inelegant, and it would be
+nice to clean that up a bit, algorithmically speaking. A nice solution for this
+is to generate a master key from the passphrase and salt, and then generate the
+two keys and the IV (the cryptovariables) from that.
+
+Starting from the master key, we derive the cryptovariables using a KDF
+algorithm, which is designed, among other things, to ``separate'' keys so that
+we can derive several different keys from the single master key. For this
+purpose, we will use KDF2, which is a generally useful KDF function (defined in
+IEEE 1363a, among other standards). The use of different labels (``cipher
+key'', etc) makes sure that each of the three derived variables will have
+different values.
+
+\begin{verbatim}
+ S2K* s2k = get_s2k("PBKDF2(SHA-256)");
+ // hard-coded iteration count for simplicity; should be sufficient
+ s2k->set_iterations(4096);
+ // 8 octet == 64-bit salt; again, good enough
+ s2k->new_random_salt(8);
+ // store the salt so we can write it to a file later
+ SecureVector<byte> the_salt = s2k->current_salt();
+
+ SymmetricKey master_key = s2k->derive_key(48, passphrase);
+
+ KDF* kdf = get_kdf("KDF2(SHA-256)");
+
+ SymmetricKey key = kdf->derive_key(32, master_key, "cipher key");
+ SymmetricKey mac_key = kdf->derive_key(32, master_key, "hmac key");
+ InitializationVector iv = kdf->derive_key(16, master_key, "cipher iv");
+\end{verbatim}
+
+\subsubsection{Final version}
+
+Here is the final version of the encryption code, with all the changes we've
+made:
+
+\begin{verbatim}
+ S2K* s2k = get_s2k("PBKDF2(SHA-256)");
+ s2k->set_iterations(4096);
+ s2k->new_random_salt(8);
+ SecureVector<byte> the_salt = s2k->current_salt();
+
+ SymmetricKey master_key = s2k->derive_key(48, passphrase);
+
+ KDF* kdf = get_kdf("KDF2(SHA-256)");
+
+ SymmetricKey key = kdf->derive_key(32, master_key, "cipher key");
+ SymmetricKey mac_key = kdf->derive_key(32, masterkey, "hmac key");
+ InitializationVector iv = kdf->derive_key(16, masterkey, "cipher iv");
+
+ Pipe pipe(new Fork(
+ new Chain(
+ get_cipher("Serpent/CBC/PKCS7", key, iv, ENCRYPTION),
+ new DataSink_Stream(outfile)
+ ),
+ new MAC_Filter("HMAC(SHA-256)", mac_key)
+ )
+ );
+
+ outfile.write((const char*)the_salt.ptr(), the_salt.size());
+
+ pipe.start_msg();
+ infile >> pipe;
+ pipe.end_msg();
+
+ SecureVector<byte> hmac = pipe.read_all(1);
+ outfile.write((const char*)hmac.ptr(), hmac.size());
+\end{verbatim}
+
+\subsubsection{Another buffering technique}
+
+Sometimes the use of \type{DataSink\_Stream} is not practical for whatever
+reason. In this case, an alternate buffering mechanism might be useful. Here is
+some code which will write all the processed data as quickly as possible, so
+that memory pressure is reduced in the case of large inputs.
+
+\begin{verbatim}
+ pipe.start_msg();
+ SecureBuffer<byte, 1024> buffer;
+ while(infile.good())
+ {
+ infile.read((char*)buffer.ptr(), buffer.size());
+ u32bit got_from_infile = infile.gcount();
+ pipe.write(buffer, got_from_infile);
+
+ if(infile.eof())
+ pipe.end_msg();
+
+ while(pipe.remaining() > 0)
+ {
+ u32bit buffered = pipe.read(buffer, buffer.size());
+ outfile.write((const char*)buffer.ptr(), buffered);
+ }
+ }
+ if(infile.bad() || (infile.fail() && !infile.eof()))
+ throw Some_Exception();
+\end{verbatim}
+
+\pagebreak
+
+\subsection{Authentication}
+
+After doing the encryption routines, doing message authentication keyed off a
+passphrase is not very difficult. In fact it's much easier than the encryption
+case, for the following reasons: a) we only need one key, and b) we don't have
+to store anything, so all the input can be done in a single step without
+worrying about it taking up a lot of memory if the input file is large.
+
+In this case, we'll hex-encode the salt and the MAC, and output them both to
+standard output (the salt followed by the MAC).
+
+\begin{verbatim}
+ S2K* s2k = get_s2k("PBKDF2(SHA-256)");
+ s2k->set_iterations(4096);
+ s2k->new_random_salt(8);
+ OctetString the_salt = s2k->current_salt();
+
+ SymmetricKey hmac_key = s2k->derive_key(32, passphrase);
+
+ Pipe pipe(new MAC_Filter("HMAC(SHA-256)", mac_key),
+ new Hex_Encoder
+ );
+
+ std::cout << the_salt.to_string(); // hex encoded
+
+ pipe.start_msg();
+ infile >> pipe;
+ pipe.end_msg();
+ std::cout << pipe.read_all_as_string() << std::endl;
+\end{verbatim}
+
+\subsection{User Authentication}
+
+Doing user authentication off a shared passphrase is fairly easy. Essentially,
+a challenge-response protocol is used - the server sends a random challenge,
+and the client responds with an appropriate response to the challenge. The idea
+is that only someone who knows the passphrase can generate or check to see if a
+response is valid.
+
+Let's say we use 160-bit (20 byte) challenges, which seems fairly
+reasonable. We can create this challenge using the global random
+number generator (RNG):
+
+\begin{verbatim}
+ byte challenge[20];
+ Global_RNG::randomize(challenge, sizeof(challenge), Nonce);
+ // send challenge to client
+\end{verbatim}
+
+After reading the challenge, the client generates a response based on
+the challenge and the passphrase. In this case, we will do it by
+repeatedly hashing the challenge, the passphrase, and (if applicable)
+the previous digest. We iterate this construction 4096 times, to make
+brute force attacks on the passphrase hard to do. Since we are already
+using 160-bit challenges, a 160-bit response seems warranted, so we'll
+use SHA-1.
+
+\begin{verbatim}
+ HashFunction* hash = get_hash("SHA-1");
+ SecureVector<byte> digest;
+ for(u32bit j = 0; j != 4096; j++)
+ {
+ hash->update(digest, digest.size());
+ hash->update(passphrase);
+ hash->update(challenge, challenge.size());
+ digest = hash->final();
+ }
+ delete hash;
+ // send value of digest to the server
+\end{verbatim}
+
+Upon receiving the response from the client, the server computes what the
+response should have been based on the challenge it sent out, and the
+passphrase. If the two responses match, the client is authenticated.
+Otherwise, it is not.
+
+An alternate method is to use PBKDF2 again, using the challenge as the salt. In
+this case, the response could (for example) be the hash of the key produced by
+PBKDF2. There is no reason to have an explicit iteration loop, as PBKDF2 is
+designed to prevent dictionary attacks (assuming PBKDF2 is set up for a large
+iteration count internally).
+
+\pagebreak
+
+\section{Public Key Cryptography}
+
+\subsection{Basic Operations}
+
+In this section, we'll assume we have a \type{X509\_PublicKey*} named
+\arg{pubkey}, and, if necessary, a private key type (a
+\type{PKCS8\_PrivateKey*}) named \arg{privkey}. A description of these types,
+how to create them, and related details appears later in this tutorial. In this
+section, we will use various functions that are defined in
+\filename{look\_pk.h} -- you will have to include this header explicitly.
+
+\subsubsection{Encryption}
+
+Basically, pick an encoding method, create a \type{PK\_Encryptor} (with
+\function{get\_pk\_encryptor}()), and use it. But first we have to make sure
+the public key can actually be used for public key encryption. For encryption
+(and decryption), the key could be RSA, ElGamal, or (in future versions) some
+other public key encryption scheme, like Rabin or an elliptic curve scheme.
+
+\begin{verbatim}
+ PK_Encrypting_Key* key = dynamic_cast<PK_Encrypting_Key*>(pubkey);
+ if(!key)
+ error();
+ PK_Encryptor* enc = get_pk_encryptor(*key, "EME1(SHA-256)");
+
+ byte msg[] = { /* ... */ };
+
+ // will also accept a SecureVector<byte> as input
+ SecureVector<byte> ciphertext = enc->encrypt(msg, sizeof(msg));
+\end{verbatim}
+
+\subsubsection{Decryption}
+
+This is essentially the same as the encryption operation, but using a private
+key instead. One major difference is that the decryption operation can fail due
+to the fact that the ciphertext was invalid (most common padding schemes, such
+as ``EME1(SHA-256)'', include various pieces of redundancy, which are checked
+after decryption).
+
+\begin{verbatim}
+ PK_Decrypting_Key* key = dynamic_cast<PK_Decrypting_Key*>(privkey);
+ if(!key)
+ error();
+ PK_Decryptor* dec = get_pk_decryptor(*key, "EME1(SHA-256)");
+
+ byte msg[] = { /* ... */ };
+
+ SecureVector<byte> plaintext;
+
+ try {
+ // will also accept a SecureVector<byte> as input
+ plaintext = dec->decrypt(msg, sizeof(msg));
+ }
+ catch(Decoding_Error)
+ {
+ /* the ciphertext was invalid */
+ }
+\end{verbatim}
+
+\subsubsection{Signature Generation}
+
+There is one difficulty with signature generation that does not occur with
+encryption or decryption. Specifically, there are various padding methods which
+can be useful for different signature algorithms, and not all are appropriate
+for all signature schemes. The following table breaks down what algorithms
+support which encodings:
+
+\begin{tabular}{|c|c|c|} \hline
+Signature Algorithm & Usable Encoding Methods & Preferred Encoding(s) \\ \hline
+DSA / NR & EMSA1 & EMSA1 \\ \hline
+RSA & EMSA1, EMSA2, EMSA3, EMSA4 & EMSA3, EMSA4 \\ \hline
+Rabin-Williams & EMSA2, EMSA4 & EMSA2, EMSA4 \\ \hline
+\end{tabular}
+
+For new applications, use EMSA4 with both RSA and Rabin-Williams, as it is
+significantly more secure than the alternatives. However, most current
+applications/libraries only support EMSA2 with Rabin-Williams and EMSA3 with
+RSA. Given this, you may be forced to use less secure encoding methods for the
+near future. In these examples, we punt on the problem, and hard-code using
+EMSA1 with SHA-256.
+
+\begin{verbatim}
+ PK_Signing_Key* key = dynamic_cast<PK_Signing_Key*>(privkey);
+ if(!key)
+ error();
+ PK_Signer* signer = get_pk_signer(*key, "EMSA1(SHA-256)");
+
+ byte msg[] = { /* ... */ };
+
+ /*
+ You can also repeatedly call update(const byte[], u32bit), followed
+ by a call to signature(), which will return the final signature of
+ all the data that was passed through update(). sign_message() is
+ just a stub that calls update() once, and returns the value of
+ signature().
+ */
+
+ SecureVector<byte> signature = signer->sign_message(msg, sizeof(msg));
+\end{verbatim}
+
+\pagebreak
+
+\subsubsection{Signature Verification}
+
+In addition to all the problems with choosing the correct padding method,
+there is yet another complication with verifying a signature. Namely, there are
+two varieties of signature algorithms - those providing message recovery (that
+is, the value that was signed can be directly recovered by someone verifying
+the signature), and those without message recovery (the verify operation simply
+returns if the signature was valid, without telling you exactly what was
+signed). This leads to two slightly different implementations of the
+verification operation, which user code has to work with. As you can see
+however, the implementation is still not at all difficult.
+
+\begin{verbatim}
+ PK_Verifier* verifier = 0;
+
+ PK_Verifying_with_MR_Key* key1 =
+ dynamic_cast<PK_Verifying_with_MR_Key*>(pubkey);
+ PK_Verifying_wo_MR_Key* key2 =
+ dynamic_cast<PK_Verifying_wo_MR_Key*>(pubkey);
+
+ if(key1)
+ verifier = get_pk_verifier(*key1, "EMSA1(SHA-256)");
+ else if(key2)
+ verifier = get_pk_verifier(*key2, "EMSA1(SHA-256)");
+ else
+ error();
+
+ byte msg[] = { /* ... */ };
+ byte sig[] = { /* ... */ };
+
+ /*
+ Like PK_Signer, you can also do repeated calls to
+ void update(const byte some_data[], u32bit length)
+ followed by a call to
+ bool check_signature(const byte the_sig[], u32bit length)
+ which will return true (valid signature) or false (bad signature).
+ The function verify_message() is a simple wrapper around update() and
+ check_signature().
+
+ */
+ bool is_valid = verifier->verify_message(msg, sizeof(msg), sig, sizeof(sig));
+\end{verbatim}
+
+\subsubsection{Key Agreement}
+
+WRITEME
+
+\pagebreak
+
+\subsection{Working with Keys}
+
+\subsubsection{Reading Public Keys (X.509 format)}
+
+There are two separate ways to read X.509 public keys. Remember that the X.509
+public keys are simply that: public keys. There is no associated information
+(such as the owner of that key) included with the public key itself. If you
+need that kind of information, you'll need to use X.509 certificates.
+
+However, there are surely times when a simple public key is sufficient. The
+most obvious is when the key is implicitly trusted, for example if access
+and/or modification of it is controlled by something else (like filesystem
+ACLs). In other cases, it is a perfectly reasonable proposition to use them
+over the network as an anonymous key exchange mechanism. This is, admittedly,
+vulnerable to man-in-the-middle attacks, but it's simple enough that it's hard
+to mess up (see, for example, Peter Guttman's paper ``Lessons Learned in
+Implementing and Deploying Crypto Software'' in Usenix '02).
+
+The way to load a key is basically to set up a \type{DataSource} and then call
+\function{X509::load\_key}, which will return a \type{X509\_PublicKey*}. For
+example:
+
+\begin{verbatim}
+ DataSource_Stream somefile("somefile.pem"); // has 3 public keys
+ X509_PublicKey* key1 = X509::load_key(somefile);
+ X509_PublicKey* key2 = X509::load_key(somefile);
+ X509_PublicKey* key3 = X509::load_key(somefile);
+ // Now we have them all loaded. Huzah!
+\end{verbatim}
+
+At this point you can use \function{dynamic\_cast} to find the operations the
+key supports (by seeing if a cast to \type{PK\_Encrypting\_Key},
+\type{PK\_Verifying\_with\_MR\_Key}, or \type{PK\_Verifying\_wo\_MR\_Key}
+succeeds).
+
+There is a variant of \function{X509::load\_key} (and of
+\function{PKCS8::load\_key}, described in the next section) which take a
+filename (as a \type{std::string}). These are just convenience functions which
+create the appropriate \type{DataSource} for you and call the main
+\function{X509::load\_key}.
+
+\subsubsection{Reading Private Keys (PKCS \#8 format)}
+
+This is very similar to reading raw public keys, with the difference that the
+key may be encrypted with a user passphrase:
+
+\begin{verbatim}
+ // rng is a RandomNumberGenerator, like AutoSeeded_RNG
+
+ DataSource_Stream somefile("somefile");
+ std::string a_passphrase = /* get from the user */
+ PKCS8_PrivateKey* key = PKCS8::load_key(somefile, rng, a_passphrase);
+\end{verbatim}
+
+You can, by the way, convert a \type{PKCS8\_PrivateKey} to a
+\type{X509\_PublicKey} simply by casting it (with \function{dynamic\_cast}), as
+the private key type is derived from \type{X509\_PublicKey}. As with
+\type{X509\_PublicKey}, you can use \function{dynamic\_cast} to figure out what
+operations the private key is capable of; in particular, you can attempt to
+cast it to \type{PK\_Decrypting\_Key}, \type{PK\_Signing\_Key}, or
+\type{PK\_Key\_Agreement\_Key}.
+
+Sometimes you can get away with having a static passphrase passed to
+\function{load\_key}. Typically, however, you'll have to do some user
+interaction to get the appropriate passphrase. In that case you'll want to use
+the \type{UI} related interface, which is fully described in the API
+documentation.
+
+\subsubsection{Generating New Private Keys}
+
+Generate a new private key is the one operation which requires you to
+explicitly name the type of key you are working with. There are (currently) two
+kinds of public key algorithms in Botan: ones based on the integer
+factorization (IF) problem (RSA and Rabin-Williams), and ones based on the
+discrete logarithm (DL) problem (DSA, Diffie-Hellman, Nyberg-Rueppel, and
+ElGamal). Since discrete logarithm parameters (primes and generators) can be
+shared among many keys, there is the notion of these being a combined type
+(called \type{DL\_Group}).
+
+To create a new DL-based private key, simply pass a desired \type{DL\_Group} to
+the constructor of the private key - a new public/private key pair will be
+generated. Since in IF-based algorithms, the modulus used isn't shared by other
+keys, we don't use this notion. You can create a new key by passing in a
+\type{u32bit} telling how long (in bits) the key should be.
+
+There are quite a few ways to get a \type{DL\_Group} object. The best is to use
+the function \function{get\_dl\_group}, which takes a string naming a group; it
+will either return that group, if it knows about it, or throw an
+exception. Names it knows about include ``IETF-n'' where n is 768, 1024, 1536,
+2048, 3072, or 4096, and ``DSA-n'', where n is 512, 768, or 1024. The IETF
+groups are the ones specified for use with IPSec, and the DSA ones are the
+default DSA parameters specified by Java's JCE. For DSA and Nyberg-Rueppel, use
+the ``DSA-n'' groups, and for Diffie-Hellman and ElGamal, use the ``IETF-n''
+groups.
+
+You can also generate a new random group. This is not recommend, because it is
+very slow, particularly for ``safe'' primes, which are needed for
+Diffie-Hellman and ElGamal.
+
+Some examples:
+
+\begin{verbatim}
+ RSA_PrivateKey rsa1(512); // 512-bit RSA key
+ RSA_PrivateKey rsa2(2048); // 2048-bit RSA key
+
+ RW_PrivateKey rw1(1024); // 1024-bit Rabin-Williams key
+ RW_PrivateKey rw2(1536); // 1536-bit Rabin-Williams key
+
+ DSA_PrivateKey dsa(get_dl_group("DSA-512")); // 512-bit DSA key
+ DH_PrivateKey dh(get_dl_group("IETF-4096")); // 4096-bit DH key
+ NR_PrivateKey nr(get_dl_group("DSA-1024")); // 1024-bit NR key
+ ElGamal_PrivateKey elg(get_dl_group("IETF-1536")); // 1536-bit ElGamal key
+\end{verbatim}
+
+To export your newly created private key, use the PKCS \#8 routines in
+\filename{pkcs8.h}:
+
+\begin{verbatim}
+ std::string a_passphrase = /* get from the user */
+ std::string the_key = PKCS8::PEM_encode(rsa2, a_passphrase);
+\end{verbatim}
+
+You can read the key back in using \function{PKCS8::load\_key}, described in
+the section ``Reading Private Keys (PKCS \#8 format)'', above. Unfortunately,
+this only works with keys that have an assigned algorithm identifier and
+standardized format. Currently this is only the RSA, DSA, DH, and ElGamal
+algorithms, though RW and NR keys can also be imported and exported by
+assigning them an OID (this can be done either through a configuration file, or
+by calling the function \function{OIDS::add\_oid} in \filename{oids.h}). Be
+aware that the OID and format for ElGamal keys is not exactly standard, but
+there does exist at least one other crypto library which will accept the
+format.
+
+The raw public can be exported using:
+
+\begin{verbatim}
+ std::string the_public_key = X509::PEM_encode(rsa2);
+\end{verbatim}
+
+\pagebreak
+
+\section{X.509v3 Certificates}
+
+Using certificates is rather complicated, so only the very basic mechanisms are
+going to be covered here. The section ``Setting up a CA'' goes into reasonable
+detail about CRLs and certificate requests, but there is a lot that isn't
+covered (else this section would get quite long and complicated).
+
+\subsection{Importing and Exporting Certificates}
+
+Importing and exporting X.509 certificates is easy. Simply call the constructor
+with either a \type{DataSource\&}, or the name of a file:
+
+\begin{verbatim}
+ X509_Certificate cert1("cert1.pem");
+
+ /* This file contains two certificates, concatenated */
+ DataSource_Stream in("certs2_and_3.pem");
+
+ X509_Certificate cert2(in); // read the first cert
+ X509_Certificate cert3(in); // read the second cert
+\end{verbatim}
+
+Exporting the certificate is a simple matter of calling the member function
+\function{PEM\_encode}(), which returns a \type{std::string} containing the
+certificate in PEM encoding.
+
+\begin{verbatim}
+ std::cout << cert3.PEM_encode();
+ some_ostream_object << cert1.PEM_encode();
+ std::string cert2_str = cert2.PEM_encode();
+\end{verbatim}
+
+\subsection{Verifying Certificates}
+
+Verifying a certificate requires that we build up a chain of trust, starting
+from the root (usually a commercial CA), down through some number of
+intermediate CAs, and finally reaching the actual certificate in
+question. Thus, to verify, we actually have to have all those certificates
+on hand (or at the very least, know where we can get the ones we need).
+
+The class which handles both storing certificates, and verifying them, is
+called \type{X509\_Store}. We'll start by assuming that we have all the
+certificates we need, and just want to verify a cert. This is done by calling
+the member function \function{validate\_cert}, which takes the
+\type{X509\_Certificate} in question, and an optional argument of type
+\type{Cert\_Usage} (which is ignored here; read the section in the API doc
+titled ``Verifying Certificates for information). It returns an enum;
+\type{X509\_Code}, which, for most purposes, is either \type{VERIFIED}, or
+something else (which specifies what circumstance caused the certificate to be
+considered invalid). Really, that's it.
+
+Now, how to let \type{X509\_Store} know about all those certificates and CRLs
+we have lying around? The simplest method is to add them directly, using the
+functions \function{add\_cert}, \function{add\_certs},
+\function{add\_trusted\_certs}, and \function{add\_crl}; for details, consult
+the API doc or read the \filename{x509stor.h} header. There is also a much more
+elegant and powerful method: \type{Certificate\_Store}s. A certificate store
+refers to an object that knows how to retrieve certificates from some external
+source (a file, an LDAP directory, a HTTP server, a SQL database, or anything
+else). By calling the function \function{add\_new\_certstore}, you can register
+a new certificate store, which \type{X509\_Store} will use to find certificates
+it needs. Thus, you can get away with only adding whichever root CA cert(s) you
+want to use, letting some online source handle the storage of all intermediate
+X.509 certificates. The API documentation has a more complete discussion of
+\type{Certificate\_Store}.
+
+\subsection{Setting up a CA}
+
+WRITEME
+
+\pagebreak
+
+\section{Special Topics}
+
+This chapter is for subjects that don't really fit into the API documentation
+or into other chapters of the tutorial.
+
+\subsection{GUIs}
+
+There is nothing particularly special about using Botan in a GUI-based
+application. However there are a few tricky spots, as well as a few ways to
+take advantage of an event-based application.
+
+\subsubsection{Initialization}
+
+Generally you will create the \type{LibraryInitializer} somewhere in
+\texttt{main}, before entering the event loop. One problem is that some GUI
+libraries take over \texttt{main} and drop you right into the event loop; the
+question then is how to initialize the library? The simplest way is probably to
+have a static flag that marks if you have already initialized the library or
+not. When you enter the event loop, check to see if this flag has not been set,
+and if so, initialize the library using the function-based initializers. Using
+\type{LibraryInitializer} obviously won't work in this case, since it would be
+destroyed as soon as the current event handler finished. You then deinitialize
+the library whenever your application is signaled to quit.
+
+\subsubsection{Interacting With the Library}
+
+In the simple case, the user will do stuff asynchronously, and then in response
+your code will do things like encrypt a file or whatever, which can all be done
+synchronously, since the data is right there for you. An application doing
+something like this is basically going to look exactly like a command line
+application that uses Botan, the only major difference being that the calls to
+the library are inside event handlers.
+
+Much harder is something like an SSH client, where you're acting as a layer
+between two asynchronous things (the user and the network). This actually isn't
+restricted to GUIs at all (text-mode SSH clients have to deal with most of the
+same problems), but it is probably more common with a GUI app. The following
+discussion is fairly vague, but hopefully somewhat useful.
+
+There are a few facilities in Botan that are primarily designed to be used by
+applications based on an event loop. See the section ``User Interfaces'' in the
+main API doc for details.
+
+\subsubsection{Entropy}
+
+One nice advantage of using a GUI is opening a new method of gathering entropy
+for the library. This is especially handy on Windows, where the available
+sources of entropy are pretty questionable. In many versions,
+\texttt{CryptGenRandom} is really rather poor, and the Toolhelp functions may
+not provide much data on a small system (such as a handheld). For example, in
+GTK+, you can use the following callback to get information about mouse
+movements:
+
+\begin{verbatim}
+static gint add_entropy(GtkWidget* widget, GdkEventMotion* event)
+ {
+ if(event)
+ Global_RNG::add_entropy(event, sizeof(GdkEventMotion));
+ return FALSE;
+ }
+\end{verbatim}
+
+And then register it with your main GTK window (presumably named
+\variable{window}) as follows:
+
+\begin{verbatim}
+gtk_signal_connect(GTK_OBJECT(window), "motion_notify_event",
+ GTK_SIGNAL_FUNC(add_entropy), NULL);
+
+gtk_widget_set_events(window, GDK_POINTER_MOTION_MASK);
+\end{verbatim}
+
+Even though we're catching all mouse movements, and hashing the results into
+the entropy pool, this doesn't use up more than a few percent of even a
+relatively slow desktop CPU. Note that in the case of using X over a network,
+catching all mouse events would cause large amounts of X traffic over the
+network, which might make your application slow, or even unusable (I haven't
+tried it, though).
+
+This could be made nicer if the collection function did something like
+calculating deltas between each run, storing them into a buffer, and then when
+enough of them have been added, hashing them and send them all to the PRNG in
+one shot. This would not only reduce load, but also prevent the PRNG from
+overestimating the amount of entropy it's getting, since its estimates don't
+(can't) take history into account. For example, you could move the mouse back
+and forth one pixel, and the PRNG would think it was getting a full load of
+entropy each time, when actually it was getting (at best) a bit or two.
+
+\end{document}