Make a certificate.

  The following extensions are added to all certificates in the following order
  *before* additional extensions specified by `exts` kwarg:

    - subjectKeyIdentifier
    - authorityKeyIdentifier

  :param OpenSSL.crypto.X509Request csr: A certificate signing request.
  :param OpenSSL.crypto.PKey ca_key: The signing authority's key.
  :param OpenSSL.crypto.X509 ca_cert: The signing authority's certificate.
  :param int serial: A serial number.
  :param int not_before: A number of seconds from now to wait before the certificate is valid.
  :param int not_after: A number of seconds from now to wait before expiring the certificate.
  :param str digest: A valid digest.
  :param int version: The version of SSL to use with this certificate.
  :param list[OpenSSL.crypto.X509Extension] exts: A list of extensions to add to this certificate.
  :return: A X.509 certificate.
  :rtype: :class:`OpenSSL.crypto.X509`

def make_certificate(csr, ca_key, ca_cert, serial, not_before, not_after, digest='sha512', version=2, exts=()):
  """Make a certificate.

  The following extensions are added to all certificates in the following order
  *before* additional extensions specified by `exts` kwarg:

    - subjectKeyIdentifier
    - authorityKeyIdentifier

  :param OpenSSL.crypto.X509Request csr: A certificate signing request.
  :param OpenSSL.crypto.PKey ca_key: The signing authority's key.
  :param OpenSSL.crypto.X509 ca_cert: The signing authority's certificate.
  :param int serial: A serial number.
  :param int not_before: A number of seconds from now to wait before the certificate is valid.
  :param int not_after: A number of seconds from now to wait before expiring the certificate.
  :param str digest: A valid digest.
  :param int version: The version of SSL to use with this certificate.
  :param list[OpenSSL.crypto.X509Extension] exts: A list of extensions to add to this certificate.
  :return: A X.509 certificate.
  :rtype: :class:`OpenSSL.crypto.X509`

  """
  crt = crypto.X509()
  crt.set_serial_number(serial)
  crt.gmtime_adj_notBefore(not_before)
  crt.gmtime_adj_notAfter(not_after)
  crt.set_issuer(ca_cert.get_subject())
  crt.set_subject(csr.get_subject())
  crt.set_pubkey(csr.get_pubkey())
  crt.set_version(version)

  crt.add_extensions([
    crypto.X509Extension(b'subjectKeyIdentifier', False, b'hash', subject=crt)])
  if ca_cert.get_subject() == crt.get_subject():
    crt.add_extensions([
      crypto.X509Extension(b'authorityKeyIdentifier', False, b'keyid:always', issuer=crt)])
  else:
    crt.add_extensions([
      crypto.X509Extension(b'authorityKeyIdentifier', False, b'keyid:always', issuer=ca_cert)])

  crt.add_extensions(exts)

  crt.sign(ca_key, digest)
  return crt