summaryrefslogtreecommitdiffstats
path: root/comm/third_party/botan/doc/api_ref/pubkey.rst
diff options
context:
space:
mode:
Diffstat (limited to 'comm/third_party/botan/doc/api_ref/pubkey.rst')
-rw-r--r--comm/third_party/botan/doc/api_ref/pubkey.rst954
1 files changed, 954 insertions, 0 deletions
diff --git a/comm/third_party/botan/doc/api_ref/pubkey.rst b/comm/third_party/botan/doc/api_ref/pubkey.rst
new file mode 100644
index 0000000000..a8b93b4573
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/pubkey.rst
@@ -0,0 +1,954 @@
+Public Key Cryptography
+=================================
+
+Public key cryptography (also called asymmetric 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 inheritance 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
+similarly for ``Private_Key``.
+
+Types of ``Public_Key`` include ``RSA_PublicKey``, ``DSA_PublicKey``,
+``ECDSA_PublicKey``, ``ECKCDSA_PublicKey``, ``ECGDSA_PublicKey``, ``DH_PublicKey``, ``ECDH_PublicKey``,
+``Curve25519_PublicKey``, ``ElGamal_PublicKey``, ``McEliece_PublicKey``, ``XMSS_PublicKey``
+and ``GOST_3410_PublicKey``. There are corresponding ``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
+
+.. 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*.
+
+ RSA key generation is relatively slow, and can take an unpredictable
+ amount of time. Generating a 2048 bit RSA key might take 5 to 10
+ seconds on a slow machine like a Raspberry Pi 2. Even on a fast
+ desktop it might take up to half a second. In a GUI blocking for
+ that long can be a problem. The usual approach is to perform key
+ generation in a new thread, with a animated modal UI element so the
+ user knows the application is still alive. If you wish to provide a
+ progress estimate things get a bit complicated but some library
+ users documented their approach in
+ `a blog post <https://medium.com/nexenio/indicating-progress-of-rsa-key-pair-generation-the-practical-approach-a049ba829dbe>`_.
+
+Algorithms based on the discrete-logarithm problem use 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 correspondingly the
+slower the operations will be.
+
+Given a ``DL_Group``, you can create new DSA, Diffie-Hellman and ElGamal 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:: ElGamal_PrivateKey::ElGamal_PrivateKey(RandomNumberGenerator& rng, \
+ const DL_Group& group, const BigInt& x = 0)
+
+ The optional *x* parameter to each of these constructors 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, ECKCDSA, ECGDSA,
+ECDH, or GOST 34.10-2001 private key with
+
+.. cpp:function:: ECDSA_PrivateKey::ECDSA_PrivateKey(RandomNumberGenerator& rng, \
+ const EC_Group& domain, const BigInt& x = 0)
+
+.. cpp:function:: ECKCDSA_PrivateKey::ECKCDSA_PrivateKey(RandomNumberGenerator& rng, \
+ const EC_Group& domain, const BigInt& x = 0)
+
+.. cpp:function:: ECGDSA_PrivateKey::ECGDSA_PrivateKey(RandomNumberGenerator& rng, \
+ const EC_Group& domain, const BigInt& x = 0)
+
+.. cpp:function:: ECDH_PrivateKey::ECDH_PrivateKey(RandomNumberGenerator& rng, \
+ const EC_Group& domain, const BigInt& x = 0)
+
+.. cpp:function:: GOST_3410_PrivateKey::GOST_3410_PrivateKey(RandomNumberGenerator& rng, \
+ const EC_Group& domain, const BigInt& x = 0)
+
+.. _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.
+
+.. cpp:function:: secure_vector<uint8_t> 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.
+
+ The currently supported PBE is PBES2 from PKCS5. Format is as follows:
+ ``PBE-PKCS5v20(CIPHER,PBKDF)``. Since 2.8.0, ``PBES2(CIPHER,PBKDF)`` also works.
+ Cipher can be any block cipher with /CBC or /GCM appended, for example
+ "AES-128/CBC" or "Camellia-256/GCM". For best interop with other systems, use
+ AES in CBC mode. The PBKDF can be either the name of a hash function (in which
+ case PBKDF2 is used with that hash) or "Scrypt", which causes the scrypt
+ memory hard password hashing function to be used. Scrypt is supported since
+ version 2.7.0.
+
+ Use `PBE-PKCS5v20(AES-256/CBC,SHA-256)` if you want to ensure the keys can
+ be imported by different software packages. Use
+ `PBE-PKCS5v20(AES-256/GCM,Scrypt)` for best security assuming you do not
+ care about interop.
+
+ For ciphers you can use anything which has an OID defined for CBC, GCM or SIV
+ modes. Currently this includes AES, Camellia, Serpent, Twofish, and SM4. Most
+ other libraries only support CBC mode for private key encryption. GCM has
+ been supported in PBES2 since 1.11.10. SIV has been supported since 2.8.
+
+.. 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 unencrypted 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:: secure_vector<uint8_t> 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 = "")
+
+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
+successful). 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::
+
+ In a future version, it is likely that ``User_Interface`` will be
+ replaced by a simple callback using ``std::function``.
+
+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
+ situation, and canceling the operation in progress).
+
+.. _serializing_public_keys:
+
+Serializing Public Keys
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+To import and export public keys, use:
+
+.. cpp:function:: std::vector<uint8_t> X509::BER_encode(const Public_Key& key)
+
+.. cpp:function:: std::string X509::PEM_encode(const Public_Key& key)
+
+.. cpp:function:: Public_Key* X509::load_key(DataSource& in)
+
+.. cpp:function:: Public_Key* X509::load_key(const secure_vector<uint8_t>& buffer)
+
+.. cpp:function:: Public_Key* X509::load_key(const std::string& filename)
+
+ These functions operate in the same way as the ones described in
+ :ref:`serializing_private_keys`, except that no encryption option is
+ available.
+
+.. _dl_group:
+
+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.
+
+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 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 keys. They can also be used with
+ Diffie-Hellman and ElGamal, but this is less common. The currently available
+ groups are "dsa/jce/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)
+
+ 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 serialize a ``DL_Group`` using
+
+.. cpp:function:: secure_vector<uint8_t> DL_Group::DER_Encode(Format format)
+
+or
+
+.. cpp:function:: std::string DL_Group::PEM_encode(Format format)
+
+where *format* is any of
+
+* ``ANSI_X9_42`` (or ``DH_PARAMETERS``) for modp groups
+* ``ANSI_X9_57`` (or ``DSA_PARAMETERS``) for DSA-style groups
+* ``PKCS_3`` is an older format for modp groups; it should only
+ be used for backwards compatibility.
+
+You can reload a serialized group using
+
+.. cpp:function:: void DL_Group::BER_decode(DataSource& source, Format format)
+
+.. cpp:function:: void DL_Group::PEM_decode(DataSource& source)
+
+Code Example
+"""""""""""""""""
+The example below creates a new 2048 bit ``DL_Group``, prints the generated
+parameters and ANSI_X9_42 encodes the created group for further usage with DH.
+
+.. code-block:: cpp
+
+ #include <botan/dl_group.h>
+ #include <botan/auto_rng.h>
+ #include <botan/rng.h>
+ #include <iostream>
+
+ int main()
+ {
+ std::unique_ptr<Botan::RandomNumberGenerator> rng(new Botan::AutoSeeded_RNG);
+ std::unique_ptr<Botan::DL_Group> group(new Botan::DL_Group(*rng.get(), Botan::DL_Group::Strong, 2048));
+ std::cout << std::endl << "p: " << group->get_p();
+ std::cout << std::endl << "q: " << group->get_q();
+ std::cout << std::endl << "g: " << group->get_q();
+ std::cout << std::endl << "ANSI_X9_42: " << std::endl << group->PEM_encode(Botan::DL_Group::ANSI_X9_42);
+
+ return 0;
+ }
+
+
+.. _ec_group:
+
+EC_Group
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+An ``EC_Group`` is initialized by passing the name of the
+group to be used to the constructor. These groups have
+semi-standardized names like "secp256r1" and "brainpool512r1".
+
+Key Checking
+---------------------------------
+
+Most public key algorithms have limitations or restrictions on their
+parameters. For example RSA requires an odd exponent, and algorithms
+based on the discrete logarithm problem need a generator > 1.
+
+Each 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.
+
+ 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.
+
+As key checks are not automatically performed they must be called
+manually after loading keys from untrusted sources. If a key from an untrusted source
+is not checked, the implementation might be vulnerable to algorithm specific attacks.
+
+The following example loads the Subject Public Key from the x509 certificate ``cert.pem`` and checks the
+loaded key. If the key check fails a respective error is thrown.
+
+.. code-block:: cpp
+
+ #include <botan/x509cert.h>
+ #include <botan/auto_rng.h>
+ #include <botan/rng.h>
+
+ int main()
+ {
+ Botan::X509_Certificate cert("cert.pem");
+ std::unique_ptr<Botan::RandomNumberGenerator> rng(new Botan::AutoSeeded_RNG);
+ std::unique_ptr<Botan::Public_Key> key(cert.subject_public_key());
+ if(!key->check_key(*rng.get(), false))
+ {
+ throw std::invalid_argument("Loaded key is invalid");
+ }
+ }
+
+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.
+
+The primary interface for encryption is
+
+.. cpp:class:: PK_Encryptor
+
+ .. cpp:function:: secure_vector<uint8_t> encrypt( \
+ const uint8_t* in, size_t length, RandomNumberGenerator& rng) const
+
+ .. cpp:function:: secure_vector<uint8_t> encrypt( \
+ const std::vector<uint8_t>& in, RandomNumberGenerator& rng) const
+
+ These encrypt a message, returning the ciphertext.
+
+ .. 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 three available in the
+library, :cpp:class:`PK_Encryptor_EME`, :cpp:class:`DLIES_Encryptor` and
+:cpp:class:`ECIES_Encryptor`. DLIES is a hybrid encryption scheme (from
+IEEE 1363) that uses the DH key agreement technique in combination with a KDF, a
+MAC and a symmetric encryption algorithm to perform message encryption. ECIES is
+similar to DLIES, but uses ECDH for the key agreement. 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*.
+
+ The recommended values for *eme* is "EME1(SHA-1)" or "EME1(SHA-256)". If
+ you need compatibility with protocols using the PKCS #1 v1.5 standard,
+ you can also use "EME-PKCS1-v1_5".
+
+.. cpp:class:: DLIES_Encryptor
+
+ Available in the header ``dlies.h``
+
+ .. cpp:function:: DLIES_Encryptor(const DH_PrivateKey& own_priv_key, \
+ RandomNumberGenerator& rng, KDF* kdf, MessageAuthenticationCode* mac, \
+ size_t mac_key_len = 20)
+
+ Where *kdf* is a key derivation function (see
+ :ref:`key_derivation_function`) and *mac* is a
+ MessageAuthenticationCode. The encryption is performed by XORing the
+ message with a stream of bytes provided by the KDF.
+
+ .. cpp:function:: DLIES_Encryptor(const DH_PrivateKey& own_priv_key, \
+ RandomNumberGenerator& rng, KDF* kdf, Cipher_Mode* cipher, \
+ size_t cipher_key_len, MessageAuthenticationCode* mac, \
+ size_t mac_key_len = 20)
+
+ Instead of XORing the message a block cipher can be specified.
+
+.. cpp:class:: ECIES_Encryptor
+
+ Available in the header ``ecies.h``.
+
+ Parameters for encryption and decryption are set by the
+ :cpp:class:`ECIES_System_Params` class which stores the EC domain parameters,
+ the KDF (see :ref:`key_derivation_function`), the cipher (see
+ :ref:`cipher_modes`) and the MAC.
+
+ .. cpp:function:: ECIES_Encryptor(const PK_Key_Agreement_Key& private_key, \
+ const ECIES_System_Params& ecies_params, \
+ RandomNumberGenerator& rng)
+
+ Where *private_key* is the key to use for the key agreement. The system
+ parameters are specified in *ecies_params* and the RNG to use is passed in
+ *rng*.
+
+ .. cpp:function:: ECIES_Encryptor(RandomNumberGenerator& rng, \
+ const ECIES_System_Params& ecies_params)
+
+ Creates an ephemeral private key which is used for the key agreement.
+
+The decryption classes are named :cpp:class:`PK_Decryptor`,
+:cpp:class:`PK_Decryptor_EME`, :cpp:class:`DLIES_Decryptor` and
+:cpp:class:`ECIES_Decryptor`. They are created in the exact same way, except
+they take the private key, and the processing function is named ``decrypt``.
+
+
+Botan implements the following encryption algorithms and padding schemes:
+
+1. RSA
+ - "PKCS1v15" || "EME-PKCS1-v1_5"
+ - "OAEP" || "EME-OAEP" || "EME1" || "EME1(SHA-1)" || "EME1(SHA-256)"
+#. DLIES
+#. ECIES
+#. SM2
+
+Code Example
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+The following Code sample reads a PKCS #8 keypair from the passed location and
+subsequently encrypts a fixed plaintext with the included public key, using EME1
+with SHA-256. For the sake of completeness, the ciphertext is then decrypted using
+the private key.
+
+.. code-block:: cpp
+
+ #include <botan/pkcs8.h>
+ #include <botan/hex.h>
+ #include <botan/pk_keys.h>
+ #include <botan/pubkey.h>
+ #include <botan/auto_rng.h>
+ #include <botan/rng.h>
+ #include <iostream>
+ int main (int argc, char* argv[])
+ {
+ if(argc!=2)
+ return 1;
+ std::string plaintext("Your great-grandfather gave this watch to your granddad for good luck. Unfortunately, Dane's luck wasn't as good as his old man's.");
+ std::vector<uint8_t> pt(plaintext.data(),plaintext.data()+plaintext.length());
+ std::unique_ptr<Botan::RandomNumberGenerator> rng(new Botan::AutoSeeded_RNG);
+
+ //load keypair
+ std::unique_ptr<Botan::Private_Key> kp(Botan::PKCS8::load_key(argv[1],*rng.get()));
+
+ //encrypt with pk
+ Botan::PK_Encryptor_EME enc(*kp,*rng.get(), "EME1(SHA-256)");
+ std::vector<uint8_t> ct = enc.encrypt(pt,*rng.get());
+
+ //decrypt with sk
+ Botan::PK_Decryptor_EME dec(*kp,*rng.get(), "EME1(SHA-256)");
+ std::cout << std::endl << "enc: " << Botan::hex_encode(ct) << std::endl << "dec: "<< Botan::hex_encode(dec.decrypt(ct));
+
+ return 0;
+ }
+
+
+Signatures
+---------------------------------
+
+Signature generation is performed using
+
+.. cpp:class:: PK_Signer
+
+ .. cpp:function:: PK_Signer(const Private_Key& key, \
+ const std::string& emsa, \
+ 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, ECKCDSA,
+ ECGDSA, GOST 34.10-2001. Other signature schemes may be supported in the future.
+
+ .. note::
+
+ Botan both supports non-deterministic and deterministic (as per RFC
+ 6979) DSA and ECDSA signatures. Deterministic signatures are compatible
+ in the way that they can be verified with a non-deterministic implementation.
+ If the ``rfc6979`` module is enabled, deterministic DSA and ECDSA signatures
+ will be generated.
+
+ 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 compatibility 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, ECKCDSA, ECGDSA and
+ GOST 34.10-2001 you should use EMSA1.
+
+ The *format* defaults to ``IEEE_1363`` which is the only available
+ format for RSA. For DSA, ECDSA, ECGDSA and ECKCDSA you can also use
+ ``DER_SEQUENCE``, which will format the signature as an ASN.1
+ SEQUENCE value.
+
+ .. cpp:function:: void update(const uint8_t* in, size_t length)
+ .. cpp:function:: void update(const std::vector<uint8_t>& in)
+ .. cpp:function:: void update(uint8_t in)
+
+ These add more data to be included in the signature
+ computation. Typically, the input will be provided directly to a
+ hash function.
+
+ .. cpp:function:: secure_vector<uint8_t> signature(RandomNumberGenerator& rng)
+
+ Creates the signature and returns it
+
+ .. cpp:function:: secure_vector<uint8_t> sign_message( \
+ const uint8_t* in, size_t length, RandomNumberGenerator& rng)
+
+ .. cpp:function:: secure_vector<uint8_t> sign_message( \
+ const std::vector<uint8_t>& in, RandomNumberGenerator& rng)
+
+ These functions are equivalent to calling
+ :cpp:func:`PK_Signer::update` and then
+ :cpp:func:`PK_Signer::signature`. Any data previously provided
+ using ``update`` will be included.
+
+Signatures are verified using
+
+.. cpp:class:: PK_Verifier
+
+ .. cpp:function:: PK_Verifier(const Public_Key& pub_key, \
+ const std::string& emsa, Signature_Format format = IEEE_1363)
+
+ Construct a new verifier for signatures associated with public
+ key *pub_key*. The *emsa* and *format* should be the same as
+ that used by the signer.
+
+ .. cpp:function:: void update(const uint8_t* in, size_t length)
+ .. cpp:function:: void update(const std::vector<uint8_t>& in)
+ .. cpp:function:: void update(uint8_t in)
+
+ Add further message data that is purportedly associated with the
+ signature that will be checked.
+
+ .. cpp:function:: bool check_signature(const uint8_t* sig, size_t length)
+ .. cpp:function:: bool check_signature(const std::vector<uint8_t>& sig)
+
+ Check to see if *sig* is a valid signature for the message data
+ that was written in. Return true if so. This function clears the
+ internal message state, so after this call you can call
+ :cpp:func:`PK_Verifier::update` to start verifying another
+ message.
+
+ .. cpp:function:: bool verify_message(const uint8_t* msg, size_t msg_length, \
+ const uint8_t* sig, size_t sig_length)
+
+ .. cpp:function:: bool verify_message(const std::vector<uint8_t>& msg, \
+ const std::vector<uint8_t>& sig)
+
+ These are equivalent to calling :cpp:func:`PK_Verifier::update`
+ on *msg* and then calling :cpp:func:`PK_Verifier::check_signature`
+ on *sig*.
+
+
+Botan implements the following signature algorithms:
+
+1. RSA
+#. DSA
+#. ECDSA
+#. ECGDSA
+#. ECKDSA
+#. GOST 34.10-2001
+#. Ed25519
+#. SM2
+
+Code Example
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The following sample program below demonstrates the generation of a new ECDSA keypair over the curve secp512r1
+and a ECDSA signature using EMSA1 with SHA-256. Subsequently the computed signature is validated.
+
+.. code-block:: cpp
+
+ #include <botan/auto_rng.h>
+ #include <botan/ecdsa.h>
+ #include <botan/ec_group.h>
+ #include <botan/pubkey.h>
+ #include <botan/hex.h>
+ #include <iostream>
+
+ int main()
+ {
+ Botan::AutoSeeded_RNG rng;
+ // Generate ECDSA keypair
+ Botan::ECDSA_PrivateKey key(rng, Botan::EC_Group("secp521r1"));
+
+ std::string text("This is a tasty burger!");
+ std::vector<uint8_t> data(text.data(),text.data()+text.length());
+ // sign data
+ Botan::PK_Signer signer(key, rng, "EMSA1(SHA-256)");
+ signer.update(data);
+ std::vector<uint8_t> signature = signer.signature(rng);
+ std::cout << "Signature:" << std::endl << Botan::hex_encode(signature);
+ // verify signature
+ Botan::PK_Verifier verifier(key, "EMSA1(SHA-256)");
+ verifier.update(data);
+ std::cout << std::endl << "is " << (verifier.check_signature(signature)? "valid" : "invalid");
+ return 0;
+ }
+
+
+Ed25519 Variants
+^^^^^^^^^^^^^^^^^^
+
+Most signature schemes in Botan follow a hash-then-sign paradigm. That is, the
+entire message is digested to a fixed length representative using a collision
+resistant hash function, and then the digest is signed. Ed25519 instead signs
+the message directly. This is beneficial, in that the Ed25519 design should
+remain secure even in the (extremely unlikely) event that a collision attack on
+SHA-512 is found. However it means the entire message must be buffered in
+memory, which can be a problem for many applications which might need to sign
+large inputs. To use this variety of Ed25519, use a padding name of "Pure".
+
+Ed25519ph (pre-hashed) instead hashes the message with SHA-512 and then signs
+the digest plus a special prefix specified in RFC 8032. To use it, specify
+padding name "Ed25519ph".
+
+Another variant of pre-hashing is used by GnuPG. There the message is digested
+with any hash function, then the digest is signed. To use it, specify any valid
+hash function. Even if SHA-512 is used, this variant is not compatible with
+Ed25519ph.
+
+For best interop with other systems, prefer "Ed25519ph".
+
+Key Agreement
+---------------------------------
+
+You can get a hold of a ``PK_Key_Agreement_Scheme`` object by calling
+``get_pk_kas`` with a key that is of a type that supports key
+agreement (such as a Diffie-Hellman key stored in a ``DH_PrivateKey``
+object), and the name of a key derivation function. This can be "Raw",
+meaning the output of the primitive itself is returned as the key, or
+"KDF1(hash)" or "KDF2(hash)" where "hash" is any string you happen to
+like (hopefully you like strings like "SHA-256" or "RIPEMD-160"), or
+"X9.42-PRF(keywrap)", which uses the PRF specified in ANSI X9.42. It
+takes the name or OID of the key wrap algorithm that will be used to
+encrypt a content encryption key.
+
+How key agreement works is that you trade public values with some
+other party, and then each of you runs a computation with the other's
+value and your key (this should return the same result to both
+parties). This computation can be called by using
+``derive_key`` with either a byte array/length pair, or a
+``secure_vector<uint8_t>`` than holds the public value of the other
+party. The last argument to either call is a number that specifies how
+long a key you want.
+
+Depending on the KDF you're using, you *might not* get back a key
+of the size you requested. In particular "Raw" will return a number
+about the size of the Diffie-Hellman modulus, and KDF1 can only return
+a key that is the same size as the output of the hash. KDF2, on the
+other hand, will always give you a key exactly as long as you request,
+regardless of the underlying hash used with it. The key returned is a
+``SymmetricKey``, ready to pass to a block cipher, MAC, or other
+symmetric algorithm.
+
+The public value that should be used can be obtained by calling
+``public_data``, which exists for any key that is associated with a
+key agreement algorithm. It returns a ``secure_vector<uint8_t>``.
+
+"KDF2(SHA-256)" is by far the preferred algorithm for key derivation
+in new applications. The X9.42 algorithm may be useful in some
+circumstances, but unless you need X9.42 compatibility, KDF2 is easier
+to use.
+
+
+Botan implements the following key agreement methods:
+
+1. ECDH over GF(p) Weierstrass curves
+#. ECDH over x25519
+#. DH over prime fields
+#. McEliece
+#. NewHope
+
+Code Example
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The code below performs an unauthenticated ECDH key agreement using the secp521r elliptic curve and
+applies the key derivation function KDF2(SHA-256) with 256 bit output length to the computed shared secret.
+
+.. code-block:: cpp
+
+ #include <botan/auto_rng.h>
+ #include <botan/ecdh.h>
+ #include <botan/ec_group.h>
+ #include <botan/pubkey.h>
+ #include <botan/hex.h>
+ #include <iostream>
+
+ int main()
+ {
+ Botan::AutoSeeded_RNG rng;
+ // ec domain and
+ Botan::EC_Group domain("secp521r1");
+ std::string kdf = "KDF2(SHA-256)";
+ // generate ECDH keys
+ Botan::ECDH_PrivateKey keyA(rng, domain);
+ Botan::ECDH_PrivateKey keyB(rng, domain);
+ // Construct key agreements
+ Botan::PK_Key_Agreement ecdhA(keyA,rng,kdf);
+ Botan::PK_Key_Agreement ecdhB(keyB,rng,kdf);
+ // Agree on shared secret and derive symmetric key of 256 bit length
+ Botan::secure_vector<uint8_t> sA = ecdhA.derive_key(32,keyB.public_value()).bits_of();
+ Botan::secure_vector<uint8_t> sB = ecdhB.derive_key(32,keyA.public_value()).bits_of();
+
+ if(sA != sB)
+ return 1;
+
+ std::cout << "agreed key: " << std::endl << Botan::hex_encode(sA);
+ return 0;
+ }
+
+
+.. _mceliece:
+
+McEliece
+--------------------------
+
+McEliece is a cryptographic scheme based on error correcting codes which is
+thought to be resistant to quantum computers. First proposed in 1978, it is fast
+and patent-free. Variants have been proposed and broken, but with suitable
+parameters the original scheme remains secure. However the public keys are quite
+large, which has hindered deployment in the past.
+
+The implementation of McEliece in Botan was contributed by cryptosource GmbH. It
+is based on the implementation HyMES, with the kind permission of Nicolas
+Sendrier and INRIA to release a C++ adaption of their original C code under the
+Botan license. It was then modified by Falko Strenzke to add side channel and
+fault attack countermeasures. You can read more about the implementation at
+http://www.cryptosource.de/docs/mceliece_in_botan.pdf
+
+Encryption in the McEliece scheme consists of choosing a message block of size
+`n`, encoding it in the error correcting code which is the public key, then
+adding `t` bit errors. The code is created such that knowing only the public
+key, decoding `t` errors is intractable, but with the additional knowledge of
+the secret structure of the code a fast decoding technique exists.
+
+The McEliece implementation in HyMES, and also in Botan, uses an optimization to
+reduce the public key size, by converting the public key into a systemic code.
+This means a portion of the public key is a identity matrix, and can be excluded
+from the published public key. However it also means that in McEliece the
+plaintext is represented directly in the ciphertext, with only a small number of
+bit errors. Thus it is absolutely essential to only use McEliece with a CCA2
+secure scheme.
+
+One such scheme, KEM, is provided in Botan currently. It it a somewhat unusual
+scheme in that it outputs two values, a symmetric key for use with an AEAD, and
+an encrypted key. It does this by choosing a random plaintext (n - log2(n)*t
+bits) using ``McEliece_PublicKey::random_plaintext_element``. Then a random
+error mask is chosen and the message is coded and masked. The symmetric key is
+SHA-512(plaintext || error_mask). As long as the resulting key is used with a
+secure AEAD scheme (which can be used for transporting arbitrary amounts of
+data), CCA2 security is provided.
+
+In ``mcies.h`` there are functions for this combination:
+
+.. cpp:function:: secure_vector<uint8_t> mceies_encrypt(const McEliece_PublicKey& pubkey, \
+ const secure_vector<uint8_t>& pt, \
+ uint8_t ad[], size_t ad_len, \
+ RandomNumberGenerator& rng, \
+ const std::string& aead = "AES-256/OCB")
+
+.. cpp:function:: secure_vector<uint8_t> mceies_decrypt(const McEliece_PrivateKey& privkey, \
+ const secure_vector<uint8_t>& ct, \
+ uint8_t ad[], size_t ad_len, \
+ const std::string& aead = "AES-256/OCB")
+
+For a given security level (SL) a McEliece key would use
+parameters n and t, and have the corresponding key sizes listed:
+
++-----+------+-----+---------------+----------------+
+| SL | n | t | public key KB | private key KB |
++=====+======+=====+===============+================+
+| 80 | 1632 | 33 | 59 | 140 |
++-----+------+-----+---------------+----------------+
+| 107 | 2280 | 45 | 128 | 300 |
++-----+------+-----+---------------+----------------+
+| 128 | 2960 | 57 | 195 | 459 |
++-----+------+-----+---------------+----------------+
+| 147 | 3408 | 67 | 265 | 622 |
++-----+------+-----+---------------+----------------+
+| 191 | 4624 | 95 | 516 | 1234 |
++-----+------+-----+---------------+----------------+
+| 256 | 6624 | 115 | 942 | 2184 |
++-----+------+-----+---------------+----------------+
+
+You can check the speed of McEliece with the suggested parameters above
+using ``botan speed McEliece``
+
+
+eXtended Merkle Signature Scheme (XMSS)
+----------------------------------------
+
+Botan implements the single tree version of the eXtended Merkle Signature
+Scheme (XMSS) using Winternitz One Time Signatures+ (WOTS+). The implementation
+is based on `RFC 8391 "XMSS: eXtended Merkle Signature Scheme"
+<https://tools.ietf.org/html/rfc8391>`_.
+
+XMSS uses the Botan interfaces for public key cryptography.
+The following algorithms are implemented:
+
+1. XMSS-SHA2_10_256
+# XMSS-SHA2_16_256
+# XMSS-SHA2_20_256
+# XMSS-SHA2_10_512
+# XMSS-SHA2_16_512
+# XMSS-SHA2_20_512
+# XMSS-SHAKE_10_256
+# XMSS-SHAKE_16_256
+# XMSS-SHAKE_20_256
+# XMSS-SHAKE_10_512
+# XMSS-SHAKE_16_512
+# XMSS-SHAKE_20_512
+
+The algorithm name contains the hash function name, tree height and digest
+width defined by the corresponding parameter set. Choosing `XMSS-SHA2_10_256`
+for instance will use the SHA2-256 hash function to generate a tree of height
+ten.
+
+Code Example
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The following code snippet shows a minimum example on how to create an XMSS
+public/private key pair and how to use these keys to create and verify a
+signature:
+
+.. code-block:: cpp
+
+ #include <iostream>
+ #include <botan/secmem.h>
+ #include <botan/auto_rng.h>
+ #include <botan/xmss.h>
+
+ int main()
+ {
+ // Create a random number generator used for key generation.
+ Botan::AutoSeeded_RNG rng;
+
+ // create a new public/private key pair using SHA2 256 as hash
+ // function and a tree height of 10.
+ Botan::XMSS_PrivateKey private_key(
+ Botan::XMSS_Parameters::xmss_algorithm_t::XMSS_SHA2_10_256,
+ rng);
+ Botan::XMSS_PublicKey public_key(private_key);
+
+ // create signature operation using the private key.
+ std::unique_ptr<Botan::PK_Ops::Signature> sig_op =
+ private_key.create_signature_op(rng, "", "");
+
+ // create and sign a message using the signature operation.
+ Botan::secure_vector<uint8_t> msg { 0x01, 0x02, 0x03, 0x04 };
+ sig_op->update(msg.data(), msg.size());
+ Botan::secure_vector<uint8_t> sig = sig_op->sign(rng);
+
+ // create verification operation using the public key
+ std::unique_ptr<Botan::PK_Ops::Verification> ver_op =
+ public_key.create_verification_op("", "");
+
+ // verify the signature for the previously generated message.
+ ver_op->update(msg.data(), msg.size());
+ if(ver_op->is_valid_signature(sig.data(), sig.size()))
+ {
+ std::cout << "Success." << std::endl;
+ }
+ else
+ {
+ std::cout << "Error." << std::endl;
+ }
+ }