aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/conf.py100
-rw-r--r--docs/development/test-vectors.rst16
-rw-r--r--docs/faq.rst28
-rw-r--r--docs/hazmat/primitives/asymmetric/ec.rst2
-rw-r--r--docs/hazmat/primitives/asymmetric/rsa.rst2
-rw-r--r--docs/hazmat/primitives/symmetric-encryption.rst2
-rw-r--r--docs/installation.rst2
-rw-r--r--docs/security.rst37
-rw-r--r--docs/spelling_wordlist.txt1
-rw-r--r--docs/x509/reference.rst44
-rw-r--r--docs/x509/tutorial.rst68
11 files changed, 193 insertions, 109 deletions
diff --git a/docs/conf.py b/docs/conf.py
index 643eddba..85a569a7 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -116,10 +116,6 @@ exclude_patterns = ['_build']
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
-# A list of ignored prefixes for module index sorting.
-# modindex_common_prefix = []
-
-
# -- Options for HTML output --------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
@@ -131,73 +127,11 @@ if sphinx_rtd_theme:
else:
html_theme = "default"
-# Theme options are theme-specific and customize the look and feel of a theme
-# further. For a list of options available for each theme, see the
-# documentation.
-# html_theme_options = {}
-
-# The name for this set of Sphinx documents. If None, it defaults to
-# "<project> v<release> documentation".
-# html_title = None
-
-# A shorter title for the navigation bar. Default is the same as html_title.
-# html_short_title = None
-
-# The name of an image file (relative to this directory) to place at the top
-# of the sidebar.
-# html_logo = None
-
-# The name of an image file (within the static path) to use as favicon of the
-# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
-# pixels large.
-# html_favicon = None
-
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
-# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
-# using the given strftime format.
-# html_last_updated_fmt = '%b %d, %Y'
-
-# If true, SmartyPants will be used to convert quotes and dashes to
-# typographically correct entities.
-# html_use_smartypants = True
-
-# Custom sidebar templates, maps document names to template names.
-# html_sidebars = {}
-
-# Additional templates that should be rendered to pages, maps page names to
-# template names.
-# html_additional_pages = {}
-
-# If false, no module index is generated.
-# html_domain_indices = True
-
-# If false, no index is generated.
-# html_use_index = True
-
-# If true, the index is split into individual pages for each letter.
-# html_split_index = False
-
-# If true, links to the reST sources are added to the pages.
-# html_show_sourcelink = True
-
-# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-# html_show_sphinx = True
-
-# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-# html_show_copyright = True
-
-# If true, an OpenSearch description file will be output, and all pages will
-# contain a <link> tag referring to it. The value of this option must be the
-# base URL from which the finished HTML is served.
-# html_use_opensearch = ''
-
-# This is the file name suffix for HTML files (e.g. ".xhtml").
-# html_file_suffix = None
-
# Output file base name for HTML help builder.
htmlhelp_basename = 'Cryptographydoc'
@@ -214,27 +148,6 @@ latex_documents = [
'Individual Contributors', 'manual'),
]
-# The name of an image file (relative to this directory) to place at the top of
-# the title page.
-# latex_logo = None
-
-# For "manual" documents, if this is true, then toplevel headings are parts,
-# not chapters.
-# latex_use_parts = False
-
-# If true, show page references after internal links.
-# latex_show_pagerefs = False
-
-# If true, show URL addresses after external links.
-# latex_show_urls = False
-
-# Documents to append as an appendix to all manuals.
-# latex_appendices = []
-
-# If false, no module index is generated.
-# latex_domain_indices = True
-
-
# -- Options for manual page output -------------------------------------------
# One entry per manual page. List of tuples
@@ -244,10 +157,6 @@ man_pages = [
['Individual Contributors'], 1)
]
-# If true, show URL addresses after external links.
-# man_show_urls = False
-
-
# -- Options for Texinfo output -----------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
@@ -260,15 +169,6 @@ texinfo_documents = [
'Miscellaneous'),
]
-# Documents to append as an appendix to all manuals.
-# texinfo_appendices = []
-
-# If false, no module index is generated.
-# texinfo_domain_indices = True
-
-# How to display URL addresses: 'footnote', 'no', or 'inline'.
-# texinfo_show_urls = 'footnote'
-
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'https://docs.python.org/3': None}
diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst
index d62fb93a..cc44492f 100644
--- a/docs/development/test-vectors.rst
+++ b/docs/development/test-vectors.rst
@@ -113,6 +113,9 @@ X.509
* ``department-of-state-root.pem`` - The intermediary CA for the Department of
State, issued by the United States Federal Government's Common Policy CA.
Notably has a ``critical`` policy constraints extensions.
+* ``e-trust.ru.der`` - A certificate from a `Russian CA`_ signed using the GOST
+ cipher and containing numerous unusual encodings such as NUMERICSTRING in
+ the subject DN.
Custom X.509 Vectors
~~~~~~~~~~~~~~~~~~~~
@@ -263,6 +266,8 @@ Custom X.509 Vectors
policy constraints extension with a require explicit policy element.
* ``unsupported_subject_public_key_info.pem`` - A certificate whose public key
is an unknown OID (``1.3.6.1.4.1.8432.1.1.2``).
+* ``policy_constraints_explicit.pem`` - A self-signed certificate containing
+ a ``policyConstraints`` extension with a ``requireExplicitPolicy`` value.
Custom X.509 Request Vectors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -281,7 +286,7 @@ Custom X.509 Request Vectors
request using RSA and SHA1 with a subject alternative name extension
generated using OpenSSL.
* ``two_basic_constraints.pem`` - A certificate signing request
- for a RSA 2048 bit key containing two basic constraints extensions.
+ for an RSA 2048 bit key containing two basic constraints extensions.
* ``unsupported_extension.pem`` - A certificate signing request
for an RSA 2048 bit key containing containing an unsupported
extension type. The OID was encoded as "1.2.3.4" with an
@@ -290,9 +295,11 @@ Custom X.509 Request Vectors
request for an RSA 2048 bit key containing containing an unsupported
extension type marked critical. The OID was encoded as "1.2.3.4"
with an ``extnValue`` of "value".
-* ``basic_constraints.pem`` - A certificate signing request for a RSA
+* ``basic_constraints.pem`` - A certificate signing request for an RSA
2048 bit key containing a basic constraints extension marked as
critical.
+* ``invalid_signature.pem`` - A certificate signing request for an RSA
+ 1024 bit key containing an invalid signature with correct padding.
Custom X.509 Certificate Revocation List Vectors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -340,6 +347,8 @@ Key derivation functions
* PBKDF2 (HMAC-SHA1) from :rfc:`6070`.
* scrypt from the `draft RFC`_.
* X9.63 KDF from `NIST CAVP`_.
+* SP 800-108 Counter Mode KDF (HMAC-SHA1, HMAC-SHA224, HMAC-SHA256,
+ HMAC-SHA384, HMAC-SHA512) from `NIST CAVP`_.
Key wrapping
~~~~~~~~~~~~
@@ -421,7 +430,7 @@ header format (substituting the correct information):
.. _`NIST CAVP`: http://csrc.nist.gov/groups/STM/cavp/
.. _`Bruce Schneier's vectors`: https://www.schneier.com/code/vectors.txt
.. _`Camellia page`: https://info.isl.ntt.co.jp/crypt/eng/camellia/
-.. _`CRYPTREC`: http://www.cryptrec.go.jp
+.. _`CRYPTREC`: https://www.cryptrec.go.jp
.. _`OpenSSL's test vectors`: https://github.com/openssl/openssl/blob/97cf1f6c2854a3a955fd7dd3a1f113deba00c9ef/crypto/evp/evptests.txt#L232
.. _`RIPEMD website`: http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
.. _`Whirlpool website`: http://www.larc.usp.br/~pbarreto/WhirlpoolPage.html
@@ -446,3 +455,4 @@ header format (substituting the correct information):
.. _`root data`: https://hg.mozilla.org/projects/nss/file/25b2922cc564/security/nss/lib/ckfw/builtins/certdata.txt#l2053
.. _`asymmetric/public/PKCS1/dsa.pub.pem`: https://github.com/ruby/ruby/blob/4ccb387f3bc436a08fc6d72c4931994f5de95110/test/openssl/test_pkey_dsa.rb#L53
.. _`Mozilla bug`: https://bugzilla.mozilla.org/show_bug.cgi?id=233586
+.. _`Russian CA`: http://e-trust.gosuslugi.ru/MainCA
diff --git a/docs/faq.rst b/docs/faq.rst
index 10c8656b..3456ba97 100644
--- a/docs/faq.rst
+++ b/docs/faq.rst
@@ -14,5 +14,33 @@ to NaCl.
If you prefer NaCl's design, we highly recommend `PyNaCl`_.
+Compiling ``cryptography`` on OS X produces a ``fatal error: 'openssl/aes.h' file not found`` error
+---------------------------------------------------------------------------------------------------
+
+This happens because OS X 10.11 no longer includes a copy of OpenSSL.
+``cryptography`` now provides wheels which include a statically linked copy of
+OpenSSL. You're seeing this error because your copy of pip is too old to find
+our wheel files. Upgrade your copy of pip with ``pip install -U pip`` and then
+try install ``cryptography`` again.
+
+Starting ``cryptography`` using ``mod_wsgi`` produces an ``InternalError`` during a call in ``_register_osrandom_engine``
+-------------------------------------------------------------------------------------------------------------------------
+
+This happens because ``mod_wsgi`` uses sub-interpreters, which can cause a
+problem during initialization of the OpenSSL backend. To resolve this set the
+`WSGIApplicationGroup`_ to ``%{GLOBAL}`` in the ``mod_wsgi`` configuration.
+
+``cryptography`` raised an ``InternalError`` and I'm not sure what to do?
+-------------------------------------------------------------------------
+
+Frequently ``InternalError`` is raised when there are errors on the OpenSSL
+error stack that were placed there by other libraries that are also using
+OpenSSL. Try removing the other libraries and see if the problem persists.
+If you have no other libraries using OpenSSL in your process, or they do not
+appear to be at fault, it's possible that this is a bug in ``cryptography``.
+Please file an `issue`_ with instructions on how to reproduce it.
+
.. _`NaCl`: https://nacl.cr.yp.to/
.. _`PyNaCl`: https://pynacl.readthedocs.org
+.. _`WSGIApplicationGroup`: https://modwsgi.readthedocs.org/en/develop/configuration-directives/WSGIApplicationGroup.html
+.. _`issue`: https://github.com/pyca/cryptography/issues
diff --git a/docs/hazmat/primitives/asymmetric/ec.rst b/docs/hazmat/primitives/asymmetric/ec.rst
index 8e3a3659..b32d331c 100644
--- a/docs/hazmat/primitives/asymmetric/ec.rst
+++ b/docs/hazmat/primitives/asymmetric/ec.rst
@@ -505,7 +505,7 @@ Key Interfaces
.. _`less than 224 bits`: http://www.ecrypt.eu.org/ecrypt2/documents/D.SPA.20.pdf
.. _`elliptic curve diffie-hellman is faster than diffie-hellman`: http://digitalcommons.unl.edu/cgi/viewcontent.cgi?article=1100&context=cseconfwork
.. _`minimize the number of security concerns for elliptic-curve cryptography`: https://cr.yp.to/ecdh/curve25519-20060209.pdf
-.. _`SafeCurves`: http://safecurves.cr.yp.to/
+.. _`SafeCurves`: https://safecurves.cr.yp.to/
.. _`ECDSA`: https://en.wikipedia.org/wiki/ECDSA
.. _`EdDSA`: https://en.wikipedia.org/wiki/EdDSA
.. _`forward secrecy`: https://en.wikipedia.org/wiki/Forward_secrecy
diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst
index 1e18915c..c2a6d437 100644
--- a/docs/hazmat/primitives/asymmetric/rsa.rst
+++ b/docs/hazmat/primitives/asymmetric/rsa.rst
@@ -660,6 +660,6 @@ Key interfaces
.. _`at least 2048`: http://www.ecrypt.eu.org/ecrypt2/documents/D.SPA.20.pdf
.. _`OpenPGP`: https://en.wikipedia.org/wiki/Pretty_Good_Privacy
.. _`Chinese Remainder Theorem`: https://en.wikipedia.org/wiki/RSA_%28cryptosystem%29#Using_the_Chinese_remainder_algorithm
-.. _`security proof`: http://eprint.iacr.org/2001/062.pdf
+.. _`security proof`: https://eprint.iacr.org/2001/062.pdf
.. _`recommended padding algorithm`: http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html
.. _`proven secure`: https://cseweb.ucsd.edu/~mihir/papers/oae.pdf
diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst
index d5884897..7b00d110 100644
--- a/docs/hazmat/primitives/symmetric-encryption.rst
+++ b/docs/hazmat/primitives/symmetric-encryption.rst
@@ -610,7 +610,7 @@ Interfaces used by the symmetric cipher modes described in
.. _`NIST SP-800-38D`: http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
.. _`Communications Security Establishment`: https://www.cse-cst.gc.ca
.. _`encrypt`: https://ssd.eff.org/en/module/what-encryption
-.. _`CRYPTREC`: http://www.cryptrec.go.jp/english/
+.. _`CRYPTREC`: https://www.cryptrec.go.jp/english/
.. _`significant patterns in the output`: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_Codebook_.28ECB.29
.. _`International Data Encryption Algorithm`: https://en.wikipedia.org/wiki/International_Data_Encryption_Algorithm
.. _`OpenPGP`: http://www.openpgp.org
diff --git a/docs/installation.rst b/docs/installation.rst
index 1804989b..8c3c436b 100644
--- a/docs/installation.rst
+++ b/docs/installation.rst
@@ -268,7 +268,7 @@ information, consult `Greg Wilson's blog post`_ on the subject.
.. _`MacPorts`: https://www.macports.org
.. _`openssl-release`: https://jenkins.cryptography.io/job/openssl-release/
.. _`bug in conda`: https://github.com/conda/conda-recipes/issues/110
-.. _`Greg Wilson's blog post`: http://software-carpentry.org/blog/2014/04/mr-biczo-was-right.html
+.. _`Greg Wilson's blog post`: https://software-carpentry.org/blog/2014/04/mr-biczo-was-right.html
.. _virtualenv: https://virtualenv.pypa.io/en/latest/
.. _openssl.org: https://openssl.org/source/
.. _`wheel cache`: https://pip.pypa.io/en/stable/reference/pip_install/#caching
diff --git a/docs/security.rst b/docs/security.rst
index 13f99960..1cc1273d 100644
--- a/docs/security.rst
+++ b/docs/security.rst
@@ -5,6 +5,39 @@ We take the security of ``cryptography`` seriously. The following are a set of
policies we have adopted to ensure that security issues are addressed in a
timely fashion.
+What is a security issue?
+-------------------------
+
+Anytime it's possible to write code using ``cryptography``'s public API which
+does not provide the guarantees that a reasonable developer would expect it to
+based on our documentation.
+
+That's a bit academic, but basically it means the scope of what we consider a
+vulnerability is broad, and we do not require a proof of concept or even a
+specific exploit, merely a reasonable threat model under which ``cryptography``
+could be attacked.
+
+To give a few examples of things we would consider security issues:
+
+* If a recipe, such as Fernet, made it easy for a user to bypass
+ confidentiality or integrity with the public API (e.g. if the API let a user
+ reuse nonces).
+* If, under any circumstances, we used a CSPRNG which wasn't fork-safe.
+* If ``cryptography`` used an API in an underlying C library and failed to
+ handle error conditions safely.
+
+Examples of things we wouldn't consider security issues:
+
+* Offering ECB mode for symmetric encryption in the *Hazmat* layer. Though ECB
+ is critically weak, it is documented as being weak in our documentation.
+* Using a variable time comparison somewhere, if it's not possible to
+ articulate any particular program in which this would result in problematic
+ information disclosure.
+
+In general, if you're unsure, we request that you to default to treating things
+as security issues and handling them sensitively, the worst thing that can
+happen is that we'll ask you to file a bug issue.
+
Reporting a security issue
--------------------------
@@ -14,7 +47,7 @@ tracker.
If you believe you've identified a security issue with ``cryptography``, please
report it to ``alex.gaynor@gmail.com``. Messages may be optionally encrypted
with PGP using key fingerprint
-``E27D 4AA0 1651 72CB C5D2 AF2B 125F 5C67 DFE9 4084`` (this public key is
+``F7FC 698F AAE2 D2EF BECD E98E D1B3 ADC0 E023 8CA6`` (this public key is
available from most commonly-used key servers).
Once you've submitted an issue via email, you should receive an acknowledgment
@@ -25,7 +58,7 @@ Supported Versions
------------------
At any given time, we will provide security support for the `master`_ branch
-as well as the 2 most recent releases.
+as well as the most recent release.
New releases for OpenSSL updates
--------------------------------
diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt
index 6def7959..47415a7e 100644
--- a/docs/spelling_wordlist.txt
+++ b/docs/spelling_wordlist.txt
@@ -45,6 +45,7 @@ multi
naïve
namespace
namespaces
+nonces
Nonces
online
paddings
diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst
index 529578ba..399d693a 100644
--- a/docs/x509/reference.rst
+++ b/docs/x509/reference.rst
@@ -761,6 +761,12 @@ X.509 CSR (Certificate Signing Request) Object
key embedded in the CSR). This data may be used to validate the CSR
signature.
+ .. attribute:: is_signature_valid
+
+ .. versionadded:: 1.3
+
+ Returns True if the CSR signature is correct, False otherwise.
+
X.509 Certificate Revocation List Builder
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1535,6 +1541,13 @@ X.509 Extensions
.. versionadded:: 1.0
+ .. note::
+
+ This method should be used if the issuer certificate does not
+ contain a :class:`~cryptography.x509.SubjectKeyIdentifier`.
+ Otherwise, use
+ :meth:`~cryptography.x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier`.
+
Creates a new AuthorityKeyIdentifier instance using the public key
provided to generate the appropriate digest. This should be the
**issuer's public key**. The resulting object will contain
@@ -1562,6 +1575,37 @@ X.509 Extensions
>>> x509.AuthorityKeyIdentifier.from_issuer_public_key(issuer_cert.public_key())
<AuthorityKeyIdentifier(key_identifier='X\x01\x84$\x1b\xbc+R\x94J=\xa5\x10r\x14Q\xf5\xaf:\xc9', authority_cert_issuer=None, authority_cert_serial_number=None)>
+ .. classmethod:: from_issuer_subject_key_identifier(ski)
+
+ .. versionadded:: 1.3
+
+ .. note::
+ This method should be used if the issuer certificate contains a
+ :class:`~cryptography.x509.SubjectKeyIdentifier`. Otherwise, use
+ :meth:`~cryptography.x509.AuthorityKeyIdentifier.from_issuer_public_key`.
+
+ Creates a new AuthorityKeyIdentifier instance using the
+ SubjectKeyIdentifier from the issuer certificate. The resulting object
+ will contain
+ :attr:`~cryptography.x509.AuthorityKeyIdentifier.key_identifier`, but
+ :attr:`~cryptography.x509.AuthorityKeyIdentifier.authority_cert_issuer`
+ and
+ :attr:`~cryptography.x509.AuthorityKeyIdentifier.authority_cert_serial_number`
+ will be None.
+
+ :param ski: The
+ :class:`~cryptography.x509.SubjectKeyIdentifier` from the issuer
+ certificate.
+
+ .. doctest::
+
+ >>> from cryptography import x509
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> issuer_cert = x509.load_pem_x509_certificate(pem_data, default_backend())
+ >>> ski = issuer_cert.extensions.get_extension_for_class(x509.SubjectKeyIdentifier)
+ >>> x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(ski)
+ <AuthorityKeyIdentifier(key_identifier='X\x01\x84$\x1b\xbc+R\x94J=\xa5\x10r\x14Q\xf5\xaf:\xc9', authority_cert_issuer=None, authority_cert_serial_number=None)>
+
.. class:: SubjectKeyIdentifier(digest)
.. versionadded:: 0.9
diff --git a/docs/x509/tutorial.rst b/docs/x509/tutorial.rst
index 7252e43a..6941372f 100644
--- a/docs/x509/tutorial.rst
+++ b/docs/x509/tutorial.rst
@@ -82,3 +82,71 @@ a few details:
... f.write(csr.public_bytes(serialization.Encoding.PEM))
Now we can give our CSR to a CA, who will give a certificate to us in return.
+
+Creating a self-signed certificate
+----------------------------------
+
+While most of the time you want a certificate that has been *signed* by someone
+else (i.e. a certificate authority), so that trust is established, sometimes
+you want to create a self-signed certificate. Self-signed certificates are not
+issued by a certificate authority, but instead they are signed by the private
+key corresponding to the public key they embed.
+
+This means that other people don't trust these certificates, but it also means
+they can be issued very easily. In general the only use case for a self-signed
+certificate is local testing, where you don't need anyone else to trust your
+certificate.
+
+Like generating a CSR, we start with creating a new private key:
+
+.. code-block:: pycon
+
+ >>> # Generate our key
+ >>> key = rsa.generate_private_key(
+ ... public_exponent=65537,
+ ... key_size=2048,
+ ... backend=default_backend()
+ ... )
+ >>> # Write our key to disk for safe keeping
+ >>> with open("path/to/store/key.pem", "wb") as f:
+ ... f.write(key.private_bytes(
+ ... encoding=serialization.Encoding.PEM,
+ ... format=serialization.PrivateFormat.TraditionalOpenSSL,
+ ... encryption_algorithm=serialization.BestAvailableEncryption(b"passphrase"),
+ ... ))
+
+Then we generate the certificate itself:
+
+.. code-block:: pycon
+
+ >>> # Various details about who we are. For a self-signed certificate the
+ >>> # subject and issuer are always the same.
+ >>> subject = issuer = x509.Name([
+ ... x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
+ ... x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"CA"),
+ ... x509.NameAttribute(NameOID.LOCALITY_NAME, u"San Francisco"),
+ ... x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"My Company"),
+ ... x509.NameAttribute(NameOID.COMMON_NAME, u"mysite.com"),
+ ... ])
+ >>> cert = x509.CertificateBuilder().subject_name(
+ ... subject
+ ... ).issuer_name(
+ ... issuer
+ ... ).public_key(
+ ... private_key.public_key()
+ ... ).not_valid_before(
+ ... datetime.datetime.utcnow()
+ ... ).not_valid_after(
+ ... # Our certificate will be valid for 10 days
+ ... datetime.datetime.utcnow() + datetime.timedelta(days=10)
+ ... ).add_extension(
+ ... x509.SubjectAlternativeName([x509.DNSName(u"localhost")]),
+ ... critical=False,
+ ... # Sign our certificate with our private key
+ ... ).sign(private_key, hashes.SHA256(), default_backend())
+ >>> # Write our certificate out to disk.
+ >>> with open("path/to/certificate.pem", "wb") as f:
+ ... f.write(cert.public_bytes(serialization.Encoding.PEM))
+
+And now we have a private key and certificate that can be used for local
+testing.