diff options
Diffstat (limited to 'doc')
-rw-r--r-- | doc/algos.txt | 72 | ||||
-rw-r--r-- | doc/build_log.txt | 11 | ||||
-rw-r--r-- | doc/building.txt | 49 | ||||
-rw-r--r-- | doc/conf.py | 17 | ||||
-rw-r--r-- | doc/contrib.txt | 71 | ||||
-rw-r--r-- | doc/download.txt | 103 | ||||
-rw-r--r-- | doc/examples.txt | 42 | ||||
-rw-r--r-- | doc/faq.txt | 4 | ||||
-rw-r--r-- | doc/filters.txt | 3 | ||||
-rw-r--r-- | doc/firststep.txt | 29 | ||||
-rw-r--r-- | doc/index.txt | 122 | ||||
-rw-r--r-- | doc/intro.txt | 80 | ||||
-rw-r--r-- | doc/old/tutorial.tex | 880 | ||||
-rw-r--r-- | doc/pgpkey.txt (renamed from doc/pgpkeys.txt) | 0 | ||||
-rw-r--r-- | doc/pubkey.txt | 330 | ||||
-rw-r--r-- | doc/ssl.txt | 2 | ||||
-rw-r--r-- | doc/support.txt | 20 | ||||
-rw-r--r-- | doc/x509.txt | 577 |
18 files changed, 746 insertions, 1666 deletions
diff --git a/doc/algos.txt b/doc/algos.txt index 3d4050c11..b82d8d5c0 100644 --- a/doc/algos.txt +++ b/doc/algos.txt @@ -1,3 +1,6 @@ + +.. _algo_list: + Algorithms ======================================== @@ -9,46 +12,39 @@ primitives, including: * Public key cryptography - * Encryption algorithms RSA, ElGamal, DLIES (padding schemes OAEP, - PKCS #1 v1.5) - - * Signature algorithms RSA, DSA, ECDSA, GOST 34.10-2001, - Nyberg-Rueppel, Rabin-Williams (padding schemes PSS, PKCS #1 v1.5, - X9.31) - - * Key agreement techniques Diffie-Hellman and ECDH + * Encryption algorithms RSA, ElGamal, DLIES (padding schemes OAEP, + PKCS #1 v1.5) + * Signature algorithms RSA, DSA, ECDSA, GOST 34.10-2001, + Nyberg-Rueppel, Rabin-Williams (padding schemes PSS, PKCS #1 v1.5, + X9.31) + * Key agreement techniques Diffie-Hellman and ECDH * Hash functions - * NIST hashes: SHA-1, SHA-224, SHA-256, SHA-384, and SHA-512 + * NIST hashes: SHA-1, SHA-224, SHA-256, SHA-384, and SHA-512 - * RIPE hashes: RIPEMD-160 and RIPEMD-128 + * RIPE hashes: RIPEMD-160 and RIPEMD-128 - * SHA-3 candidates Skein-512, Keccak, and Blue Midnight Wish-512 + * SHA-3 candidates Skein-512, Keccak, and Blue Midnight Wish-512 - * Other common hash functions Whirlpool and Tiger + * Other common hash functions Whirlpool and Tiger - * National standard hashes HAS-160 and GOST 34.11 + * National standard hashes HAS-160 and GOST 34.11 - * Obsolete or insecure hashes MD5, MD4, MD2 + * Obsolete or insecure hashes MD5, MD4, MD2 - * Non-cryptographic checksums Adler32, CRC24, CRC32 + * Non-cryptographic checksums Adler32, CRC24, CRC32 * Block ciphers - * AES (Rijndael) and AES candidates Serpent, Twofish, MARS, CAST-256, RC6 - - * DES, and variants 3DES and DESX - - * National/telecom block ciphers SEED, KASUMI, MISTY1, GOST 28147, Skipjack - - * Other block ciphers including Blowfish, CAST-128, IDEA, Noekeon, - TEA, XTEA, RC2, RC5, SAFER-SK, and Square - - * Block cipher constructions Luby-Rackoff and Lion - - * Block cipher modes ECB, CBC, CBC/CTS, CFB, OFB, CTR, XTS and - authenticated cipher mode EAX + * AES (Rijndael) and AES candidates Serpent, Twofish, MARS, CAST-256, RC6 + * DES, and variants 3DES and DESX + * National/telecom block ciphers SEED, KASUMI, MISTY1, GOST 28147, Skipjack + * Other block ciphers including Blowfish, CAST-128, IDEA, Noekeon, + TEA, XTEA, RC2, RC5, SAFER-SK, and Square + * Block cipher constructions Luby-Rackoff and Lion + * Block cipher modes ECB, CBC, CBC/CTS, CFB, OFB, CTR, XTS and + authenticated cipher mode EAX * Stream ciphers ARC4, Salsa20/XSalsa20, Turing, and WiderWake4+1 @@ -57,21 +53,17 @@ primitives, including: * Public Key Infrastructure - * X.509 certificates (including generating new self-signed and CA - certs) and CRLs - - * Certificate path validation - - * PKCS #10 certificate requests (creation and certificate issue) + * X.509 certificates (including generating new self-signed and CA + certs) and CRLs + * Certificate path validation + * PKCS #10 certificate requests (creation and certificate issue) * Other cryptographic utility functions including - * Key derivation functions for passwords: PBKDF1 (PKCS #5 v1.5), - PBKDF2 (PKCS #5 v2.0), OpenPGP S2K (RFC 2440) - - * General key derivation functions KDF1 and KDF2 from IEEE 1363 - - * PRFs from ANSI X9.42, SSL v3.0, TLS v1.0 + * Key derivation functions for passwords: PBKDF1 (PKCS #5 v1.5), + PBKDF2 (PKCS #5 v2.0), OpenPGP S2K (RFC 2440) + * General key derivation functions KDF1 and KDF2 from IEEE 1363 + * PRFs from ANSI X9.42, SSL v3.0, TLS v1.0 Recommended Algorithms --------------------------------- diff --git a/doc/build_log.txt b/doc/build_log.txt index 968c9e912..de6197389 100644 --- a/doc/build_log.txt +++ b/doc/build_log.txt @@ -1,13 +1,12 @@ -.. _build_log: - Build Log ======================================== -To report build results (successful or not), email Jack -([email protected]) your results and relevant system -information (OS versions, compiler name and version, CPU architecture -and other hardware information, configuration settings). +To report build results (successful or not), email the `development +list <http://lists.randombit.net/mailman/listinfo/botan-devel/>`_ your +results and relevant system information (OS versions, compiler name +and version, CPU architecture and other hardware information, +configuration settings). Debian reports the build results for 1.8 on `a number of platforms <http://buildd.debian.org/pkg.cgi?pkg=botan1.8>`_. diff --git a/doc/building.txt b/doc/building.txt index fba56196d..6784a0141 100644 --- a/doc/building.txt +++ b/doc/building.txt @@ -55,10 +55,10 @@ system, and use that. It will print a display at the end showing which algorithms have and have not been enabled. For instance on one system we might see lines like:: - INFO: Skipping mod because CPU incompatible - asm_amd64 mp_amd64 mp_asm64 sha1_amd64 - INFO: Skipping mod because OS incompatible - cryptoapi_rng win32_stats - INFO: Skipping mod because compiler incompatible - mp_ia32_msvc - INFO: Skipping mod because loaded on request only - bzip2 gnump openssl qt_mutex zlib + INFO: Skipping, by request only - bzip2 gnump openssl qt_mutex zlib + INFO: Skipping, incompatible CPU - aes_intel aes_ssse3 asm_x86_64 mp_asm64 mp_x86_64 sha1_x86_64 + INFO: Skipping, incompatible OS - beos_stats cryptoapi_rng win32_crit_section win32_stats + INFO: Skipping, incompatible compiler - mp_msvc64 mp_x86_32_msvc The ones that are 'loaded on request only' have to be explicitly asked for, because they rely on third party libraries which your system @@ -168,9 +168,27 @@ compiler to look for both include files and library files in place where they will be in the default compiler search paths (consult your documentation and/or local expert for details). -Trickier Things +.. _amalgamation: + +The Amalgamation Build ---------------------------------------- +You can also configure Botan to be built using only a single source +file; this is quite convenient if you plan to embed the library into +another application. To do so, run ``configure.py`` with +whatever arguments you would ordinarily use, along with the option +``--gen-amalgamation``. This will create two (rather large) +files, ``botan_all.h`` and ``botan_all.cpp``. + +Whenever you would have included a botan header, you can then include +``botan_all.h``, and include ``botan_all.cpp`` along +with the rest of the source files in your build. If you want to be +able to easily switch between amalgamated and non-amalgamated versions +(for instance to take advantage of prepackaged versions of botan on +operating systems that support it), you can instead ignore +``botan_all.h`` and use the headers from +``build/include`` as normal. + Modules Relying on Third Party Libraries ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -196,27 +214,6 @@ enabled at build time; these include: required. Note that (unlike GNU MP) OpenSSL's versions are not always faster than the versions built into botan. -.. _amalgamation: - -Amalgamation -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -You can also configure Botan to be built using only a single source -file; this is quite convenient if you plan to embed the library into -another application. To do so, run ``configure.py`` with -whatever arguments you would ordinarily use, along with the option -``--gen-amalgamation``. This will create two (rather large) -files, ``botan_all.h`` and ``botan_all.cpp``. - -Whenever you would have included a botan header, you can then include -``botan_all.h``, and include ``botan_all.cpp`` along -with the rest of the source files in your build. If you want to be -able to easily switch between amalgamated and non-amalgamated versions -(for instance to take advantage of prepackaged versions of botan on -operating systems that support it), you can instead ignore -``botan_all.h`` and use the headers from -``build/include`` as normal. - Multiple Builds ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/doc/conf.py b/doc/conf.py index f4884cb69..d802afa28 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -70,11 +70,11 @@ release = '%d.%d.%d' % (botan_version.release_major, # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' +today_fmt = '%Y-%m-%d' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ['_build'] +exclude_patterns = [] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None @@ -115,7 +115,7 @@ html_theme = 'default' # The name for this set of Sphinx documents. If None, it defaults to # "<project> v<release> documentation". -#html_title = None +html_title = 'Botan' # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None @@ -132,7 +132,7 @@ html_theme = 'default' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. @@ -217,12 +217,3 @@ latex_show_urls = True # If false, no module index is generated. #latex_domain_indices = True - -# -- Options for manual page output -------------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'botan', u'botan Documentation', - [u'Jack Lloyd'], 1) -] diff --git a/doc/contrib.txt b/doc/contrib.txt deleted file mode 100644 index 2ad420747..000000000 --- a/doc/contrib.txt +++ /dev/null @@ -1,71 +0,0 @@ - -Contributing -======================================== - -Contributions to the library are most certainly welcome. To increase -the chances your patch will actually make it into releases in a timely -fashion, here are some guidelines for patch submission. - -Getting The Latest Sources ----------------------------------------- - -Botan's development occurs using a distributed version control system -called `Monotone <http://www.monotone.ca>`_. - -The main branch of development occurs on the branch named -``net.randombit.botan``; this is probably the branch you want, -especially if you are planning on making major changes. To -download that branch and set up a new workspace, run:: - - $ mtn db init --db=botan.mtn - $ mtn pull --db=botan.mtn randombit.net 'net.randombit.botan' - [...] - $ mtn checkout --db=botan.mtn --branch=net.randombit.botan - [...] - -By default the ``checkout`` command will place the workspace in a -directory with the same name as the branch you are checking out. If -you want a different directory name, just include it after the -``--branch`` option (you can also rename this directory at any time). - -If this is the first time you've connected to the server, Monotone -will print:: - - mtn: first time connecting to server randombit.net - mtn: I'll assume it's really them, but you might want to double-check - mtn: their key's fingerprint: 8c0b868f2247215c63c96983b1c8ca0f0f0cfd9a - -The fingerprint shown above was the correct one as of September 21, -2010. - -To pull further changes, from anywhere in the workspace run these -commands:: - - $ mtn pull - [...] - $ mtn update - [summary of changes] - -The ``mtn update`` command will give you a summary of which files -changed; to view the full changelog, run ``mtn log``. - -Monotone's distributed nature means you can check into your database -while continuing to merge changes made upstream. This is particularly -useful if your change is large or invasive, as you can checkpoint your -progress over time. - -If you are making a large number of changes, you may want to start up -a new branch that occasionally merges against the mainline; check the -monotone documentation for details. - -After you finish your changes, you can review them using ``mtn diff`` -to diff against the latest official head; send the output to the -mailing list for review and inclusion. - -Don't forget to update the file ``credits.txt`` with your information, -if you want to be listed as a contributor. Also, if your patch is -substantial enough to be considered copyrightable, add yourself to -``license.txt``. - -Patches are best directed to the `botan-devel -<http://lists.randombit.net/mailman/listinfo/botan-devel>`_. diff --git a/doc/download.txt b/doc/download.txt new file mode 100644 index 000000000..8d4e2436c --- /dev/null +++ b/doc/download.txt @@ -0,0 +1,103 @@ + +Getting The Latest Sources +======================================== + +Latest Releases +---------------------------------------- + +All releases are signed with a :doc:`PGP key <pgpkey>`. + +Unsure which release you want? Check the :ref:`FAQ <devel_vs_stable>`. + +.. only:: not website + + .. note:: + + If you are viewing this documentation offline, a more recent + version may be available at http://botan.randombit.net/download.html + +Current Stable Release +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The current stable release is `1.8.11 +<http://botan.randombit.net/news/releases/1_8_11.html>`_ which was +released on 2010-11-02. + +Sources: + +`1.8.11 tar/gz <http://botan.randombit.net/files/Botan-1.8.11.tgz>`_ +(`1.8.11 tar/gz sig <http://botan.randombit.net/files/Botan-1.8.11.tgz.asc>`_), + +`1.8.11 tar/bzip <http://botan.randombit.net/files/Botan-1.8.11.tbz>`_ +(`1.8.11 tar/bzip sig <http://botan.randombit.net/files/Botan-1.8.11.tbz.asc>`_) + +Windows binary installer for use with Visual C++ 2008: + +`1.8.11 x86-32 installer +<http://botan.randombit.net/files/win32/botan-1.8.11_win32.exe>`_ + +`1.8.11 x86-64 installer +<http://botan.randombit.net/files/win32/botan-1.8.11_win64.exe>`_ + +Current Development Release +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The current development release is `1.9.16 +<http://botan.randombit.net/news/releases/1_9_16.html>`_ which was +released on 2011-04-11. + +Sources: + +`1.9.16 tar/gz <http://botan.randombit.net/files/Botan-1.9.16.tgz>`_ +(`1.9.16 tar/gz sig <http://botan.randombit.net/files/Botan-1.9.16.tgz.asc>`_), + +`1.9.16 tar/bzip <http://botan.randombit.net/files/Botan-1.9.16.tbz>`_ +(`1.9.16 tar/bzip sig <http://botan.randombit.net/files/Botan-1.9.16.tbz.asc>`_) + +Windows binary installer for use with Visual C++ 2010: + +`1.9.17-pre x86-32 installer +<http://botan.randombit.net/files/win32/botan-1.9.17_win32.exe>`_ + +`1.9.17-pre x86-64 installer +<http://botan.randombit.net/files/win32/botan-1.9.17_win64.exe>`_ + +Accessing Version Control +---------------------------------------- + +Botan's development occurs using a distributed version control system +called `Monotone <http://www.monotone.ca>`_. + +The main branch of development occurs on the branch named +``net.randombit.botan``; this is probably the branch you want. To +download that branch and set up a new workspace, run:: + + $ mtn db init --db=botan.mtn + $ mtn pull --db=botan.mtn randombit.net 'net.randombit.botan' + [...] + $ mtn checkout --db=botan.mtn --branch=net.randombit.botan + [...] + +By default the ``checkout`` command will place the workspace in a directory +with the same name as the branch you are checking out. If you want a +different directory name, just include it after the ``--branch`` option (you +can also rename this directory at any time). + +If this is the first time you've connected to the server, Monotone +will print:: + + mtn: first time connecting to server randombit.net + mtn: I'll assume it's really them, but you might want to double-check + mtn: their key's fingerprint: 8c0b868f2247215c63c96983b1c8ca0f0f0cfd9a + +The fingerprint shown above was the correct one as of September 21, 2010. + +To pull further changes, from anywhere in the workspace run these commands:: + + $ mtn pull + [...] + $ mtn update + [summary of changes] + +The ``mtn update`` command will give you a summary of which files changed; +to view the full changelog, run ``mtn log``. diff --git a/doc/examples.txt b/doc/examples.txt deleted file mode 100644 index b9296829a..000000000 --- a/doc/examples.txt +++ /dev/null @@ -1,42 +0,0 @@ - -Examples -======================================== - -X.509 Certificate Examples ----------------------------------------- - -PKCS #10 Certificate Requests -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. literalinclude:: examples/pkcs10.cpp - -Self Signed Certificate -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Generate a 2048 bit RSA key, and then create a self-signed X.509v3 -certificate with that key. If the do_CA variable is set to true, then -it will be marked for CA use, otherwise it will get extensions -appropriate for use with a client certificate. The private key is -stored as an encrypted PKCS #8 object in another file. - -.. literalinclude:: examples/self_sig.cpp - -Certificate Authority -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Implement the functionality of a simple CA: read in a CA certificate, -the associated private key, and a PKCS #10 certificate request. Sign -the request and print the new certificate to stdout. - -File names are hardcoded for simplicity. The CA certificate is -expected in "cacert.pem", the private key is expected in -"caprivate.pem", and "req.pem" is a PKCS #10 certificate request. - -.. literalinclude:: examples/ca.cpp - -ASN.1 Parsing ----------------------------------------- - -This example is a simple ASN.1 parser - -.. literalinclude:: examples/asn1.cpp diff --git a/doc/faq.txt b/doc/faq.txt index 822deaa5d..38be253a7 100644 --- a/doc/faq.txt +++ b/doc/faq.txt @@ -1,6 +1,4 @@ -.. _faq: - Frequently Asked Questions ======================================== @@ -14,6 +12,8 @@ standards and de-facto standards like X.509v3 certificates, and various useful constructs like format-preserving encryption, all or nothing transforms, and secret splitting. +.. _devel_vs_stable: + Which release should I use? ---------------------------------------- diff --git a/doc/filters.txt b/doc/filters.txt index 7df1da5af..1af8c10f3 100644 --- a/doc/filters.txt +++ b/doc/filters.txt @@ -658,8 +658,7 @@ byte onto the next filter -- a 1 or a 0, which specifies whether the signature verified or not (respectively). For more information about PK algorithms (including creating the -appropriate objects to pass to the constructors), see -:ref:`public_key_crypto`. +appropriate objects to pass to the constructors), see :doc:`pubkey`. Encoders ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/doc/firststep.txt b/doc/firststep.txt index 0576e9c06..fb4eb583e 100644 --- a/doc/firststep.txt +++ b/doc/firststep.txt @@ -16,19 +16,22 @@ Initializing the Library There is a set of core services that the library needs access to while it is performing requests. To ensure these are set up, you must create -a ``LibraryInitializer`` object (usually called 'init' in Botan -example code; 'botan\_library' or 'botan\_init' may make more sense in -real applications) prior to making any calls to Botan. This object's -lifetime must exceed that of all other Botan objects your application -creates; for this reason the best place to create the -``LibraryInitializer`` is at the start of your ``main`` -function, since this guarantees that it will be created first and -destroyed last (via standard C++ RAII rules). The initializer does -things like setting up the memory allocation system and algorithm -lookup tables, finding out if there is a high resolution timer -available to use, and similar such matters. With no arguments, the -library is initialized with various default settings. So (unless you -are writing threaded code; see below), all you need is:: +an object of type + +.. cpp:class:: LibraryInitializer + +prior to making any other library calls. Typically this will be named +something like ``init`` or ``botan_init``. The object lifetime must +exceed that of all other Botan objects your application creates; for +this reason the best place to create the ``LibraryInitializer`` is at +the start of your ``main`` function, since this guarantees that it +will be created first and destroyed last (via standard C++ RAII +rules). The initializer does things like setting up the memory +allocation system and algorithm lookup tables, finding out if there is +a high resolution timer available to use, and similar such +matters. With no arguments, the library is initialized with various +default settings. So (unless you are writing threaded code; see +below), all you need is:: Botan::LibraryInitializer init; diff --git a/doc/index.txt b/doc/index.txt index 2f55ea362..442d0b6b9 100644 --- a/doc/index.txt +++ b/doc/index.txt @@ -1,13 +1,119 @@ -Botan Reference Manual +.. _contents: + +A friendly C++ crypto library +======================================== + +Botan is a :doc:`BSD-licensed <license>` crypto library for C++. It +provides applications with most any :doc:`cryptographic algorithm +<algos>` you might be looking for, along with :doc:`SSL/TLS <ssl>`, +:doc:`X.509 certificates and CRLs <x509>`, a :doc:`pipeline-style +message processing system <filters>`, and a wide variety of other +features. A third party open source implementation of `SSHv2 +<http://www.netsieben.com/products/ssh/>`_ that uses botan is also +available. + +.. only:: html and website + + See :doc:`download` for information about getting the latest version. + +The core of botan is written in C++98 with no dependencies besides the +STL and the rest of the ISO standard library, but the library also +includes optional modules which make further assumptions about their +environment, providing features such as compression (using zlib or +bzip2), entropy gathering, and secure memory allocation. Assembly +implementations of key algorithms like SHA-1 and multiple precision +integer routines for x86 and x86-64 processors are also included. + +It runs on most common operating systems and can be used with a number +of different commercial and open source compilers. The :doc:`build log +<build_log>` contains information about recently tested targets. It is +already included in most major package distributions, including +\ +`Fedora <https://admin.fedoraproject.org/pkgdb/acls/name/botan>`_, +`EPEL <http://download.fedora.redhat.com/pub/epel/beta/6/SRPMS/repoview/botan.html>`_ (for RHEL/CentOS), +`Debian <http://packages.debian.org/search?keywords=libbotan>`_, +`Ubuntu <http://packages.ubuntu.com/search?keywords=botan>`_, +`Gentoo <http://packages.gentoo.org/package/botan>`_, +`Arch Linux <http://www.archlinux.org/packages/extra/x86_64/botan/>`_, +`Slackbuild <http://slackbuilds.org/result/?search=Botan>`_, +`FreeBSD <http://www.freshports.org/security/botan>`_, +`NetBSD <ftp://ftp.netbsd.org/pub/pkgsrc/current/pkgsrc/security/botan/README.html>`_, +`Cygwin <http://cygwin.com/packages/botan/>`_, +`MacPorts <http://www.macports.org/ports.php?by=name&substr=botan>`_, +`OpenPKG <http://www.openpkg.org/product/packages/?package=botan>`_, and +`T2 SDE <http://www.t2-project.org/packages/botan.html>`_ and has +more than a few :doc:`known users <users>`. + +It was started as a personal project by `Jack Lloyd +<http:://www.randombit.net>`_, who continues to be the maintainer and +release manager. Since the first release in 2001, many individuals and +organizations have contributed bug fixes and new features. There have +been over 150 releases in the decade since the first publicly released +version; the :doc:`release notes <log>` and `news archive +<http://botan.randombit.net/news>`_ have more information about the +release history. + +In addition to C++ you can use botan from Python or Perl, though the +current bindings only wrap portions of the library. + +See the :doc:`faq` for a list of common questions and answers. + +If you need help or have questions, send a mail to the `development +mailing list +<http://lists.randombit.net/mailman/listinfo/botan-devel/>`_. +"Philosophical" bug reports, announcements of programs using the +library, and related topics are also welcome. :doc:`Commercial support +options <support>` are also available. + +If you find what you believe to be a bug, please file a ticket in +`Bugzilla <http://bugs.randombit.net/>`_. + +A useful reference while reading this manual is the `Doxygen +documentation <http://botan.randombit.net/doxygen>`_. + +Recommended Reading +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It's a very good idea if you have some knowledge of cryptography +*before* trying to use the library. This is an area where it is very +easy to make mistakes, and where things are often subtle and/or +counterintuitive. Obviously the library tries to provide things at a +high level precisely to minimize the number of ways things can go +wrong, but naive use will almost certainly not result in a secure +system. + +Especially recommended are: + +- *Cryptography Engineering* + Niels Ferguson, Bruce Schneier, and Tadayoshi Kohno + +- *Security Engineering -- A Guide to Building Dependable Distributed Systems* + Ross Anderson + +- *Handbook of Applied Cryptography* + Alfred J. Menezes, Paul C. Van Oorschot, and Scott A. Vanstone + (`available online <http://www.cacr.math.uwaterloo.ca/hac/>`_) + +Documentation Contents ================================= -Contents: +.. toctree:: + :hidden: + + algos + build_log + download + faq + license + log + pgpkey + support + users .. toctree:: :maxdepth: 2 - intro building firststep filters @@ -22,17 +128,7 @@ Contents: passhash rng fpe - examples - algos - faq - pgpkeys - license credits - contrib - support - users - build_log - log Indices and tables ================== diff --git a/doc/intro.txt b/doc/intro.txt deleted file mode 100644 index 01e65da86..000000000 --- a/doc/intro.txt +++ /dev/null @@ -1,80 +0,0 @@ - -Introduction -================================= - -Botan is a BSD-licensed crypto library for C++. It provides -applications with the ability to use a number of cryptographic -algorithms, as well as SSL/TLS, X.509 certificates and CRLs, PKCS #10 -certificate requests, a filter/pipe message processing system, and a -wide variety of other features. A third party open source -implementation of `SSHv2 <http://www.netsieben.com/products/ssh/>`_ -that uses botan is also available. - -The core of botan is written in C++98 with no dependencies besides the -STL and the rest of the ISO standard library, but the library also -includes optional modules which make further assumptions about their -environment, providing features such as compression (using zlib or -bzip2), entropy gathering, and secure memory allocation. Assembly -implementations of key algorithms like SHA-1 and multiple precision -integer routines for x86 and x86-64 processors are also included. - -It runs on most common operating systems and can be used with a number -of different commercial and open source compilers. It is already -included in most major Linux and BSD distros, as well as in Cygwin and -MacPorts. The :ref:`build log <build_log>` contains information about -recently tested targets. - -The primary system targets are 32 and 64 bit CPUs, with a flat memory -address space of at least 32 bits. Given the choice between optimizing -for 32 bit systems and 64 bit systems, 64 bit is preferred, on the -general theory that where performance is a real concern, modern 64 bit -processors are the obvious choice. Smaller devices like handhelds, -settop boxes, and smart phones may also be capable. - -It was started as a personal project by `Jack Lloyd -<http:://www.randombit.net>`_, who continues to be the maintainer and -release manager. Since the first release in 2001, many individuals and -organizations have contributed bug fixes and new features. There have -been over 140 releases in the decade since the first publicly released -version; the :ref:`release notes <relnotes>` and news archive have -more information about the release history. - -In addition to C++ you can use botan from Python or Perl, though the -current bindings only wrap portions of the library. - -See the :ref:`faq` for a list of common questions and answers. - -If you need help or have questions, send a mail to the `development -mailing list -<http://lists.randombit.net/mailman/listinfo/botan-devel/>`_. -"Philosophical" bug reports, announcements of programs using the -library, and related topics are also welcome. - -If you find what you believe to be a bug, please file a ticket in -`Bugzilla <http://bugs.randombit.net/>`_. - -A useful reference while reading this manual is the `Doxygen -documentation <http://botan.randombit.net/doxygen>`_. - -Recommended Reading ---------------------------------- - -It's a very good idea if you have some knowledge of cryptography -*before* trying to use the library. This is an area where it is very -easy to make mistakes, and where things are often subtle and/or -counterintuitive. Obviously the library tries to provide things at -a high level precisely to minimize the number of ways things can go -wrong, but naive use will almost certainly not result in a secure -system. - -Especially recommended are: - - - *Cryptography Engineering* - Niels Ferguson, Bruce Schneier, and Tadayoshi Kohno - - - *Security Engineering -- A Guide to Building Dependable Distributed Systems* - Ross Anderson - - - *Handbook of Applied Cryptography* Alfred J. Menezes, Paul C. Van - Oorschot, and Scott A. Vanstone (available online at - http://www.cacr.math.uwaterloo.ca/hac/) diff --git a/doc/old/tutorial.tex b/doc/old/tutorial.tex deleted file mode 100644 index f220d765a..000000000 --- a/doc/old/tutorial.tex +++ /dev/null @@ -1,880 +0,0 @@ -\documentclass{article} - -\setlength{\textwidth}{6.5in} % 1 inch side margins -\setlength{\textheight}{9in} % ~1 inch top and bottom margins - -\setlength{\headheight}{0in} -\setlength{\topmargin}{0in} -\setlength{\headsep}{0in} - -\setlength{\oddsidemargin}{0in} -\setlength{\evensidemargin}{0in} - -\title{\textbf{Botan Tutorial}} -\author{Jack Lloyd \\ - \texttt{[email protected]}} -\date{2009/07/08} - -\newcommand{\filename}[1]{\texttt{#1}} -\newcommand{\manpage}[2]{\texttt{#1}(#2)} - -\newcommand{\macro}[1]{\texttt{#1}} - -\newcommand{\function}[1]{\textbf{#1}} -\newcommand{\type}[1]{\texttt{#1}} -\renewcommand{\arg}[1]{\textsl{#1}} -\newcommand{\variable}[1]{\textsl{#1}} - -\begin{document} - -\maketitle - -\tableofcontents - -\parskip=5pt -\pagebreak - -\section{Introduction} - -This document essentially sets up various simple scenarios and then -shows how to solve the problems using Botan. It's fairly simple, and -doesn't cover many of the available APIs and algorithms, especially -the more obscure or unusual ones. It is a supplement to the API -documentation and the example applications, which are included in the -distribution. - -To quote the Perl man page: '``There's more than one way to do it.'' -Divining how many more is left as an exercise to the reader.' - -This is \emph{not} a general introduction to cryptography, and most simple -terms and ideas are not explained in any great detail. - -Finally, most of the code shown in this tutorial has not been tested, it was -just written down from memory. If you find errors, please let me know. - -\section{Initializing the Library} - -The first step to using Botan is to create a \type{LibraryInitializer} object, -which handles creating various internal structures, and also destroying them at -shutdown. Essentially: - -\begin{verbatim} -#include <botan/botan.h> -/* include other headers here */ - -int main() - { - LibraryInitializer init; - /* now do stuff */ - return 0; - } -\end{verbatim} - -\section{Hashing a File} - -\section{Symmetric Cryptography} - -\subsection{Encryption with a passphrase} - -Probably the most common crypto problem is encrypting a file (or some data that -is in-memory) using a passphrase. There are a million ways to do this, most of -them bad. In particular, you have to protect against weak passphrases, -people reusing a passphrase many times, accidental and deliberate modification, -and a dozen other potential problems. - -We'll start with a simple method that is commonly used, and show the problems -that can arise. Each subsequent solution will modify the previous one to -prevent one or more common problems, until we arrive at a good version. - -In these examples, we'll always use Serpent in Cipher-Block Chaining -(CBC) mode. Whenever we need a hash function, we'll use SHA-256, since -that is a common and well-known hash that is thought to be secure. - -In all examples, we choose to derive the Initialization Vector (IV) from the -passphrase. Another (probably more common) alternative is to generate the IV -randomly and include it at the beginning of the message. Either way is -acceptable, and can be secure. The method used here was chosen to make for more -interesting examples (because it's harder to get right), and may not be an -appropriate choice for some environments. - -First, some notation. The passphrase is stored as a \type{std::string} named -\variable{passphrase}. The input and output files (\variable{infile} and -\variable{outfile}) are of types \type{std::ifstream} and \type{std::ofstream} -(respectively). - -\subsubsection{First try} - -We hash the passphrase with SHA-256, and use the resulting hash to key -Serpent. To generate the IV, we prepend a single '0' character to the -passphrase, hash it, and truncate it to 16 bytes (which is Serpent's -block size). - -\begin{verbatim} - HashFunction* hash = get_hash("SHA-256"); - - SymmetricKey key = hash->process(passphrase); - SecureVector<byte> raw_iv = hash->process('0' + passphrase); - InitializationVector iv(raw_iv, 16); - - Pipe pipe(get_cipher("Serpent/CBC/PKCS7", key, iv, ENCRYPTION)); - - pipe.start_msg(); - infile >> pipe; - pipe.end_msg(); - outfile << pipe; -\end{verbatim} - -\subsubsection{Problem 1: Buffering} - -There is a problem with the above code, if the input file is fairly large as -compared to available memory. Specifically, all the encrypted data is stored -in memory, and then flushed to \variable{outfile} in a single go at the very -end. If the input file is big (say, a gigabyte), this will be most problematic. - -The solution is to use a \type{DataSink} to handle the output for us (writing -to \arg{outfile} will be implicit with writing to the \type{Pipe}). We can do -this by replacing the last few lines with: - -\begin{verbatim} - Pipe pipe(get_cipher("Serpent/CBC/PKCS7", key, iv, ENCRYPTION), - new DataSink_Stream(outfile)); - - pipe.start_msg(); - infile >> pipe; - pipe.end_msg(); -\end{verbatim} - -\subsubsection{Problem 2: Deriving the key and IV} - -Hash functions like SHA-256 are deterministic; if the same passphrase -is supplied twice, then the key (and in our case, the IV) will be the -same. This is very dangerous, and could easily open the whole system -up to attack. What we need to do is introduce a salt (or nonce) into -the generation of the key from the passphrase. This will mean that the -key will not be the same each time the same passphrase is typed in by -a user. - -There is another problem with using a bare hash function to derive -keys. While it's inconceivable (based on our current understanding of -thermodynamics and theories of computation) that an attacker could -brute-force a 256-bit key, it would be fairly simple for them to -compute the SHA-256 hashes of various common passwords ('password', -the name of the dog, the significant other's middle name, favorite -sports team) and try those as keys. So we want to slow the attacker -down if we can, and an easy way to do that is to iterate the hash -function a bunch of times (say, 1024 to 4096 times). This will involve -only a small amount of effort for a legitimate user (since they only -have to compute the hashes once, when they type in their passphrase), -but an attacker, trying out a large list of potential passphrases, -will be seriously annoyed (and slowed down) by this. - -In this iteration of the example, we'll kill these two birds with one -stone, and derive the key from the passphrase using a PBKDF -(Password-Based Key Derivation Function). In this example, we use -PBKDF2 with Hash Message Authentication Code (HMAC(SHA-256)), which is -specified in PKCS \#5. We replace the first four lines of code from -the first example with: - -\begin{verbatim} - PBKDF* pbkdf = get_pbkdf("PBKDF2(SHA-256)"); - // hard-coded iteration count for simplicity; should be sufficient - pbkdf->set_iterations(10000); - // 8 octets == 64-bit salt; again, good enough - pbkdf->new_random_salt(8); - SecureVector<byte> the_salt = pbkdf->current_salt(); - - // 48 octets == 32 for key + 16 for IV - SecureVector<byte> key_and_IV = pbkdf->derive_key(48, passphrase).bits_of(); - - SymmetricKey key(key_and_IV, 32); - InitializationVector iv(key_and_IV + 32, 16); -\end{verbatim} - -To complete the example, we have to remember to write out the salt (stored in -\variable{the\_salt}) at the beginning of the file. The receiving side needs to -know this value in order to restore it (by calling the \variable{pbkdf} object's -\function{change\_salt} function) so it can derive the same key and IV from the -passphrase. - -\subsubsection{Problem 3: Protecting against modification} - -As it is, an attacker can undetectably alter the message while it is -in transit. It is vital to remember that encryption does not imply -authentication (except when using special modes that are specifically -designed to provide authentication along with encryption, like OCB and -EAX). For this purpose, we will append a message authentication code -to the encrypted message. Specifically, we will generate an extra 256 -bits of key data, and use it to key the ``HMAC(SHA-256)'' MAC -function. We don't want to have the MAC and the cipher to share the -same key; that is very much a no-no. - -\begin{verbatim} - // 80 octets == 32 for cipher key + 16 for IV + 32 for hmac key - SecureVector<byte> keys_and_IV = pbkdf->derive_key(80, passphrase); - - SymmetricKey key(keys_and_IV, 32); - InitializationVector iv(keys_and_IV + 32, 16); - SymmetricKey mac_key(keys_and_IV + 32 + 16, 32); - - Pipe pipe(new Fork( - new Chain( - get_cipher("Serpent/CBC/PKCS7", key, iv, ENCRYPTION), - new DataSink_Stream(outfile) - ), - new MAC_Filter("HMAC(SHA-256)", mac_key) - ) - ); - - pipe.start_msg(); - infile >> pipe; - pipe.end_msg(); - - // now read the MAC from message #2. Message numbers start from 0 - SecureVector<byte> hmac = pipe.read_all(1); - outfile.write((const char*)&hmac[0], hmac.size()); -\end{verbatim} - -The receiver can check the size of the file (in bytes), and since it knows how -long the MAC is, can figure out how many bytes of ciphertext there are. Then it -reads in that many bytes, sending them to a Serpent/CBC decryption object -(which could be obtained by calling \verb|get_cipher| with an argument of -\type{DECRYPTION} instead of \type{ENCRYPTION}), and storing the final bytes to -authenticate the message with. - -\subsubsection{Problem 4: Cleaning up the key generation} - -The method used to derive the keys and IV is rather inelegant, and it would be -nice to clean that up a bit, algorithmically speaking. A nice solution for this -is to generate a master key from the passphrase and salt, and then generate the -two keys and the IV (the cryptovariables) from that. - -Starting from the master key, we derive the cryptovariables using a KDF -algorithm, which is designed, among other things, to ``separate'' keys so that -we can derive several different keys from the single master key. For this -purpose, we will use KDF2, which is a generally useful KDF function (defined in -IEEE 1363a, among other standards). The use of different labels (``cipher -key'', etc) makes sure that each of the three derived variables will have -different values. - -\begin{verbatim} - PBKDF* pbkdf = get_pbkdf("PBKDF2(SHA-256)"); - // hard-coded iteration count for simplicity; should be sufficient - pbkdf->set_iterations(10000); - // 8 octet == 64-bit salt; again, good enough - pbkdf->new_random_salt(8); - // store the salt so we can write it to a file later - SecureVector<byte> the_salt = pbkdf->current_salt(); - - SymmetricKey master_key = pbkdf->derive_key(48, passphrase); - - KDF* kdf = get_kdf("KDF2(SHA-256)"); - - SymmetricKey key = kdf->derive_key(32, master_key, "cipher key"); - SymmetricKey mac_key = kdf->derive_key(32, master_key, "hmac key"); - InitializationVector iv = kdf->derive_key(16, master_key, "cipher iv"); -\end{verbatim} - -\subsubsection{Final version} - -Here is the final version of the encryption code, with all the changes we've -made: - -\begin{verbatim} - PBKDF* pbkdf = get_pbkdf("PBKDF2(SHA-256)"); - pbkdf->set_iterations(10000); - pbkdf->new_random_salt(8); - SecureVector<byte> the_salt = pbkdf->current_salt(); - - SymmetricKey master_key = pbkdf->derive_key(48, passphrase); - - KDF* kdf = get_kdf("KDF2(SHA-256)"); - - SymmetricKey key = kdf->derive_key(32, master_key, "cipher key"); - SymmetricKey mac_key = kdf->derive_key(32, masterkey, "hmac key"); - InitializationVector iv = kdf->derive_key(16, masterkey, "cipher iv"); - - Pipe pipe(new Fork( - new Chain( - get_cipher("Serpent/CBC/PKCS7", key, iv, ENCRYPTION), - new DataSink_Stream(outfile) - ), - new MAC_Filter("HMAC(SHA-256)", mac_key) - ) - ); - - outfile.write((const char*)&the_salt[0], the_salt.size()); - - pipe.start_msg(); - infile >> pipe; - pipe.end_msg(); - - SecureVector<byte> hmac = pipe.read_all(1); - outfile.write((const char*)&hmac[0], hmac.size()); -\end{verbatim} - -\subsubsection{Another buffering technique} - -Sometimes the use of \type{DataSink\_Stream} is not practical for whatever -reason. In this case, an alternate buffering mechanism might be useful. Here is -some code which will write all the processed data as quickly as possible, so -that memory pressure is reduced in the case of large inputs. - -\begin{verbatim} - pipe.start_msg(); - SecureBuffer<byte, 1024> buffer; - while(infile.good()) - { - infile.read((char*)&buffer[0], buffer.size()); - u32bit got_from_infile = infile.gcount(); - pipe.write(buffer, got_from_infile); - - if(infile.eof()) - pipe.end_msg(); - - while(pipe.remaining() > 0) - { - u32bit buffered = pipe.read(buffer, buffer.size()); - outfile.write((const char*)&buffer[0], buffered); - } - } - if(infile.bad() || (infile.fail() && !infile.eof())) - throw Some_Exception(); -\end{verbatim} - -\pagebreak - -\subsection{Authentication} - -After doing the encryption routines, doing message authentication keyed off a -passphrase is not very difficult. In fact it's much easier than the encryption -case, for the following reasons: a) we only need one key, and b) we don't have -to store anything, so all the input can be done in a single step without -worrying about it taking up a lot of memory if the input file is large. - -In this case, we'll hex-encode the salt and the MAC, and output them both to -standard output (the salt followed by the MAC). - -\begin{verbatim} - PBKDF* pbkdf = get_pbkdf("PBKDF2(SHA-256)"); - pbkdf->set_iterations(10000); - pbkdf->new_random_salt(8); - OctetString the_salt = pbkdf->current_salt(); - - SymmetricKey hmac_key = pbkdf->derive_key(32, passphrase); - - Pipe pipe(new MAC_Filter("HMAC(SHA-256)", mac_key), - new Hex_Encoder - ); - - std::cout << the_salt.to_string(); // hex encoded - - pipe.start_msg(); - infile >> pipe; - pipe.end_msg(); - std::cout << pipe.read_all_as_string() << std::endl; -\end{verbatim} - -\subsection{User Authentication} - -Doing user authentication off a shared passphrase is fairly easy. Essentially, -a challenge-response protocol is used - the server sends a random challenge, -and the client responds with an appropriate response to the challenge. The idea -is that only someone who knows the passphrase can generate or check to see if a -response is valid. - -Let's say we use 160-bit (20 byte) challenges, which seems fairly -reasonable. We can create this challenge using the global random -number generator (RNG): - -\begin{verbatim} - byte challenge[20]; - Global_RNG::randomize(challenge, sizeof(challenge), Nonce); - // send challenge to client -\end{verbatim} - -After reading the challenge, the client generates a response based on -the challenge and the passphrase. In this case, we will do it by -repeatedly hashing the challenge, the passphrase, and (if applicable) -the previous digest. We iterate this construction 10000 times, to make -brute force attacks on the passphrase hard to do. Since we are already -using 160-bit challenges, a 160-bit response seems warranted, so we'll -use SHA-1. - -\begin{verbatim} - HashFunction* hash = get_hash("SHA-1"); - SecureVector<byte> digest; - for(u32bit j = 0; j != 10000; j++) - { - hash->update(digest, digest.size()); - hash->update(passphrase); - hash->update(challenge, challenge.size()); - digest = hash->final(); - } - delete hash; - // send value of digest to the server -\end{verbatim} - -Upon receiving the response from the client, the server computes what the -response should have been based on the challenge it sent out, and the -passphrase. If the two responses match, the client is authenticated. -Otherwise, it is not. - -An alternate method is to use PBKDF2 again, using the challenge as the salt. In -this case, the response could (for example) be the hash of the key produced by -PBKDF2. There is no reason to have an explicit iteration loop, as PBKDF2 is -designed to prevent dictionary attacks (assuming PBKDF2 is set up for a large -iteration count internally). - -\pagebreak - -\section{Public Key Cryptography} - -\subsection{Basic Operations} - -In this section, we'll assume we have a \type{X509\_PublicKey*} named -\arg{pubkey}, and, if necessary, a private key type (a -\type{PKCS8\_PrivateKey*}) named \arg{privkey}. A description of these types, -how to create them, and related details appears later in this tutorial. In this -section, we will use various functions that are defined in -\filename{look\_pk.h} -- you will have to include this header explicitly. - -\subsubsection{Encryption} - -Basically, pick an encoding method, create a \type{PK\_Encryptor} (with -\function{get\_pk\_encryptor}()), and use it. But first we have to make sure -the public key can actually be used for public key encryption. For encryption -(and decryption), the key could be RSA, ElGamal, or (in future versions) some -other public key encryption scheme, like Rabin or an elliptic curve scheme. - -\begin{verbatim} - PK_Encrypting_Key* key = dynamic_cast<PK_Encrypting_Key*>(pubkey); - if(!key) - error(); - PK_Encryptor* enc = get_pk_encryptor(*key, "EME1(SHA-256)"); - - byte msg[] = { /* ... */ }; - - // will also accept a SecureVector<byte> as input - SecureVector<byte> ciphertext = enc->encrypt(msg, sizeof(msg)); -\end{verbatim} - -\subsubsection{Decryption} - -This is essentially the same as the encryption operation, but using a private -key instead. One major difference is that the decryption operation can fail due -to the fact that the ciphertext was invalid (most common padding schemes, such -as ``EME1(SHA-256)'', include various pieces of redundancy, which are checked -after decryption). - -\begin{verbatim} - PK_Decrypting_Key* key = dynamic_cast<PK_Decrypting_Key*>(privkey); - if(!key) - error(); - PK_Decryptor* dec = get_pk_decryptor(*key, "EME1(SHA-256)"); - - byte msg[] = { /* ... */ }; - - SecureVector<byte> plaintext; - - try { - // will also accept a SecureVector<byte> as input - plaintext = dec->decrypt(msg, sizeof(msg)); - } - catch(Decoding_Error) - { - /* the ciphertext was invalid */ - } -\end{verbatim} - -\subsubsection{Signature Generation} - -There is one difficulty with signature generation that does not occur with -encryption or decryption. Specifically, there are various padding methods which -can be useful for different signature algorithms, and not all are appropriate -for all signature schemes. The following table breaks down what algorithms -support which encodings: - -\begin{tabular}{|c|c|c|} \hline -Signature Algorithm & Usable Encoding Methods & Preferred Encoding(s) \\ \hline -DSA / NR & EMSA1 & EMSA1 \\ \hline -RSA & EMSA1, EMSA2, EMSA3, EMSA4 & EMSA3, EMSA4 \\ \hline -Rabin-Williams & EMSA2, EMSA4 & EMSA2, EMSA4 \\ \hline -\end{tabular} - -For new applications, use EMSA4 with both RSA and Rabin-Williams, as it is -significantly more secure than the alternatives. However, most current -applications/libraries only support EMSA2 with Rabin-Williams and EMSA3 with -RSA. Given this, you may be forced to use less secure encoding methods for the -near future. In these examples, we punt on the problem, and hard-code using -EMSA1 with SHA-256. - -\begin{verbatim} - Public_Key* key = /* loaded or generated somehow */ - PK_Signer* signer = get_pk_signer(*key, "EMSA1(SHA-256)"); - - byte msg[] = { /* ... */ }; - - /* - You can also repeatedly call update(const byte[], u32bit), followed - by a call to signature(), which will return the final signature of - all the data that was passed through update(). sign_message() is - just a stub that calls update() once, and returns the value of - signature(). - */ - - SecureVector<byte> signature = signer->sign_message(msg, sizeof(msg)); -\end{verbatim} - -\pagebreak - -\subsubsection{Signature Verification} - -In addition to all the problems with choosing the correct padding method, -there is yet another complication with verifying a signature. Namely, there are -two varieties of signature algorithms - those providing message recovery (that -is, the value that was signed can be directly recovered by someone verifying -the signature), and those without message recovery (the verify operation simply -returns if the signature was valid, without telling you exactly what was -signed). This leads to two slightly different implementations of the -verification operation, which user code has to work with. As you can see -however, the implementation is still not at all difficult. - -\begin{verbatim} - PK_Verifier* verifier = 0; - - PK_Verifying_with_MR_Key* key1 = - dynamic_cast<PK_Verifying_with_MR_Key*>(pubkey); - PK_Verifying_wo_MR_Key* key2 = - dynamic_cast<PK_Verifying_wo_MR_Key*>(pubkey); - - if(key1) - verifier = get_pk_verifier(*key1, "EMSA1(SHA-256)"); - else if(key2) - verifier = get_pk_verifier(*key2, "EMSA1(SHA-256)"); - else - error(); - - byte msg[] = { /* ... */ }; - byte sig[] = { /* ... */ }; - - /* - Like PK_Signer, you can also do repeated calls to - void update(const byte some_data[], u32bit length) - followed by a call to - bool check_signature(const byte the_sig[], u32bit length) - which will return true (valid signature) or false (bad signature). - The function verify_message() is a simple wrapper around update() and - check_signature(). - - */ - bool is_valid = verifier->verify_message(msg, sizeof(msg), sig, sizeof(sig)); -\end{verbatim} - -\subsubsection{Key Agreement} - -WRITEME - -\pagebreak - -\subsection{Working with Keys} - -\subsubsection{Reading Public Keys (X.509 format)} - -There are two separate ways to read X.509 public keys. Remember that the X.509 -public keys are simply that: public keys. There is no associated information -(such as the owner of that key) included with the public key itself. If you -need that kind of information, you'll need to use X.509 certificates. - -However, there are surely times when a simple public key is sufficient. The -most obvious is when the key is implicitly trusted, for example if access -and/or modification of it is controlled by something else (like filesystem -ACLs). In other cases, it is a perfectly reasonable proposition to use them -over the network as an anonymous key exchange mechanism. This is, admittedly, -vulnerable to man-in-the-middle attacks, but it's simple enough that it's hard -to mess up (see, for example, Peter Guttman's paper ``Lessons Learned in -Implementing and Deploying Crypto Software'' in Usenix '02). - -The way to load a key is basically to set up a \type{DataSource} and then call -\function{X509::load\_key}, which will return a \type{X509\_PublicKey*}. For -example: - -\begin{verbatim} - DataSource_Stream somefile("somefile.pem"); // has 3 public keys - X509_PublicKey* key1 = X509::load_key(somefile); - X509_PublicKey* key2 = X509::load_key(somefile); - X509_PublicKey* key3 = X509::load_key(somefile); - // Now we have them all loaded. Huzah! -\end{verbatim} - -At this point you can use \function{dynamic\_cast} to find the operations the -key supports (by seeing if a cast to \type{PK\_Encrypting\_Key}, -\type{PK\_Verifying\_with\_MR\_Key}, or \type{PK\_Verifying\_wo\_MR\_Key} -succeeds). - -There is a variant of \function{X509::load\_key} (and of -\function{PKCS8::load\_key}, described in the next section) which take a -filename (as a \type{std::string}). These are just convenience functions which -create the appropriate \type{DataSource} for you and call the main -\function{X509::load\_key}. - -\subsubsection{Reading Private Keys (PKCS \#8 format)} - -This is very similar to reading raw public keys, with the difference that the -key may be encrypted with a user passphrase: - -\begin{verbatim} - // rng is a RandomNumberGenerator, like AutoSeeded_RNG - - DataSource_Stream somefile("somefile"); - std::string a_passphrase = /* get from the user */ - PKCS8_PrivateKey* key = PKCS8::load_key(somefile, rng, a_passphrase); -\end{verbatim} - -You can, by the way, convert a \type{PKCS8\_PrivateKey} to a -\type{X509\_PublicKey} simply by casting it (with \function{dynamic\_cast}), as -the private key type is derived from \type{X509\_PublicKey}. As with -\type{X509\_PublicKey}, you can use \function{dynamic\_cast} to figure out what -operations the private key is capable of; in particular, you can attempt to -cast it to \type{PK\_Decrypting\_Key}, \type{PK\_Signing\_Key}, or -\type{PK\_Key\_Agreement\_Key}. - -Sometimes you can get away with having a static passphrase passed to -\function{load\_key}. Typically, however, you'll have to do some user -interaction to get the appropriate passphrase. In that case you'll want to use -the \type{UI} related interface, which is fully described in the API -documentation. - -\subsubsection{Generating New Private Keys} - -Generate a new private key is the one operation which requires you to -explicitly name the type of key you are working with. There are (currently) two -kinds of public key algorithms in Botan: ones based on the integer -factorization (IF) problem (RSA and Rabin-Williams), and ones based on the -discrete logarithm (DL) problem (DSA, Diffie-Hellman, Nyberg-Rueppel, and -ElGamal). Since discrete logarithm parameters (primes and generators) can be -shared among many keys, there is the notion of these being a combined type -(called \type{DL\_Group}). - -To create a new DL-based private key, simply pass a desired \type{DL\_Group} to -the constructor of the private key - a new public/private key pair will be -generated. Since in IF-based algorithms, the modulus used isn't shared by other -keys, we don't use this notion. You can create a new key by passing in a -\type{u32bit} telling how long (in bits) the key should be. - -There are quite a few ways to get a \type{DL\_Group} object. The best is to use -the function \function{get\_dl\_group}, which takes a string naming a group; it -will either return that group, if it knows about it, or throw an -exception. Names it knows about include ``IETF-n'' where n is 768, 1024, 1536, -2048, 3072, or 4096, and ``DSA-n'', where n is 512, 768, or 1024. The IETF -groups are the ones specified for use with IPSec, and the DSA ones are the -default DSA parameters specified by Java's JCE. For DSA and Nyberg-Rueppel, use -the ``DSA-n'' groups, and for Diffie-Hellman and ElGamal, use the ``IETF-n'' -groups. - -You can also generate a new random group. This is not recommend, because it is -very slow, particularly for ``safe'' primes, which are needed for -Diffie-Hellman and ElGamal. - -Some examples: - -\begin{verbatim} - RSA_PrivateKey rsa1(512); // 512-bit RSA key - RSA_PrivateKey rsa2(2048); // 2048-bit RSA key - - RW_PrivateKey rw1(1024); // 1024-bit Rabin-Williams key - RW_PrivateKey rw2(1536); // 1536-bit Rabin-Williams key - - DSA_PrivateKey dsa(get_dl_group("DSA-512")); // 512-bit DSA key - DH_PrivateKey dh(get_dl_group("IETF-4096")); // 4096-bit DH key - NR_PrivateKey nr(get_dl_group("DSA-1024")); // 1024-bit NR key - ElGamal_PrivateKey elg(get_dl_group("IETF-1536")); // 1536-bit ElGamal key -\end{verbatim} - -To export your newly created private key, use the PKCS \#8 routines in -\filename{pkcs8.h}: - -\begin{verbatim} - std::string a_passphrase = /* get from the user */ - std::string the_key = PKCS8::PEM_encode(rsa2, a_passphrase); -\end{verbatim} - -You can read the key back in using \function{PKCS8::load\_key}, described in -the section ``Reading Private Keys (PKCS \#8 format)'', above. Unfortunately, -this only works with keys that have an assigned algorithm identifier and -standardized format. Currently this is only the RSA, DSA, DH, and ElGamal -algorithms, though RW and NR keys can also be imported and exported by -assigning them an OID (this can be done either through a configuration file, or -by calling the function \function{OIDS::add\_oid} in \filename{oids.h}). Be -aware that the OID and format for ElGamal keys is not exactly standard, but -there does exist at least one other crypto library which will accept the -format. - -The raw public can be exported using: - -\begin{verbatim} - std::string the_public_key = X509::PEM_encode(rsa2); -\end{verbatim} - -\pagebreak - -\section{X.509v3 Certificates} - -Using certificates is rather complicated, so only the very basic mechanisms are -going to be covered here. The section ``Setting up a CA'' goes into reasonable -detail about CRLs and certificate requests, but there is a lot that isn't -covered (else this section would get quite long and complicated). - -\subsection{Importing and Exporting Certificates} - -Importing and exporting X.509 certificates is easy. Simply call the constructor -with either a \type{DataSource\&}, or the name of a file: - -\begin{verbatim} - X509_Certificate cert1("cert1.pem"); - - /* This file contains two certificates, concatenated */ - DataSource_Stream in("certs2_and_3.pem"); - - X509_Certificate cert2(in); // read the first cert - X509_Certificate cert3(in); // read the second cert -\end{verbatim} - -Exporting the certificate is a simple matter of calling the member function -\function{PEM\_encode}(), which returns a \type{std::string} containing the -certificate in PEM encoding. - -\begin{verbatim} - std::cout << cert3.PEM_encode(); - some_ostream_object << cert1.PEM_encode(); - std::string cert2_str = cert2.PEM_encode(); -\end{verbatim} - -\subsection{Verifying Certificates} - -Verifying a certificate requires that we build up a chain of trust, starting -from the root (usually a commercial CA), down through some number of -intermediate CAs, and finally reaching the actual certificate in -question. Thus, to verify, we actually have to have all those certificates -on hand (or at the very least, know where we can get the ones we need). - -The class which handles both storing certificates, and verifying them, is -called \type{X509\_Store}. We'll start by assuming that we have all the -certificates we need, and just want to verify a cert. This is done by calling -the member function \function{validate\_cert}, which takes the -\type{X509\_Certificate} in question, and an optional argument of type -\type{Cert\_Usage} (which is ignored here; read the section in the API doc -titled ``Verifying Certificates for information). It returns an enum; -\type{X509\_Code}, which, for most purposes, is either \type{VERIFIED}, or -something else (which specifies what circumstance caused the certificate to be -considered invalid). Really, that's it. - -Now, how to let \type{X509\_Store} know about all those certificates and CRLs -we have lying around? The simplest method is to add them directly, using the -functions \function{add\_cert}, \function{add\_certs}, -\function{add\_trusted\_certs}, and \function{add\_crl}; for details, consult -the API doc or read the \filename{x509stor.h} header. There is also a much more -elegant and powerful method: \type{Certificate\_Store}s. A certificate store -refers to an object that knows how to retrieve certificates from some external -source (a file, an LDAP directory, a HTTP server, a SQL database, or anything -else). By calling the function \function{add\_new\_certstore}, you can register -a new certificate store, which \type{X509\_Store} will use to find certificates -it needs. Thus, you can get away with only adding whichever root CA cert(s) you -want to use, letting some online source handle the storage of all intermediate -X.509 certificates. The API documentation has a more complete discussion of -\type{Certificate\_Store}. - -\subsection{Setting up a CA} - -WRITEME - -\pagebreak - -\section{Special Topics} - -This chapter is for subjects that don't really fit into the API documentation -or into other chapters of the tutorial. - -\subsection{GUIs} - -There is nothing particularly special about using Botan in a GUI-based -application. However there are a few tricky spots, as well as a few ways to -take advantage of an event-based application. - -\subsubsection{Initialization} - -Generally you will create the \type{LibraryInitializer} somewhere in -\texttt{main}, before entering the event loop. One problem is that some GUI -libraries take over \texttt{main} and drop you right into the event loop; the -question then is how to initialize the library? The simplest way is probably to -have a static flag that marks if you have already initialized the library or -not. When you enter the event loop, check to see if this flag has not been set, -and if so, initialize the library using the function-based initializers. Using -\type{LibraryInitializer} obviously won't work in this case, since it would be -destroyed as soon as the current event handler finished. You then deinitialize -the library whenever your application is signaled to quit. - -\subsubsection{Interacting With the Library} - -In the simple case, the user will do stuff asynchronously, and then in response -your code will do things like encrypt a file or whatever, which can all be done -synchronously, since the data is right there for you. An application doing -something like this is basically going to look exactly like a command line -application that uses Botan, the only major difference being that the calls to -the library are inside event handlers. - -Much harder is something like an SSH client, where you're acting as a layer -between two asynchronous things (the user and the network). This actually isn't -restricted to GUIs at all (text-mode SSH clients have to deal with most of the -same problems), but it is probably more common with a GUI app. The following -discussion is fairly vague, but hopefully somewhat useful. - -There are a few facilities in Botan that are primarily designed to be used by -applications based on an event loop. See the section ``User Interfaces'' in the -main API doc for details. - -\subsubsection{Entropy} - -One nice advantage of using a GUI is opening a new method of gathering entropy -for the library. This is especially handy on Windows, where the available -sources of entropy are pretty questionable. In many versions, -\texttt{CryptGenRandom} is really rather poor, and the Toolhelp functions may -not provide much data on a small system (such as a handheld). For example, in -GTK+, you can use the following callback to get information about mouse -movements: - -\begin{verbatim} -static gint add_entropy(GtkWidget* widget, GdkEventMotion* event) - { - if(event) - Global_RNG::add_entropy(event, sizeof(GdkEventMotion)); - return FALSE; - } -\end{verbatim} - -And then register it with your main GTK window (presumably named -\variable{window}) as follows: - -\begin{verbatim} -gtk_signal_connect(GTK_OBJECT(window), "motion_notify_event", - GTK_SIGNAL_FUNC(add_entropy), NULL); - -gtk_widget_set_events(window, GDK_POINTER_MOTION_MASK); -\end{verbatim} - -Even though we're catching all mouse movements, and hashing the results into -the entropy pool, this doesn't use up more than a few percent of even a -relatively slow desktop CPU. Note that in the case of using X over a network, -catching all mouse events would cause large amounts of X traffic over the -network, which might make your application slow, or even unusable (I haven't -tried it, though). - -This could be made nicer if the collection function did something like -calculating deltas between each run, storing them into a buffer, and then when -enough of them have been added, hashing them and send them all to the PRNG in -one shot. This would not only reduce load, but also prevent the PRNG from -overestimating the amount of entropy it's getting, since its estimates don't -(can't) take history into account. For example, you could move the mouse back -and forth one pixel, and the PRNG would think it was getting a full load of -entropy each time, when actually it was getting (at best) a bit or two. - -\end{document} diff --git a/doc/pgpkeys.txt b/doc/pgpkey.txt index 1d2f3debc..1d2f3debc 100644 --- a/doc/pgpkeys.txt +++ b/doc/pgpkey.txt diff --git a/doc/pubkey.txt b/doc/pubkey.txt index f12aae0b5..6ff016038 100644 --- a/doc/pubkey.txt +++ b/doc/pubkey.txt @@ -1,60 +1,55 @@ -.. _public_key_crypto: - Public Key Cryptography ================================= -Public key cryptography (also called assymmetric cryptography) is a -collection of techniques allowing for encryption, signatures, and key -agreement. +Public key cryptography (also called assymmetric cryptography) is a collection +of techniques allowing for encryption, signatures, and key agreement. Key Objects ---------------------------------------- -Public and private keys are represented by classes ``Public_Key`` and -it's subclass ``Private_Key``. The use of inheritence here means that -a ``Private_Key`` can be converted into a reference to a public key. +Public and private keys are represented by classes ``Public_Key`` and it's +subclass ``Private_Key``. The use of inheritence here means that a +``Private_Key`` can be converted into a reference to a public key. None of the functions on ``Public_Key`` and ``Private_Key`` itself are particularly useful for users of the library, because 'bare' public key -operations are *very insecure*. The only purpose of these functions is -to provide a clean interface that higher level operations can be built -on. So really the only thing you need to know is that when a function -takes a reference to a ``Public_Key``, it can take any public key or -private key, and similiarly for ``Private_Key``. +operations are *very insecure*. The only purpose of these functions is to +provide a clean interface that higher level operations can be built on. So +really the only thing you need to know is that when a function takes a +reference to a ``Public_Key``, it can take any public key or private key, and +similiarly for ``Private_Key``. Types of ``Public_Key`` include ``RSA_PublicKey``, ``DSA_PublicKey``, -``ECDSA_PublicKey``, ``DH_PublicKey``, ``ECDH_PublicKey``, -``RW_PublicKey``, ``NR_PublicKey``,, and ``GOST_3410_PublicKey``. -There are cooresponding ``Private_Key`` classes for each of these -algorithms. +``ECDSA_PublicKey``, ``DH_PublicKey``, ``ECDH_PublicKey``, ``RW_PublicKey``, +``NR_PublicKey``,, and ``GOST_3410_PublicKey``. There are cooresponding +``Private_Key`` classes for each of these algorithms. .. _creating_new_private_keys: Creating New Private Keys ---------------------------------------- -Creating a new private key requires two things: a source of -random numbers (see :ref:`random_number_generators`) and some -algorithm specific parameters that define the *security level* -of the resulting key. For instance, the security level of an RSA -key is (at least in part) defined by the length of the public key -modulus in bits. So to create a new RSA private key, you would call +Creating a new private key requires two things: a source of random numbers +(see :ref:`random_number_generators`) and some algorithm specific parameters +that define the *security level* of the resulting key. For instance, the +security level of an RSA key is (at least in part) defined by the length of +the public key modulus in bits. So to create a new RSA private key, you would +call .. cpp:function:: RSA_PrivateKey::RSA_PrivateKey(RandomNumberGenerator& rng, size_t bits) A constructor that creates a new random RSA private key with a modulus of length *bits*. -Algorithms based on the discrete-logarithm problem uses what is called -a *group*; a group can safely be used with many keys, and for some -operations, like key agreement, the two keys *must* use the same -group. There are currently two kinds of discrete logarithm groups -supported in botan: the integers modulo a prime, represented by -:ref:`dl_group`, and elliptic curves in GF(p), represented by -:ref:`ec_group`. A rough generalization is that the larger the group -is, the more secure the algorithm is, but coorespondingly the slower -the operations will be. +Algorithms based on the discrete-logarithm problem uses what is called a +*group*; a group can safely be used with many keys, and for some operations, +like key agreement, the two keys *must* use the same group. There are +currently two kinds of discrete logarithm groups supported in botan: the +integers modulo a prime, represented by :ref:`dl_group`, and elliptic curves +in GF(p), represented by :ref:`ec_group`. A rough generalization is that the +larger the group is, the more secure the algorithm is, but coorespondingly the +slower the operations will be. Given a ``DL_Group``, you can create new DSA, Diffie-Hellman, and Nyberg-Rueppel key pairs with @@ -71,12 +66,11 @@ Nyberg-Rueppel key pairs with .. cpp:function:: ElGamal_PrivateKey::ElGamal_PrivateKey(RandomNumberGenerator& rng, \ const DL_Group& group, const BigInt& x = 0) - The optional *x* parameter to each of these contructors is a private - key value. This allows you to create keys where the private key is - formed by some special technique; for instance you can use the hash - of a password (see :ref:`pbkdf` for how to do that) as a private key - value. Normally, you would leave the value as zero, letting the - class generate a new random key. + The optional *x* parameter to each of these contructors is a private key + value. This allows you to create keys where the private key is formed by + some special technique; for instance you can use the hash of a password (see + :ref:`pbkdf` for how to do that) as a private key value. Normally, you would + leave the value as zero, letting the class generate a new random key. Finally, given an ``EC_Group`` object, you can create a new ECDSA, ECDH, or GOST 34.10-2001 private key with @@ -94,11 +88,10 @@ ECDH, or GOST 34.10-2001 private key with Generating RSA keys ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -This example will generate an RSA key of a specified bitlength, and -put it into a pair of key files. One is the public key in X.509 format -(PEM encoded), the private key is in PKCS #8 format (also PEM -encoded), either encrypted or unencrypted depending on if a password -was given. +This example will generate an RSA key of a specified bitlength, and put it +into a pair of key files. One is the public key in X.509 format (PEM encoded), +the private key is in PKCS #8 format (also PEM encoded), either encrypted or +unencrypted depending on if a password was given. .. literalinclude:: examples/rsa_kgen.cpp @@ -110,15 +103,14 @@ This example generates a 2048 bit DSA key .. literalinclude:: examples/dsa_kgen.cpp - .. _serializing_private_keys: Serializing Private Keys Using PKCS #8 ---------------------------------------- -The standard format for serializing a private key is PKCS #8, the -operations for which are defined in ``pkcs8.h``. It supports both -unencrypted and encrypted storage. +The standard format for serializing a private key is PKCS #8, the operations +for which are defined in ``pkcs8.h``. It supports both unencrypted and +encrypted storage. .. cpp:function:: SecureVector<byte> PKCS8::BER_encode(const Private_Key& key, \ RandomNumberGenerator& rng, const std::string& password, const std::string& pbe_algo = "") @@ -134,23 +126,22 @@ unencrypted and encrypted storage. .. cpp:function:: std::string PKCS8::PEM_encode(const Private_Key& key, \ RandomNumberGenerator& rng, const std::string& pass, const std::string& pbe_algo = "") - This formats the key in the same manner as ``BER_encode``, but - additionally encodes it into a text format with identifying - headers. Using PEM encoding is *highly* recommended for many - reasons, including compatibility with other software, for - transmission over 8-bit unclean channels, because it can be - identified by a human without special tools, and because it - sometimes allows more sane behavior of tools that process the data. + This formats the key in the same manner as ``BER_encode``, but additionally + encodes it into a text format with identifying headers. Using PEM encoding + is *highly* recommended for many reasons, including compatibility with other + software, for transmission over 8-bit unclean channels, because it can be + identified by a human without special tools, and because it sometimes allows + more sane behavior of tools that process the data. Unencrypted serialization is also supported. .. warning:: - In most situations, using unecrypted private key storage is a bad - idea, because anyone can come along and grab the private key without - having to know any passwords or other secrets. Unless you have very - particular security requirements, always use the versions that - encrypt the key based on a passphrase, described above. + In most situations, using unecrypted private key storage is a bad idea, + because anyone can come along and grab the private key without having to + know any passwords or other secrets. Unless you have very particular + security requirements, always use the versions that encrypt the key based on + a passphrase, described above. .. cpp:function:: SecureVector<byte> PKCS8::BER_encode(const Private_Key& key) @@ -176,27 +167,25 @@ decrypt, if necessary) a PKCS #8 private key: .. cpp:function:: Private_Key* PKCS8::load_key(const std::string& filename, \ RandomNumberGenerator& rng, const std::string& passphrase = "") -These functions will return an object allocated key object based on -the data from whatever source it is using (assuming, of course, the -source is in fact storing a representation of a private key, and the -decryption was sucessful). The encoding used (PEM or BER) need not be -specified; the format will be detected automatically. The key is -allocated with ``new``, and should be released with ``delete`` when -you are done with it. The first takes a generic ``DataSource`` that -you have to create - the other is a simple wrapper functions that take -either a filename or a memory buffer and create the appropriate -``DataSource``. - -The versions taking a ``std::string`` attempt to decrypt using the -password given (if the key is encrypted; if it is not, the passphase -value will be ignored). If the passphrase does not decrypt the key, an -exception will be thrown. - -The ones taking a ``User_Interface`` provide a simple callback -interface which makes handling incorrect passphrases and such a bit -simpler. A ``User_Interface`` has very little to do with talking to -users; it's just a way to glue together Botan and whatever user -interface you happen to be using. +These functions will return an object allocated key object based on the data +from whatever source it is using (assuming, of course, the source is in fact +storing a representation of a private key, and the decryption was +sucessful). The encoding used (PEM or BER) need not be specified; the format +will be detected automatically. The key is allocated with ``new``, and should +be released with ``delete`` when you are done with it. The first takes a +generic ``DataSource`` that you have to create - the other is a simple wrapper +functions that take either a filename or a memory buffer and create the +appropriate ``DataSource``. + +The versions taking a ``std::string`` attempt to decrypt using the password +given (if the key is encrypted; if it is not, the passphase value will be +ignored). If the passphrase does not decrypt the key, an exception will be +thrown. + +The ones taking a ``User_Interface`` provide a simple callback interface which +makes handling incorrect passphrases and such a bit simpler. A +``User_Interface`` has very little to do with talking to users; it's just a +way to glue together Botan and whatever user interface you happen to be using. .. note:: @@ -208,28 +197,25 @@ To use ``User_Interface``, derive a subclass and implement: .. cpp:function:: std::string User_Interface::get_passphrase(const std::string& what, \ const std::string& source, UI_Result& result) const - The ``what`` argument specifies what the passphrase is needed for - (for example, PKCS #8 key loading passes ``what`` as "PKCS #8 - private key"). This lets you provide the user with some indication - of *why* your application is asking for a passphrase; feel free to - pass the string through ``gettext(3)`` or moral equivalent for i18n - purposes. Similarly, ``source`` specifies where the data in question - came from, if available (for example, a file name). If the source is - not available for whatever reason, then ``source`` will be an empty - string; be sure to account for this possibility. - - The function returns the passphrase as the return value, and a - status code in ``result`` (either ``OK`` or ``CANCEL_ACTION``). If - ``CANCEL_ACTION`` is returned in ``result``, then the return value - will be ignored, and the caller will take whatever action is - necessary (typically, throwing an exception stating that the - passphrase couldn't be determined). In the specific case of PKCS #8 - key decryption, a ``Decoding_Error`` exception will be thrown; your - UI should assume this can happen, and provide appropriate error - handling (such as putting up a dialog box informing the user of the + The ``what`` argument specifies what the passphrase is needed for (for + example, PKCS #8 key loading passes ``what`` as "PKCS #8 private key"). This + lets you provide the user with some indication of *why* your application is + asking for a passphrase; feel free to pass the string through ``gettext(3)`` + or moral equivalent for i18n purposes. Similarly, ``source`` specifies where + the data in question came from, if available (for example, a file name). If + the source is not available for whatever reason, then ``source`` will be an + empty string; be sure to account for this possibility. + + The function returns the passphrase as the return value, and a status code + in ``result`` (either ``OK`` or ``CANCEL_ACTION``). If ``CANCEL_ACTION`` is + returned in ``result``, then the return value will be ignored, and the + caller will take whatever action is necessary (typically, throwing an + exception stating that the passphrase couldn't be determined). In the + specific case of PKCS #8 key decryption, a ``Decoding_Error`` exception will + be thrown; your UI should assume this can happen, and provide appropriate + error handling (such as putting up a dialog box informing the user of the situation, and canceling the operation in progress). - .. _serializing_public_keys: Serializing Public Keys @@ -256,36 +242,34 @@ To import and export public keys, use: DL_Group ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -As described in :ref:`creating_new_private_keys`, a discrete logarithm -group can be shared among many keys, even keys created by users who do -not trust each other. However, it is necessary to trust the entity who -created the group; that is why organization like NIST use algorithms -which generate groups in a deterministic way such that creating a -bogus group would require breaking some trusted cryptographic -primitive like SHA-2. +As described in :ref:`creating_new_private_keys`, a discrete logarithm group +can be shared among many keys, even keys created by users who do not trust +each other. However, it is necessary to trust the entity who created the +group; that is why organization like NIST use algorithms which generate groups +in a deterministic way such that creating a bogus group would require breaking +some trusted cryptographic primitive like SHA-2. Instantiating a ``DL_Group`` simply requires calling .. cpp:function:: DL_Group::DL_Group(const std::string& name) - The *name* parameter is a specially formatted string that consists - of three things, the type of the group ("modp" or "dsa"), the - creator of the group, and the size of the group in bits, all - delimited by '/' characters. - - Currently all "modp" groups included in botan are ones defined by - the Internet Engineering Task Force, so the provider is "ietf", and - the strings look like "modp/ietf/N" where N can be any of 768, 1024, - 1536, 2048, 3072, 4096, 6144, or 8192. This group type is used - for Diffie-Hellman and ElGamal algorithms. - - The other type, "dsa" is used for DSA and Nyberg-Rueppel keys. They - can also be used with Diffie-Hellman and ElGamal, but this is less - common. The currently available groups are "dsa/jce/N" for N in 512, - 768, or 1024, and "dsa/botan/N" with N being 2048 or 3072. The - "jce" groups are the standard DSA groups used in the Java - Cryptography Extensions, while the "botan" groups were randomly - generated using the FIPS 186-3 algorithm by the library maintainers. + The *name* parameter is a specially formatted string that consists of three + things, the type of the group ("modp" or "dsa"), the creator of the group, + and the size of the group in bits, all delimited by '/' characters. + + Currently all "modp" groups included in botan are ones defined by the + Internet Engineering Task Force, so the provider is "ietf", and the strings + look like "modp/ietf/N" where N can be any of 768, 1024, 1536, 2048, 3072, + 4096, 6144, or 8192. This group type is used for Diffie-Hellman and ElGamal + algorithms. + + The other type, "dsa" is used for DSA and Nyberg-Rueppel keys. They can + also be used with Diffie-Hellman and ElGamal, but this is less common. The + currently available groups are "dsa/jce/N" for N in 512, 768, or 1024, and + "dsa/botan/N" with N being 2048 or 3072. The "jce" groups are the standard + DSA groups used in the Java Cryptography Extensions, while the "botan" + groups were randomly generated using the FIPS 186-3 algorithm by the library + maintainers. You can generate a new random group using @@ -338,26 +322,25 @@ Each public key type has a function .. cpp:function:: bool Public_Key::check_key(RandomNumberGenerator& rng, bool strong) - This function performs a number of algorithm-specific tests that the - key seems to be mathematically valid and consistent, and returns - true if all of the tests pass. + This function performs a number of algorithm-specific tests that the key + seems to be mathematically valid and consistent, and returns true if all of + the tests pass. It does not have anything to do with the validity of the key for any - particular use, nor does it have anything to do with certificates - that link a key (which, after all, is just some numbers) with a user - or other entity. If *strong* is ``true``, then it does "strong" - checking, which includes expensive operations like primality - checking. + particular use, nor does it have anything to do with certificates that link + a key (which, after all, is just some numbers) with a user or other + entity. If *strong* is ``true``, then it does "strong" checking, which + includes expensive operations like primality checking. Encryption --------------------------------- -Safe public key encryption requires the use of a padding scheme which -hides the underlying mathematical properties of the algorithm. -Additionally, they will add randomness, so encrypting the same -plaintext twice produces two different ciphertexts. +Safe public key encryption requires the use of a padding scheme which hides +the underlying mathematical properties of the algorithm. Additionally, they +will add randomness, so encrypting the same plaintext twice produces two +different ciphertexts. -The primary interface for encryption is +The primary interface for encryption is .. cpp:class:: PK_Encryptor @@ -371,30 +354,28 @@ The primary interface for encryption is .. cpp:function:: size_t maximum_input_size() const - Returns the maximum size of the message that can be processed, - in bytes. If you call :cpp:func:`PK_Encryptor::encrypt` with a - value larger than this the operation will fail with an - exception. - -:cpp:class:`PK_Encryptor` is only an interface - to actually encrypt -you have to create an implementation, of which there are currently two -available in the library, :cpp:class:`PK_Encryptor_EME` and -:cpp:class:`DLIES_Encryptor`. DLIES is a standard method (from IEEE -1363) that uses a key agreement technique such as DH or ECDH to -perform message encryption. Normally, public key encryption is done -using algorithms which support it directly, such as RSA or ElGamal; + Returns the maximum size of the message that can be processed, in + bytes. If you call :cpp:func:`PK_Encryptor::encrypt` with a value larger + than this the operation will fail with an exception. + +:cpp:class:`PK_Encryptor` is only an interface - to actually encrypt you have +to create an implementation, of which there are currently two available in the +library, :cpp:class:`PK_Encryptor_EME` and :cpp:class:`DLIES_Encryptor`. DLIES +is a standard method (from IEEE 1363) that uses a key agreement technique such +as DH or ECDH to perform message encryption. Normally, public key encryption +is done using algorithms which support it directly, such as RSA or ElGamal; these use the EME class: .. cpp:class:: PK_Encryptor_EME .. cpp:function:: PK_Encryptor_EME(const Public_Key& key, std::string eme) - With *key* being the key you want to encrypt messages to. The - padding method to use is specified in *eme*. + With *key* being the key you want to encrypt messages to. The padding + method to use is specified in *eme*. - The recommended values for *eme* is "EME1(SHA-1)" or - "EME1(SHA-256)". If you need compatability with protocols using - the PKCS #1 v1.5 standard, you can also use "EME-PKCS1-v1_5". + The recommended values for *eme* is "EME1(SHA-1)" or "EME1(SHA-256)". If + you need compatability with protocols using the PKCS #1 v1.5 standard, + you can also use "EME-PKCS1-v1_5". .. cpp:class:: DLIES_Encryptor @@ -407,10 +388,9 @@ these use the EME class: :ref:`key_derivation_function`) and *mac* is a MessageAuthenticationCode. -The decryption classes are named ``PK_Decryptor``, -``PK_Decryptor_EME``, and ``DLIES_Decryptor``. They are created in the -exact same way, except they take the private key, and the processing -function is named ``decrypt``. +The decryption classes are named ``PK_Decryptor``, ``PK_Decryptor_EME``, and +``DLIES_Decryptor``. They are created in the exact same way, except they take +the private key, and the processing function is named ``decrypt``. Signatures @@ -425,22 +405,22 @@ Signature generation is performed using Signature_Format format = IEEE_1363) Constructs a new signer object for the private key *key* using the - signature format *emsa*. The key must support signature operations. - In the current version of the library, this includes RSA, DSA, - ECDSA, GOST 34.10-2001, Nyberg-Rueppel, and Rabin-Williams. Other - signature schemes may be supported in the future. - - Currently available values for *emsa* include EMSA1, EMSA2, EMSA3, - EMSA4, and Raw. All of them, except Raw, take a parameter naming a - message digest function to hash the message with. The Raw encoding - signs the input directly; if the message is too big, the signing - operation will fail. Raw is not useful except in very specialized - applications. Examples are "EMSA1(SHA-1)" and "EMSA4(SHA-256)". - - For RSA, use EMSA4 (also called PSS) unless you need compatability - with software that uses the older PKCS #1 v1.5 standard, in which - case use EMSA3 (also called "EMSA-PKCS1-v1_5"). For DSA, ECDSA, - GOST 34.10-2001, and Nyberg-Rueppel, you should use EMSA1. + signature format *emsa*. The key must support signature operations. In + the current version of the library, this includes RSA, DSA, ECDSA, GOST + 34.10-2001, Nyberg-Rueppel, and Rabin-Williams. Other signature schemes + may be supported in the future. + + Currently available values for *emsa* include EMSA1, EMSA2, EMSA3, EMSA4, + and Raw. All of them, except Raw, take a parameter naming a message + digest function to hash the message with. The Raw encoding signs the + input directly; if the message is too big, the signing operation will + fail. Raw is not useful except in very specialized applications. Examples + are "EMSA1(SHA-1)" and "EMSA4(SHA-256)". + + For RSA, use EMSA4 (also called PSS) unless you need compatability with + software that uses the older PKCS #1 v1.5 standard, in which case use + EMSA3 (also called "EMSA-PKCS1-v1_5"). For DSA, ECDSA, GOST 34.10-2001, + and Nyberg-Rueppel, you should use EMSA1. The *format* defaults to ``IEEE_1363`` which is the only available format for RSA. For DSA and ECDSA, you can also use diff --git a/doc/ssl.txt b/doc/ssl.txt index 8f2ad3a2a..7b61fa88c 100644 --- a/doc/ssl.txt +++ b/doc/ssl.txt @@ -1,4 +1,6 @@ +.. _ssl_api: + SSL and TLS ======================================== diff --git a/doc/support.txt b/doc/support.txt index a341d5830..288ed8aa0 100644 --- a/doc/support.txt +++ b/doc/support.txt @@ -6,14 +6,14 @@ Commercial support is currently available for Botan from a couple of sources. If you provide services related to Botan, email the development list and your information can be added here. - * `FlexSecure GmbH <http://www.flexsecure.de>`_ offers support for - both Botan and `InSiTo <http://www.flexsecure.eu/insito/>`_ - libraries. Developers from FlexSecure have done extensive work - with Botan in the past, and many new features to Botan have been - implemented and contributed by them. More information at - http://www.flexsecure.eu/insito/support.html +* `FlexSecure GmbH <http://www.flexsecure.de>`_ offers support for + both Botan and `InSiTo <http://www.flexsecure.eu/insito/>`_ + libraries. Developers from FlexSecure have done extensive work + with Botan in the past, and many new features to Botan have been + implemented and contributed by them. More information at + http://www.flexsecure.eu/insito/support.html - * `Jack Lloyd <http://www.randombit.net>`_ can provide services - relating to Botan including performance analysis of application - code using Botan, review of cryptographic use and designs for - security flaws, and implementing new features. +* `Jack Lloyd <http://www.randombit.net>`_ can provide services + relating to Botan including performance analysis of application + code using Botan, review of cryptographic use and designs for + security flaws, and implementing new features. diff --git a/doc/x509.txt b/doc/x509.txt index 05adeaaad..d31a84498 100644 --- a/doc/x509.txt +++ b/doc/x509.txt @@ -5,84 +5,77 @@ Certificate Handling ================================= A certificate is a binding between some identifying information -(called a *subject*) and a public key. This binding is asserted -by a signature on the certificate, which is placed there by some -authority (the *issuer*) that at least claims that it knows the -subject named in the certificate really "owns" the private key -corresponding to the public key in the certificate. +(called a *subject*) and a public key. This binding is asserted by a +signature on the certificate, which is placed there by some authority +(the *issuer*) that at least claims that it knows the subject named in +the certificate really "owns" the private key corresponding to the +public key in the certificate. -The major certificate format in use today is X.509v3, designed by ISO and -further hacked on by dozens (hundreds?) of other organizations. +The major certificate format in use today is X.509v3, designed by ISO +and further hacked on by dozens (hundreds?) of other organizations. When working with certificates, the main class to remember is -``X509_Certificate``. You can read an object of this type, but you -can't create one on the fly; a CA object is necessary for making a new -certificate. So for the most part, you only have to worry about -reading them in, verifying the signatures, and getting the bits of -data in them (most commonly the public key, and the information about -the user of that key). An X.509v3 certificate can contain a literally -infinite number of items related to all kinds of things. Botan doesn't -support a lot of them, because nobody uses them and they're an -impossible mess to work with. This section only documents the most +``X509_Certificate``. You can read an object of this type, but you can't create +one on the fly; a CA object is necessary for making a new certificate. So for +the most part, you only have to worry about reading them in, verifying the +signatures, and getting the bits of data in them (most commonly the public key, +and the information about the user of that key). An X.509v3 certificate can +contain a literally infinite number of items related to all kinds of +things. Botan doesn't support a lot of them, because nobody uses them and +they're an impossible mess to work with. This section only documents the most commonly used ones of the ones that are supported; for the rest, read -``x509cert.h`` and ``asn1_obj.h`` (which has the -definitions of various common ASN.1 constructs used in X.509). +``x509cert.h`` and ``asn1_obj.h`` (which has the definitions of various common +ASN.1 constructs used in X.509). So what's in an X.509 certificate? ----------------------------------- -Obviously, you want to be able to get the public key. This is achieved -by calling the member function ``subject_public_key``, which will -return a ``Public_Key``\*. As to what to do with this, read about -``load_key`` in :ref:`serializing_public_keys`. In the general case, -this could be any kind of public key, though 99% of the time it will -be an RSA key. However, Diffie-Hellman, DSA, and ECDSA keys are also -supported, so be careful about how you treat this. It is also a wise -idea to examine the value returned by ``constraints``, to see what -uses the public key is approved for. - -The second major piece of information you'll want is the -name/email/etc of the person to whom this certificate is -assigned. Here is where things get a little nasty. X.509v3 has two -(well, mostly just two...) different places where you can stick -information about the user: the *subject* field, and in an extension -called *subjectAlternativeName*. The *subject* field is supposed to -only included the following information: country, organization, an -organizational sub-unit name, and a so-called common name. The common -name is usually the name of the person, or it could be a title -associated with a position of some sort in the organization. It may -also include fields for state/province and locality. What a locality -is, nobody knows, but it's usually given as a city name. - -Botan doesn't currently support any of the Unicode variants used in -ASN.1 (UTF-8, UCS-2, and UCS-4), any of which could be used for the -fields in the DN. This could be problematic, particularly in Asia and -other areas where non-ASCII characters are needed for most names. The -UTF-8 and UCS-2 string types *are* accepted (in fact, UTF-8 is -used when encoding much of the time), but if any of the characters -included in the string are not in ISO 8859-1 (ie 0 ... 255), an -exception will get thrown. Currently the ``ASN1_String`` type -holds its data as ISO 8859-1 internally (regardless of local character -set); this would have to be changed to hold UCS-2 or UCS-4 in order to -support Unicode (also, many interfaces in the X.509 code would have to -accept or return a ``std::wstring`` instead of a -``std::string``). - -Like the distinguished names, subject alternative names can contain a -lot of things that Botan will flat out ignore (most of which you would -likely never want to use). However, there are three very useful pieces -of information that this extension might hold: an email address -([email protected]), a DNS name (somehost.example.com), or a URI -(http://www.example.com). - -So, how to get the information? Call ``subject_info`` with the name of -the piece of information you want, and it will return a -``std::string`` that is either empty (signifying that the certificate -doesn't have this information), or has the information -requested. There are several names for each possible item, but the -most easily readable ones are: "Name", "Country", "Organization", -"Organizational Unit", "Locality", "State", "RFC822", "URI", and -"DNS". These values are returned as a ``std::string``. +Obviously, you want to be able to get the public key. This is achieved by +calling the member function ``subject_public_key``, which will return a +``Public_Key``\*. As to what to do with this, read about ``load_key`` in +:ref:`serializing_public_keys`. In the general case, this could be any kind of +public key, though 99% of the time it will be an RSA key. However, +Diffie-Hellman, DSA, and ECDSA keys are also supported, so be careful about how +you treat this. It is also a wise idea to examine the value returned by +``constraints``, to see what uses the public key is approved for. + +The second major piece of information you'll want is the name/email/etc of the +person to whom this certificate is assigned. Here is where things get a little +nasty. X.509v3 has two (well, mostly just two...) different places where you +can stick information about the user: the *subject* field, and in an extension +called *subjectAlternativeName*. The *subject* field is supposed to only +included the following information: country, organization, an organizational +sub-unit name, and a so-called common name. The common name is usually the name +of the person, or it could be a title associated with a position of some sort +in the organization. It may also include fields for state/province and +locality. What a locality is, nobody knows, but it's usually given as a city +name. + +Botan doesn't currently support any of the Unicode variants used in ASN.1 +(UTF-8, UCS-2, and UCS-4), any of which could be used for the fields in the +DN. This could be problematic, particularly in Asia and other areas where +non-ASCII characters are needed for most names. The UTF-8 and UCS-2 string +types *are* accepted (in fact, UTF-8 is used when encoding much of the time), +but if any of the characters included in the string are not in ISO 8859-1 (ie 0 +... 255), an exception will get thrown. Currently the ``ASN1_String`` type +holds its data as ISO 8859-1 internally (regardless of local character set); +this would have to be changed to hold UCS-2 or UCS-4 in order to support +Unicode (also, many interfaces in the X.509 code would have to accept or return +a ``std::wstring`` instead of a ``std::string``). + +Like the distinguished names, subject alternative names can contain a lot of +things that Botan will flat out ignore (most of which you would likely never +want to use). However, there are three very useful pieces of information that +this extension might hold: an email address ([email protected]), a DNS name +(somehost.example.com), or a URI (http://www.example.com). + +So, how to get the information? Call ``subject_info`` with the name of the +piece of information you want, and it will return a ``std::string`` that is +either empty (signifying that the certificate doesn't have this information), +or has the information requested. There are several names for each possible +item, but the most easily readable ones are: "Name", "Country", "Organization", +"Organizational Unit", "Locality", "State", "RFC822", "URI", and "DNS". These +values are returned as a ``std::string``. You can also get information about the issuer of the certificate in the same way, using ``issuer_info``. @@ -90,18 +83,16 @@ way, using ``issuer_info``. X.509v3 Extensions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -X.509v3 specifies a large number of possible extensions. Botan -supports some, but by no means all of them. This section lists which -ones are supported, and notes areas where there may be problems with -the handling. +X.509v3 specifies a large number of possible extensions. Botan supports some, +but by no means all of them. This section lists which ones are supported, and +notes areas where there may be problems with the handling. - Key Usage and Extended Key Usage: No problems known. - - Basic Constraints: No problems known. The default for a v1/v2 - certificate is assume it's a CA if and only if the option - "x509/default_to_ca" is set. A v3 certificate is marked as a CA if - (and only if) the basic constraints extension is present and set - for a CA cert. + - Basic Constraints: No problems known. The default for a v1/v2 certificate is + assume it's a CA if and only if the option "x509/default_to_ca" is set. A v3 + certificate is marked as a CA if (and only if) the basic constraints + extension is present and set for a CA cert. - Subject Alternative Names: Only the "rfc822Name", "dNSName", and "uniformResourceIdentifier" fields will be stored; all others are @@ -113,26 +104,25 @@ the handling. - Authority Key Identifier: Only the version using KeyIdentifier is supported. If the GeneralNames version is used and the extension is - critical, an exception is thrown. If both the KeyIdentifier and - GeneralNames versions are present, then the KeyIdentifier will be - used, and the GeneralNames ignored. + critical, an exception is thrown. If both the KeyIdentifier and GeneralNames + versions are present, then the KeyIdentifier will be used, and the + GeneralNames ignored. - Subject Key Identifier: No problems known. Revocation Lists ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -It will occasionally happen that a certificate must be revoked before -its expiration date. Examples of this happening include the private -key being compromised, or the user to which it has been assigned -leaving an organization. Certificate revocation lists are an answer to -this problem (though online certificate validation techniques are -starting to become somewhat more popular). Every once in a while the -CA will release a new CRL, listing all certificates that have been -revoked. Also included is various pieces of information like what time -a particular certificate was revoked, and for what reason. In most -systems, it is wise to support some form of certificate revocation, -and CRLs handle this easily. +It will occasionally happen that a certificate must be revoked before its +expiration date. Examples of this happening include the private key being +compromised, or the user to which it has been assigned leaving an +organization. Certificate revocation lists are an answer to this problem +(though online certificate validation techniques are starting to become +somewhat more popular). Every once in a while the CA will release a new CRL, +listing all certificates that have been revoked. Also included is various +pieces of information like what time a particular certificate was revoked, and +for what reason. In most systems, it is wise to support some form of +certificate revocation, and CRLs handle this easily. For most users, processing a CRL is quite easy. All you have to do is call the constructor, which will take a filename (or a ``DataSource&``). The CRLs @@ -161,7 +151,15 @@ Reading Certificates --------------------------------- ``X509_Certificate`` has two constructors, each of which takes a source of -data; a filename to read, and a ``DataSource&``. +data; a filename to read, and a ``DataSource&``:: + + X509_Certificate cert1("cert1.pem"); + + /* This file contains two certificates, concatenated */ + DataSource_Stream in("certs2_and_3.pem"); + + X509_Certificate cert2(in); // read the first cert + X509_Certificate cert3(in); // read the second cert .. _x509_store: @@ -175,11 +173,10 @@ we hit the top of the certificate tree somewhere. It would be a might huge pain to have to handle all of that manually in every application, so there is something that does it for you: ``X509_Store``. -The basic operations are: put certificates and CRLs into it, search -for certificates, and attempt to verify certificates. That's about -it. In the future, there will be support for online retrieval of -certificates and CRLs (eg with the HTTP cert-store interface -currently under consideration by PKIX). +The basic operations are: put certificates and CRLs into it, search for +certificates, and attempt to verify certificates. That's about it. In the +future, there will be support for online retrieval of certificates and CRLs (eg +with the HTTP cert-store interface currently under consideration by PKIX). Adding Certificates ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -197,17 +194,15 @@ functions: The versions that take a ``DataSource&`` will add all the certificates that it can find in that source. -All of them add the cert(s) to the store. The "trusted" certificates -are the ones that you are willing to trust for certification -purposes. For example, say your application is working with -certificates that are owned by employees of some company, and all of -their certificates are signed by the company CA, whose certificate is -in turned signed by a commercial root CA. What you would then do is -include the certificate of the commercial CA with your application, -and read it in as a trusted certificate. From there, you could verify -the company CA's certificate, and then use that to verify the end -user's certificates. Only self-signed certificates may be considered -trusted. +All of them add the cert(s) to the store. The "trusted" certificates are the +ones that you are willing to trust for certification purposes. For example, say +your application is working with certificates that are owned by employees of +some company, and all of their certificates are signed by the company CA, whose +certificate is in turned signed by a commercial root CA. What you would then do +is include the certificate of the commercial CA with your application, and read +it in as a trusted certificate. From there, you could verify the company CA's +certificate, and then use that to verify the end user's certificates. Only +self-signed certificates may be considered trusted. Adding CRLs ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -231,38 +226,36 @@ be read by both Botan and other libraries/applications. Certificate Stores ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -An object of type ``Certificate_Store`` is a generalized interface to -an external source for certificates (and CRLs). Examples of such a -store would be one that looked up the certificates in a SQL database, -or by contacting a CGI script running on a HTTP server. There are -currently three mechanisms for looking up a certificate, and one for -retrieving CRLs. By default, most of these mechanisms will return an -empty ``std::vector`` of ``X509_Certificate``. This storage mechanism -is *only* queried when doing certificate validation: it allows you to -distribute only the root key with an application, and let some online -method handle getting all the other certificates that are needed to -validate an end entity certificate. In particular, the search routines -will not attempt to access the external database. - -The three certificate lookup methods are ``by_SKID`` (Subject Key -Identifier), ``by_name`` (the CommonName DN entry), and ``by_email`` -(stored in either the distinguished name, or in a -subjectAlternativeName extension). The name and email versions take a -``std::string``, while the SKID version takes a ``SecureVector<byte>`` -containing the subject key identifier in raw binary. You can choose -not to implement ``by_name`` or ``by_email``, but ``by_SKID`` is -mandatory to implement, and, currently, is the only version that is -used by ``X509_Store``. - -Finally, there is a method for finding CRLs, called ``get_crls_for``, -that takes an ``X509_Certificate`` object, and returns a -``std::vector`` of ``X509_CRL``. While normally there will be only one -CRL, the use of the vector makes it easy to return no CRLs (eg, if the -certificate store doesn't support retrieving them), or return multiple -ones (for example, if the certificate store can't determine precisely -which key was used to sign the certificate). Implementing the function -is optional, and by default will return no CRLs. If it is available, -it will be used by ``X509_CRL``. +An object of type ``Certificate_Store`` is a generalized interface to an +external source for certificates (and CRLs). Examples of such a store would be +one that looked up the certificates in a SQL database, or by contacting a CGI +script running on a HTTP server. There are currently three mechanisms for +looking up a certificate, and one for retrieving CRLs. By default, most of +these mechanisms will return an empty ``std::vector`` of +``X509_Certificate``. This storage mechanism is *only* queried when doing +certificate validation: it allows you to distribute only the root key with an +application, and let some online method handle getting all the other +certificates that are needed to validate an end entity certificate. In +particular, the search routines will not attempt to access the external +database. + +The three certificate lookup methods are ``by_SKID`` (Subject Key Identifier), +``by_name`` (the CommonName DN entry), and ``by_email`` (stored in either the +distinguished name, or in a subjectAlternativeName extension). The name and +email versions take a ``std::string``, while the SKID version takes a +``SecureVector<byte>`` containing the subject key identifier in raw binary. You +can choose not to implement ``by_name`` or ``by_email``, but ``by_SKID`` is +mandatory to implement, and, currently, is the only version that is used by +``X509_Store``. + +Finally, there is a method for finding CRLs, called ``get_crls_for``, that +takes an ``X509_Certificate`` object, and returns a ``std::vector`` of +``X509_CRL``. While normally there will be only one CRL, the use of the vector +makes it easy to return no CRLs (eg, if the certificate store doesn't support +retrieving them), or return multiple ones (for example, if the certificate +store can't determine precisely which key was used to sign the +certificate). Implementing the function is optional, and by default will return +no CRLs. If it is available, it will be used by ``X509_CRL``. As for using such a store, you have to tell ``X509_Store`` about it with @@ -275,84 +268,86 @@ with Verifying Certificates ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -There is a single function in ``X509_Store`` related to verifying a -certificate: - -.. .cpp:function:: X509_Code X509_Store::validate_cert(const X509_Certificate& cert, Cert_Usage usage = ANY) - -This function will return ``VERIFIED`` if the certificate can -safely be considered valid for the usage(s) described by ``usage``, -and an error code if it is not. Naturally, things are a bit more -complicated than that. The enum ``Cert_Usage`` is defined inside -the ``X509_Store`` class, it (currently) can take on any of the -values ``ANY`` (any usage is OK), ``TLS_SERVER`` (for SSL/TLS -server authentication), ``TLS_CLIENT`` (for SSL/TLS client -authentication), ``CODE_SIGNING``, ``EMAIL_PROTECTION`` (email -encryption, usually this means S/MIME), ``TIME_STAMPING`` (in -theory any time stamp application, usually IETF PKIX's Time Stamp -Protocol), or ``CRL_SIGNING``. Note that Microsoft's code signing -system, certainly the most widely used, uses a completely different -(and mostly undocumented) method for marking certificates for code -signing. - -First, how does it know if a certificate is valid? A certificate is -valid if both of the following hold: a) the signature in the -certificate can be verified using the public key in the issuer's -certificate, and b) the issuer's certificate is a valid CA -certificate. Note that this definition is recursive. We get out of -this by "bottoming out" when we reach a certificate that we consider -trusted. In general this will either be a commercial root CA, or an -organization or application specific CA. - -There are a few other restrictions (validity periods, key usage -restrictions, etc), but the above summarizes the major points of the -validation algorithm. In theory, Botan implements the certificate path -validation algorithm given in RFC 2459, but in practice it does not -(yet), because we don't support the X.509v3 policy or name constraint -extensions. - -Possible values for ``usage`` are ``TLS_SERVER``, ``TLS_CLIENT``, -``CODE_SIGNING``, ``EMAIL_PROTECTION``, ``CRL_SIGNING``, and -``TIME_STAMPING``, and ``ANY``. The default ``ANY`` does not mean -valid for any use, it means "is valid for some usage". This is usually -what you want; requiring that a random certificate support a -particular usage will likely result in a lot of failures, unless your -application is very careful to always issue certificates with the -proper extensions, and you never use certificates generated by other -apps. +Verifying a certificate requires that we build up a chain of trust, starting +from the root (usually a commercial CA), down through some number of +intermediate CAs, and finally reaching the actual certificate in +question. Thus, to verify, we actually have to have all those certificates on +hand (or at the very least, know where we can get the ones we need). + +The class which handles both storing certificates, and verifying them, +is + +.. cpp:class:: X509_Store + +.. cpp:type:: Cert_Usage + + Can be any of: + * ``ANY`` (any usage is OK) + * ``CRL_SIGNING`` + * ``TLS_SERVER`` (for SSL/TLS server authentication) + * ``TLS_CLIENT`` (for SSL/TLS client authentication) + * ``CODE_SIGNING`` + * ``EMAIL_PROTECTION`` (usually this means S/MIME) + * ``TIME_STAMPING`` (in theory any time stamp application, + usually IETF PKIX's Time Stamp Protocol) + +.. cpp:function:: X509_Code validate_cert(const X509_Certificate& cert, \ + Cert_Usage usage = ANY) + + Return ``VERIFIED`` if the certificate can safely be considered + valid for the usage(s) described by *usage*, and an error code if + it is not. + +First, how does :cpp:class`X509_Store::validate_cert` know if a certificate is +valid? A certificate is valid if both of the following hold: a) the signature +in the certificate can be verified using the public key in the issuer's +certificate, and b) the issuer's certificate is a valid CA certificate. Note +that this definition is recursive. We get out of this by "bottoming out" when +we reach a certificate that we consider trusted. In general this will either be +a commercial root CA, or an organization or application specific CA. + +There are a few other restrictions (validity periods, key usage restrictions, +etc), but the above summarizes the major points of the validation algorithm. In +theory, Botan implements the certificate path validation algorithm given in RFC +2459, but in practice it does not (yet), because we don't support the X.509v3 +policy or name constraint extensions. + +The default ``ANY`` does not mean valid for any use, it means "is valid for +some usage". This is usually what you want; requiring that a random certificate +support a particular usage will likely result in a lot of failures, unless your +application is very careful to always issue certificates with the proper +extensions, and you never use certificates generated by other apps. Return values for ``validate_cert`` (and ``add_crl``) include: - - VERIFIED: The certificate is valid for the specified use. +* VERIFIED: The certificate is valid for the specified use. +* INVALID_USAGE: The certificate cannot be used for the specified use. - - INVALID_USAGE: The certificate cannot be used for the specified use. +* CANNOT_ESTABLISH_TRUST: The root certificate was not marked as trusted. - - CANNOT_ESTABLISH_TRUST: The root certificate was not marked as - trusted. +* CERT_CHAIN_TOO_LONG: The certificate chain exceeded the length + allowed by a basicConstraints extension. - - CERT_CHAIN_TOO_LONG: The certificate chain exceeded the length - allowed by a basicConstraints extension. +* SIGNATURE_ERROR: An invalid signature was found - - SIGNATURE_ERROR: An invalid signature was found +* POLICY_ERROR: Some problem with the certificate policies was found. - - POLICY_ERROR: Some problem with the certificate policies was found. - - - CERT_FORMAT_ERROR: Some format problem was found in a certificate. - - CERT_ISSUER_NOT_FOUND: The issuer of a certificate could not be found. - - CERT_NOT_YET_VALID: The certificate is not yet valid. - - CERT_HAS_EXPIRED: The certificate has expired. - - CERT_IS_REVOKED: The certificate has been revoked. - - CRL_FORMAT_ERROR: Some format problem was found in a CRL. - - CRL_ISSUER_NOT_FOUND: The issuer of a CRL could not be found. - - CRL_NOT_YET_VALID: The CRL is not yet valid. - - CRL_HAS_EXPIRED: The CRL has expired. - - CA_CERT_CANNOT_SIGN: The CA certificate found does not have an - contain a public key that allows signature verification. - - CA_CERT_NOT_FOR_CERT_ISSUER: The CA cert found is not allowed to - issue certificates. - - CA_CERT_NOT_FOR_CRL_ISSUER: The CA cert found is not allowed to - issue CRLs. - - UNKNOWN_X509_ERROR: Some other error occurred. +* CERT_FORMAT_ERROR: Some format problem was found in a certificate. +* CERT_ISSUER_NOT_FOUND: The issuer of a certificate could not be found. +* CERT_NOT_YET_VALID: The certificate is not yet valid. +* CERT_HAS_EXPIRED: The certificate has expired. +* CERT_IS_REVOKED: The certificate has been revoked. +* CRL_FORMAT_ERROR: Some format problem was found in a CRL. +* CRL_ISSUER_NOT_FOUND: The issuer of a CRL could not be found. +* CRL_NOT_YET_VALID: The CRL is not yet valid. +* CRL_HAS_EXPIRED: The CRL has expired. +* CA_CERT_CANNOT_SIGN: The CA certificate found does not have an + contain a public key that allows signature verification. +* CA_CERT_NOT_FOR_CERT_ISSUER: The CA cert found is not allowed to + issue certificates. +* CA_CERT_NOT_FOR_CRL_ISSUER: The CA cert found is not allowed to + issue CRLs. +* UNKNOWN_X509_ERROR: Some other error occurred. Certificate Authorities --------------------------------- @@ -418,38 +413,40 @@ certificates, along with any new ones. This is done by calling function returns a new ``X509_CRL`` to make available for clients. -The ``CRL_Entry`` type is a structure that contains, at a minimum, the -serial number of the revoked certificate. As serial numbers are never -repeated, the pairing of an issuer and a serial number (should) -distinctly identify any certificate. In this case, we represent the -serial number as a ``SecureVector<byte>`` called ``serial``. There are -two additional (optional) values, an enumeration called ``CRL_Code`` -that specifies the reason for revocation (``reason``), and an object -that represents the time that the certificate became invalid (if this -information is known). +The ``CRL_Entry`` type is a structure that contains, at a minimum, the serial +number of the revoked certificate. As serial numbers are never repeated, the +pairing of an issuer and a serial number (should) distinctly identify any +certificate. In this case, we represent the serial number as a +``SecureVector<byte>`` called ``serial``. There are two additional (optional) +values, an enumeration called ``CRL_Code`` that specifies the reason for +revocation (``reason``), and an object that represents the time that the +certificate became invalid (if this information is known). If you wish to remove an old entry from the CRL, insert a new entry for the -same cert, with a ``reason`` code of ``DELETE_CRL_ENTRY``. For example, -if a revoked certificate has expired 'normally', there is no reason to continue -to explicitly revoke it, since clients will reject the cert as expired in any +same cert, with a ``reason`` code of ``DELETE_CRL_ENTRY``. For example, if a +revoked certificate has expired 'normally', there is no reason to continue to +explicitly revoke it, since clients will reject the cert as expired in any case. Self-Signed Certificates ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Generating a new self-signed certificate can often be useful, for -example when setting up a new root CA, or for use in email -applications. The library provides a utility function for this: +Generating a new self-signed certificate can often be useful, for example when +setting up a new root CA, or for use in email applications. The library +provides a utility function for this: .. cpp:function:: X509_Certificate create_self_signed_cert( \ const X509_Cert_Options& opts, const Private_Key& key) -Where ``key`` is obviously the private key you wish to use (the public key, -used in the certificate itself, is extracted from the private key), and -``opts`` is an structure that has various bits of information that will be -used in creating the certificate (this structure, and its use, is discussed -below). This function is found in the header ``x509self.h``. There is an -example of using this function in the ``self_sig`` example. + Where *key* is the private key you wish to use (the public key, + used in the certificate itself, is extracted from the private key), + and *opts* is an structure that has various bits of information + that will be used in creating the certificate (this structure, and + its use, is discussed below). + +An example: + +.. literalinclude:: examples/self_sig.cpp Creating PKCS #10 Requests ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -460,77 +457,71 @@ certificate requests: .. cpp:function:: PKCS10_Request create_cert_req( \ const X509_Cert_Options& opts, const Private_Key& key) -This function acts quite similarly to ``create_self_signed_cert``, -except it instead returns a PKCS #10 certificate request. After -creating it, one would typically transmit it to a CA, who signs it and -returns a freshly minted X.509 certificate. There is an example of -using this function in the ``pkcs10`` example. +This function acts quite similarly to +:cpp:func:`create_self_signed_cert`, except it instead returns a PKCS +#10 certificate request. After creating it, one would typically +transmit it to a CA, who signs it and returns a freshly minted X.509 +certificate. + +An example: + +.. literalinclude:: examples/pkcs10.cpp Certificate Options ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -What is this ``X509_Cert_Options`` thing we've been passing around? -It's a class representing a bunch of information that will end up -being stored into the certificate. This information comes in 3 major -flavors: information about the subject (CA or end-user), the validity -period of the certificate, and restrictions on the usage of the -certificate. +What is this ``X509_Cert_Options`` thing we've been passing around? It's a +class representing a bunch of information that will end up being stored into +the certificate. This information comes in 3 major flavors: information about +the subject (CA or end-user), the validity period of the certificate, and +restrictions on the usage of the certificate. -First and foremost is a number of ``std::string`` members, which -contains various bits of information about the user: ``common_name``, -``serial_number``, ``country``, ``organization``, ``org_unit``, -``locality``, ``state``, ``email``, ``dns_name``, and ``uri``. As many -of these as possible should be filled it (especially an email -address), though the only required ones are ``common_name`` and -``country``. +First and foremost is a number of ``std::string`` members, which contains +various bits of information about the user: ``common_name``, ``serial_number``, +``country``, ``organization``, ``org_unit``, ``locality``, ``state``, +``email``, ``dns_name``, and ``uri``. As many of these as possible should be +filled it (especially an email address), though the only required ones are +``common_name`` and ``country``. There is another value that is only useful when creating a PKCS #10 request, which is called ``challenge``. This is a challenge password, which you can later use to request certificate revocation (*if* the CA supports doing revocations in this manner). -Then there is the validity period; these are set with ``not_before`` -and ``not_after``. Both of these functions also take a -``std::string``, which specifies when the certificate should start -being valid, and when it should stop being valid. If you don't set the -starting validity period, it will automatically choose the current -time. If you don't set the ending time, it will choose the starting -time plus a default time period. The arguments to these functions -specify the time in the following format: "2002/11/27 1:50:14". The -time is in 24-hour format, and the date is encoded as -year/month/day. The date must be specified, but you can omit the time -or trailing parts of it, for example "2002/11/27 1:50" or -"2002/11/27". - -Lastly, you can set constraints on a key. The one you're mostly likely -to want to use is to create (or request) a CA certificate, which can -be done by calling the member function ``CA_key``. This should only be -used when needed. +Then there is the validity period; these are set with ``not_before`` and +``not_after``. Both of these functions also take a ``std::string``, which +specifies when the certificate should start being valid, and when it should +stop being valid. If you don't set the starting validity period, it will +automatically choose the current time. If you don't set the ending time, it +will choose the starting time plus a default time period. The arguments to +these functions specify the time in the following format: "2002/11/27 +1:50:14". The time is in 24-hour format, and the date is encoded as +year/month/day. The date must be specified, but you can omit the time or +trailing parts of it, for example "2002/11/27 1:50" or "2002/11/27". + +Lastly, you can set constraints on a key. The one you're mostly likely to want +to use is to create (or request) a CA certificate, which can be done by calling +the member function ``CA_key``. This should only be used when needed. Other constraints can be set by calling the member functions -``add_constraints`` and ``add_ex_constraints``. The -first takes a ``Key_Constraints`` value, and replaces any -previously set value. If no value is set, then the certificate key is -marked as being valid for any usage. You can set it to any of the -following (for more than one usage, OR them together): -``DIGITAL_SIGNATURE``, ``NON_REPUDIATION``, -``KEY_ENCIPHERMENT``, ``DATA_ENCIPHERMENT``, -``KEY_AGREEMENT``, ``KEY_CERT_SIGN``, ``CRL_SIGN``, -``ENCIPHER_ONLY``, ``DECIPHER_ONLY``. Many of these have quite -special semantics, so you should either consult the appropriate -standards document (such as RFC 3280), or just not call -``add_constraints``, in which case the appropriate values will -be chosen for you. - -The second function, ``add_ex_constraints``, allows you to specify an -OID that has some meaning with regards to restricting the key to -particular usages. You can, if you wish, specify any OID you like, but -there is a set of standard ones that other applications will be able -to understand. These are the ones specified by the PKIX standard, and -are named "PKIX.ServerAuth" (for TLS server authentication), -"PKIX.ClientAuth" (for TLS client authentication), "PKIX.CodeSigning", -"PKIX.EmailProtection" (most likely for use with S/MIME), +``add_constraints`` and ``add_ex_constraints``. The first takes a +``Key_Constraints`` value, and replaces any previously set value. If no value +is set, then the certificate key is marked as being valid for any usage. You +can set it to any of the following (for more than one usage, OR them together): +``DIGITAL_SIGNATURE``, ``NON_REPUDIATION``, ``KEY_ENCIPHERMENT``, +``DATA_ENCIPHERMENT``, ``KEY_AGREEMENT``, ``KEY_CERT_SIGN``, ``CRL_SIGN``, +``ENCIPHER_ONLY``, ``DECIPHER_ONLY``. Many of these have quite special +semantics, so you should either consult the appropriate standards document +(such as RFC 3280), or just not call ``add_constraints``, in which case the +appropriate values will be chosen for you. + +The second function, ``add_ex_constraints``, allows you to specify an OID that +has some meaning with regards to restricting the key to particular usages. You +can, if you wish, specify any OID you like, but there is a set of standard ones +that other applications will be able to understand. These are the ones +specified by the PKIX standard, and are named "PKIX.ServerAuth" (for TLS server +authentication), "PKIX.ClientAuth" (for TLS client authentication), +"PKIX.CodeSigning", "PKIX.EmailProtection" (most likely for use with S/MIME), "PKIX.IPsecUser", "PKIX.IPsecTunnel", "PKIX.IPsecEndSystem", and -"PKIX.TimeStamping". You can call "add_ex_constraints" any number of -times - each new OID will be added to the list to include in the -certificate. +"PKIX.TimeStamping". You can call "add_ex_constraints" any number of times - +each new OID will be added to the list to include in the certificate. |