diff options
Diffstat (limited to 'doc')
94 files changed, 5443 insertions, 12326 deletions
diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 000000000..152fa3e09 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,60 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html singlehtml latex latexpdf text man + +help: + @echo "Please use \`make <target>' where <target> is one of" + @echo " html to make standalone HTML files" + @echo " singlehtml to make a single large HTML file" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + make -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." diff --git a/doc/algos.txt b/doc/algos.txt new file mode 100644 index 000000000..0221405d6 --- /dev/null +++ b/doc/algos.txt @@ -0,0 +1,78 @@ +Algorithms +================================= + +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. + + - Block ciphers: AES or Serpent in CBC, CTR, or XTS mode + + - Hash functions: SHA-256, SHA-512 + + - MACs: HMAC with any recommended hash function + + - Public Key Encryption: RSA with "EME1(SHA-256)" + + - Public Key Signatures: RSA with EMSA4 and any recommended + hash, or DSA or ECDSA with "EMSA1(SHA-256)" + + - Key Agreement: Diffie-Hellman or ECDH, with "KDF2(SHA-256)" + +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. 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 +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. 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' ``name`` function returns (the names tend to +match that in SCAN, if it's defined there). + + - ROUNDS: The number of rounds in a block cipher. + - OUTSZ: The output size of a hash function or MAC + +**Block Ciphers:** "AES-128", "AES-192", "AES-256", "Blowfish", +"CAST-128", "CAST-256", "DES", "DESX", "TripleDES", "GOST-28147-89", +"IDEA", "KASUMI", "MARS", "MISTY1(ROUNDS)", "Noekeon", "RC2", +"RC5(ROUNDS)", "RC6", "SAFER-SK(ROUNDS)", "SEED", "Serpent", +"Skipjack", "Square", "TEA", "Twofish", "XTEA" + +**Stream Ciphers:** "ARC4", "MARK4", "Salsa20", "Turing", +"WiderWake4+1-BE" + +**Hash Functions:** "HAS-160", "GOST-34.11", "MD2", "MD4", "MD5", +"RIPEMD-128", "RIPEMD-160", "SHA-160", "SHA-256", "SHA-384", +"SHA-512", "Skein-512", "Tiger(OUTSZ)", "Whirlpool" + +**MACs:** "HMAC(HASH)", "CMAC(BLOCK)", "X9.19-MAC" diff --git a/doc/api.tex b/doc/api.tex deleted file mode 100644 index 434b717e4..000000000 --- a/doc/api.tex +++ /dev/null @@ -1,2959 +0,0 @@ -\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 Reference Manual}} -\author{} -\date{2010/06/14} - -\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{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 at least one and -ideally all of these books before seriously using the library. - -\setlength{\parskip}{5pt} - -\noindent -\textit{Cryptography Engineering}, Niels Ferguson, Bruce Schneier, and -Tadayoshi Kohno; Wiley - -\noindent -\textit{Security Engineering -- A Guide to Building Dependable - Distributed Systems}, Ross Anderson; Wiley - -\noindent -\textit{Handbook of Applied Cryptography}, Alfred J. Menezes, -Paul C. Van Oorschot, and Scott A. Vanstone; CRC Press (available -online at \url{http://www.cacr.math.uwaterloo.ca/hac/}) - -\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. Given the choice -between optimizing for 32-bit systems and 64-bit systems, Botan is -written to prefer 64-bit, on the theory that where performance is a -real concern, modern 64-bit processors are the obvious choice. - -Smaller handhelds, set-top boxes, and the bigger smart phones and smart -cards, are also capable of using Botan. However, Botan uses a -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 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 ask Botan -if the algorithm exists, and if Botan says yes, ask the library to -give them such an object for that algorithm. - -\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 \keyword{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 (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 if you wish to share a -single object between threads. - -If you do not create a \type{LibraryInitializer} object, all library -operations will fail, because it will be unable to do basic things -like allocate memory or get random bits. You should never create more -than one \type{LibraryInitializer}. - -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; in many C++ runtimes, these -objects will be destroyed after main has returned. - -Botan's memory object classes (\type{MemoryRegion}, -\type{MemoryVector}, \type{SecureVector}) are extremely primitive, and -meant only for secure storage of potentially sensitive data like -keys. They do not meet the requirements for an STL container object -and you should not try to use them with STL algorithms. For a -general-purpose container, use \type{std::vector}. - -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. 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. - -Botan has about 40 filters that perform different operations on data. -Here's code that uses one of them to encrypt a string with AES: - -\begin{verbatim} - AutoSeeded_RNG rng, - SymmetricKey key(rng, 16); // a random 128-bit key - InitializationVector iv(rng, 16); // a random 128-bit IV - - // 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 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}() 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, 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 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. Make sure you're including the header \filename{lookup.h}, and -then call \function{get\_cipher}. You will pass the return value -directly into a \type{Pipe}. There are a couple different functions -which do varying levels of initialization: - -\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}. - -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: ``AES-128/CBC'', -``Blowfish/CTR-BE'', ``Serpent/XTS'', and ``AES-256/EAX''. - -``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 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 much the -same in terms of dataflow - ach 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 the entire input as a -single blob 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 -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. 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 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 -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. The filter should finish up with whatever computation it -is 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. - -Additionally, if necessary, filters can define a constructor that -takes any needed arguments, and a destructor to deal with deallocating -memory, closing files, etc. - -\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<Public_Key> 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 three kinds of public key algorithms in Botan: -ones based on integer factorization (RSA and Rabin-Williams), ones -based on the discrete logarithm problem in the integers modulo a prime -(DSA, Diffie-Hellman, Nyberg-Rueppel, and ElGamal), and ones based on -the discrete logarithm problem in an elliptic curve (ECDSA, ECDH, GOST -34.10). The systems based on discrete logarithms (in either regular -integers or elliptic curves) use a group (a mathematical term), which -can be shared among many keys. An elliptic curve group is represented -by the class \type{EC\_Domain\_Params}, while a modulo-prime group is -represented by a \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 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 necessary for security). To get an -object that knows how to do padding, use the wrapper classes included -in \filename{pubkey.h}. These take a key, along with a string that -specifies 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). - -\begin{verbatim} - // PKCS #1 v2.0 / IEEE 1363 compatible encryption - PK_Encryptor_EME rsa_enc_pkcs1_v2(rsakey, "EME1(SHA-1)"); - // PKCS #1 v1.5 compatible encryption - PK_Encryptor_EME rsa_enc_pkcs1_v15(rsakey, "PKCS1v15") - - // This object can decrypt things encrypted by rsa_ - PK_Decryptor_EME rsa_dec_pkcs1_v2(rsakey, "EME1(SHA-1)"); - - // PKCS #1 v1.5 compatible signatures - PK_Signer rsa_sign_pkcs1_v15(rsakey, "EMSA3(MD5)"); - PK_Verifier rsa_verify_pkcs1_v15(rsakey, "EMSA3(MD5)"); - - // PKCS #1 v2.1 compatible signatures - PK_Signer rsa_sign_pkcs1_v2(rsakey, "EMSA4(SHA-1)"); - PK_Verifier rsa_verify_pkcs1_v2(rsakey, "EMSA4(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. You -can call \function{maximum\_input\_size} to find out the maximum size -input (in bytes) that you can safely use with any particular key. - -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, -ECDSA, GOST-34.11, 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. The Raw encoding 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, ECDSA, GOST-34.11, 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 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 KDF you're using, you \emph{might not} get back a key -of the size you requested. 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 { - MemoryVector<byte> BER_encode(const Public_Key& key); - std::string PEM_encode(const Public_Key& out); - - Public_Key* load_key(DataSource& in); - Public_Key* load_key(const SecureVector<byte>& buffer); -} -\end{verbatim} - -The function \function{X509::BER\_encode} will take any -\type{Public\_Key} and return a standard binary structure representing -the key which can be read by many other crypto libraries. - -The function \function{X509::PEM\_encode} does the same, but -additionally formats it into a text format with headers and base64 -encoding. Using 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. - -For loading a public key, use 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 create~--~the others are simple wrapper functions that take -either a filename or a memory buffer. - -Here's an example of loading a public key and then encrypting with it: - -\begin{verbatim} - /* Might be RSA, might be ElGamal, might be ... */ - Public_Key* key = X509::load_key("pubkey.asc"); - - /* This might throw an exception if the key doesn't support any - encryption operations - */ - - PK_Encryptor_EME encryptor(*key, "EME1(SHA-1)"); - - SecureVector<byte> ciphertext = encryptor.encrypt(msg, size_of_msg); -\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 { - SecureVector<byte> BER_encode(const Private_Key& key); - std::string PEM_encode(const Private_Key& key); -} -\end{verbatim} - -These functions are similiar to the X.509 functions described -previously. The only difference is that they take a -\type{Private\_Key} object instead. 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 -store the whole thing into another structure. This method is -definitely preferred, since otherwise the private key is -unprotected. The algorithms and structures used here are standardized -by PKCS \#5 and PKCS \#8, and can be read by many other crypto -libraries. - -\begin{verbatim} -namespace PKCS8 { - SecureVector<byte> BER_encode(const Private_Key& key, - RandomNumberGenerator& rng, - const std::string& pass, - const std::string& pbe_algo = ""); - - std::string PEM_encode(const Private_Key& key, - RandomNumberGenerator& rng, - const std::string& pass, - const std::string& pbe_algo = ""); -} -\end{verbatim} - -There are three new arguments needed here to support the encryption -process in addition to the private key itself. The first is a -\type{RandomNumberGenerator}, which is needed for various purposes -internally. The \arg{pass} argument is the passphrase that will be -used to encrypt the key. Both of these are required. The final -(optional) argument is \arg{pbe}; this specifies a particular password -based encryption (or PBE) algorithm. If you don't specify a PBE, -a compiled in default will be used; this should be fine. - -Last but not least, there are some functions that will load (and -decrypt, if necessary) a PKCS \#8 private key: - -\begin{verbatim} -namespace PKCS8 { - Private_Key* load_key(DataSource& in, - RandomNumberGenerator& rng, - const User_Interface& ui); - - Private_Key* load_key(DataSource& in, - RandomNumberGenerator& rng, - std::string passphrase = ""); - - Private_Key* load_key(const std::string& filename, - RandomNumberGenerator& rng, - const User_Interface& ui); - - Private_Key* 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 implemented, and provides for much more -flexibility. If the passphrase passed in is not correct, then an -exception is thrown and that is that. However, if you pass in an UI -object, 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 rather -dumb, and acts rather like the versions taking the \type{std::string}; -it tries the passphrase passed in first, and then it cancels. - -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} the object 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). - -\section{Certificate Handling} - -A certificate is a binding between some identifying information -(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 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, 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{Public\_Key*}. 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, an organizational sub-unit name, 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 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 -likely never want to use). However, there are three very useful pieces -of information that this extension might hold: an email address -(``[email protected]''), a DNS name (``somehost.site2.com''), or a URI -(``http://www.site3.com''). - -So, how to get the information? 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. - -\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). Every once in a while the -CA will release a new 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 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}. - -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 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 -normally 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 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}) - -This function will return \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 mostly undocumented) method for marking certificates for code -signing. - -First, how does it know if a certificate is valid? 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 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 usually what you want; 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 perhaps 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 Private_Key& key); -\end{verbatim} - -The private key is the private key corresponding to the public key in the -CA's certificate. - -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. A request is vetted by humans (who somehow -verify that the name in the request corresponds to the name of the -entity 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. Never fear; empty CRLs, which revoke nothing at all, can -be issued. 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. The library provides a utility function for this: - -\begin{verbatim} -namespace X509 { - X509_Certificate create_self_signed_cert(const X509_Cert_Options& opts, - const Private_Key& 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 Private_Key&); -} -\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} - -What is this \type{X509\_Cert\_Options} thing we've been passing -around? It's a class representing 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 just 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. - -\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. The object will look and behave 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 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 copies its input. - -\subsection{Symmetrically Keyed Algorithms} - -Block ciphers, stream ciphers, and MACs are all keyed operations; to -be useful, they have to be set to use a particular key, which is a -randomly chosen string of bits of a specified length. The length -required by any particular algorithm may vary, depending on both the -algorithm specification and the implementation. You can query any -botan object to find out what key length(s) it supports. - -To make this similarity in terms of keying 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 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 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}[], - \type{byte} \arg{out}[]) const - -\noindent -\type{void} \function{encrypt}(\type{byte} \arg{block}[]) 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}). Exactly one block will be -encrypted; you can find out the block size of the cipher you are -working with by calling the member function \function{block\_size}. -\type{BlockCipher}s have similar functions \function{decrypt}, which -perform the inverse operation. - -If you want to process multiple blocks in parallel, use -\function{encrypt\_n} and \function{decrypt\_n}. - -\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{size\_t} \function{output\_length}() - -Return the size of the output of this function. - -\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}[]) - -\noindent -\type{SecureVector<byte>} \function{final}(): - -Complete the hash/MAC calculation and place the result into \arg{out}. -For the argument taking an array, exactly \function{output\_length}() -bytes will be written. 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. - -There is also a pair of functions called \function{process}. They are -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 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. - -\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 ethe 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 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 -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 entropy. - -\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. - -\begin{verbatim} - std::string get_passphrase(const std::string& what, - const std::string& source, - UI_Result& result) const; -\end{verbatim} - -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. - -\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 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 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 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. The CAPI RNG is usually a -default software-based PRNG, but there are a few providers 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 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 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. 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 be used. - -\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 PBKDF -algorithms, have a wide degree of applicability. - -\subsection{PBKDF Algorithms} - -There are various procedures (usually 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{pbkdf.h}. The main function is \function{derive\_key}, which -takes a passphrase, a salt, an iteration count, and the desired length -of the output key, and returns a key of that length, deterministically -produced from the passphrase and salt. 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). - -The purpose of the iteration count is to make the algorithm take -longer to compute the final key (reducing the speed of brute-force -attacks of various kinds). Most standards recommend an iteration count -of at least 10000. Currently defined PBKDF algorithms are -``PBKDF1(digest)'', ``PBKDF2(digest)'', and ``OpenPGP-S2K(digest)''; -you can retrieve any of these using the \function{get\_pbkdf}, found in -\filename{lookup.h}. As of this writing, ``PBKDF2(SHA-256)'' with -10000 iterations and a 16 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, 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{Password Hashing} - -Storing passwords for user authentication purposes in plaintext is the -simplest but least secure method; when an attacker compromises the -database in which the passwords are stored, they immediately gain -access to all of them. Often passwords are reused among multiple -services or machines, meaning once a password to a single service is -known an attacker has a substantial head start on attacking other -machines. - -The general approach is to store, instead of the password, the output -of a one way function of the password. Upon receiving an -authentication request, the authenticator can recompute the one way -function and compare the value just computed with the one that was -stored. If they match, then the authentication request succeeds. But -when an attacker gains access to the database, they only have the -output of the one way function, not the original password. - -Common hash functions such as SHA-256 are one way, but used alone they -have problems for this purpose. What an attacker can do, upon gaining -access to such a stored password database, is hash common dictionary -words and other possible passwords, storing them in a list. Then he -can search through his list; if a stored hash and an entry in his list -match, then he has found the password. Even worse, this can happen -\emph{offline}: an attacker can begin hashing common passwords days, -months, or years before ever gaining access to the database. In -addition, if two users choose the same password, the one way function -output will be the same for both of them, which will be visible upon -inspection of the database. - -There are two solutions to these problems: salting and -iteration. Salting refers to including, along with the password, a -randomly chosen value which perturbs the one way function. Salting can -reduce the effectivness of offline dictionary generation (because for -each potential password, an attacker would have to compute the one way -function output for all possible salts - with a large enough salt, -this can make the problem quite difficult). It also prevents the same -password from producing the same output, as long as the salts do not -collide. With a large salt (say 80 to 128 bits) this will be quite -unlikely. Iteration refers to the general technique of forcing -multiple one way function evaluations when computing the output, to -slow down the operation. For instance if hashing a single password -requires running SHA-256 100,000 times instead of just once, that will -slow down user authentication by a factor of 100,000, but user -authentication happens quite rarely, and usually there are more -expensive operations that need to occur anyway (network and database -I/O, etc). On the other hand, an attacker who is attempting to break a -database full of stolen password hashes will be seriously -inconvenienced by a factor of 100,000 slowdown; they will be able to -only test at a rate of .0001\% of what they would without iterations -(or, equivalently, will require 100,000 times as many zombie botnet -hosts). - -There are many different ways of doing this password hashing -operation, with common ones including Unix's crypt (which is based on -DES) and OpenBSD's bcrypt (based on Blowfish). Other variants using -MD5 or SHA-256 are also in use on various systems. - -Botan provides a technique called passhash9, in -\filename{passhash9.h}, which is based on PBKDF2. Two functions are -provided in this header, \function{generate\_passhash9} and -\function{check\_passhash9}. The generate function takes the password -to hash, a \type{RandomNumberGenerator}, and a work factor, which -tells how many iterations to compute. The default work factor is 10 -(which means 100,000 iterations), but any non-zero value is accepted. -The check function takes a password and a passhash9 output and checks -if the password is the same as the one that was used to generate the -passhash9 output, returning a boolean true (same) or false (not same). -An example can be found in \filename{doc/examples/passhash.cpp}. - -Passhash9 currently uses HMAC(SHA-1) for the underlying PBKDF2 -psuedo-random function, but can be extended to use different -algorithms in the future if necessary. For instance using a PRF based -on Blowfish (a block cipher that requires 4 KiB of RAM for efficient -execution) could be used to make hardware-based password cracking more -expensive (this was one motivation for Blowfish's use in the bcrypt -hashing scheme, in fact). - -\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. - -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}. Code needing -to allocate or deallocate memory calls \function{get\_allocator}, -which returns a pointer to an allocator object. This pointer should -not be freed: the caller does not own the allocator (it is shared -among multiple allocatore users, and uses a mutex to serialize access -internally if necessary). 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. - -\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 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 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. - -\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, CTR, or XTS 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 or ECDSA with ``EMSA1(SHA-256)'' - - \item Key Agreement: Diffie-Hellman or ECDH, with ``KDF2(SHA-256)'' -\end{list} - -\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. 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. 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 -\end{list} - -\vskip .05in -\noindent -\textbf{Block Ciphers:} ``AES'' (and ``AES-128'', ``AES-192'', and -``AES-256''), ``Blowfish'', ``CAST-128'', ``CAST-256'', ``DES'', -``DESX'', ``TripleDES'', ``GOST-28147-89'', ``IDEA'', ``KASUMI'', -``MARS'', ``MISTY1(ROUNDS)'', ``Noekeon'', ``RC2'', ``RC5(ROUNDS)'', -``RC6'', ``SAFER-SK(ROUNDS)'', ``SEED'', ``Serpent'', ``Skipjack'', -``Square'', ``TEA'', ``Twofish'', ``XTEA'' - -\noindent -\textbf{Stream Ciphers:} ``ARC4'', ``MARK4'', ``Salsa20'', ``Turing'', -``WiderWake4+1-BE'' - -\noindent -\textbf{Hash Functions:} ``HAS-160'', ``GOST-34.11'', -``MD2'', ``MD4'', ``MD5'', ``RIPEMD-128'', ``RIPEMD-160'', -``SHA-160'', ``SHA-256'', ``SHA-384'', ``SHA-512'', ``Skein-512'', -``Tiger(OUTSZ)'', ``Whirlpool'' - -\noindent -\textbf{MACs:} ``HMAC(HASH)'', ``CMAC(BLOCK)'', ``X9.19-MAC'' - -\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{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 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.txt}; -PGP keys for the developers are also stored there. - -\vskip 5pt \noindent -Web Site: \url{http://botan.randombit.net} - -\subsection{License} - -Copyright \copyright 2000-2010, Jack Lloyd - -Licensed under the same terms as the Botan source - -\end{document} diff --git a/doc/bigint.txt b/doc/bigint.txt new file mode 100644 index 000000000..1cdc685d3 --- /dev/null +++ b/doc/bigint.txt @@ -0,0 +1,64 @@ +BigInt +======================================== + +``BigInt`` is Botan's implementation of a multiple-precision +integer. Thanks to C++'s operator overloading features, using ``BigInt`` is +often quite similar to using a native integer type. The number of functions +related to ``BigInt`` is quite large. You can find most of them in +``botan/bigint.h`` and ``botan/numthry.h``. + +Probably the most important are the encoding/decoding functions, which +transform the normal representation of a ``BigInt`` into some other +form, such as a decimal string. + +.. cpp:function:: SecureVector<byte> BigInt::encode(const BigInt& n, Encoding enc = Binary) + + This function encodes the BigInt n into a memory + vector. ``Encoding`` is an enum that has values ``Binary``, + ``Octal``, ``Decimal``, and ``Hexadecimal``. + +.. cpp:function:: BigInt BigInt::decode(const MemoryRegion<byte>& vec, Encoding enc) + + Decode the integer from ``vec`` using the encoding specified. + +These functions are static member functions, so they would be called +like this:: + + BigInt n1 = ...; // some number + SecureVector<byte> n1_encoded = BigInt::encode(n1); + BigInt n2 = BigInt::decode(n1_encoded); + assert(n1 == n2); + +There are also C++-style I/O operators defined for use with +``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. + +``BigInt`` has constructors that can create a ``BigInt`` from an +unsigned integer or a string. You can also decode an array (a ``byte`` +pointer plus a length) into a ``BigInt`` using a constructor. + +Efficiency Hints +---------------------------------------- + +If you can, always use expressions of the form ``a += b`` over +``a = a + b``. The difference can be *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 ``BarrettReducer`` ahead of time. If the exponent or base is a constant, +use the classes in ``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 +``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 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. diff --git a/doc/building.tex b/doc/building.tex deleted file mode 100644 index 7164f74eb..000000000 --- a/doc/building.tex +++ /dev/null @@ -1,444 +0,0 @@ -\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{[email protected]}} -\date{2010-06-10} - -\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.py, which is a Python -script. Python 2.5 or later is required. If you want to use the -(incompatible) Python 3, you must first run the \texttt{2to3} script -on it. - -\section{For the Impatient} - -\begin{verbatim} -$ ./configure.py [--prefix=/some/directory] -$ make -$ make check -$ 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 Python installed in an unusual -spot, you might need to prefix the \texttt{configure.py} command with -\texttt{python} or \texttt{/path/to/python}. - -\section{Building the Library} - -The first step is to run \filename{configure.py}, which is a Python -script that creates various directories, config files, and a Makefile -for building everything. The script requires at least Python 2.5; any -later version of Python 2.x should also work. Python 3.1 will also -work but requires an extra step, see the section ``Using Python 3.1'', -later in this document. - -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|. - -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. 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 enabled. For instance on one system -we might see lines like: - -\begin{verbatim} - INFO: Skipping mod because CPU incompatible - asm_amd64 mp_amd64 mp_asm64 sha1_amd64 - INFO: Skipping mod because OS incompatible - cryptoapi_rng win32_stats - INFO: Skipping mod because compiler incompatible - mp_ia32_msvc - INFO: Skipping mod because loaded on request only - bzip2 gnump openssl qt_mutex zlib -\end{verbatim} - -The ones that are 'loaded on request only' have to be explicitly asked -for, because they rely on third party libraries which your system -might not have. For instance to enable zlib support, add -\verb|--with-zlib| to your invocation of \verb|configure.py|. - -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=zlib| and \verb|--disable-modules=rc5,idea|. -Modules not listed on the command line will simply be loaded if needed -or if configured to load by default. If you use \verb|--no-autoload|, -only the most core modules will be included; you can then explicitly -enable things that you want to use with enable-modules. This is useful -for creating a minimal build targetted to a specific application. - -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}. - -\subsection{POSIX / Unix} - -The basic build procedure on Unix and Unix-like systems is: - -\begin{verbatim} - $ ./configure.py [--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} - -On Unix systems the script will default to using GCC; use -\texttt{--cc} if you want something else. For instance use -\texttt{--cc=icc} for Intel C++ and \texttt{--cc=clang} for Clang. - -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.py}, like so: - -\verb|./configure.py --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{Mac OS X} - -In general the Unix instructions above should apply, however OS X does -not support \texttt{LD\_LIBRARY\_PATH}. Thomas Keller suggests instead -running \verb|install_name_tool| between building and running the -self-test program: - -\begin{verbatim} - $ VERSION=1.9.10 - $ install_name_tool -change $(otool -X -D libbotan-$VERSION.dylib) \ - $PWD/libbotan-$VERSION.dylib check -\end{verbatim} - -\subsection{MS Windows} - -If you don't want to deal with building botan on Windows, check the -website; commonly prebuilt Windows binaries with installers are -available, especially for stable versions. - -You need to have a copy of Python installed, and have both Python and -your chosen compiler in your path. Open a command shell (or the SDK -shell), and run: - -\begin{verbatim} - > python configure.py --cc=msvc (or --cc=gcc for MinGW) [--cpu=CPU] - > nmake - > nmake check # optional, but recommended - > nmake install -\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 versions of Windows support both methods, so -this shouldn't be much of an issue anymore. - -By default the install target will be 'C:\textbackslash botan'; you -can modify this with the \texttt{--prefix} option. - -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). - -\section{Trickier Things} - -\subsection{Modules Relying on Third Party Libraries} - -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. Most are loaded (or not) automatically as -necessary, but some require external libraries are thus must be -enabled at build time; these include: - -\newcommand{\mod}[2]{\textbf{#1}: #2} - -\begin{list}{$\cdot$} - \item \mod{bzip2}{Enables an application to perform bzip2 - compression and decompression using the library. Available on any - system that has bzip2. To enable, use option \texttt{--with-bzip2}} - - \item \mod{zlib}{Enables an application to perform zlib compression - and decompression using the library. Available on any system that - has zlib. To enable, use option \texttt{--with-zlib}} - - \item \mod{gnump}{An engine that uses GNU MP to speed up PK - operations. GNU MP 4.1 or later is required. To enable, use - option \texttt{--with-gnump}} - - \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. Note that, unlike GNU MP, OpenSSL's versions are not - always faster than the versions built into botan. To enable, use - option \texttt{--with-openssl}} - -\end{list} - -\subsection{Amalgamation} - -You can also configure Botan to be built using only a single source -file; this is quite convenient if you plan to embed the library into -another application. To do so, run \filename{configure.py} with -whatever arguments you would ordinarily use, along with the option -\texttt{--gen-amalgamation}. This will create two (rather large) -files, \filename{botan\_all.h} and \filename{botan\_all.cpp}. - -Whenever you would have included a botan header, you can then include -\filename{botan\_all.h}, and include \filename{botan\_all.cpp} along -with the rest of the source files in your build. If you want to be -able to easily switch between amalgamated and non-amalgamated versions -(for instance to take advantage of prepackaged versions of botan on -operating systems that support it), you can instead ignore -\filename{botan\_all.h} and use the headers from -\filename{build/include} as normal. - -\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{Using Python 3.1} - -The versions of Python begininning with 3 are (intentionally) -incompatible with the (currently more common) 2.x series. If you want -to use Python 3.1 to set up the build, you'll have to use the -\texttt{2to3} program (included in the Python distribution) on the -script; this will convert the script to the Python 3.x dialect: - -\begin{verbatim} - $ python ./configure.py - File "configure.py", line 860 - except KeyError, e: - ^ -SyntaxError: invalid syntax - $ # incompatible python version, let's fix it - $ 2to3 -w configure.py -[...] -RefactoringTool: Files that were modified: -RefactoringTool: configure.py - $ python ./configure.py -[...] -\end{verbatim} - -\subsection{Local Configuration} - -You may want to do something peculiar with the configuration; to -support this there is a flag to \filename{configure.py} 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. - -\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. - -\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.9 --modversion -1.9.8 -$ pkg-config botan-1.9 --cflags --I/usr/local/include -$ pkg-config botan-1.9 --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. - -\section{Language Wrappers} - -\subsection{Building the Python wrappers} - -The Python wrappers for Botan use Boost.Python, so you must have Boost -installed. To build the wrappers, add the flag - -\verb|--with-boost-python| - -to \verb|configure.py|. This will create a second makefile, -\verb|Makefile.python|, with instructions for building the Python -module. After building the library, execute - -\begin{verbatim} -$ make -f Makefile.python -\end{verbatim} - -to build the module. Currently only Unix systems are supported, and -the Makefile assumes that the version of Python you want to build -against is the same one you used to run \verb|configure.py|. - -To install the module, use the \verb|install| target. - -Examples of using the Python module can be seen in \filename{doc/python} - -\subsection{Building the Perl XS wrappers} - -To build the Perl XS wrappers, change your directory to -\filename{src/wrap/perl-xs} and run \verb|perl Makefile.PL|, then run -\verb|make| to build the module and \verb|make test| to run the test -suite. - -\begin{verbatim} -$ perl Makefile.PL -Checking if your kit is complete... -Looks good -Writing Makefile for Botan -$ make -cp Botan.pm blib/lib/Botan.pm -AutoSplitting blib/lib/Botan.pm (blib/lib/auto/Botan) -/usr/bin/perl5.8.8 /usr/lib64/perl5/5.8.8/ExtUtils/xsubpp [...] -g++ -c -Wno-write-strings -fexceptions -g [...] -Running Mkbootstrap for Botan () -chmod 644 Botan.bs -rm -f blib/arch/auto/Botan/Botan.so -g++ -shared Botan.o -o blib/arch/auto/Botan/Botan.so \ - -lbotan -lbz2 -lpthread -lrt -lz \ - -chmod 755 blib/arch/auto/Botan/Botan.so -cp Botan.bs blib/arch/auto/Botan/Botan.bs -chmod 644 blib/arch/auto/Botan/Botan.bs -Manifying blib/man3/Botan.3pm -$ make test -PERL_DL_NONLAZY=1 /usr/bin/perl5.8.8 [...] -t/base64......ok -t/filt........ok -t/hex.........ok -t/oid.........ok -t/pipe........ok -t/x509cert....ok -All tests successful. -Files=6, Tests=83, 0 wallclock secs ( 0.08 cusr + 0.02 csys = 0.10 CPU) -\end{verbatim} - -\end{document} diff --git a/doc/building.txt b/doc/building.txt new file mode 100644 index 000000000..2e52eee1c --- /dev/null +++ b/doc/building.txt @@ -0,0 +1,403 @@ + +Building Botan +================================= + +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.py, which is a `Python +<http://www.python.org>`_ script. Python 2.5 or later is required. + +For the impatient, this works for most systems:: + + $ ./configure.py [--prefix=/some/directory] + $ make + $ make check + $ make install + +Or using ``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 Python installed in an unusual spot, you +might need to prefix the ``configure.py`` command with ``python`` or +``/path/to/python``:: + + $ python ./configure.py [arguments] + +Configuring the Build +--------------------------------- + +The first step is to run ``configure.py``, which is a Python script +that creates various directories, config files, and a Makefile for +building everything. The script requires at least Python 2.5; any +later version of Python 2.x should also work. Python 3.1 will also +work but requires an extra step; see :ref:`configure_with_python3` for +details. + +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 ``--cc``, +``--os``, and ``--cpu``. + +You can pass basically anything reasonable with ``--cpu``: the script +knows about a large number of different architectures, their +sub-models, and common aliases for them. 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 enabled. For instance on one system +we might see lines like:: + + INFO: Skipping mod because CPU incompatible - asm_amd64 mp_amd64 mp_asm64 sha1_amd64 + INFO: Skipping mod because OS incompatible - cryptoapi_rng win32_stats + INFO: Skipping mod because compiler incompatible - mp_ia32_msvc + INFO: Skipping mod because loaded on request only - bzip2 gnump openssl qt_mutex zlib + +The ones that are 'loaded on request only' have to be explicitly asked +for, because they rely on third party libraries which your system +might not have. For instance to enable zlib support, add +``--with-zlib`` to your invocation of ``configure.py``. + +You can control which algorithms and modules are built using the +options ``--enable-modules=MODS`` and ``--disable-modules=MODS``, for +instance ``--enable-modules=zlib`` and ``--disable-modules=rc5,idea``. +Modules not listed on the command line will simply be loaded if needed +or if configured to load by default. If you use ``--no-autoload``, +only the most core modules will be included; you can then explicitly +enable things that you want to use with ``--enable-modules``. This is +useful for creating a minimal build targetted to a specific +application, especially in conjuction with the amalgamation option; +see :ref:`amalgamation`. + +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 +``--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 +``src/build-data/makefile``. + +On Unix +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The basic build procedure on Unix and Unix-like systems is:: + + $ ./configure.py [--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 + +On Unix systems the script will default to using GCC; use +``--cc`` if you want something else. For instance use +``--cc=icc`` for Intel C++ and ``--cc=clang`` for Clang. + +The ``make install`` target has a default directory in which it +will install Botan (typically ``/usr/local``). You can override +this by using the ``--prefix`` argument to +``configure.py``, like so: + +``./configure.py --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 +``/etc/ld.so.conf`` and run ``ldconfig`` (as root) in +order for new shared libraries to be picked up by the linker. An +alternative is to set your ``LD_LIBRARY_PATH`` shell variable +to include the directory that the Botan libraries were installed into. + +On Mac OS X +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In general the Unix instructions above should apply, however OS X does +not support ``LD_LIBRARY_PATH``. Thomas Keller suggests instead +running ``install_name_tool`` between building and running the +self-test program:: + + $ VERSION=1.10.0 # or whatever the current version is + $ install_name_tool -change $(otool -X -D libbotan-$VERSION.dylib) \ + $PWD/libbotan-$VERSION.dylib check + +On MS Windows +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you don't want to deal with building botan on Windows, check the +website; commonly prebuilt Windows binaries with installers are +available, especially for stable versions. + +You need to have a copy of Python installed, and have both Python and +your chosen compiler in your path. Open a command shell (or the SDK +shell), and run:: + + > python configure.py --cc=msvc (or --cc=gcc for MinGW) [--cpu=CPU] + > nmake + > nmake check # optional, but recommended + > nmake install + +For Win95 pre OSR2, the ``cryptoapi_rng`` module will not work, +because CryptoAPI didn't exist. And all versions of NT4 lack the +ToolHelp32 interface, which is how ``win32_stats`` does its slow +polls, so a version of the library built with that module will not +load under NT4. Later versions of Windows support both methods, so +this shouldn't be much of an issue anymore. + +By default the install target will be ``C:\botan``; you can modify +this with the ``--prefix`` option. + +When building your applications, all you have to do is tell the +compiler to look for both include files and library files in +``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). + +Trickier Things +---------------------------------------- + +Modules Relying on Third Party Libraries +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +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. Most are loaded (or not) automatically as +necessary, but some require external libraries are thus must be +enabled at build time; these include: + + - ``--with-bzip2`` enables the filters providing bzip2 compression + and decompression. Requires the bzip2 development libraries to be + installed. + + - ``--with-zlib`` enables the filters providing zlib compression + and decompression. Requires the zlib development libraries to be + installed. + + - ``--with-gnump`` adds an alternative engine for public key cryptography + that uses the GNU MP library. GNU MP 4.1 or later is required. + + - ``--with-openssl`` adds an engine that uses OpenSSL for some public + key operations and ciphers/hashes. OpenSSL 0.9.7 or later is + required. Note that (unlike GNU MP) OpenSSL's versions are not + always faster than the versions built into botan. + +.. _amalgamation: + +Amalgamation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can also configure Botan to be built using only a single source +file; this is quite convenient if you plan to embed the library into +another application. To do so, run ``configure.py`` with +whatever arguments you would ordinarily use, along with the option +``--gen-amalgamation``. This will create two (rather large) +files, ``botan_all.h`` and ``botan_all.cpp``. + +Whenever you would have included a botan header, you can then include +``botan_all.h``, and include ``botan_all.cpp`` along +with the rest of the source files in your build. If you want to be +able to easily switch between amalgamated and non-amalgamated versions +(for instance to take advantage of prepackaged versions of botan on +operating systems that support it), you can instead ignore +``botan_all.h`` and use the headers from +``build/include`` as normal. + +Multiple Builds +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It may be useful to run multiple builds with different +configurations. Specify ``--build-dir=<dir>`` to set up a build +environment in a different directory. + + +.. _configure_with_python3: + +Configuring the Build With Python 3.1 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The versions of Python begininning with 3 are (intentionally) +incompatible with the (currently more common) 2.x series. If you want +to use Python 3.1 to set up the build, you'll have to use the +``2to3`` program (included in the Python distribution) on the +script; this will convert the script to the Python 3.x dialect:: + + $ python ./configure.py + File "configure.py", line 860 + except KeyError, e: + ^ + SyntaxError: invalid syntax + $ # incompatible python version, let's fix it + $ 2to3 -w configure.py + [...] + RefactoringTool: Files that were modified: + RefactoringTool: configure.py + $ python ./configure.py + [...] + +Local Configuration Settings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You may want to do something peculiar with the configuration; to +support this there is a flag to ``configure.py`` called +``--with-local-config=<file>``. The contents of the file are +inserted into ``build/build.h`` which is (indirectly) included +into every Botan header and source file. + +Configuration Parameters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There are some configuration parameters which you may want to tweak +before building the library. These can be found in ``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 ``build/build.h`` are macros which let applications +check which features are included in the current version of the +library. All of them begin with ``BOTAN_HAS_``. For example, if +``BOTAN_HAS_BLOWFISH`` is defined, then an application can include +``<botan/blowfish.h>`` and use the Blowfish class. + +``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. Normally this defaults to either 32 or 64, depending +on the processor. Unless you are building for a 8 or 16-bit CPU, this +isn't worth messing with. + +``BOTAN_VECTOR_OVER_ALLOCATE``: The memory container ``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 *really* want to reduce memory usage, set it to 0. Otherwise, the +default should be perfectly fine. + +``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 +purposes. + +Building Applications +---------------------------------------- + +Unix +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Botan usually links in several different system libraries (such as +``librt`` and ``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 *is* linked against? + +The answer is to ask the ``botan-config`` script. This +basically solves the same problem all the other ``*-config`` +scripts solve, and in basically the same manner. + +There are 4 options: + +``--prefix[=DIR]``: If no argument, print the prefix where Botan +is installed (such as ``/opt`` or ``/usr/local``). If an +argument is specified, other options given with the same command will +execute as if Botan as actually installed at ``DIR`` and not +where it really is; or at least where ``botan-config`` thinks +it really is. I should mention that it + +``--version``: Print the Botan version number. + +``--cflags``: Print options that should be passed to the compiler +whenever a C++ file is compiled. Typically this is used for setting +include paths. + +``--libs``: Print options for which libraries to link to (this includes +``-lbotan``). + +Your ``Makefile`` can run ``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 ``pkg-config``, +namespaced by the major and minor versions. So it can be used, +for instance, as:: + + $ pkg-config botan-1.10 --modversion + 1.10.0 + $ pkg-config botan-1.10 --cflags + -I/usr/local/include + $ pkg-config botan-1.10 --libs + -L/usr/local/lib -lbotan -lm -lbz2 -lpthread -lrt + +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. + +Language Wrappers +---------------------------------------- + +Building the Python wrappers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The Python wrappers for Botan use Boost.Python, so you must have Boost +installed. To build the wrappers, pass the flag +``--with-boost-python`` to ``configure.py``. This will create a second +makefile, ``Makefile.python``, with instructions for building the +Python module. After building the library, execute:: + + $ make -f Makefile.python + +to build the module. Currently only Unix systems are supported, and +the Makefile assumes that the version of Python you want to build +against is the same one you used to run ``configure.py``. + +To install the module, use the ``install`` target. + +Examples of using the Python module can be seen in +``doc/examples/python`` + +Building the Perl XS wrappers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To build the Perl XS wrappers, change your directory to +``src/wrap/perl-xs`` and run ``perl Makefile.PL``, then run +``make`` to build the module and ``make test`` to run the test +suite:: + + $ perl Makefile.PL + Checking if your kit is complete... + Looks good + Writing Makefile for Botan + $ make + cp Botan.pm blib/lib/Botan.pm + AutoSplitting blib/lib/Botan.pm (blib/lib/auto/Botan) + /usr/bin/perl5.8.8 /usr/lib64/perl5/5.8.8/ExtUtils/xsubpp [...] + g++ -c -Wno-write-strings -fexceptions -g [...] + Running Mkbootstrap for Botan () + chmod 644 Botan.bs + rm -f blib/arch/auto/Botan/Botan.so + g++ -shared Botan.o -o blib/arch/auto/Botan/Botan.so \ + -lbotan -lbz2 -lpthread -lrt -lz \ + + chmod 755 blib/arch/auto/Botan/Botan.so + cp Botan.bs blib/arch/auto/Botan/Botan.bs + chmod 644 blib/arch/auto/Botan/Botan.bs + Manifying blib/man3/Botan.3pm + $ make test + PERL_DL_NONLAZY=1 /usr/bin/perl5.8.8 [...] + t/base64......ok + t/filt........ok + t/hex.........ok + t/oid.........ok + t/pipe........ok + t/x509cert....ok + All tests successful. + Files=6, Tests=83, 0 wallclock secs ( 0.08 cusr + 0.02 csys = 0.10 CPU) diff --git a/doc/conf.py b/doc/conf.py new file mode 100644 index 000000000..c3f8677fa --- /dev/null +++ b/doc/conf.py @@ -0,0 +1,223 @@ +# -*- coding: utf-8 -*- +# +# botan documentation build configuration file, created by +# sphinx-quickstart on Sun Apr 3 11:41:06 2011. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +sys.path.insert(0, os.pardir) + +import botan_version + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = [] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.txt' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'botan' +copyright = u'2000-2011, Jack Lloyd' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '%d.%d' % (botan_version.major, botan_version.minor) +# The full version, including alpha/beta/rc tags. +release = '%d.%d.%d%s' % (botan_version.major, + botan_version.minor, + botan_version.patch, + botan_version.release_suffix) + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# "<project> v<release> documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a <link> tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'botandoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'botan.tex', u'botan Documentation', + u'Jack Lloyd', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'botan', u'botan Documentation', + [u'Jack Lloyd'], 1) +] diff --git a/doc/credits.txt b/doc/credits.txt index 636a99f99..076498756 100644 --- a/doc/credits.txt +++ b/doc/credits.txt @@ -1,78 +1,80 @@ -This is at least a partial credits-file of people that have -contributed to the Botan project. It is sorted by name and formatted -to allow easy grepping and beautification by scripts. The fields are: -name (N), email (E), web-address (W), PGP key ID and fingerprint (P), -description (D), and snail-mail address (S). - -Thanks, - Jack Lloyd ----------- - -N: Charles Brockman -W: http://www.securitygenetics.com/ -D: documentation editing -S: Oregon, USA - -N: Martin Doering -D: GF(p) arithmetic - -N: Olivier de Gaalon -D: SQLite encryption codec (src/wrap/sqlite) - -N: Matthew Gregan -D: Binary file I/O support, allocator fixes - -N: Hany Greiss -D: Windows porting - -N: Manuel Hartl -W: http://www.flexsecure.de/ -D: ECDSA, ECDH - -N: Yves Jerschow -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 -D: Bzip2 compression module -S: Colorado, USA - -N: Justin Karneges -D: Qt support modules (mutexes and types), X.509 API design - -N: Jack Lloyd -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 and Windows DLL support in general - -N: Christoph Ludwig -D: GP(p) arithmetic - -N: Vaclav Ovsik -D: Perl XS module (src/wrap/perl-xs) - -N: Luca Piccarreta -D: x86/amd64 assembler, BigInt optimizations, Win32 mutex module -S: Italy - -N: Falko Strenzke -W: http://www.flexsecure.de/ -D: GF(p) arithmetic, CVC, Shanks-Tonelli algorithm -S: Darmstadt, Germany + +Credits +======================================== + +This is at least a partial credits-file of people that have contributed +to botan. It is sorted by name and formatted to allow easy grepping +and beautification by scripts. The fields are name (N), email (E), +web-address (W), PGP key ID and fingerprint (P), description (D), and +snail-mail address (S). + +:: + + N: Charles Brockman + W: http://www.securitygenetics.com/ + D: documentation editing + S: Oregon, USA + + N: Martin Doering + E: [email protected] + D: GF(p) arithmetic + + N: Olivier de Gaalon + D: SQLite encryption codec (src/wrap/sqlite) + + N: Matthew Gregan + D: Binary file I/O support, allocator fixes + + N: Hany Greiss + D: Windows porting + + N: Manuel Hartl + E: [email protected] + W: http://www.flexsecure.de/ + D: ECDSA, ECDH + + N: Yves Jerschow + E: [email protected] + 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: [email protected] + 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: [email protected] + 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 and Windows DLL support in general + + N: Christoph Ludwig + E: [email protected] + D: GP(p) arithmetic + + N: Vaclav Ovsik + E: [email protected] + D: Perl XS module (src/wrap/perl-xs) + + N: Luca Piccarreta + E: [email protected] + D: x86/amd64 assembler, BigInt optimizations, Win32 mutex module + S: Italy + + N: Falko Strenzke + E: [email protected] + W: http://www.flexsecure.de/ + D: GF(p) arithmetic, CVC, Shanks-Tonelli algorithm + S: Darmstadt, Germany diff --git a/doc/examples/GNUmakefile b/doc/examples/GNUmakefile deleted file mode 100644 index 44fcfeea5..000000000 --- a/doc/examples/GNUmakefile +++ /dev/null @@ -1,21 +0,0 @@ - -BOTAN_CONFIG = botan-config - -CXX = g++ -CFLAGS = -O2 -ansi -W -Wall -I../../build/include -LIBS = -L../.. -lbotan - -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/doc/examples/asn1.cpp b/doc/examples/asn1.cpp deleted file mode 100644 index b0a6aa104..000000000 --- a/doc/examples/asn1.cpp +++ /dev/null @@ -1,312 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -/* - 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 -*/ - -// 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/doc/examples/base64.cpp b/doc/examples/base64.cpp deleted file mode 100644 index dbe8d19e3..000000000 --- a/doc/examples/base64.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* -* Encode/decode base64 strings -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#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/doc/examples/bcrypt.cpp b/doc/examples/bcrypt.cpp deleted file mode 100644 index 27a98cf33..000000000 --- a/doc/examples/bcrypt.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* -* Bcrypt example -* (C) 2011 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/botan.h> -#include <botan/bcrypt.h> -#include <iostream> - -using namespace Botan; - -int main(int argc, char* argv[]) - { - if(argc != 2 && argc != 3) - { - std::cout << "Usage: " << argv[0] << " password\n" - << " " << argv[0] << " password passhash\n"; - return 1; - } - - LibraryInitializer init; - - if(argc == 2) - { - AutoSeeded_RNG rng; - - std::cout << generate_bcrypt(argv[1], rng, 12) << "\n"; - } - else if(argc == 3) - { - if(strlen(argv[2]) != 60) - { - std::cout << "Note: hash " << argv[2] - << " has wrong length and cannot be valid\n"; - } - - const bool ok = check_bcrypt(argv[1], argv[2]); - - std::cout << "Password is " << (ok ? "valid" : "NOT valid") << "\n"; - } - - return 0; - } diff --git a/doc/examples/bench.cpp b/doc/examples/bench.cpp deleted file mode 100644 index 20e6ec40b..000000000 --- a/doc/examples/bench.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/benchmark.h> -#include <botan/init.h> -#include <botan/auto_rng.h> -#include <botan/libstate.h> - -using namespace Botan; - -#include <iostream> - -namespace { - -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", - "GOST-34.11", - "HAS-160", - "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", - "", -}; - -void benchmark_algo(const std::string& algo, - RandomNumberGenerator& rng) - { - u32bit milliseconds = 3000; - Algorithm_Factory& af = global_state().algorithm_factory(); - - std::map<std::string, double> speeds = - algorithm_benchmark(algo, af, rng, milliseconds, 16*1024); - - std::cout << algo << ":"; - - for(std::map<std::string, double>::const_iterator i = speeds.begin(); - i != speeds.end(); ++i) - { - std::cout << " " << i->second << " [" << i->first << "]"; - } - std::cout << "\n"; - } - -} - -int main(int argc, char* argv[]) - { - LibraryInitializer init; - - AutoSeeded_RNG rng; - - if(argc == 1) // no args, benchmark everything - { - for(u32bit i = 0; algos[i] != ""; ++i) - benchmark_algo(algos[i], rng); - } - else - { - for(int i = 1; argv[i]; ++i) - benchmark_algo(argv[i], rng); - } - } diff --git a/doc/examples/benchmark.cpp b/doc/examples/benchmark.cpp deleted file mode 100644 index 7ad1775e2..000000000 --- a/doc/examples/benchmark.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#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::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 = - algorithm_benchmark(algo, af, rng, ms, 16*1024); - - 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/doc/examples/bzip.cpp b/doc/examples/bzip.cpp deleted file mode 100644 index 6137bb6af..000000000 --- a/doc/examples/bzip.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* -* Bzip2 Compression/Decompression -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <string> -#include <cstring> -#include <vector> -#include <fstream> -#include <iostream> -#include <botan/botan.h> - -/* -* If Bzip2 isn't included, we know nothing works at compile time, but -* we wait to fail at runtime. Otherwise I would get 2-3 mails a month -* about how this was failing to compile (even with an informative -* #error message explaining the situation) because bzip2 wasn't -* included in the build. -*/ - -#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::ios::binary); - std::ofstream out(outfile.c_str(), std::ios::binary); - 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/doc/examples/ca.cpp b/doc/examples/ca.cpp deleted file mode 100644 index 8dd3e981f..000000000 --- a/doc/examples/ca.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -/* - 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 -*/ - -#include <botan/botan.h> -#include <botan/x509_ca.h> -#include <botan/time.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, "SHA-256"); - - // 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/doc/examples/cert_verify.cpp b/doc/examples/cert_verify.cpp deleted file mode 100644 index 04bcbecad..000000000 --- a/doc/examples/cert_verify.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* -* Simple example of a certificate validation -* (C) 2010 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/botan.h> -#include <botan/x509cert.h> -#include <botan/x509stor.h> - -#include <stdio.h> - -using namespace Botan; - -int main() - { - LibraryInitializer init; - - X509_Certificate ca_cert("ca_cert.pem"); - X509_Certificate subject_cert("http_cert.pem"); - - X509_Store cert_store; - - cert_store.add_cert(ca_cert, /*trusted=*/true); - - X509_Code code = cert_store.validate_cert(subject_cert); - - if(code == VERIFIED) - printf("Cert validated\n"); - else - printf("Cert did not validate, code = %d\n", code); - - return 0; - } diff --git a/doc/examples/checksum.cpp b/doc/examples/checksum.cpp deleted file mode 100644 index dba7a7d70..000000000 --- a/doc/examples/checksum.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#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/doc/examples/cms_dec.cpp b/doc/examples/cms_dec.cpp deleted file mode 100644 index 84355fb4a..000000000 --- a/doc/examples/cms_dec.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#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) - { - std::cout << "Usage: " << argv[0] << " <filename>\n"; - 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]); - - CMS_Decoder decoder(message, store, 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/doc/examples/cms_enc.cpp b/doc/examples/cms_enc.cpp deleted file mode 100644 index 2cf813987..000000000 --- a/doc/examples/cms_enc.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#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/doc/examples/cpuid.cpp b/doc/examples/cpuid.cpp deleted file mode 100644 index 6d4cc7593..000000000 --- a/doc/examples/cpuid.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <iostream> -#include <string> -#include <botan/cpuid.h> - -using namespace Botan; - -namespace { - -void print_if_feature(const std::string& feature_name, bool exists) - { - std::cout << (exists ? '+' : '-') << " " << feature_name << "\n"; - } - -void print_header(const std::string& descr) - { - std::cout << "\n" << descr << "\n-----\n"; - } - -} - -int main() - { - CPUID::initialize(); - - std::cout << "Cache line size = " << CPUID::cache_line_size() << "\n"; - - print_header("SIMD instruction sets"); - print_if_feature("SSE2", CPUID::has_sse2()); - print_if_feature("SSSE3", CPUID::has_ssse3()); - print_if_feature("SSE4.1", CPUID::has_sse41()); - print_if_feature("SSE4.2", CPUID::has_sse42()); - print_if_feature("AVX", CPUID::has_avx()); - print_if_feature("AltiVec", CPUID::has_altivec()); - - print_header("Other extensions"); - print_if_feature("RDTSC", CPUID::has_rdtsc()); - print_if_feature("PCMUL", CPUID::has_pcmuludq()); - print_if_feature("AES-NI", CPUID::has_aes_ni()); - print_if_feature("MOVBE", CPUID::has_movbe()); - } diff --git a/doc/examples/cryptobox.cpp b/doc/examples/cryptobox.cpp deleted file mode 100644 index 38d750d17..000000000 --- a/doc/examples/cryptobox.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#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::ios::binary); - - 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/doc/examples/decrypt.cpp b/doc/examples/decrypt.cpp deleted file mode 100644 index ea510c5e9..000000000 --- a/doc/examples/decrypt.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -/* -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. -*/ - -#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; - } - - const BlockCipher* cipher_proto = global_state().algorithm_factory().prototype_block_cipher(algo); - - if(!cipher_proto) - { - std::cout << "Don't know about the block cipher \"" << algo << "\"\n"; - return 1; - } - - const u32bit key_len = cipher_proto->maximum_keylength(); - const u32bit iv_len = cipher_proto->block_size(); - - std::auto_ptr<PBKDF> pbkdf(get_pbkdf("PBKDF2(SHA-1)")); - - const u32bit PBKDF2_ITERATIONS = 8192; - - SecureVector<byte> salt = b64_decode(salt_str); - - SymmetricKey bc_key = pbkdf->derive_key(key_len, "BLK" + passphrase, - &salt[0], salt.size(), - PBKDF2_ITERATIONS); - - InitializationVector iv = pbkdf->derive_key(iv_len, "IVL" + passphrase, - &salt[0], salt.size(), - PBKDF2_ITERATIONS); - - SymmetricKey mac_key = pbkdf->derive_key(16, "MAC" + passphrase, - &salt[0], salt.size(), - PBKDF2_ITERATIONS); - - 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/doc/examples/dh.cpp b/doc/examples/dh.cpp deleted file mode 100644 index 652c7b136..000000000 --- a/doc/examples/dh.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* -* (C) 2009-2010 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/botan.h> -#include <botan/dh.h> -#include <botan/pubkey.h> -using namespace Botan; - -#include <iostream> -#include <memory> - -int main() - { - Botan::LibraryInitializer init; - - try - { - AutoSeeded_RNG rng; - - // Alice and Bob agree on a DH domain to use - DL_Group shared_domain("modp/ietf/1024"); - - // Alice creates a DH key and sends (the public part) to Bob - DH_PrivateKey private_a(rng, shared_domain); - - // Alice sends to Bob her public key: - MemoryVector<byte> public_a = private_a.public_value(); - - // Bob creates a key with a matching group - DH_PrivateKey private_b(rng, shared_domain); - - // Bob sends his public key to Alice - MemoryVector<byte> public_b = private_b.public_value(); - - PK_Key_Agreement ka1(private_a, "KDF2(SHA-1)"); - PK_Key_Agreement ka2(private_b, "KDF2(SHA-1)"); - - /* - * Preferably, include some salt or parameter that binds this key - * generation to the current session (for instance a session - * identifier, if guaranteed unique, would be a good choice). Or - * anything else that both sides can agree on that will never - * repeat. - */ - const std::string ka_salt = "alice and bob agree on a key"; - - SymmetricKey alice_key = ka1.derive_key(32, public_b, ka_salt); - SymmetricKey bob_key = ka2.derive_key(32, public_a, ka_salt); - - 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! Hmmm...\n"; - std::cout << "Alice's key was: " << alice_key.as_string() << "\n"; - std::cout << "Bob's key was: " << bob_key.as_string() << "\n"; - } - - // Now use the shared key for encryption or MACing or whatever - } - catch(std::exception& e) - { - std::cout << e.what() << std::endl; - return 1; - } - return 0; - } diff --git a/doc/examples/dsa_kgen.cpp b/doc/examples/dsa_kgen.cpp deleted file mode 100644 index fe3157370..000000000 --- a/doc/examples/dsa_kgen.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -* -* 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. -*/ - -#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/doc/examples/dsa_sign.cpp b/doc/examples/dsa_sign.cpp deleted file mode 100644 index 5f02c0dc1..000000000 --- a/doc/examples/dsa_sign.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* -* DSA signature generation example -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <iostream> -#include <iomanip> -#include <fstream> -#include <string> -#include <memory> - -#include <botan/botan.h> -#include <botan/pubkey.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], std::ios::binary); - 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, "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/doc/examples/dsa_ver.cpp b/doc/examples/dsa_ver.cpp deleted file mode 100644 index a666259c1..000000000 --- a/doc/examples/dsa_ver.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -/* -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: take the IEEE 1363 -signature format, encoded into base64 with a trailing newline. -*/ - -#include <iostream> -#include <iomanip> -#include <fstream> -#include <cstdlib> -#include <string> -#include <memory> - -#include <botan/botan.h> -#include <botan/pubkey.h> -#include <botan/dsa.h> -using namespace Botan; - -namespace { - -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], std::ios::binary); - 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); - - PK_Verifier ver(*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/doc/examples/eax_test.cpp b/doc/examples/eax_test.cpp deleted file mode 100644 index 32311800d..000000000 --- a/doc/examples/eax_test.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <fstream> -#include <iostream> -#include <sstream> -#include <boost/regex.hpp> - -#include <botan/botan.h> -#include <botan/eax.h> - -using namespace Botan; - -namespace { - -unsigned from_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 = from_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/doc/examples/eax_tv.txt b/doc/examples/eax_tv.txt deleted file mode 100644 index 95cd7c1ab..000000000 --- a/doc/examples/eax_tv.txt +++ /dev/null @@ -1,461 +0,0 @@ -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/doc/examples/ecdsa.cpp b/doc/examples/ecdsa.cpp deleted file mode 100644 index df1e1b93a..000000000 --- a/doc/examples/ecdsa.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/botan.h> -#include <botan/ecdsa.h> -#include <botan/pubkey.h> - -#include <memory> -#include <iostream> - -using namespace Botan; - -int main() - { - Botan::LibraryInitializer init; - - try - { - AutoSeeded_RNG rng; - - EC_Domain_Params params("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); - */ - - PK_Signer 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"; - - PK_Verifier 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/doc/examples/encrypt.cpp b/doc/examples/encrypt.cpp deleted file mode 100644 index 28017d875..000000000 --- a/doc/examples/encrypt.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -/* -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. -*/ - -#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(), std::ios::binary); - 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 - { - const BlockCipher* cipher_proto = global_state().algorithm_factory().prototype_block_cipher(algo); - - if(!cipher_proto) - { - std::cout << "Don't know about the block cipher \"" << algo << "\"\n"; - return 1; - } - - const u32bit key_len = cipher_proto->maximum_keylength(); - const u32bit iv_len = cipher_proto->block_size(); - - AutoSeeded_RNG rng; - - std::auto_ptr<PBKDF> pbkdf(get_pbkdf("PBKDF2(SHA-1)")); - - SecureVector<byte> salt(8); - rng.randomize(&salt[0], salt.size()); - - const u32bit PBKDF2_ITERATIONS = 8192; - - SymmetricKey bc_key = pbkdf->derive_key(key_len, "BLK" + passphrase, - &salt[0], salt.size(), - PBKDF2_ITERATIONS); - - InitializationVector iv = pbkdf->derive_key(iv_len, "IVL" + passphrase, - &salt[0], salt.size(), - PBKDF2_ITERATIONS); - - SymmetricKey mac_key = pbkdf->derive_key(16, "MAC" + passphrase, - &salt[0], salt.size(), - PBKDF2_ITERATIONS); - - // Just to be all fancy we even write a (simple) header. - out << "-------- ENCRYPTED FILE --------" << std::endl; - out << algo << std::endl; - out << b64_encode(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/doc/examples/encrypt2.cpp b/doc/examples/encrypt2.cpp deleted file mode 100644 index 41f4fb478..000000000 --- a/doc/examples/encrypt2.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#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)); - - const u32bit PBKDF2_ITERATIONS = 8192; - - SecureVector<byte> salt(8); - rng.randomize(&salt[0], salt.size()); - - SecureVector<byte> master_key = pbkdf2.derive_key(48, passphrase, - &salt[0], salt.size(), - PBKDF2_ITERATIONS).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*)salt.begin(), 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/doc/examples/factor.cpp b/doc/examples/factor.cpp deleted file mode 100644 index 58b12d9a5..000000000 --- a/doc/examples/factor.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/* -* (C) 2009-2010 Jack Lloyd -* -* Distributed under the terms of the Botan license -* -* 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 <iterator> - -namespace { - -/* -* 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(check_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 << ": "; - std::copy(factors.begin(), - factors.end(), - std::ostream_iterator<BigInt>(std::cout, " ")); - std::cout << "\n"; - } - catch(std::exception& e) - { - std::cout << e.what() << std::endl; - return 1; - } - return 0; - } diff --git a/doc/examples/fpe.cpp b/doc/examples/fpe.cpp deleted file mode 100644 index 9b18d4879..000000000 --- a/doc/examples/fpe.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -/* -* Encrypt credit cards numbers with valid checksums into other credit -* card numbers with valid checksums using format preserving encryption. -*/ - -#include <botan/fpe.h> -#include <botan/sha160.h> -#include <botan/init.h> - -using namespace Botan; - -#include <iostream> -#include <stdexcept> - -namespace { - -byte luhn_checksum(u64bit cc_number) - { - byte sum = 0; - - bool alt = false; - while(cc_number) - { - byte digit = cc_number % 10; - if(alt) - { - digit *= 2; - if(digit > 9) - digit -= 9; - } - - sum += digit; - - cc_number /= 10; - alt = !alt; - } - - return (sum % 10); - } - -bool luhn_check(u64bit cc_number) - { - return (luhn_checksum(cc_number) == 0); - } - -u64bit cc_rank(u64bit cc_number) - { - // Remove Luhn checksum - return cc_number / 10; - } - -u64bit cc_derank(u64bit cc_number) - { - for(u32bit i = 0; i != 10; ++i) - if(luhn_check(cc_number * 10 + i)) - return (cc_number * 10 + i); - return 0; - } - -/* -* Use the SHA-1 hash of the account name or ID as a tweak -*/ -SecureVector<byte> sha1(const std::string& acct_name) - { - SHA_160 hash; - hash.update(acct_name); - return hash.final(); - } - -u64bit encrypt_cc_number(u64bit cc_number, - const SymmetricKey& key, - const std::string& acct_name) - { - BigInt n = 1000000000000000; - - u64bit cc_ranked = cc_rank(cc_number); - - BigInt c = fpe_encrypt(n, cc_ranked, key, sha1(acct_name)); - - if(c.bits() > 50) - throw std::runtime_error("FPE produced a number too large"); - - u64bit enc_cc = 0; - for(u32bit i = 0; i != 7; ++i) - enc_cc = (enc_cc << 8) | c.byte_at(6-i); - return cc_derank(enc_cc); - } - -u64bit decrypt_cc_number(u64bit enc_cc, - const SymmetricKey& key, - const std::string& acct_name) - { - BigInt n = 1000000000000000; - - u64bit cc_ranked = cc_rank(enc_cc); - - BigInt c = fpe_decrypt(n, cc_ranked, key, sha1(acct_name)); - - if(c.bits() > 50) - throw std::runtime_error("FPE produced a number too large"); - - u64bit dec_cc = 0; - for(u32bit i = 0; i != 7; ++i) - dec_cc = (dec_cc << 8) | c.byte_at(6-i); - return cc_derank(dec_cc); - } - -} - -int main(int argc, char* argv[]) - { - LibraryInitializer init; - - if(argc != 4) - { - std::cout << "Usage: " << argv[0] << " cc-number acct-name passwd\n"; - return 1; - } - - u64bit cc_number = atoll(argv[1]); - std::string acct_name = argv[2]; - std::string passwd = argv[3]; - - std::cout << "Input was: " << cc_number << ' ' - << luhn_check(cc_number) << '\n'; - - /** - * In practice something like PBKDF2 with a salt and high iteration - * count would be a good idea. - */ - SymmetricKey key = sha1(passwd); - - u64bit enc_cc = encrypt_cc_number(cc_number, key, acct_name); - - std::cout << "Encrypted: " << enc_cc - << ' ' << luhn_check(enc_cc) << '\n'; - - u64bit dec_cc = decrypt_cc_number(enc_cc, key, acct_name); - - std::cout << "Decrypted: " << dec_cc - << ' ' << luhn_check(dec_cc) << '\n'; - - if(dec_cc != cc_number) - std::cout << "Something went wrong :( Bad CC checksum?\n"; - } diff --git a/doc/examples/gen_certs.cpp b/doc/examples/gen_certs.cpp deleted file mode 100644 index f8c9fe124..000000000 --- a/doc/examples/gen_certs.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -/* -* Generate a root CA plus httpd, dovecot, and postfix certs/keys -* -*/ - -#include <botan/botan.h> -#include <botan/rsa.h> -#include <botan/time.h> -#include <botan/x509self.h> -#include <botan/x509_ca.h> - -using namespace Botan; - -#include <iostream> -#include <fstream> - -namespace { - -void fill_commoninfo(X509_Cert_Options& opts) - { - opts.country = "US"; - opts.organization = "randombit.net"; - opts.email = "[email protected]"; - 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, "SHA-256", 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, "SHA-1", 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, "SHA-256"); - - 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/doc/examples/gtk/Makefile b/doc/examples/gtk/Makefile deleted file mode 100644 index 10e069bb3..000000000 --- a/doc/examples/gtk/Makefile +++ /dev/null @@ -1,18 +0,0 @@ - -LIBS=$(shell botan-config --libs) $(shell pkg-config --libs gtk+-2.0) -IFLAGS=$(shell botan-config --cflags) $(shell pkg-config --cflags gtk+-2.0) - -CXX = g++ -CXXFLAGS = -Wall -W $(IFLAGS) - -dsa: gtk_ui.o dsa.o - $(CXX) $^ $(LIBS) -o $@ - -gtk_ui.o: gtk_ui.cpp gtk_ui.h - $(CXX) $(CXXFLAGS) -c $< -o $@ - -dsa.o: dsa.cpp gtk_ui.h - $(CXX) $(CXXFLAGS) -c $< -o $@ - -clean: - rm -f dsa *.o diff --git a/doc/examples/gtk/dsa.cpp b/doc/examples/gtk/dsa.cpp deleted file mode 100644 index 2cd91b0e8..000000000 --- a/doc/examples/gtk/dsa.cpp +++ /dev/null @@ -1,566 +0,0 @@ -/* - 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/pk_filts.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" - -static Botan::RandomNumberGenerator* rng = 0; - -/* -* 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>[email protected]</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, *rng, 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)"), *rng - ), - 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); - } - -#if 0 -/* -* 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(); - } -#endif - -/* -* 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(*rng, Botan::DL_Group::DSA_Kosherizer, 1024); - key = new Botan::DSA_PrivateKey(*rng, 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, *rng, 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; - - rng = new Botan::AutoSeeded_RNG; - - /* 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/doc/examples/gtk/gtk_ui.cpp b/doc/examples/gtk/gtk_ui.cpp deleted file mode 100644 index d4e9cd238..000000000 --- a/doc/examples/gtk/gtk_ui.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* -* GTK+ User Interface Source File -*/ - -#include "gtk_ui.h" -#include <cstring> - -/* -* 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; - std::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/doc/examples/gtk/gtk_ui.h b/doc/examples/gtk/gtk_ui.h deleted file mode 100644 index 065a4f76b..000000000 --- a/doc/examples/gtk/gtk_ui.h +++ /dev/null @@ -1,27 +0,0 @@ -/* -* (C) 2006 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#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/doc/examples/gtk/readme.txt b/doc/examples/gtk/readme.txt deleted file mode 100644 index 4f3691166..000000000 --- a/doc/examples/gtk/readme.txt +++ /dev/null @@ -1,18 +0,0 @@ - -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/doc/examples/hash.cpp b/doc/examples/hash.cpp deleted file mode 100644 index 1a4ca1b64..000000000 --- a/doc/examples/hash.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#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], std::ios::binary); - 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/doc/examples/hash_fd.cpp b/doc/examples/hash_fd.cpp deleted file mode 100644 index 32acdbec3..000000000 --- a/doc/examples/hash_fd.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -/* -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. -*/ - -#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/doc/examples/hash_quickly.cpp b/doc/examples/hash_quickly.cpp deleted file mode 100644 index 005a6d719..000000000 --- a/doc/examples/hash_quickly.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -/* -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. -*/ - -#include <botan/botan.h> -#include <botan/benchmark.h> -#include <botan/filters.h> - -#include <iostream> -#include <fstream> -#include <string> -#include <map> -#include <cstdlib> - -namespace { - -void set_fastest_implementation(const std::string& algo, - Botan::RandomNumberGenerator& rng, - double ms = 30) - { - Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory(); - - std::map<std::string, double> results = - Botan::algorithm_benchmark(algo, af, rng, ms, 16*1024); - - 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], std::ios::binary); - 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/doc/examples/hasher.cpp b/doc/examples/hasher.cpp deleted file mode 100644 index e5c52ba55..000000000 --- a/doc/examples/hasher.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#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], std::ios::binary); - 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/doc/examples/hasher2.cpp b/doc/examples/hasher2.cpp deleted file mode 100644 index b6303b644..000000000 --- a/doc/examples/hasher2.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* -* (C) 2001 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -/* -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. -*/ - -#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], std::ios::binary); - 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/doc/examples/keywrap.cpp b/doc/examples/keywrap.cpp deleted file mode 100644 index 730bcb6c9..000000000 --- a/doc/examples/keywrap.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* -* NIST keywrap example -* (C) 2011 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/botan.h> -#include <botan/rfc3394.h> -#include <botan/hex.h> -#include <iostream> - -int main() - { - using namespace Botan; - - LibraryInitializer init; - - AutoSeeded_RNG rng; - - // The key to encrypt - SymmetricKey key(rng, 24); - - // The key encryption key - SymmetricKey kek(rng, 32); - - std::cout << "Original: " << key.as_string() << "\n"; - - Algorithm_Factory& af = global_state().algorithm_factory(); - - SecureVector<byte> enc = rfc3394_keywrap(key.bits_of(), kek, af); - - std::cout << "Encrypted: " << hex_encode(enc) << "\n"; - - SecureVector<byte> dec = rfc3394_keyunwrap(enc, kek, af); - - std::cout << "Decrypted: " << hex_encode(dec) << "\n"; - } diff --git a/doc/examples/make_prime.cpp b/doc/examples/make_prime.cpp deleted file mode 100644 index acaaac698..000000000 --- a/doc/examples/make_prime.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#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/doc/examples/new_engine.cpp b/doc/examples/new_engine.cpp deleted file mode 100644 index 42e5dbe33..000000000 --- a/doc/examples/new_engine.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* -* Adding an application specific engine -* (C) 2004,2008 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/stream_cipher.h> -#include <botan/engine.h> - -using namespace Botan; - -class XOR_Cipher : public StreamCipher - { - public: - void clear() throw() { mask.clear(); 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; } - - Key_Length_Specification key_spec() const - { - return Key_Length_Specification(1, 32); - } - - XOR_Cipher() : mask_pos(0) {} - private: - void cipher(const byte in[], byte out[], size_t length) - { - for(size_t j = 0; j != length; j++) - { - out[j] = in[j] ^ mask[mask_pos]; - mask_pos = (mask_pos + 1) % mask.size(); - } - } - - void key_schedule(const byte key[], size_t length) - { - mask.resize(length); - copy_mem(&mask[0], key, length); - } - - SecureVector<byte> mask; - u32bit mask_pos; - }; - -class Application_Engine : public Engine - { - public: - std::string provider_name() const { return "application"; } - - StreamCipher* find_stream_cipher(const SCAN_Name& request, - Algorithm_Factory&) const - { - if(request.algo_name() == "XOR") - return new XOR_Cipher; - return 0; - } - }; - -#include <botan/botan.h> -#include <iostream> -#include <string> - -int main() - { - - Botan::LibraryInitializer init; - - global_state().algorithm_factory().add_engine( - new Application_Engine); - - // 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/doc/examples/package.cpp b/doc/examples/package.cpp deleted file mode 100644 index 02cf52816..000000000 --- a/doc/examples/package.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/botan.h> -#include <botan/serpent.h> -#include <botan/package.h> - -#include <iostream> -#include <fstream> -#include <vector> - -using namespace Botan; - -namespace { - -std::vector<byte> slurp_file(const std::string& filename) - { - std::ifstream in(filename.c_str(), std::ios::binary); - - std::vector<byte> out; - byte buf[4096] = { 0 }; - - while(in.good()) - { - in.read((char*)buf, sizeof(buf)); - ssize_t got = in.gcount(); - - out.insert(out.end(), buf, buf+got); - } - - return out; - } - -} - -int main(int argc, char* argv[]) - { - if(argc != 2) - { - std::cout << "Usage: " << argv[0] << " filename\n"; - return 1; - } - - LibraryInitializer init; - - AutoSeeded_RNG rng; - - BlockCipher* cipher = new Serpent; - - std::vector<byte> input = slurp_file(argv[1]); - std::vector<byte> output(input.size() + cipher->block_size()); - - aont_package(rng, new Serpent, - &input[0], input.size(), - &output[0]); - - std::vector<byte> unpackage_output(output.size() - cipher->block_size()); - - aont_unpackage(new Serpent, - &output[0], output.size(), - &unpackage_output[0]); - - if(unpackage_output == input) - std::cout << "Package/unpackage worked\n"; - else - std::cout << "Something went wrong :(\n"; - } diff --git a/doc/examples/passhash.cpp b/doc/examples/passhash.cpp deleted file mode 100644 index 586c28c3f..000000000 --- a/doc/examples/passhash.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/botan.h> -#include <botan/passhash9.h> -#include <iostream> -#include <memory> - -#include <stdio.h> - -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) - { - Botan::AutoSeeded_RNG rng; - - std::cout << "H('" << argv[1] << "') = " - << Botan::generate_passhash9(argv[1], rng) << '\n'; - } - else - { - bool ok = Botan::check_passhash9(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; - } diff --git a/doc/examples/pkcs10.cpp b/doc/examples/pkcs10.cpp deleted file mode 100644 index 3f5ec8e05..000000000 --- a/doc/examples/pkcs10.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* -* (C) 2003 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#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 = "[email protected]"; - - PKCS10_Request req = X509::create_cert_req(opts, priv_key, "SHA-1", 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/doc/examples/pqg_gen.cpp b/doc/examples/pqg_gen.cpp deleted file mode 100644 index c033dac3b..000000000 --- a/doc/examples/pqg_gen.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <iostream> -#include <fstream> -#include <string> -#include <vector> -#include <map> -#include <memory> - -#include <botan/botan.h> -#include <botan/auto_rng.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 std::runtime_error("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 std::runtime_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/doc/examples/read_ssh.cpp b/doc/examples/read_ssh.cpp deleted file mode 100644 index f6299a29d..000000000 --- a/doc/examples/read_ssh.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -/* -* Example of reading SSH2 format public keys (see RFC 4716) -*/ - -#include <fstream> -#include <botan/x509_key.h> -#include <botan/filters.h> -#include <botan/loadstor.h> -#include <botan/rsa.h> -#include <botan/dsa.h> - -using namespace Botan; - -namespace { - -u32bit read_u32bit(Pipe& pipe) - { - byte out[4] = { 0 }; - pipe.read(out, 4); - u32bit len = load_be<u32bit>(out, 0); - if(len > 10000) - throw Decoding_Error("Huge size in read_u32bit, something went wrong"); - return len; - } - -std::string read_string(Pipe& pipe) - { - u32bit len = read_u32bit(pipe); - - std::string out(len, 'X'); - pipe.read(reinterpret_cast<byte*>(&out[0]), len); - return out; - } - -BigInt read_bigint(Pipe& pipe) - { - u32bit len = read_u32bit(pipe); - - SecureVector<byte> buf(len); - pipe.read(&buf[0], len); - return BigInt::decode(buf); - } - -Public_Key* read_ssh_pubkey(const std::string& file) - { - std::ifstream in(file.c_str()); - - const std::string ssh_header = "---- BEGIN SSH2 PUBLIC KEY ----"; - const std::string ssh_trailer = "---- END SSH2 PUBLIC KEY ----"; - - std::string hex_bits; - - std::string line; - std::getline(in, line); - - if(line != ssh_header) - return 0; - - while(in.good()) - { - std::getline(in, line); - - if(line.find("Comment: ") == 0) - { - while(line[line.size()-1] == '\\') - std::getline(in, line); - std::getline(in, line); - } - - if(line == ssh_trailer) - break; - - hex_bits += line; - } - - Pipe pipe(new Base64_Decoder); - pipe.process_msg(hex_bits); - - std::string key_type = read_string(pipe); - - if(key_type != "ssh-rsa" && key_type != "ssh-dss") - return 0; - - if(key_type == "ssh-rsa") - { - BigInt e = read_bigint(pipe); - BigInt n = read_bigint(pipe); - return new RSA_PublicKey(n, e); - } - else if(key_type == "ssh-dss") - { - BigInt p = read_bigint(pipe); - BigInt q = read_bigint(pipe); - BigInt g = read_bigint(pipe); - BigInt y = read_bigint(pipe); - - return new DSA_PublicKey(DL_Group(p, q, g), y); - } - - return 0; - } - -} - -#include <botan/init.h> -#include <iostream> - -int main() - { - LibraryInitializer init; - - Public_Key* key = read_ssh_pubkey("dsa.ssh"); - - if(key == 0) - { - std::cout << "Failed\n"; - return 1; - } - - std::cout << X509::PEM_encode(*key); - - return 0; - } diff --git a/doc/examples/readme.txt b/doc/examples/readme.txt deleted file mode 100644 index fb6a03ddf..000000000 --- a/doc/examples/readme.txt +++ /dev/null @@ -1,77 +0,0 @@ -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, PBKDF 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/doc/examples/rng_test.cpp b/doc/examples/rng_test.cpp deleted file mode 100644 index c0d24fd80..000000000 --- a/doc/examples/rng_test.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/botan.h> -#include <botan/x931_rng.h> -#include <botan/hex.h> -#include <botan/lookup.h> - -#include <iostream> -#include <fstream> -#include <deque> -#include <stdexcept> - -using namespace Botan; - -namespace { - -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[], size_t len) throw() - { - for(size_t j = 0; j != len; j++) - out[j] = random(); - } - - std::string name() const { return "Fixed_Output_RNG"; } - - void reseed(size_t) {} - - void clear() throw() {} - - void add_entropy(const byte in[], size_t 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 = hex_decode(input); - prng.add_entropy(x.begin(), x.size()); - - SecureVector<byte> output(result.size() / 2); - prng.randomize(output, output.size()); - - if(hex_decode(result) != output) - std::cout << "FAIL"; - else - std::cout << "PASS"; - - std::cout << " Seed " << input << " " - << "Got " << hex_encode(output) << " " - << "Exp " << result << "\n"; - } - - } - -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 = split_on(line, ':'); - - if(l.size() != 2) - throw std::runtime_error("Bad line " + line); - - out.push_back(std::make_pair(l[0], l[1])); - } - - return out; - } - -} - -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"); - } diff --git a/doc/examples/row_encryptor.cpp b/doc/examples/row_encryptor.cpp deleted file mode 100644 index 685850945..000000000 --- a/doc/examples/row_encryptor.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#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); - - Row_Encryptor(const std::string& passphrase, - const MemoryRegion<byte>& salt); - - std::string encrypt(const std::string& input, - const MemoryRegion<byte>& salt); - - std::string decrypt(const std::string& input, - const MemoryRegion<byte>& salt); - - SecureVector<byte> get_pbkdf_salt() const { return pbkdf_salt; } - private: - void init(const std::string& passphrase); - - Row_Encryptor(const Row_Encryptor&) {} - Row_Encryptor& operator=(const Row_Encryptor&) { return (*this); } - - SecureVector<byte> pbkdf_salt; - 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) - { - pbkdf_salt.resize(10); // 80 bits - rng.randomize(&pbkdf_salt[0], pbkdf_salt.size()); - init(passphrase); - } - -Row_Encryptor::Row_Encryptor(const std::string& passphrase, - const MemoryRegion<byte>& salt) - { - pbkdf_salt = salt; - init(passphrase); - } - -void Row_Encryptor::init(const std::string& passphrase) - { - std::auto_ptr<PBKDF> pbkdf(get_pbkdf("PBKDF2(SHA-160)")); - - SecureVector<byte> key = pbkdf->derive_key(32, passphrase, - &pbkdf_salt[0], pbkdf_salt.size(), - 10000).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.process_msg(input); - 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.process_msg(input); - return dec_pipe.read_all_as_string(Pipe::LAST_MESSAGE); - } - -/* -* Test code follows: -*/ - -int main() - { - Botan::LibraryInitializer init; - - AutoSeeded_RNG rng; - - const std::string secret_passphrase = "secret passphrase"; - - Row_Encryptor encryptor("secret passphrase", rng); - - std::vector<std::string> original_inputs; - - for(u32bit i = 0; i != 50000; ++i) - { - std::ostringstream out; - - u32bit output_bytes = rng.next_byte(); - - for(u32bit j = 0; j != output_bytes; ++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]; - - for(u32bit j = 0; j != 4; ++j) - salt[j] = (i >> 8) & 0xFF; - - encrypted_values.push_back(encryptor.encrypt(input, salt)); - } - - for(u32bit i = 0; i != encrypted_values.size(); ++i) - { - std::string ciphertext = encrypted_values[i]; - - // NOTE: same salt value as previous loop (index value) - for(u32bit j = 0; j != 4; ++j) - salt[j] = (i >> 8) & 0xFF; - - std::string output = encryptor.decrypt(ciphertext, salt); - - if(output != original_inputs[i]) - std::cout << "BOOM " << i << "\n"; - } - - Row_Encryptor test_pbkdf_salt_copy(secret_passphrase, - encryptor.get_pbkdf_salt()); - - zeroise(salt); - std::string test = test_pbkdf_salt_copy.decrypt(encrypted_values[0], salt); - if(test != original_inputs[0]) - std::cout << "PBKDF salt copy failed to decrypt properly\n"; - - return 0; - } diff --git a/doc/examples/rsa_dec.cpp b/doc/examples/rsa_dec.cpp deleted file mode 100644 index 81592328c..000000000 --- a/doc/examples/rsa_dec.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* -* (C) 2002-2010 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -/* -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. -*/ - -#include <iostream> -#include <fstream> -#include <string> -#include <memory> - -#include <botan/botan.h> -#include <botan/pubkey.h> -#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(), std::ios::binary); - 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); - - PK_Decryptor_EME 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/doc/examples/rsa_enc.cpp b/doc/examples/rsa_enc.cpp deleted file mode 100644 index ac609c4b3..000000000 --- a/doc/examples/rsa_enc.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* -* (C) 2002 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -/* - 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. -*/ - -#include <iostream> -#include <fstream> -#include <string> -#include <memory> - -#include <botan/botan.h> -#include <botan/pubkey.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], std::ios::binary); - 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; - - PK_Encryptor_EME 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<size_t>(32, - 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/doc/examples/rsa_kgen.cpp b/doc/examples/rsa_kgen.cpp deleted file mode 100644 index f4566263b..000000000 --- a/doc/examples/rsa_kgen.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* -* (C) 2002 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -/* -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). -*/ - -#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 > 16384) - { - 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/doc/examples/rsa_manykey.cpp b/doc/examples/rsa_manykey.cpp deleted file mode 100644 index e6a511753..000000000 --- a/doc/examples/rsa_manykey.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -/* -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/doc/examples/self_sig.cpp b/doc/examples/self_sig.cpp deleted file mode 100644 index 6710cfb51..000000000 --- a/doc/examples/self_sig.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* -* (C) 2003 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -/* -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. -*/ - -#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 = "[email protected]"; - - if(do_CA) - opts.CA_key(); - - X509_Certificate cert = - X509::create_self_signed_cert(opts, key, "SHA-256", 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/doc/examples/sig_gen.cpp b/doc/examples/sig_gen.cpp deleted file mode 100644 index cf273216a..000000000 --- a/doc/examples/sig_gen.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <iostream> -#include <fstream> -#include <string> -#include <vector> -#include <map> -#include <memory> - -#include <botan/botan.h> -#include <botan/dsa.h> -#include <botan/pubkey.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(); - - PK_Verifier verifier(key, "EMSA1(SHA-1)"); - - return verifier.verify_message(pipe.read_all(0), pipe.read_all(1)); - } diff --git a/doc/examples/stack.cpp b/doc/examples/stack.cpp deleted file mode 100644 index 0c00ed183..000000000 --- a/doc/examples/stack.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* -* (C) 2002 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -/* -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. -*/ - -#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], std::ios::binary); - 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/doc/examples/tls_client.cpp b/doc/examples/tls_client.cpp deleted file mode 100644 index 10ead20cc..000000000 --- a/doc/examples/tls_client.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* -* (C) 2008 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/init.h> -#include <botan/tls_client.h> -#include <botan/unx_sock.h> - -using namespace Botan; - -#include <stdio.h> -#include <string> -#include <iostream> -#include <memory> - -class Client_TLS_Policy : public TLS_Policy - { - public: - bool check_cert(const std::vector<X509_Certificate>& certs) const - { - for(size_t i = 0; i != certs.size(); ++i) - { - std::cout << certs[i].to_string(); - } - - std::cout << "Warning: not checking cert signatures\n"; - - return true; - } - }; - -int main(int argc, char* argv[]) - { - if(argc != 2 && argc != 3) - { - printf("Usage: %s host [port]\n", argv[0]); - return 1; - } - - try - { - LibraryInitializer init; - - std::string host = argv[1]; - u32bit port = argc == 3 ? Botan::to_u32bit(argv[2]) : 443; - - printf("Connecting to %s:%d...\n", host.c_str(), port); - - Unix_Socket sock(argv[1], port); - - std::auto_ptr<Botan::RandomNumberGenerator> rng( - Botan::RandomNumberGenerator::make_rng()); - - Client_TLS_Policy policy; - - TLS_Client tls(std::tr1::bind(&Socket::read, std::tr1::ref(sock), _1, _2), - std::tr1::bind(&Socket::write, std::tr1::ref(sock), _1, _2), - policy, *rng); - - printf("Handshake extablished...\n"); - -#if 0 - std::string http_command = "GET / HTTP/1.1\r\n" - "Server: " + host + ':' + to_string(port) + "\r\n\r\n"; -#else - std::string http_command = "GET / HTTP/1.0\r\n\r\n"; -#endif - - tls.write((const byte*)http_command.c_str(), http_command.length()); - - u32bit total_got = 0; - - while(true) - { - if(tls.is_closed()) - break; - - byte buf[16+1] = { 0 }; - u32bit got = tls.read(buf, sizeof(buf)-1); - printf("%s", buf); - fflush(0); - - total_got += got; - } - - printf("\nRetrieved %d bytes total\n", total_got); - } - catch(std::exception& e) - { - printf("%s\n", e.what()); - return 1; - } - return 0; - } diff --git a/doc/examples/tls_server.cpp b/doc/examples/tls_server.cpp deleted file mode 100644 index da13953f8..000000000 --- a/doc/examples/tls_server.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* -* (C) 2008-2010 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/botan.h> -#include <botan/tls_server.h> -#include <botan/unx_sock.h> - -#include <botan/rsa.h> -#include <botan/dsa.h> -#include <botan/x509self.h> - -using namespace Botan; - -#include <stdio.h> -#include <string> -#include <iostream> -#include <memory> - -class Server_TLS_Policy : public TLS_Policy - { - public: - bool check_cert(const std::vector<X509_Certificate>& certs) const - { - for(size_t i = 0; i != certs.size(); ++i) - { - std::cout << certs[i].to_string(); - } - - std::cout << "Warning: not checking cert signatures\n"; - - return true; - } - }; -int main(int argc, char* argv[]) - { - - int port = 4433; - - if(argc == 2) - port = to_u32bit(argv[1]); - - try - { - LibraryInitializer init; - - AutoSeeded_RNG rng; - - //RSA_PrivateKey key(rng, 1024); - DSA_PrivateKey key(rng, DL_Group("dsa/jce/1024")); - - X509_Cert_Options options( - "localhost/US/Syn Ack Labs/Mathematical Munitions Dept"); - - X509_Certificate cert = - X509::create_self_signed_cert(options, key, "SHA-1", rng); - - Unix_Server_Socket listener(port); - - Server_TLS_Policy policy; - - while(true) - { - try { - printf("Listening for new connection on port %d\n", port); - - Socket* sock = listener.accept(); - - printf("Got new connection\n"); - - TLS_Server tls( - std::tr1::bind(&Socket::read, std::tr1::ref(sock), _1, _2), - std::tr1::bind(&Socket::write, std::tr1::ref(sock), _1, _2), - policy, - rng, - cert, - key); - - std::string hostname = tls.requested_hostname(); - - if(hostname != "") - printf("Client requested host '%s'\n", hostname.c_str()); - - printf("Writing some text\n"); - - char msg[] = "Foo\nBar\nBaz\nQuux\n"; - tls.write((const byte*)msg, strlen(msg)); - - printf("Now trying a read...\n"); - - char buf[1024] = { 0 }; - u32bit got = tls.read((byte*)buf, sizeof(buf)-1); - printf("%d: '%s'\n", got, buf); - - tls.close(); - } - catch(std::exception& e) { printf("%s\n", e.what()); } - } - } - catch(std::exception& e) - { - printf("%s\n", e.what()); - return 1; - } - return 0; - } diff --git a/doc/examples/toolbox.cpp b/doc/examples/toolbox.cpp deleted file mode 100644 index 622a1f56f..000000000 --- a/doc/examples/toolbox.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/botan.h> - -#if defined(BOTAN_HAS_COMPRESSOR_BZIP2) - #include <botan/bzip2.h> -#endif - -#if defined(BOTAN_HAS_COMPRESSOR_ZLIB) - #include <botan/zlib.h> -#endif - -#include <iostream> -#include <fstream> - -using namespace Botan; - -#include "../../checks/getopt.h" - -class Encoder_Decoder - { - public: - Encoder_Decoder(const std::string& command, - bool decode, - const std::vector<std::string>& args) : - type(command), - args(args), - decode(decode) - { } - - void run(std::istream& in, std::ostream& out) - { - Filter* filt = decode ? decoder(type) : encoder(type); - - DataSource_Stream src(in); - Pipe pipe(filt, new DataSink_Stream(out)); - pipe.process_msg(src); - } - - Filter* encoder(const std::string& type) const - { - if(type == "hex") return new Hex_Encoder; - if(type == "base64") return new Base64_Encoder; - -#if defined(BOTAN_HAS_COMPRESSOR_BZIP2) - if(type == "bzip2") return new Bzip_Compression; -#endif - -#if defined(BOTAN_HAS_COMPRESSOR_ZLIB) - if(type == "zlib") return new Zlib_Compression; -#endif - return 0; - } - - Filter* decoder(const std::string& type) const - { - if(type == "hex") return new Hex_Decoder; - if(type == "base64") return new Base64_Decoder; - -#if defined(BOTAN_HAS_COMPRESSOR_BZIP2) - if(type == "bzip2") return new Bzip_Decompression; -#endif - -#if defined(BOTAN_HAS_COMPRESSOR_ZLIB) - if(type == "zlib") return new Zlib_Decompression; -#endif - - return 0; - } - - private: - std::string type; - std::vector<std::string> args; - bool decode; - }; - -void run_command(const std::string& command, - const std::vector<std::string>& arguments, - const OptionParser& opts) - { - if(command == "hex" || - command == "base64" || - command == "bzip2" || - command == "zlib") - { - bool decode = opts.is_set("decode"); - - std::string output = opts.value_or_else("output", "-"); - std::string input = opts.value_or_else("input", "-"); - - Encoder_Decoder enc_dec(command, decode, arguments); - - try - { - if(output == "-") - { - if(input == "-") - enc_dec.run(std::cin, std::cout); - else - { - std::ifstream in(input.c_str()); - enc_dec.run(in, std::cout); - } - } - else // output != "-" - { - std::ofstream out(output.c_str()); - - if(input == "-") - enc_dec.run(std::cin, out); - else - { - std::ifstream in(input.c_str()); - enc_dec.run(in, out); - } - } - } - catch(Botan::Stream_IO_Error& e) - { - std::cout << "I/O failure - " << e.what() << '\n'; - } - } - else if(command == "hash" || - command == "sha1" || - command == "md5") - { - std::string hash; - - if(command == "md5") - hash = "MD5"; - if(command == "sha1") - hash = "SHA-160"; - else - hash = opts.value_or_else("hash", "SHA-160"); // sha1 is default - - Pipe pipe(new Hash_Filter(get_hash(hash)), - new Hex_Encoder(false, 0, Hex_Encoder::Lowercase)); - - for(size_t i = 0; i != arguments.size(); ++i) - { - std::string file_name = arguments[i]; - - u32bit previously = pipe.message_count(); - - if(file_name == "-") - { - pipe.start_msg(); - std::cin >> pipe; - pipe.end_msg(); - } - else - { - std::ifstream in(file_name.c_str()); - if(in) - { - pipe.start_msg(); - in >> pipe; - pipe.end_msg(); - } - else - std::cerr << "Could not read " << file_name << '\n'; - } - - if(pipe.message_count() > previously) - std::cout << pipe.read_all_as_string(Pipe::LAST_MESSAGE) << " " - << file_name << '\n'; - } - - } - else - { - std::cerr << "Command " << command << " not known\n"; - } - } - -int main(int argc, char* argv[]) - { - LibraryInitializer init; - - OptionParser opts("help|version|seconds=|" - "input=|output=|decode|" - "hash=|key="); - - try - { - opts.parse(argv); - } - catch(std::runtime_error& e) - { - std::cout << "Command line problem: " << e.what() << '\n'; - return 2; - } - - if(opts.is_set("version") || argc <= 1) - { - std::cerr << "Botan Toolbox v" << version_string() << '\n'; - std::cerr << "Commands: hash hex base64 "; -#if defined(BOTAN_HAS_COMPRESSOR_BZIP2) - std::cerr << "bzip2 "; -#endif - -#if defined(BOTAN_HAS_COMPRESSOR_ZLIB) - std::cerr << "zlib "; -#endif - - std::cerr << "\n"; - - return 0; - } - - if(opts.is_set("help")) - { - std::vector<std::string> what = opts.leftovers(); - - for(size_t i = 0; i != what.size(); ++i) - std::cerr << what[i] << "? Never heard of it\n"; - return 0; - } - - std::vector<std::string> args = opts.leftovers(); - - if(args.size() == 0) - return 0; - - std::string command = args[0]; - args.erase(args.begin()); - - run_command(command, args, opts); - - return 0; - } diff --git a/doc/examples/tss.cpp b/doc/examples/tss.cpp deleted file mode 100644 index 03d7699bf..000000000 --- a/doc/examples/tss.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/botan.h> -#include <botan/tss.h> -#include <iostream> -#include <stdio.h> - -namespace { - -void print(const Botan::SecureVector<Botan::byte>& r) - { - for(Botan::u32bit i = 0; i != r.size(); ++i) - printf("%02X", r[i]); - printf("\n"); - } - -} - -int main() - { - using namespace Botan; - - LibraryInitializer init; - - AutoSeeded_RNG rng; - - byte id[16]; - for(int i = 0; i != 16; ++i) - id[i] = i; - - const byte S2[] = { 0xDE, 0xAD, 0xCA, 0xFE, 0xBA, 0xBE, 0xBE, 0xEF }; - - std::vector<RTSS_Share> shares = - RTSS_Share::split(4, 6, S2, sizeof(S2), id, rng); - - for(size_t i = 0; i != shares.size(); ++i) - std::cout << i << " = " << shares[i].to_string() << "\n"; - - print(RTSS_Share::reconstruct(shares)); - } diff --git a/doc/examples/x509info.cpp b/doc/examples/x509info.cpp deleted file mode 100644 index b22b4ebd8..000000000 --- a/doc/examples/x509info.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* -* Read an X.509 certificate, and print various things about it -* (C) 2003 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/botan.h> -#include <botan/x509cert.h> -using namespace Botan; - -#include <iostream> - -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 << cert.to_string(); - } - catch(std::exception& e) - { - std::cout << e.what() << std::endl; - return 1; - } - return 0; - } diff --git a/doc/filters.txt b/doc/filters.txt new file mode 100644 index 000000000..8ce396371 --- /dev/null +++ b/doc/filters.txt @@ -0,0 +1,782 @@ + +Information Flow: Pipes and Filters +======================================== + +Many common uses of cryptography involve processing one or more +streams of data. 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 *filters* in Botan. A set of filters are created and placed into +a *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:: + + 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" + +Bytestreams in the pipe are grouped into messages; blocks of data that +are processed in an identical fashion (ie, with the same sequence of +filter operations). Messages are delimited by calls to ``start_msg`` +and ``end_msg``. Each message in a pipe has its own identifier, which +currently is an integer that increments up from zero. + +The ``Base64_Encoder`` was allocated using ``new``; but where was it +deallocated? When a filter object is passed to a ``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 ``Pipe`` without changing the ``Pipe`` +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 *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 +``Pipe`` between each message, by adding or removing filters; +functions that let you do this are documented in the Pipe API section. + +Botan has about 40 filters that perform different operations on data. +Here's code that uses one of them to encrypt a string with AES:: + + AutoSeeded_RNG rng, + SymmetricKey key(rng, 16); // a random 128-bit key + InitializationVector iv(rng, 16); // a random 128-bit IV + + // 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 }; + size_t got_out = pipe.read(c2, sizeof(c2), 1); + // use c2[0...got_out] + +Note the use of ``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 +``AutoSeeded_RNG`` is preferable. + +``Pipe`` also has convenience methods for dealing with +``std::iostream``s. Here is an example of those, using the +``Bzip_Compression`` filter (included as a module; if you have bzlib +available, check the build instructions for how to enable it) to +compress a file:: + + 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; + +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 ``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:: + + 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(); + +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 +``DataSink_Stream``. Anything written to a ``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 ``pipe.read_all()`` after ``pipe.end_msg()``, you'd get +an empty vector out. + +Here's an example using two computational filters:: + + 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; + +Fork +--------------------------------- + +It is 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 +``Fork`` comes in. ``Fork`` is a filter that takes input and passes it +on to *one or more* filters that are attached to it. ``Fork`` changes +the nature of the pipe system completely: instead of being a linked +list, it becomes a tree or acyclic graph. + +Each 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 pipe, then you start a new one with a fork that has three +paths of filter's inside it, you add three new messages to the +pipe. The data you put into the pipe is duplicated and sent +into each set of filter and the eventual output is placed into a +dedicated message slot in the pipe. + +Messages in the pipe are allocated in a depth-first manner. This is only +interesting if you are using more than one fork in a single pipe. +As an example, consider the following:: + + Pipe pipe(new Fork( + new Fork( + new Base64_Encoder, + new Fork( + NULL, + new Base64_Encoder + ) + ), + new Hex_Encoder + ) + ); + +In this case, message 0 will be the output of the first +``Base64_Encoder``, message 1 will be a copy of the input (see below +for how fork interprets NULL pointers), message 2 will be the output +of the second ``Base64_Encoder``, and message 3 will be the output of +the ``Hex_Encoder``. 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 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:: + + // 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(); + +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 filters that are attached to the pipe after the fork are +implicitly attached onto the first branch created by the fork. For +example, let's say you created this pipe:: + + Pipe pipe(new Fork(new Hash_Filter("MD5"), new Hash_Filter("SHA-1")), + new Hex_Encoder); + +And then called ``start_msg``, inserted some data, then +``end_msg``. Then ``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 ``Chain`` +instead. + +Chain +--------------------------------- + +A ``Chain`` filter creates a chain of filters 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 ``Fork`` constructor. + +You can call ``Chain``'s constructor with up to four ``Filter`` +pointers (they will be added in order), or with an array of filter +pointers and a ``size_t`` that tells ``Chain`` how many filters 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 implicit +passthrough the other version used:: + + Pipe pipe(new Fork( + new Chain(new Hash_Filter("MD5"), new Hex_Encoder), + new Hash_Filter("SHA-1") + ) + ); + +Sources and Sinks +---------------------------------------- + +Data Sources +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A ``DataSource`` is a simple abstraction for a thing that stores bytes. This +type is used heavily in the areas of the API related to ASN.1 +encoding/decoding. The following types are ``DataSource``s: ``Pipe``, +``SecureQueue``, and a couple of special purpose ones: +``DataSource_Memory`` and ``DataSource_Stream``. + +You can create a ``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 ``DataSource_Stream`` is probably more useful than the memory based +one. Its constructors take either a ``std::istream`` or a +``std::string``. If it's a stream, the data source will use the +``istream`` to satisfy read requests (this is particularly useful to use +with ``std::cin``). If the string version is used, it will attempt to open +up a file with that name and read from it. + +Data Sinks +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A ``DataSink`` (in ``data_snk.h``) is a ``Filter`` that +takes arbitrary amounts of input, and produces no output. This means +it's doing something with the data outside the realm of what +``Filter``/``Pipe`` can handle, for example, writing it to a +file (which is what the ``DataSink_Stream`` does). There is no +need for ``DataSink``s that write to a ``std::string`` or memory +buffer, because ``Pipe`` can handle that by itself. + +Here's a quick example of using a ``DataSink``, which encrypts +``in.txt`` and sends the output to ``out.txt``. There is +no explicit output operation; the writing of ``out.txt`` is +implicit:: + + DataSource_Stream in("in.txt"); + Pipe pipe(new CBC_Encryption("AES-128", "PKCS7", key, iv), + new DataSink_Stream("out.txt")); + pipe.process_msg(in); + +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 be used. + +The Pipe API +--------------------------------- + +Initializing Pipe +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +By default, ``Pipe`` will do nothing at all; any input placed into the +``Pipe`` will be read back unchanged. Obviously, this has limited +utility, and presumably you want to use one or more filters to somehow +process the data. First, you can choose a set of filters to initialize +the ``Pipe`` via the constructor. You can pass it either a set of up +to four filter pointers, or a pre-defined array and a length:: + + 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); + +This is by far the most common way to initialize a ``Pipe``. However, +occasionally a more flexible initialization strategy is necessary; +this is supported by 4 member functions. These functions may only be +used while the pipe in question is not in use; that is, either before +calling ``start_msg``, or after ``end_msg`` has been called (and no +new calls to ``start_msg`` have been made yet). + +.. cpp:function:: void Pipe::prepend(Filter* filter) + + Calling ``prepend`` will put the passed filter first in the list of + transformations. For example, if you prepend a filter implementing + encryption, and the pipe already had a filter that hex encoded the + input, then the next message processed would be first encrypted, + and *then* hex encoded. + +.. cpp:function:: void Pipe::append(Filter* filter) + + Like ``prepend``, but places the filter at the end of the message + flow. This doesn't always do what you expect if there is a fork. + +.. cpp:function:: void Pipe::pop() + + Removes the first filter in the flow. + +.. cpp:function:: void Pipe::reset() + + Removes all the filters that the pipe currently holds - it is reset + to an empty/no-op state. Any data that is being retained by the + pipe is retained after a ``reset``, and ``reset`` does not affect + message numbers (discussed later). + +Giving Data to a Pipe +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Input to a ``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). + +.. cpp:function:: void Pipe::start_msg() + + Starts a new message; if a message was already running, an exception is + thrown. After this function returns, you can call ``write``. + +.. cpp:function:: void Pipe::write(const byte* input, size_t length) + +.. cpp:function:: void Pipe::write(const MemoryRegion<byte>& input) + +.. cpp:function:: void Pipe::write(const std::string& input) + +.. cpp:function:: void Pipe::write(DataSource& input) + +.. cpp:function:: void Pipe::write(byte input) + + All versions of ``write`` write the input into the filter sequence. + If a message is not currently active, an exception is thrown. + +.. cpp:function:: void Pipe::end_msg() + + End the currently active message + +Sometimes, you may want to do only a single write per message. In this +case, you can use the ``process_msg`` series of functions, which start +a message, write their argument into the pipe, and then end the +message. In this case you would not make any explicit calls to +``start_msg``/``end_msg``. + +Pipes can also be used with the ``>>`` operator, and will accept a +``std::istream``, or on Unix systems with the ``fd_unix`` module, a +Unix file descriptor. In either case, the entire contents of the file +will be read into the pipe. + +Getting Output from a Pipe +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Retrieving the processed data from a pipe is a bit more complicated, +for various reasons. The pipe will separate each message into a +separate buffer, and you have to retrieve data from each message +independently. Each of the reader functions has a final parameter that +specifies what message to read from. If this parameter is set to +``Pipe::DEFAULT_MESSAGE``, it will read the current default message +(``DEFAULT_MESSAGE`` is also the default value of this parameter). + +Functions in ``Pipe`` related to reading include: + +.. cpp:function:: size_t Pipe::read(byte* out, size_t len) + + Reads up to ``len`` bytes into ``out``, and returns the number of + bytes actually read. + +.. cpp:function:: size_t Pipe::peek(byte* out, size_t len) + + Acts exactly like `read`, except the data is not actually read; the + next read will return the same data. + +.. cpp:function:: SecureVector<byte> Pipe::read_all() + + Reads the entire message into a buffer and returns it + +.. cpp:function:: std::string Pipe::read_all_as_string() + + Like ``read_all``, but it returns the data as a ``std::string``. + No encoding is done; if the message contains raw binary, so will + the string. + +.. cpp:function:: size_t Pipe::remaining() + + Returns how many bytes are left in the message + +.. cpp:function:: Pipe::message_id default_msg() + + Returns the current default message number + +.. cpp:function:: Pipe::message_id Pipe::message_count() + + Returns the total number of messages currently in the pipe + +.. cpp:function:: Pipe::set_default_msg(Pipe::message_id msgno) + + Sets the default message number (which must be a valid message + number for that pipe). The ability to set the default message number + is particularly important in the case of using the file output + operations (``<<`` with a ``std::ostream`` or Unix file descriptor), + because there is no way to specify the message explicitly when using + the output operator. + +Pipe I/O for Unix File Descriptors +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This is a minor feature, but it comes in handy sometimes. In all +installations of the library, Botan's ``Pipe`` object overloads the +``<<`` and ``>>`` 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 ``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 ``hash_fd`` example, included in the Botan distribution. + +A Filter Example +--------------------------------- + +Here is some code that takes one or more filenames in ``argv`` and +calculates the result of several hash functions for each file. The complete +program can be found as ``hasher.cpp`` in the Botan distribution. For +brevity, error checking has been removed:: + + string name[3] = { "MD5", "SHA-1", "RIPEMD-160" }; + Filter* hash[3] = { + new Chain(new Hash_Filter(name[0]), + new Hex_Encoder), + new Chain(new Hash_Filter(name[1]), + new Hex_Encoder), + new Chain(new Hash_Filter(name[2]), + new Hex_Encoder) }; + + Pipe pipe(new Fork(hash, COUNT)); + + for(size_t j = 1; argv[j] != 0; j++) + { + ifstream file(argv[j]); + pipe.start_msg(); + file >> pipe; + pipe.end_msg(); + file.close(); + for(size_t k = 0; k != 3; k++) + { + pipe.set_default_msg(3*(j-1)+k); + cout << name[k] << "(" << argv[j] << ") = " << pipe << endl; + } + } + + +Filter Catalog +--------------------------------- + +This section documents most of the useful filters included in the +library. + +Keyed Filters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A few sections ago, it was mentioned that ``Pipe`` can process +multiple messages, treating each of them 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 ``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, ``set_key`` and ``set_iv``. Calling +``set_key`` will set (or reset) the key used by the algorithm. Setting +the IV only makes sense in certain algorithms -- a call to ``set_iv`` +on an object that doesn't support IVs will cause an exception. You +must call ``set_key`` *before* calling ``set_iv``. + +Here's a example:: + + 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(); + +There are some requirements to using ``Keyed_Filter`` that you must +follow. If you call ``set_key`` or ``set_iv`` on a filter that +is owned by a ``Pipe``, you must do so while the ``Pipe`` is +"unlocked". This refers to the times when no messages are being processed by +``Pipe`` -- either before ``Pipe``'s ``start_msg`` is called, or +after ``end_msg`` is called (and no new call to ``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 *first*. + +Cipher Filters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Getting a hold of a ``Filter`` implementing a cipher is very +easy. Make sure you're including the header ``lookup.h``, and +then call ``get_cipher``. You will pass the return value +directly into a ``Pipe``. There are a couple different functions +which do varying levels of initialization: + +.. cpp:function:: Keyed_Filter* get_cipher(std::string cipher_spec, SymmetricKey key, InitializationVector iv, Cipher_Dir dir) + +.. cpp:function:: Keyed_Filter* get_cipher(std::string cipher_spec, SymmetricKey key, Cipher_Dir 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 cipher spec that does want a IV, and you use the version +that doesn't take one, an exception will be thrown. The ``dir`` +argument can be either ``ENCRYPTION`` or ``DECRYPTION``. + +The cipher_spec is a string that specifies what cipher is to be +used. The general syntax for "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 "cipher_spec arguments are: "AES-128/CBC", +"Blowfish/CTR-BE", "Serpent/XTS", and "AES-256/EAX". + +"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. + +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 +``end_msg`` is called, at which time they complete the hash or MAC and +send that as output. + +These filters 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. + +.. cpp:function:: Hash_Filter::Hash_Filter(std::string hash, size_t outlen = 0) + + This constructor creates a filter that hashes its input with + ``hash``. When ``end_msg`` is called on the owning pipe, the hash is + completed and the digest is sent on to the next filter in the + pipeline. The parameter ``outlen`` specifies how many bytes of the + hash output will be passed along to the next filter when ``end_msg`` + is called. By default, it will pass the entire hash. + + Examples of names for ``Hash_Filter`` are "SHA-1" and "Whirlpool". + +.. cpp:function:: MAC_Filter::MAC_Filter(std::string mac, SymmetricKey key, size_t outlen = 0) + + This constructor takes a name for a mac, such as "HMAC(SHA-1)" or + "CMAC(AES-128)", along with a key to use. The optional ``outlen`` + works the same as in ``Hash_Filter``. + +PK Filters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There are four classes in this category, ``PK_Encryptor_Filter``, +``PK_Decryptor_Filter``, ``PK_Signer_Filter``, and +``PK_Verifier_Filter``. Each takes a pointer to an object of the +appropriate type (``PK_Encryptor``, ``PK_Decryptor``, etc) that is +deleted by the destructor. These classes are found in ``pk_filts.h``. + +Three of these, for encryption, decryption, and signing are much the +same in terms of dataflow - ach of them buffers its input until the +end of the message is marked with a call to the ``end_msg`` +function. Then they encrypt, decrypt, or sign the entire input as a +single blob 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 +``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 ``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), see +:ref:`public_key_crypto`. + +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 +``Hex_Encoder`` and ``Base64_Encoder`` will convert arbitrary binary +data into hex or base64 formats. Not surprisingly, you can use +``Hex_Decoder`` and ``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 ``bool`` +which 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. If you want a specific value, set it. Otherwise the +default should be fine. + +Lastly, ``Hex_Encoder`` takes an argument of type ``Case``, which can +be ``Uppercase`` or ``Lowercase`` (default is ``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. + +You can find the declarations for these types in ``hex_filt.h`` and +``b64_filt.h``. + +Compressors +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There are two compression algorithms supported by Botan, zlib and +bzip2. 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 *before* you encrypt, because encryption seeks +to hide the redundancy that compression is supposed to try to find and remove. + +To test for Bzip2, check to see if ``BOTAN_HAS_COMPRESSOR_BZIP2`` is +defined. If so, you can include ``botan/bzip2.h``, which will declare +a pair of ``Filter`` objects: ``Bzip2_Compression`` and +``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 ``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. + +Zlib compression works much like Bzip2 compression. The only +differences in this case are that the macro is +``BOTAN_HAS_COMPRESSOR_ZLIB``, the header you need to include is +called ``botan/zlib.h`` (remember that you shouldn't just ``#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 +``Zlib_Compression`` and ``Zlib_Decompression``. + +Like Bzip2, a ``Zlib_Decompression`` object will throw an exception if +invalid (in the sense of not being in the Zlib format) data is passed +into it. + +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. + +Writing New Filters +--------------------------------- + +The system of filters and pipes was designed in an attempt to make it +as simple as possible to write new filter types. There are four +functions that need to be implemented by a class deriving from +``Filter``: + +.. cpp:function:: void Filter::write(const byte* input, size_t length) + + This function is what is called when a filter receives input for it + to process. The filter is not required to process the data right + away; many filters buffer their input before producing any output. A + filter will usually have ``write`` called many times during its + lifetime. + +.. cpp:function:: void Filter::send(byte* output, size_t 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 ``send`` + with whatever it wants to send along to the next filter. There is + also a version of ``send`` taking a single byte argument, as a + convenience. + +.. cpp:function:: void Filter::start_msg() + + Implementing this function is optional. Implement it if your filter + would like to do some processing or setup at the start of each + message, such as allocating a data structure. + +.. cpp:function:: void Filter::end_msg() + + Implementing this function is optional. It is called when it has + been requested that filters finish up their computations. The filter + should finish up with whatever computation it is working on (for + example, a compressing filter would flush the compressor and + ``send`` the final block), and empty any buffers in preparation for + processing a fresh new set of input. + +Additionally, if necessary, filters can define a constructor that +takes any needed arguments, and a destructor to deal with deallocating +memory, closing files, etc. + diff --git a/doc/fips140.tex b/doc/fips140.tex deleted file mode 100644 index 8b2004508..000000000 --- a/doc/fips140.tex +++ /dev/null @@ -1,156 +0,0 @@ -\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{[email protected]}} -\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/doc/indent.el b/doc/indent.el index 9811bf848..7fa2540b0 100644 --- a/doc/indent.el +++ b/doc/indent.el @@ -2,19 +2,14 @@ ; 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: +; M-x c-set-style <RET> and then enter "botan". -; (add-hook 'c++-mode-common-hook -; (function (lambda() -; (c-add-style "botan" botan t)))) - -(setq botan '( +(setq botan-style '( (c-basic-offset . 3) (c-comment-only-line-offset . 0) (c-offsets-alist @@ -55,3 +50,6 @@ (label . 0) ) )) + +(add-hook 'c++-mode-common-hook + (function (lambda () (c-add-style "botan" botan-style nil)))) diff --git a/doc/index.txt b/doc/index.txt new file mode 100644 index 000000000..1dfa6abcc --- /dev/null +++ b/doc/index.txt @@ -0,0 +1,27 @@ + +Botan Reference Manual +================================= + +Contents: + +.. toctree:: + :maxdepth: 2 + + intro + building + filters + pubkey + x509 + lowlevel + bigint + algos + pgpkeys + license + credits + log + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`search` diff --git a/doc/internals.tex b/doc/internals.tex deleted file mode 100644 index 5b1650f6e..000000000 --- a/doc/internals.tex +++ /dev/null @@ -1,179 +0,0 @@ -\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 ([email protected])} -\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/doc/intro.txt b/doc/intro.txt new file mode 100644 index 000000000..c9a153563 --- /dev/null +++ b/doc/intro.txt @@ -0,0 +1,169 @@ + +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 most modern C++ compilers. + +It is released under the 2 clause BSD license and can be used by +commercial and open source software; see :ref:`license` for the +specifics. + +The base library is written in ISO C++, so it can be ported with +minimal fuss, but a modules system is also used. This system exposes +system dependent code to the library through portable interfaces, +extending the set of services available to users. + +The primary system targets are 32 and 64 bit CPUs, with a flat memory +address space of at least 32 bits. Given the choice between optimizing +for 32 bit systems and 64 bit systems, 64 bit is preferred, on the +general theory that where performance is a real concern, modern 64 bit +processors are the obvious choice. Smaller devices like handhelds, +settop boxes, and smart phones are also capable of using Botan. + +The 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 algorithm in question. They can ask the +library if the algorithm exists, and if so, retrieve an object +implementing that algorithm. + +Recommended Reading +--------------------------------- + +It's a very good idea if you have some knowledge of cryptography +*before* trying to use the library. This is an area where it is very +easy to make mistakes, and where things are often subtle and/or +counterintuitive. Obviously the library tries to provide things at +a high level precisely to minimize the number of ways things can go +wrong, but naive use will almost certainly not result in a secure +system. + +Especially recommended are: + + - *Cryptography Engineering* + Niels Ferguson, Bruce Schneier, and Tadayoshi Kohno + + - *Security Engineering -- A Guide to Building Dependable Distributed Systems* + Ross Anderson + + - *Handbook of Applied Cryptography* Alfred J. Menezes, Paul C. Van + Oorschot, and Scott A. Vanstone (available online at + http://www.cacr.math.uwaterloo.ca/hac/) + +Getting Help +---------------------------------------- + +Questions or problems you have with Botan can be directed to the +`development mailing list +<http://lists.randombit.net/mailman/listinfo/botan-devel/>`_. +"Philosophical" bug reports, announcements of programs using Botan, +and anything else having to do with Botan are also welcome. + +If you find what you believe to be a bug, please file a ticket in +`Bugzilla <http://bugs.randombit.net/>`_. + +Getting Started +--------------------------------- + +All declarations in the library are contained within the namespace +``Botan``, so you need to either prefix types with ``Botan::`` or add +a ``using`` declaration in your code. All examples will assume a +``using`` declaration. + +All library headers are included like so:: + + #include <botan/botan.h> + +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 ``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 +``LibraryInitializer`` is at the start of your ``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 (unless you +are writing threaded code; see below), all you need is:: + + Botan::LibraryInitializer init; + +at the start of your ``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 if you wish to share a single +object between threads. + +If you do not create a ``LibraryInitializer`` object, all library +operations will fail, because it will be unable to do basic things +like allocate memory or get random bits. You should never create more +than one ``LibraryInitializer``. + +Pitfalls +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There are a few things to watch out for to prevent problems when using +the library. + +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 ``LibraryInitializer``. Merely making the +``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 ``LibraryInitializer`` is +destroyed. This implies you can't have static variables that are Botan +objects inside functions or classes; in many C++ runtimes, these +objects will be destroyed after main has returned. + +The memory object classes (``MemoryRegion``, ``MemoryVector``, +``SecureVector``) are extremely primitive, and meant only for +secure storage of potentially sensitive data like keys. They do not +meet the requirements for an STL container object and you should not +try to use them with STL algorithms. For a general-purpose container, +use ``std::vector``. + +Use a ``try``/``catch`` block inside your ``main`` function, and catch +any ``std::exception`` throws (remember to catch by reference, as +``std::exception::what`` is polymorphic):: + + int main() + { + try + { + LibraryInitializer init; + + // ... + } + catch(std::exception& e) + { + std::cerr << e.what() << "\n"; + } + } + +This is not strictly required, but if you don't, and Botan throws an +exception, the runtime will call ``std::terminate``, which usually +calls ``abort`` or something like it, leaving you (or worse, a user of +your application) wondering what went wrong. diff --git a/doc/license.txt b/doc/license.txt index f1b261eab..33b2f5982 100644 --- a/doc/license.txt +++ b/doc/license.txt @@ -1,42 +1,48 @@ -Botan (http://botan.randombit.net/) is distributed under these terms: - -Copyright (C) 1999-2011 Jack Lloyd - 2001 Peter J Jones - 2004-2007 Justin Karneges - 2004 Vaclav Ovsik - 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 - 2010 Olivier de Gaalon -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. + +.. _license: + +License +======================================== + +Botan (http://botan.randombit.net/) is distributed under these terms:: + + Copyright (C) 1999-2011 Jack Lloyd + 2001 Peter J Jones + 2004-2007 Justin Karneges + 2004 Vaclav Ovsik + 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 + 2010 Olivier de Gaalon + 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/doc/log.txt b/doc/log.txt index 8ceb13a60..d4dd96430 100644 --- a/doc/log.txt +++ b/doc/log.txt @@ -1,1545 +1,1884 @@ -* 1.9.16-dev, ????-??-?? - - Second release candidate for 1.10.0 - - Disable the by-default 'strong' checking of private keys that are - loaded from storage. You can always request key material sanity - checking using check_key. - - Bring back removed functions min_keylength_of, max_keylength_of, - keylength_multiple_of in lookup.h to avoid breaking applications. - -* 1.9.15, 2011-03-21 - - First release candidate for 1.10.0 - - Modify how message expansion is done in SHA-256 and SHA-512. - Instead of expanding the entire message at the start, compute them - in the minimum number of registers. Values are computed 15 rounds - before they are needed. On a Core i7-860, GCC 4.5.2, went from - 143 to 157 MiB/s in SHA-256, and 211 to 256 MiB/s in SHA-512. - - Pipe will delete empty output queues as soon as they are no longer - needed, even if earlier messages still have data unread. However an - (empty) entry in a deque of pointers will remain until all prior - messages are completely emptied. - - Avoid reading the SPARC %tick register on OpenBSD as unlike Linux - the kernel will not trap and emulate it for us, causing a illegal - instruction crash. - - Improve detection and autoconfiguration for ARM processors. - -* 1.9.14, 2011-03-01 - - Add support for bcrypt, OpenBSD's password hashing scheme - - Add support for NIST's AES key wrapping algorithm - - Fix an infinite loop in zlib filters introduced in 1.9.11 (PR 142) - -* 1.9.13, 2011-02-19 - - Update Keccak to the round 3 variant - - Fix ordering in GOST 34.10 signatures to match DNSSEC specifications - - Use size_t instead of u32bit for small integers in DER/BER codecs - - Add new build option --distribution-info - - Fix problems in the amalgamation build - - Fix building under Clang 2.9 and Sun Studio 12 - -* 1.9.12, 2010-12-13 - - Add the Keccak hash function - - Fix compilation problems in Python wrappers - - Fix compilation problem in OpenSSL engine - - Update SQLite3 database encryption codec - -* 1.9.11, 2010-11-29 - - Many SSL/TLS APIs have changed. This API is still unstable. - - The SSL interface requires TR1 (uses std::tr1::function) - - Fix SSL handshake failures when using RC4 ciphersuites - - Fix a number of CRL encoding and decoding bugs - - Counter mode now always encrypts 256 blocks in parallel - - Code where u32bit was used to represent a length now uses size_t - - Use small tables in the first round of AES - - Removed AES class: app must choose AES-128, AES-192, or AES-256 - - Add hex encoding/decoding functions that can be used without a Pipe - - Add base64 encoding functions that can be used without a Pipe - - Add to_string function to X509_Certificate - - Add support for dynamic engine loading on Windows - - Replace BlockCipher::BLOCK_SIZE attribute with function block_size() - - Replace HashFunction::HASH_BLOCK_SIZE attribute with hash_block_size() - - Changed semantics of MemoryRegion::resize and clear to match STL - - Removed MemoryRegion::append, replaced by push_back and operator+= - - Move PBKDF lookup to engine system - - The IDEA key schedule has been changed to run in constant time - - Avoid a possible timing vulnerability in Montgomery reduction - - Add Algorithm and Key_Length_Specification classes - - Switch default PKCS #8 encryption algorithm from AES-128 to AES-256 - - Update Skein-512 to match the v1.3 specification - - Allow using PBKDF2 with empty passphrases - - Add compile-time deprecation warnings for GCC, Clang, and MSVC - - Support use of HMAC(SHA-256) and CMAC(Blowfish) in passhash9 - - Improve support for Intel Atom processors - - Fix compilation problems under Sun Studio and Clang - -* 1.8.11, 2010-11-02 - - Fix a number of CRL encoding and decoding bugs - - When building a debug library under VC++, use the debug runtime - - Fix compilation under Sun Studio on Linux and Solaris - - Add several functions for compatability with 1.9 - - In the examples, read most input files as binary - - The Perl build script has been removed in this release - -* 1.8.10, 2010-08-31 - - Switch default PKCS #8 encryption algorithm from 3DES to AES-256 - - Increase default hash iterations from 2048 to 10000 in PBES1 and PBES2 - - Use small tables in the first round of AES - - Add PBKDF typedef and get_pbkdf for better compatability with 1.9 - - Add version of S2K::derive_key taking salt and iteration count - - Enable the /proc-walking entropy source on NetBSD - - Fix the doxygen makefile target - -* 1.9.10, 2010-08-12 - - Add a constant time AES implementation using SSSE3 - - Add support for loading new Engines at runtime - - Use GCC byteswap intrinsics where possible - - Drop support for building with Python 2.4 - - Fix benchmarking of block ciphers in ECB mode - - Consolidate the two x86 assembly engines - - Rename S2K to PBKDF - -* 1.9.9, 2010-06-28 - - Add new X509::BER_encode and PKCS8::BER_encode - - Give all Filter objects a name() function - - Add Keyed_Filter::valid_iv_length - - Increase default iteration counts for private key encryption - - Fix compilation of mp_asm64 on 64-bit MIPS with GCC 4.4 and later - - Fix compilation under Apple's GCC 4.2 - - Expand and update the Doxygen documentation - -* 1.8.9, 2010-06-16 - - Use constant time multiplication in IDEA - - Avoid possible timing attack against OAEP decoding - - Add new X509::BER_encode and PKCS8::BER_encode - - Enable DLL builds under Windows - - Add Win32 installer support - - Add support for the Clang compiler - - Fix problem in semcem.h preventing build under Clang or GCC 3.4 - - Fix bug that prevented creation of DSA groups under 1024 bits - - Fix crash in GMP_Engine if library is shutdown and reinitialized - - Work around problem with recent binutils in x86-64 SHA-1 - - The Perl build script is no longer supported and refuses to run by default - -* 1.9.8, 2010-06-14 - - Add support for wide multiplications on 64-bit Windows - - Use constant time multiplication in IDEA - - Avoid possible timing attack against OAEP decoding - - Removed FORK-256; rarely used and it has been broken - - Rename --use-boost-python to --with-boost-python - - Skip building shared libraries on MinGW/Cygwin - - Fix creation of 512 and 768 bit DL groups using the DSA kosherizer - - Fix compilation on GCC versions before 4.3 (missing cpuid.h) - - Fix compilation under the Clang compiler - -* 1.9.7, 2010-04-27 - - TLS: Support reading SSLv2 client hellos - - TLS: Add support for SEED ciphersuites (RFC 4162) - - Add Comb4P hash combiner function - - Fix checking of EMSA_Raw signatures with leading 0 bytes - -* 1.9.6, 2010-04-09 - - TLS: Add support for TLS v1.1 - - TLS: Support server name indicator extension - - TLS: Fix server handshake - - TLS: Fix server using DSA certificates - - TLS: Avoid timing channel between CBC padding check and MAC verification - -* 1.9.5, 2010-03-29 - - Numerous ECC optimizations - - Fix GOST 34.10-2001 X.509 key loading - - Allow PK_Signer's fault protection checks to be toggled off - - Avoid using pool-based locking allocator if we can't mlock - - Remove all runtime options - - New BER_Decoder::{decode_and_check, decode_octet_string_bigint} - - Remove SecureBuffer in favor of SecureVector length parameter - - HMAC_RNG: Perform a poll along with user-supplied entropy - - Fix crash in MemoryRegion if Allocator::get failed - - Fix small compilation problem on FreeBSD - -* 1.9.4, 2010-03-09 - - Add the Ajisai SSLv3/TLSv1.0 implementation - - Add GOST 34.10-2001 public key signature scheme - - Add SIMD implementation of Noekeon - - Add SSE2 implementation of IDEA - - Extend Salsa20 to support longer IVs (XSalsa20) - - Perform XTS encryption and decryption in parallel where possible - - Perform CBC decryption in parallel where possible - - Add SQLite3 db encryption codec, contributed by Olivier de Gaalon - - Add a block cipher cascade construction - - Add support for password hashing for authentication (passhash9.h) - - Add support for Win32 high resolution system timers - - Major refactoring and API changes in the public key code - - Use consistency checking (anti-fault attack) for all signature schemes - - Changed S2K interface: derive_key now takes salt, iteration count - - Remove dependency on TR1 for ECC and CVC code - - Renamed ECKAEG to its more usual name, ECDH - - Fix crash in GMP_Engine if library is shutdown and reinitialized - - Fix an invalid memory read in MD4 - - Fix Visual C++ static builds - - Remove Timer class entirely - - Switch default PKCS #8 encryption algorithm from 3DES to AES-128 - - New option --gen-amalgamation for creating a SQLite-style amalgamation - - Many headers are now explicitly internal-use-only and are not installed - - Greatly improve the Win32 installer - - Several fixes for Visual C++ debug builds - -* 1.9.3, 2009-11-19 - - Add new AES implementation using Intel's AES instruction intrinsics - - Add an implementation of format preserving encryption - - Allow use of any hash function in X.509 certificate creation - - Optimizations for MARS, Skipjack, and AES - - Set macros for available SIMD instructions in build.h - - Add support for using InnoSetup to package Windows builds - - By default build a DLL on Windows - -* 1.9.2, 2009-11-03 - - Add SIMD version of XTEA - - Support both SSE2 and AltiVec SIMD for Serpent and XTEA - - Optimizations for SHA-1 and SHA-2 - - Add AltiVec runtime detection - - Fix x86 CPU identification with Intel C++ and Visual C++ - -* 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.9.1, 2009-10-23 - - Better support for Python and Perl wrappers - - Add an implementation of Blue Midnight Wish (Round 2 tweak version) - - Modify Skein-512 to match the tweaked 1.2 specification - - Add threshold secret sharing (draft-mcgrew-tss-02) - - Add runtime cpu feature detection for x86/x86-64 - - Add code for general runtime self testing for hashes, MACs, and ciphers - - Optimize XTEA; twice as fast as before on Core2 and Opteron - - Convert CTR_BE and OFB from filters to stream ciphers - - New parsing code for SCAN algorithm names - - Enable SSE2 optimizations under Visual C++ - - Remove all use of C++ exception specifications - - Add support for GNU/Hurd and Clang/LLVM - -* 1.9.0, 2009-09-09 - - Add support for parallel invocation of block ciphers where possible - - Add SSE2 implementation of Serpent - - Add Rivest's package transform (an all or nothing transform) - - Minor speedups to the Turing key schedule - - Fix processing multiple messages in XTS mode - - Add --no-autoload option to configure.py, for minimized builds - - The previously used configure.pl script is no longer supported - -* 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.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.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.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.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.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.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 +Release Notes +======================================== + +2011 +---------------------------------------- + +1.9.16-dev, ????-??-?? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + * Second release candidate for 1.10.0 + * The documenation, previously written in LaTeX, is now in + reStructuredText suitable for processing by Sphinx, which can + generate HTML, PDFs, or man pages. + * Disable the by-default 'strong' checking of private keys that are + loaded from storage. You can always request key material sanity + checking using check_key. + * Bring back removed functions min_keylength_of, max_keylength_of, + keylength_multiple_of in lookup.h to avoid breaking applications. + +1.9.15, 2011-03-21 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + * First release candidate for 1.10.0 + * Modify how message expansion is done in SHA-256 and SHA-512. + Instead of expanding the entire message at the start, compute them + in the minimum number of registers. Values are computed 15 rounds + before they are needed. On a Core i7-860, GCC 4.5.2, went from + 143 to 157 MiB/s in SHA-256, and 211 to 256 MiB/s in SHA-512. + * Pipe will delete empty output queues as soon as they are no longer + needed, even if earlier messages still have data unread. However an + (empty) entry in a deque of pointers will remain until all prior + messages are completely emptied. + * Avoid reading the SPARC %tick register on OpenBSD as unlike Linux + the kernel will not trap and emulate it for us, causing a illegal + instruction crash. + * Improve detection and autoconfiguration for ARM processors. + +1.9.14, 2011-03-01 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + * Add support for bcrypt, OpenBSD's password hashing scheme + * Add support for NIST's AES key wrapping algorithm + * Fix an infinite loop in zlib filters introduced in 1.9.11 (PR 142) + +1.9.13, 2011-02-19 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + * Update Keccak to the round 3 variant + * Fix ordering in GOST 34.10 signatures to match DNSSEC specifications + * Use size_t instead of u32bit for small integers in DER/BER codecs + * Add new build option --distribution-info + * Fix problems in the amalgamation build + * Fix building under Clang 2.9 and Sun Studio 12 + +2010 +---------------------------------------- + +1.9.12, 2010-12-13 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + * Add the Keccak hash function + * Fix compilation problems in Python wrappers + * Fix compilation problem in OpenSSL engine + * Update SQLite3 database encryption codec + +1.9.11, 2010-11-29 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + * Many SSL/TLS APIs have changed. This API is still unstable. + * The SSL interface requires TR1 (uses std::tr1::function) + * Fix SSL handshake failures when using RC4 ciphersuites + * Fix a number of CRL encoding and decoding bugs + * Counter mode now always encrypts 256 blocks in parallel + * Code where u32bit was used to represent a length now uses size_t + * Use small tables in the first round of AES + * Removed AES class: app must choose AES-128, AES-192, or AES-256 + * Add hex encoding/decoding functions that can be used without a Pipe + * Add base64 encoding functions that can be used without a Pipe + * Add to_string function to X509_Certificate + * Add support for dynamic engine loading on Windows + * Replace BlockCipher::BLOCK_SIZE attribute with function block_size() + * Replace HashFunction::HASH_BLOCK_SIZE attribute with hash_block_size() + * Changed semantics of MemoryRegion::resize and clear to match STL + * Removed MemoryRegion::append, replaced by push_back and operator+= + * Move PBKDF lookup to engine system + * The IDEA key schedule has been changed to run in constant time + * Avoid a possible timing vulnerability in Montgomery reduction + * Add Algorithm and Key_Length_Specification classes + * Switch default PKCS #8 encryption algorithm from AES-128 to AES-256 + * Update Skein-512 to match the v1.3 specification + * Allow using PBKDF2 with empty passphrases + * Add compile-time deprecation warnings for GCC, Clang, and MSVC + * Support use of HMAC(SHA-256) and CMAC(Blowfish) in passhash9 + * Improve support for Intel Atom processors + * Fix compilation problems under Sun Studio and Clang + +1.8.11, 2010-11-02 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + * Fix a number of CRL encoding and decoding bugs + * When building a debug library under VC++, use the debug runtime + * Fix compilation under Sun Studio on Linux and Solaris + * Add several functions for compatability with 1.9 + * In the examples, read most input files as binary + * The Perl build script has been removed in this release + +1.8.10, 2010-08-31 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + * Switch default PKCS #8 encryption algorithm from 3DES to AES-256 + * Increase default hash iterations from 2048 to 10000 in PBES1 and PBES2 + * Use small tables in the first round of AES + * Add PBKDF typedef and get_pbkdf for better compatability with 1.9 + * Add version of S2K::derive_key taking salt and iteration count + * Enable the /proc-walking entropy source on NetBSD + * Fix the doxygen makefile target + +1.9.10, 2010-08-12 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + * Add a constant time AES implementation using SSSE3 + * Add support for loading new Engines at runtime + * Use GCC byteswap intrinsics where possible + * Drop support for building with Python 2.4 + * Fix benchmarking of block ciphers in ECB mode + * Consolidate the two x86 assembly engines + * Rename S2K to PBKDF + +1.9.9, 2010-06-28 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + * Add new X509::BER_encode and PKCS8::BER_encode + * Give all Filter objects a name() function + * Add Keyed_Filter::valid_iv_length + * Increase default iteration counts for private key encryption + * Fix compilation of mp_asm64 on 64-bit MIPS with GCC 4.4 and later + * Fix compilation under Apple's GCC 4.2 + * Expand and update the Doxygen documentation + +1.8.9, 2010-06-16 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + * Use constant time multiplication in IDEA + * Avoid possible timing attack against OAEP decoding + * Add new X509::BER_encode and PKCS8::BER_encode + * Enable DLL builds under Windows + * Add Win32 installer support + * Add support for the Clang compiler + * Fix problem in semcem.h preventing build under Clang or GCC 3.4 + * Fix bug that prevented creation of DSA groups under 1024 bits + * Fix crash in GMP_Engine if library is shutdown and reinitialized + * Work around problem with recent binutils in x86-64 SHA-1 + * The Perl build script is no longer supported and refuses to run by default + +1.9.8, 2010-06-14 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + * Add support for wide multiplications on 64-bit Windows + * Use constant time multiplication in IDEA + * Avoid possible timing attack against OAEP decoding + * Removed FORK-256; rarely used and it has been broken + * Rename --use-boost-python to --with-boost-python + * Skip building shared libraries on MinGW/Cygwin + * Fix creation of 512 and 768 bit DL groups using the DSA kosherizer + * Fix compilation on GCC versions before 4.3 (missing cpuid.h) + * Fix compilation under the Clang compiler + +1.9.7, 2010-04-27 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + * TLS: Support reading SSLv2 client hellos + * TLS: Add support for SEED ciphersuites (RFC 4162) + * Add Comb4P hash combiner function + * Fix checking of EMSA_Raw signatures with leading 0 bytes + +1.9.6, 2010-04-09 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + * TLS: Add support for TLS v1.1 + * TLS: Support server name indicator extension + * TLS: Fix server handshake + * TLS: Fix server using DSA certificates + * TLS: Avoid timing channel between CBC padding check and MAC verification + +1.9.5, 2010-03-29 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + * Numerous ECC optimizations + * Fix GOST 34.10-2001 X.509 key loading + * Allow PK_Signer's fault protection checks to be toggled off + * Avoid using pool-based locking allocator if we can't mlock + * Remove all runtime options + * New BER_Decoder::{decode_and_check, decode_octet_string_bigint} + * Remove SecureBuffer in favor of SecureVector length parameter + * HMAC_RNG: Perform a poll along with user-supplied entropy + * Fix crash in MemoryRegion if Allocator::get failed + * Fix small compilation problem on FreeBSD + +1.9.4, 2010-03-09 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + * Add the Ajisai SSLv3/TLSv1.0 implementation + * Add GOST 34.10-2001 public key signature scheme + * Add SIMD implementation of Noekeon + * Add SSE2 implementation of IDEA + * Extend Salsa20 to support longer IVs (XSalsa20) + * Perform XTS encryption and decryption in parallel where possible + * Perform CBC decryption in parallel where possible + * Add SQLite3 db encryption codec, contributed by Olivier de Gaalon + * Add a block cipher cascade construction + * Add support for password hashing for authentication (passhash9.h) + * Add support for Win32 high resolution system timers + * Major refactoring and API changes in the public key code + * Use consistency checking (anti-fault attack) for all signature schemes + * Changed S2K interface: derive_key now takes salt, iteration count + * Remove dependency on TR1 for ECC and CVC code + * Renamed ECKAEG to its more usual name, ECDH + * Fix crash in GMP_Engine if library is shutdown and reinitialized + * Fix an invalid memory read in MD4 + * Fix Visual C++ static builds + * Remove Timer class entirely + * Switch default PKCS #8 encryption algorithm from 3DES to AES-128 + * New option --gen-amalgamation for creating a SQLite-style amalgamation + * Many headers are now explicitly internal-use-only and are not installed + * Greatly improve the Win32 installer + * Several fixes for Visual C++ debug builds + +2009 +---------------------------------------- + +1.9.3, 2009-11-19 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + * Add new AES implementation using Intel's AES instruction intrinsics + * Add an implementation of format preserving encryption + * Allow use of any hash function in X.509 certificate creation + * Optimizations for MARS, Skipjack, and AES + * Set macros for available SIMD instructions in build.h + * Add support for using InnoSetup to package Windows builds + * By default build a DLL on Windows + +1.9.2, 2009-11-03 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + * Add SIMD version of XTEA + * Support both SSE2 and AltiVec SIMD for Serpent and XTEA + * Optimizations for SHA-1 and SHA-2 + * Add AltiVec runtime detection + * Fix x86 CPU identification with Intel C++ and Visual C++ + +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.9.1, 2009-10-23 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + * Better support for Python and Perl wrappers + * Add an implementation of Blue Midnight Wish (Round 2 tweak version) + * Modify Skein-512 to match the tweaked 1.2 specification + * Add threshold secret sharing (draft-mcgrew-tss-02) + * Add runtime cpu feature detection for x86/x86-64 + * Add code for general runtime self testing for hashes, MACs, and ciphers + * Optimize XTEA; twice as fast as before on Core2 and Opteron + * Convert CTR_BE and OFB from filters to stream ciphers + * New parsing code for SCAN algorithm names + * Enable SSE2 optimizations under Visual C++ + * Remove all use of C++ exception specifications + * Add support for GNU/Hurd and Clang/LLVM + +1.9.0, 2009-09-09 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + * Add support for parallel invocation of block ciphers where possible + * Add SSE2 implementation of Serpent + * Add Rivest's package transform (an all or nothing transform) + * Minor speedups to the Turing key schedule + * Fix processing multiple messages in XTS mode + * Add --no-autoload option to configure.py, for minimized builds + * The previously used configure.pl script is no longer supported + +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 + +2008 +---------------------------------------- + +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 + +2007 +---------------------------------------- + +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.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.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.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 + +2006 +---------------------------------------- + +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.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.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.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 + +2005 +---------------------------------------- + +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 + +2004 +---------------------------------------- + +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 + +2003 +---------------------------------------- + +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 + +2002 +---------------------------------------- + +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) + +2001 +---------------------------------------- + +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/doc/lowlevel.txt b/doc/lowlevel.txt new file mode 100644 index 000000000..4f63948da --- /dev/null +++ b/doc/lowlevel.txt @@ -0,0 +1,641 @@ + +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). + +Basic Algorithm Abilities +--------------------------------- + +There are a small handful of functions implemented by most of Botan's +algorithm objects. Among these are: + +.. cpp:function:: std::string name() + +Returns a human-readable string of the name of this +algorithm. Examples of names returned are "AES-128" and +"HMAC(SHA-512)". You can turn names back into algorithm objects using +the functions in ``lookup.h``. + +.. cpp:function:: void 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. The object will look and behave as it did when you initially +allocated it. + +.. cpp:function:: T* clone() + +This function is central to Botan's name-based interface. The +``clone`` has many different return types, such as ``BlockCipher``\* +and ``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 ``clone`` do not affect the initial state of the new +clone. + +Cloned objects can (and should) be deallocated with the C++ ``delete`` +operator. + +Keys and IVs +--------------------------------- + +Both symmetric keys and initialization values can be considered byte +(or octet) strings. These are represented by the classes +``SymmetricKey`` and ``InitializationVector``, which are +subclasses of ``OctetString``. + +Since often it's hard to distinguish between a key and IV, many things +(such as key derivation mechanisms) return ``OctetString`` instead of +``SymmetricKey`` to allow its use as a key or an IV. + +.. cpp:function:: OctetString::OctetString(RandomNumberGenerator& rng, size_t length) + + This constructor creates a new random key ``length`` bytes long + using the random number generator. + +.. cpp:function:: OctetString::OctetString(std::string str) + + The argument ``str`` is assumed to be a hex string; it is converted + to binary and stored. Whitespace is ignored. + +.. cpp:function:: OctetString::OctetString(const byte* input, size_t length) + + This constructor copies its input. + +Symmetrically Keyed Algorithms +--------------------------------- + +Block ciphers, stream ciphers, and MACs are all keyed operations; to +be useful, they have to be set to use a particular key, which is a +randomly chosen string of bits of a specified length. The length +required by any particular algorithm may vary, depending on both the +algorithm specification and the implementation. You can query any +botan object to find out what key length(s) it supports. + +To make this similarity in terms of keying explicit, all algorithms of +those types are derived from the ``SymmetricAlgorithm`` base +class. This type provides functions for setting the key, and querying +restrictions on the size of the key: + +.. cpp:function:: void set_key(const byte* key, size_t length) + + This sets the key to the value specified. Most algorithms only + accept keys of certain lengths. If you attempt to call ``set_key`` + with a key length that is not supported, the exception + ``Invalid_Key_Length`` will be thrown. There is also another version + of ``set_key`` that takes a ``SymmetricKey`` as an argument. + + In all cases, ``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, but probably + will not be good. + +.. cpp:function:: bool valid_keylength(size_t length) const + + This function returns true if and only if ``length`` is a valid keylength + for the algorithm. + +.. cpp:function:: size_t minimum_keylength() const + + Return the smallest key length (in bytes) that is acceptible for the + algorithm. + +.. cpp:function:: size_t maximum_keylength() const + + Return the largest key length (in bytes) that is acceptible for the + algorithm + +Block Ciphers +--------------------------------- + +Block ciphers implement the interface ``BlockCipher``, found in +``block_cipher.h``, as well as the ``SymmetricAlgorithm`` interface. + +.. cpp:function:: size_t block_size() const + + Returns the block size of the cipher in bytes + +.. cpp:function:: void encrypt_n(const byte* in, byte* out, size_t blocks) const + + Encrypt ``blocks`` blocks of data, taking the input from ``in`` and + placing the ciphertext in ``out``. The two pointers may be + identical, but should not overlap ranges. + +.. cpp:function:: void encrypt(const byte* in, byte* out) const + + Encrypt a single block, taking the input from ``in`` and placing it + in ``out``. + +.. cpp:function:: void encrypt(byte* block) const + + Identical to ``encrypt(block, block)``. + +.. cpp:function:: void decrypt_n(const byte* in, byte* out, size_t blocks) const + + Decrypt ``blocks`` blocks of data, taking the input from ``in`` and + placing the plaintext in ``out``. The two pointers may be identical, + but should not overlap ranges. + +.. cpp:function:: void decrypt(const byte* in, byte* out) const + + Decrypt a single block, taking the input from ``in`` and placing it + in ``out``. + +.. cpp:function:: void decrypt(byte* block) const + + Identical to ``decrypt(block, block)``. + + +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). + +.. cpp:function:: void encrypt(const byte* in, byte* out, size_t length) + +.. cpp:function:: void encrypt(byte* data, size_t length) + +Stream ciphers implement the ``SymmetricAlgorithm`` interface. + +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 +``BufferedComputation``, which has the following functions. + +.. cpp:function:: size_t output_length() + +Return the size of the output of this function. + +.. cpp:function:: void update(const byte* input, size_t length) + +.. cpp:function:: void update(byte input) + +.. cpp:function:: void update(const std::string& input) + +Updates the hash/mac calculation with ``input``. + +.. cpp:function:: void final(byte* out) + +.. cpp:function:: SecureVector<byte> final() + +Complete the hash/MAC calculation and place the result into ``out``. +For the argument taking an array, exactly ``output_length`` bytes will +be written. After you call ``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. + +There is also a pair of functions called ``process``. They are +a combination of a single ``update``, and ``final``. +Both versions return the final value, rather than placing it an +array. Calling ``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 a keyed hash function, so +classes that are derived from ``MessageAuthenticationCode`` have +``update`` and ``final`` classes just like a +``HashFunction`` (and like a ``HashFunction``, after +``final`` is called, it can be used to make a new MAC right +away; the key is kept around). + +A MAC has the ``SymmetricAlgorithm`` interface in addition to the +``BufferedComputation`` interface. + +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 ethe same seed (ie, two +``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 ``EntropySource`` (see below). To add some (typically +application specific) entropy to a PRNG, you can use + +.. cpp:function:: void add_entropy(const byte* data, size_t length) + +Once a PRNG has been initialized, you can get a single byte of random +data by + +.. cpp:function:: byte random() + +or get a large block by calling + +.. cpp:function:: void randomize(byte* data, size_t length) + +Randpool +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``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 +``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. + +``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 ``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). + +ANSI X9.31 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``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 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. + + +Entropy Sources +--------------------------------- + +An ``EntropySource`` is an abstract representation of some method of +gather "real" entropy. This tends to be very system dependent. The +*only* way you should use an ``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! + +``EntropySource`` has a pair of functions for getting entropy from +some external source, called ``fast_poll`` and ``slow_poll``. These +pass a buffer of bytes to be written; the functions then return how +many bytes of entropy were gathered. + +Note for writers of ``EntropySource`` subclasses: 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 ``RandomNumberGenerator`` that asked for the +entropy, thus any hashing you do will be wasteful of both CPU cycles +and entropy. + +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 ``User_Interface``, 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 (``User_Interface`` will probably be extended +in the future to support other operations as they are needed). The +base ``User_Interface`` 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 *attached* to a terminal, and so on). But +since you can subclass ``User_Interface`` to use whatever method +happens to be appropriate for your application, this isn't a big deal: + +.. cpp:function:: std::string User_Interface::get_passphrase(const std::string& what, const std::string& source, UI_Result& result) const + + The ``what`` argument specifies what the passphrase is needed for + (for example, PKCS #8 key loading passes ``what`` as "PKCS #8 + private key"). This lets you provide the user with some indication + of *why* your application is asking for a passphrase; feel free to + pass the string through ``gettext(3)`` or moral equivalent for i18n + purposes. Similarly, ``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 ``source`` will be an empty + string; be sure to account for this possibility when writing a + ``User_Interface`` subclass. + + The function returns the passphrase as the return value, and a + status code in ``result`` (either ``OK`` or ``CANCEL_ACTION``). If + ``CANCEL_ACTION`` is returned in ``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 ``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 ``User_Interface`` that uses GTK+ available on the +web site. The ``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 +``User_Interface`` 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. + +PBKDF Algorithms +--------------------------------- + +There are various procedures (usually 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 +``pbkdf.h``. The main function is ``derive_key``, which +takes a passphrase, a salt, an iteration count, and the desired length +of the output key, and returns a key of that length, deterministically +produced from the passphrase and salt. 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). + +The purpose of the iteration count is to make the algorithm take +longer to compute the final key (reducing the speed of brute-force +attacks of various kinds). Most standards recommend an iteration count +of at least 10000. Currently defined PBKDF algorithms are +"PBKDF1(digest)", "PBKDF2(digest)", and "OpenPGP-S2K(digest)"; you can +retrieve any of these using the ``get_pbkdf``, found in +``lookup.h``. As of this writing, "PBKDF2(SHA-256)" with 10000 +iterations and a 16 byte salt is recommend for new applications. + +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 *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, 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. + +Password Hashing +--------------------------------- + +Storing passwords for user authentication purposes in plaintext is the +simplest but least secure method; when an attacker compromises the +database in which the passwords are stored, they immediately gain +access to all of them. Often passwords are reused among multiple +services or machines, meaning once a password to a single service is +known an attacker has a substantial head start on attacking other +machines. + +The general approach is to store, instead of the password, the output +of a one way function of the password. Upon receiving an +authentication request, the authenticator can recompute the one way +function and compare the value just computed with the one that was +stored. If they match, then the authentication request succeeds. But +when an attacker gains access to the database, they only have the +output of the one way function, not the original password. + +Common hash functions such as SHA-256 are one way, but used alone they +have problems for this purpose. What an attacker can do, upon gaining +access to such a stored password database, is hash common dictionary +words and other possible passwords, storing them in a list. Then he +can search through his list; if a stored hash and an entry in his list +match, then he has found the password. Even worse, this can happen +*offline*: an attacker can begin hashing common passwords days, +months, or years before ever gaining access to the database. In +addition, if two users choose the same password, the one way function +output will be the same for both of them, which will be visible upon +inspection of the database. + +There are two solutions to these problems: salting and +iteration. Salting refers to including, along with the password, a +randomly chosen value which perturbs the one way function. Salting can +reduce the effectivness of offline dictionary generation (because for +each potential password, an attacker would have to compute the one way +function output for all possible salts - with a large enough salt, +this can make the problem quite difficult). It also prevents the same +password from producing the same output, as long as the salts do not +collide. With a large salt (say 80 to 128 bits) this will be quite +unlikely. Iteration refers to the general technique of forcing +multiple one way function evaluations when computing the output, to +slow down the operation. For instance if hashing a single password +requires running SHA-256 100,000 times instead of just once, that will +slow down user authentication by a factor of 100,000, but user +authentication happens quite rarely, and usually there are more +expensive operations that need to occur anyway (network and database +I/O, etc). On the other hand, an attacker who is attempting to break a +database full of stolen password hashes will be seriously +inconvenienced by a factor of 100,000 slowdown; they will be able to +only test at a rate of .0001% of what they would without iterations +(or, equivalently, will require 100,000 times as many zombie botnet +hosts). + +There are many different ways of doing this password hashing +operation, with common ones including Unix's crypt (which is based on +DES) and OpenBSD's bcrypt (based on Blowfish). Other variants using +MD5 or SHA-256 are also in use on various systems. + +Botan provides two techniques, passhash9 and bcrypt + +Passhash9 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Botan provides a password hashing technique called passhash9, in +``passhash9.h``, which is based on PBKDF2. A usage example can be +found in ``doc/examples/passhash.cpp``. Three functions are provided +in this header: + +.. cpp:function:: std::string generate_passhash9(const std::string& password, RandomNumberGenerator& rng, u16bit work_factor = 10) + + Takes the password to hash, a rng, and a work factor, which tells + how many iterations to compute. The default work factor is 10 + (which means 100,000 iterations), but any non-zero value is + accepted. + +.. cpp:function:: std::string generate_passhash9(const std::string& password, byte alg_id, RandomNumberGenerator& rng, u16bit work_factor = 10) + + Like the other ``generate_passhash9``, but taking a parameter that + specifies which PRF to use. Currently defined values are 0 + ("HMAC(SHA-1)"), 1 ("HMAC(SHA-256)"), and 2 ("CMAC(Blowfish)"). + +.. cpp:function:: bool check_passhash9(const std::string& password, const std::string& hash) + + Takes a password and a passhash9 output and checks if the password + is the same as the one that was used to generate the passhash9 + output, returning a boolean true (same) or false (not same). + +Bcrypt +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Bcrypt is a password hashing scheme originally designed for use in +OpenBSD, but numerous other implementations exist. It is made +available by including ``bcrypt.h``, and provides the functions + +.. cpp:function:: std::string generate_bcrypt(const std::string& password, RandomNumberGenerator& rng, u16bit work_factor = 10) + +and + +.. cpp:function:: bool check_bcrypt(const std::string& password, const std::string& hash) + +These work in exactly the same way as the passhash9 password hashing +functions. + +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. + +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 ``mux_pthr`` module, implementing the ``Mutex`` interface for +systems that have POSIX threads. + +If your application is using threads, you *must* add the option +"thread_safe" to the options string when you create the +``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. + +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 ``mlock`` 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 ``setuid`` ``root``, and then drop privileges +immediately after creating your ``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 ``root`` +all the time. + +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 ``std::vector``, since these objects know how to clear +themselves when they are destroyed. You cannot, however, have a +``std::vector`` (or any other container) of ``Pipe`` objects or +filters, because these types have pointers to other filters, 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 ``secmem.h`` and +``allocate.h``. + +``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 ``clear()``, and +``size_t`` ``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: ``SecureBuffer<byte, 8> key;``). + +``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 ``SecureBuffer``, it implements ``clear`` +and ``size``. + +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 ``allocate.h``. Code needing +to allocate or deallocate memory calls ``get_allocator``, +which returns a pointer to an allocator object. This pointer should +not be freed: the caller does not own the allocator (it is shared +among multiple allocatore users, and uses a mutex to serialize access +internally if necessary). It is possible to call +``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 ``Default_Allocator``, +which just allocates memory using ``malloc``, and zeroizes it 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 ``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 ``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, +``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. + diff --git a/doc/architecture.pdf b/doc/old/architecture.pdf Binary files differindex f0edc3fc1..f0edc3fc1 100644 --- a/doc/architecture.pdf +++ b/doc/old/architecture.pdf diff --git a/doc/insito_manual.pdf b/doc/old/insito_manual.pdf Binary files differindex b07146992..b07146992 100644 --- a/doc/insito_manual.pdf +++ b/doc/old/insito_manual.pdf diff --git a/doc/tutorial.tex b/doc/old/tutorial.tex index f220d765a..f220d765a 100644 --- a/doc/tutorial.tex +++ b/doc/old/tutorial.tex diff --git a/doc/tutorial2.tex b/doc/old/tutorial2.tex index 840679d10..840679d10 100644 --- a/doc/tutorial2.tex +++ b/doc/old/tutorial2.tex diff --git a/doc/pgpkeys.txt b/doc/pgpkeys.txt index 8da1d1d05..1d2f3debc 100644 --- a/doc/pgpkeys.txt +++ b/doc/pgpkeys.txt @@ -1,36 +1,41 @@ -pub 2048R/EFBADFBC 2004-10-30 - Key fingerprint = 621D AF64 11E1 851C 4CF9 A2E1 6211 EBF1 EFBA DFBC -uid Botan Distribution Key +PGP Code Signing Key +======================================== ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v2.0.17 (GNU/Linux) +The following PGP key is used to sign all releases:: -mQELBEGD1j0BCADHxPJkPcjJE+4Dlisx2hVc0Dj6JI1MSLrkM8R+2bOhVUSferxP -T1EMPhfrAdOHTAloyvRThJztnZsNKqfLL49GGcBLdEGAVNks1pG37Teze5Lx1XIu -zJFrozL2sqBy5C6nHpFgd1tcD68Rah2wp0u2cR9owXf1IqKdEfuo661+MTv7wTB1 -4hKV75nB7ZO6676SEZRILYM+7RJwKAKEmEPJc6hEf94VXn9ecNzaTlHgYkjhz9db -LOd3od9XvuUw+LMR1dwBqMxbvR90MiXjbedDEkbArcZB9YOAIvEX/lC3qaW4XJt4 -iwHWl/YVZEfALcvQywe2CDrH5hO794wd9MpBAAYptBZCb3RhbiBEaXN0cmlidXRp -b24gS2V5iQEqBBMBAgAUAhsDAh4BAheABQJKfFpnBBUKCQgACgkQYhHr8e+637xk -PQf/aOi78XenwwvFrwXOVIVTdZIf8rK1zJksf26h09UD8uVV6z5iiTcpn86+eN9p -6Ar8IH3tD+JuFnPSwZ/r9MNC2XZwenYo4Gb14jqM6/9hBe328vmeM4Y1G7bD4HrL -kgV5WEyokqm3zbp3FBLr3Vh68TAC5JB9aHevra+cCA2u3vBNI3YUM5z4TdO150P3 -J00whkqImQEUni8bgxvllBLFM+uhucsX3HZWkoDEpotbg8yd0bqMkiPEyMr1OnJq -eDVDMrB5wnyLgLFfRAAw3mopM0C1PNOAHr/BIYiaDHX2OwnOfep8rMDoRVf2Ge0D -DBgsJJ6LduQHLeg403SHWL2F6YkCHAQTAQIABgUCQYPWUgAKCRBcD5boTsFta+r9 -EACWVis7YcaGkKKgRB/5ox8rM36XVhMXdh/hnnGHt5rapbbRRkRHRcWU8WIcFO1A -59+TfwNNd8gN1MEt/5aX5KHWVKHBDexJgIxm6Dm1pisYHf/dnYQPM18hmqqwNlKY -97hFkPpHd7enrtc/SvGbQhhLXYlpwBrdMl76e9xJLnnrRQksxegGPo8cr+C9HTs1 -Lwa8zzBxyBwYBYX+0moDkDShEhuXx6mEOXrGvQanJuIvpoIwGH+62E65MbJGlwWp -w/MAtm2jFhBIhGV0bqJCFp9zIgdNgfskBaPr0oilbuJQZqP0Iqe/6CCt4XkS51yW -ZqxjLAFpEpvDec4PGw3witKf/koGon9X8C035+nEjLBrWy18Q91vw2USyLI+mm9d -iMAS8pY2gomfxBO2VwYHJryZykjCYQkccRA1tHteRj4gqTObo0Ak47y5MnplTWwi -40oP7K2cfhCRBmMioxmYES4xsHEupfRBo3xr1Jq9q0t688WTT1NXHPMPoueF9mKZ -Cf2pa9aHsqBmWTm3sCaNQKGubCDBEUmJUyndmSatJyYM7NVYoUp6EfqMACFuTNdB -sjKMh7aWVikQpbJDfA1BIU3lZeqgjgrghVAWkEOBfhG0IVZj+RVCJpsqoTJ8asY2 -VreArSCyr/VnLEnfuH/QpgvCiCbepo3E34DJt4SaAOO2ZohGBBARAgAGBQJMGVc1 -AAoJEKY/LL36AvvMgsoAn2G7kXd09BF7ffk1Sfh174SVrvM9AKC7+R7x0+yV3SCd -JkkUOo3xR5cOxw== -=1QuR ------END PGP PUBLIC KEY BLOCK----- + pub 2048R/EFBADFBC 2004-10-30 + Key fingerprint = 621D AF64 11E1 851C 4CF9 A2E1 6211 EBF1 EFBA DFBC + uid Botan Distribution Key + + -----BEGIN PGP PUBLIC KEY BLOCK----- + Version: GnuPG v2.0.17 (GNU/Linux) + + mQELBEGD1j0BCADHxPJkPcjJE+4Dlisx2hVc0Dj6JI1MSLrkM8R+2bOhVUSferxP + T1EMPhfrAdOHTAloyvRThJztnZsNKqfLL49GGcBLdEGAVNks1pG37Teze5Lx1XIu + zJFrozL2sqBy5C6nHpFgd1tcD68Rah2wp0u2cR9owXf1IqKdEfuo661+MTv7wTB1 + 4hKV75nB7ZO6676SEZRILYM+7RJwKAKEmEPJc6hEf94VXn9ecNzaTlHgYkjhz9db + LOd3od9XvuUw+LMR1dwBqMxbvR90MiXjbedDEkbArcZB9YOAIvEX/lC3qaW4XJt4 + iwHWl/YVZEfALcvQywe2CDrH5hO794wd9MpBAAYptBZCb3RhbiBEaXN0cmlidXRp + b24gS2V5iQEqBBMBAgAUAhsDAh4BAheABQJKfFpnBBUKCQgACgkQYhHr8e+637xk + PQf/aOi78XenwwvFrwXOVIVTdZIf8rK1zJksf26h09UD8uVV6z5iiTcpn86+eN9p + 6Ar8IH3tD+JuFnPSwZ/r9MNC2XZwenYo4Gb14jqM6/9hBe328vmeM4Y1G7bD4HrL + kgV5WEyokqm3zbp3FBLr3Vh68TAC5JB9aHevra+cCA2u3vBNI3YUM5z4TdO150P3 + J00whkqImQEUni8bgxvllBLFM+uhucsX3HZWkoDEpotbg8yd0bqMkiPEyMr1OnJq + eDVDMrB5wnyLgLFfRAAw3mopM0C1PNOAHr/BIYiaDHX2OwnOfep8rMDoRVf2Ge0D + DBgsJJ6LduQHLeg403SHWL2F6YkCHAQTAQIABgUCQYPWUgAKCRBcD5boTsFta+r9 + EACWVis7YcaGkKKgRB/5ox8rM36XVhMXdh/hnnGHt5rapbbRRkRHRcWU8WIcFO1A + 59+TfwNNd8gN1MEt/5aX5KHWVKHBDexJgIxm6Dm1pisYHf/dnYQPM18hmqqwNlKY + 97hFkPpHd7enrtc/SvGbQhhLXYlpwBrdMl76e9xJLnnrRQksxegGPo8cr+C9HTs1 + Lwa8zzBxyBwYBYX+0moDkDShEhuXx6mEOXrGvQanJuIvpoIwGH+62E65MbJGlwWp + w/MAtm2jFhBIhGV0bqJCFp9zIgdNgfskBaPr0oilbuJQZqP0Iqe/6CCt4XkS51yW + ZqxjLAFpEpvDec4PGw3witKf/koGon9X8C035+nEjLBrWy18Q91vw2USyLI+mm9d + iMAS8pY2gomfxBO2VwYHJryZykjCYQkccRA1tHteRj4gqTObo0Ak47y5MnplTWwi + 40oP7K2cfhCRBmMioxmYES4xsHEupfRBo3xr1Jq9q0t688WTT1NXHPMPoueF9mKZ + Cf2pa9aHsqBmWTm3sCaNQKGubCDBEUmJUyndmSatJyYM7NVYoUp6EfqMACFuTNdB + sjKMh7aWVikQpbJDfA1BIU3lZeqgjgrghVAWkEOBfhG0IVZj+RVCJpsqoTJ8asY2 + VreArSCyr/VnLEnfuH/QpgvCiCbepo3E34DJt4SaAOO2ZohGBBARAgAGBQJMGVc1 + AAoJEKY/LL36AvvMgsoAn2G7kXd09BF7ffk1Sfh174SVrvM9AKC7+R7x0+yV3SCd + JkkUOo3xR5cOxw== + =1QuR + -----END PGP PUBLIC KEY BLOCK----- diff --git a/doc/pubkey.txt b/doc/pubkey.txt new file mode 100644 index 000000000..2b765cc10 --- /dev/null +++ b/doc/pubkey.txt @@ -0,0 +1,398 @@ + +.. _public_key_crypto: + +Public Key Cryptography +================================= + +Quick Start +--------------------------------- + +Let's create a 2048-bit RSA private key, serialize the public key as a +PKCS #1 file with PEM encoding (which can be understood by many other +cryptographic programs), and then load it on another machine:: + + // everyone does: + AutoSeeded_RNG rng; + + // Alice + RSA_PrivateKey priv_rsa(rng, 2048 /* bits */); + + std::string alice_pem = X509::PEM_encode(priv_rsa); + + // send alice_pem to Bob, who does + + // Bob + std::auto_ptr<Public_Key> alice(load_key(alice_pem)); + + RSA_PublicKey* alice_rsa = dynamic_cast<RSA_PublicKey>(alice); + if(alice_rsa) + { + /* ... */ + } + +Creating New Public Key Pairs +--------------------------------- + +The library has interfaces for public key encryption, signatures, and +key agreement that do not require knowing the exact algorithm in +use. One place where we *do* need to know exactly what kind of +algorithm is in use is when we are creating a key. + +There are currently three kinds of public key algorithms in Botan: +ones based on integer factorization (RSA and Rabin-Williams), ones +based on the discrete logarithm problem in the integers modulo a prime +(DSA, Diffie-Hellman, Nyberg-Rueppel, and ElGamal), and ones based on +the discrete logarithm problem in an elliptic curve (ECDSA, ECDH, and +GOST 34.10). The systems based on discrete logarithms (in either +regular integers or elliptic curves) use a group (a mathematical +term), which can be shared among many keys. An elliptic curve group is +represented by the class ``EC_Domain_Params``, while a modulo-prime +group is represented by a ``DL_Group``. + +There are two ways to create a DL private key (such as +``DSA_PrivateKey``). One is to pass in just a ``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 ``size_t`` 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 +``BigInt``: prime 1, prime 2, encryption exponent, decryption +exponent, modulus. The last two are optional, since they can easily be +derived from the first three. + +Creating a DL_Group +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There are quite a few ways to get a ``DL_Group`` object. The best is +to use the 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 "modp/ietf/N" where N +is 768, 1024, 1536, 2048, 3072, 4096, 6144, and 8192 for +Diffie-Hellman and ElGamal. DSA-style groups are named "dsa/jce/N" for +N 512, 768, 1024, and "dsa/botan/N" for 2048 and 3072. + +You can also generate a new random group. This is not recommend, +because it is quite slow, especially for safe primes. + +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 ``check_key`` that +takes a ``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 ``check_key``'s argument +is ``true``, then it does "strong" checking, which includes 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). + +Getting a PK algorithm object +--------------------------------- + +The key types, like ``RSA_PrivateKey``, do not implement any kind of +padding or encoding (which is necessary for security). To get an +object that knows how to do padding, use the wrapper classes included +in ``pubkey.h``. These take a key, along with a string that specifies +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 ``rsakey`` is an +``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):: + + // PKCS #1 v2.0 / IEEE 1363 compatible encryption + PK_Encryptor_EME rsa_enc_pkcs1_v2(rsakey, "EME1(SHA-1)"); + // PKCS #1 v1.5 compatible encryption + PK_Encryptor_EME rsa_enc_pkcs1_v15(rsakey, "PKCS1v15") + + // This object can decrypt things encrypted by rsa_ + PK_Decryptor_EME rsa_dec_pkcs1_v2(rsakey, "EME1(SHA-1)"); + + // PKCS #1 v1.5 compatible signatures + PK_Signer rsa_sign_pkcs1_v15(rsakey, "EMSA3(MD5)"); + PK_Verifier rsa_verify_pkcs1_v15(rsakey, "EMSA3(MD5)"); + + // PKCS #1 v2.1 compatible signatures + PK_Signer rsa_sign_pkcs1_v2(rsakey, "EMSA4(SHA-1)"); + PK_Verifier rsa_verify_pkcs1_v2(rsakey, "EMSA4(SHA-1)"); + +Encryption +--------------------------------- + +The ``PK_Encryptor`` and ``PK_Decryptor`` classes are the +interface for encryption and decryption, respectively. + +Calling ``encrypt`` with a ``byte`` array, a length +parameter, and an RNG object will return the input encrypted with +whatever scheme is being used. Calling the similar ``decrypt`` +will perform the inverse operation. You can also do these operations +with ``SecureVector<byte>``s. In all cases, the output is returned +via a ``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. You +can call ``maximum_input_size`` to find out the maximum size +input (in bytes) that you can safely use with any particular key. + +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. + +Signatures +--------------------------------- + +The signature algorithms look quite a bit like the hash functions. You +can repeatedly call ``update``, giving more and more of a +message you wish to sign, and then call ``signature``, which +will return a signature for that message. If you want to do it all in +one shot, call ``sign_message``, which will just call +``update`` with its argument and then return whatever +``signature`` returns. Generating a signature requires random +numbers with some schemes, so ``signature`` and +``sign_message`` both take a ``RandomNumberGenerator&``. + +You can validate a signature by updating the verifier class, and finally seeing +the if the value returned from ``check_signature`` is true (you pass +the supposed signature to the ``check_signature`` function as a byte +array and a length or as a ``MemoryRegion<byte>``). There is another +function, ``verify_message``, which takes a pair of byte array/length +pairs (or a pair of ``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, +ECDSA, GOST-34.11, 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. The Raw encoding 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 *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, ECDSA, GOST-34.11, and Nyberg-Rueppel, you should use +EMSA1. None of the other encoding methods are particularly useful for +these algorithms. + +Key Agreement +--------------------------------- + +You can get a hold of a ``PK_Key_Agreement_Scheme`` object by calling +``get_pk_kas`` with a key that is of a type that supports key +agreement (such as a Diffie-Hellman key stored in a ``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 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 +``derive_key`` with either a byte array/length pair, or a +``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 KDF you're using, you *might not* get back a key +of the size you requested. 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 +``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 +``public_data``, which exists for any key that is associated with a +key agreement algorithm. It returns a ``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. + +.. _pk_import_export: + +Importing and Exporting Keys +--------------------------------- + +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: the X.509 subject public key info format (for public keys), and +PKCS #8 (for private keys). Other crypto libraries, such as Crypto++ +and OpenSSL, 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 :ref:`x509_certificates`. + +.. _import_export_public_keys: + +Importing/Exporting Public Keys +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To import and export public keys, use: + +.. cpp:function:: MemoryVector<byte> X509::BER_encode(const Public_Key& key) + + Takes any public key object, and returns a standard binary structure + representing the key which can be read by many other crypto + libraries. + +.. cpp:function:: std::string X509::PEM_encode(const Public_Key& key) + + This formats the key the same as ``BER_encode``, but additionally + encodes it into a text format with identifying headers. Using PEM + encoding is *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. + +.. cpp:function:: Public_Key* X509::load_key(DataSource& in) + +.. cpp:function:: Public_Key* X509::load_key(const SecureVector<byte>& buffer) + +.. cpp:function:: Public_Key* X509::load_key(const std::string& filename) + + For loading a public key, use one of the variants of ``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 ``new``, and should be + released with ``delete`` when you are done with it. The first takes + a generic ``DataSource`` that you have to create - the other is a + simple wrapper functions that take either a filename or a memory + buffer and create the appropriate ``DataSource``. + +Importing/Exporting 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: + +.. cpp:function:: SecureVector<byte> PKCS8::BER_encode(const Private_Key& key) + +.. cpp:function:: std::string PKCS8::PEM_encode(const Private_Key& key) + +These functions are similiar to the X.509 functions described in +:ref:`import_export_public_keys`. The only difference is that they take +a ``Private_Key`` object instead. In most situations, using these +versions 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 described +below. 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 +store the whole thing into another structure. This method is +definitely preferred, since otherwise the private key is +unprotected. The algorithms and structures used here are standardized +by PKCS #5 and PKCS #8, and can be read by many other crypto +libraries: + +.. cpp:function:: SecureVector<byte> PKCS8::BER_encode(const Private_Key& key, RandomNumberGenerator& rng, const std::string& pass, const std::string& pbe_algo = "") + +.. cpp:function:: std::string PKCS8::PEM_encode(const Private_Key& key, RandomNumberGenerator& rng, const std::string& pass, const std::string& pbe_algo = "") + + +There are three new arguments needed here to support the encryption +process. The first is a ``RandomNumberGenerator``, which is used to +generate salts to randomize the encryption. The ``pass`` argument is +the passphrase that will be used to encrypt the key. Both of these are +required. The final (optional) argument, ``pbe_algo``, specifies a +particular password based encryption (or PBE) algorithm. If you don't +specify a PBE, a sensible default will be used. + +Last but not least, there are some functions that will load (and +decrypt, if necessary) a PKCS #8 private key: + +.. cpp:function:: Private_Key* PKCS8::load_key(DataSource& in, RandomNumberGenerator& rng, const User_Interface& ui) + +.. cpp:function:: Private_Key* PKCS8::load_key(DataSource& in, RandomNumberGenerator& rng, std::string passphrase = "") + +.. cpp:function:: Private_Key* PKCS8::load_key(const std::string& filename, RandomNumberGenerator& rng, const User_Interface& ui) + +.. cpp:function:: Private_Key* PKCS8::load_key(const std::string& filename, RandomNumberGenerator& rng, const std::string& passphrase = "") + +The versions that pass the passphrase as a ``std::string`` are +primarily for compatibility, but they are useful in limited +circumstances. The ``User_Interface`` versions are how ``load_key`` is +implemented, and provides for much more flexibility. If the passphrase +passed in is not correct, then an exception is thrown and that is +that. However, if you pass in an UI object, 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 +``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 ``User_Interface`` is rather dumb, and acts +rather like the versions taking the ``std::string``; it tries the +passphrase passed in first, and then it cancels. + +All versions need access to a ``RandomNumberGenerator`` in order to +perform probabilistic tests on the loaded key material. + +After loading a key, you can use ``dynamic_cast`` to find out what +operations it supports, and use it appropriately. Remember to +``delete`` the object once you are done with it. diff --git a/doc/python.tex b/doc/python.tex deleted file mode 100644 index afdd66b6a..000000000 --- a/doc/python.tex +++ /dev/null @@ -1,68 +0,0 @@ -\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 Python Interface Documentation}} -\author{Jack Lloyd \\ - \texttt{[email protected]}} -\date{2009/10/10} - -\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{Ciphers} - -Botan's Python interface provides a generic interface to any cipher -supported by the library. The class \type{botan.Cipher} takes three -arguments, all strings: first, the name of the algorith, second the -direction (which can be either ``encrypt'' or ``decrypt''), and -lastly, the key to use. For instance - -\begin{verbatim} - encryptor = botan.Cipher("AES-128/EAX", "encrypt", key) -\end{verbatim} - -creates an object that will encrypt and authenticate messages using -the EAX mode of operation using the AES cipher. To use this object, -call the \function{cipher} function with two arguments - the input -to encrypt, and the IV to use: - -\begin{verbatim} - ciphertext = encryptor.cipher(input, salt) -\end{verbatim} - - -\subsection{Cryptobox} - - -\subsection{RNGs} - -\section{RSA} - - - -\end{document} diff --git a/doc/python/cipher.py b/doc/python/cipher.py deleted file mode 100755 index 1be2759ae..000000000 --- a/doc/python/cipher.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/python - -import botan -import sys - -def encrypt(input, passphrase): - rng = botan.RandomNumberGenerator() - - # Use as both EAX IV and PBKDF2 salt - salt = rng.gen_random(10) - - iterations = 10000 - output_size = 16 - - key = botan.pbkdf2(passphrase, salt, iterations, output_size, "SHA-1") - - encryptor = botan.Cipher("AES-128/EAX", "encrypt", key) - - ciphertext = encryptor.cipher(input, salt) - return (ciphertext, salt) - -def decrypt(input, salt, passphrase): - iterations = 10000 - output_size = 16 - - key = botan.pbkdf2(passphrase, salt, iterations, output_size, "SHA-1") - - decryptor = botan.Cipher("AES-128/EAX", "decrypt", key) - - return decryptor.cipher(input, salt) - -def main(args = None): - if args is None: - args = sys.argv - - passphrase = args[1] - input = ''.join(open(args[2]).readlines()) - - (ciphertext, salt) = encrypt(input, passphrase) - - print decrypt(ciphertext, salt, passphrase) - -if __name__ == '__main__': - sys.exit(main()) diff --git a/doc/python/cryptobox.py b/doc/python/cryptobox.py deleted file mode 100755 index f76ed6bc3..000000000 --- a/doc/python/cryptobox.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/python - -import sys -import botan - -def main(args = None): - if args is None: - args = sys.argv - - if len(args) != 3: - raise Exception("Usage: <password> <input>"); - - password = args[1] - input = ''.join(open(args[2]).readlines()) - - rng = botan.RandomNumberGenerator() - - ciphertext = botan.cryptobox_encrypt(input, password, rng) - - print ciphertext - - plaintext = '' - - try: - plaintext = botan.cryptobox_decrypt(ciphertext, password + 'FAIL') - except Exception, e: - print "Good news: bad password caused exception: " - print e - - plaintext = botan.cryptobox_decrypt(ciphertext, password) - - print "Original input was: " - print plaintext - -if __name__ == '__main__': - sys.exit(main()) diff --git a/doc/python/nisttest.py b/doc/python/nisttest.py deleted file mode 100755 index 3ea8fda0f..000000000 --- a/doc/python/nisttest.py +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/python - -import sys, os, botan -from os.path import join; - -def validate(ca_certs, certs, crls, ee_certs): - store = botan.X509_Store() - for cert in certs: - if cert not in ee_certs: - store.add_cert(botan.X509_Certificate(cert), cert in ca_certs) - - for crl in crls: - r = store.add_crl(botan.X509_CRL(crl)) - if r != botan.verify_result.verified: - return r - - for ee in ee_certs: - r = store.validate(botan.X509_Certificate(ee)) - if r != botan.verify_result.verified: - return r - - return botan.verify_result.verified - -def run_test(files, rootdir, testname, expected): - crls = [join(rootdir,x) for x in files if x.endswith(".crl")] - certs = [join(rootdir,x) for x in files if x.endswith(".crt")] - end_entity = [x for x in certs if x.find("end.crt") != -1] - ca_certs = [x for x in certs if x.find("root.crt") != -1] - - print "%s..." % testname, - - result = validate(ca_certs, certs, crls, end_entity) - result = repr(result).replace('botan._botan.verify_result.', '') - - if result != expected: - print "FAILED: got %s, expected %s" % (result, expected) - else: - print "passed" - -def main(): - def load_results(file): - results = {} - for line in open(file, 'r'): - line = line[0:line.find('#')].strip() - if line: - test,result = line.split(' ') - results[test] = result - return results - - results = load_results('results.txt') - - for root, dirs, files in os.walk('../../checks/nist_tests/tests'): - if files: - thistest = root[root.rfind('/')+1:] - if thistest in results: - run_test(files, root, thistest, results[thistest]) - else: - print "%s... skipping - no expected result set" % thistest - -if __name__ == "__main__": - sys.exit(main()) diff --git a/doc/python/results.txt b/doc/python/results.txt deleted file mode 100644 index 7a3824001..000000000 --- a/doc/python/results.txt +++ /dev/null @@ -1,60 +0,0 @@ -# This is the file of expected results for nisttest.py -test01 verified -test02 signature_error -test03 signature_error -test04 verified -test05 cert_not_yet_valid -test06 cert_not_yet_valid -test07 verified -test08 cert_not_yet_valid -test09 cert_has_expired -test10 cert_has_expired -test11 cert_has_expired -test12 verified -test13 cert_issuer_not_found -test14 cert_issuer_not_found -test15 verified -test16 verified -test17 verified -test18 verified -# changed; should be no_revocation_data_available, but I don't want to -# force people to use CRLs -test19 verified -test20 cert_is_revoked -test21 cert_is_revoked -test22 ca_cert_not_for_cert_issuer -test23 ca_cert_not_for_cert_issuer -test24 verified -test25 ca_cert_not_for_cert_issuer -test26 verified -test27 verified -test28 ca_cert_not_for_cert_issuer -test29 ca_cert_not_for_cert_issuer -test30 verified -test31 ca_cert_not_for_crl_issuer -test32 ca_cert_not_for_crl_issuer -test33 verified -test54 cert_chain_too_long -test55 cert_chain_too_long -test56 verified -test57 verified -test58 cert_chain_too_long -test59 cert_chain_too_long -test60 cert_chain_too_long -test61 cert_chain_too_long -test62 verified -test63 verified -test64 signature_error -# changed; I have no idea why this test is supposed to fail -test65 verified -test66 crl_issuer_not_found -# changed; one of the CRLs has an unknown creator, so we fail -# prior to getting to the end-entity check -test67 crl_issuer_not_found -test68 cert_is_revoked -test69 cert_is_revoked -test70 cert_is_revoked -test71 cert_is_revoked -test72 crl_has_expired -test73 crl_has_expired -test74 verified diff --git a/doc/python/rng_test.py b/doc/python/rng_test.py deleted file mode 100755 index 06c79b84e..000000000 --- a/doc/python/rng_test.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/python - -import botan - -rng = botan.RandomNumberGenerator() - -print "name", rng.name() - -rng.add_entropy("blah") - -print "random 16", rng.gen_random(16).encode("hex") -print "random 32", rng.gen_random(32).encode("base64"), - -rng.reseed() - -for i in range(0, 10): - print rng.gen_random_byte(), -print - -rng.add_entropy("blah") - -print "random 16", rng.gen_random(16).encode("hex") diff --git a/doc/python/rsa.py b/doc/python/rsa.py deleted file mode 100755 index 8ca95ff8b..000000000 --- a/doc/python/rsa.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/python - -import botan - -def make_into_c_array(ber): - output = 'static unsigned char key_data[%d] = {\n\t' % (len(ber)) - - for (idx,c) in zip(range(len(ber)), ber): - if idx != 0 and idx % 8 == 0: - output += "\n\t" - output += "0x%s, " % (c.encode('hex')) - - output += "\n};\n" - - return output - -rng = botan.RandomNumberGenerator() - -rsa_priv = botan.RSA_PrivateKey(768, rng) - -print rsa_priv.to_string() -print int(rsa_priv.get_N()) -print int(rsa_priv.get_E()) - -rsa_pub = botan.RSA_PublicKey(rsa_priv) - -print make_into_c_array(rsa_pub.to_ber()) -#print make_into_c_array(rsa_priv.to_ber()) - -key = rng.gen_random(20) - -ciphertext = rsa_pub.encrypt(key, 'EME1(SHA-1)', rng) - -print ciphertext.encode('hex') - -plaintext = rsa_priv.decrypt(ciphertext, 'EME1(SHA-1)') - -print plaintext == key - -signature = rsa_priv.sign(key, 'EMSA4(SHA-256)', rng) - -print rsa_pub.verify(key, signature, 'EMSA4(SHA-256)') - -# Corrupt the signature, make sure it doesn't verify -signature = signature.replace(signature[0], '0') - -print rsa_pub.verify(key, signature, 'EMSA4(SHA-256)') diff --git a/doc/scripts/print_deps.py b/doc/scripts/print_deps.py deleted file mode 100755 index c68fa2617..000000000 --- a/doc/scripts/print_deps.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/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).replace('internal/', '') - -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/doc/scripts/update_deps.py b/doc/scripts/update_deps.py deleted file mode 100755 index ac19885e0..000000000 --- a/doc/scripts/update_deps.py +++ /dev/null @@ -1,41 +0,0 @@ -#!/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 len(lines) > 0 and 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/doc/thanks.txt b/doc/thanks.txt deleted file mode 100644 index 68fd81b3b..000000000 --- a/doc/thanks.txt +++ /dev/null @@ -1,53 +0,0 @@ - -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 -via public domain code which has been repurposed into the library: - - Dean Gaudet wrote the SSE2 implementation of SHA-1 - - Mike Hamburg wrote x86-64/SSSE3 assembly which was the basis for the - constant time AES implementation - - 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 its 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/doc/x509.txt b/doc/x509.txt new file mode 100644 index 000000000..3243928de --- /dev/null +++ b/doc/x509.txt @@ -0,0 +1,543 @@ + +.. _x509_certificates: + +Certificate Handling +================================= + +A certificate is a binding between some identifying information +(called a *subject*) and a public key. This binding is asserted +by a signature on the certificate, which is placed there by some +authority (the *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 +``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 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, 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 +``x509cert.h`` and ``asn1_obj.h`` (which has the +definitions of various common ASN.1 constructs used in X.509). + +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 ``subject_public_key``, which +will return a ``Public_Key*``. As to what to do with this, read +about ``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 +``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 $...$) different places where you can stick +information about the user: the *subject* field, and in an +extension called *subjectAlternativeName*. The *subject* +field is supposed to only included the following information: country, +organization, an organizational sub-unit name, 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 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 *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 ... 255), an +exception will get thrown. Currently the ``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 ``std::wstring`` instead of a +``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 +likely never want to use). However, there are three very useful pieces +of information that this extension might hold: an email address +([email protected]), a DNS name (somehost.example.com), or a URI +(http://www.example.com). + +So, how to get the information? Call ``subject_info`` with the +name of the piece of information you want, and it will return a +``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 +``std::string``. + +You can also get information about the issuer of the certificate in the same +way, using ``issuer_info``. + +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. + + - Key Usage and Extended Key Usage: No problems known. + + - 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. + + - Subject Alternative Names: Only the "rfc822Name", "dNSName", and + "uniformResourceIdentifier" fields will be stored; all others are + ignored. + + - Issuer Alternative Names: Same restrictions as the Subject + Alternative Names extension. New certificates generated by Botan + never include the issuer alternative name. + + - 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. + + - Subject Key Identifier: No problems known. + +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). Every once in a while the +CA will release a new 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 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 ``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:: + + X509_CRL crl1("crl1.der"); + + DataSource_Stream in("crl2.pem"); + X509_CRL crl2(in); + +After that, pass the ``X509_CRL`` object to a ``X509_Store`` object +with ``X509_Code`` ``add_crl``(``X509_CRL``), and all future +verifications will take into account the certificates listed, assuming +``add_crl`` returns ``VERIFIED``. If it doesn't return +``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 ``X509_Store`` API, read the section later in this chapter. + +Reading Certificates +--------------------------------- + +``X509_Certificate`` has two constructors, each of which takes a source of +data; a filename to read, and a ``DataSource&``. + +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: ``X509_Store``. + +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). + +Adding Certificates +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can add new certificates to a certificate store using any of these +functions: + +``add_cert``(``const X509_Certificate&`` ``cert``, + ``bool`` ``trusted`` ``= false``) + +``add_certs``(``DataSource&`` ``source``) + +``add_trusted_certs``(``DataSource&`` ``source``) + +The versions that take a ``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. + +Adding CRLs +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``X509_Code`` ``add_crl``(``const X509_CRL&`` ``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 +``VERIFIED`` if everything completed successfully. + +Storing Certificates +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can output a set of certificates by calling ``PEM_encode``, which +will return a ``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. + +Searching for Certificates +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can find certificates in the store with a series of functions contained +in the ``X509_Store_Search`` namespace:: + + 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); + +These functions will return a (possibly empty) vector of certificates from +``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 ``X509_Store_Search::by_name``(``your_store``, +"dob") will return certificates for ``J.R. 'Bob' Dobbs'' and +``H. Dobbertin'', assuming both of those certificates are in ``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. + +Certificate Stores +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +An object of 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 return an +empty ``std::vector`` of ``X509_Certificate``. This storage +mechanism is *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 ``by_SKID`` (Subject Key +Identifier), ``by_name`` (the CommonName DN entry), and +``by_email`` (stored in either the distinguished name, or in a +subjectAlternativeName extension). The name and email versions take a +``std::string``, while the SKID version takes a ``SecureVector<byte>`` +containing the subject key identifier in raw binary. You can choose not to +implement ``by_name`` or ``by_email``, but ``by_SKID`` +is mandatory to implement, and, currently, is the only version that is used by +``X509_Store``. + +Finally, there is a method for finding CRLs, called +``get_crls_for``, that takes an ``X509_Certificate`` +object, and returns a ``std::vector`` of ``X509_CRL``. While +normally 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 +``X509_CRL``. + +As for using such a store, you have to tell ``X509_Store`` about +it, by calling the ``X509_Store`` member function + +``add_new_certstore``(``Certificate_Store``* ``new_store``) + +The argument, ``new_store``, will be deleted by ``X509_Store``'s +destructor, so make sure to allocate it with ``new``. + +Verifying Certificates +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There is a single function in ``X509_Store`` related to verifying a +certificate: + +.. .cpp:function:: X509_Code validate_cert(const X509_Certificate& cert, Cert_Usage usage = ANY) + +This function will return ``VERIFIED`` if the certificate can +safely be considered valid for the usage(s) described by ``usage``, +and an error code if it is not. Naturally, things are a bit more +complicated than that. The enum ``Cert_Usage`` is defined inside +the ``X509_Store`` class, it (currently) can take on any of the +values ``ANY`` (any usage is OK), ``TLS_SERVER`` (for SSL/TLS +server authentication), ``TLS_CLIENT`` (for SSL/TLS client +authentication), ``CODE_SIGNING``, ``EMAIL_PROTECTION`` (email +encryption, usually this means S/MIME), ``TIME_STAMPING`` (in +theory any time stamp application, usually IETF PKIX's Time Stamp +Protocol), or ``CRL_SIGNING``. Note that Microsoft's code signing +system, certainly the most widely used, uses a completely different +(and mostly undocumented) method for marking certificates for code +signing. + +First, how does it know if a certificate is valid? 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 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 ``usage`` are ``TLS_SERVER``, ``TLS_CLIENT``, +``CODE_SIGNING``, ``EMAIL_PROTECTION``, ``CRL_SIGNING``, and +``TIME_STAMPING``, and ``ANY``. The default ``ANY`` does not mean +valid for any use, it means "is valid for some usage". This is usually +what you want; 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 ``validate_cert`` (and ``add_crl``) include: + + - VERIFIED: The certificate is valid for the specified use. + + - INVALID_USAGE: The certificate cannot be used for the specified use. + + - CANNOT_ESTABLISH_TRUST: The root certificate was not marked as + trusted. + + - CERT_CHAIN_TOO_LONG: The certificate chain exceeded the length + allowed by a basicConstraints extension. + + - SIGNATURE_ERROR: An invalid signature was found + + - POLICY_ERROR: Some problem with the certificate policies was found. + + - CERT_FORMAT_ERROR: Some format problem was found in a certificate. + - CERT_ISSUER_NOT_FOUND: The issuer of a certificate could not be found. + - CERT_NOT_YET_VALID: The certificate is not yet valid. + - CERT_HAS_EXPIRED: The certificate has expired. + - CERT_IS_REVOKED: The certificate has been revoked. + - CRL_FORMAT_ERROR: Some format problem was found in a CRL. + - CRL_ISSUER_NOT_FOUND: The issuer of a CRL could not be found. + - CRL_NOT_YET_VALID: The CRL is not yet valid. + - CRL_HAS_EXPIRED: The CRL has expired. + - CA_CERT_CANNOT_SIGN: The CA certificate found does not have an + contain a public key that allows signature verification. + - CA_CERT_NOT_FOR_CERT_ISSUER: The CA cert found is not allowed to + issue certificates. + - CA_CERT_NOT_FOR_CRL_ISSUER: The CA cert found is not allowed to + issue CRLs. + - UNKNOWN_X509_ERROR: Some other error occurred. + +Certificate Authorities +--------------------------------- + +Setting up a CA for X.509 certificates is perhaps the easiest thing to +do related to X.509. A CA is represented by the type ``X509_CA``, +which can be found in ``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:: + + X509_CA(const X509_Certificate& cert, const Private_Key& key); + +The private key is the private key corresponding to the public key in the +CA's certificate. + +Requests for new certificates are supplied to a CA in the form on PKCS +#10 certificate requests (called a ``PKCS10_Request`` object in +Botan). These are decoded in a similar manner to +certificates/CRLs/etc. A request is vetted by humans (who somehow +verify that the name in the request corresponds to the name of the +entity who requested it), and then signed by a CA key, generating a +new certificate:: + + X509_Certificate sign_request(const PKCS10_Request&) const; + +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. Never fear; empty CRLs, which revoke nothing at all, can +be issued. To generate a new, empty CRL, just call ``X509_CRL`` +``X509_CA::new_crl``(``size_t``~``seconds``~=~0)~--~it +will create a new, empty, CRL. If ``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 ``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 +``X509_CA`` member function +``update_crl``(``X509_CRL``~``old_crl``, +``std::vector<CRL_Entry>``~``new_revoked``, +``size_t``~``seconds``~=~0), where ``X509_CRL`` is the last CRL this +CA issued, and ``new_revoked`` is a list of any newly revoked certificates. +The function returns a new ``X509_CRL`` to make available for clients. The +semantics for the ``seconds`` argument is the same as ``new_crl``. + +The ``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 +``SecureVector<byte>`` called ``serial``. There are two additional +(optional) values, an enumeration called ``CRL_Code`` that specifies the +reason for revocation (``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 ``reason`` code of ``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. + +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. The library provides a utility function for this:: + +.. cpp:function:: X509_Certificate create_self_signed_cert(const X509_Cert_Options& opts, const Private_Key& key) + +Where ``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 +``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 ``x509self.h``. There is an +example of using this function in the ``self_sig`` example. + +Creating PKCS #10 Requests +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Also in ``x509self.h``, there is a function for generating new PKCS #10 +certificate requests:: + +.. cpp:function:: PKCS10_Request create_cert_req(const X509_Cert_Options&, const Private_Key&) + +This function acts quite similarly to ``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 +``pkcs10`` example. + +Certificate Options +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +What is this ``X509_Cert_Options`` thing we've been passing +around? It's a class representing 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 ``std::string`` members, which contains +various bits of information about the user: ``common_name``, +``serial_number``, ``country``, ``organization``, ``org_unit``, +``locality``, ``state``, ``email``, ``dns_name``, and ``uri``. As +many of these as possible should be filled it (especially an email address), +though the only required ones are ``common_name`` and ``country``. + +There is another value that is only useful when creating a PKCS #10 request, +which is called ``challenge``. This is a challenge password, which you can +later use to request certificate revocation (*if* the CA supports doing +revocations in this manner). + +Then there is the validity period; these are set with ``not_before`` +and ``not_after``. Both of these functions also take a +``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 ``CA_key``. This should only be used when needed. + +Other constraints can be set by calling the member functions +``add_constraints`` and ``add_ex_constraints``. The +first takes a ``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): +``DIGITAL_SIGNATURE``, ``NON_REPUDIATION``, +``KEY_ENCIPHERMENT``, ``DATA_ENCIPHERMENT``, +``KEY_AGREEMENT``, ``KEY_CERT_SIGN``, ``CRL_SIGN``, +``ENCIPHER_ONLY``, ``DECIPHER_ONLY``. Many of these have quite +special semantics, so you should either consult the appropriate +standards document (such as RFC 3280), or just not call +``add_constraints``, in which case the appropriate values will +be chosen for you. + +The second 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 "add_ex_constraints" any number of +times~--~each new OID will be added to the list to include in the +certificate. |