Elliptic Curve Operations
============================

In addition to high level operations for signatures, key agreement,
and message encryption using elliptic curve cryptography, the library
contains lower level interfaces for performing operations such as
elliptic curve point multiplication.

Only curves over prime fields are supported.

.. warning::

   You should only use these interfaces if you know what you are doing.

.. note::

   Prior to 3.6.0, Botan used :cpp:class:`BigInt` to represent scalar values,
   and ``EC_Point`` for elliptic curve points in Jacobian projective
   form. ``EC_Point`` still exists, but is intentionally undocumented, and will
   be removed in Botan4.

.. cpp:class:: EC_Group

      .. cpp:function:: EC_Group::from_OID(const OID& oid)

         Initialize an ``EC_Group`` using an OID referencing the curve
         parameters.

      .. cpp:function:: EC_Group::from_name(std::string_view name)

         Initialize an ``EC_Group`` using a name (such as "secp256r1")

      .. cpp:function:: EC_Group::from_PEM(std::string_view pem)

         Initialize an ``EC_Group`` using a PEM encoded parameter block

      .. cpp:function:: EC_Group(const OID& oid, \
               const BigInt& p, \
               const BigInt& a, \
               const BigInt& b, \
               const BigInt& base_x, \
               const BigInt& base_y, \
               const BigInt& order)

          Create an application specific elliptic curve.

          .. warning::

             Using application specific curves may be hazardous to your health.

          This constructor imposes the following restrictions:

          * The prime must be between 128 and 512 bits, and a multiple of 32 bits.
          * As a special extension regarding the above restriction, the prime may
            alternately be 521 bits, in which case it must be exactly 2**521-1
          * The prime must be congruent to 3 modulo 4
          * The group order must have identical bitlength to the prime
          * No cofactor is allowed
          * An object identifier must be specified

      .. cpp:function:: EC_Group(const BigInt& p, \
               const BigInt& a, \
               const BigInt& b, \
               const BigInt& base_x, \
               const BigInt& base_y, \
               const BigInt& order, \
               const BigInt& cofactor, \
               const OID& oid = OID())

          This is a deprecated alternative interface for creating application
          specific elliptic curves.

          This does not impose the same restrictions regarding use of
          arbitrary sized groups, use of a cofactor, etc, and the
          object identifier is optional.

          .. warning::

             If you are using this constructor, and cannot use the
             non-deprecated constructor due to the restrictions it places on the
             curve parameters, be aware that this constructor will be dropped
             in Botan 4. Please open an issue on Github describing your usecase.

      .. cpp:function:: EC_Group(std::span<const uint8_t> ber_encoding)

         Initialize an ``EC_Group`` by decoding a DER encoded parameter block.

      .. cpp:function:: std::vector<uint8_t> DER_encode() const

         Return the DER encoding of this group.

      .. cpp:function:: std::vector<uint8_t> DER_encode(EC_Group_Encoding form) const

         Return the DER encoding of this group. This variant is deprecated, but allows
         the curve to be encoded using the explicit (vs OID) encoding. All support for
         explicitly encoded elliptic curves is deprecated and will be removed in Botan4.

      .. cpp:function:: std::string PEM_encode() const

         Return the PEM encoding of this group (base64 of DER encoding plus
         header/trailer).

      .. cpp:function:: const BigInt& get_p() const

         Return the prime modulus as a :cpp:class:`BigInt`

      .. cpp:function:: const BigInt& get_a() const

         Return the ``a`` parameter of the elliptic curve equation as a :cpp:class:`BigInt`

      .. cpp:function:: const BigInt& get_b() const

         Return the ``b`` parameter of the elliptic curve equation as a :cpp:class:`BigInt`

      .. cpp:function:: const EC_Point& get_base_point() const

         Return the groups base point element as a :cpp:class:`BigInt`

      .. cpp:function:: const BigInt& get_g_x() const

         Return the x coordinate of the base point element as a :cpp:class:`BigInt`

      .. cpp:function:: const BigInt& get_g_y() const

         Return the y coordinate of the base point element as a :cpp:class:`BigInt`

      .. cpp:function:: const BigInt& get_order() const

         Return the order of the group generated by the base point as a :cpp:class:`BigInt`

      .. cpp:function:: const BigInt& get_cofactor() const

         Return the cofactor of the curve. In most cases this will be 1.

         .. warning::

            In Botan4 all support for elliptic curves group with a
            cofactor > 1 will be removed.

      .. cpp:function:: const OID& get_curve_oid() const

         Return the OID used to identify this curve. May be empty.

      .. cpp:function:: bool verify_group(RandomNumberGenerator& rng, bool strong = false) const

         Attempt to verify the group seems valid.

      .. cpp:function:: static const std::set<std::string>& known_named_groups()

         Return a list of known groups, ie groups for which ``EC_Group::from_name(name)``
         will succeed.

