diff options
Diffstat (limited to 'doc')
-rw-r--r-- | doc/examples.txt | 109 | ||||
-rw-r--r-- | doc/index.txt | 5 | ||||
-rw-r--r-- | doc/lowlevel.txt | 258 | ||||
-rw-r--r-- | doc/passhash.txt | 152 | ||||
-rw-r--r-- | doc/pubkey.txt | 365 | ||||
-rw-r--r-- | doc/rng.txt | 112 | ||||
-rw-r--r-- | doc/ssl.txt | 10 | ||||
-rw-r--r-- | doc/support.txt | 19 | ||||
-rw-r--r-- | doc/x509.txt | 10 |
9 files changed, 634 insertions, 406 deletions
diff --git a/doc/examples.txt b/doc/examples.txt new file mode 100644 index 000000000..5d4aad8ed --- /dev/null +++ b/doc/examples.txt @@ -0,0 +1,109 @@ + +Examples +======================================== + +RSA Examples +---------------------------------------- + +RSA Key Generation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +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 + +DSA Examples +---------------------------------------- + +DSA Key Generation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Generate a 2048 bit DSA key + +.. literalinclude:: examples/dsa_kgen.cpp + +DSA Signature Generation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Reads a DSA private key and signs the specified file using SHA-1 + +.. literalinclude:: examples/dsa_sign.cpp + +DSA Signature Verification +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Reads a DSA public key and a signature, and checks if the signature +is valid for the specified file + +..literalinclude:: examples/dsa_ver.cpp + +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 + + +Format Preserving Encryption +---------------------------------------- + +Format preserving encryption is a way of mapping data with an +arbitrarly specified format such that the ciphertext has the same +formatting. This example encrypts a credit card number with a valid +`Luhn checksum <http://en.wikipedia.org/wiki/Luhn_algorithm>`_ to +another number with the same format, including a correct checksum. + +.. literalinclude:: examples/fpe.cpp + +ASN.1 Parsing +---------------------------------------- + +This example is a simple ASN.1 parser + +.. literalinclude:: examples/asn1.cpp + +SSL/TLS +---------------------------------------- + +SSL Client +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A simple SSL/TLS client + +.. literalinclude:: examples/tls_client.cpp + +SSL Server +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A simple SSL/TLS server + +.. literalinclude:: examples/tls_server.cpp diff --git a/doc/index.txt b/doc/index.txt index 1dfa6abcc..ecbeb8803 100644 --- a/doc/index.txt +++ b/doc/index.txt @@ -12,12 +12,17 @@ Contents: filters pubkey x509 + ssl lowlevel + passhash + rng bigint + examples algos pgpkeys license credits + support log Indices and tables diff --git a/doc/lowlevel.txt b/doc/lowlevel.txt index 4f63948da..d6bf071bc 100644 --- a/doc/lowlevel.txt +++ b/doc/lowlevel.txt @@ -216,116 +216,6 @@ away; the key is kept around). A MAC has the ``SymmetricAlgorithm`` interface in addition to the ``BufferedComputation`` interface. -Random Number Generators ---------------------------------- - -The random number generators provided in Botan are meant for creating -keys, IVs, padding, nonces, and anything else that requires 'random' -data. It is important to remember that the output of these classes -will vary, even if they are supplied with ethe same seed (ie, two -``Randpool`` objects with similar initial states will not produce -the same output, because the value of high resolution timers is added -to the state at various points). - -To ensure good quality output, a PRNG needs to be seeded with truly -random data (such as that produced by a hardware RNG). Typically, you -will use an ``EntropySource`` (see below). To add some (typically -application specific) entropy to a PRNG, you can use - -.. cpp:function:: void add_entropy(const byte* data, size_t length) - -Once a PRNG has been initialized, you can get a single byte of random -data by - -.. cpp:function:: byte random() - -or get a large block by calling - -.. cpp:function:: void randomize(byte* data, size_t length) - -Randpool -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -``Randpool`` is the primary PRNG within Botan. In recent versions all -uses of it have been wrapped by an implementation of the X9.31 PRNG -(see below). If for some reason you should have cause to create a PRNG -instead of using the "global" one owned by the library, it would be -wise to consider the same on the grounds of general caution; while -``Randpool`` is designed with known attacks and PRNG weaknesses in -mind, it is not an standard/official PRNG. The remainder of this -section is a (fairly technical, though high-level) description of the -algorithms used in this PRNG. Unless you have a specific interest in -this subject, the rest of this section might prove somewhat -uninteresting. - -``Randpool`` has an internal state called pool, which is 512 bytes -long. This is where entropy is mixed into and extracted from. There is also a -small output buffer (called buffer), which holds the data which has already -been generated but has just not been output yet. - -It is based around a MAC and a block cipher (which are currently -HMAC(SHA-256) and AES-256). Where a specific size is mentioned, it -should be taken as a multiple of the cipher's block size. For example, -if a 256-bit block cipher were used instead of AES, all the sizes -internally would double. Every time some new output is needed, we -compute the MAC of a counter and a high resolution timer. The -resulting MAC is XORed into the output buffer (wrapping as needed), -and the output buffer is then encrypted with AES, producing 16 bytes -of output. - -After 8 blocks (or 128 bytes) have been produced, we mix the pool. To -do this, we first rekey both the MAC and the cipher; the new MAC key -is the MAC of the current pool under the old MAC key, while the new -cipher key is the MAC of the current pool under the just-chosen MAC -key. We then encrypt the entire pool in CBC mode, using the current -(unused) output buffer as the IV. We then generate a new output -buffer, using the mechanism described in the previous paragraph. - -To add randomness to the PRNG, we compute the MAC of the input and XOR -the output into the start of the pool. Then we remix the pool and -produce a new output buffer. The initial MAC operation should make it -very hard for chosen inputs to harm the security of ``Randpool``, and -as HMAC should be able to hold roughly 256 bits of state, it is -unlikely that we are wasting much input entropy (or, if we are, it -doesn't matter, because we have a very abundant supply). - -ANSI X9.31 -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -``ANSI_X931_PRNG`` is the standard issue X9.31 Appendix A.2.4 PRNG, -though using AES-256 instead of 3DES as the block cipher. This PRNG -implementation has been checked against official X9.31 test vectors. - -Internally, the PRNG holds a pointer to another PRNG (typically -Randpool). This internal PRNG generates the key and seed used by the -X9.31 algorithm, as well as the date/time vectors. Each time an X9.31 -PRNG object receives entropy, it passes it along to the PRNG it is -holding, and then pulls out some random bits to generate a new key and -seed. This PRNG considers itself seeded as soon as the internal PRNG -is seeded. - - -Entropy Sources ---------------------------------- - -An ``EntropySource`` is an abstract representation of some method of -gather "real" entropy. This tends to be very system dependent. The -*only* way you should use an ``EntropySource`` is to pass it to a PRNG -that will extract entropy from it -- never use the output directly for -any kind of key or nonce generation! - -``EntropySource`` has a pair of functions for getting entropy from -some external source, called ``fast_poll`` and ``slow_poll``. These -pass a buffer of bytes to be written; the functions then return how -many bytes of entropy were gathered. - -Note for writers of ``EntropySource`` subclasses: it isn't necessary -to use any kind of cryptographic hash on your output. The data -produced by an EntropySource is only used by an application after it -has been hashed by the ``RandomNumberGenerator`` that asked for the -entropy, thus any hashing you do will be wasteful of both CPU cycles -and entropy. - User Interfaces --------------------------------- @@ -384,154 +274,6 @@ wxWidgets, FOX, etc), and would like to make it available to users in general (ideally under a permissive license such as public domain or MIT/BSD), feel free to send in a copy. -PBKDF Algorithms ---------------------------------- - -There are various procedures (usually ad-hoc) for turning a -passphrase into a (mostly) arbitrary length key for a symmetric -cipher. A general interface for such algorithms is presented in -``pbkdf.h``. The main function is ``derive_key``, which -takes a passphrase, a salt, an iteration count, and the desired length -of the output key, and returns a key of that length, deterministically -produced from the passphrase and salt. If an algorithm can't produce a -key of that size, it will throw an exception (most notably, PKCS #5's -PBKDF1 can only produce strings between 1 and $n$ bytes, where $n$ is -the output size of the underlying hash function). - -The purpose of the iteration count is to make the algorithm take -longer to compute the final key (reducing the speed of brute-force -attacks of various kinds). Most standards recommend an iteration count -of at least 10000. Currently defined PBKDF algorithms are -"PBKDF1(digest)", "PBKDF2(digest)", and "OpenPGP-S2K(digest)"; you can -retrieve any of these using the ``get_pbkdf``, found in -``lookup.h``. As of this writing, "PBKDF2(SHA-256)" with 10000 -iterations and a 16 byte salt is recommend for new applications. - -OpenPGP S2K -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -There are some oddities about OpenPGP's S2K algorithms that are -documented here. For one thing, it uses the iteration count in a -strange manner; instead of specifying how many times to iterate the -hash, it tells how many *bytes* should be hashed in total -(including the salt). So the exact iteration count will depend on the -size of the salt (which is fixed at 8 bytes by the OpenPGP standard, -though the implementation will allow any salt size) and the size of -the passphrase. - -To get what OpenPGP calls "Simple S2K", set iterations to 0, and do -not specify a salt. To get "Salted S2K", again leave the iteration -count at 0, but give an 8-byte salt. "Salted and Iterated S2K" -requires an 8-byte salt and some iteration count (this should be -significantly larger than the size of the longest passphrase that -might reasonably be used; somewhere from 1024 to 65536 would probably -be about right). Using both a reasonably sized salt and a large -iteration count is highly recommended to prevent password guessing -attempts. - -Password Hashing ---------------------------------- - -Storing passwords for user authentication purposes in plaintext is the -simplest but least secure method; when an attacker compromises the -database in which the passwords are stored, they immediately gain -access to all of them. Often passwords are reused among multiple -services or machines, meaning once a password to a single service is -known an attacker has a substantial head start on attacking other -machines. - -The general approach is to store, instead of the password, the output -of a one way function of the password. Upon receiving an -authentication request, the authenticator can recompute the one way -function and compare the value just computed with the one that was -stored. If they match, then the authentication request succeeds. But -when an attacker gains access to the database, they only have the -output of the one way function, not the original password. - -Common hash functions such as SHA-256 are one way, but used alone they -have problems for this purpose. What an attacker can do, upon gaining -access to such a stored password database, is hash common dictionary -words and other possible passwords, storing them in a list. Then he -can search through his list; if a stored hash and an entry in his list -match, then he has found the password. Even worse, this can happen -*offline*: an attacker can begin hashing common passwords days, -months, or years before ever gaining access to the database. In -addition, if two users choose the same password, the one way function -output will be the same for both of them, which will be visible upon -inspection of the database. - -There are two solutions to these problems: salting and -iteration. Salting refers to including, along with the password, a -randomly chosen value which perturbs the one way function. Salting can -reduce the effectivness of offline dictionary generation (because for -each potential password, an attacker would have to compute the one way -function output for all possible salts - with a large enough salt, -this can make the problem quite difficult). It also prevents the same -password from producing the same output, as long as the salts do not -collide. With a large salt (say 80 to 128 bits) this will be quite -unlikely. Iteration refers to the general technique of forcing -multiple one way function evaluations when computing the output, to -slow down the operation. For instance if hashing a single password -requires running SHA-256 100,000 times instead of just once, that will -slow down user authentication by a factor of 100,000, but user -authentication happens quite rarely, and usually there are more -expensive operations that need to occur anyway (network and database -I/O, etc). On the other hand, an attacker who is attempting to break a -database full of stolen password hashes will be seriously -inconvenienced by a factor of 100,000 slowdown; they will be able to -only test at a rate of .0001% of what they would without iterations -(or, equivalently, will require 100,000 times as many zombie botnet -hosts). - -There are many different ways of doing this password hashing -operation, with common ones including Unix's crypt (which is based on -DES) and OpenBSD's bcrypt (based on Blowfish). Other variants using -MD5 or SHA-256 are also in use on various systems. - -Botan provides two techniques, passhash9 and bcrypt - -Passhash9 -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Botan provides a password hashing technique called passhash9, in -``passhash9.h``, which is based on PBKDF2. A usage example can be -found in ``doc/examples/passhash.cpp``. Three functions are provided -in this header: - -.. cpp:function:: std::string generate_passhash9(const std::string& password, RandomNumberGenerator& rng, u16bit work_factor = 10) - - Takes the password to hash, a rng, and a work factor, which tells - how many iterations to compute. The default work factor is 10 - (which means 100,000 iterations), but any non-zero value is - accepted. - -.. cpp:function:: std::string generate_passhash9(const std::string& password, byte alg_id, RandomNumberGenerator& rng, u16bit work_factor = 10) - - Like the other ``generate_passhash9``, but taking a parameter that - specifies which PRF to use. Currently defined values are 0 - ("HMAC(SHA-1)"), 1 ("HMAC(SHA-256)"), and 2 ("CMAC(Blowfish)"). - -.. cpp:function:: bool check_passhash9(const std::string& password, const std::string& hash) - - Takes a password and a passhash9 output and checks if the password - is the same as the one that was used to generate the passhash9 - output, returning a boolean true (same) or false (not same). - -Bcrypt -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Bcrypt is a password hashing scheme originally designed for use in -OpenBSD, but numerous other implementations exist. It is made -available by including ``bcrypt.h``, and provides the functions - -.. cpp:function:: std::string generate_bcrypt(const std::string& password, RandomNumberGenerator& rng, u16bit work_factor = 10) - -and - -.. cpp:function:: bool check_bcrypt(const std::string& password, const std::string& hash) - -These work in exactly the same way as the passhash9 password hashing -functions. Checksums --------------------------------- diff --git a/doc/passhash.txt b/doc/passhash.txt new file mode 100644 index 000000000..a7a18ebb4 --- /dev/null +++ b/doc/passhash.txt @@ -0,0 +1,152 @@ + +.. _pbkdf: + +PBKDF Algorithms +--------------------------------- + +There are various procedures (usually ad-hoc) for turning a +passphrase into a (mostly) arbitrary length key for a symmetric +cipher. A general interface for such algorithms is presented in +``pbkdf.h``. The main function is ``derive_key``, which +takes a passphrase, a salt, an iteration count, and the desired length +of the output key, and returns a key of that length, deterministically +produced from the passphrase and salt. If an algorithm can't produce a +key of that size, it will throw an exception (most notably, PKCS #5's +PBKDF1 can only produce strings between 1 and $n$ bytes, where $n$ is +the output size of the underlying hash function). + +The purpose of the iteration count is to make the algorithm take +longer to compute the final key (reducing the speed of brute-force +attacks of various kinds). Most standards recommend an iteration count +of at least 10000. Currently defined PBKDF algorithms are +"PBKDF1(digest)", "PBKDF2(digest)", and "OpenPGP-S2K(digest)"; you can +retrieve any of these using the ``get_pbkdf``, found in +``lookup.h``. As of this writing, "PBKDF2(SHA-256)" with 10000 +iterations and a 16 byte salt is recommend for new applications. + +OpenPGP S2K +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There are some oddities about OpenPGP's S2K algorithms that are +documented here. For one thing, it uses the iteration count in a +strange manner; instead of specifying how many times to iterate the +hash, it tells how many *bytes* should be hashed in total +(including the salt). So the exact iteration count will depend on the +size of the salt (which is fixed at 8 bytes by the OpenPGP standard, +though the implementation will allow any salt size) and the size of +the passphrase. + +To get what OpenPGP calls "Simple S2K", set iterations to 0, and do +not specify a salt. To get "Salted S2K", again leave the iteration +count at 0, but give an 8-byte salt. "Salted and Iterated S2K" +requires an 8-byte salt and some iteration count (this should be +significantly larger than the size of the longest passphrase that +might reasonably be used; somewhere from 1024 to 65536 would probably +be about right). Using both a reasonably sized salt and a large +iteration count is highly recommended to prevent password guessing +attempts. + +Password Hashing +--------------------------------- + +Storing passwords for user authentication purposes in plaintext is the +simplest but least secure method; when an attacker compromises the +database in which the passwords are stored, they immediately gain +access to all of them. Often passwords are reused among multiple +services or machines, meaning once a password to a single service is +known an attacker has a substantial head start on attacking other +machines. + +The general approach is to store, instead of the password, the output +of a one way function of the password. Upon receiving an +authentication request, the authenticator can recompute the one way +function and compare the value just computed with the one that was +stored. If they match, then the authentication request succeeds. But +when an attacker gains access to the database, they only have the +output of the one way function, not the original password. + +Common hash functions such as SHA-256 are one way, but used alone they +have problems for this purpose. What an attacker can do, upon gaining +access to such a stored password database, is hash common dictionary +words and other possible passwords, storing them in a list. Then he +can search through his list; if a stored hash and an entry in his list +match, then he has found the password. Even worse, this can happen +*offline*: an attacker can begin hashing common passwords days, +months, or years before ever gaining access to the database. In +addition, if two users choose the same password, the one way function +output will be the same for both of them, which will be visible upon +inspection of the database. + +There are two solutions to these problems: salting and +iteration. Salting refers to including, along with the password, a +randomly chosen value which perturbs the one way function. Salting can +reduce the effectivness of offline dictionary generation (because for +each potential password, an attacker would have to compute the one way +function output for all possible salts - with a large enough salt, +this can make the problem quite difficult). It also prevents the same +password from producing the same output, as long as the salts do not +collide. With a large salt (say 80 to 128 bits) this will be quite +unlikely. Iteration refers to the general technique of forcing +multiple one way function evaluations when computing the output, to +slow down the operation. For instance if hashing a single password +requires running SHA-256 100,000 times instead of just once, that will +slow down user authentication by a factor of 100,000, but user +authentication happens quite rarely, and usually there are more +expensive operations that need to occur anyway (network and database +I/O, etc). On the other hand, an attacker who is attempting to break a +database full of stolen password hashes will be seriously +inconvenienced by a factor of 100,000 slowdown; they will be able to +only test at a rate of .0001% of what they would without iterations +(or, equivalently, will require 100,000 times as many zombie botnet +hosts). + +There are many different ways of doing this password hashing +operation, with common ones including Unix's crypt (which is based on +DES) and OpenBSD's bcrypt (based on Blowfish). Other variants using +MD5 or SHA-256 are also in use on various systems. + +Botan provides two techniques, passhash9 and bcrypt + +Passhash9 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Botan provides a password hashing technique called passhash9, in +``passhash9.h``, which is based on PBKDF2. A usage example can be +found in ``doc/examples/passhash.cpp``. Three functions are provided +in this header: + +.. cpp:function:: std::string generate_passhash9(const std::string& password, RandomNumberGenerator& rng, u16bit work_factor = 10) + + Takes the password to hash, a rng, and a work factor, which tells + how many iterations to compute. The default work factor is 10 + (which means 100,000 iterations), but any non-zero value is + accepted. + +.. cpp:function:: std::string generate_passhash9(const std::string& password, byte alg_id, RandomNumberGenerator& rng, u16bit work_factor = 10) + + Like the other ``generate_passhash9``, but taking a parameter that + specifies which PRF to use. Currently defined values are 0 + ("HMAC(SHA-1)"), 1 ("HMAC(SHA-256)"), and 2 ("CMAC(Blowfish)"). + +.. cpp:function:: bool check_passhash9(const std::string& password, const std::string& hash) + + Takes a password and a passhash9 output and checks if the password + is the same as the one that was used to generate the passhash9 + output, returning a boolean true (same) or false (not same). + +Bcrypt +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Bcrypt is a password hashing scheme originally designed for use in +OpenBSD, but numerous other implementations exist. It is made +available by including ``bcrypt.h``, and provides the functions + +.. cpp:function:: std::string generate_bcrypt(const std::string& password, RandomNumberGenerator& rng, u16bit work_factor = 10) + +and + +.. cpp:function:: bool check_bcrypt(const std::string& password, const std::string& hash) + +These work in exactly the same way as the passhash9 password hashing +functions. + diff --git a/doc/pubkey.txt b/doc/pubkey.txt index 2b765cc10..1be471e1b 100644 --- a/doc/pubkey.txt +++ b/doc/pubkey.txt @@ -4,80 +4,240 @@ Public Key Cryptography ================================= -Quick Start ---------------------------------- +Public key cryptography (also called assymmetric cryptography) is a +collection of techniques allowing for encryption, signatures, and key +agreement. -Let's create a 2048-bit RSA private key, serialize the public key as a -PKCS #1 file with PEM encoding (which can be understood by many other -cryptographic programs), and then load it on another machine:: +Key Objects +---------------------------------------- - // everyone does: - AutoSeeded_RNG rng; +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. - // Alice - RSA_PrivateKey priv_rsa(rng, 2048 /* bits */); +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``. - std::string alice_pem = X509::PEM_encode(priv_rsa); +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. - // send alice_pem to Bob, who does +.. _creating_new_private_keys: - // Bob - std::auto_ptr<Public_Key> alice(load_key(alice_pem)); +Creating New Private Keys +---------------------------------------- - RSA_PublicKey* alice_rsa = dynamic_cast<RSA_PublicKey>(alice); - if(alice_rsa) - { - /* ... */ - } +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 New Public Key Pairs ---------------------------------- +.. 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_dompar`. 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 + +.. cpp:function:: DSA_PrivateKey::DSA_PrivateKey(RandomNumberGenerator& rng, const DL_Group& group, const BigInt& x = 0) + +.. cpp:function:: DH_PrivateKey::DH_PrivateKey(RandomNumberGenerator& rng, const DL_Group& group, const BigInt& x = 0) + +.. cpp:function:: NR_PrivateKey::NR_PrivateKey(RandomNumberGenerator& rng, const DL_Group& group, const BigInt& x = 0) + +.. 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. + +Finally, given an ``EC_Domain_Params`` object, you can create a new +ECDSA, ECDH, or GOST 34.10 private key with + +.. cpp:function:: ECDSA_PrivateKey::ECDSA_PrivateKey(RandomNumberGenerator& rng, const EC_Domain_Params& domain) + +.. cpp:function:: ECDH_PrivateKey::ECDH_PrivateKey(RandomNumberGenerator& rng, const EC_Domain_Params& domain) + +.. cpp:function:: GOST_3410_PrivateKey::GOST_3410_PrivateKey(RandomNumberGenerator& rng, const EC_Domain_Params& domain) + +Unlike the integer modulo a prime key types, the constructor that takes a +predefined ``BigInt`` private key value is different: + +.. cpp:function:: ECDSA_PrivateKey::ECDSA_PrivateKey(const EC_Domain_Params& domain, const BigInt& x) + +.. cpp:function:: ECDH_PrivateKey::ECDH_PrivateKey(const EC_Domain_Params& domain, const BigInt& x) + +.. cpp:function:: GOST_3410_PrivateKey::GOST_3410_PrivateKey(const EC_Domain_Params& domain, const BigInt& x) + +.. note:: + + It is likely that these constructors will be removed in a future + release, and a third optional parameter will be added to the + constructors described above, to match the integer modulo prime + versions. Only use them if you really need them. + + +Serializing Private Keys +---------------------------------------- + +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 = "") + + Takes any private key object, serializes it, encrypts it using + *password*, and returns a binary structure representing the private + key. + + The final (optional) argument, *pbe_algo*, specifies a particular + password based encryption (or PBE) algorithm. If you don't specify a + PBE, a sensible default will be used. + +.. 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. + +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. + +.. cpp:function:: SecureVector<byte> PKCS8::BER_encode(const Private_Key& key) + + Serializes the private key and returns the result. + +.. cpp:function:: std::string PKCS8::PEM_encode(const Private_Key& key) + + Serializes the private key, base64 encodes it, and returns the + result. + +Last but not least, there are some functions that will load (and +decrypt, if necessary) a PKCS #8 private key: + +.. cpp:function:: Private_Key* PKCS8::load_key(DataSource& in, RandomNumberGenerator& rng, const User_Interface& ui) + +.. cpp:function:: Private_Key* PKCS8::load_key(DataSource& in, RandomNumberGenerator& rng, std::string passphrase = "") + +.. cpp:function:: Private_Key* PKCS8::load_key(const std::string& filename, RandomNumberGenerator& rng, const User_Interface& ui) + +.. cpp:function:: Private_Key* PKCS8::load_key(const std::string& filename, RandomNumberGenerator& rng, const std::string& passphrase = "") + +The result is an object allocated using ``new``. + +The versions that pass the passphrase as a ``std::string`` are +primarily for compatibility, but they are useful in limited +circumstances. The ``User_Interface`` versions are how ``load_key`` is +implemented, and provides for much more flexibility. If the passphrase +passed in is not correct, then an exception is thrown and that is +that. However, if you pass in an UI object, then the UI object can +keep asking the user for the passphrase until they get it right (or +until they cancel the action, though the UI interface). A +``User_Interface`` has very little to do with talking to users; it's +just a way to glue together Botan and whatever user interface you +happen to be using. You can think of it as a user interface +interface. The default ``User_Interface`` is rather dumb, and acts +rather like the versions taking the ``std::string``; it tries the +passphrase passed in first, and then it cancels. + +.. note:: + + In a future version, it is likely that ``User_Interface`` will be + replaced by a simple callback using ``std::function``. + +.. _dl_group: -The library has interfaces for public key encryption, signatures, and -key agreement that do not require knowing the exact algorithm in -use. One place where we *do* need to know exactly what kind of -algorithm is in use is when we are creating a key. - -There are currently three kinds of public key algorithms in Botan: -ones based on integer factorization (RSA and Rabin-Williams), ones -based on the discrete logarithm problem in the integers modulo a prime -(DSA, Diffie-Hellman, Nyberg-Rueppel, and ElGamal), and ones based on -the discrete logarithm problem in an elliptic curve (ECDSA, ECDH, and -GOST 34.10). The systems based on discrete logarithms (in either -regular integers or elliptic curves) use a group (a mathematical -term), which can be shared among many keys. An elliptic curve group is -represented by the class ``EC_Domain_Params``, while a modulo-prime -group is represented by a ``DL_Group``. - -There are two ways to create a DL private key (such as -``DSA_PrivateKey``). One is to pass in just a ``DL_Group`` object -- a -new key will automatically be generated. The other involves passing in -a group to use, along with both the public and private values (private -value first). - -Since in integer factorization algorithms, the modulus used isn't -shared by other keys, we don't use this notion. You can create a new -key by passing in a ``size_t`` telling how long (in bits) the key -should be, or you can copy an pre-existing key by passing in the -appropriate parameters (primes, exponents, etc). For RSA and -Rabin-Williams (the two IF schemes in Botan), the parameters are all -``BigInt``: prime 1, prime 2, encryption exponent, decryption -exponent, modulus. The last two are optional, since they can easily be -derived from the first three. - -Creating a DL_Group +DL_Group ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -There are quite a few ways to get a ``DL_Group`` object. The best is -to use the function ``get_dl_group``, which takes a string naming a -group; it will either return that group, if it knows about it, or -throw an exception. Names it knows about include "modp/ietf/N" where N -is 768, 1024, 1536, 2048, 3072, 4096, 6144, and 8192 for -Diffie-Hellman and ElGamal. DSA-style groups are named "dsa/jce/N" for -N 512, 768, 1024, and "dsa/botan/N" for 2048 and 3072. +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. + +You can generate a new random group using + +.. cpp:function:: DL_Group::DL_Group(RandomNumberGenerator& rng, PrimeType type, size_t pbits, size_t qbits = 0) -You can also generate a new random group. This is not recommend, -because it is quite slow, especially for safe primes. + The *type* can be either ``Strong``, ``Prime_Subgroup``, or + ``DSA_Kosherizer``. *pbits* specifies the size of the prime in + bits. If the *type* is ``Prime_Subgroup`` or ``DSA_Kosherizer``, + then *qbits* specifies the size of the subgroup. + +You can export a ``DL_Group`` using + +.. cpp:function:: SecureVector<byte> DL_Group::DER_Encode(Format format) + +or + +.. cpp:function:: std::string DL_Group::PEM_encode(Format format) + +where *format* is any of + +.. _ec_dompar: + +EC_Domain_Params +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Key Checking --------------------------------- @@ -291,19 +451,9 @@ To import and export public keys, use: .. cpp:function:: MemoryVector<byte> X509::BER_encode(const Public_Key& key) - Takes any public key object, and returns a standard binary structure - representing the key which can be read by many other crypto - libraries. .. cpp:function:: std::string X509::PEM_encode(const Public_Key& key) - This formats the key the same as ``BER_encode``, but additionally - encodes it into a text format with identifying headers. Using PEM - encoding is *highly* recommended for many reasons, including - compatibility with other software, for transmission over 8-bit - unclean channels, because it can be identified by a human without - special tools, and because it sometimes allows more sane behavior of - tools that process the data. .. cpp:function:: Public_Key* X509::load_key(DataSource& in) @@ -325,74 +475,3 @@ To import and export public keys, use: Importing/Exporting Private Keys ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -There are two different options for private key import/export. The -first is a plaintext version of the private key. This is supported by -the following functions: - -.. cpp:function:: SecureVector<byte> PKCS8::BER_encode(const Private_Key& key) - -.. cpp:function:: std::string PKCS8::PEM_encode(const Private_Key& key) - -These functions are similiar to the X.509 functions described in -:ref:`import_export_public_keys`. The only difference is that they take -a ``Private_Key`` object instead. In most situations, using these -versions is a bad idea, because anyone can come along and grab the -private key without having to know any passwords or other -secrets. Unless you have very particular security requirements, always -use the versions that encrypt the key based on a passphrase described -below. For importing, the same functions can be used for encrypted and -unencrypted keys. - -The other way to export a PKCS #8 key is to first encode it in the -same manner as done above, then encrypt it using a passphrase, and -store the whole thing into another structure. This method is -definitely preferred, since otherwise the private key is -unprotected. The algorithms and structures used here are standardized -by PKCS #5 and PKCS #8, and can be read by many other crypto -libraries: - -.. cpp:function:: SecureVector<byte> PKCS8::BER_encode(const Private_Key& key, RandomNumberGenerator& rng, const std::string& pass, const std::string& pbe_algo = "") - -.. cpp:function:: std::string PKCS8::PEM_encode(const Private_Key& key, RandomNumberGenerator& rng, const std::string& pass, const std::string& pbe_algo = "") - - -There are three new arguments needed here to support the encryption -process. The first is a ``RandomNumberGenerator``, which is used to -generate salts to randomize the encryption. The ``pass`` argument is -the passphrase that will be used to encrypt the key. Both of these are -required. The final (optional) argument, ``pbe_algo``, specifies a -particular password based encryption (or PBE) algorithm. If you don't -specify a PBE, a sensible default will be used. - -Last but not least, there are some functions that will load (and -decrypt, if necessary) a PKCS #8 private key: - -.. cpp:function:: Private_Key* PKCS8::load_key(DataSource& in, RandomNumberGenerator& rng, const User_Interface& ui) - -.. cpp:function:: Private_Key* PKCS8::load_key(DataSource& in, RandomNumberGenerator& rng, std::string passphrase = "") - -.. cpp:function:: Private_Key* PKCS8::load_key(const std::string& filename, RandomNumberGenerator& rng, const User_Interface& ui) - -.. cpp:function:: Private_Key* PKCS8::load_key(const std::string& filename, RandomNumberGenerator& rng, const std::string& passphrase = "") - -The versions that pass the passphrase as a ``std::string`` are -primarily for compatibility, but they are useful in limited -circumstances. The ``User_Interface`` versions are how ``load_key`` is -implemented, and provides for much more flexibility. If the passphrase -passed in is not correct, then an exception is thrown and that is -that. However, if you pass in an UI object, then the UI object can -keep asking the user for the passphrase until they get it right (or -until they cancel the action, though the UI interface). A -``User_Interface`` has very little to do with talking to users; it's -just a way to glue together Botan and whatever user interface you -happen to be using. You can think of it as a user interface -interface. The default ``User_Interface`` is rather dumb, and acts -rather like the versions taking the ``std::string``; it tries the -passphrase passed in first, and then it cancels. - -All versions need access to a ``RandomNumberGenerator`` in order to -perform probabilistic tests on the loaded key material. - -After loading a key, you can use ``dynamic_cast`` to find out what -operations it supports, and use it appropriately. Remember to -``delete`` the object once you are done with it. diff --git a/doc/rng.txt b/doc/rng.txt new file mode 100644 index 000000000..756dccfc9 --- /dev/null +++ b/doc/rng.txt @@ -0,0 +1,112 @@ +.. _random_number_generators: + +Random Number Generators +--------------------------------- + +The random number generators provided in Botan are meant for creating +keys, IVs, padding, nonces, and anything else that requires 'random' +data. It is important to remember that the output of these classes +will vary, even if they are supplied with ethe same seed (ie, two +``Randpool`` objects with similar initial states will not produce +the same output, because the value of high resolution timers is added +to the state at various points). + +To ensure good quality output, a PRNG needs to be seeded with truly +random data (such as that produced by a hardware RNG). Typically, you +will use an ``EntropySource`` (see below). To add some (typically +application specific) entropy to a PRNG, you can use + +.. cpp:function:: void add_entropy(const byte* data, size_t length) + +Once a PRNG has been initialized, you can get a single byte of random +data by + +.. cpp:function:: byte random() + +or get a large block by calling + +.. cpp:function:: void randomize(byte* data, size_t length) + +Randpool +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``Randpool`` is the primary PRNG within Botan. In recent versions all +uses of it have been wrapped by an implementation of the X9.31 PRNG +(see below). If for some reason you should have cause to create a PRNG +instead of using the "global" one owned by the library, it would be +wise to consider the same on the grounds of general caution; while +``Randpool`` is designed with known attacks and PRNG weaknesses in +mind, it is not an standard/official PRNG. The remainder of this +section is a (fairly technical, though high-level) description of the +algorithms used in this PRNG. Unless you have a specific interest in +this subject, the rest of this section might prove somewhat +uninteresting. + +``Randpool`` has an internal state called pool, which is 512 bytes +long. This is where entropy is mixed into and extracted from. There is also a +small output buffer (called buffer), which holds the data which has already +been generated but has just not been output yet. + +It is based around a MAC and a block cipher (which are currently +HMAC(SHA-256) and AES-256). Where a specific size is mentioned, it +should be taken as a multiple of the cipher's block size. For example, +if a 256-bit block cipher were used instead of AES, all the sizes +internally would double. Every time some new output is needed, we +compute the MAC of a counter and a high resolution timer. The +resulting MAC is XORed into the output buffer (wrapping as needed), +and the output buffer is then encrypted with AES, producing 16 bytes +of output. + +After 8 blocks (or 128 bytes) have been produced, we mix the pool. To +do this, we first rekey both the MAC and the cipher; the new MAC key +is the MAC of the current pool under the old MAC key, while the new +cipher key is the MAC of the current pool under the just-chosen MAC +key. We then encrypt the entire pool in CBC mode, using the current +(unused) output buffer as the IV. We then generate a new output +buffer, using the mechanism described in the previous paragraph. + +To add randomness to the PRNG, we compute the MAC of the input and XOR +the output into the start of the pool. Then we remix the pool and +produce a new output buffer. The initial MAC operation should make it +very hard for chosen inputs to harm the security of ``Randpool``, and +as HMAC should be able to hold roughly 256 bits of state, it is +unlikely that we are wasting much input entropy (or, if we are, it +doesn't matter, because we have a very abundant supply). + +ANSI X9.31 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``ANSI_X931_PRNG`` is the standard issue X9.31 Appendix A.2.4 PRNG, +though using AES-256 instead of 3DES as the block cipher. This PRNG +implementation has been checked against official X9.31 test vectors. + +Internally, the PRNG holds a pointer to another PRNG (typically +Randpool). This internal PRNG generates the key and seed used by the +X9.31 algorithm, as well as the date/time vectors. Each time an X9.31 +PRNG object receives entropy, it passes it along to the PRNG it is +holding, and then pulls out some random bits to generate a new key and +seed. This PRNG considers itself seeded as soon as the internal PRNG +is seeded. + + +Entropy Sources +--------------------------------- + +An ``EntropySource`` is an abstract representation of some method of +gather "real" entropy. This tends to be very system dependent. The +*only* way you should use an ``EntropySource`` is to pass it to a PRNG +that will extract entropy from it -- never use the output directly for +any kind of key or nonce generation! + +``EntropySource`` has a pair of functions for getting entropy from +some external source, called ``fast_poll`` and ``slow_poll``. These +pass a buffer of bytes to be written; the functions then return how +many bytes of entropy were gathered. + +Note for writers of ``EntropySource`` subclasses: it isn't necessary +to use any kind of cryptographic hash on your output. The data +produced by an EntropySource is only used by an application after it +has been hashed by the ``RandomNumberGenerator`` that asked for the +entropy, thus any hashing you do will be wasteful of both CPU cycles +and entropy. + diff --git a/doc/ssl.txt b/doc/ssl.txt new file mode 100644 index 000000000..dd206d5fc --- /dev/null +++ b/doc/ssl.txt @@ -0,0 +1,10 @@ + +SSL/TLS +======================================== + +SSL/TLS Clients +---------------------------------------- + + +SSL/TLS Servers +---------------------------------------- diff --git a/doc/support.txt b/doc/support.txt new file mode 100644 index 000000000..a341d5830 --- /dev/null +++ b/doc/support.txt @@ -0,0 +1,19 @@ + +Commercial Support Options +======================================== + +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 + + * `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 027548b16..942d27f4c 100644 --- a/doc/x509.txt +++ b/doc/x509.txt @@ -187,11 +187,11 @@ Adding Certificates You can add new certificates to a certificate store using any of these functions: -.. cpp:function:: void add_cert(const X509_Certificate& cert, bool trusted = false) +.. cpp:function:: void X509_Store::add_cert(const X509_Certificate& cert, bool trusted = false) -.. cpp:function:: void add_cert(DataSource& source) +.. cpp:function:: void X509_Store::add_cert(DataSource& source) -.. cpp:function:: void add_trusted_certs(DataSource& source) +.. cpp:function:: void X509_Store::add_trusted_certs(DataSource& source) The versions that take a ``DataSource&`` will add all the certificates that it can find in that source. @@ -211,7 +211,7 @@ trusted. Adding CRLs ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. cpp:function:: X509_Code add_crl(const X509_CRL& crl) +.. cpp:function:: X509_Code X509_Store::add_crl(const X509_CRL& crl) This will process the CRL and mark the revoked certificates. This will also work if a revoked certificate is added to the store sometime @@ -277,7 +277,7 @@ Verifying Certificates There is a single function in ``X509_Store`` related to verifying a certificate: -.. .cpp:function:: X509_Code validate_cert(const X509_Certificate& cert, Cert_Usage usage = ANY) +.. .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``, |