aboutsummaryrefslogtreecommitdiffstats
path: root/doc
diff options
context:
space:
mode:
authorlloyd <[email protected]>2008-09-30 21:13:38 +0000
committerlloyd <[email protected]>2008-09-30 21:13:38 +0000
commit3f0d484096e1e782f72e3cdf43853c7d9f309ee9 (patch)
tree341f05d66128321304aafc72df28854650e13ef1 /doc
parentb8115f4123a55510ab4f4840efb623de662a248f (diff)
parenta2c9be1a6bf801aac4d6d32759d51608f536d14a (diff)
propagate from branch 'net.randombit.botan' (head 9524e848cdacd0b56ded9bd6b51fd34b6a7d3fc4)
to branch 'net.randombit.botan.ecdsa' (head 8231f4285dce2d5ec754f7afa72e0d34807de061)
Diffstat (limited to 'doc')
-rw-r--r--doc/building.tex176
-rw-r--r--doc/credits.txt4
-rw-r--r--doc/examples/GNUmakefile26
-rw-r--r--doc/examples/Makefile134
-rw-r--r--doc/examples/bzip.cpp14
-rw-r--r--doc/examples/cms_dec.cpp111
-rw-r--r--doc/examples/cms_enc.cpp46
-rw-r--r--doc/examples/decrypt.cpp6
-rw-r--r--doc/examples/eax_test.cpp240
-rw-r--r--doc/examples/eax_tv.txt461
-rw-r--r--doc/examples/encrypt.cpp9
-rw-r--r--doc/examples/gtk/Makefile18
-rw-r--r--doc/examples/gtk/dsa.cpp556
-rw-r--r--doc/examples/gtk/gtk_ui.cpp78
-rw-r--r--doc/examples/gtk/gtk_ui.h25
-rw-r--r--doc/examples/gtk/readme.txt18
-rw-r--r--doc/examples/hash_fd.cpp2
-rw-r--r--doc/examples/make_prime.cpp69
-rw-r--r--doc/examples/pqg_gen.cpp114
-rw-r--r--doc/examples/ressol.cpp77
-rw-r--r--doc/examples/rng_test.cpp136
-rw-r--r--doc/examples/row_encryptor.cpp134
-rw-r--r--doc/examples/rsa_manykey.cpp34
-rw-r--r--doc/examples/sig_gen.cpp90
-rw-r--r--doc/info.txt5
-rw-r--r--doc/log.txt35
-rwxr-xr-xdoc/scripts/comba.py65
-rwxr-xr-xdoc/scripts/combine_bmarks.pl120
-rwxr-xr-xdoc/scripts/dist.sh63
-rwxr-xr-xdoc/scripts/primes.py63
-rw-r--r--doc/thanks.txt2
-rw-r--r--doc/todo.txt4
32 files changed, 2701 insertions, 234 deletions
diff --git a/doc/building.tex b/doc/building.tex
index 2cb1d0723..bff6cc6fa 100644
--- a/doc/building.tex
+++ b/doc/building.tex
@@ -13,7 +13,7 @@
\title{\textbf{Botan Build Guide}}
\author{Jack Lloyd \\
-\date{}
+\date{2008-09-30}
\newcommand{\filename}[1]{\texttt{#1}}
\newcommand{\module}[1]{\texttt{#1}}
@@ -41,10 +41,13 @@ POSIX (such as VMS, MacOS 9, OS/390, OS/400, ...) are not supported by
the build system, primarily due to lack of access. Please contact the
maintainer if you would like to build Botan on such a system.
+Botan's build is controlled by configure.pl, which is a Perl
+script. Perl 5.6 or later is required.
+
\section{For the Impatient}
\begin{verbatim}
-$ ./configure.pl
+$ ./configure.pl [--prefix=/some/directory]
$ make
$ make install
\end{verbatim}
@@ -77,24 +80,42 @@ 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.
-The script also knows about the various extension modules
-available. You can enable one or more with the option
-``\verb|--modules=MOD|'', where \verb|MOD| is some name that
-identifies the extension (or a comma separated list of them). Modules
-provide additional capabilities which require the use of APIs not
-provided by ISO C/C++.
+By default the script tries to figure out what will work on your
+system, and use that. It will print a display at the end showing
+which algorithms have and have not been abled. For instance on one
+system we might see the line:
+
+\begin{verbatim}
+ (loading): entropy: [beos_stats] buf_es [cryptoapi_rng] \\
+ dev_random egd proc_walk unix_procs [win32_stats]
+\end{verbatim}
-Not all OSes or CPUs have specific support in \filename{configure.pl}. If the
-CPU architecture of your system isn't supported by \filename{configure.pl}, use
-'generic'. This setting disables machine-specific optimization
-flags. Similarly, setting OS to 'generic' disables things which depend greatly
-on OS support (specifically, shared libraries).
+The names listed in brackets are disabled, the others are
+enabled. Here we see the list of entropy sources which are going to be
+compiled into Botan. Since this particular line comes when Botan was
+configuring for a Linux system, the Win32 and BeOS specific modules
+were disabled, while modules that use Unix APIs and /dev/random are
+built.
+
+You can control which algorithms and modules are built using the
+options ``\verb|--enable-modules=MODS|'' and
+``\verb|--disable-modules=MODS|'', for instance \\
+``\verb|--enable-modules=blowfish,md5,rsa,zlib --disable-modules=arc4,cmac|''.
+Modules not listed on the command line will simply be loaded if needed
+or if configured to load by default.
+
+Not all OSes or CPUs have specific support in
+\filename{configure.pl}. If the CPU architecture of your system isn't
+supported by \filename{configure.pl}, use 'generic'. This setting
+disables machine-specific optimization flags. Similarly, setting OS to
+'generic' disables things which depend greatly on OS support
+(specifically, shared libraries).
However, it's impossible to guess which options to give to a system
compiler. Thus, if you want to compile Botan with a compiler which
\filename{configure.pl} does not support, you will need to tell it how
that compiler works. This is done by adding a new file in the
-directory \filename{misc/config/cc}; the existing files should put you
+directory \filename{src/build-data/cc}; the existing files should put you
in the right direction.
The script tries to guess what kind of makefile to generate, and it
@@ -105,7 +126,7 @@ commands). Just in case, you can override it with
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{misc/config/makefile}.
+\filename{src/build-data/makefile}.
\pagebreak
@@ -114,7 +135,7 @@ script for VMS), you will need to create a new template file in
The basic build procedure on Unix and Unix-like systems is:
\begin{verbatim}
- $ ./configure.pl --module-set=[unix|beos] --modules=<other mods>
+ $ ./configure.pl [--enable-modules=<list>] [--cc=CC]
$ make
# You may need to set your LD_LIBRARY_PATH or equivalent for ./check to run
$ make check # optional, but a good idea
@@ -124,13 +145,6 @@ The basic build procedure on Unix and Unix-like systems is:
This will probably default to using GCC, depending on what can be
found within your PATH.
-The 'unix' module set should work on most POSIX/Unix systems out there
-(including MacOS X), while the 'beos' module is specific to BeOS. While the two
-sets share a number of modules, some normal Unix ones don't work on BeOS (in
-particular, BeOS doesn't have a working \function{mmap} function), and BeOS has
-a few extras just for it. The library will pick a default module set for you
-based on the value of OS, so there is rarely a reason to specify that.
-
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
@@ -152,47 +166,44 @@ The situation is not much different here. We'll assume you're using Visual C++
have a copy of Perl installed, and have both Perl and Visual C++ in your path.
\begin{verbatim}
- > perl configure.pl --cc=msvc --os=windows [--cpu=CPU] --module-set=win32
+ > perl configure.pl --cc=msvc --os=windows [--cpu=CPU]
> nmake
> nmake check # optional, but recommended
\end{verbatim}
-The configure script will include the 'win32' module set by default if
-you pass \verb|--os=windows|. This module set includes a pair of
-entropy sources for use on Windows; at some point in the future it
-will also add support for high-resolution timers, mutexes for thread
-safety, and other useful things.
-
-For Win95 pre OSR2, the \verb|es_capi| module will not work, because
-CryptoAPI didn't exist. All versions of NT4 lack the ToolHelp32
-interface, which is how \verb|es_win32| does its slow polls, so a
-version of the library built with that module will not load under
-NT4. Later systems (98/ME/2000/XP) support both methods, so this
-shouldn't be much of an issue.
+For Win95 pre OSR2, the \verb|cryptoapi\_rng| module will not work,
+because CryptoAPI didn't exist. And all versions of NT4 lack the
+ToolHelp32 interface, which is how \verb|win32_stats| does its slow
+polls, so a version of the library built with that module will not
+load under NT4. Later systems (98/ME/2000/XP) support both methods, so
+this shouldn't be much of an issue.
Unfortunately, there currently isn't an install script usable on
Windows. Basically all you have to do is copy the newly created
\filename{libbotan.lib} to someplace where you can find it later (say,
-\verb|C:\Botan\|). Then copy the entire \verb|include\botan| directory, which
-was constructed when you built the library, into the same directory.
+\verb|C:\botan\|). Then copy the entire \verb|build\include\botan|
+directory, which was constructed when you built the library, into the
+same directory.
When building your applications, all you have to do is tell the compiler to
-look for both include files and library files in \verb|C:\Botan|, and it will
+look for both include files and library files in \verb|C:\botan|, and it will
find both.
\pagebreak
\subsection{Configuration Parameters}
-There are some configuration parameters which you may want to tweak before
-building the library. These can be found in \filename{config.h}. This file is
-overwritten every time the configure script is run (and does not exist until
-after you run the script for the first time).
+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{config.h} are macros which are defined if one or
-more extensions are available. All of them begin with \verb|BOTAN_EXT_|. For
-example, if \verb|BOTAN_EXT_COMPRESSOR_BZIP2| is defined, then an application
-using Botan can include \filename{<botan/bzip2.h>} and use the Bzip2 filters.
+Also included in \filename{config.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
@@ -232,9 +243,9 @@ environment in a different directory.
You may want to do something peculiar with the configuration; to
support this there is a flag to \filename{configure.pl} called
-\texttt{--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.
+\texttt{--with-local-config=<file>}. The contents of the file are
+inserted into \filename{build/build.h} which is (indirectly) included
+into every Botan header and source file.
\pagebreak
@@ -252,80 +263,73 @@ unusual circumstances. The modules included with this release are:
the sensitive data will be swapped to where we can later clean it,
rather than somewhere in the swap partition.}
- \item \mod{comp\_bzip2}{Enables an application to perform bzip2 compression
+ \item \mod{bzip2}{Enables an application to perform bzip2 compression
and decompression using the library. Available on any system that has
bzip2.}
- \item \mod{comp\_zlib}{Enables an application to perform zlib compression and
+ \item \mod{zlib}{Enables an application to perform zlib compression and
decompression using the library. Available on any system that has
zlib.}
- \item \mod{eng\_aep}{An engine that uses any available AEP accelerator card
- to speed up PK operations. You have to have the AEP drivers installed
- for this to link correctly, but you don't have to have a card
- installed - it will automatically be enabled if a card is detected at
- run time.}
+ %\item \mod{eng\_aep}{An engine that uses any available AEP accelerator card
+ % to speed up PK operations. You have to have the AEP drivers installed
+ % for this to link correctly, but you don't have to have a card
+ % installed - it will automatically be enabled if a card is detected at
+ % run time.}
- \item \mod{eng\_gmp}{An engine that uses GNU MP to speed up PK operations.
+ \item \mod{gnump}{An engine that uses GNU MP to speed up PK operations.
GNU MP 4.1 or later is required.}
- \item \mod{eng\_ossl}{An engine that uses OpenSSL's BN library to speed up PK
- operations. OpenSSL 0.9.7 or later is required.}
+ \item \mod{openssl}{An engine that uses OpenSSL to speed up public key
+ operations and some ciphers/hashes. OpenSSL 0.9.7 or
+ later is required.}
- \item \mod{es\_beos}{An entropy source that uses BeOS-specific APIs to gather
- (hopefully unpredictable) data from the system.}
+ \item \mod{beos\_stats}{An entropy source that uses BeOS-specific
+ APIs to gather (hopefully unpredictable) data from the system.}
- \item \mod{es\_capi}{An entropy source that uses the Win32 CryptoAPI function
- \texttt{CryptGenRandom} to gather entropy. Supported on NT4, Win95
- OSR2, and all later Windows systems.}
+ \item \mod{cryptoapi\_rng}{An entropy source that uses the Win32
+ CryptoAPI function \texttt{CryptGenRandom} to gather
+ entropy. Supported on NT4, Win95 OSR2, and all later Windows
+ systems.}
- \item \mod{es\_egd}{An entropy source that accesses EGD (the entropy
+ \item \mod{egd}{An entropy source that accesses EGD (the entropy
gathering daemon). Common on Unix systems that don't have
\texttt{/dev/random}.}
- \item \mod{es\_ftw}{Gather entropy by reading files from a particular file
+ \item \mod{proc\_walk}{Gather entropy by reading files from a particular file
tree. Usually used with \texttt{/proc}; most other file trees don't
have sufficient variability over time to be useful.}
- \item \mod{es\_unix}{Gather entropy by running various Unix programs, like
+ \item \mod{unix\_procs}{Gather entropy by running various Unix programs, like
\texttt{arp} and \texttt{vmstat}, and reading their output in the
hopes that at least some of it will be unpredictable to an attacker.}
- \item \mod{es\_win32}{Gather entropy by walking through various pieces of
+ \item \mod{win32\_stats}{Gather entropy by walking through various pieces of
information about processes running on the system. Does not run on
NT4, but should run on all other Win32 systems.}
\item \mod{fd\_unix}{Let the users of \texttt{Pipe} perform I/O with Unix
file descriptors in addition to \texttt{iostream} objects.}
- \item \mod{ml\_unix}{Add hooks for locking memory into RAM. Usually requires
- the application to run as \texttt{root} to actually work, but if the
- application is not allowed to call \texttt{mlock}, no harm results.}
-
- \item \mod{mp\_asm64}{Use inline assembly to access the multiply instruction
- available on some 64-bit CPUs. This module only runs on Alpha, AMD64,
- IA-64, MIPS64, and PowerPC-64. Typically PKI operations are several
- times as fast with this module than without.}
-
- \item \mod{mux\_pthr}{Add support for using \texttt{pthread} mutexes to
+ \item \mod{pthread}{Add support for using \texttt{pthread} mutexes to
lock internal data structures. Important if you are using threads
with the library.}
- \item \mod{mux\_qt}{Add support for using Qt mutexes to lock internal data
+ \item \mod{qt\_mutex}{Add support for using Qt mutexes to lock internal data
structures.}
- \item \mod{tm\_hard}{Use the contents of the CPU cycle counter when
+ \item \mod{cpu\_counter}{Use the contents of the CPU cycle counter when
generating random bits to further randomize the results. Works on x86
(Pentium and up), Alpha, and SPARCv9.}
- \item \mod{tm\_posix}{Use the POSIX realtime clock as a high-resolution
+ \item \mod{posix\_rt}{Use the POSIX realtime clock as a high-resolution
timer.}
- \item \mod{tm\_unix}{Use the traditional Unix \texttt{gettimeofday} as a high
- resolution timer.}
+ \item \mod{gettimeofday}{Use the traditional Unix
+ \texttt{gettimeofday} as a high resolution timer.}
- \item \mod{tm\_win32}{Use Win32's \texttt{GetSystemTimeAsFileTime} as a high
- resolution timer.}
+ \item \mod{win32\_query\_perf\_ctr}{Use Win32's
+ \texttt{QueryPerformanceCounter} as a high resolution timer.}
\end{list}
diff --git a/doc/credits.txt b/doc/credits.txt
index 79818565e..be7d23626 100644
--- a/doc/credits.txt
+++ b/doc/credits.txt
@@ -44,6 +44,10 @@ S: New York NY, USA
N: Joel Low
D: DLL symbol visibility
+N: Vaclav Ovsik
+D: Perl XS module
+
N: Luca Piccarreta
D: x86/amd64 assembler, BigInt optimizations, Win32 mutex module
diff --git a/doc/examples/GNUmakefile b/doc/examples/GNUmakefile
new file mode 100644
index 000000000..4b45af0a6
--- /dev/null
+++ b/doc/examples/GNUmakefile
@@ -0,0 +1,26 @@
+# Assumes Botan was compiled with GCC
+
+BOTAN_DIR = ../..
+
+CXX = g++
+CFLAGS = -O2 -ansi -W -Wall
+
+INCLUDES = $(shell $(BOTAN_DIR)/botan-config --cflags)
+
+LIBS = $(shell $(BOTAN_DIR)/botan-config --libs)
+FLAGS = $(INCLUDES) $(CFLAGS) -I$(BOTAN_DIR)/build/include -L$(BOTAN_DIR)
+
+SRCS=$(wildcard *.cpp)
+
+PROGS=$(patsubst %.cpp,%,$(SRCS))
+
+all: $(PROGS)
+
+clean:
+ @rm -f $(PROGS)
+
+%: %.cpp
+ $(CXX) $(FLAGS) $? $(LIBS) -o $@
+
+eax_test: eax_test.cpp
+ $(CXX) $(FLAGS) $? $(LIBS) -lboost_regex -o $@
diff --git a/doc/examples/Makefile b/doc/examples/Makefile
deleted file mode 100644
index 879d48d83..000000000
--- a/doc/examples/Makefile
+++ /dev/null
@@ -1,134 +0,0 @@
-# Assumes Botan was compiled with GCC
-
-BOTAN_DIR = ../..
-
-CXX = g++
-CFLAGS = -O2 -ansi -W -Wall
-
-INCLUDES = `$(BOTAN_DIR)/botan-config --cflags`
-LIBS = `$(BOTAN_DIR)/botan-config --libs`
-FLAGS = $(INCLUDES) $(CFLAGS) -I$(BOTAN_DIR)/build/include -L$(BOTAN_DIR)
-
-PROGS = asn1 base base64 bzip ca decrypt dh dsa_kgen dsa_sign dsa_ver \
- ecdsa encrypt factor hash hash_fd hasher hasher2 \
- passhash pkcs10 rsa_dec rsa_enc rsa_kgen self_sig stack \
- x509info xor_ciph
-
-STRIP = true
-
-all: $(PROGS)
-
-clean:
- @rm -f $(PROGS)
-
-asn1: asn1.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
-
-base: base.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
-
-base64: base64.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
-
-bzip: bzip.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
-
-ca: ca.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
-
-decrypt: decrypt.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
-
-dh: dh.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
-
-dsa_kgen: dsa_kgen.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
-
-dsa_sign: dsa_sign.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
-
-dsa_ver: dsa_ver.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
-
-encrypt: encrypt.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
-
-ecdsa: ecdsa.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
-
-factor: factor.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
-
-hash: hash.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
-
-hash_fd: hash_fd.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
-
-hasher: hasher.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
-
-hasher2: hasher2.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
-
-pass_dec: pass_dec.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
-
-pass_enc: pass_enc.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
-
-passhash: passhash.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
-
-pkcs10: pkcs10.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
-
-rsa_dec: rsa_dec.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
-
-rsa_enc: rsa_enc.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
-
-rsa_kgen: rsa_kgen.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
-
-self_sig: self_sig.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
-
-stack: stack.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
-
-x509info: x509info.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
-
-xor_ciph: xor_ciph.cpp
- $(CXX) $(FLAGS) $? $(LIBS) -o $@
- @$(STRIP) $@
diff --git a/doc/examples/bzip.cpp b/doc/examples/bzip.cpp
index 82bc3100a..1abe4d309 100644
--- a/doc/examples/bzip.cpp
+++ b/doc/examples/bzip.cpp
@@ -12,10 +12,8 @@ This file is in the public domain
#include <iostream>
#include <botan/botan.h>
-#if defined(BOTAN_EXT_COMPRESSOR_BZIP2)
+#if defined(BOTAN_HAS_COMPRESSOR_BZIP2)
#include <botan/bzip2.h>
-#else
- #error "You didn't compile the bzip module into Botan"
#endif
const std::string SUFFIX = ".bz2";
@@ -52,11 +50,19 @@ int main(int argc, char* argv[])
try {
- Botan::Filter* bzip;
+ 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);
diff --git a/doc/examples/cms_dec.cpp b/doc/examples/cms_dec.cpp
new file mode 100644
index 000000000..593cf2e09
--- /dev/null
+++ b/doc/examples/cms_dec.cpp
@@ -0,0 +1,111 @@
+#include <botan/cms_dec.h>
+using namespace Botan;
+
+#include <iostream>
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 2)
+ {
+ printf("Usage: %s <filename>\n", argv[0]);
+ return 1;
+ }
+
+ LibraryInitializer init;
+
+ try {
+ X509_Certificate mycert("mycert.pem");
+ PKCS8_PrivateKey* mykey = PKCS8::load_key("mykey.pem", "cut");
+
+ X509_Certificate yourcert("yourcert.pem");
+ X509_Certificate cacert("cacert.pem");
+ X509_Certificate int_ca("int_ca.pem");
+
+ X509_Store store;
+ store.add_cert(mycert);
+ store.add_cert(yourcert);
+ store.add_cert(cacert, true);
+ store.add_cert(int_ca);
+
+ DataSource_Stream message(argv[1]);
+
+ User_Interface ui;
+
+ CMS_Decoder decoder(message, store, ui, mykey);
+
+ while(decoder.layer_type() != CMS_Decoder::DATA)
+ {
+ CMS_Decoder::Status status = decoder.layer_status();
+ CMS_Decoder::Content_Type content = decoder.layer_type();
+
+ if(status == CMS_Decoder::FAILURE)
+ {
+ std::cout << "Failure reading CMS data" << std::endl;
+ break;
+ }
+
+ if(content == CMS_Decoder::DIGESTED)
+ {
+ std::cout << "Digested data, hash = " << decoder.layer_info()
+ << std::endl;
+ std::cout << "Hash is "
+ << ((status == CMS_Decoder::GOOD) ? "good" : "bad")
+ << std::endl;
+ }
+
+ if(content == CMS_Decoder::SIGNED)
+ {
+ // how to handle multiple signers? they can all exist within a
+ // single level...
+
+ std::cout << "Signed by " << decoder.layer_info() << std::endl;
+ //std::cout << "Sign time: " << decoder.xxx() << std::endl;
+ std::cout << "Signature is ";
+ if(status == CMS_Decoder::GOOD)
+ std::cout << "valid";
+ else if(status == CMS_Decoder::BAD)
+ std::cout << "bad";
+ else if(status == CMS_Decoder::NO_KEY)
+ std::cout << "(cannot check, no known cert)";
+ std::cout << std::endl;
+ }
+ if(content == CMS_Decoder::ENVELOPED ||
+ content == CMS_Decoder::COMPRESSED ||
+ content == CMS_Decoder::AUTHENTICATED)
+ {
+ if(content == CMS_Decoder::ENVELOPED)
+ std::cout << "Enveloped";
+ if(content == CMS_Decoder::COMPRESSED)
+ std::cout << "Compressed";
+ if(content == CMS_Decoder::AUTHENTICATED)
+ std::cout << "MACed";
+
+ std::cout << ", algo = " << decoder.layer_info() << std::endl;
+
+ if(content == CMS_Decoder::AUTHENTICATED)
+ {
+ std::cout << "MAC status is ";
+ if(status == CMS_Decoder::GOOD)
+ std::cout << "valid";
+ else if(status == CMS_Decoder::BAD)
+ std::cout << "bad";
+ else if(status == CMS_Decoder::NO_KEY)
+ std::cout << "(cannot check, no key)";
+ std::cout << std::endl;
+ }
+ }
+ decoder.next_layer();
+ }
+
+ if(decoder.layer_type() == CMS_Decoder::DATA)
+ std::cout << "Message is \"" << decoder.get_data()
+ << '"' << std::endl;
+ else
+ std::cout << "No data anywhere?" << std::endl;
+ }
+ catch(std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
+ return 0;
+ }
diff --git a/doc/examples/cms_enc.cpp b/doc/examples/cms_enc.cpp
new file mode 100644
index 000000000..0319925d8
--- /dev/null
+++ b/doc/examples/cms_enc.cpp
@@ -0,0 +1,46 @@
+#include <botan/cms_enc.h>
+using namespace Botan;
+
+#include <iostream>
+#include <fstream>
+
+int main()
+ {
+ LibraryInitializer init;
+
+ try {
+ PKCS8_PrivateKey* mykey = PKCS8::load_key("mykey.pem", "cut");
+
+ 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");
+
+ 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(mycert);
+ encoder.sign(store, *mykey);
+
+ SecureVector<byte> raw = encoder.get_contents();
+ std::ofstream out("out.der");
+
+ out.write((const char*)raw.ptr(), raw.size());
+ }
+ catch(std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
+ return 0;
+ }
diff --git a/doc/examples/decrypt.cpp b/doc/examples/decrypt.cpp
index 279a341fe..7018e5f49 100644
--- a/doc/examples/decrypt.cpp
+++ b/doc/examples/decrypt.cpp
@@ -18,10 +18,8 @@ This file is in the public domain
#include <botan/botan.h>
-#if defined(BOTAN_EXT_COMPRESSOR_ZLIB)
+#if defined(BOTAN_HAS_COMPRESSOR_ZLIB)
#include <botan/zlib.h>
-#else
- #error "You didn't compile the zlib module into Botan"
#endif
using namespace Botan;
@@ -112,7 +110,9 @@ int main(int argc, char* argv[])
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),
diff --git a/doc/examples/eax_test.cpp b/doc/examples/eax_test.cpp
new file mode 100644
index 000000000..b69aec5e9
--- /dev/null
+++ b/doc/examples/eax_test.cpp
@@ -0,0 +1,240 @@
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include <boost/regex.hpp>
+
+#include <botan/botan.h>
+#include <botan/eax.h>
+
+using namespace Botan;
+
+unsigned to_string(const std::string& s)
+ {
+ std::istringstream stream(s);
+ unsigned n;
+ stream >> n;
+ return n;
+ }
+
+std::string seq(unsigned n)
+ {
+ std::string s;
+
+ for(unsigned i = 0; i != n; ++i)
+ {
+ unsigned char b = (i & 0xFF);
+
+ const char bin2hex[] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+ s += bin2hex[(b >> 4)];
+ s += bin2hex[(b & 0x0f)];
+ }
+
+ return s;
+ }
+
+void eax_test(const std::string& algo,
+ const std::string& key_str,
+ const std::string& nonce_str,
+ const std::string& header_str,
+ const std::string& tag_str,
+ const std::string& plaintext_str,
+ const std::string& ciphertext)
+ {
+ /*
+ printf("EAX(algo=%s key=%s nonce=%s header=%s tag=%s pt=%s ct=%s)\n",
+ algo.c_str(), key_str.c_str(), nonce_str.c_str(), header_str.c_str(), tag_str.c_str(),
+ plaintext_str.c_str(), ciphertext.c_str());
+ */
+
+ //std::auto_ptr<RandomNumberGenerator> rng(RandomNumberGenerator::make_rng());
+
+ SymmetricKey key(key_str);
+ InitializationVector iv(nonce_str);
+
+ EAX_Encryption* enc;
+
+ Pipe pipe(new Hex_Decoder,
+ enc = new EAX_Encryption(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(algo),
+ new Hex_Encoder);
+
+ dec->set_key(key);
+ dec->set_iv(iv);
+
+ dec->set_header(header.begin(), header.length());
+
+ pipe2.start_msg();
+ pipe2.write(ciphertext);
+ pipe2.write(tag_str);
+ pipe2.end_msg();
+
+ std::string out2 = pipe2.read_all_as_string();
+
+ if(out2 != plaintext_str)
+ {
+ printf("BAD decrypt %s '%s'\n", algo.c_str(), out2.c_str());
+ }
+ else
+ printf("OK decrypt %s\n", algo.c_str());
+ }
+ catch(std::exception& e)
+ {
+ printf("%s\n", e.what());
+ }
+
+ }
+
+std::pair<std::string, int> translate_algo(const std::string& in)
+ {
+ if(in == "aes (16 byte key)")
+ return std::make_pair("AES-128", 16);
+
+ if(in == "blowfish (8 byte key)")
+ return std::make_pair("Blowfish", 8);
+
+ if(in == "rc2 (8 byte key)")
+ return std::make_pair("RC2", 8);
+
+ if(in == "rc5 (8 byte key)")
+ return std::make_pair("RC5", 8);
+
+ if(in == "rc6 (16 byte key)")
+ return std::make_pair("RC6", 16);
+
+ if(in == "safer-sk128 (16 byte key)")
+ return std::make_pair("SAFER-SK(10)", 16);
+
+ if(in == "twofish (16 byte key)")
+ return std::make_pair("Twofish", 16);
+
+ if(in == "des (8 byte key)")
+ return std::make_pair("DES", 8);
+
+ if(in == "3des (24 byte key)")
+ return std::make_pair("TripleDES", 24);
+
+ // These 3 are disabled due to differences in base algorithm.
+
+#if 0
+ // XTEA: LTC uses little endian, Botan (and Crypto++) use big-endian
+ // I swapped to LE in XTEA and the vectors did match
+ if(in == "xtea (16 byte key)")
+ return std::make_pair("XTEA", 16);
+
+ // Skipjack: LTC uses big-endian, Botan (and Crypto++) use
+ // little-endian I am not sure if that was the full difference
+ // though, was unable to replicate LTC's EAX vectors with Skipjack
+ if(in == "skipjack (10 byte key)")
+ return std::make_pair("Skipjack", 10);
+
+ // Noekeon: unknown cause, though LTC's lone test vector does not
+ // match Botan
+
+ if(in == "noekeon (16 byte key)")
+ return std::make_pair("Noekeon", 16);
+
+#endif
+
+ return std::make_pair("", 0);
+ }
+
+std::string rep(const std::string& s_in, unsigned n)
+ {
+ std::string s_out;
+
+ for(unsigned i = 0; i != n; ++i)
+ s_out += s_in[i % s_in.size()];
+
+ return s_out;
+ }
+
+void run_tests(std::istream& in)
+ {
+ std::string algo;
+ std::string key;
+
+ while(in.good())
+ {
+ std::string line;
+
+ std::getline(in, line);
+
+ if(line == "")
+ continue;
+
+ if(line.size() > 5 && line.substr(0, 4) == "EAX-")
+ {
+ std::pair<std::string, int> name_and_keylen = translate_algo(line.substr(4));
+ algo = name_and_keylen.first;
+ key = seq(name_and_keylen.second);
+ }
+ else if(algo != "")
+ {
+ boost::regex vec_regex("^([ 0-9]{3}): (.*), (.*)$");
+
+ boost::smatch what;
+
+ if(boost::regex_match(line, what, vec_regex, boost::match_extra))
+ {
+ unsigned n = to_string(what[1]);
+ std::string ciphertext = what[2];
+ std::string tag = what[3];
+
+ std::string plaintext = seq(n);
+ std::string header = seq(n);
+ std::string nonce = seq(n);
+
+ eax_test(algo, key, nonce, header, tag,
+ plaintext, ciphertext);
+
+ key = rep(tag, key.size()); // repeat as needed
+ }
+ }
+ }
+
+
+ }
+
+int main()
+ {
+ std::ifstream in("eax_tv.txt");
+
+ 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
new file mode 100644
index 000000000..95cd7c1ab
--- /dev/null
+++ b/doc/examples/eax_tv.txt
@@ -0,0 +1,461 @@
+EAX Test Vectors. Uses the 00010203...NN-1 pattern for header/nonce/plaintext/key. The outputs
+are of the form ciphertext,tag for a given NN. The key for step N>1 is the tag of the previous
+step repeated sufficiently.
+
+EAX-aes (16 byte key)
+ 0: , 9AD07E7DBFF301F505DE596B9615DFFF
+ 1: 47, 57C4AC75A42D05260AFA093ACD4499ED
+ 2: C4E2, 26C5AB00325306772E6F6E4C8093F3D2
+ 3: 16177B, 852260F91F27898D4FC176E311F6E1D1
+ 4: F09F68BE, 700766CA231643B5D60C3B91B1B700C1
+ 5: 8472705EDF, AC4C3359326EEA4CF71FC03E0E0292F2
+ 6: 14C25EB5FD0D, 8DBD749CA79CCF11C1B370F8C975858C
+ 7: F6A37F60670A85, AFBD1D5921557187504ADE61014C9622
+ 8: 1AACFEAE8FBAD833, 82F477325D6F76BB81940AE25F9801C2
+ 9: 069414324EC293697C, B980E21C09CA129B69E9032D980A9DC5
+ 10: D8174DE9A2FC92B7DA9C, 1E42CC58BA2C8BFD83806444EA29DB61
+ 11: 2C087DEA30F8B7EE510990, 83DB400A080C4D43CAA6EC3F1085A923
+ 12: F36B93C272A703D3422C6A11, 1370C3AF2F3392916364BBBCC2C62EC1
+ 13: A0F33477BAE2E28E6747AA3193, B626DC719528CAC65DB0EF94E35422CE
+ 14: FCF5193506052E8BFA095C1A5205, F5BD02E0B3C91CC7D6FAAA8A9A76CE6A
+ 15: 3797D7F8599B8EEAB39C56241880DC, 0B70003E77146B903F06EF294FECD517
+ 16: C4BAD0E0356FFD369110C048D45D81BE, DE7C2B1D83BE2CC8EA402ABE1038BB79
+ 17: AF5C358BD31CDCAC2F0EA5252F1C3BE1E4, 2D700986F93B22DFE6695C2A243B4E42
+ 18: 7DEF9056FBDAF491D7206B26B19DEF617AA1, E71A7D00BE972D85C77931D7591B2151
+ 19: 6E9B2C0A90BF9D38A6EA3B5D2B9B2D97F938EB, 5B483D7F15C39602C2918181E57DA341
+ 20: 7C5F68DEE9BBA3B04F11D5FC7C9C7FE6E8B5025C, 0AE6A12D37A9C10BB1A494E16705DC05
+ 21: AF0A886BF673BC72045FC074F06A0176C96105E2E6, 06B2DC9A2868C23F86D710E01E37E07B
+ 22: 5F228A986DFE4301EDBAF07A02E114F1B30932995CD1, 74EBF68627C78B1FD024A59B56B2A8FA
+ 23: 911322F60555118CBECD8DD82F186AC19514316E8D48BA, B6A8BAF2F175CD0C71B63B1EF37E185E
+ 24: E7F52730CFB808EFDB376A5D5DF31A7EF8292DC5FC37E9BC, BA2AD158A2D2E5CE01296402B592E1DB
+ 25: B3F8D7CA47D8D86E94D670AFBAFA3B8D9E186C97DC029D4705, 709D2D2B9975D4729C19D4EAC430E65E
+ 26: 7178FEC027AFADDC2C03518E75CF34D207CAC2EB1537A0DBA520, A315F034CE5E66601444402520F55DE2
+ 27: FC230B2B8522F53459D0B968421469BBA7E683ACB0190393B2870F, 48679A78E470E175CF3D3E9B46CEDFCE
+ 28: 35A641127C78C721ECDC50866C21637FDC9515E41CE60F09015EA713, 0062987222F6412B7AAF8A9ABF6FBF98
+ 29: 3D42D6C113421743C08A6F682CFA0E517D5531BB66241C02EC4DCC26F7, B1AAFE11FA2D6E0C870177DDD7F98FF0
+ 30: DAD065B4669B7C59C8392D8E7BD7E64BC01CEFFF27E335B25A328D356F0E, 8973B9B9ECF26DAB58CCF0787EE928E5
+ 31: EBE626F9E241FD233D9781C359430C982667AA26921B62E98FAEC502C01B0B, 2AC0D7052A2CDCCE8E26FEA7595198AA
+ 32: 64D842B66796A797C2B4C6905742FDF2148FFC445E192F9E03B53810C082F788, 9778B345EC12D222DCC6DBABD2651750
+
+EAX-blowfish (8 byte key)
+ 0: , D8C4C23A6AC0B7B7
+ 1: 2A, 5E0E4BDDB60772FB
+ 2: 7695, 7581B16CCC9C45F1
+ 3: EB14C8, 6223A121CFA216C7
+ 4: 5A5C809C, 4A47658796337D6A
+ 5: 8BC2041181, E1FBA8DBA00571FC
+ 6: 89C666F015FA, 2B4A76A0E699FCFE
+ 7: 86C1FA92484AF6, 31B3B738A261D6F5
+ 8: D1F401C145C9328B, 4C4A045EB489F59C
+ 9: 70C9C7753698324A73, AB298B5B20567EB4
+ 10: A50D9D88DC101B6DC8D2, 529DFCBFD13B8E6C
+ 11: 7CC2885C2BE79C44F28FF2, 566255022B40C81C
+ 12: 6902D58347C29250EE07981C, 34619AF18E14C690
+ 13: AB6C3C4AD3EC45143392B642DA, E6D2DD323DA175BB
+ 14: 7065B28BA8AB67B2FB7B6D5E3FAF, AEDCAA54F4B0772F
+ 15: CBBA14A74AD4ADC0EF036EDAE42D51, F2BFFA4D81BAC034
+ 16: 60A315193F58144F5701D547C79FEEED, 912FDBDB05467DF5
+
+EAX-xtea (16 byte key)
+ 0: , 86881D824E3BC561
+ 1: EE, 4C3505F04611D9C2
+ 2: 80C8, 6A3428BEEAD60738
+ 3: BF88E7, 04F1E99E9F5906C2
+ 4: E06574B7, 33B0153AAEF9776F
+ 5: 42D950AF63, 4A0F415640322FDF
+ 6: C30F6AD46EC9, 9646FE909D2B95CB
+ 7: A0049FCA856A14, A0257289C6BBF278
+ 8: 2814B0C1358440E0, C4B0A2354925E887
+ 9: BF4F062B52C1E489CF, B56442A3CA57A041
+ 10: 63DF433956831B8780FC, ADF9ED0B46DCA19E
+ 11: C317FD079817F50E0E8A16, 2EA0EC993FC603AE
+ 12: 2BD12FDDD81EB11660346D2A, FBC6F69125BBA88D
+ 13: 85D356536FE2843C6BBE60EDBC, BB2FEFD04F230E79
+ 14: 22493009DB01B4746F4927A8C4FB, 64CC08471D93C9AC
+ 15: C0F3C0DB08DC93FBA725D1E02DE084, 77B762213DDCCFFE
+ 16: 568B66D3112556BD98FF9339E9C002E5, C8355F508219FE0C
+
+EAX-rc5 (8 byte key)
+ 0: , 169C7954341EF44D
+ 1: 22, DABFDA9A0B0BA067
+ 2: 2E54, 6A3D6D9AA5877C5A
+ 3: 2A6ECF, 2A34A3AF5DE8919E
+ 4: 9CC5F84F, D3F673EDAF75E3B5
+ 5: FF5611756C, CC647FAAC8D49BF1
+ 6: 74C939BEB31C, C335999CCFE8F5FA
+ 7: 7976B6F7709B5F, 2A7969C5FD063A88
+ 8: 421EEC5022276174, 2C9BFB1EAC3C54A2
+ 9: 6A4761CD266B1C0ECB, 3EA3CCEBC85FAC4E
+ 10: 7C09201098E764239A2E, 8043ABA9BF4D5AEE
+ 11: 8CE26277562F646DE33C88, D72AED48895E3B40
+ 12: 52150F44D37D121560DA87F6, 58E865E22B485906
+ 13: BA0A73B45F93ECFBFC3AB3D8D0, 683D52FA47FB1A52
+ 14: 96546CBE01054AD24CC95DB54724, D80D0D530E5D1DDE
+ 15: 61E654BB18CD26FC36C09F874DC2C7, C65884CB9D9FEC1E
+ 16: 1D77B8BF02CDEAB4A707C07628826D5B, F18D1730C3D64701
+
+EAX-rc6 (16 byte key)
+ 0: , 1DF8B0B92A3F0C951C425AF4830E63FD
+ 1: 1A, 8A2959EBBE90180999994DEB7036DB85
+ 2: 435D, 7EF00CB57DB7B4155DB530D75CE6B025
+ 3: 08A6CF, 2ED6AF0F2D5BAB05F623D389480A01F2
+ 4: A86E54D3, FC69547C8BD922A5BF2F7B26C4D20F98
+ 5: ED0822E439, 0007A3C6DEFC6C912C0E5B853B520368
+ 6: 7BEFC7FD4054, D32C43A4D1086D57C5BCFAEE04EBC600
+ 7: 5235E58E79287C, A27E9C781327C0FC7C55410EB0C828A9
+ 8: CEB5EE99BE521F4D, 547F46383987F2A3582A81A3BCF9B280
+ 9: 0358B063D5F99C3770, C0A73730512CDA6AD49599775D59EDA1
+ 10: 434B9AEE07DFADD0A332, 499BD88881E558E09A8E822BE27D2496
+ 11: D47849E650F350BB622D74, 638E37A84E7FAAF8F5D77F1B061773DC
+ 12: 814592F568284085E79A024B, 9EB1405E8422FE50BC0D88D837A2C650
+ 13: 6F2B55EC91B591082053AF692E, C48F91EF01AA43A1EE3B36D233DDD48B
+ 14: 506CBDD2901838EE2F178B6953DA, 03778957F536509BFCA577B23A18F726
+ 15: 446EE435D3D1848B51BB8C5F7BE4A1, 1129EAEAADE534940546D43242A4C839
+ 16: FB9D2B150C42465B1685D8F069CC06DB, 41E2940F5DC63CB4E2FBEC25ED8A31E6
+ 17: 9684F683260107BE8FEBBEE1D3EEDAA7BD, BAE7C116F7FF96631F4ACEE95C65CEF3
+ 18: 5082B1FE48CD3AB58F63C2DCFDD4069AC736, 19AC7B8EE315CBB7131A283851B32266
+ 19: 8C72AE495B6F003A3C784D144E84E88885F78E, FA4CEC023740A8D670E351FBCF62C1CB
+ 20: 815D6361C7AE34C9D796ADF9C71ABC46AEF88BC9, 9A1F7288C61A6623B9A82748137ED7CC
+ 21: 904A853E2E96BD2B85AAB3F5DFB900E9B3642EE667, 9AA90DBDD461CAD20495DCFBCB513DD2
+ 22: 79D738A462F727B3D3C529ED999B6FDCCD991D1C5A4D, BF0987BEDDE650D73CAE7D380FED3431
+ 23: B2DEFDB7D503A84E83155A04B8DE8C8DBB68C2FC475007, B7CE900CF43CD518024123C76F6DA328
+ 24: 9E723E15439E12F6C46DF8A309AE1E97B6FD18436259CFB0, DF8B6E1E23512CC4CF5FF531A1908F69
+ 25: A7F0AD03CEBCC9202718AA164886E1026975306A664C5AC7A9, 4A771BF8B9A4325705C85E5499FD98E9
+ 26: A53A92AD1C6835F28E04EF591E783D36F3D76E489B31B87BEB7A, AA263B52A6E6A043DE4D7029D4DC73F5
+ 27: 79BE3C38291A7F77E932C8A9DEAC08DE6442EA9B3895B101A14E7B, 33B84DE06342E675E019CD0237292ED0
+ 28: FA108123C5A69571CFDFE8C3D00535121FDE3096DDC0D700F8F26A5A, 764025D7CA1A3F2C54D28956423B0C77
+ 29: 36EC2D67FD977BD2B73DB6D8EB756B3EADA13690E1B6DFC12A4781B34B, 4BC6B38DE3B02283D92F4DF19A5C48C5
+ 30: 96D3243C945905C9732B5927E46F00886D511463B38C86002FC26B65AB8C, 5B5511CDEC35687AB8425AB22D58B4F1
+ 31: 9CF83B87BEA3374AF7722E999863E3DABB858B0383383EAC7757F5B80FD44B, 1E0CBC961940FDA93B73A92DACFD67F3
+ 32: CE3BC3C9FA5EF4AFE5272B3EDD24B1B003FED2C2E501528CFF44D3FABFF52CB4, DC94FDDC78AAB2B7CAA1E1EF149AC355
+
+EAX-safer+ (16 byte key)
+ 0: , B120C7B37450C46189712E4DFD1F0C44
+ 1: CA, 82BA1869C5FF1EF2A4F6ADC1E7DC1F1D
+ 2: DD20, 6BD5601B16C9943A84AC1F99A176E6D1
+ 3: C1C09F, 0911DC63AA414C004E2BD825BECDC93B
+ 4: 27E43F59, BD858F084B082F76814DC385E1FB20D1
+ 5: 2A9A92F246, 5ADC4A32491934AC0BD00FCE686B26F1
+ 6: 52C78C0CD6F4, F35886F46C03EDCA10B3D01CF07B1E0A
+ 7: 23E0D3CED3795F, FE33D96FC98B78A30C0A412C60E93992
+ 8: CD3FC9961559F239, 9982364A61609FC41068260267231EE9
+ 9: 6EA46CB7AD7505C1BC, BB15053EF0F78B9091B3064118F3E9BF
+ 10: 05D9BA230A56CCA0703A, 1338E68E3DC992B6EB2685C668E75869
+ 11: 7AAD6049DFDCA6771AE42B, 35267E431051E1812495615324C4CBE6
+ 12: 8695091532B83B23C296F620, 7B2EEA861E9A91E6B6A911E10FC3FDD1
+ 13: D909DA4BC7372ACAEA78E6A0EE, EA6C1CD16180DF0B07F4E204A4B4FACB
+ 14: 7DEC8443600D0563AEFE87A2064F, DA454728069B3B409889664783588189
+ 15: C042FE656742CD2FE5D9C212D18C6C, 5929E4AECC2CA047BAE948E7023FE4D0
+ 16: 0B84D3CF59EEF7319633F4A397D47CF8, 31F892FFDB7535DF5D9143456E404163
+ 17: 8C9E57AAFA7969B142742B63AB73286600, C418231C44F96660DDBA8C26B3BB3681
+ 18: E9EED66D370A3A6A39C7E0E570D96F807EAC, A4AFE8D1D3C31B956A3BDBD043E7A665
+ 19: 1A5D47992DA5597D1449B4C8DD47B7404C7657, F3ECEE5182014FC3365FDBC4C33CC06A
+ 20: E7C7945FD1AFD3F5DCE666D8A5A2E8A3C11A7A5F, 86D78B2FBA7597B8806BED505B52BDF6
+ 21: 9E2165B47B29CBC4ACD50660E011D691F061209969, E9B1E860BD02085177E1A94E1EE6F3F0
+ 22: 48EA2945C8DD3FE09407BAC8973A861DB15B788C8FFD, 502926712EDB1B3DD13806052C6C75D7
+ 23: F37D46B35B60819EA52B00457D79155C04B55972D0DFA9, BB2B7D210BF0570F422640BF81F39B9E
+ 24: 12E85C0C78227205CC682360C79E35BF58EC6551CF8FE2D0, 042990D7A58D458C570A15DD375DB4E7
+ 25: 4F6C15109DE980DD14A7F4C27F48671E4787C53A564232F427, B097A5990D8067DD89C21473150C070F
+ 26: AAC472E49DB101B564A8A01E2C80C0C6AE9065D332C2DE79FAB6, ACDD587A7DB86542E195DF73AF1C1CBC
+ 27: B9912CE18019C31692A1F7E11D9CCB20297ACCB9DC62C47C01D2C2, B0ACBF028CA5B15E0035D2EB8CA916BE
+ 28: B4F2B1FE14A1ECDC9C8EA1A0120395E6ED1E69D3FC85DD0F3F90F350, 9A561EBC769369B95B9CB74FC6AC27D3
+ 29: 3FE397C8AD02689B7437A37861F0907AF1F6014A293B46419348771C5A, 6B7BEB9BD5018FECD71BE5081C7C2544
+ 30: 5019089142199F7207E1B7731B8B247A18A685B231499DF12A73F5D67D37, 307E93446777005BA1B088F178A0DB6E
+ 31: EAE8F9F02F8DB3D70B78B08CFB0949D99F1A86C958A8E3823736BCEAB86BE1, 6C94F48591C18BF9C450515B73379973
+ 32: B9C795F7A87305B4AD36DBA10B3B1C70B329D29E49C8C6A932D96A74334AEE4A, D18E6E233FEFD6E5C7148BDC1504299C
+
+EAX-twofish (16 byte key)
+ 0: , DB0C02CB069E3773296D3BD4A87A381B
+ 1: 99, 7D21D19E9C440F68E99F1F2EA2668694
+ 2: 0696, EA590EC417C88E23FD23917F9ECFB0C6
+ 3: B9B082, 82D4C9B68DDB02C906496413E13A2D68
+ 4: D6B29D74, 5BCE5CA4F662E883BF7FCAAE5FB2CE01
+ 5: A59C9CB009, CBFB04226D1029A7EC9D64A48A6729BE
+ 6: F4924FE3E355, 3D85B3900DECA0528C815F1447A1F209
+ 7: 679C88D52FB519, 931C7A863C3701D8015FDBD8696C6C30
+ 8: 26DA41C0D115375E, 7627E23E791A4DCB0FA5ED71B1ED2288
+ 9: 8FEC6EB7016AD2B178, F65ED0286A724F0CB2EA317D5022B0D8
+ 10: B5F22415B1334133C531, 87C4F3A8991BBB85984BC4D3305A5CF1
+ 11: 23E1D0ED2E820AFE7DA2FE, 100499F1093FAB2ECF73B643594E98E3
+ 12: 79519ABA91F46B8DAD6D5335, FBDCD1FCDB20AB99135F28A714C6992F
+ 13: 5968D0B4198A0AAD3D0395018F, 781F22E2DA98F83398FCF911B2010057
+ 14: 4E55B14432B601E3EF2EF567CB15, 8BF6E53D7657E56EA3DA1BFD9C9EC06E
+ 15: 6ED89651CE19B3DD1EE5C8780B5015, 131CFD657D32D4E1B35140ADDCA0E13A
+ 16: 2295A968B4D072D12757756247554850, F35FAC95C2AA4155450EAAA6E2E789B5
+ 17: F9B2AA2AA502EA79BBA0C5EAD932B8E1EE, 0ED81AA40B9BF39A9AAEDDDB7A04BEA6
+ 18: 385055F1C1C26C0472A504B4CD225DCA55FE, 24831680B56368231AC54227D737F582
+ 19: 771529585C741A3F8B1C973709892F255A99EE, 2A132B4BF96FD5109DB04459103F5E84
+ 20: E7A2197D9FAA8AB8B303B5EC71AE34AD5EC5DD66, CCAB6518371EC8E0A9E9EE4F7CA5878B
+ 21: 279E54F755EAC6B57375B9EC4406E43DB3139D740C, 7B6F26F2C0ECC9F2DF4EDD7513E6E0B7
+ 22: 27816AA94CBA2BF98E49E595AF5B3FAD12BF1D6F1AC6, D04876C5492D275F15C834E3CF794F0E
+ 23: B5658DC148855F68B282211D879F688F3C142FE555CF81, 4539CDA8A65DB9047AAD76B421B81120
+ 24: 72F0BD4F939C2C9B4FA734DCB0AE4FB9BD342BC8459ED2FE, CEA8469BC0457EBF3418C1114288C904
+ 25: 70568245E6E6BD5D11AD0C74030D7AE08BA05057DEA0FBF4AD, 71554FDE6B87477A51EE4499D78783D2
+ 26: 8702D35BE07D7ADF70684046CC6C72FBBBF821E0BBCCBC973601, 33CC6FBFDA15E306919E0C3BB2E22BB6
+ 27: 0BA23F4A6174165D4A8BA80B7C875340B0F8B2A6967D34E106BC22, 00E6679496714236EECEC84B9AF3072E
+ 28: B9E25ABA84C6BD95B5149E7616FE2E1D6FAACEAAD77A636C60279176, 8D8AD0B9D4C709E1DA370EE01611482A
+ 29: 74759711F6D542581F9F83498FB616638D092732BA07109BF4B5BE045C, 71A40DC777BD09F75362F7B20E0B7576
+ 30: ADBF7E98926484BA2C7F6CD7CD9734FC19265F68AF3BFCAEB025F6296E37, 8DF15B5F69B67F7DABE44E3666B55047
+ 31: 2DC26D449379997D110309B2A0DC2760FCE8CADB4B14ED580F86C70F69C9BA, EFCB60EB2B25737E256BC76700B198EF
+ 32: 2B1890EB9FC0B8293E45D42D2126F4072754AA54E220C853C5F20FBA86BE0795, 1A1B15BBC287372FB9AF035FB124B6A1
+
+EAX-safer-k64 (8 byte key)
+ 0: , 9065118C8F6F7842
+ 1: A1, 1926B3F5112C33BA
+ 2: 2E9A, 5FA6078A0AA7B7C8
+ 3: 56FCE2, 984E385F9441FEC8
+ 4: C33ACE8A, 24AC1CBBCCD0D00A
+ 5: 24307E196B, DD2D52EFCA571B68
+ 6: 31471EAA5155, EB41C2B36FAAA774
+ 7: 03D397F6CFFF62, 7DFBC8485C8B169B
+ 8: 8FA39E282C21B5B2, 2C7EC769966B36D7
+ 9: FEA5402D9A8BE34946, A058E165B5FFB556
+ 10: 6CDEF76554CA845193F0, FED516001FFE039A
+ 11: DC50D19E98463543D94820, 8F9CCF32394498A1
+ 12: 42D8DC34F1974FB4EB2535D7, 77F648526BCBB5AF
+ 13: B75F1299EF6211A6318F6A8EAA, C5086AEA1BE7640B
+ 14: 1E28D68373330829DD1FFC5D083E, 33EDA06A7B5929A2
+ 15: 85529CF87C4706751B0D47CC89CEA6, D031905D6141CBED
+ 16: FE5CB61BAF93B30ED3C296EE85F51864, CC484888F0ABD922
+
+EAX-safer-sk64 (8 byte key)
+ 0: , 5254AB3079CDCB78
+ 1: 75, 798DCF14FEF8F4D1
+ 2: 0300, D5FCA75DAC97849C
+ 3: 520F98, 10E357957CE20898
+ 4: 80E2764D, 5C7F46656C6A46EA
+ 5: C48960CDAA, 3CCF44BD41F01CA8
+ 6: E0E60BD9AA2C, EBB493983FCEE79D
+ 7: D13D8804906A1B, 6EDDCA919978F0B6
+ 8: B7AE14C37A343BFB, 2369E38A9B686747
+ 9: 5DE326BBCC7D0D35E9, 041E5EE8568E941C
+ 10: 13494F5B0635BA3D6E53, EAEEA8AFA55141DD
+ 11: A9BB35B14C831FDA0D83F7, 4002A696F1363987
+ 12: E242043A1C355409819FABFC, 63A085B8886C5FDC
+ 13: 204598B889272C6FE694BDBB4D, 194A1530138EFECE
+ 14: EE3F39E0823A82615679C664DEBF, 1EFF8134C8BEFB3A
+ 15: 8579D87FD3B5E2780BC229665F1D1B, A832CD3E1C1C2289
+ 16: 74D7290D72DA67C4A9EAD434AE3A0A85, 96BAA615A5253CB5
+
+EAX-safer-k128 (16 byte key)
+ 0: , 7E32E3F943777EE7
+ 1: D1, BA00336F561731A7
+ 2: F6D7, 8E3862846CD1F482
+ 3: 5323B5, BD1B8C27B061969B
+ 4: A3EC3416, 170BBB9CE17D1D62
+ 5: 0C74D66716, 7BD024B890C5CE01
+ 6: 6158A630EB37, B5C5BD0652ACB712
+ 7: 17F2D0E019947D, F9FF81E2638EC21C
+ 8: 68E135CC154509C8, AA9EAEF8426886AA
+ 9: EDB1ABE0B486749C21, 355C99E4651C0400
+ 10: DB0C30E9367A72E8F5B2, 631B5671B8A1DB9A
+ 11: D4E5453D9A4C9DB5170FCE, 75A2DF0042E14D82
+ 12: 3F429CC9A550CBDA44107AA7, 2C2977EA13FEBD45
+ 13: A7CA22A97C2361171B415E7083, BFE81185F31727A8
+ 14: 170F79D8B0E3F77299C44208C5B1, D5ED9F9459DF9C22
+ 15: 2E24312D2AE5D5F09D5410900A4BBA, 2FC865CA96EA5A7E
+ 16: 8F3C49A316BA27067FF2C6D99EC8C846, 9D840F40CDB62E4B
+
+EAX-safer-sk128 (16 byte key)
+ 0: , 22D90A75BBA5F298
+ 1: 3F, 98C31AB2DE61DE82
+ 2: 584D, F4701D4A1A09928C
+ 3: B9DEAD, 6E221A98505153DA
+ 4: 06D4A6EB, 0E57C51B96BA13B6
+ 5: 7B58B441CA, E28CCF271F5D0A29
+ 6: 7950E0D1EC24, 2ACDDE6E38180C07
+ 7: 65A4F4E098D7C6, 7DC1C9E9602BACF2
+ 8: FEBE4E72BAA0848F, C4607EA3F138BAD9
+ 9: 9B7BD6D6D655985AA3, 8B2C58A9530EA6AC
+ 10: 60C92F925D1478470203, 51E6F5F6DC996F84
+ 11: 7B40769370E651F64AA654, 74F1F8A8D3F4B9AF
+ 12: 7215832C2FB9C54DF7A9C686, 9BF9AEF14F9151D1
+ 13: AD0F9C79008572AB8AE2466EFF, F375D0583D921B69
+ 14: C05076E2C330A0D25D7CEC80597F, 843C12F84B00A8E0
+ 15: D18F0563AB0278140B0CD9A9B07B34, 262B1688E16A171E
+ 16: 650747091F5C532EE37D2D78EE1EC605, 1BAC36144F9A0E8D
+
+EAX-rc2 (8 byte key)
+ 0: , D6CC8632EEE0F46B
+ 1: 4C, EA19572CB8970CB4
+ 2: 5537, 3EDD3253F6D0C1A8
+ 3: 206FA6, 20FA88F03F240D31
+ 4: 17EE8B40, 702E8194F1FCBFDE
+ 5: 2A89287136, 31C5534786E15FB3
+ 6: 3A6AEDC7066B, 3C663A4081E1D243
+ 7: 8BC5203947A644, 6AAC806C92BFBD6E
+ 8: 2E0274BBE14D21A3, CEB0E0CB73C3664C
+ 9: 9C4B292B0CF17E3A29, F23CD535559023EC
+ 10: 8E322734308F85662877, 46363D7EFC322821
+ 11: C413C405767FF5F98E3667, E7BA35D8F3678E7E
+ 12: D77806B7A218098B1569EADC, BA67C306E5C0181B
+ 13: 4BE5EF74F9E9799A4D636FEA9F, 4C511C44ADBA4030
+ 14: 7E19969170C2C8D8AEBA8C7FBC2C, 54CC6D466A2DF6DA
+ 15: 2EF1CEDC1DD3403CF440FC5561BE33, 61C6FB277E93701F
+ 16: DE052719153EBACE9D7B19F52AC4282F, 4AC2A96F2FA8634C
+
+EAX-des (8 byte key)
+ 0: , 44048B7F240B6F5F
+ 1: 0A, 37009B7D4E09953A
+ 2: 03BA, BFD2FD7758961728
+ 3: 37EE10, 16A6AF96DE888A19
+ 4: 07F44290, 100CA84AA0EDAA1D
+ 5: 389EF0023B, 9614FB800A533268
+ 6: 3F4DBA8AA01C, EFA6B55B7ED5E40F
+ 7: 8C7B837896EAE7, C113CE8F664CE3D4
+ 8: 7011D993D8EDB0C7, B4C370A919F60497
+ 9: 0DEB30A31351B13D7B, 00ABC82DC5F3A1AF
+ 10: 8D3897B2CBE323D6EE1C, 7A2D15627CA1441B
+ 11: DBC002C817DEBFB419F94B, D8EB87F86D6ACDEF
+ 12: 17048E2976FA85AA849E9A80, 229FCD1C9D1E3B9C
+ 13: 30B989EF646544885A478AC198, C1B7EB4F799105C8
+ 14: 5C2E12A7F118A08D6FD585F9C839, C358679FEE6FE7D7
+ 15: 8D1A1E888BBB8648E638C4E74E11B8, 685E006C441448B8
+ 16: 93AE906B8BE4EAC8ED6D8F48F04A7AFF, 71DD7AF752FE28FB
+
+EAX-3des (24 byte key)
+ 0: , 8914311BB990B725
+ 1: D8, 2094EDC5D03E54B1
+ 2: FEE5, 781CFB0EBE3895CA
+ 3: DECF5E, 59918E8A5C4B459B
+ 4: BD583AAD, 2013BEEBEEA795A1
+ 5: 2BC01C6C78, 0B1134DBBEAB5D3F
+ 6: 4D5EAF01A895, AB4D17516ECBA50A
+ 7: AF229F90614480, D3113C0A9D133CD4
+ 8: BCA6F375DF4568E0, 8E9EAEC8E77786BC
+ 9: 575F34219E6DD8DB4C, B40C75139E5D1860
+ 10: A199B8AC433B615EC96F, 774AF803698ADE3D
+ 11: 718A2975DD9A872A68AE10, 3B9460F849CBA7FB
+ 12: AB38E148180F6E2FFBB96F91, E3EE3B8FC50DADBC
+ 13: EB10E0233507459D4A6C29EE80, 8D90B46BB1EAB27E
+ 14: EB48559C320DFB056C37458E19B5, 9315F0C4AF8500EB
+ 15: 9E8C73EADA105749B5D8D97392EDC3, 2E749EE66C1E6A16
+ 16: 600FA4149AF252C87B828C780AEFF8BC, 33D7D11DCDC19936
+
+EAX-cast5 (8 byte key)
+ 0: , 382FB8F7E9F69FDC
+ 1: 99, 20DA959849B3F7AB
+ 2: C54B, D05547C6AFA3484A
+ 3: 579836, AAA92B2321FC50C5
+ 4: FEB7AE55, 639EDF01C4FB965D
+ 5: EA8A6023FA, 01274B3ED5CE102C
+ 6: B7C4E995121F, 712BFE27CAFF6DDE
+ 7: F44236660B0004, FAC51D1DF8EC7093
+ 8: 01CD7E3D0BF29E8A, 049C47A45D868D0B
+ 9: DAB170493DFD6E0365, 6F3AEDD9A3ECF4FD
+ 10: 82C9EEC4803D9CD11FA8, 32683C0A9128C6EA
+ 11: 324AC59E87B244ECE0F32F, F6B095AAB49353CF
+ 12: DBDDAB11D02C9CA5843C406E, EA728FC46DDD3B04
+ 13: D67376C2A4AD92E7DD80E39303, CAF72B7E7C237EB3
+ 14: F2B9BBEF08036C2982C6DDD06918, 70A29D780C22752C
+ 15: 96E3D9141F8EBF520540C2BC9A9C23, CEFC86A1CD48203D
+ 16: 70CABBA983179106AE7FCD5F1F31D5C3, BF7F9168F4F82F56
+
+EAX-noekeon (16 byte key)
+ 0: , 556805EEA595CFB9A30FAD196103D7FD
+ 1: F5, 0A7DAEDFB656526CEF4DDBA8087A227A
+ 2: 7B8C, 249895D79962D5B4D18FE07366281B72
+ 3: ACFF15, DCC489D24832EB106F576AE6B6EB957A
+ 4: 08ADE7DB, 0D3215999E9960EDAB29B78744C7F139
+ 5: 66139213F6, 505E1E7141D043E903C26EE0959EEECD
+ 6: 078B79F880A8, 35B7EB326A55E50332866EEDB682EC20
+ 7: 2809E34D9667D4, FFDEC555F68524A09A6ABACA372077D9
+ 8: 93D267DE1EC635D3, 4FF3561990A56E4B374618722EF850FF
+ 9: F377A4D93FF32F4A51, 91D4070423A90FC54D305169C03F49ED
+ 10: 6244B717E082993EB7A1, 2E3A8A354AFA9473667ED7FDD46BE9FC
+ 11: E917559625D25E6E5F2EDA, 19295C37A70314CC9A1D11FDE8D23C92
+ 12: 1E6DF2EE112A893AB14DFA92, 12C4A89D4CD65F8116A03A135AFD3701
+ 13: 47B18CD762E011770E203CF605, 434909A97E118B20D3AEDC79AFE33A9E
+ 14: 72D9A1A7DA6F33D5E0B927F9F32C, 779C23714FCAA2B2321EC7FB5B03E222
+ 15: DA8B830FFCB3DB274807F780D33240, EDC2F1C8A401F328A53392597730B007
+ 16: B53DD2BB840AD933D36A7B5FFDCCFBBB, 4EC0E6D1F916BF633869239B672B37A1
+ 17: 42936BB9A936C30408660855F4F47F3314, F0DAA6DDA15585E1697ABBB4790B15B5
+ 18: 00372E47F5BA016F1B2A1E680B76AB02052A, CDBF3D241BF7FF96D3DFBEDDB872E901
+ 19: 8AA236B0C8BEF6F67A97C2DF90628F6E5838FF, 731DCD61F7F26004C03519F9500EA824
+ 20: 55338647812FC9D86CBDDCED7120268A4D43F8BA, 0E61B3C835CAD95FD49FEF002C014E72
+ 21: 435820B28E52154B47A04D5E635D8FE37FA47FC985, F6A96DCE4917E8D7C610923627E80970
+ 22: 0D30C15B6FEB4A48B14DD15D41A4B25D442AA677B25C, 28E15CCB74AE992C68BDDC8D87802050
+ 23: D9D701F9AD6B0E13D2CDDA15A5194E7CE8BD2C02137391, 2DB9A15884E9C996C3D6B5BDA44B9598
+ 24: E2390AC5CE10CCFBC72106A52C7F180CB477E3C193CBACA8, 22D3F7DCD6947EA4E78DF57A8E1A9A59
+ 25: ADEFB7D9500658D34996AF6BE6336CD78891064EA1DB8E9785, F239D67D039A15C620A7CD4BE4796B3F
+ 26: 89964C90ABF54A6DF9F13C3681E70C702D80A17BE79F8160F30E, 6336F729ECE1ED7368669D75B7E2DCBA
+ 27: 576B2813CECDA4F905BD5D58349EF070FF41B7EB6BB2B01B061B0B, 125324CBF2ACF1011A44A99A11EC8AFC
+ 28: 430B957481748519A60494F0B5F698F34B1A8235B00AC0D1F0A4442E, 1E80A7FCEBBB8E1E12D6831906154485
+ 29: E781BFE5FCDE0BFC056CC86C4A0B9DD3B815BE8CA678204CF47289B5B5, 190D5AAA9EC1CB4CC86FACE53BF1201B
+ 30: 78BFAC07A9B7B2AE9329BF9F9BF18A1A49DD9587001EFCA00E9AD9752764, 4FB5ECBEEB0995C150EBC66508FA19C1
+ 31: 7D6C20694109DE21F7955855A8FF832347518DD496C2A114DF142C68ACDEAA, B25D4BB34056DC091A7A3950D46C32EC
+ 32: 3E1E4395DEC1AFEA9212B95F37E679B6E2D14DF23C5DE49018C2C8038CC4AD45, 9A6DE7BD41A21918AD504490EF4E581D
+
+EAX-skipjack (10 byte key)
+ 0: , 85F74B6AFFB10ACD
+ 1: 3F, 604DF8BDD98A0B3F
+ 2: EA87, 792374FE07588BF9
+ 3: 0169CA, 489AB8AF69DA3306
+ 4: A7AC3EB1, 428DAF508E24B583
+ 5: AA9028D5B3, C0A44EDA71FB2C86
+ 6: DA97BA88A061, DA2EC34077F42585
+ 7: 7E25FAA41CEBC8, 36D4987551E06D5B
+ 8: F662DA6C9001CBFE, B7DEF76680C316A9
+ 9: 6D3F73EC716E1DA897, 5F0F83BAE4D3513B
+ 10: 2A300F585BEE9C889743, F4756C24DEB72A9C
+ 11: 80518B010DD77C82D19106, 50FF5CAA365F4A70
+ 12: 6E579A2173C861B6F37B4CD3, 81E3E5ABBA8F0292
+ 13: 5B04829880A72C38871C7021F3, 6B26F463708A3294
+ 14: 934177878E9A9A9FB4DEB3895922, EBC1C32F0A2A3E96
+ 15: 07AF486D1C458AAB2DBF13C3243FAD, 87288E41A9E64089
+ 16: 84059283DF9A2A8563E7AF69235F26DF, 351652A0DBCE9D6E
+
+EAX-anubis (16 byte key)
+ 0: , 8E20F19D9BA22ABA09FB86FDE6B9EF38
+ 1: 3B, F4201E546A9160F989191942EC8FD1D3
+ 2: 9F38, 4E3CEAE3E1CB954E021A10E814B71732
+ 3: 4F4769, 3E8F35A6A5B11200E9F1AA38590066CD
+ 4: AB41F5FC, EC4C97A8892AAF5433106D4AC8A49843
+ 5: 414F95D61B, BF831E34D1E3FECB973A8C730ECA2E6D
+ 6: 4798322F06D1, 005BBC30BFEDBE6463536C4F80D1A071
+ 7: F256B6CD1BF4F5, 468A28F0661884B846B191B530C8D064
+ 8: 90906F27A633ADDE, 6D9200A37A7F6A456CB103673184C2E5
+ 9: 16CD3C17C9B4EAB135, 6D716E23D7B35109F55B036EDFA7742E
+ 10: 7AD1C22F1F06298DFB25, B076990F8193543C8F3185D3792BCE56
+ 11: 0476F2ABCD057FE6FEE39D, BB2876DB18C00038FADBBD9B264ACC3C
+ 12: B69EDE336407DBC2EE735857, AB63E5906116A8BE22C52B5DA31B1839
+ 13: C3864C1354065A56470669E602, C72BFD3A0BC73BFF051C9AB2F0DFED93
+ 14: 296D8F183A59020D33890420DD7B, C9D90B9EB42C32EDCF6223587D1598A6
+ 15: 256ED8E9D982616680559979BDF2E9, 179FE4E7BA7E966050D35900317E9916
+ 16: D4ED8F30FF9C0470D75B3B16750A3AE4, 5D50F05BB270A292DFF9F67A3BA84675
+ 17: 40CDEB6388274143CA3C4F6020BD9A4875, B27C7DFB1BFBB3FCCEE0171852C7924E
+ 18: 54EF262EC1801D505C7629D038654EBA0594, 9D2060FCD0A2C577511C7752ADE60BBE
+ 19: F39EE54A37F16DD38B624D7AB8F0D9CBD4B981, BC056C7D2C09D813703CDD63C1C69F44
+ 20: F4E7AD474FCA153ABD670E43081ED09EB2C4CC1A, F244BD4D630272F0D98FCA04226C04F1
+ 21: 039ECC36A0A16273E7246CA1FF19D213AC87B53F29, 3056DB6916C925DF220B6C9980EE141A
+ 22: 7DE1DCDEF01447CA2FE83375A48DD84E4A7CB7C01992, 79AFEA4816EAF8DAC8A5E93960F1594F
+ 23: A886C4B914BF0983003272F226F9B2197EF2DC05ACDDE0, B59D85A0FDA5FA4422F7203C055B97A9
+ 24: 00B3E1E91448E250AAFB695C0643A6577AB453EFECFABF53, 4A7EFF1CBC1AB535122A017203616D85
+ 25: 85E972E774D66D0531E40B8FE9E264A77B50FA883AB0943080, B18E164BF89B7E7AB0DC256DFEC7C72F
+ 26: 004849E39334969B392CB0CF3FDEFB3D792DCBBC15F8328C7EDC, 3C51295711F5F878DE8F0B2B5A26A227
+ 27: A0BAD6C2264AB1578993BA49E59D4598822FFED20A57D88F756FF1, 2EB9D525697A419A10DB2A84AEEA5FBC
+ 28: C34DD806EAB5AD823D78BCA78A7709A705FC94ECC521A367D76C9588, 3C57580C7903039D645C06DBAF07B477
+ 29: C447EC77512938CF7862388C32AF22ACE6B5E4CBAA998BE4F5CBC4D215, 43425D09B7ACFD90371C08953946A955
+ 30: 2C16993AAE624CBA4CDAF34FE3D368559E6BE548292B281439866375013B, 3B7360C3FA8FB1C15D19F567153CB46C
+ 31: 538E5DFAF14854A786851E4165F2E01CDDA963E318FCE4FB58E31A6B5CFC33, 2F8EA13B7A6873FE556CA535ABA0968B
+ 32: 5E29CDB7D9695A110043E9C260104BDF020A3A2A139D4112E918AB584BDD7EDA, 9133213AA7BCF062D2BD37F866683D3F
+
+EAX-khazad (16 byte key)
+ 0: , 75968E54452F6781
+ 1: 95, ADAF5949F09B5A22
+ 2: 6B8F, A06B201947424A11
+ 3: 5BE668, 3251416625DF347A
+ 4: 5A92E82B, 33E25772427D9786
+ 5: 62F9F2ABCC, DE714F5F5D17D6D0
+ 6: 0E3CD825BD8D, A7991C8CB8975ED9
+ 7: 4AD0D999503AAD, 53A827D7886F7227
+ 8: BB08E6FAED1DAEE8, 91A118749B7AB9F3
+ 9: 16E30CB12E20D18495, F8F8B8C1280158F9
+ 10: 616DBCC6346959D89E4A, 506BF35A70297D53
+ 11: F86B022D4B28FDB1F0B7D3, EA42220C805FD759
+ 12: 9B8A3D9CDBADD9BBCCCD2B28, BB478D3CE9A229C9
+ 13: CDC4AB4EF2D5B46E87827241F0, 658EDB9497A91823
+ 14: 1A113D96B21B4AEBDB13E34C381A, 63AD0C4084AC84B0
+ 15: 14DA751E5AF7E01F35B3CE74EE1ACF, 3C76AB64E1724DCE
+ 16: A13BBC7E408D2C550634CBC64690B8FE, 3D4BBC0C76536730
+
diff --git a/doc/examples/encrypt.cpp b/doc/examples/encrypt.cpp
index e5245cd5d..959461b63 100644
--- a/doc/examples/encrypt.cpp
+++ b/doc/examples/encrypt.cpp
@@ -26,10 +26,8 @@ This file is in the public domain
#include <botan/botan.h>
-#if defined(BOTAN_EXT_COMPRESSOR_ZLIB)
+#if defined(BOTAN_HAS_COMPRESSOR_ZLIB)
#include <botan/zlib.h>
-#else
- #error "You didn't compile the zlib module into Botan"
#endif
using namespace Botan;
@@ -141,7 +139,10 @@ int main(int argc, char* argv[])
new Chain(new MAC_Filter("HMAC(SHA-1)", mac_key),
new Base64_Encoder
),
- new Chain(new Zlib_Compression,
+ new Chain(
+#ifdef BOTAN_HAS_COMPRESSOR_ZLIB
+ new Zlib_Compression,
+#endif
get_cipher(algo + "/CBC", bc_key, iv, ENCRYPTION),
new Base64_Encoder(true)
)
diff --git a/doc/examples/gtk/Makefile b/doc/examples/gtk/Makefile
new file mode 100644
index 000000000..10e069bb3
--- /dev/null
+++ b/doc/examples/gtk/Makefile
@@ -0,0 +1,18 @@
+
+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
new file mode 100644
index 000000000..dff547737
--- /dev/null
+++ b/doc/examples/gtk/dsa.cpp
@@ -0,0 +1,556 @@
+/*
+ This shows some of the details involved in a GUI application that uses
+ Botan. Actually most of the code is just dealing with GTK+, but it shows how
+ the password callback and pulse function stuff works. (See gtk_ui.cpp for the
+ acutal password callback code.)
+
+ The major points of interest (assuming what you care about is how to use
+ Botan from a GUI, and not looking at my terrible GTK code) are gtk_ui.cpp
+ and, in this file, GTK_Pulse, gen_key(), and get_key():
+
+ gtk_ui.cpp and get_key() show how to get a passphrase from a user for
+ decrypting (well, in theory, anything), but in this case, PKCS #8 private
+ keys. Which is coincidentally the only thing Botan currently uses UI
+ objects for, though that will probably change eventually. GTK_UI does
+ double duty, for getting passphrases for encryption as well (in
+ do_save_key).
+
+ gen_key() and GTK_Pulse show how to do an activity meter while doing a
+ long-term operation inside Botan. Since, typically, the only operations
+ which take a long time and can't be broken up into smaller parts are prime
+ generation/testing, that is currently where the pulse hooks are
+ called. It's certainly not the most general callback method in the world,
+ but it's general enough that it's usable without getting in the way too
+ much. The callbacks will eventually be extended to other parts of the
+ library (Pipe, maybe) where it's useful.
+
+ This program is in the public domain.
+*/
+#include <fstream>
+#include <iostream>
+#include <memory>
+
+#include <botan/botan.h>
+#include <botan/libstate.h>
+#include <botan/look_pk.h>
+#include <botan/filters.h>
+#include <botan/dsa.h>
+// we don't have a 'using namespace' here, so it's easy to grep for code that
+// is actually dealing with the library (rather than messing around with GTK).
+
+#include <gtk/gtk.h>
+#include "gtk_ui.h"
+
+/*************************************************
+* Pop up an message box *
+*************************************************/
+static void show_dialog(const std::string& about_message,
+ const std::string& dialog_name)
+ {
+ GtkDialogFlags flags =
+ (GtkDialogFlags)(GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL);
+
+ GtkWidget* dialog = gtk_dialog_new_with_buttons(dialog_name.c_str(),
+ NULL, flags,
+ GTK_STOCK_OK,
+ GTK_RESPONSE_NONE,
+ NULL);
+ GtkWidget* label = gtk_label_new(NULL);
+ gtk_label_set_markup(GTK_LABEL(label), about_message.c_str());
+ gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
+
+ g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
+ G_CALLBACK(gtk_widget_destroy),
+ GTK_OBJECT(dialog));
+
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
+ gtk_widget_show_all(dialog);
+ }
+
+/*************************************************
+* Pop up an About box *
+*************************************************/
+static void show_about()
+ {
+ const std::string about_message =
+ "<big>DSA Utility</big>\n"
+ "\n"
+ "A simple application showing how to use Botan within a GUI.\n"
+ "It lets you generate or load keys, and sign text files.\n"
+ "\n"
+ "Send comments/questions to <tt>[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, passphrase);
+ else
+ out_priv << Botan::PKCS8::PEM_encode(*key);
+
+ // for testing
+ //std::cout << X509::PEM_encode(*key);
+ }
+ }
+
+/*************************************************
+* Generate a signature for the text buffer *
+*************************************************/
+static void sign_buffer()
+ {
+ /* No key? Ignore request. */
+ if(key == 0)
+ return;
+
+ /* same format as the text-mode dsa_sign example */
+ Botan::Pipe pipe(new Botan::PK_Signer_Filter(
+ Botan::get_pk_signer(*key, "EMSA1(SHA-1)")
+ ),
+ new Botan::Base64_Encoder
+ );
+
+ /* It would probably be smart to do this a little bit at a time */
+ GtkTextIter start, end;
+ gtk_text_buffer_get_bounds(buffer, &start, &end);
+ gchar* bits = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
+ size_t length = strlen(bits);
+
+ pipe.start_msg();
+ pipe.write((unsigned char*)bits, length);
+ pipe.end_msg();
+
+ std::string sig = pipe.read_all_as_string();
+
+ zap_sig();
+
+ gint position = 0;
+ gtk_editable_insert_text(GTK_EDITABLE(sig_view), sig.c_str(), sig.length(),
+ &position);
+
+ g_free(bits);
+ }
+
+/*************************************************
+* GTK+ pulse callback *
+*************************************************/
+class GTK_Pulse : public Botan::Library_State::UI
+ {
+ public:
+ void pulse(Botan::Pulse_Type);
+ };
+
+void GTK_Pulse::pulse(Botan::Pulse_Type)
+ {
+ /* We need this to flush the updates, otherwise GTK+ will wait until we're
+ done with the computation before doing any updates (generally the right
+ thing, but not with a progress bar).
+ */
+
+ while(gtk_events_pending())
+ gtk_main_iteration();
+ }
+
+/*************************************************
+* Actual do the pulse (as a GTK+ timeout func) *
+*************************************************/
+static gboolean gtk_pulse_timeout(void* pbar)
+ {
+ GtkWidget* progress_bar = (GtkWidget*)pbar;
+ gtk_progress_bar_pulse(GTK_PROGRESS_BAR(progress_bar));
+ return TRUE; /* keep calling us */
+ }
+
+/*************************************************
+* Generate a new key *
+*************************************************/
+static void gen_key()
+ {
+ /* This gives a nice smooth progress bar, though we do use up quite a bit of
+ CPU for it. Keep in mind that if PULSE_INTERVAL is significantly less
+ than the average time between pulses from the library, the progress bar
+ will jerk around going slower or faster. Keep it at at least 50ms.
+ */
+ const double PROGRESS_PER_PULSE = .01; /* % of bar */
+ const guint32 PULSE_INTERVAL = 30; /* ms */
+
+ delete key;
+
+ GtkDialogFlags flags =
+ (GtkDialogFlags)(GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL);
+
+ GtkWidget* dialog =
+ gtk_dialog_new_with_buttons("Generating Key", NULL, flags, NULL);
+
+ GtkWidget* label = gtk_label_new(" Generating new key, please wait... \n");
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
+
+ GtkWidget* progress_bar = gtk_progress_bar_new();
+ gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(progress_bar),
+ PROGRESS_PER_PULSE);
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), progress_bar);
+
+ guint timer_id = gtk_timeout_add(PULSE_INTERVAL, gtk_pulse_timeout,
+ progress_bar);
+
+ gtk_widget_show_all(dialog);
+
+ while(gtk_events_pending())
+ gtk_main_iteration();
+
+ /* Register gtk_pulse so it will be called every so often when we embark
+ on our prime generation quest...
+ */
+ /* this just updates the GUI; the GTK+ timeout function actually updates
+ the progress bar. That's because the amount of time between pulses
+ from the library is rather irregular, so the progress bar looks jerky.
+ */
+ Botan::global_state().set_ui(new GTK_Pulse);
+
+ /* Not generally recommended, since it's slow and there's not much point.
+ However, *because* it's slow, we'll want to put up a progress bar or
+ something, and part of this whole thing is to show how to do that and get
+ the pulse functions to do the right thing.
+ */
+ Botan::DL_Group group(1024, Botan::DL_Group::DSA_Kosherizer);
+ key = new Botan::DSA_PrivateKey(group);
+
+ gtk_timeout_remove(timer_id);
+ Botan::global_state().set_ui(0); // unset the pulse function
+
+ gtk_widget_destroy(dialog);
+
+ do_save_key("Save New Key");
+
+ /* new key, any old sigs are no longer useful */
+ zap_sig();
+ }
+
+/*************************************************
+* Load up a key *
+*************************************************/
+static void get_key()
+ {
+ std::string fsname = get_filename("Select a DSA Key");
+
+ if(fsname != "")
+ {
+ try {
+ delete key;
+ key = 0;
+ zap_sig();
+
+ /*
+ A GTK_UI is a subclass of User_Interface that pops up a dialog that
+ asks the user for a passphrase. It actually works quite well,
+ though the fixed upper limit on the passphrase size is not
+ ideal. Feel free to use it as-is or modify it however you like
+ (gtk_ui.* is public domain).
+ */
+ GTK_UI ui;
+ Botan::PKCS8_PrivateKey* p8_key = Botan::PKCS8::load_key(fsname, ui);
+ key = dynamic_cast<Botan::DSA_PrivateKey*>(p8_key);
+ if(!key)
+ show_dialog("The key in " + fsname + " is not a DSA key",
+ "Failure");
+ }
+ catch(std::exception)
+ {
+ key = 0; // make sure it's not something random
+ show_dialog("Loading the key from " + fsname + " failed.", "Failure");
+ }
+ }
+ }
+
+static void really_sign_buffer()
+ {
+ /* No key? Ask the user for one. */
+ if(key == 0)
+ get_key();
+ sign_buffer();
+ }
+
+/*************************************************
+* Clear the text buffer *
+*************************************************/
+static void new_buffer()
+ {
+ /*
+ In theory, it would be nice to check if this was unsaved text and prompt
+ to save it. However, this really isn't supposed to be a GTK+ example, so
+ we won't.
+ */
+ gtk_text_buffer_set_text(buffer, "", -1);
+ buffer_source = "";
+ }
+
+/*************************************************
+* Put the contents of a file into the buffer *
+*************************************************/
+static void open_buffer()
+ {
+ std::string filename = get_filename("Select File");
+
+ if(filename == "")
+ return;
+
+ std::ifstream in(filename.c_str());
+
+ new_buffer();
+ buffer_source = filename;
+
+ while(in.good())
+ {
+ char buf[1024] = { 0 };
+
+ in.read(buf, 1024);
+ size_t got = in.gcount();
+
+ GtkTextIter iter;
+ gtk_text_buffer_get_end_iter(buffer, &iter);
+ gtk_text_buffer_insert(buffer, &iter, buf, got);
+ }
+ }
+
+/*************************************************
+* Save the signature to a file *
+*************************************************/
+static void save_sig()
+ {
+ std::string sig_file = buffer_source;
+
+ /* No sig, nothing to save */
+ const gchar* sig = gtk_entry_get_text(GTK_ENTRY(sig_view));
+ if(strlen(sig) == 0)
+ return;
+
+ if(sig_file == "")
+ sig_file = get_filename("Select Signature Output File");
+ else
+ sig_file += ".sig";
+
+ std::ofstream out(sig_file.c_str());
+ out << sig << std::endl;
+ }
+
+/*************************************************
+* Save the current key *
+*************************************************/
+static void save_key()
+ {
+ do_save_key("Save Current Key");
+ }
+
+/*************************************************
+* Common case of Save/Save As *
+*************************************************/
+static void do_save(const std::string& filename)
+ {
+ std::ofstream out(filename.c_str());
+
+ GtkTextIter start, end;
+ gtk_text_buffer_get_bounds(buffer, &start, &end);
+ gchar* bits = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
+ out.write(bits, strlen(bits));
+ g_free(bits);
+ buffer_source = filename;
+ }
+
+/*************************************************
+* Save the buffer *
+*************************************************/
+static void save_buffer_as()
+ {
+ std::string filename = get_filename("Select Output File");
+ if(filename != "")
+ do_save(filename);
+ }
+
+/*************************************************
+* Save the buffer *
+*************************************************/
+static void save_buffer()
+ {
+ if(buffer_source != "")
+ do_save(buffer_source);
+ else
+ save_buffer_as();
+ }
+
+/*************************************************
+* Make a menubar for the app *
+*************************************************/
+static GtkWidget* make_menubar(GtkWidget *window)
+ {
+ static GtkItemFactoryEntry menu_items[] = {
+ { "/_File", NULL, NULL, 0, "<Branch>", NULL },
+ { "/File/_New", "<control>N", new_buffer, 0, NULL, NULL },
+ { "/File/_Open", "<control>O", open_buffer, 0, NULL, NULL },
+ { "/File/_Save", "<control>S", save_buffer, 0, NULL, NULL },
+ { "/File/Save _As", NULL, save_buffer_as, 0, NULL, NULL },
+ { "/File/sep1", NULL, NULL, 0, "<Separator>", NULL },
+ { "/File/Save Sig", NULL, save_sig, 0, NULL, NULL },
+ { "/File/sep2", NULL, NULL, 0, "<Separator>", NULL },
+ { "/File/_Quit", "<control>Q", gtk_main_quit, 0, NULL, NULL },
+
+ { "/_Keys", NULL, NULL, 0, "<Branch>", NULL },
+ { "/Keys/Open", NULL, get_key, 0, NULL, NULL },
+ { "/Keys/_Generate", NULL, gen_key, 0, NULL, NULL },
+ { "/Keys/Save Current", NULL, save_key, 0, NULL, NULL },
+
+ { "/Signing", NULL, NULL, 0, "<Branch>", NULL },
+ { "/Signing/Sign", NULL, really_sign_buffer, 0, NULL, NULL },
+
+ { "/_Help", NULL, NULL, 0, "<LastBranch>", NULL },
+ { "/Help/Help", NULL, show_help, 0, NULL, NULL },
+ { "/Help/sep1", NULL, NULL, 0, "<Separator>", NULL },
+ { "/Help/About", NULL, show_about, 0, NULL, NULL },
+ };
+
+ GtkAccelGroup* accel_group = gtk_accel_group_new();
+ GtkItemFactory* item_factory =
+ gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group);
+ const gint nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
+ gtk_item_factory_create_items(item_factory, nmenu_items, menu_items, NULL);
+ gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
+ return gtk_item_factory_get_widget(item_factory, "<main>");
+ }
+
+int main(int argc, char *argv[])
+ {
+ gtk_init(&argc, &argv);
+
+ try {
+ Botan::LibraryInitializer init;
+
+ /* Create a new top-level window */
+ GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title(GTK_WINDOW(window), "DSA Utility");
+ gtk_signal_connect(GTK_OBJECT(window), "delete_event",
+ gtk_main_quit, NULL);
+
+ /* Create the vbox to hold our stuff */
+ GtkWidget* vbox = gtk_vbox_new(FALSE, 0);
+ gtk_container_border_width(GTK_CONTAINER(vbox), 1);
+ gtk_container_add(GTK_CONTAINER(window), vbox);
+
+ /* Create the menu bar */
+ GtkWidget *menubar = make_menubar(window);
+
+ /* Create the entry that holds the signature */
+ sig_view = gtk_entry_new();
+ gtk_editable_set_editable(GTK_EDITABLE(sig_view), FALSE);
+
+ /* Create the text box */
+ GtkWidget* view = gtk_text_view_new();
+ buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
+
+ gtk_widget_set_size_request(view, 640, 480);
+ gtk_text_buffer_set_text(buffer, "Some initial contents.", -1);
+
+ // Resign it on each change: fast enough, but probably not really useful
+ //g_signal_connect(G_OBJECT(buffer), "changed", sign_buffer, 0);
+ g_signal_connect(G_OBJECT(buffer), "changed", zap_sig, 0);
+
+ gtk_container_add(GTK_CONTAINER(vbox), menubar);
+ gtk_container_add(GTK_CONTAINER(vbox), view);
+ gtk_container_add(GTK_CONTAINER(vbox), sig_view);
+
+ gtk_widget_show_all(window);
+
+ gtk_main();
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << std::endl;
+ }
+ return 0;
+ }
diff --git a/doc/examples/gtk/gtk_ui.cpp b/doc/examples/gtk/gtk_ui.cpp
new file mode 100644
index 000000000..515fbc519
--- /dev/null
+++ b/doc/examples/gtk/gtk_ui.cpp
@@ -0,0 +1,78 @@
+/*************************************************
+* GTK+ User Interface Source File *
+*************************************************/
+
+#include "gtk_ui.h"
+
+/*************************************************
+* GTK+ Callback *
+*************************************************/
+void GTK_UI::callback(GtkWidget* entry, gpointer passphrase_ptr)
+ {
+ const gchar *entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
+ char* passphrase = (char*)passphrase_ptr;
+ strcpy(passphrase, entry_text);
+ }
+
+/*************************************************
+* Get a passphrase from the user *
+*************************************************/
+std::string GTK_UI::get_passphrase(const std::string& what,
+ const std::string& source,
+ UI_Result& result) const
+ {
+ std::string msg = "A passphrase is needed to access the " + what;
+ if(source != "") msg += "\nin " + source;
+ return get_passphrase(msg, result);
+ }
+
+/*************************************************
+* Get a passphrase from the user *
+*************************************************/
+std::string GTK_UI::get_passphrase(const std::string& label_text,
+ UI_Result& result) const
+ {
+ const int MAX_PASSPHRASE = 64;
+
+ GtkDialogFlags flags =
+ (GtkDialogFlags)(GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL);
+
+ GtkWidget* dialog = gtk_dialog_new_with_buttons(
+ "Enter Passphrase",
+ NULL, flags,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ NULL);
+
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
+
+ GtkWidget* label = gtk_label_new(label_text.c_str());
+
+ GtkWidget* entry = gtk_entry_new();
+ gtk_entry_set_visibility(GTK_ENTRY(entry), 0);
+ gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
+ gtk_entry_set_max_length(GTK_ENTRY(entry), MAX_PASSPHRASE);
+
+ char passphrase_buf[MAX_PASSPHRASE + 1] = { 0 };
+
+ gtk_signal_connect(GTK_OBJECT(entry), "activate",
+ GTK_SIGNAL_FUNC(callback), passphrase_buf);
+
+ GtkWidget* vbox = gtk_vbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, FALSE, 0);
+
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox, TRUE, TRUE, 0);
+ gtk_widget_show_all(vbox);
+
+ /* Block until we get something back */
+ result = CANCEL_ACTION;
+ if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
+ result = OK;
+
+ gtk_widget_destroy(dialog);
+
+ if(result == OK)
+ return std::string(passphrase_buf);
+ return "";
+ }
diff --git a/doc/examples/gtk/gtk_ui.h b/doc/examples/gtk/gtk_ui.h
new file mode 100644
index 000000000..9ced83a81
--- /dev/null
+++ b/doc/examples/gtk/gtk_ui.h
@@ -0,0 +1,25 @@
+/*************************************************
+* GTK+ User Interface Header File *
+*************************************************/
+
+#ifndef BOTAN_EXT_GTK_UI__
+#define BOTAN_EXT_GTK_UI__
+
+#include <botan/ui.h>
+#include <gtk/gtk.h>
+
+/*************************************************
+* GTK+ Passphrase Callback Object *
+*************************************************/
+class GTK_UI : public Botan::User_Interface
+ {
+ public:
+ std::string get_passphrase(const std::string&, const std::string&,
+ UI_Result&) const;
+
+ std::string get_passphrase(const std::string&, UI_Result&) const;
+
+ static void callback(GtkWidget*, gpointer);
+ };
+
+#endif
diff --git a/doc/examples/gtk/readme.txt b/doc/examples/gtk/readme.txt
new file mode 100644
index 000000000..4f3691166
--- /dev/null
+++ b/doc/examples/gtk/readme.txt
@@ -0,0 +1,18 @@
+
+This is an example of how to use Botan in a GUI. You need at least
+Botan 1.6.0.
+
+You'll also need GTK+ 2.x (tested with GTK+ 2.10; should work with
+most versions). Keep in mind that I was learning GTK as I was writing
+this code, so it is not exactly the best GTK code you're likely to
+see.
+
+dsa.cpp is the main GTK+ driver. It has some comments at the top which
+point out major areas of interest.
+
+gtk_ui.* implement a User_Interface object that opens up a GTK+ dialog
+box that asks the user for their passphrase. It works pretty well, the
+only major deficiency is a fixed upper limit on the size of the
+passphrase (currently 64). You may want to use this in your own code,
+assuming you use GTK. If not, it should at least provide an outline
+for writing a version for your favorite windowing system.
diff --git a/doc/examples/hash_fd.cpp b/doc/examples/hash_fd.cpp
index d6487095a..1deed6988 100644
--- a/doc/examples/hash_fd.cpp
+++ b/doc/examples/hash_fd.cpp
@@ -18,7 +18,7 @@ I guess any POSIX.1 compliant OS (in theory).
#include <iostream>
#include <botan/botan.h>
-#if !defined(BOTAN_EXT_PIPE_UNIXFD_IO)
+#if !defined(BOTAN_HAS_PIPE_UNIXFD_IO)
#error "You didn't compile the pipe_unixfd module into Botan"
#endif
diff --git a/doc/examples/make_prime.cpp b/doc/examples/make_prime.cpp
new file mode 100644
index 000000000..ab84e1cdc
--- /dev/null
+++ b/doc/examples/make_prime.cpp
@@ -0,0 +1,69 @@
+#include <botan/numthry.h>
+
+using namespace Botan;
+
+#include <set>
+#include <iostream>
+#include <iterator>
+#include <map>
+
+int main()
+ {
+ RandomNumberGenerator* rng = RandomNumberGenerator::make_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/pqg_gen.cpp b/doc/examples/pqg_gen.cpp
new file mode 100644
index 000000000..328dc785e
--- /dev/null
+++ b/doc/examples/pqg_gen.cpp
@@ -0,0 +1,114 @@
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+#include <map>
+#include <memory>
+
+#include <botan/botan.h>
+#include <botan/look_pk.h>
+#include <botan/dsa.h>
+#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 {
+ LibraryInitializer init("use_engines");
+
+ std::auto_ptr<RandomNumberGenerator> rng(
+ RandomNumberGenerator::make_rng());
+
+ std::ifstream in("PQGGen.rsp");
+ if(!in)
+ throw Exception("Can't open response file");
+
+ std::map<std::string, std::string> inputs;
+
+ while(in.good())
+ {
+ std::string line;
+ std::getline(in, line);
+
+ if(line == "" || line[0] == '[' || line[0] == '#')
+ continue;
+
+ std::vector<std::string> name_and_val = split_on(line, '=');
+
+ if(name_and_val.size() != 2)
+ throw Decoding_Error("Unexpected input: " + line);
+
+ name_and_val[0].erase(name_and_val[0].size()-1);
+ name_and_val[1].erase(0, 1);
+
+ std::string name = name_and_val[0], value = name_and_val[1];
+
+ inputs[name] = value;
+
+ if(name == "H")
+ {
+ bool result = check(*rng, inputs);
+ std::cout << "." << std::flush;
+ if(result == false)
+ {
+ std::cout << " Check failed\n";
+
+ std::map<std::string, std::string>::const_iterator i;
+
+ for(i = inputs.begin(); i != inputs.end(); i++)
+ std::cout << i->first << " = " << i->second << "\n";
+
+ std::cout << "\n";
+ }
+
+ inputs.clear();
+ }
+ }
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
+
+bool check(RandomNumberGenerator& rng,
+ std::map<std::string, std::string> inputs)
+ {
+ BigInt p("0x"+inputs["P"]),
+ q("0x"+inputs["Q"]),
+ g("0x"+inputs["G"]),
+ h("0x"+inputs["H"]);
+
+ if(h < 1 || h >= p-1) return false;
+
+ //u32bit c = to_u32bit(inputs["c"]);
+
+ Pipe pipe(new Hex_Decoder);
+ pipe.process_msg(inputs["Seed"]);
+ SecureVector<byte> seed = pipe.read_all();
+
+ BigInt our_p, our_q;
+
+ u32bit qbits = (p.bits() <= 1024) ? 160 : 256;
+
+ bool found = DL_Group::generate_dsa_primes(rng, 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/ressol.cpp b/doc/examples/ressol.cpp
new file mode 100644
index 000000000..9fedc8115
--- /dev/null
+++ b/doc/examples/ressol.cpp
@@ -0,0 +1,77 @@
+#include <botan/numthry.h>
+
+using namespace Botan;
+
+#include <iostream>
+
+void test_ressol(const BigInt& p, RandomNumberGenerator& rng)
+ {
+ std::cout << p << std::endl;
+
+ // const BigInt p_16 = p / 16;
+
+ int noroot = 0, false_result = 0;
+
+ for(int j = 0; j != 1000; ++j)
+ {
+ BigInt x = random_integer(rng, 0, p);
+ //if(x % p_16 == 0)
+ //std::cout << "p = " << p << " x = " << x << "\n";
+
+ BigInt sqrt_x = ressol(x, p);
+
+ if(sqrt_x < 0)
+ {
+ ++noroot;
+ continue;
+ }
+
+ BigInt check = square(sqrt_x) % p;
+
+ if(check != x % p)
+ {
+ std::cout << "FAIL "
+ << "x = " << x << "; "
+ << "p = " << p << "; "
+ << "s = " << sqrt_x << "; "
+ << "s^2%p = " << check << "\n";
+ ++false_result;
+ }
+ }
+ /*
+ std::cout << "nomatch=" << nomatch << " "
+ << "noroot=" << noroot << " "
+ << "false=" << false_result << "\n";
+ */
+ }
+
+int main()
+ {
+ RandomNumberGenerator* rng = RandomNumberGenerator::make_rng();
+
+#if 0
+ std::cout << ressol(8, 17) << "\n";
+ std::cout << ressol_orig(8, 17) << "\n";
+#endif
+
+#if 1
+ for(int j = 16; j != 1024; ++j)
+ {
+ std::cout << "Round " << j << "\n";
+ BigInt p = random_prime(*rng, j);
+ test_ressol(p, *rng);
+ //printf("%d\n", j);
+
+
+ }
+#endif
+ /*
+ for(u32bit j = 9; j != PRIME_TABLE_SIZE; ++j)
+ {
+ std::cout << "PRIME[" << j << "] == " << PRIMES[j] << std::endl;
+ //printf("%d - ", PRIMES[j]);
+ test_ressol(PRIMES[j], *rng);
+ //printf("\n");
+ }
+ */
+ }
diff --git a/doc/examples/rng_test.cpp b/doc/examples/rng_test.cpp
new file mode 100644
index 000000000..0cf7bd7fc
--- /dev/null
+++ b/doc/examples/rng_test.cpp
@@ -0,0 +1,136 @@
+#include <botan/botan.h>
+#include <botan/x931_rng.h>
+#include <botan/filters.h>
+
+#include <iostream>
+#include <fstream>
+#include <boost/algorithm/string.hpp>
+#include <stdexcept>
+
+using namespace Botan;
+
+std::vector<std::pair<std::string, std::string> > read_file(const std::string&);
+
+SecureVector<byte> decode_hex(const std::string& in)
+ {
+ SecureVector<byte> result;
+
+ try {
+ Botan::Pipe pipe(new Botan::Hex_Decoder);
+ pipe.process_msg(in);
+ result = pipe.read_all();
+ }
+ catch(std::exception& e)
+ {
+ result.destroy();
+ }
+ return result;
+ }
+
+std::string hex_encode(const byte in[], u32bit len)
+ {
+ Botan::Pipe pipe(new Botan::Hex_Encoder);
+ pipe.process_msg(in, len);
+ return pipe.read_all_as_string();
+ }
+
+class Fixed_Output_RNG : public RandomNumberGenerator
+ {
+ public:
+ bool is_seeded() const { return !buf.empty(); }
+
+ byte random()
+ {
+ if(buf.empty())
+ throw std::runtime_error("Out of bytes");
+
+ byte out = buf.front();
+ buf.pop_front();
+ return out;
+ }
+
+ void randomize(byte out[], u32bit len) throw()
+ {
+ for(u32bit j = 0; j != len; j++)
+ out[j] = random();
+ }
+
+ std::string name() const { return "Fixed_Output_RNG"; }
+
+ void clear() throw() {}
+
+ void add_entropy(const byte in[], u32bit len)
+ {
+ buf.insert(buf.end(), in, in + len);
+ }
+
+ void add_entropy_source(EntropySource* es) { delete es; }
+
+ Fixed_Output_RNG() {}
+ private:
+ std::deque<byte> buf;
+ };
+
+void x931_tests(std::vector<std::pair<std::string, std::string> > vecs,
+ const std::string& cipher)
+ {
+ for(size_t j = 0; j != vecs.size(); ++j)
+ {
+ const std::string result = vecs[j].first;
+ const std::string input = vecs[j].second;
+
+ ANSI_X931_RNG prng(cipher, new Fixed_Output_RNG);
+
+ SecureVector<byte> x = decode_hex(input);
+ prng.add_entropy(x.begin(), x.size());
+
+ SecureVector<byte> output(result.size() / 2);
+ prng.randomize(output, output.size());
+
+ if(decode_hex(result) != output)
+ std::cout << "FAIL";
+ else
+ std::cout << "PASS";
+
+ std::cout << " Seed " << input << " "
+ << "Got " << hex_encode(output, output.size()) << " "
+ << "Exp " << result << "\n";
+ }
+
+ }
+
+int main()
+ {
+ x931_tests(read_file("ANSI931_AES128VST.txt.vst"), "AES-128");
+ x931_tests(read_file("ANSI931_AES192VST.txt.vst"), "AES-192");
+ x931_tests(read_file("ANSI931_AES256VST.txt.vst"), "AES-256");
+ x931_tests(read_file("ANSI931_TDES2VST.txt.vst"), "TripleDES");
+ x931_tests(read_file("ANSI931_TDES3VST.txt.vst"), "TripleDES");
+ }
+
+
+std::vector<std::pair<std::string, std::string> > read_file(const std::string& fsname)
+ {
+ std::ifstream in(fsname.c_str());
+
+ std::vector<std::pair<std::string, std::string> > out;
+
+ while(in.good())
+ {
+ std::string line;
+ std::getline(in, line);
+
+ if(line == "")
+ break;
+
+ std::vector<std::string> l;
+ boost::split(l, line, boost::is_any_of(":"));
+
+ if(l.size() != 2)
+ throw std::runtime_error("Bad line " + line);
+
+ out.push_back(std::make_pair(l[0], l[1]));
+ }
+
+ return out;
+ }
diff --git a/doc/examples/row_encryptor.cpp b/doc/examples/row_encryptor.cpp
new file mode 100644
index 000000000..dc15ee6c4
--- /dev/null
+++ b/doc/examples/row_encryptor.cpp
@@ -0,0 +1,134 @@
+#include <string>
+#include <memory>
+#include <sstream>
+#include <iostream>
+
+#include <botan/botan.h>
+#include <botan/filters.h>
+#include <botan/eax.h>
+
+using namespace Botan;
+
+/**
+Encrypt and decrypt small rows
+*/
+class Row_Encryptor
+ {
+ public:
+ Row_Encryptor(const std::string& passphrase,
+ RandomNumberGenerator& rng);
+
+ std::string encrypt(const std::string& input,
+ const MemoryRegion<byte>& salt);
+
+ std::string decrypt(const std::string& input,
+ const MemoryRegion<byte>& salt);
+
+ private:
+ Row_Encryptor(const Row_Encryptor&) {}
+ Row_Encryptor& operator=(const Row_Encryptor&) { return (*this); }
+
+ Pipe enc_pipe, dec_pipe;
+ EAX_Encryption* eax_enc; // owned by enc_pipe
+ EAX_Decryption* eax_dec; // owned by dec_pipe;
+ };
+
+Row_Encryptor::Row_Encryptor(const std::string& passphrase,
+ RandomNumberGenerator& rng)
+ {
+ std::auto_ptr<S2K> s2k(get_s2k("PBKDF2(SHA-160)"));
+
+ s2k->set_iterations(10000);
+
+ s2k->new_random_salt(rng, 10); // 10 bytes == 80 bits
+
+ SecureVector<byte> key = s2k->derive_key(32, passphrase).bits_of();
+
+ /*
+ Save pointers to the EAX objects so we can change the IV as needed
+ */
+ enc_pipe.append(eax_enc = new EAX_Encryption("Serpent"));
+ dec_pipe.append(eax_dec = new EAX_Decryption("Serpent"));
+
+ eax_enc->set_key(key);
+ eax_dec->set_key(key);
+ }
+
+std::string Row_Encryptor::encrypt(const std::string& input,
+ const MemoryRegion<byte>& salt)
+ {
+ eax_enc->set_iv(salt);
+
+ enc_pipe.start_msg();
+ enc_pipe.write(input);
+ enc_pipe.end_msg();
+
+ return enc_pipe.read_all_as_string(Pipe::LAST_MESSAGE);
+ }
+
+std::string Row_Encryptor::decrypt(const std::string& input,
+ const MemoryRegion<byte>& salt)
+ {
+ eax_dec->set_iv(salt);
+
+ dec_pipe.start_msg();
+ dec_pipe.write(input);
+ dec_pipe.end_msg();
+
+ return dec_pipe.read_all_as_string(Pipe::LAST_MESSAGE);
+ }
+
+/*************************
+ Test code follows:
+*/
+
+#include <botan/loadstor.h>
+
+int main()
+ {
+ LibraryInitializer init;
+
+ std::auto_ptr<RandomNumberGenerator> rng(RandomNumberGenerator::make_rng());
+
+ Row_Encryptor encryptor("secret passphrase", *rng);
+
+ std::vector<std::string> original_inputs;
+
+ for(u32bit i = 0; i != 15000; ++i)
+ {
+ std::ostringstream out;
+
+ // This will actually generate variable length inputs (when
+ // there are leading 0s, which are skipped), which is good
+ // since it assures performance is OK across a mix of lengths
+ // TODO: Maybe randomize the length slightly?
+
+ for(u32bit j = 0; j != 32; ++j)
+ out << std::hex << (int)rng->next_byte();
+
+ original_inputs.push_back(out.str());
+ }
+
+ std::vector<std::string> encrypted_values;
+ MemoryVector<byte> salt(4); // keep out of loop to avoid excessive dynamic allocation
+
+ for(u32bit i = 0; i != original_inputs.size(); ++i)
+ {
+ std::string input = original_inputs[i];
+ store_le(i, salt);
+
+ encrypted_values.push_back(encryptor.encrypt(input, salt));
+ }
+
+ for(u32bit i = 0; i != encrypted_values.size(); ++i)
+ {
+ std::string ciphertext = encrypted_values[i];
+ store_le(i, salt); // NOTE: same salt value as previous loop (index value)
+
+ std::string output = encryptor.decrypt(ciphertext, salt);
+
+ if(output != original_inputs[i])
+ std::cout << "BOOM " << i << "\n";
+ }
+
+ }
diff --git a/doc/examples/rsa_manykey.cpp b/doc/examples/rsa_manykey.cpp
new file mode 100644
index 000000000..95be8c568
--- /dev/null
+++ b/doc/examples/rsa_manykey.cpp
@@ -0,0 +1,34 @@
+/*
+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()
+ {
+ std::auto_ptr<RandomNumberGenerator> rng(RandomNumberGenerator::make_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/sig_gen.cpp b/doc/examples/sig_gen.cpp
new file mode 100644
index 000000000..ca7058549
--- /dev/null
+++ b/doc/examples/sig_gen.cpp
@@ -0,0 +1,90 @@
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+#include <map>
+#include <memory>
+
+#include <botan/botan.h>
+#include <botan/look_pk.h>
+#include <botan/dsa.h>
+using namespace Botan;
+
+bool check(std::map<std::string, std::string>);
+
+int main()
+ {
+ try {
+ LibraryInitializer init;
+
+ std::ifstream in("SigGen.rsp");
+ if(!in)
+ throw Exception("Can't open response file");
+
+ std::map<std::string, std::string> inputs;
+
+ while(in.good())
+ {
+ std::string line;
+ std::getline(in, line);
+
+ if(line == "" || line[0] == '[' || line[0] == '#')
+ continue;
+
+ std::vector<std::string> name_and_val = split_on(line, '=');
+
+ if(name_and_val.size() != 2)
+ throw Decoding_Error("Unexpected input: " + line);
+
+ name_and_val[0].erase(name_and_val[0].size()-1);
+ name_and_val[1].erase(0, 1);
+
+ std::string name = name_and_val[0], value = name_and_val[1];
+
+ inputs[name] = value;
+
+ if(name == "S")
+ {
+ bool result = check(inputs);
+ if(result == false)
+ {
+ std::cout << " Check failed\n";
+
+ std::map<std::string, std::string>::const_iterator i;
+
+ for(i = inputs.begin(); i != inputs.end(); i++)
+ std::cout << i->first << " = " << i->second << "\n";
+ }
+ inputs["Msg"] = inputs["R"] = inputs["S"] = "";
+ }
+ }
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
+
+bool check(std::map<std::string, std::string> inputs)
+ {
+ BigInt p("0x"+inputs["P"]),
+ q("0x"+inputs["Q"]),
+ g("0x"+inputs["G"]),
+ y("0x"+inputs["Y"]);
+
+ DSA_PublicKey key(DL_Group(p, q, g), y);
+
+ Pipe pipe(new Hex_Decoder);
+
+ pipe.process_msg(inputs["Msg"]);
+ pipe.start_msg();
+ pipe.write(inputs["R"]);
+ pipe.write(inputs["S"] );
+ pipe.end_msg();
+
+ std::auto_ptr<PK_Verifier> verify(get_pk_verifier(key, "EMSA1(SHA-1)"));
+
+ return verify->verify_message(pipe.read_all(0), pipe.read_all(1));
+ }
diff --git a/doc/info.txt b/doc/info.txt
index 52afda968..b73b01738 100644
--- a/doc/info.txt
+++ b/doc/info.txt
@@ -25,6 +25,11 @@ Botan supports the following basic cryptographic algorithms:
For build instructions, read 'doc/building.pdf'. The license can be
found in 'doc/license.txt', and the ChangeLog is in 'doc/log.txt'.
+Higher level protocols are implemented on top of Botan by:
+
+NetSieben SSH Library (SSHv2): http://www.netsieben.com/products/ssh/
+Ajisai (SSLv3/TLSv1): http://www.randombit.net/code/ajisai/
+
Check http://botan.randombit.net/ for announcements and news. If
you'll be developing code using Botan, consider joining the mailing
lists; links to subscriptions forms and the archives can be found on
diff --git a/doc/log.txt b/doc/log.txt
index 8782a121f..135cce82d 100644
--- a/doc/log.txt
+++ b/doc/log.txt
@@ -1,4 +1,39 @@
+* 1.7.15, ????-??-??
+ - Alter configure.pl options for better autotools compatability
+
+* 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
+ - 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
diff --git a/doc/scripts/comba.py b/doc/scripts/comba.py
new file mode 100755
index 000000000..ce3cfed77
--- /dev/null
+++ b/doc/scripts/comba.py
@@ -0,0 +1,65 @@
+#!/usr/bin/python
+
+import sys
+
+def comba_indexes(N):
+
+ indexes = []
+
+ for i in xrange(0, 2*N):
+ x = []
+
+ for j in xrange(max(0, i-N+1), min(N, i+1)):
+ x += [(j,i-j)]
+ indexes += [sorted(x)]
+
+ return indexes
+
+def comba_sqr_indexes(N):
+
+ indexes = []
+
+ for i in xrange(0, 2*N):
+ x = []
+
+ for j in xrange(max(0, i-N+1), min(N, i+1)):
+ if j < i-j:
+ x += [(j,i-j)]
+ else:
+ x += [(i-j,j)]
+ indexes += [sorted(x)]
+
+ return indexes
+
+def comba_multiply_code(N):
+ indexes = comba_indexes(N)
+
+ for (i,idx) in zip(range(0, len(indexes)), indexes):
+ for pair in idx:
+ print "word3_muladd(&w2, &w1, &w0, x[%2d], y[%2d]);" % (pair)
+ print "z[%2d] = w0; w0 = w1; w1 = w2; w2 = 0;" % (i)
+
+def comba_square_code(N):
+ indexes = comba_sqr_indexes(N)
+
+ for (rnd,idx) in zip(range(0, len(indexes)), indexes):
+ for (i,pair) in zip(range(0, len(idx)), idx):
+ if pair[0] == pair[1]:
+ print " word3_muladd(&w2, &w1, &w0, x[%2d], x[%2d]);" % (pair)
+ elif i % 2 == 0:
+ print " word3_muladd_2(&w2, &w1, &w0, x[%2d], x[%2d]);" % (pair[0], pair[1])
+ if rnd < len(idx)-2:
+ print " z[%2d] = w0; w0 = w1; w1 = w2; w2 = 0;\n" % (rnd)
+ elif rnd == len(idx)-1:
+ print " z[%2d] = w0;\n" % (rnd)
+ else:
+ print " z[%2d] = w1;\n" % (rnd)
+
+def main(args = None):
+ if args is None:
+ args = sys.argv
+ #comba_square_code(int(args[1]))
+ comba_multiply_code(int(args[1]))
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/doc/scripts/combine_bmarks.pl b/doc/scripts/combine_bmarks.pl
new file mode 100755
index 000000000..b6436496e
--- /dev/null
+++ b/doc/scripts/combine_bmarks.pl
@@ -0,0 +1,120 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+my %results;
+my %pk;
+
+my %pk_algos;
+my %algos;
+
+my %filename_to_desc;
+
+for my $filename (@ARGV) {
+
+ open IN, "<$filename" or die "Couldn't read $filename ($!)\n";
+
+ my $desc = <IN>;
+ chomp $desc;
+
+ $results{$desc} = {};
+
+ while(<IN>) {
+ if(/(.*): +(.*) Mbytes\/sec/) {
+ $results{$desc}{$1} = $2;
+ $algos{$1} = undef;
+ }
+ if(/(.*): (.*) ops \/ second \((.*)\)/) {
+ my $alg = "$1";
+ $alg = "$alg $3" if defined($3);
+ $pk{$desc}{$alg} = $2;
+ $pk_algos{$alg} = undef;
+ }
+ }
+}
+
+
+sub print_table {
+ my @columns = sort keys %results;
+
+ print "\n<P>All results are in MiB / second:\n";
+ print "<TABLE BORDER CELLSPACING=1>\n<THEAD>\n";
+
+ my %col_index = ();
+
+ my $line = "<TR><TH>Algorithm ";
+
+ foreach my $col (@columns) {
+ $col_index{$col} = length($line);
+ $line .= "<TH>" . $col . " ";
+ }
+
+ $line .= "\n<TBODY>\n";
+
+ print $line;
+
+ $line = '';
+
+ foreach my $algo (sort keys %algos) {
+ $line = " <TR><TH>$algo ";
+
+ for my $col (@columns) {
+ my $result = $results{$col}{$algo};
+ $result = "-" if not defined($result);
+
+ $result = "<TH>$result";
+
+ $line .= ' ' while(length($line) < ($col_index{$col}));
+ $line .= $result;
+
+ }
+
+ print $line, "\n";
+ $line = '';
+ }
+
+ print "</TABLE>\n";
+}
+
+
+sub print_pk_table {
+ my @columns = sort keys %pk;
+
+ print "\n<P>All results are in operations per second:\n";
+ print "<TABLE BORDER CELLSPACING=1>\n<THEAD>\n";
+
+ my %col_index = ();
+
+ my $line = "<TR><TH>Algorithm ";
+
+ foreach my $col (@columns) {
+ $col_index{$col} = length($line);
+ $line .= "<TH>" . $col . " ";
+ }
+
+ $line .= "\n<TBODY>\n";
+
+ print $line;
+
+ foreach my $algo (sort keys %pk_algos) {
+ my $line = " <TR><TH>$algo ";
+
+ for my $col (@columns) {
+ my $result = $pk{$col}{$algo};
+ $result = '-' if not defined($result);
+
+ $result = "<TH>$result";
+
+ $line .= ' ' while(length($line) < ($col_index{$col}));
+ $line .= $result;
+
+ }
+
+ print $line, "\n";
+ }
+
+ print "</TABLE>\n";
+}
+
+print_table();
+print_pk_table();
diff --git a/doc/scripts/dist.sh b/doc/scripts/dist.sh
new file mode 100755
index 000000000..88edc71be
--- /dev/null
+++ b/doc/scripts/dist.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+
+SELECTOR=h:net.randombit.botan
+KEY_ID=EFBADFBC
+MTN_DB=${HOME}/var/mtn/botan.mtn
+WEB_DIR=${HOME}/projects/www
+
+DIST_DIR=~/Botan-dist
+
+# You shouldn't have to change anything after this
+mkdir -p $DIST_DIR
+cd $DIST_DIR
+
+mtn -d $MTN_DB checkout -r $SELECTOR Botan
+
+VERSION=$(Botan/configure.pl --version | sed 's/Botan //')
+
+mv Botan Botan-$VERSION
+
+cd Botan-$VERSION
+rm -rf _MTN
+rm -f .mtn-ignore
+
+# Build docs
+cd doc
+
+for doc in api tutorial building
+do
+ latex $doc.tex
+ latex $doc.tex
+ dvips $doc.dvi -o
+ pdflatex $doc.tex
+ pdflatex $doc.tex
+ cp $doc.pdf $DIST_DIR
+ mv $doc.ps $DIST_DIR
+ # Clean up after TeX
+ rm -f $doc.aux $doc.log $doc.dvi $doc.toc
+done
+
+cp log.txt ../..
+
+cd .. # topdir
+cd .. # now in DIST_DIR
+
+tar -cf Botan-$VERSION.tar Botan-$VERSION
+
+bzip2 -9 -k Botan-$VERSION.tar
+gzip -9 Botan-$VERSION.tar
+
+rm -rf Botan-$VERSION
+
+mv Botan-$VERSION.tar.gz Botan-$VERSION.tgz
+mv Botan-$VERSION.tar.bz2 Botan-$VERSION.tbz
+
+echo "*****************************************************"
+read -a PASSWORD -p "Enter PGP password (or ^C to skip signatures): "
+
+echo $PASSWORD | gpg --batch --armor -b --passphrase-fd 0 -u $KEY_ID Botan-$VERSION.tgz
+echo $PASSWORD | gpg --batch --armor -b --passphrase-fd 0 -u $KEY_ID Botan-$VERSION.tbz
+
+mv Botan-$VERSION.tgz* $WEB_DIR/files/botan/archive/v1.7
+mv Botan-$VERSION.tbz* $WEB_DIR/files/botan/
+mv -f log.txt $WEB_DIR/botan/log.txt
diff --git a/doc/scripts/primes.py b/doc/scripts/primes.py
new file mode 100755
index 000000000..cf4d139e3
--- /dev/null
+++ b/doc/scripts/primes.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+
+import sys
+
+def gcd(x,y):
+ if x <= 0 or y <= 0:
+ raise ValueError, "Arguments must be positive integers"
+ g = y
+ while x > 0:
+ g = x
+ x = y % x
+ y = g
+ return g
+
+
+def gen_primes():
+ primes = [2,3,5,7,11]
+
+ # Primes < 11351 fit into less than 256x64 bits
+ for i in xrange(1+primes[-1], 11351+1):
+ for prime in primes:
+ if gcd(i, prime) != 1:
+ break
+ else:
+ primes.append(i)
+
+ return primes
+
+def extract_product(primes):
+ product = 1
+
+ used = set()
+
+ for prime in sorted(primes, reverse=True):
+ if product * prime < 2**64:
+ product *= prime
+ used.add(prime)
+
+ primes -= used
+
+ return product
+
+def main():
+ primes = gen_primes()
+
+ primes.sort()
+ primes.reverse()
+
+ primes = set(primes)
+
+ while len(primes):
+ print "0x%016X, " % extract_product(primes)
+
+ #product = 1
+ #for prime in primes:
+ # product *= prime
+
+ # if product >= 2**64:
+ # print "%016X" % (product/prime)
+ # product = prime
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/doc/thanks.txt b/doc/thanks.txt
index 0d1f538e7..b6a3ef30b 100644
--- a/doc/thanks.txt
+++ b/doc/thanks.txt
@@ -22,6 +22,8 @@ drivers, enabling the creation of Botan's AEP engine module.
In addition, the following people have unknowingly contributed help:
+ Dean Gaudet <[email protected]> wrote the SSE2 implementation of SHA-1
+
The implementation of DES is based off a public domain implementation by Phil
Karn from 1994 (he, in turn, credits Richard Outerbridge and Jim Gillogly).
diff --git a/doc/todo.txt b/doc/todo.txt
index b861ed20c..f17a40e1f 100644
--- a/doc/todo.txt
+++ b/doc/todo.txt
@@ -138,8 +138,8 @@ architectures (such as Cell's SPU units, PowerPC, SPARCv9, MIPS, and
ARM) could really help, as could further work on the x86 code
(including making use of SSE instructions and VIA's Montgomery
multiplication instruction). The key routines for good performance are
-bigint_monty_redc and bigint_mul_add_words; together they make up
-30-60% of the runtime of most public key algorithms.
+bigint_monty_redc and bigint_simple_sqr; together they make up 30-60%
+of the runtime of most public key algorithms.
It is very likely that many of the core algorithms (in src/mp_*) could
be optimized at the C level by anyone has some knowledge or interest