.. cpp:class:: EC_Scalar

   An elliptic curve scalar; that is, an integer in the range ``[0,n)`` where
   ``n`` is size of the prime order subgroup generated by the standard group
   generator.

   Note that while zero is a representable value, some of the
   deserialization functions reject zero.

   .. cpp:function:: static std::optional<EC_Scalar> deserialize(const EC_Group& group, std::span<const uint8_t> buf)

      Deserialize a scalar. The bytestring must be exactly the length of the group order;
      neither inputs with excess leading zero bytes nor short encodings are accepted.

      Returns ``nullopt`` if the length is incorrect or if the integer is not
      within the range ``[1,n)`` where ``n`` is the group order.

   .. cpp:function:: static EC_Scalar from_bytes_with_trunc(const EC_Group& group, std::span<const uint8_t> buf)

      Convert a bytestring to a scalar using the ECDSA truncation rules. This can return zero.

   .. cpp:function:: static EC_Scalar from_bytes_mod_order(const EC_Group& group, std::span<const uint8_t> buf)

      Treating the input as the big-endian encoding of an integer, reduce that integer modulo ``n``.

      The encoded integer should be no greater than ``n**2``.

   .. cpp:function:: EC_Scalar(const EC_Group& group, std::span<const uint8_t> buf)

      Deserialize a scalar. This is equivalent to :cpp:func:`deserialize` except that
      it will throw an exception if the input is unacceptable.

   .. cpp:function:: static EC_Scalar random(const EC_Group& group, RandomNumberGenerator& rng)

       Return a random scalar

   .. cpp:function:: static EC_Scalar gk_x_mod_order(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>& ws)

       Compute the elliptic curve scalar multiplication (g*k) where g is the
       standard base point on the curve. Then extract the x coordinate of the
       resulting point, and reduce it modulo the group order.

       If the scalar value is zero (resulting in the scalar multiplication
       producing the identity element) then this function returns zero.

   .. cpp:function:: size_t bytes() const

       Return the byte length of the scalar

   .. cpp:function:: void serialize_to(std::span<uint8_t> buf) const

       Serialize the scalar to the provided span. It must have length
       exactly equal to the value returned by :cpp:func:`bytes`.

   .. cpp:function:: bool is_zero() const

       Returns true if this scalar value is zero

   .. cpp:function:: bool is_nonzero() const

       Returns true if this scalar value is zero

   .. cpp:function:: EC_Scalar invert() const

       Return the multiplicative inverse, or zero if `*this` is zero

   .. cpp:function:: EC_Scalar negate() const

       Return the additive inverse

   .. cpp:function:: EC_Scalar operator+(const EC_Scalar& x, const EC_Scalar& y)

       Addition modulo `n`

   .. cpp:function:: EC_Scalar operator-(const EC_Scalar& x, const EC_Scalar& y)

       Subtraction modulo `n`

   .. cpp:function:: EC_Scalar operator*(const EC_Scalar& x, const EC_Scalar& y)

       Multiplication modulo `n`

   .. cpp:function:: bool operator==(const EC_Scalar& x, const EC_Scalar& y)

       Equality test

.. cpp:class:: EC_AffinePoint

   A point on the elliptic curve.

   .. cpp:function:: EC_AffinePoint(const EC_Group& group, std::span<const uint8_t> bytes)

      Point deserialization. Throws if invalid, including if the point is not on the curve.

      This accepts SEC1 compressed or uncompressed formats

   .. cpp:function:: static std::optional<EC_AffinePoint> deserialize(const EC_Group& group, std::span<const uint8_t> bytes)

      Point deserialization. Returns ``nullopt`` if invalid, including if the point is not on the curve.

      This accepts SEC1 compressed or uncompressed formats

   .. cpp:function::  static EC_AffinePoint g_mul(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>& ws)

      Fixed base scalar multiplication. Constant time with blinding.

   .. cpp:function:: EC_AffinePoint mul(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>& ws) const

      Variable base scalar multiplication. Constant time with blinding.

   .. cpp:function:: static EC_AffinePoint hash_to_curve_ro(const EC_Group& group, \
                                             std::string_view hash_fn, \
                                             std::span<const uint8_t> input, \
                                             std::span<const uint8_t> domain_sep)

      Has to curve (RFC 9380), random oracle variant.

      This is currently only supported for a few curves.

   .. cpp:function:: static EC_AffinePoint hash_to_curve_nu(const EC_Group& group, \
                                             std::string_view hash_fn, \
                                             std::span<const uint8_t> input, \
                                             std::span<const uint8_t> domain_sep)

      Has to curve (RFC 9380), non-uniform variant.

      This is currently only supported for a few curves.

   .. cpp:function:: size_t field_element_bytes() const

      Return the size of the x and y coordinates, in bytes.

   .. cpp:function:: void serialize_x_to(std::span<uint8_t> bytes) const

      Serialize x coordinate to the output span

   .. cpp:function:: void serialize_y_to(std::span<uint8_t> bytes) const

      Serialize y coordinate to the output span

   .. cpp:function:: void serialize_xy_to(std::span<uint8_t> bytes) const

      Serialize x and y coordinates to the output span

   .. cpp:function:: void serialize_compressed_to(std::span<uint8_t> bytes) const

      Serialize the compressed SEC1 encoding to the output span

   .. cpp:function:: void serialize_uncompressed_to(std::span<uint8_t> bytes) const

      Serialize the uncompressed SEC1 encoding to the output span
