aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/api-stability.rst32
-rw-r--r--docs/community.rst3
-rw-r--r--docs/conf.py119
-rw-r--r--docs/cryptography-docs.py26
-rw-r--r--docs/development/c-bindings.rst32
-rw-r--r--docs/development/custom-vectors/arc4.rst30
-rw-r--r--docs/development/custom-vectors/arc4/generate_arc4.py98
-rw-r--r--docs/development/custom-vectors/arc4/verify_arc4.go111
-rw-r--r--docs/development/custom-vectors/cast5/generate_cast5.py44
-rw-r--r--docs/development/custom-vectors/cast5/verify_cast5.go2
-rw-r--r--docs/development/custom-vectors/hkdf.rst28
-rw-r--r--docs/development/custom-vectors/hkdf/generate_hkdf.py39
-rw-r--r--docs/development/custom-vectors/hkdf/verify_hkdf.go69
-rw-r--r--docs/development/custom-vectors/idea.rst2
-rw-r--r--docs/development/custom-vectors/idea/generate_idea.py1
-rw-r--r--docs/development/custom-vectors/rsa-oaep-sha2.rst56
-rw-r--r--docs/development/custom-vectors/rsa-oaep-sha2/VerifyRSAOAEPSHA2.java416
-rw-r--r--docs/development/custom-vectors/rsa-oaep-sha2/generate_rsa_oaep_sha2.py128
-rw-r--r--docs/development/custom-vectors/secp256k1.rst2
-rw-r--r--docs/development/custom-vectors/secp256k1/generate_secp256k1.py1
-rw-r--r--docs/development/custom-vectors/secp256k1/verify_secp256k1.py4
-rw-r--r--docs/development/custom-vectors/seed.rst2
-rw-r--r--docs/development/custom-vectors/seed/generate_seed.py1
-rw-r--r--docs/development/getting-started.rst81
-rw-r--r--docs/development/index.rst2
-rw-r--r--docs/development/reviewing-patches.rst12
-rw-r--r--docs/development/submitting-patches.rst15
-rw-r--r--docs/development/test-vectors.rst394
-rw-r--r--docs/doing-a-release.rst36
-rw-r--r--docs/faq.rst137
-rw-r--r--docs/fernet.rst175
-rw-r--r--docs/glossary.rst35
-rw-r--r--docs/hazmat/backends/commoncrypto.rst30
-rw-r--r--docs/hazmat/backends/index.rst10
-rw-r--r--docs/hazmat/backends/interfaces.rst351
-rw-r--r--docs/hazmat/backends/multibackend.rst45
-rw-r--r--docs/hazmat/backends/openssl.rst56
-rw-r--r--docs/hazmat/bindings/commoncrypto.rst30
-rw-r--r--docs/hazmat/bindings/index.rst1
-rw-r--r--docs/hazmat/bindings/openssl.rst26
-rw-r--r--docs/hazmat/primitives/aead.rst248
-rw-r--r--docs/hazmat/primitives/asymmetric/dh.rst403
-rw-r--r--docs/hazmat/primitives/asymmetric/dsa.rst264
-rw-r--r--docs/hazmat/primitives/asymmetric/ec.rst767
-rw-r--r--docs/hazmat/primitives/asymmetric/ed25519.rst166
-rw-r--r--docs/hazmat/primitives/asymmetric/ed448.rst131
-rw-r--r--docs/hazmat/primitives/asymmetric/index.rst10
-rw-r--r--docs/hazmat/primitives/asymmetric/interfaces.rst32
-rw-r--r--docs/hazmat/primitives/asymmetric/rsa.rst307
-rw-r--r--docs/hazmat/primitives/asymmetric/serialization.rst328
-rw-r--r--docs/hazmat/primitives/asymmetric/utils.rst70
-rw-r--r--docs/hazmat/primitives/asymmetric/x25519.rst184
-rw-r--r--docs/hazmat/primitives/asymmetric/x448.rst179
-rw-r--r--docs/hazmat/primitives/constant-time.rst2
-rw-r--r--docs/hazmat/primitives/cryptographic-hashes.rst168
-rw-r--r--docs/hazmat/primitives/index.rst11
-rw-r--r--docs/hazmat/primitives/interfaces.rst80
-rw-r--r--docs/hazmat/primitives/key-derivation-functions.rst497
-rw-r--r--docs/hazmat/primitives/keywrap.rst98
-rw-r--r--docs/hazmat/primitives/mac/cmac.rst20
-rw-r--r--docs/hazmat/primitives/mac/hmac.rst20
-rw-r--r--docs/hazmat/primitives/mac/index.rst9
-rw-r--r--docs/hazmat/primitives/mac/poly1305.rst132
-rw-r--r--docs/hazmat/primitives/padding.rst67
-rw-r--r--docs/hazmat/primitives/symmetric-encryption.rst348
-rw-r--r--docs/hazmat/primitives/twofactor.rst75
-rw-r--r--docs/index.rst80
-rw-r--r--docs/installation.rst249
-rw-r--r--docs/limitations.rst25
-rw-r--r--docs/random-numbers.rst15
-rw-r--r--docs/security.rst92
-rw-r--r--docs/spelling_wordlist.txt64
-rw-r--r--docs/x509.rst1569
-rw-r--r--docs/x509/certificate-transparency.rst79
-rw-r--r--docs/x509/index.rst17
-rw-r--r--docs/x509/ocsp.rst689
-rw-r--r--docs/x509/reference.rst3200
-rw-r--r--docs/x509/tutorial.rst171
78 files changed, 10453 insertions, 3095 deletions
diff --git a/docs/api-stability.rst b/docs/api-stability.rst
index 53669b0f..205b1844 100644
--- a/docs/api-stability.rst
+++ b/docs/api-stability.rst
@@ -34,18 +34,38 @@ One exception to our API stability policy is for security. We will violate this
policy as necessary in order to resolve a security issue or harden
``cryptography`` against a possible attack.
+Versioning
+----------
+
+This project uses a custom versioning scheme as described below.
+
+Given a version ``cryptography X.Y.Z``,
+
+* ``X.Y`` is a decimal number that is incremented for
+ potentially-backwards-incompatible releases.
+
+ * This increases like a standard decimal.
+ In other words, 0.9 is the ninth release, and 1.0 is the tenth (not 0.10).
+ The dividing decimal point can effectively be ignored.
+
+* ``Z`` is an integer that is incremented for backward-compatible releases.
+
Deprecation
------------
+~~~~~~~~~~~
From time to time we will want to change the behavior of an API or remove it
entirely. In that case, here's how the process will work:
* In ``cryptography X.Y`` the feature exists.
-* In ``cryptography X.Y+1`` using that feature will emit a
- ``PendingDeprecationWarning``.
-* In ``cryptography X.Y+2`` using that feature will emit a
- ``DeprecationWarning``.
-* In ``cryptography X.Y+3`` the feature will be removed or changed.
+* In ``cryptography X.Y + 0.1`` using that feature will emit a
+ ``UserWarning``.
+* In ``cryptography X.Y + 0.2`` using that feature will emit a
+ ``UserWarning``.
+* In ``cryptography X.Y + 0.3`` the feature will be removed or changed.
In short, code that runs without warnings will always continue to work for a
period of two releases.
+
+From time to time, we may decide to deprecate an API that is particularly
+widely used. In these cases, we may decide to provide an extended deprecation
+period, at our discretion.
diff --git a/docs/community.rst b/docs/community.rst
index 2b7cdc60..da637653 100644
--- a/docs/community.rst
+++ b/docs/community.rst
@@ -9,8 +9,7 @@ You can find ``cryptography`` all over the web:
* `Documentation`_
* IRC: ``#cryptography-dev`` on ``irc.freenode.net``
-Wherever we interact, we strive to follow the `Python Community Code of
-Conduct`_.
+Wherever we interact, we adhere to the `Python Community Code of Conduct`_.
.. _`Mailing list`: https://mail.python.org/mailman/listinfo/cryptography-dev
diff --git a/docs/conf.py b/docs/conf.py
index 5a4c41b1..fc0079ac 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -71,7 +71,7 @@ master_doc = 'index'
# General information about the project.
project = 'Cryptography'
-copyright = '2013-2015, Individual Contributors'
+copyright = '2013-2017, Individual Contributors'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@@ -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,16 +169,24 @@ 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}
epub_theme = 'epub'
+
+# Retry requests in the linkcheck builder so that we're resillient against
+# transient network errors.
+linkcheck_retries = 10
+
+linkcheck_timeout = 5
+
+linkcheck_ignore = [
+ # Small DH key results in a TLS failure on modern OpenSSL
+ r"https://info.isl.ntt.co.jp/crypt/eng/camellia/",
+ # Inconsistent small DH params they seem incapable of fixing
+ r"https://www.secg.org/sec1-v2.pdf",
+ # 403ing from Travis
+ r"https://devblogs.microsoft.com/oldnewthing/\?p=4223",
+ # Incomplete cert chain
+ r"https://cveform.mitre.org/",
+]
diff --git a/docs/cryptography-docs.py b/docs/cryptography-docs.py
index 6aa7847d..923ec6f5 100644
--- a/docs/cryptography-docs.py
+++ b/docs/cryptography-docs.py
@@ -5,8 +5,7 @@
from __future__ import absolute_import, division, print_function
from docutils import nodes
-
-from sphinx.util.compat import Directive, make_admonition
+from docutils.parsers.rst import Directive
DANGER_MESSAGE = """
@@ -29,20 +28,11 @@ class HazmatDirective(Directive):
if self.content:
message += DANGER_ALTERNATE.format(alternate=self.content[0])
- ad = make_admonition(
- Hazmat,
- self.name,
- [],
- self.options,
- nodes.paragraph("", message),
- self.lineno,
- self.content_offset,
- self.block_text,
- self.state,
- self.state_machine
- )
- ad[0].line = self.lineno
- return ad
+ content = nodes.paragraph("", message)
+ admonition_node = Hazmat("\n".join(content))
+ self.state.nested_parse(content, self.content_offset, admonition_node)
+ admonition_node.line = self.lineno
+ return [admonition_node]
class Hazmat(nodes.Admonition, nodes.Element):
@@ -68,3 +58,7 @@ def setup(app):
latex=(latex_visit_hazmat_node, depart_hazmat_node),
)
app.add_directive("hazmat", HazmatDirective)
+
+ return {
+ "parallel_read_safe": True,
+ }
diff --git a/docs/development/c-bindings.rst b/docs/development/c-bindings.rst
index 993a4ab2..1b58dab6 100644
--- a/docs/development/c-bindings.rst
+++ b/docs/development/c-bindings.rst
@@ -3,7 +3,7 @@ C bindings
C bindings are bindings to C libraries, using cffi_ whenever possible.
-.. _cffi: https://cffi.readthedocs.org
+.. _cffi: https://cffi.readthedocs.io
Bindings live in :py:mod:`cryptography.hazmat.bindings`.
@@ -88,9 +88,10 @@ Adding constant, types, functions...
You can create bindings for any name that exists in some version of
the library you're binding against. However, the project also has to
-keep supporting older versions of the library. In order to achieve
-this, binding modules have ``CUSTOMIZATIONS`` and
-``CONDITIONAL_NAMES`` constants.
+keep supporting older versions of the library. In order to achieve this,
+binding modules have a ``CUSTOMIZATIONS`` constant, and there is a
+``CONDITIONAL_NAMES`` constants in
+``src/cryptography/hazmat/bindings/openssl/_conditional.py``.
Let's say you want to enable quantum transmogrification. The upstream
library implements this as the following API::
@@ -127,9 +128,7 @@ opaque struct::
...;
} QM_TRANSMOGRIFICATION_CTX;
-Confusingly, functions that aren't always available on all supported
-versions of the library, should be defined in ``MACROS`` and *not* in
-``FUNCTIONS``. Fortunately, you just have to copy the signature::
+For functions just add the signature to ``FUNCTIONS``::
int QM_transmogrify(QM_TRANSMOGRIFICATION_CTX *, int);
@@ -168,24 +167,31 @@ the necessarily type definitions are in place.
Finally, add an entry to ``CONDITIONAL_NAMES`` with all of the things
you want to conditionally export::
- CONDITIONAL_NAMES = {
- ...
- "Cryptography_HAS_QUANTUM_TRANSMOGRIFICATION": [
+ def cryptography_has_quantum_transmogrification():
+ return [
"QM_TRANSMOGRIFICATION_ALIGNMENT_LEFT",
"QM_TRANSMOGRIFICATION_ALIGNMENT_RIGHT",
- "QM_transmogrify"
+ "QM_transmogrify",
]
+
+
+ CONDITIONAL_NAMES = {
+ ...
+ "Cryptography_HAS_QUANTUM_TRANSMOGRIFICATION": (
+ cryptography_has_quantum_transmogrification
+ ),
}
+
Caveats
~~~~~~~
Sometimes, a set of loosely related features are added in the same
version, and it's impractical to create ``#ifdef`` statements for each
one. In that case, it may make sense to either check for a particular
-version. For example, to check for OpenSSL 1.0.0 or newer::
+version. For example, to check for OpenSSL 1.1.0 or newer::
- #if OPENSSL_VERSION_NUMBER >= 0x10000000L
+ #if CRYPTOGRAPHY_OPENSSL_110_OR_GREATER
Sometimes, the version of a library on a particular platform will have
features that you thought it wouldn't, based on its version.
diff --git a/docs/development/custom-vectors/arc4.rst b/docs/development/custom-vectors/arc4.rst
new file mode 100644
index 00000000..5b1b65d5
--- /dev/null
+++ b/docs/development/custom-vectors/arc4.rst
@@ -0,0 +1,30 @@
+ARC4 vector creation
+====================
+
+This page documents the code that was used to generate the ARC4 test
+vectors for key lengths not available in :rfc:`6229`. All the vectors
+were generated using OpenSSL and verified with Go.
+
+Creation
+--------
+
+``cryptography`` was modified to support ARC4 key lengths not listed
+in :rfc:`6229`. Then the following Python script was run to generate the
+vector files.
+
+.. literalinclude:: /development/custom-vectors/arc4/generate_arc4.py
+
+Download link: :download:`generate_arc4.py
+</development/custom-vectors/arc4/generate_arc4.py>`
+
+
+Verification
+------------
+
+The following Go code was used to verify the vectors.
+
+.. literalinclude:: /development/custom-vectors/arc4/verify_arc4.go
+ :language: go
+
+Download link: :download:`verify_arc4.go
+</development/custom-vectors/arc4/verify_arc4.go>`
diff --git a/docs/development/custom-vectors/arc4/generate_arc4.py b/docs/development/custom-vectors/arc4/generate_arc4.py
new file mode 100644
index 00000000..3dee44a3
--- /dev/null
+++ b/docs/development/custom-vectors/arc4/generate_arc4.py
@@ -0,0 +1,98 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import binascii
+
+from cryptography.hazmat.backends import default_backend
+from cryptography.hazmat.primitives import ciphers
+from cryptography.hazmat.primitives.ciphers import algorithms
+
+
+_RFC6229_KEY_MATERIALS = [
+ (True,
+ 8 * '0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20'),
+ (False,
+ 8 * '1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a')
+]
+
+
+_RFC6229_OFFSETS = [
+ 0,
+ 16,
+ 240,
+ 256,
+ 496,
+ 512,
+ 752,
+ 768,
+ 1008,
+ 1024,
+ 1520,
+ 1536,
+ 2032,
+ 2048,
+ 3056,
+ 3072,
+ 4080,
+ 4096
+]
+
+
+_SIZES_TO_GENERATE = [
+ 160
+]
+
+
+def _key_for_size(size, keyinfo):
+ msb, key = keyinfo
+ if msb:
+ return key[:size // 4]
+ else:
+ return key[-size // 4:]
+
+
+def _build_vectors():
+ count = 0
+ output = []
+ key = None
+ plaintext = binascii.unhexlify(32 * '0')
+ for size in _SIZES_TO_GENERATE:
+ for keyinfo in _RFC6229_KEY_MATERIALS:
+ key = _key_for_size(size, keyinfo)
+ cipher = ciphers.Cipher(
+ algorithms.ARC4(binascii.unhexlify(key)),
+ None,
+ default_backend())
+ encryptor = cipher.encryptor()
+ current_offset = 0
+ for offset in _RFC6229_OFFSETS:
+ if offset % 16 != 0:
+ raise ValueError(
+ "Offset {} is not evenly divisible by 16"
+ .format(offset))
+ while current_offset < offset:
+ encryptor.update(plaintext)
+ current_offset += len(plaintext)
+ output.append("\nCOUNT = {}".format(count))
+ count += 1
+ output.append("KEY = {}".format(key))
+ output.append("OFFSET = {}".format(offset))
+ output.append("PLAINTEXT = {}".format(
+ binascii.hexlify(plaintext)))
+ output.append("CIPHERTEXT = {}".format(
+ binascii.hexlify(encryptor.update(plaintext))))
+ current_offset += len(plaintext)
+ assert not encryptor.finalize()
+ return "\n".join(output)
+
+
+def _write_file(data, filename):
+ with open(filename, 'w') as f:
+ f.write(data)
+
+
+if __name__ == '__main__':
+ _write_file(_build_vectors(), 'arc4.txt')
diff --git a/docs/development/custom-vectors/arc4/verify_arc4.go b/docs/development/custom-vectors/arc4/verify_arc4.go
new file mode 100644
index 00000000..508fe980
--- /dev/null
+++ b/docs/development/custom-vectors/arc4/verify_arc4.go
@@ -0,0 +1,111 @@
+package main
+
+import (
+ "bufio"
+ "bytes"
+ "crypto/rc4"
+ "encoding/hex"
+ "fmt"
+ "os"
+ "strconv"
+ "strings"
+)
+
+func unhexlify(s string) []byte {
+ bytes, err := hex.DecodeString(s)
+ if err != nil {
+ panic(err)
+ }
+ return bytes
+}
+
+type vectorArgs struct {
+ count string
+ offset uint64
+ key string
+ plaintext string
+ ciphertext string
+}
+
+type vectorVerifier interface {
+ validate(count string, offset uint64, key, plaintext, expectedCiphertext []byte)
+}
+
+type arc4Verifier struct{}
+
+func (o arc4Verifier) validate(count string, offset uint64, key, plaintext, expectedCiphertext []byte) {
+ if offset%16 != 0 || len(plaintext) != 16 || len(expectedCiphertext) != 16 {
+ panic(fmt.Errorf("Unexpected input value encountered: offset=%v; len(plaintext)=%v; len(expectedCiphertext)=%v",
+ offset,
+ len(plaintext),
+ len(expectedCiphertext)))
+ }
+ stream, err := rc4.NewCipher(key)
+ if err != nil {
+ panic(err)
+ }
+
+ var currentOffset uint64 = 0
+ ciphertext := make([]byte, len(plaintext))
+ for currentOffset <= offset {
+ stream.XORKeyStream(ciphertext, plaintext)
+ currentOffset += uint64(len(plaintext))
+ }
+ if !bytes.Equal(ciphertext, expectedCiphertext) {
+ panic(fmt.Errorf("vector mismatch @ COUNT = %s:\n %s != %s\n",
+ count,
+ hex.EncodeToString(expectedCiphertext),
+ hex.EncodeToString(ciphertext)))
+ }
+}
+
+func validateVectors(verifier vectorVerifier, filename string) {
+ vectors, err := os.Open(filename)
+ if err != nil {
+ panic(err)
+ }
+ defer vectors.Close()
+
+ var segments []string
+ var vector *vectorArgs
+
+ scanner := bufio.NewScanner(vectors)
+ for scanner.Scan() {
+ segments = strings.Split(scanner.Text(), " = ")
+
+ switch {
+ case strings.ToUpper(segments[0]) == "COUNT":
+ if vector != nil {
+ verifier.validate(vector.count,
+ vector.offset,
+ unhexlify(vector.key),
+ unhexlify(vector.plaintext),
+ unhexlify(vector.ciphertext))
+ }
+ vector = &vectorArgs{count: segments[1]}
+ case strings.ToUpper(segments[0]) == "OFFSET":
+ vector.offset, err = strconv.ParseUint(segments[1], 10, 64)
+ if err != nil {
+ panic(err)
+ }
+ case strings.ToUpper(segments[0]) == "KEY":
+ vector.key = segments[1]
+ case strings.ToUpper(segments[0]) == "PLAINTEXT":
+ vector.plaintext = segments[1]
+ case strings.ToUpper(segments[0]) == "CIPHERTEXT":
+ vector.ciphertext = segments[1]
+ }
+ }
+ if vector != nil {
+ verifier.validate(vector.count,
+ vector.offset,
+ unhexlify(vector.key),
+ unhexlify(vector.plaintext),
+ unhexlify(vector.ciphertext))
+ }
+}
+
+func main() {
+ validateVectors(arc4Verifier{}, "vectors/cryptography_vectors/ciphers/ARC4/arc4.txt")
+ fmt.Println("ARC4 OK.")
+}
diff --git a/docs/development/custom-vectors/cast5/generate_cast5.py b/docs/development/custom-vectors/cast5/generate_cast5.py
index 20f35179..ce046b0f 100644
--- a/docs/development/custom-vectors/cast5/generate_cast5.py
+++ b/docs/development/custom-vectors/cast5/generate_cast5.py
@@ -23,33 +23,34 @@ def encrypt(mode, key, iv, plaintext):
def build_vectors(mode, filename):
- vector_file = open(filename, "r")
-
count = 0
output = []
key = None
iv = None
plaintext = None
- for line in vector_file:
- line = line.strip()
- if line.startswith("KEY"):
- if count != 0:
- output.append("CIPHERTEXT = {}".format(
- encrypt(mode, key, iv, plaintext))
- )
- output.append("\nCOUNT = {}".format(count))
- count += 1
- name, key = line.split(" = ")
- output.append("KEY = {}".format(key))
- elif line.startswith("IV"):
- name, iv = line.split(" = ")
- iv = iv[0:16]
- output.append("IV = {}".format(iv))
- elif line.startswith("PLAINTEXT"):
- name, plaintext = line.split(" = ")
- output.append("PLAINTEXT = {}".format(plaintext))
- output.append("CIPHERTEXT = {}".format(encrypt(mode, key, iv, plaintext)))
+ with open(filename, "r") as vector_file:
+ for line in vector_file:
+ line = line.strip()
+ if line.startswith("KEY"):
+ if count != 0:
+ output.append("CIPHERTEXT = {}".format(
+ encrypt(mode, key, iv, plaintext))
+ )
+ output.append("\nCOUNT = {}".format(count))
+ count += 1
+ name, key = line.split(" = ")
+ output.append("KEY = {}".format(key))
+ elif line.startswith("IV"):
+ name, iv = line.split(" = ")
+ iv = iv[0:16]
+ output.append("IV = {}".format(iv))
+ elif line.startswith("PLAINTEXT"):
+ name, plaintext = line.split(" = ")
+ output.append("PLAINTEXT = {}".format(plaintext))
+ output.append(
+ "CIPHERTEXT = {}".format(encrypt(mode, key, iv, plaintext))
+ )
return "\n".join(output)
@@ -57,6 +58,7 @@ def write_file(data, filename):
with open(filename, "w") as f:
f.write(data)
+
cbc_path = "tests/hazmat/primitives/vectors/ciphers/AES/CBC/CBCMMT128.rsp"
write_file(build_vectors(modes.CBC, cbc_path), "cast5-cbc.txt")
ofb_path = "tests/hazmat/primitives/vectors/ciphers/AES/OFB/OFBMMT128.rsp"
diff --git a/docs/development/custom-vectors/cast5/verify_cast5.go b/docs/development/custom-vectors/cast5/verify_cast5.go
index cbc89a03..b2d711a9 100644
--- a/docs/development/custom-vectors/cast5/verify_cast5.go
+++ b/docs/development/custom-vectors/cast5/verify_cast5.go
@@ -3,7 +3,7 @@ package main
import (
"bufio"
"bytes"
- "code.google.com/p/go.crypto/cast5"
+ "golang.org/x/crypto/cast5"
"crypto/cipher"
"encoding/hex"
"fmt"
diff --git a/docs/development/custom-vectors/hkdf.rst b/docs/development/custom-vectors/hkdf.rst
new file mode 100644
index 00000000..6d7e8618
--- /dev/null
+++ b/docs/development/custom-vectors/hkdf.rst
@@ -0,0 +1,28 @@
+HKDF vector creation
+====================
+
+This page documents the code that was used to generate a longer
+HKDF test vector (1200 bytes) than is available in :rfc:`5869`. All
+the vectors were generated using OpenSSL and verified with Go.
+
+Creation
+--------
+
+The following Python script was run to generate the vector files.
+
+.. literalinclude:: /development/custom-vectors/hkdf/generate_hkdf.py
+
+Download link: :download:`generate_hkdf.py
+</development/custom-vectors/hkdf/generate_hkdf.py>`
+
+
+Verification
+------------
+
+The following Go code was used to verify the vectors.
+
+.. literalinclude:: /development/custom-vectors/hkdf/verify_hkdf.go
+ :language: go
+
+Download link: :download:`verify_hkdf.go
+</development/custom-vectors/hkdf/verify_hkdf.go>`
diff --git a/docs/development/custom-vectors/hkdf/generate_hkdf.py b/docs/development/custom-vectors/hkdf/generate_hkdf.py
new file mode 100644
index 00000000..8976effd
--- /dev/null
+++ b/docs/development/custom-vectors/hkdf/generate_hkdf.py
@@ -0,0 +1,39 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import binascii
+
+from cryptography.hazmat.backends import default_backend
+from cryptography.hazmat.primitives import hashes
+from cryptography.hazmat.primitives.kdf.hkdf import HKDF
+
+IKM = binascii.unhexlify(b"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b")
+L = 1200
+OKM = HKDF(
+ algorithm=hashes.SHA256(), length=L, salt=None, info=None,
+ backend=default_backend()
+).derive(IKM)
+
+
+def _build_vectors():
+ output = [
+ "COUNT = 0",
+ "Hash = SHA-256",
+ "IKM = " + binascii.hexlify(IKM).decode("ascii"),
+ "salt = ", "info = ",
+ "L = {}".format(L),
+ "OKM = " + binascii.hexlify(OKM).decode("ascii"),
+ ]
+ return "\n".join(output)
+
+
+def _write_file(data, filename):
+ with open(filename, 'w') as f:
+ f.write(data)
+
+
+if __name__ == '__main__':
+ _write_file(_build_vectors(), 'hkdf.txt')
diff --git a/docs/development/custom-vectors/hkdf/verify_hkdf.go b/docs/development/custom-vectors/hkdf/verify_hkdf.go
new file mode 100644
index 00000000..ddeb3d8e
--- /dev/null
+++ b/docs/development/custom-vectors/hkdf/verify_hkdf.go
@@ -0,0 +1,69 @@
+package main
+
+import (
+ "bufio"
+ "bytes"
+ "crypto/sha256"
+ "encoding/hex"
+ "fmt"
+ "golang.org/x/crypto/hkdf"
+ "io"
+ "os"
+ "strconv"
+ "strings"
+)
+
+func unhexlify(s string) []byte {
+ bytes, err := hex.DecodeString(s)
+ if err != nil {
+ panic(err)
+ }
+ return bytes
+}
+
+func verifier(l uint64, ikm, okm []byte) bool {
+ hash := sha256.New
+ hkdf := hkdf.New(hash, ikm, nil, nil)
+ okmComputed := make([]byte, l)
+ io.ReadFull(hkdf, okmComputed)
+ return bytes.Equal(okmComputed, okm)
+}
+
+func validateVectors(filename string) bool {
+ vectors, err := os.Open(filename)
+ if err != nil {
+ panic(err)
+ }
+ defer vectors.Close()
+
+ var segments []string
+ var l uint64
+ var ikm, okm string
+
+ scanner := bufio.NewScanner(vectors)
+ for scanner.Scan() {
+ segments = strings.Split(scanner.Text(), " = ")
+
+ switch {
+ case strings.ToUpper(segments[0]) == "L":
+ l, err = strconv.ParseUint(segments[1], 10, 64)
+ if err != nil {
+ panic(err)
+ }
+ case strings.ToUpper(segments[0]) == "IKM":
+ ikm = segments[1]
+ case strings.ToUpper(segments[0]) == "OKM":
+ okm = segments[1]
+ }
+ }
+ return verifier(l, unhexlify(ikm), unhexlify(okm))
+}
+
+func main() {
+ if validateVectors("vectors/cryptography_vectors/KDF/hkdf-generated.txt") {
+ fmt.Println("HKDF OK.")
+ } else {
+ fmt.Println("HKDF failed.")
+ os.Exit(1)
+ }
+}
diff --git a/docs/development/custom-vectors/idea.rst b/docs/development/custom-vectors/idea.rst
index 336cdf01..758a108e 100644
--- a/docs/development/custom-vectors/idea.rst
+++ b/docs/development/custom-vectors/idea.rst
@@ -29,4 +29,4 @@ project's Python bindings.
Download link: :download:`verify_idea.py
</development/custom-vectors/idea/verify_idea.py>`
-.. _`Botan`: http://botan.randombit.net
+.. _`Botan`: https://botan.randombit.net
diff --git a/docs/development/custom-vectors/idea/generate_idea.py b/docs/development/custom-vectors/idea/generate_idea.py
index c9f94024..2eb6996e 100644
--- a/docs/development/custom-vectors/idea/generate_idea.py
+++ b/docs/development/custom-vectors/idea/generate_idea.py
@@ -52,6 +52,7 @@ def write_file(data, filename):
with open(filename, "w") as f:
f.write(data)
+
CBC_PATH = "tests/hazmat/primitives/vectors/ciphers/AES/CBC/CBCMMT128.rsp"
write_file(build_vectors(modes.CBC, CBC_PATH), "idea-cbc.txt")
OFB_PATH = "tests/hazmat/primitives/vectors/ciphers/AES/OFB/OFBMMT128.rsp"
diff --git a/docs/development/custom-vectors/rsa-oaep-sha2.rst b/docs/development/custom-vectors/rsa-oaep-sha2.rst
new file mode 100644
index 00000000..36f256d7
--- /dev/null
+++ b/docs/development/custom-vectors/rsa-oaep-sha2.rst
@@ -0,0 +1,56 @@
+RSA OAEP SHA2 vector creation
+=============================
+
+This page documents the code that was used to generate the RSA OAEP SHA2
+test vectors as well as code used to verify them against another
+implementation.
+
+
+Creation
+--------
+
+``cryptography`` was modified to allow the use of SHA2 in OAEP encryption. Then
+the following python script was run to generate the vector files.
+
+.. literalinclude:: /development/custom-vectors/rsa-oaep-sha2/generate_rsa_oaep_sha2.py
+
+Download link: :download:`generate_rsa_oaep_sha2.py
+</development/custom-vectors/rsa-oaep-sha2/generate_rsa_oaep_sha2.py>`
+
+
+Verification
+------------
+
+A Java 8 program was written using `Bouncy Castle`_ to load and verify the test
+vectors.
+
+
+.. literalinclude:: /development/custom-vectors/rsa-oaep-sha2/VerifyRSAOAEPSHA2.java
+
+Download link: :download:`VerifyRSAOAEPSHA2.java
+</development/custom-vectors/rsa-oaep-sha2/VerifyRSAOAEPSHA2.java>`
+
+Using the Verifier
+------------------
+
+Download and install the `Java 8 SDK`_. Initial verification was performed
+using ``jdk-8u77-macosx-x64.dmg``.
+
+Download the latest `Bouncy Castle`_ JAR. Initial verification was performed
+using ``bcprov-jdk15on-154.jar``.
+
+Set the ``-classpath`` to include the Bouncy Castle jar and the path to
+``VerifyRSAOAEPSHA2.java`` and compile the program.
+
+.. code-block:: console
+
+ $ javac -classpath ~/Downloads/bcprov-jdk15on-154.jar:./ VerifyRSAOAEPSHA2.java
+
+Finally, run the program with the path to the SHA-2 vectors:
+
+.. code-block:: console
+
+ $ java -classpath ~/Downloads/bcprov-jdk15on-154.jar:./ VerifyRSAOAEPSHA2
+
+.. _`Bouncy Castle`: https://www.bouncycastle.org/
+.. _`Java 8 SDK`: https://www.oracle.com/technetwork/java/javase/downloads/index.html
diff --git a/docs/development/custom-vectors/rsa-oaep-sha2/VerifyRSAOAEPSHA2.java b/docs/development/custom-vectors/rsa-oaep-sha2/VerifyRSAOAEPSHA2.java
new file mode 100644
index 00000000..e1bfd3d1
--- /dev/null
+++ b/docs/development/custom-vectors/rsa-oaep-sha2/VerifyRSAOAEPSHA2.java
@@ -0,0 +1,416 @@
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.AlgorithmParameters;
+import java.security.GeneralSecurityException;
+import java.security.KeyFactory;
+import java.security.PrivateKey;
+import java.security.Security;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.MGF1ParameterSpec;
+import java.security.spec.RSAPrivateKeySpec;
+import java.util.Arrays;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.OAEPParameterSpec;
+import javax.crypto.spec.PSource;
+import javax.xml.bind.DatatypeConverter;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+
+class TestVectorData {
+ public BigInteger pub_key_modulus;
+ public BigInteger pub_key_exponent;
+ public BigInteger priv_key_public_exponent;
+ public BigInteger priv_key_modulus;
+ public BigInteger priv_key_exponent;
+ public BigInteger priv_key_prime_1;
+ public BigInteger priv_key_prime_2;
+ public BigInteger priv_key_prime_exponent_1;
+ public BigInteger priv_key_prime_exponent_2;
+ public BigInteger priv_key_coefficient;
+ public byte[] plaintext;
+ public byte[] ciphertext;
+}
+
+class TestVectorLoader {
+ private static final String FILE_HEADER = "# RSA OAEP SHA2 vectors built";
+ private static final String EXAMPLE_HEADER = "# =====";
+ private static final String EXAMPLE = "# Example";
+ private static final String PUBLIC_KEY = "# Public key";
+ private static final String PUB_MODULUS = "# Modulus:";
+ private static final String PUB_EXPONENT = "# Exponent:";
+ private static final String PRIVATE_KEY = "# Private key";
+ private static final String PRIV_MODULUS = "# Modulus:";
+ private static final String PRIV_PUBLIC_EXPONENT = "# Public exponent:";
+ private static final String PRIV_EXPONENT = "# Exponent:";
+ private static final String PRIV_PRIME_1 = "# Prime 1:";
+ private static final String PRIV_PRIME_2 = "# Prime 2:";
+ private static final String PRIV_PRIME_EXPONENT_1 = "# Prime exponent 1:";
+ private static final String PRIV_PRIME_EXPONENT_2 = "# Prime exponent 2:";
+ private static final String PRIV_COEFFICIENT = "# Coefficient:";
+ private static final String OAEP_EXAMPLE_HEADER = "# OAEP Example";
+ private static final String MESSAGE = "# Message:";
+ private static final String ENCRYPTION = "# Encryption:";
+
+ private BufferedReader m_reader = null;
+ private FileReader m_file_reader = null;
+ private TestVectorData m_data = null;
+
+ TestVectorLoader() {
+
+ }
+
+ protected void finalize() {
+ close();
+ }
+
+ public void open(String path) throws IOException {
+ close();
+ m_file_reader = new FileReader(path);
+ m_reader = new BufferedReader(m_file_reader);
+ m_data = new TestVectorData();
+ }
+
+ public void close() {
+ try {
+ if (m_reader != null) {
+ m_reader.close();
+ m_reader = null;
+ }
+ if (m_file_reader != null) {
+ m_file_reader.close();
+ m_file_reader = null;
+ }
+ m_data = null;
+ } catch (IOException e) {
+ System.out.println("Exception closing files");
+ e.printStackTrace();
+ }
+ }
+
+ public TestVectorData loadNextTest() throws IOException {
+ if (m_file_reader == null || m_reader == null || m_data == null) {
+ throw new IOException("A test vector file must be opened first");
+ }
+
+ String line = m_reader.readLine();
+
+ if (line == null) {
+ // end of file
+ return null;
+ }
+
+ if (line.startsWith(FILE_HEADER)) {
+ // start of file
+ skipFileHeader(m_reader);
+ line = m_reader.readLine();
+ }
+
+ if (line.startsWith(OAEP_EXAMPLE_HEADER)) {
+ // Next example, keep existing keys and load next message
+ loadMessage(m_reader, m_data);
+ return m_data;
+ }
+
+ // otherwise it's a new example
+ if (!line.startsWith(EXAMPLE_HEADER)) {
+ throw new IOException("Test Header Missing");
+ }
+ startNewTest(m_reader);
+ m_data = new TestVectorData();
+
+ line = m_reader.readLine();
+ if (!line.startsWith(PUBLIC_KEY))
+ throw new IOException("Public Key Missing");
+ loadPublicKey(m_reader, m_data);
+
+ line = m_reader.readLine();
+ if (!line.startsWith(PRIVATE_KEY))
+ throw new IOException("Private Key Missing");
+ loadPrivateKey(m_reader, m_data);
+
+ line = m_reader.readLine();
+ if (!line.startsWith(OAEP_EXAMPLE_HEADER))
+ throw new IOException("Message Missing");
+ loadMessage(m_reader, m_data);
+
+ return m_data;
+ }
+
+ private byte[] unhexlify(String line) {
+ byte[] bytes = DatatypeConverter.parseHexBinary(line);
+ return bytes;
+ }
+
+ private BigInteger readBigInteger(BufferedReader br) throws IOException {
+ return new BigInteger(br.readLine(), 16);
+ }
+
+ private void skipFileHeader(BufferedReader br) throws IOException {
+ br.readLine(); // # # Derived from the NIST OAEP SHA1 vectors
+ br.readLine(); // # # Verified against the Bouncy Castle OAEP SHA2 implementation
+ br.readLine(); // #
+ }
+
+ private void startNewTest(BufferedReader br) throws IOException {
+ String line = br.readLine();
+ if (!line.startsWith(EXAMPLE))
+ throw new IOException("Example Header Missing");
+ }
+
+ private void loadPublicKey(BufferedReader br, TestVectorData data) throws IOException {
+ String line = br.readLine();
+ if (!line.startsWith(PUB_MODULUS))
+ throw new IOException("Public Key Modulus Missing");
+ data.pub_key_modulus = readBigInteger(br);
+
+ line = br.readLine();
+ if (!line.startsWith(PUB_EXPONENT))
+ throw new IOException("Public Key Exponent Missing");
+ data.pub_key_exponent = readBigInteger(br);
+ }
+
+ private void loadPrivateKey(BufferedReader br, TestVectorData data) throws IOException {
+ String line = br.readLine();
+ if (!line.startsWith(PRIV_MODULUS))
+ throw new IOException("Private Key Modulus Missing");
+ data.priv_key_modulus = readBigInteger(br);
+
+ line = br.readLine();
+ if (!line.startsWith(PRIV_PUBLIC_EXPONENT))
+ throw new IOException("Private Key Public Exponent Missing");
+ data.priv_key_public_exponent = readBigInteger(br);
+
+ line = br.readLine();
+ if (!line.startsWith(PRIV_EXPONENT))
+ throw new IOException("Private Key Exponent Missing");
+ data.priv_key_exponent = readBigInteger(br);
+
+ line = br.readLine();
+ if (!line.startsWith(PRIV_PRIME_1))
+ throw new IOException("Private Key Prime 1 Missing");
+ data.priv_key_prime_1 = readBigInteger(br);
+
+ line = br.readLine();
+ if (!line.startsWith(PRIV_PRIME_2))
+ throw new IOException("Private Key Prime 2 Missing");
+ data.priv_key_prime_2 = readBigInteger(br);
+
+ line = br.readLine();
+ if (!line.startsWith(PRIV_PRIME_EXPONENT_1))
+ throw new IOException("Private Key Prime Exponent 1 Missing");
+ data.priv_key_prime_exponent_1 = readBigInteger(br);
+
+ line = br.readLine();
+ if (!line.startsWith(PRIV_PRIME_EXPONENT_2))
+ throw new IOException("Private Key Prime Exponent 2 Missing");
+ data.priv_key_prime_exponent_2 = readBigInteger(br);
+
+ line = br.readLine();
+ if (!line.startsWith(PRIV_COEFFICIENT))
+ throw new IOException("Private Key Coefficient Missing");
+ data.priv_key_coefficient = readBigInteger(br);
+ }
+
+ private void loadMessage(BufferedReader br, TestVectorData data) throws IOException {
+ String line = br.readLine();
+ if (!line.startsWith(MESSAGE))
+ throw new IOException("Plaintext Missing");
+ data.plaintext = unhexlify(br.readLine());
+
+ line = br.readLine();
+ if (!line.startsWith(ENCRYPTION))
+ throw new IOException("Ciphertext Missing");
+ data.ciphertext = unhexlify(br.readLine());
+ }
+
+}
+
+public class VerifyRSAOAEPSHA2 {
+
+ public enum SHAHash {
+ SHA1, SHA224, SHA256, SHA384, SHA512
+ }
+
+ private SHAHash m_mgf1_hash;
+ private SHAHash m_alg_hash;
+ private Cipher m_cipher;
+ private PrivateKey m_private_key;
+ private AlgorithmParameters m_algo_param;
+
+ VerifyRSAOAEPSHA2(SHAHash mgf1_hash, SHAHash alg_hash, TestVectorData test_data) throws Exception {
+
+ m_mgf1_hash = mgf1_hash;
+ m_alg_hash = alg_hash;
+
+ MGF1ParameterSpec mgf1_spec = getMGF1ParameterSpec(m_mgf1_hash);
+ AlgorithmParameterSpec algo_param_spec = getAlgorithmParameterSpec(m_alg_hash, mgf1_spec);
+
+ m_algo_param = AlgorithmParameters.getInstance("OAEP");
+ m_algo_param.init(algo_param_spec);
+
+ m_private_key = loadPrivateKey(test_data);
+
+ m_cipher = getCipher(m_alg_hash);
+ }
+
+ private Cipher getCipher(SHAHash alg_hash) throws GeneralSecurityException {
+ Cipher cipher = null;
+
+ switch (alg_hash) {
+
+ case SHA1:
+ cipher = Cipher.getInstance("RSA/ECB/OAEPwithSHA1andMGF1Padding", "BC");
+ break;
+
+ case SHA224:
+ cipher = Cipher.getInstance("RSA/ECB/OAEPwithSHA-224andMGF1Padding", "BC");
+ break;
+
+ case SHA256:
+ cipher = Cipher.getInstance("RSA/ECB/OAEPwithSHA-256andMGF1Padding", "BC");
+ break;
+
+ case SHA384:
+ cipher = Cipher.getInstance("RSA/ECB/OAEPwithSHA-384andMGF1Padding", "BC");
+ break;
+
+ case SHA512:
+ cipher = Cipher.getInstance("RSA/ECB/OAEPwithSHA-512andMGF1Padding", "BC");
+ break;
+ }
+
+ return cipher;
+ }
+
+ private MGF1ParameterSpec getMGF1ParameterSpec(SHAHash mgf1_hash) {
+ MGF1ParameterSpec mgf1 = null;
+
+ switch (mgf1_hash) {
+
+ case SHA1:
+ mgf1 = MGF1ParameterSpec.SHA1;
+ break;
+ case SHA224:
+ mgf1 = MGF1ParameterSpec.SHA224;
+ break;
+
+ case SHA256:
+ mgf1 = MGF1ParameterSpec.SHA256;
+ break;
+
+ case SHA384:
+ mgf1 = MGF1ParameterSpec.SHA384;
+ break;
+
+ case SHA512:
+ mgf1 = MGF1ParameterSpec.SHA512;
+ break;
+ }
+
+ return mgf1;
+ }
+
+ private AlgorithmParameterSpec getAlgorithmParameterSpec(SHAHash alg_hash, MGF1ParameterSpec mgf1_spec) {
+
+ OAEPParameterSpec oaep_spec = null;
+
+ switch (alg_hash) {
+
+ case SHA1:
+ oaep_spec = new OAEPParameterSpec("SHA1", "MGF1", mgf1_spec, PSource.PSpecified.DEFAULT);
+ break;
+
+ case SHA224:
+ oaep_spec = new OAEPParameterSpec("SHA-224", "MGF1", mgf1_spec, PSource.PSpecified.DEFAULT);
+ break;
+
+ case SHA256:
+ oaep_spec = new OAEPParameterSpec("SHA-256", "MGF1", mgf1_spec, PSource.PSpecified.DEFAULT);
+ break;
+
+ case SHA384:
+ oaep_spec = new OAEPParameterSpec("SHA-384", "MGF1", mgf1_spec, PSource.PSpecified.DEFAULT);
+ break;
+
+ case SHA512:
+ oaep_spec = new OAEPParameterSpec("SHA-512", "MGF1", mgf1_spec, PSource.PSpecified.DEFAULT);
+ break;
+ }
+
+ return oaep_spec;
+ }
+
+ private PrivateKey loadPrivateKey(TestVectorData test_data) throws Exception {
+ KeyFactory kf = KeyFactory.getInstance("RSA");
+
+ RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(test_data.priv_key_modulus, test_data.priv_key_exponent);
+
+ return kf.generatePrivate(keySpec);
+ }
+
+ public void testDecrypt(byte[] plaintext, byte[] ciphertext) throws Exception {
+ System.out.println("Verifying OAEP with mgf1_hash: " + m_mgf1_hash + " alg_hash: " + m_alg_hash + " - "
+ + ciphertext.length + " bytes ciphertext - "
+ + plaintext.length + " bytes plaintext");
+
+ m_cipher.init(Cipher.DECRYPT_MODE, m_private_key, m_algo_param);
+ byte[] java_plaintext = m_cipher.doFinal(ciphertext);
+
+ if (Arrays.equals(java_plaintext, plaintext) == false) {
+ throw new Exception("Verification failure - plaintext does not match after decryption.");
+ }
+ }
+
+ public static void main(String[] args) {
+ Security.addProvider(new BouncyCastleProvider());
+
+ // assume current directory if no path given on command line
+ String vector_path = "./vectors/cryptography_vectors/asymmetric/RSA/oaep-custom";
+
+ if (args.length > 0) {
+ vector_path = args[0];
+ }
+
+ System.out.println("Vector file path: " + vector_path);
+
+ try {
+ // loop over each combination of hash loading the vector file
+ // to verify for each
+ for (SHAHash mgf1_hash : SHAHash.values()) {
+ for (SHAHash alg_hash : SHAHash.values()) {
+ if (mgf1_hash.name().toLowerCase().equals("sha1") &&
+ alg_hash.name().toLowerCase().equals("sha1")) {
+ continue;
+ }
+ String filename = "oaep-" + mgf1_hash.name().toLowerCase() +
+ "-" + alg_hash.name().toLowerCase() + ".txt";
+
+ System.out.println("Loading " + filename + "...");
+
+ TestVectorLoader loader = new TestVectorLoader();
+ loader.open(vector_path + filename);
+
+ TestVectorData test_data;
+
+ // load each test in the file and verify
+ while ((test_data = loader.loadNextTest()) != null) {
+ VerifyRSAOAEPSHA2 verify = new VerifyRSAOAEPSHA2(mgf1_hash, alg_hash, test_data);
+ verify.testDecrypt(test_data.plaintext, test_data.ciphertext);
+ }
+
+ System.out.println("Verifying " + filename + " completed successfully.");
+ }
+ }
+
+ System.out.println("All verification completed successfully");
+
+ } catch (Exception e) {
+ // if any exception is thrown the verification has failed
+ e.printStackTrace();
+ System.out.println("Verification Failed!");
+ }
+ }
+}
diff --git a/docs/development/custom-vectors/rsa-oaep-sha2/generate_rsa_oaep_sha2.py b/docs/development/custom-vectors/rsa-oaep-sha2/generate_rsa_oaep_sha2.py
new file mode 100644
index 00000000..bd5148f5
--- /dev/null
+++ b/docs/development/custom-vectors/rsa-oaep-sha2/generate_rsa_oaep_sha2.py
@@ -0,0 +1,128 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import binascii
+import itertools
+import os
+
+from cryptography.hazmat.backends.openssl.backend import backend
+from cryptography.hazmat.primitives import hashes
+from cryptography.hazmat.primitives.asymmetric import padding, rsa
+
+from tests.utils import load_pkcs1_vectors, load_vectors_from_file
+
+
+def build_vectors(mgf1alg, hashalg, filename):
+ vectors = load_vectors_from_file(filename, load_pkcs1_vectors)
+
+ output = []
+ for vector in vectors:
+ # RSA keys for this must be long enough to accommodate the length of
+ # the underlying hash function. This means we can't use the keys from
+ # the sha1 test vectors for sha512 tests because 1024-bit keys are too
+ # small. Instead we parse the vectors for the test cases, then
+ # generate our own 2048-bit keys for each.
+ private, _ = vector
+ skey = rsa.generate_private_key(65537, 2048, backend)
+ pn = skey.private_numbers()
+ examples = private["examples"]
+ output.append(b"# =============================================")
+ output.append(b"# Example")
+ output.append(b"# Public key")
+ output.append(b"# Modulus:")
+ output.append(format(pn.public_numbers.n, "x"))
+ output.append(b"# Exponent:")
+ output.append(format(pn.public_numbers.e, "x"))
+ output.append(b"# Private key")
+ output.append(b"# Modulus:")
+ output.append(format(pn.public_numbers.n, "x"))
+ output.append(b"# Public exponent:")
+ output.append(format(pn.public_numbers.e, "x"))
+ output.append(b"# Exponent:")
+ output.append(format(pn.d, "x"))
+ output.append(b"# Prime 1:")
+ output.append(format(pn.p, "x"))
+ output.append(b"# Prime 2:")
+ output.append(format(pn.q, "x"))
+ output.append(b"# Prime exponent 1:")
+ output.append(format(pn.dmp1, "x"))
+ output.append(b"# Prime exponent 2:")
+ output.append(format(pn.dmq1, "x"))
+ output.append(b"# Coefficient:")
+ output.append(format(pn.iqmp, "x"))
+ pkey = skey.public_key()
+ vectorkey = rsa.RSAPrivateNumbers(
+ p=private["p"],
+ q=private["q"],
+ d=private["private_exponent"],
+ dmp1=private["dmp1"],
+ dmq1=private["dmq1"],
+ iqmp=private["iqmp"],
+ public_numbers=rsa.RSAPublicNumbers(
+ e=private["public_exponent"],
+ n=private["modulus"]
+ )
+ ).private_key(backend)
+ count = 1
+
+ for example in examples:
+ message = vectorkey.decrypt(
+ binascii.unhexlify(example["encryption"]),
+ padding.OAEP(
+ mgf=padding.MGF1(algorithm=hashes.SHA1()),
+ algorithm=hashes.SHA1(),
+ label=None
+ )
+ )
+ assert message == binascii.unhexlify(example["message"])
+ ct = pkey.encrypt(
+ message,
+ padding.OAEP(
+ mgf=padding.MGF1(algorithm=mgf1alg),
+ algorithm=hashalg,
+ label=None
+ )
+ )
+ output.append(
+ b"# OAEP Example {0} alg={1} mgf1={2}".format(
+ count, hashalg.name, mgf1alg.name
+ )
+ )
+ count += 1
+ output.append(b"# Message:")
+ output.append(example["message"])
+ output.append(b"# Encryption:")
+ output.append(binascii.hexlify(ct))
+
+ return b"\n".join(output)
+
+
+def write_file(data, filename):
+ with open(filename, "w") as f:
+ f.write(data)
+
+
+oaep_path = os.path.join(
+ "asymmetric", "RSA", "pkcs-1v2-1d2-vec", "oaep-vect.txt"
+)
+hashalgs = [
+ hashes.SHA1(),
+ hashes.SHA224(),
+ hashes.SHA256(),
+ hashes.SHA384(),
+ hashes.SHA512(),
+]
+for hashtuple in itertools.product(hashalgs, hashalgs):
+ if (
+ isinstance(hashtuple[0], hashes.SHA1) and
+ isinstance(hashtuple[1], hashes.SHA1)
+ ):
+ continue
+
+ write_file(
+ build_vectors(hashtuple[0], hashtuple[1], oaep_path),
+ "oaep-{0}-{1}.txt".format(hashtuple[0].name, hashtuple[1].name)
+ )
diff --git a/docs/development/custom-vectors/secp256k1.rst b/docs/development/custom-vectors/secp256k1.rst
index b19bf4e4..e0579b4f 100644
--- a/docs/development/custom-vectors/secp256k1.rst
+++ b/docs/development/custom-vectors/secp256k1.rst
@@ -29,4 +29,4 @@ the following python script was run to generate the vector files.
Download link: :download:`verify_secp256k1.py
</development/custom-vectors/secp256k1/verify_secp256k1.py>`
-.. _`pure Python ecdsa`: https://pypi.python.org/pypi/ecdsa
+.. _`pure Python ecdsa`: https://pypi.org/project/ecdsa/
diff --git a/docs/development/custom-vectors/secp256k1/generate_secp256k1.py b/docs/development/custom-vectors/secp256k1/generate_secp256k1.py
index 502a3ff6..d6a2071a 100644
--- a/docs/development/custom-vectors/secp256k1/generate_secp256k1.py
+++ b/docs/development/custom-vectors/secp256k1/generate_secp256k1.py
@@ -74,6 +74,7 @@ def write_file(lines, dest):
print(line)
print(line, file=dest)
+
source_path = os.path.join("asymmetric", "ECDSA", "FIPS_186-3", "SigGen.txt")
dest_path = os.path.join("asymmetric", "ECDSA", "SECP256K1", "SigGen.txt")
diff --git a/docs/development/custom-vectors/secp256k1/verify_secp256k1.py b/docs/development/custom-vectors/secp256k1/verify_secp256k1.py
index 3d2c25b9..b236d77f 100644
--- a/docs/development/custom-vectors/secp256k1/verify_secp256k1.py
+++ b/docs/development/custom-vectors/secp256k1/verify_secp256k1.py
@@ -6,7 +6,7 @@ from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.asymmetric.utils import (
- encode_rfc6979_signature
+ encode_dss_signature
)
from tests.utils import (
@@ -27,7 +27,7 @@ def verify_one_vector(vector):
message = vector['message']
x = vector['x']
y = vector['y']
- signature = encode_rfc6979_signature(vector['r'], vector['s'])
+ signature = encode_dss_signature(vector['r'], vector['s'])
numbers = ec.EllipticCurvePublicNumbers(
x, y,
diff --git a/docs/development/custom-vectors/seed.rst b/docs/development/custom-vectors/seed.rst
index 290fb77a..8c4a7aab 100644
--- a/docs/development/custom-vectors/seed.rst
+++ b/docs/development/custom-vectors/seed.rst
@@ -29,4 +29,4 @@ project's Python bindings.
Download link: :download:`verify_seed.py
</development/custom-vectors/seed/verify_seed.py>`
-.. _`Botan`: http://botan.randombit.net
+.. _`Botan`: https://botan.randombit.net
diff --git a/docs/development/custom-vectors/seed/generate_seed.py b/docs/development/custom-vectors/seed/generate_seed.py
index d59597fd..5c62d671 100644
--- a/docs/development/custom-vectors/seed/generate_seed.py
+++ b/docs/development/custom-vectors/seed/generate_seed.py
@@ -51,6 +51,7 @@ def write_file(data, filename):
with open(filename, "w") as f:
f.write(data)
+
OFB_PATH = "vectors/cryptography_vectors/ciphers/AES/OFB/OFBMMT128.rsp"
write_file(build_vectors(modes.OFB, OFB_PATH), "seed-ofb.txt")
CFB_PATH = "vectors/cryptography_vectors/ciphers/AES/CFB/CFB128MMT128.rsp"
diff --git a/docs/development/getting-started.rst b/docs/development/getting-started.rst
index b3474002..1d939a9c 100644
--- a/docs/development/getting-started.rst
+++ b/docs/development/getting-started.rst
@@ -1,25 +1,63 @@
Getting started
===============
+Development dependencies
+------------------------
Working on ``cryptography`` requires the installation of a small number of
development dependencies in addition to the dependencies for
:doc:`/installation`. These are listed in ``dev-requirements.txt`` and they can
-be installed in a `virtualenv`_ using `pip`_. Once you've installed the
-dependencies, install ``cryptography`` in ``editable`` mode. For example:
+be installed in a `virtualenv`_ using `pip`_. Before you install them, follow
+the **build** instructions in :doc:`/installation` (be sure to stop before
+actually installing ``cryptography``). Once you've done that, install the
+development dependencies, and then install ``cryptography`` in ``editable``
+mode. For example:
.. code-block:: console
$ # Create a virtualenv and activate it
+ $ # Set up your cryptography build environment
$ pip install --requirement dev-requirements.txt
$ pip install --editable .
+Make sure that ``pip install --requirement ...`` has installed the Python
+package ``vectors/`` and packages on ``tests/`` . If it didn't, you may
+install them manually by using ``pip`` on each directory.
+
You will also need to install ``enchant`` using your system's package manager
to check spelling in the documentation.
+.. note::
+ There is an upstream bug in ``enchant`` that prevents its installation on
+ Windows with 64-bit Python. See `this Github issue`_ for more information.
+ The easiest workaround is to use 32-bit Python for ``cryptography``
+ development, even on 64-bit Windows.
+
You are now ready to run the tests and build the documentation.
+OpenSSL on macOS
+~~~~~~~~~~~~~~~~
+
+You must have installed `OpenSSL`_ via `Homebrew`_ or `MacPorts`_ and must set
+``CFLAGS`` and ``LDFLAGS`` environment variables before installing the
+``dev-requirements.txt`` otherwise pip will fail with include errors.
+
+For example, with `Homebrew`_:
+
+.. code-block:: console
+
+ $ env LDFLAGS="-L$(brew --prefix openssl@1.1)/lib" \
+ CFLAGS="-I$(brew --prefix openssl@1.1)/include" \
+ pip install --requirement ./dev-requirements.txt
+
+Alternatively for a static build you can specify
+``CRYPTOGRAPHY_SUPPRESS_LINK_FLAGS=1`` and ensure ``LDFLAGS`` points to the
+absolute path for the `OpenSSL`_ libraries before calling pip.
+
+.. tip::
+ You will also need to set these values when `Building documentation`_.
+
Running tests
-~~~~~~~~~~~~~
+-------------
``cryptography`` unit tests are found in the ``tests/`` directory and are
designed to be run using `pytest`_. `pytest`_ will discover the tests
@@ -27,7 +65,7 @@ automatically, so all you have to do is:
.. code-block:: console
- $ py.test
+ $ pytest
...
62746 passed in 220.43 seconds
@@ -41,10 +79,9 @@ each supported Python version and run the tests. For example:
$ tox
...
- ERROR: py26: InterpreterNotFound: python2.6
py27: commands succeeded
ERROR: pypy: InterpreterNotFound: pypy
- py33: commands succeeded
+ py38: commands succeeded
docs: commands succeeded
pep8: commands succeeded
@@ -52,22 +89,8 @@ You may not have all the required Python versions installed, in which case you
will see one or more ``InterpreterNotFound`` errors.
-Explicit backend selection
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-While testing you may want to run tests against a subset of the backends that
-cryptography supports. Explicit backend selection can be done via the
-``--backend`` flag. This flag should be passed to ``py.test`` with a comma
-delimited list of backend names.
-
-
-.. code-block:: console
-
- $ tox -- --backend=openssl
- $ py.test --backend=openssl,commoncrypto
-
Building documentation
-~~~~~~~~~~~~~~~~~~~~~~
+----------------------
``cryptography`` documentation is stored in the ``docs/`` directory. It is
written in `reStructured Text`_ and rendered using `Sphinx`_.
@@ -84,9 +107,13 @@ Use `tox`_ to build the documentation. For example:
The HTML documentation index can now be found at
``docs/_build/html/index.html``.
-.. _`pytest`: https://pypi.python.org/pypi/pytest
-.. _`tox`: https://pypi.python.org/pypi/tox
-.. _`virtualenv`: https://pypi.python.org/pypi/virtualenv
-.. _`pip`: https://pypi.python.org/pypi/pip
-.. _`sphinx`: https://pypi.python.org/pypi/Sphinx
-.. _`reStructured Text`: http://sphinx-doc.org/rest.html
+.. _`Homebrew`: https://brew.sh
+.. _`MacPorts`: https://www.macports.org
+.. _`OpenSSL`: https://www.openssl.org
+.. _`pytest`: https://pypi.org/project/pytest/
+.. _`tox`: https://pypi.org/project/tox/
+.. _`virtualenv`: https://pypi.org/project/virtualenv/
+.. _`pip`: https://pypi.org/project/pip/
+.. _`sphinx`: https://pypi.org/project/Sphinx/
+.. _`reStructured Text`: https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html
+.. _`this Github issue`: https://github.com/rfk/pyenchant/issues/42
diff --git a/docs/development/index.rst b/docs/development/index.rst
index f9bc9eea..81befe43 100644
--- a/docs/development/index.rst
+++ b/docs/development/index.rst
@@ -17,4 +17,4 @@ bug check out `what to put in your bug report`_.
c-bindings
.. _`GitHub`: https://github.com/pyca/cryptography
-.. _`what to put in your bug report`: http://www.contribution-guide.org/#what-to-put-in-your-bug-report
+.. _`what to put in your bug report`: https://www.contribution-guide.org/#what-to-put-in-your-bug-report
diff --git a/docs/development/reviewing-patches.rst b/docs/development/reviewing-patches.rst
index bd3ee96a..08446183 100644
--- a/docs/development/reviewing-patches.rst
+++ b/docs/development/reviewing-patches.rst
@@ -7,18 +7,18 @@ review is our opportunity to share knowledge, design ideas and make friends.
When reviewing a patch try to keep each of these concepts in mind:
-Architecture
-------------
-
-* Is the proposed change being made in the correct place? Is it a fix in a
- backend when it should be in the primitives?
-
Intent
------
* What is the change being proposed?
* Do we want this feature or is the bug they're fixing really a bug?
+Architecture
+------------
+
+* Is the proposed change being made in the correct place? Is it a fix in a
+ backend when it should be in the primitives?
+
Implementation
--------------
diff --git a/docs/development/submitting-patches.rst b/docs/development/submitting-patches.rst
index 66105843..ac1986a3 100644
--- a/docs/development/submitting-patches.rst
+++ b/docs/development/submitting-patches.rst
@@ -48,7 +48,7 @@ API considerations
Most projects' APIs are designed with a philosophy of "make easy things easy,
and make hard things possible". One of the perils of writing cryptographic code
is that secure code looks just like insecure code, and its results are almost
-always indistinguishable. As a result ``cryptography`` has, as a design
+always indistinguishable. As a result, ``cryptography`` has, as a design
philosophy: "make it hard to do insecure things". Here are a few strategies for
API design that should be both followed, and should inspire other API choices:
@@ -126,6 +126,11 @@ should begin with the "Hazardous Materials" warning:
.. hazmat::
+Always prefer terminology that is most broadly accepted. For example:
+
+* When referring to class instances use "an instance of ``Foo``"
+ instead of "a ``Foo`` provider".
+
When referring to a hypothetical individual (such as "a person receiving an
encrypted message") use gender neutral pronouns (they/them/their).
@@ -149,8 +154,8 @@ So, specifically:
* Use Sphinx parameter/attribute documentation `syntax`_.
-.. _`Write comments as complete sentences.`: http://nedbatchelder.com/blog/201401/comments_should_be_sentences.html
-.. _`syntax`: http://sphinx-doc.org/domains.html#info-field-lists
-.. _`Studies have shown`: https://smartbear.com/smartbear/media/pdfs/wp-cc-11-best-practices-of-peer-code-review.pdf
+.. _`Write comments as complete sentences.`: https://nedbatchelder.com/blog/201401/comments_should_be_sentences.html
+.. _`syntax`: https://www.sphinx-doc.org/en/master/usage/restructuredtext/domains.html#info-field-lists
+.. _`Studies have shown`: https://smartbear.com/learn/code-review/best-practices-for-peer-code-review/
.. _`our mailing list`: https://mail.python.org/mailman/listinfo/cryptography-dev
-.. _`doc8`: https://github.com/stackforge/doc8
+.. _`doc8`: https://github.com/openstack/doc8
diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst
index bc171b21..182df188 100644
--- a/docs/development/test-vectors.rst
+++ b/docs/development/test-vectors.rst
@@ -8,12 +8,23 @@ not possible ``cryptography`` has chosen to create a set of custom vectors
using an official vector file as input to verify consistency between
implemented backends.
-Vectors are kept in the `cryptography_vectors` package rather than within our
+Vectors are kept in the ``cryptography_vectors`` package rather than within our
main test suite.
Sources
-------
+Project Wycheproof
+~~~~~~~~~~~~~~~~~~
+
+We run vectors from `Project Wycheproof`_ -- a collection of known edge-cases
+for various cryptographic algorithms. These are not included in the repository
+(or ``cryptography_vectors`` package), but rather cloned from Git in our
+continuous integration environments.
+
+We have ensured all test vectors are used as of commit
+``2196000605e45d91097147c9c71f26b72af58003``.
+
Asymmetric ciphers
~~~~~~~~~~~~~~~~~~
@@ -30,11 +41,16 @@ Asymmetric ciphers
* PKCS #8 PEM serialization vectors from
* GnuTLS: `enc-rsa-pkcs8.pem`_, `enc2-rsa-pkcs8.pem`_,
- `unenc-rsa-pkcs8.pem`_, `pkcs12_s2k_pem.c`_. The contents of
- `enc2-rsa-pkcs8.pem`_ was re-encrypted using a stronger PKCS#8 cipher.
+ `unenc-rsa-pkcs8.pem`_, `pkcs12_s2k_pem.c`_. The encoding error in
+ `unenc-rsa-pkcs8.pem`_ was fixed, and the contents of `enc-rsa-pkcs8.pem`_
+ was re-encrypted to include it. The contents of `enc2-rsa-pkcs8.pem`_
+ was re-encrypted using a stronger PKCS#8 cipher.
* `Botan's ECC private keys`_.
* `asymmetric/public/PKCS1/dsa.pub.pem`_ is a PKCS1 DSA public key from the
Ruby test suite.
+* X25519 and X448 test vectors from :rfc:`7748`.
+* RSA OAEP with custom label from the `BoringSSL evp tests`_.
+* Ed448 test vectors from :rfc:`8032`.
Custom asymmetric vectors
@@ -44,6 +60,7 @@ Custom asymmetric vectors
:maxdepth: 1
custom-vectors/secp256k1
+ custom-vectors/rsa-oaep-sha2
* ``asymmetric/PEM_Serialization/ec_private_key.pem`` and
``asymmetric/DER_Serialization/ec_private_key.der`` - Contains an Elliptic
@@ -69,6 +86,11 @@ Custom asymmetric vectors
* ``asymmetric/PEM_Serialization/dsa_public_key.pem`` and
``asymmetric/DER_Serialization/dsa_public_key.der`` - Contains a DSA 2048 bit
key generated using OpenSSL from ``dsa_private_key.pem``.
+* ``asymmetric/DER_Serialization/dsa_public_key_no_params.der`` - Contains a
+ DSA public key with the optional parameters removed.
+* ``asymmetric/DER_Serialization/dsa_public_key_invalid_bit_string.der`` -
+ Contains a DSA public key with the bit string padding value set to 2 rather
+ than the required 0.
* ``asymmetric/PKCS8/unenc-dsa-pkcs8.pem`` and
``asymmetric/DER_Serialization/unenc-dsa-pkcs8.der`` - Contains a DSA 1024
bit key generated using OpenSSL.
@@ -82,14 +104,86 @@ Custom asymmetric vectors
* ``asymmetric/public/PKCS1/rsa.pub.pem`` and
``asymmetric/public/PKCS1/rsa.pub.der`` are PKCS1 conversions of the public
key from ``asymmetric/PKCS8/unenc-rsa-pkcs8.pem`` using PEM and DER encoding.
+* ``x509/custom/ca/ca_key.pem`` - An unencrypted PCKS8 ``secp256r1`` key. It is
+ the private key for the certificate ``x509/custom/ca/ca.pem``. This key is
+ encoded in several of the PKCS12 custom vectors.
+* ``asymmetric/EC/compressed_points.txt`` - Contains compressed public points
+ generated using OpenSSL.
+* ``asymmetric/X448/x448-pkcs8-enc.pem`` and
+ ``asymmetric/X448/x448-pkcs8-enc.der`` contain an X448 key encrypted with
+ AES 256 CBC with the password ``password``.
+* ``asymmetric/X448/x448-pkcs8.pem`` and ``asymmetric/X448/x448-pkcs8.der``
+ contain an unencrypted X448 key.
+* ``asymmetric/X448/x448-pub.pem`` and ``asymmetric/X448/x448-pub.der`` contain
+ an X448 public key.
+* ``asymmetric/Ed25519/ed25519-pkcs8-enc.pem`` and
+ ``asymmetric/Ed25519/ed25519-pkcs8-enc.der`` contain an Ed25519 key encrypted
+ with AES 256 CBC with the password ``password``.
+* ``asymmetric/Ed25519/ed25519-pkcs8.pem`` and
+ ``asymmetric/Ed25519/ed25519-pkcs8.der`` contain an unencrypted Ed25519 key.
+* ``asymmetric/Ed25519/ed25519-pub.pem`` and
+ ``asymmetric/Ed25519/ed25519-pub.der`` contain an Ed25519 public key.
+* ``asymmetric/X25519/x25519-pkcs8-enc.pem`` and
+ ``asymmetric/X25519/x25519-pkcs8-enc.der`` contain an X25519 key encrypted
+ with AES 256 CBC with the password ``password``.
+* ``asymmetric/X25519/x25519-pkcs8.pem`` and
+ ``asymmetric/X25519/x25519-pkcs8.der`` contain an unencrypted X25519 key.
+* ``asymmetric/X25519/x25519-pub.pem`` and ``asymmetric/X25519/x25519-pub.der``
+ contain an X25519 public key.
+* ``asymmetric/Ed448/ed448-pkcs8-enc.pem`` and
+ ``asymmetric/Ed448/ed448-pkcs8-enc.der`` contain an Ed448 key encrypted
+ with AES 256 CBC with the password ``password``.
+* ``asymmetric/Ed448/ed448-pkcs8.pem`` and
+ ``asymmetric/Ed448/ed448-pkcs8.der`` contain an unencrypted Ed448 key.
+* ``asymmetric/Ed448/ed448-pub.pem`` and ``asymmetric/Ed448/ed448-pub.der``
+ contain an Ed448 public key.
Key exchange
~~~~~~~~~~~~
+* ``vectors/cryptography_vectors/asymmetric/DH/rfc3526.txt`` contains
+ several standardized Diffie-Hellman groups from :rfc:`3526`.
+
* ``vectors/cryptography_vectors/asymmetric/DH/RFC5114.txt`` contains
Diffie-Hellman examples from appendix A.1, A.2 and A.3 of :rfc:`5114`.
+* ``vectors/cryptography_vectors/asymmetric/DH/vec.txt`` contains
+ Diffie-Hellman examples from `botan`_.
+
+* ``vectors/cryptography_vectors/asymmetric/DH/bad_exchange.txt`` contains
+ Diffie-Hellman vector pairs that were generated using OpenSSL
+ ``DH_generate_parameters_ex`` and ``DH_generate_key``.
+
+* ``vectors/cryptography_vectors/asymmetric/DH/dhp.pem``,
+ ``vectors/cryptography_vectors/asymmetric/DH/dhkey.pem`` and
+ ``vectors/cryptography_vectors/asymmetric/DH/dhpub.pem`` contains
+ Diffie-Hellman parameters and key respectively. The keys were
+ generated using OpenSSL following `DHKE`_ guide.
+ ``vectors/cryptography_vectors/asymmetric/DH/dhkey.txt`` contains
+ all parameter in text.
+ ``vectors/cryptography_vectors/asymmetric/DH/dhp.der``,
+ ``vectors/cryptography_vectors/asymmetric/DH/dhkey.der`` and
+ ``vectors/cryptography_vectors/asymmetric/DH/dhpub.der`` contains
+ are the above parameters and keys in DER format.
+
+* ``vectors/cryptography_vectors/asymmetric/DH/dhp_rfc5114_2.pem``,
+ ``vectors/cryptography_vectors/asymmetric/DH/dhkey_rfc5114_2.pem`` and
+ ``vectors/cryptography_vectors/asymmetric/DH/dhpub_rfc5114_2.pem`` contains
+ Diffie-Hellman parameters and key respectively. The keys were
+ generated using OpenSSL following `DHKE`_ guide. When creating the
+ parameters we added the `-pkeyopt dh_rfc5114:2` option to use
+ :rfc:`5114` 2048 bit DH parameters with 224 bit subgroup.
+ ``vectors/cryptography_vectors/asymmetric/DH/dhkey_rfc5114_2.txt`` contains
+ all parameter in text.
+ ``vectors/cryptography_vectors/asymmetric/DH/dhp_rfc5114_2.der``,
+ ``vectors/cryptography_vectors/asymmetric/DH/dhkey_rfc5114_2.der`` and
+ ``vectors/cryptography_vectors/asymmetric/DH/dhpub_rfc5114_2.der`` contains
+ are the above parameters and keys in DER format.
+
+* ``vectors/cryptoraphy_vectors/asymmetric/ECDH/brainpool.txt`` contains
+ Brainpool vectors from :rfc:`7027`.
+
X.509
~~~~~
@@ -102,8 +196,57 @@ X.509
tree.
* ``cryptography.io.pem`` - A leaf certificate issued by RapidSSL for the
cryptography website.
+* ``rapidssl_sha256_ca_g3.pem`` - The intermediate CA that issued the
+ ``cryptography.io.pem`` certificate.
+* ``cryptography.io.precert.pem`` - A pre-certificate with the CT poison
+ extension for the cryptography website.
+* ``cryptography-scts.io.pem`` - A leaf certificate issued by Let's Encrypt for
+ the cryptography website which contains signed certificate timestamps.
* ``wildcard_san.pem`` - A leaf certificate issued by a public CA for
``langui.sh`` that contains wildcard entries in the SAN extension.
+* ``san_edipartyname.der`` - A DSA certificate from a `Mozilla bug`_
+ containing a SAN extension with an ``ediPartyName`` general name.
+* ``san_x400address.der`` - A DSA certificate from a `Mozilla bug`_ containing
+ a SAN extension with an ``x400Address`` general name.
+* ``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.
+* ``alternate-rsa-sha1-oid.pem`` - A certificate from an
+ `unknown signature OID`_ Mozilla bug that uses an alternate signature OID for
+ RSA with SHA1.
+* ``badssl-sct.pem`` - A certificate with the certificate transparency signed
+ certificate timestamp extension.
+* ``bigoid.pem`` - A certificate with a rather long OID in the
+ Certificate Policies extension. We need to make sure we can parse
+ long OIDs.
+* ``wosign-bc-invalid.pem`` - A certificate issued by WoSign that contains
+ a basic constraints extension with CA set to false and a path length of zero
+ in violation of :rfc:`5280`.
+* ``tls-feature-ocsp-staple.pem`` - A certificate issued by Let's Encrypt that
+ contains a TLS Feature extension with the ``status_request`` feature
+ (commonly known as OCSP Must-Staple).
+* ``unique-identifier.pem`` - A certificate containing
+ a distinguished name with an ``x500UniqueIdentifier``.
+* ``utf8-dnsname.pem`` - A certificate containing non-ASCII characters in the
+ DNS name entries of the SAN extension.
+* ``badasn1time.pem`` - A certificate containing an incorrectly specified
+ UTCTime in its validity->not_after.
+* ``letsencryptx3.pem`` - A subordinate certificate used by Let's Encrypt to
+ issue end entity certificates.
+* ``ed25519-rfc8410.pem`` - A certificate containing an X25519 public key with
+ an ``ed25519`` signature taken from :rfc:`8410`.
+* ``root-ed25519.pem`` - An ``ed25519`` root certificate (``ed25519`` signature
+ with ``ed25519`` public key) from the OpenSSL test suite.
+ (`root-ed25519.pem`_)
+* ``server-ed25519-cert.pem`` - An ``ed25519`` server certificate (RSA
+ signature with ``ed25519`` public key) from the OpenSSL test suite.
+ (`server-ed25519-cert.pem`_)
+* ``server-ed448-cert.pem`` - An ``ed448`` server certificate (RSA
+ signature with ``ed448`` public key) from the OpenSSL test suite.
+ (`server-ed448-cert.pem`_)
Custom X.509 Vectors
~~~~~~~~~~~~~~~~~~~~
@@ -135,6 +278,10 @@ Custom X.509 Vectors
* ``unsupported_extension.pem`` - An RSA 2048 bit self-signed certificate
containing an unsupported extension type. The OID was encoded as
"1.2.3.4" with an ``extnValue`` of "value".
+* ``unsupported_extension_2.pem`` - A ``secp256r1`` certificate
+ containing two unsupported extensions. The OIDs are ``1.3.6.1.4.1.41482.2``
+ with an ``extnValue`` of ``1.3.6.1.4.1.41482.1.2`` and
+ ``1.3.6.1.4.1.45724.2.1.1`` with an ``extnValue`` of ``\x03\x02\x040``
* ``unsupported_extension_critical.pem`` - An RSA 2048 bit self-signed
certificate containing an unsupported extension type marked critical. The OID
was encoded as "1.2.3.4" with an ``extnValue`` of "value".
@@ -142,6 +289,9 @@ Custom X.509 Vectors
certificate containing a subject alternative name extension with the
following general names: ``rfc822Name``, ``dNSName``, ``iPAddress``,
``directoryName``, and ``uniformResourceIdentifier``.
+* ``san_empty_hostname.pem`` - An RSA 2048 bit self-signed certificate
+ containing a subject alternative extension with an empty ``dNSName``
+ general name.
* ``san_other_name.pem`` - An RSA 2048 bit self-signed certificate containing
a subject alternative name extension with the ``otherName`` general name.
* ``san_registered_id.pem`` - An RSA 1024 bit certificate containing a
@@ -187,6 +337,9 @@ Custom X.509 Vectors
containing an authority information access extension with an OCSP entry.
* ``aia_ca_issuers.pem`` - An RSA 2048 bit self-signed certificate
containing an authority information access extension with a CA issuers entry.
+* ``cdp_empty_hostname.pem`` - An RSA 2048 bit self-signed certificate
+ containing a CRL distribution point extension with ``fullName`` URI without
+ a hostname.
* ``cdp_fullname_reasons_crl_issuer.pem`` - An RSA 1024 bit certificate
containing a CRL distribution points extension with ``fullName``,
``cRLIssuer``, and ``reasons`` data.
@@ -199,11 +352,25 @@ Custom X.509 Vectors
set.
* ``nc_permitted_excluded.pem`` - An RSA 2048 bit self-signed certificate
containing a name constraints extension with both permitted and excluded
- elements.
+ elements. Contains ``IPv4`` and ``IPv6`` addresses with network mask as well
+ as ``dNSName`` with a leading period.
+* ``nc_permitted_excluded_2.pem`` - An RSA 2048 bit self-signed certificate
+ containing a name constraints extension with both permitted and excluded
+ elements. Unlike ``nc_permitted_excluded.pem``, the general names do not
+ contain any name constraints specific values.
* ``nc_permitted.pem`` - An RSA 2048 bit self-signed certificate containing a
name constraints extension with permitted elements.
+* ``nc_permitted_2.pem`` - An RSA 2048 bit self-signed certificate containing a
+ name constraints extension with permitted elements that do not contain any
+ name constraints specific values.
* ``nc_excluded.pem`` - An RSA 2048 bit self-signed certificate containing a
name constraints extension with excluded elements.
+* ``nc_invalid_ip_netmask.pem`` - An RSA 2048 bit self-signed certificate
+ containing a name constraints extension with a permitted element that has an
+ ``IPv6`` IP and an invalid network mask.
+* ``nc_single_ip_netmask.pem`` - An RSA 2048 bit self-signed certificate
+ containing a name constraints extension with a permitted element that has two
+ IPs with ``/32`` and ``/128`` network masks.
* ``cp_user_notice_with_notice_reference.pem`` - An RSA 2048 bit self-signed
certificate containing a certificate policies extension with a
notice reference in the user notice.
@@ -215,6 +382,8 @@ Custom X.509 Vectors
* ``cp_user_notice_no_explicit_text.pem`` - An RSA 2048 bit self-signed
certificate containing a certificate policies extension with a user notice
with no explicit text.
+* ``cp_invalid.pem`` - An RSA 2048 bit self-signed certificate containing a
+ certificate policies extension with invalid data.
* ``ian_uri.pem`` - An RSA 2048 bit certificate containing an issuer
alternative name extension with a ``URI`` general name.
* ``ocsp_nocheck.pem`` - An RSA 2048 bit self-signed certificate containing
@@ -226,6 +395,20 @@ Custom X.509 Vectors
policy constraints extension with an inhibit policy mapping element.
* ``pc_require.pem`` - An RSA 2048 bit self-signed certificate containing a
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.
+* ``freshestcrl.pem`` - A self-signed certificate containing a ``freshestCRL``
+ extension.
+* ``ca/ca.pem`` - A self-signed certificate with ``basicConstraints`` set to
+ true. Its private key is ``ca/ca_key.pem``. This certificate is encoded in
+ several of the PKCS12 custom vectors.
+* ``negative_serial.pem`` - A certificate with a serial number that is a
+ negative number.
+* ``rsa_pss.pem`` - A certificate with an RSA PSS signature.
+* ``root-ed448.pem`` - An ``ed448`` self-signed CA certificate
+ using ``ed448-pkcs8.pem`` as key.
Custom X.509 Request Vectors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -244,7 +427,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
@@ -253,9 +436,13 @@ 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.
+* ``challenge.pem`` - A certificate signing request for an RSA 2048 bit key
+ containing a challenge password.
Custom X.509 Certificate Revocation List Vectors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -272,6 +459,137 @@ Custom X.509 Certificate Revocation List Vectors
to "1.2.3.4". The CRL uses an unsupported MD2 signature algorithm.
* ``crl_unsupported_reason.pem`` - Contains a CRL with one revocation which has
an unsupported reason code.
+* ``crl_inval_cert_issuer_entry_ext.pem`` - Contains a CRL with one revocation
+ which has one entry extension for certificate issuer with an empty value.
+* ``crl_empty.pem`` - Contains a CRL with no revoked certificates.
+* ``crl_ian_aia_aki.pem`` - Contains a CRL with ``IssuerAlternativeName``,
+ ``AuthorityInformationAccess``, ``AuthorityKeyIdentifier`` and ``CRLNumber``
+ extensions.
+* ``valid_signature.pem`` - Contains a CRL with the public key which was used
+ to generate it.
+* ``invalid_signature.pem`` - Contains a CRL with the last signature byte
+ incremented by 1 to produce an invalid signature, and the public key which
+ was used to generate it.
+* ``crl_delta_crl_indicator.pem`` - Contains a CRL with the
+ ``DeltaCRLIndicator`` extension.
+* ``crl_idp_fullname_only.pem`` - Contains a CRL with an
+ ``IssuingDistributionPoints`` extension with only a ``fullname`` for the
+ distribution point.
+* ``crl_idp_only_ca.pem`` - Contains a CRL with an
+ ``IssuingDistributionPoints`` extension that is only valid for CA certificate
+ revocation.
+* ``crl_idp_fullname_only_aa.pem`` - Contains a CRL with an
+ ``IssuingDistributionPoints`` extension that sets a ``fullname`` and is only
+ valid for attribute certificate revocation.
+* ``crl_idp_fullname_only_user.pem`` - Contains a CRL with an
+ ``IssuingDistributionPoints`` extension that sets a ``fullname`` and is only
+ valid for user certificate revocation.
+* ``crl_idp_fullname_indirect_crl.pem`` - Contains a CRL with an
+ ``IssuingDistributionPoints`` extension that sets a ``fullname`` and the
+ indirect CRL flag.
+* ``crl_idp_reasons_only.pem`` - Contains a CRL with an
+ ``IssuingDistributionPoints`` extension that is only valid for revocations
+ with the ``keyCompromise`` reason.
+* ``crl_idp_relative_user_all_reasons.pem`` - Contains a CRL with an
+ ``IssuingDistributionPoints`` extension that sets all revocation reasons as
+ allowed.
+* ``crl_idp_relativename_only.pem`` - Contains a CRL with an
+ ``IssuingDistributionPoints`` extension with only a ``relativename`` for
+ the distribution point.
+
+X.509 OCSP Test Vectors
+~~~~~~~~~~~~~~~~~~~~~~~
+* ``x509/ocsp/resp-sha256.der`` - An OCSP response for ``cryptography.io`` with
+ a SHA256 signature.
+* ``x509/ocsp/resp-unauthorized.der`` - An OCSP response with an unauthorized
+ status.
+* ``x509/ocsp/resp-revoked.der`` - An OCSP response for ``revoked.badssl.com``
+ with a revoked status.
+* ``x509/ocsp/resp-delegate-unknown-cert.der`` - An OCSP response for an
+ unknown cert from ``AC Camerafirma``. This response also contains a delegate
+ certificate.
+* ``x509/ocsp/resp-responder-key-hash.der`` - An OCSP response from the
+ ``DigiCert`` OCSP responder that uses a key hash for the responder ID.
+* ``x509/ocsp/resp-revoked-reason.der`` - An OCSP response from the
+ ``QuoVadis`` OCSP responder that contains a revoked certificate with a
+ revocation reason.
+* ``x509/ocsp/resp-revoked-no-next-update.der`` - An OCSP response that
+ contains a revoked certificate and no ``nextUpdate`` value.
+* ``x509/ocsp/resp-invalid-signature-oid.der`` - An OCSP response that was
+ modified to contain an MD2 signature algorithm object identifier.
+* ``x509/ocsp/resp-single-extension-reason.der`` - An OCSP response that
+ contains a ``CRLReason`` single extension.
+* ``x509/ocsp/resp-sct-extension.der`` - An OCSP response containing a
+ ``CT Certificate SCTs`` single extension, from the SwissSign OCSP responder.
+
+Custom X.509 OCSP Test Vectors
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+* ``x509/ocsp/req-sha1.der`` - An OCSP request containing a single request and
+ using SHA1 as the hash algorithm.
+* ``x509/ocsp/req-multi-sha1.der`` - An OCSP request containing multiple
+ requests.
+* ``x509/ocsp/req-invalid-hash-alg.der`` - An OCSP request containing an
+ invalid hash algorithm OID.
+* ``x509/ocsp/req-ext-nonce.der`` - An OCSP request containing a nonce
+ extension.
+
+Custom PKCS12 Test Vectors
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+* ``pkcs12/cert-key-aes256cbc.p12`` - A PKCS12 file containing a cert
+ (``x509/custom/ca/ca.pem``) and key (``x509/custom/ca/ca_key.pem``)
+ both encrypted with AES 256 CBC with the password ``cryptography``.
+* ``pkcs12/cert-none-key-none.p12`` - A PKCS12 file containing a cert
+ (``x509/custom/ca/ca.pem``) and key (``x509/custom/ca/ca_key.pem``)
+ with no encryption. The password (used for integrity checking only) is
+ ``cryptography``.
+* ``pkcs12/cert-rc2-key-3des.p12`` - A PKCS12 file containing a cert
+ (``x509/custom/ca/ca.pem``) encrypted with RC2 and key
+ (``x509/custom/ca/ca_key.pem``) encrypted via 3DES with the password
+ ``cryptography``.
+* ``pkcs12/no-password.p12`` - A PKCS12 file containing a cert
+ (``x509/custom/ca/ca.pem``) and key (``x509/custom/ca/ca_key.pem``) with no
+ encryption and no password.
+* ``pkcs12/no-cert-key-aes256cbc.p12`` - A PKCS12 file containing a key
+ (``x509/custom/ca/ca_key.pem``) encrypted via AES 256 CBC with the
+ password ``cryptography`` and no certificate.
+* ``pkcs12/cert-aes256cbc-no-key.p12`` - A PKCS12 file containing a cert
+ (``x509/custom/ca/ca.pem``) encrypted via AES 256 CBC with the
+ password ``cryptography`` and no private key.
+
+Custom OpenSSH Test Vectors
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Generated by
+``asymmetric/OpenSSH/gen.sh``
+using command-line tools from OpenSSH_7.6p1 package.
+
+* ``dsa-nopsw.key``, ``dsa-nopsw.key.pub``, ``dsa-nopsw.key-cert.pub`` -
+ DSA-1024 private key; and corresponding public key in plain format
+ and with self-signed certificate.
+* ``dsa-psw.key``, ``dsa-psw.key.pub`` -
+ Password-protected DSA-1024 private key and corresponding public key.
+ Password is "password".
+* ``ecdsa-nopsw.key``, ``ecdsa-nopsw.key.pub``,
+ ``ecdsa-nopsw.key-cert.pub`` -
+ SECP256R1 private key; and corresponding public key in plain format
+ and with self-signed certificate.
+* ``ecdsa-psw.key``, ``ecdsa-psw.key.pub`` -
+ Password-protected SECP384R1 private key and corresponding public key.
+ Password is "password".
+* ``ed25519-nopsw.key``, ``ed25519-nopsw.key.pub``,
+ ``ed25519-nopsw.key-cert.pub`` -
+ Ed25519 private key; and corresponding public key in plain format
+ and with self-signed certificate.
+* ``ed25519-psw.key``, ``ed25519-psw.key.pub`` -
+ Password-protected Ed25519 private key and corresponding public key.
+ Password is "password".
+* ``rsa-nopsw.key``, ``rsa-nopsw.key.pub``,
+ ``rsa-nopsw.key-cert.pub`` -
+ RSA-2048 private key; and corresponding public key in plain format
+ and with self-signed certificate.
+* ``rsa-psw.key``, ``rsa-psw.key.pub`` -
+ Password-protected RSA-2048 private key and corresponding public key.
+ Password is "password".
Hashes
~~~~~~
@@ -279,8 +597,10 @@ Hashes
* MD5 from :rfc:`1321`.
* RIPEMD160 from the `RIPEMD website`_.
* SHA1 from `NIST CAVP`_.
-* SHA2 (224, 256, 384, 512) from `NIST CAVP`_.
-* Whirlpool from the `Whirlpool website`_.
+* SHA2 (224, 256, 384, 512, 512/224, 512/256) from `NIST CAVP`_.
+* SHA3 (224, 256, 384, 512) from `NIST CAVP`_.
+* SHAKE (128, 256) from `NIST CAVP`_.
+* Blake2s and Blake2b from OpenSSL `test/evptests.txt`_.
HMAC
~~~~
@@ -296,11 +616,15 @@ Key derivation functions
* HKDF (SHA1, SHA256) from :rfc:`5869`.
* 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
~~~~~~~~~~~~
* AES key wrap (AESKW) and 3DES key wrap test vectors from `NIST CAVP`_.
+* AES key wrap with padding vectors from `Botan's key wrap vectors`_.
Recipes
~~~~~~~
@@ -310,16 +634,21 @@ Recipes
Symmetric ciphers
~~~~~~~~~~~~~~~~~
-* AES (CBC, CFB, ECB, GCM, OFB) from `NIST CAVP`_.
+* AES (CBC, CFB, ECB, GCM, OFB, CCM) from `NIST CAVP`_.
* AES CTR from :rfc:`3686`.
* 3DES (CBC, CFB, ECB, OFB) from `NIST CAVP`_.
-* ARC4 from :rfc:`6229`.
+* ARC4 (KEY-LENGTH: 40, 56, 64, 80, 128, 192, 256) from :rfc:`6229`.
+* ARC4 (KEY-LENGTH: 160) generated by this project.
+ See: :doc:`/development/custom-vectors/arc4`
* Blowfish (CBC, CFB, ECB, OFB) from `Bruce Schneier's vectors`_.
* Camellia (ECB) from NTT's `Camellia page`_ as linked by `CRYPTREC`_.
* Camellia (CBC, CFB, OFB) from `OpenSSL's test vectors`_.
* CAST5 (ECB) from :rfc:`2144`.
* CAST5 (CBC, CFB, OFB) generated by this project.
See: :doc:`/development/custom-vectors/cast5`
+* ChaCha20 from :rfc:`7539`.
+* ChaCha20Poly1305 from :rfc:`7539`, `OpenSSL's evpciph.txt`_, and the
+ `BoringSSL ChaCha20Poly1305 tests`_.
* IDEA (ECB) from the `NESSIE IDEA vectors`_ created by `NESSIE`_.
* IDEA (CBC, CFB, OFB) generated by this project.
See: :doc:`/development/custom-vectors/idea`
@@ -340,21 +669,29 @@ CMAC
* AES-128, AES-192, AES-256, 3DES from `NIST SP-800-38B`_
+Poly1305
+~~~~~~~~
+
+* Test vectors from :rfc:`7539`.
+
Creating test vectors
---------------------
When official vectors are unavailable ``cryptography`` may choose to build
its own using existing vectors as source material.
-Custom Symmetric Vectors
-~~~~~~~~~~~~~~~~~~~~~~~~
+Created Vectors
+~~~~~~~~~~~~~~~
.. toctree::
:maxdepth: 1
+ custom-vectors/arc4
custom-vectors/cast5
custom-vectors/idea
custom-vectors/seed
+ custom-vectors/hkdf
+
If official test vectors appear in the future the custom generated vectors
should be discarded.
@@ -369,18 +706,21 @@ header format (substituting the correct information):
# Verified against the CommonCrypto and Go crypto packages
# Key Length : 128
-.. _`NIST`: http://www.nist.gov/
+.. _`NIST`: https://www.nist.gov/
.. _`IETF`: https://www.ietf.org/
-.. _`NIST CAVP`: http://csrc.nist.gov/groups/STM/cavp/
+.. _`Project Wycheproof`: https://github.com/google/wycheproof
+.. _`NIST CAVP`: https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program
.. _`Bruce Schneier's vectors`: https://www.schneier.com/code/vectors.txt
-.. _`Camellia page`: http://info.isl.ntt.co.jp/crypt/eng/camellia/
-.. _`CRYPTREC`: http://www.cryptrec.go.jp
+.. _`Camellia page`: https://info.isl.ntt.co.jp/crypt/eng/camellia/
+.. _`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
+.. _`OpenSSL's evpciph.txt`: https://github.com/openssl/openssl/blob/5a7bc0be97dee9ac715897fe8180a08e211bc6ea/test/evpciph.txt#L2362
+.. _`BoringSSL ChaCha20Poly1305 tests`: https://boringssl.googlesource.com/boringssl/+/2e2a226ac9201ac411a84b5e79ac3a7333d8e1c9/crypto/cipher_extra/test/chacha20_poly1305_tests.txt
+.. _`BoringSSL evp tests`: https://boringssl.googlesource.com/boringssl/+/ce3773f9fe25c3b54390bc51d72572f251c7d7e6/crypto/evp/evp_tests.txt
+.. _`RIPEMD website`: https://homes.esat.kuleuven.be/~bosselae/ripemd160.html
.. _`draft RFC`: https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01
.. _`Specification repository`: https://github.com/fernet/spec
-.. _`errata`: http://www.rfc-editor.org/errata_search.php?rfc=6238
+.. _`errata`: https://www.rfc-editor.org/errata_search.php?rfc=6238
.. _`OpenSSL example key`: https://github.com/openssl/openssl/blob/d02b48c63a58ea4367a0e905979f140b7d090f86/test/testrsa.pem
.. _`GnuTLS key parsing tests`: https://gitlab.com/gnutls/gnutls/commit/f16ef39ef0303b02d7fa590a37820440c466ce8d
.. _`enc-rsa-pkcs8.pem`: https://gitlab.com/gnutls/gnutls/blob/f8d943b38bf74eaaa11d396112daf43cb8aa82ae/tests/pkcs8-decode/encpkcs8.pem
@@ -391,10 +731,20 @@ header format (substituting the correct information):
.. _`GnuTLS example keys`: https://gitlab.com/gnutls/gnutls/commit/ad2061deafdd7db78fd405f9d143b0a7c579da7b
.. _`NESSIE IDEA vectors`: https://www.cosic.esat.kuleuven.be/nessie/testvectors/bc/idea/Idea-128-64.verified.test-vectors
.. _`NESSIE`: https://en.wikipedia.org/wiki/NESSIE
-.. _`Ed25519 website`: http://ed25519.cr.yp.to/software.html
-.. _`NIST SP-800-38B`: http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
-.. _`NIST PKI Testing`: http://csrc.nist.gov/groups/ST/crypto_apps_infra/pki/pkitesting.html
+.. _`Ed25519 website`: https://ed25519.cr.yp.to/software.html
+.. _`NIST SP-800-38B`: https://csrc.nist.gov/publications/detail/sp/800-38b/archive/2005-05-01
+.. _`NIST PKI Testing`: https://csrc.nist.gov/Projects/PKI-Testing
.. _`testx509.pem`: https://github.com/openssl/openssl/blob/master/test/testx509.pem
.. _`DigiCert Global Root G3`: http://cacerts.digicert.com/DigiCertGlobalRootG3.crt
.. _`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`: https://e-trust.gosuslugi.ru/MainCA
+.. _`test/evptests.txt`: https://github.com/openssl/openssl/blob/2d0b44126763f989a4cbffbffe9d0c7518158bb7/test/evptests.txt
+.. _`unknown signature OID`: https://bugzilla.mozilla.org/show_bug.cgi?id=405966
+.. _`botan`: https://github.com/randombit/botan/blob/57789bdfc55061002b2727d0b32587612829a37c/src/tests/data/pubkey/dh.vec
+.. _`DHKE`: https://sandilands.info/sgordon/diffie-hellman-secret-key-exchange-with-openssl
+.. _`Botan's key wrap vectors`: https://github.com/randombit/botan/blob/737f33c09a18500e044dca3e2ae13bd2c08bafdd/src/tests/data/keywrap/nist_key_wrap.vec
+.. _`root-ed25519.pem`: https://github.com/openssl/openssl/blob/2a1e2fe145c6eb8e75aa2e1b3a8c3a49384b2852/test/certs/root-ed25519.pem
+.. _`server-ed25519-cert.pem`: https://github.com/openssl/openssl/blob/2a1e2fe145c6eb8e75aa2e1b3a8c3a49384b2852/test/certs/server-ed25519-cert.pem
+.. _`server-ed448-cert.pem`: https://github.com/openssl/openssl/blob/2a1e2fe145c6eb8e75aa2e1b3a8c3a49384b2852/test/certs/server-ed448-cert.pem
diff --git a/docs/doing-a-release.rst b/docs/doing-a-release.rst
index 283b98b6..043d52d2 100644
--- a/docs/doing-a-release.rst
+++ b/docs/doing-a-release.rst
@@ -3,12 +3,33 @@ Doing a release
Doing a release of ``cryptography`` requires a few steps.
+Security Releases
+-----------------
+
+In addition to the other steps described below, for a release which fixes a
+security vulnerability, you should also include the following steps:
+
+* Request a `CVE from MITRE`_. Once you have received the CVE, it should be
+ included in the :doc:`changelog`. Ideally you should request the CVE before
+ starting the release process so that the CVE is available at the time of the
+ release.
+* Ensure that the :doc:`changelog` entry credits whoever reported the issue.
+* The release should be announced on the `oss-security`_ mailing list, in
+ addition to the regular announcement lists.
+
Verifying OpenSSL version
-------------------------
-The release process uses a static build for Windows wheels. Check that the
-Windows Jenkins builders have the latest version of OpenSSL installed
-before performing the release.
+The release process creates wheels bundling OpenSSL for Windows, macOS, and
+Linux. Check that the Windows, macOS, and Linux builders (both
+``pyca/cryptography-manylinux1`` and ``pyca/cryptography-manylinux2010``) have
+the latest OpenSSL. If anything is out of date follow the instructions for
+upgrading OpenSSL.
+
+Upgrading OpenSSL
+-----------------
+
+Use the `upgrading OpenSSL issue template`_.
Bumping the version number
--------------------------
@@ -30,7 +51,7 @@ The commit that merged the version number bump is now the official release
commit for this release. You will need to have ``gpg`` installed and a ``gpg``
key in order to do a release. Once this has happened:
-* Run ``invoke release {version}``.
+* Run ``python release.py {version}``.
The release should now be available on PyPI and a tag should be available in
the repository.
@@ -59,8 +80,9 @@ Post-release tasks
------------------
* Update the version number to the next major (e.g. ``0.5.dev1``) in
- ``cryptography/__about__.py`` and
+ ``src/cryptography/__about__.py`` and
``vectors/cryptography_vectors/__about__.py``.
+* Close the `milestone`_ for the previous release on GitHub.
* Add new :doc:`/changelog` entry with next version and note that it is under
active development
* Send a pull request with these items
@@ -70,5 +92,9 @@ Post-release tasks
* Send an email to the `mailing list`_ and `python-announce`_ announcing the
release.
+.. _`CVE from MITRE`: https://cveform.mitre.org/
+.. _`oss-security`: https://www.openwall.com/lists/oss-security/
+.. _`upgrading OpenSSL issue template`: https://github.com/pyca/cryptography/issues/new?template=openssl-release.md
+.. _`milestone`: https://github.com/pyca/cryptography/milestones
.. _`mailing list`: https://mail.python.org/mailman/listinfo/cryptography-dev
.. _`python-announce`: https://mail.python.org/mailman/listinfo/python-announce-list
diff --git a/docs/faq.rst b/docs/faq.rst
index 0b7bdce4..38a895d8 100644
--- a/docs/faq.rst
+++ b/docs/faq.rst
@@ -1,6 +1,16 @@
Frequently asked questions
==========================
+``cryptography`` failed to install!
+-----------------------------------
+
+If you are having issues installing ``cryptography`` the first troubleshooting
+step is to upgrade ``pip`` and then try to install again. For most users this will
+take the form of ``pip install -U pip``, but on Windows you should do
+``python -m pip install -U pip``. If you are still seeing errors after upgrading
+and trying ``pip install cryptography`` again, please see the :doc:`/installation`
+documentation.
+
How does ``cryptography`` compare to NaCl (Networking and Cryptography Library)?
--------------------------------------------------------------------------------
@@ -12,7 +22,128 @@ features a collection of hand selected algorithms.
``cryptography``'s :ref:`recipes <cryptography-layout>` layer has similar goals
to NaCl.
-If you prefer NaCl's design, we highly recommend `PyNaCl`_.
+If you prefer NaCl's design, we highly recommend `PyNaCl`_, which is also
+maintained by the PyCA team.
+
+Why use ``cryptography``?
+-------------------------
+
+If you've done cryptographic work in Python before you have likely encountered
+other libraries in Python such as *M2Crypto*, *PyCrypto*, or *PyOpenSSL*. In
+building ``cryptography`` we wanted to address a few issues we observed in the
+legacy libraries:
+
+* Extremely error prone APIs and insecure defaults.
+* Use of poor implementations of algorithms (i.e. ones with known side-channel
+ attacks).
+* Lack of maintenance.
+* Lack of high level APIs.
+* Lack of PyPy and Python 3 support.
+* Absence of algorithms such as
+ :class:`AES-GCM <cryptography.hazmat.primitives.ciphers.modes.GCM>` and
+ :class:`~cryptography.hazmat.primitives.kdf.hkdf.HKDF`.
+
+Compiling ``cryptography`` on macOS produces a ``fatal error: 'openssl/aes.h' file not found`` error
+----------------------------------------------------------------------------------------------------
+
+This happens because macOS 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.
+
+If you are using PyPy, we do not currently ship ``cryptography`` wheels for
+PyPy. You will need to install your own copy of OpenSSL -- we recommend using
+Homebrew.
+
+``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.
+
+error: ``-Werror=sign-conversion``: No option ``-Wsign-conversion`` during installation
+---------------------------------------------------------------------------------------
+
+The compiler you are using is too old and not supported by ``cryptography``.
+Please upgrade to a more recent version. If you are running OpenBSD 6.1 or
+earlier the default compiler is extremely old. Use ``pkg_add`` to install a
+newer ``gcc`` and then install ``cryptography`` using
+``CC=/path/to/newer/gcc pip install cryptography``.
+
+Installing ``cryptography`` fails with ``Invalid environment marker: python_version < '3'``
+-------------------------------------------------------------------------------------------
+
+Your ``pip`` and/or ``setuptools`` are outdated. Please upgrade to the latest
+versions with ``pip install -U pip setuptools`` (or on Windows
+``python -m pip install -U pip setuptools``).
+
+Installing cryptography with OpenSSL 0.9.8, 1.0.0, 1.0.1 fails
+--------------------------------------------------------------
+
+The OpenSSL project has dropped support for the 0.9.8, 1.0.0, and 1.0.1 release
+series. Since they are no longer receiving security patches from upstream,
+``cryptography`` is also dropping support for them. To fix this issue you
+should upgrade to a newer version of OpenSSL (1.0.2 or later). This may require
+you to upgrade to a newer operating system.
+
+Why are there no wheels for Python 3.6+ on Linux or macOS?
+----------------------------------------------------------
+
+Our Python3 wheels, for macOS and Linux, are ``abi3`` wheels. This means they
+support multiple versions of Python. The Python 3.5 ``abi3`` wheel can be used
+with any version of Python greater than or equal to 3.5. Recent versions of
+``pip`` will automatically install ``abi3`` wheels.
+
+``ImportError``: ``idna`` is not installed
+------------------------------------------
+
+``cryptography`` deprecated passing :term:`U-label` strings to various X.509
+constructors in version 2.1 and in version 2.5 moved the ``idna`` dependency
+to a ``setuptools`` extra. If you see this exception you should upgrade your
+software so that it no longer depends on this deprecated feature. If that is
+not yet possible you can also install ``cryptography`` with
+``pip install cryptography[idna]`` to automatically install the missing
+dependency. This workaround will be available until the feature is fully
+removed.
+
+Why can't I import my PEM file?
+-------------------------------
+
+PEM is a format (defined by several RFCs, but originally :rfc:`1421`) for
+encoding keys, certificates and others cryptographic data into a regular form.
+The data is encoded as base64 and wrapped with a header and footer.
+
+If you are having trouble importing PEM files, make sure your file fits
+the following rules:
+
+* has a one-line header like this: ``-----BEGIN [FILE TYPE]-----``
+ (where ``[FILE TYPE]`` is ``CERTIFICATE``, ``PUBLIC KEY``, ``PRIVATE KEY``,
+ etc.)
+
+* has a one-line footer like this: ``-----END [FILE TYPE]-----``
+
+* all lines, except for the final one, must consist of exactly 64
+ characters.
+
+For example, this is a PEM file for a RSA Public Key: ::
+
+ -----BEGIN PUBLIC KEY-----
+ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7CsKFSzq20NLb2VQDXma
+ 9DsDXtKADv0ziI5hT1KG6Bex5seE9pUoEcUxNv4uXo2jzAUgyRweRl/DLU8SoN8+
+ WWd6YWik4GZvNv7j0z28h9Q5jRySxy4dmElFtIRHGiKhqd1Z06z4AzrmKEzgxkOk
+ LJjY9cvwD+iXjpK2oJwNNyavvjb5YZq6V60RhpyNtKpMh2+zRLgIk9sROEPQeYfK
+ 22zj2CnGBMg5Gm2uPOsGDltl/I/Fdh1aO3X4i1GXwCuPf1kSAg6lPJD0batftkSG
+ v0X0heUaV0j1HSNlBWamT4IR9+iJfKJHekOqvHQBcaCu7Ja4kXzx6GZ3M2j/Ja3A
+ 2QIDAQAB
+ -----END PUBLIC KEY-----
+
-.. _`NaCl`: http://nacl.cr.yp.to/
-.. _`PyNaCl`: https://pynacl.readthedocs.org
+.. _`NaCl`: https://nacl.cr.yp.to/
+.. _`PyNaCl`: https://pynacl.readthedocs.io
+.. _`WSGIApplicationGroup`: https://modwsgi.readthedocs.io/en/develop/configuration-directives/WSGIApplicationGroup.html
+.. _`issue`: https://github.com/pyca/cryptography/issues
diff --git a/docs/fernet.rst b/docs/fernet.rst
index eacbc2ae..dd9d75bd 100644
--- a/docs/fernet.rst
+++ b/docs/fernet.rst
@@ -3,7 +3,7 @@ Fernet (symmetric encryption)
.. currentmodule:: cryptography.fernet
-Fernet provides guarantees that a message encrypted using it cannot be
+Fernet guarantees that a message encrypted using it cannot be
manipulated or read without the key. `Fernet`_ is an implementation of
symmetric (also known as "secret key") authenticated cryptography. Fernet also
has support for implementing key rotation via :class:`MultiFernet`.
@@ -19,13 +19,14 @@ has support for implementing key rotation via :class:`MultiFernet`.
>>> f = Fernet(key)
>>> token = f.encrypt(b"my deep dark secret")
>>> token
- '...'
+ b'...'
>>> f.decrypt(token)
- 'my deep dark secret'
+ b'my deep dark secret'
- :param bytes key: A URL-safe base64-encoded 32-byte key. This **must** be
- kept secret. Anyone with this key is able to create and
- read messages.
+ :param key: A URL-safe base64-encoded 32-byte key. This **must** be
+ kept secret. Anyone with this key is able to create and
+ read messages.
+ :type key: bytes or str
.. classmethod:: generate_key()
@@ -37,6 +38,9 @@ has support for implementing key rotation via :class:`MultiFernet`.
.. method:: encrypt(data)
+ Encrypts data passed. The result of this encryption is known as a
+ "Fernet token" and has strong privacy and authenticity guarantees.
+
:param bytes data: The message you would like to encrypt.
:returns bytes: A secure message that cannot be read or altered
without the key. It is URL-safe base64-encoded. This is
@@ -50,8 +54,35 @@ has support for implementing key rotation via :class:`MultiFernet`.
generated in *plaintext*, the time a message was created will
therefore be visible to a possible attacker.
+ .. method:: encrypt_at_time(data, current_time)
+
+ .. versionadded:: 3.0
+
+ Encrypts data passed using explicitly passed current time. See
+ :meth:`encrypt` for the documentation of the ``data`` parameter, the
+ return type and the exceptions raised.
+
+ The motivation behind this method is for the client code to be able to
+ test token expiration. Since this method can be used in an insecure
+ manner one should make sure the correct time (``int(time.time())``)
+ is passed as ``current_time`` outside testing.
+
+ :param int current_time: The current time.
+
+ .. note::
+
+ Similarly to :meth:`encrypt` the encrypted message contains the
+ timestamp in *plaintext*, in this case the timestamp is the value
+ of the ``current_time`` parameter.
+
+
.. method:: decrypt(token, ttl=None)
+ Decrypts a Fernet token. If successfully decrypted you will receive the
+ original plaintext as the result, otherwise an exception will be
+ raised. It is safe to use this data immediately as Fernet verifies
+ that the data has not been tampered with prior to returning it.
+
:param bytes token: The Fernet token. This is the result of calling
:meth:`encrypt`.
:param int ttl: Optionally, the number of seconds old a message may be
@@ -72,13 +103,47 @@ has support for implementing key rotation via :class:`MultiFernet`.
:raises TypeError: This exception is raised if ``token`` is not
``bytes``.
+ .. method:: decrypt_at_time(token, ttl, current_time)
+
+ .. versionadded:: 3.0
+
+ Decrypts a token using explicitly passed current time. See
+ :meth:`decrypt` for the documentation of the ``token`` and ``ttl``
+ parameters (``ttl`` is required here), the return type and the exceptions
+ raised.
+
+ The motivation behind this method is for the client code to be able to
+ test token expiration. Since this method can be used in an insecure
+ manner one should make sure the correct time (``int(time.time())``)
+ is passed as ``current_time`` outside testing.
+
+ :param int current_time: The current time.
+
+
+ .. method:: extract_timestamp(token)
+
+ .. versionadded:: 2.3
+
+ Returns the timestamp for the token. The caller can then decide if
+ the token is about to expire and, for example, issue a new token.
+
+ :param bytes token: The Fernet token. This is the result of calling
+ :meth:`encrypt`.
+ :returns int: The UNIX timestamp of the token.
+ :raises cryptography.fernet.InvalidToken: If the ``token``'s signature
+ is invalid this exception
+ is raised.
+ :raises TypeError: This exception is raised if ``token`` is not
+ ``bytes``.
+
.. class:: MultiFernet(fernets)
.. versionadded:: 0.7
This class implements key rotation for Fernet. It takes a ``list`` of
- :class:`Fernet` instances, and implements the same API:
+ :class:`Fernet` instances and implements the same API with the exception
+ of one additional method: :meth:`MultiFernet.rotate`:
.. doctest::
@@ -88,9 +153,9 @@ has support for implementing key rotation via :class:`MultiFernet`.
>>> f = MultiFernet([key1, key2])
>>> token = f.encrypt(b"Secret message!")
>>> token
- '...'
+ b'...'
>>> f.decrypt(token)
- 'Secret message!'
+ b'Secret message!'
MultiFernet performs all encryption options using the *first* key in the
``list`` provided. MultiFernet attempts to decrypt tokens with each key in
@@ -101,11 +166,96 @@ has support for implementing key rotation via :class:`MultiFernet`.
the front of the list to start encrypting new messages, and remove old keys
as they are no longer needed.
+ Token rotation as offered by :meth:`MultiFernet.rotate` is a best practice
+ and manner of cryptographic hygiene designed to limit damage in the event of
+ an undetected event and to increase the difficulty of attacks. For example,
+ if an employee who had access to your company's fernet keys leaves, you'll
+ want to generate new fernet key, rotate all of the tokens currently deployed
+ using that new key, and then retire the old fernet key(s) to which the
+ employee had access.
+
+ .. method:: rotate(msg)
+
+ .. versionadded:: 2.2
+
+ Rotates a token by re-encrypting it under the :class:`MultiFernet`
+ instance's primary key. This preserves the timestamp that was originally
+ saved with the token. If a token has successfully been rotated then the
+ rotated token will be returned. If rotation fails this will raise an
+ exception.
+
+ .. doctest::
+
+ >>> from cryptography.fernet import Fernet, MultiFernet
+ >>> key1 = Fernet(Fernet.generate_key())
+ >>> key2 = Fernet(Fernet.generate_key())
+ >>> f = MultiFernet([key1, key2])
+ >>> token = f.encrypt(b"Secret message!")
+ >>> token
+ b'...'
+ >>> f.decrypt(token)
+ b'Secret message!'
+ >>> key3 = Fernet(Fernet.generate_key())
+ >>> f2 = MultiFernet([key3, key1, key2])
+ >>> rotated = f2.rotate(token)
+ >>> f2.decrypt(rotated)
+ b'Secret message!'
+
+ :param bytes msg: The token to re-encrypt.
+ :returns bytes: A secure message that cannot be read or altered without
+ the key. This is URL-safe base64-encoded. This is referred to as a
+ "Fernet token".
+ :raises cryptography.fernet.InvalidToken: If a ``token`` is in any
+ way invalid this exception is raised.
+ :raises TypeError: This exception is raised if the ``msg`` is not
+ ``bytes``.
+
.. class:: InvalidToken
See :meth:`Fernet.decrypt` for more information.
+
+Using passwords with Fernet
+---------------------------
+
+It is possible to use passwords with Fernet. To do this, you need to run the
+password through a key derivation function such as
+:class:`~cryptography.hazmat.primitives.kdf.pbkdf2.PBKDF2HMAC`, bcrypt or
+:class:`~cryptography.hazmat.primitives.kdf.scrypt.Scrypt`.
+
+.. doctest::
+
+ >>> import base64
+ >>> import os
+ >>> from cryptography.fernet import Fernet
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
+ >>> password = b"password"
+ >>> salt = os.urandom(16)
+ >>> kdf = PBKDF2HMAC(
+ ... algorithm=hashes.SHA256(),
+ ... length=32,
+ ... salt=salt,
+ ... iterations=100000,
+ ... backend=default_backend()
+ ... )
+ >>> key = base64.urlsafe_b64encode(kdf.derive(password))
+ >>> f = Fernet(key)
+ >>> token = f.encrypt(b"Secret message!")
+ >>> token
+ b'...'
+ >>> f.decrypt(token)
+ b'Secret message!'
+
+In this scheme, the salt has to be stored in a retrievable location in order
+to derive the same key from the password in the future.
+
+The iteration count used should be adjusted to be as high as your server can
+tolerate. A good default is at least 100,000 iterations which is what Django
+recommended in 2014.
+
Implementation
--------------
@@ -122,6 +272,13 @@ Specifically it uses:
For complete details consult the `specification`_.
+Limitations
+-----------
+
+Fernet is ideal for encrypting data that easily fits in memory. As a design
+feature it does not expose unauthenticated bytes. Unfortunately, this makes it
+generally unsuitable for very large files at this time.
+
.. _`Fernet`: https://github.com/fernet/spec/
.. _`specification`: https://github.com/fernet/spec/blob/master/Spec.md
diff --git a/docs/glossary.rst b/docs/glossary.rst
index 202fa2de..95b893c8 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -72,3 +72,38 @@ Glossary
or pseudo-random number (see :doc:`Random number generation
</random-numbers>`). Since a nonce does not have to be unpredictable,
it can also take a form of a counter.
+
+ opaque key
+ An opaque key is a type of key that allows you to perform cryptographic
+ operations such as encryption, decryption, signing, and verification,
+ but does not allow access to the key itself. Typically an opaque key is
+ loaded from a `hardware security module`_ (HSM).
+
+ A-label
+ The ASCII compatible encoded (ACE) representation of an
+ internationalized (unicode) domain name. A-labels begin with the
+ prefix ``xn--``. To create an A-label from a unicode domain string use
+ a library like `idna`_.
+
+ bits
+ A bit is binary value -- a value that has only two possible states.
+ Typically binary values are represented visually as 0 or 1, but
+ remember that their actual value is not a printable character. A byte
+ on modern computers is 8 bits and represents 256 possible values. In
+ cryptographic applications when you see something say it requires a 128
+ bit key, you can calculate the number of bytes by dividing by 8. 128
+ divided by 8 is 16, so a 128 bit key is a 16 byte key.
+
+ bytes-like
+ A bytes-like object contains binary data and supports the
+ `buffer protocol`_. This includes ``bytes``, ``bytearray``, and
+ ``memoryview`` objects.
+
+ U-label
+ The presentational unicode form of an internationalized domain
+ name. U-labels use unicode characters outside the ASCII range and
+ are encoded as A-labels when stored in certificates.
+
+.. _`hardware security module`: https://en.wikipedia.org/wiki/Hardware_security_module
+.. _`idna`: https://pypi.org/project/idna/
+.. _`buffer protocol`: https://docs.python.org/3/c-api/buffer.html
diff --git a/docs/hazmat/backends/commoncrypto.rst b/docs/hazmat/backends/commoncrypto.rst
deleted file mode 100644
index ddaf97e5..00000000
--- a/docs/hazmat/backends/commoncrypto.rst
+++ /dev/null
@@ -1,30 +0,0 @@
-.. hazmat::
-
-CommonCrypto backend
-====================
-
-The `CommonCrypto`_ C library provided by Apple on OS X and iOS. The
-CommonCrypto backend is only supported on OS X versions 10.8 and above.
-
-.. currentmodule:: cryptography.hazmat.backends.commoncrypto.backend
-
-.. versionadded:: 0.2
-
-.. data:: cryptography.hazmat.backends.commoncrypto.backend
-
- This is the exposed API for the CommonCrypto backend.
-
- It implements the following interfaces:
-
- * :class:`~cryptography.hazmat.backends.interfaces.CipherBackend`
- * :class:`~cryptography.hazmat.backends.interfaces.HashBackend`
- * :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
- * :class:`~cryptography.hazmat.backends.interfaces.PBKDF2HMACBackend`
-
- It has one additional public attribute.
-
- .. attribute:: name
-
- The string name of this backend: ``"commoncrypto"``
-
-.. _`CommonCrypto`: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/Common%20Crypto.3cc.html
diff --git a/docs/hazmat/backends/index.rst b/docs/hazmat/backends/index.rst
index aec7a1e0..a8a1ff30 100644
--- a/docs/hazmat/backends/index.rst
+++ b/docs/hazmat/backends/index.rst
@@ -8,15 +8,11 @@ Getting a backend
.. currentmodule:: cryptography.hazmat.backends
-``cryptography`` aims to support multiple backends to ensure it can provide
-the widest number of supported cryptographic algorithms as well as supporting
-platform specific implementations.
+``cryptography`` was originally designed to support multiple backends, but
+this design has been deprecated.
You can get the default backend by calling :func:`~default_backend`.
-The default backend will change over time as we implement new backends and
-the libraries we use in those backends changes.
-
.. function:: default_backend()
@@ -31,6 +27,4 @@ Individual backends
:maxdepth: 1
openssl
- commoncrypto
- multibackend
interfaces
diff --git a/docs/hazmat/backends/interfaces.rst b/docs/hazmat/backends/interfaces.rst
index fb3786c3..36dd3a7a 100644
--- a/docs/hazmat/backends/interfaces.rst
+++ b/docs/hazmat/backends/interfaces.rst
@@ -22,18 +22,17 @@ A specific ``backend`` may provide one or more of these interfaces.
The following backends implement this interface:
* :doc:`/hazmat/backends/openssl`
- * :doc:`/hazmat/backends/commoncrypto`
.. method:: cipher_supported(cipher, mode)
Check if a ``cipher`` and ``mode`` combination is supported by
this backend.
- :param cipher: An instance of a
- :class:`~cryptography.hazmat.primitives.ciphers.CipherAlgorithm`
- provider.
- :param mode: An instance of a
- :class:`~cryptography.hazmat.primitives.ciphers.modes.Mode` provider.
+ :param cipher: An instance of
+ :class:`~cryptography.hazmat.primitives.ciphers.CipherAlgorithm`.
+
+ :param mode: An instance of
+ :class:`~cryptography.hazmat.primitives.ciphers.modes.Mode`.
:returns: ``True`` if the specified ``cipher`` and ``mode`` combination
is supported by this backend, otherwise ``False``
@@ -46,11 +45,11 @@ A specific ``backend`` may provide one or more of these interfaces.
can be used for encrypting data with the symmetric ``cipher`` using
the given ``mode``.
- :param cipher: An instance of a
- :class:`~cryptography.hazmat.primitives.ciphers.CipherAlgorithm`
- provider.
- :param mode: An instance of a
- :class:`~cryptography.hazmat.primitives.ciphers.modes.Mode` provider.
+ :param cipher: An instance of
+ :class:`~cryptography.hazmat.primitives.ciphers.CipherAlgorithm`.
+
+ :param mode: An instance of
+ :class:`~cryptography.hazmat.primitives.ciphers.modes.Mode`.
:returns:
:class:`~cryptography.hazmat.primitives.ciphers.CipherContext`
@@ -65,11 +64,11 @@ A specific ``backend`` may provide one or more of these interfaces.
can be used for decrypting data with the symmetric ``cipher`` using
the given ``mode``.
- :param cipher: An instance of a
- :class:`~cryptography.hazmat.primitives.ciphers.CipherAlgorithm`
- provider.
- :param mode: An instance of a
- :class:`~cryptography.hazmat.primitives.ciphers.modes.Mode` provider.
+ :param cipher: An instance of
+ :class:`~cryptography.hazmat.primitives.ciphers.CipherAlgorithm`.
+
+ :param mode: An instance of
+ :class:`~cryptography.hazmat.primitives.ciphers.modes.Mode`.
:returns:
:class:`~cryptography.hazmat.primitives.ciphers.CipherContext`
@@ -84,15 +83,13 @@ A specific ``backend`` may provide one or more of these interfaces.
The following backends implement this interface:
* :doc:`/hazmat/backends/openssl`
- * :doc:`/hazmat/backends/commoncrypto`
.. method:: hash_supported(algorithm)
Check if the specified ``algorithm`` is supported by this backend.
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- provider.
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
:returns: ``True`` if the specified ``algorithm`` is supported by this
backend, otherwise ``False``.
@@ -104,9 +101,8 @@ A specific ``backend`` may provide one or more of these interfaces.
:class:`~cryptography.hazmat.primitives.hashes.HashContext` that
uses the specified ``algorithm`` to calculate a message digest.
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- provider.
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
:returns:
:class:`~cryptography.hazmat.primitives.hashes.HashContext`
@@ -120,29 +116,28 @@ A specific ``backend`` may provide one or more of these interfaces.
The following backends implement this interface:
* :doc:`/hazmat/backends/openssl`
- * :doc:`/hazmat/backends/commoncrypto`
.. method:: hmac_supported(algorithm)
Check if the specified ``algorithm`` is supported by this backend.
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- provider.
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
:returns: ``True`` if the specified ``algorithm`` is supported for HMAC
by this backend, otherwise ``False``.
- .. method:: create_hmac_ctx(algorithm)
+ .. method:: create_hmac_ctx(key, algorithm)
Create a
:class:`~cryptography.hazmat.primitives.hashes.HashContext` that
uses the specified ``algorithm`` to calculate a hash-based message
authentication code.
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- provider.
+ :param bytes key: Secret key as ``bytes``.
+
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
:returns:
:class:`~cryptography.hazmat.primitives.hashes.HashContext`
@@ -156,23 +151,21 @@ A specific ``backend`` may provide one or more of these interfaces.
.. method:: cmac_algorithm_supported(algorithm)
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.ciphers.BlockCipherAlgorithm`
- provider.
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.ciphers.BlockCipherAlgorithm`.
+
:return: Returns True if the block cipher is supported for CMAC by this backend
.. method:: create_cmac_ctx(algorithm)
Create a
- :class:`~cryptography.hazmat.primitives.interfaces.MACContext` that
+ context that
uses the specified ``algorithm`` to calculate a message authentication code.
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.ciphers.BlockCipherAlgorithm`
- provider.
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.ciphers.BlockCipherAlgorithm`.
- :returns:
- :class:`~cryptography.hazmat.primitives.interfaces.MACContext`
+ :returns: CMAC object.
.. class:: PBKDF2HMACBackend
@@ -184,24 +177,21 @@ A specific ``backend`` may provide one or more of these interfaces.
The following backends implement this interface:
* :doc:`/hazmat/backends/openssl`
- * :doc:`/hazmat/backends/commoncrypto`
.. method:: pbkdf2_hmac_supported(algorithm)
Check if the specified ``algorithm`` is supported by this backend.
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- provider.
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
:returns: ``True`` if the specified ``algorithm`` is supported for
PBKDF2 HMAC by this backend, otherwise ``False``.
.. method:: derive_pbkdf2_hmac(self, algorithm, length, salt, iterations, key_material)
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- provider.
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
:param int length: The desired length of the derived key. Maximum is
(2\ :sup:`32` - 1) * ``algorithm.digest_size``
@@ -233,9 +223,8 @@ A specific ``backend`` may provide one or more of these interfaces.
:param int key_size: The length in bits of the modulus. Should be
at least 2048.
- :return: A new instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`
- provider.
+ :return: A new instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`.
:raises ValueError: If the public_exponent is not valid.
@@ -243,9 +232,8 @@ A specific ``backend`` may provide one or more of these interfaces.
Check if the specified ``padding`` is supported by the backend.
- :param padding: An instance of an
- :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`
- provider.
+ :param padding: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`.
:returns: ``True`` if the specified ``padding`` is supported by this
backend, otherwise ``False``.
@@ -264,7 +252,7 @@ A specific ``backend`` may provide one or more of these interfaces.
:param numbers: An instance of
:class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateNumbers`.
- :returns: A provider of
+ :returns: An instance of
:class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`.
:raises ValueError: This is raised when the values of ``p``, ``q``,
@@ -277,9 +265,9 @@ A specific ``backend`` may provide one or more of these interfaces.
.. method:: load_rsa_public_numbers(numbers)
:param numbers: An instance of
- :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateNumbers`.
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicNumbers`.
- :returns: A provider of
+ :returns: An instance of
:class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`.
:raises ValueError: This is raised when the values of
@@ -305,24 +293,19 @@ A specific ``backend`` may provide one or more of these interfaces.
support for larger key sizes specified in FIPS 186-3 and are still
restricted to only the 1024-bit keys specified in FIPS 186-2.
- :return: A new instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAParameters`
- provider.
+ :return: A new instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAParameters`.
.. method:: generate_dsa_private_key(parameters)
- :param parameters: A
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAParameters`
- provider.
+ :param parameters: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAParameters`.
- :return: A new instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`
- provider.
+ :return: A new instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`.
:raises ValueError: This is raised if the key size is not one of 1024,
- 2048, or 3072. It is also raised when OpenSSL is older than version
- 1.0.0 and the key size is larger than 1024; older OpenSSL versions
- do not support keys larger than 1024 bits.
+ 2048, or 3072.
.. method:: generate_dsa_private_key_and_parameters(key_size)
@@ -333,18 +316,16 @@ A specific ``backend`` may provide one or more of these interfaces.
support for larger key sizes specified in FIPS 186-3 and are still
restricted to only the 1024-bit keys specified in FIPS 186-2.
- :return: A new instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`
- provider.
+ :return: A new instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`.
:raises ValueError: This is raised if the key size is not supported
by the backend.
.. method:: dsa_hash_supported(algorithm)
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- provider.
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
:returns: ``True`` if the specified ``algorithm`` is supported by this
backend, otherwise ``False``.
@@ -365,7 +346,7 @@ A specific ``backend`` may provide one or more of these interfaces.
:param numbers: An instance of
:class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAParameterNumbers`.
- :returns: A provider of
+ :returns: An instance of
:class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAParameters`.
:raises cryptography.exceptions.UnsupportedAlgorithm: This is raised
@@ -376,7 +357,7 @@ A specific ``backend`` may provide one or more of these interfaces.
:param numbers: An instance of
:class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateNumbers`.
- :returns: A provider of
+ :returns: An instance of
:class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`.
:raises cryptography.exceptions.UnsupportedAlgorithm: This is raised
@@ -387,7 +368,7 @@ A specific ``backend`` may provide one or more of these interfaces.
:param numbers: An instance of
:class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicNumbers`.
- :returns: A provider of
+ :returns: An instance of
:class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`.
:raises cryptography.exceptions.UnsupportedAlgorithm: This is raised
@@ -400,49 +381,51 @@ A specific ``backend`` may provide one or more of these interfaces.
.. method:: elliptic_curve_supported(curve)
- :param curve: An instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurve`
- provider.
+ :param curve: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurve`.
:returns: True if the elliptic curve is supported by this backend.
.. method:: elliptic_curve_signature_algorithm_supported(signature_algorithm, curve)
- :param signature_algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurveSignatureAlgorithm`
- provider.
+ :param signature_algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurveSignatureAlgorithm`.
- :param curve: An instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurve`
- provider.
+ :param curve: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurve`.
:returns: True if the signature algorithm and curve are supported by this backend.
.. method:: generate_elliptic_curve_private_key(curve)
- :param curve: An instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurve`
- provider.
+ :param curve: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurve`.
.. method:: load_elliptic_curve_private_numbers(numbers)
- :param numbers: An instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateNumbers`
- provider.
+ :param numbers: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateNumbers`.
- :returns: An instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`
- provider.
+ :returns: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`.
.. method:: load_elliptic_curve_public_numbers(numbers)
- :param numbers: An instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicNumbers`
- provider.
+ :param numbers: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicNumbers`.
+
+ :returns: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`.
+
+ .. method:: derive_elliptic_curve_private_key(private_value, curve)
- :returns: An instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`
- provider.
+ :param private_value: A secret scalar value.
+
+ :param curve: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurve`.
+
+ :returns: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`.
.. class:: PEMSerializationBackend
@@ -468,6 +451,15 @@ A specific ``backend`` may provide one or more of these interfaces.
serialized data contains.
:raises ValueError: If the data could not be deserialized.
+ .. method:: load_pem_parameters(data)
+
+ .. versionadded:: 2.0
+
+ :param bytes data: PEM data to load.
+ :return: A new instance of the appropriate type of asymmetric
+ parameters the serialized data contains.
+ :raises ValueError: If the data could not be deserialized.
+
.. class:: DERSerializationBackend
.. versionadded:: 0.8
@@ -492,6 +484,16 @@ A specific ``backend`` may provide one or more of these interfaces.
serialized data contains.
:raises ValueError: If the data could not be deserialized.
+ .. method:: load_der_parameters(data)
+
+ .. versionadded:: 2.0
+
+ :param bytes data: DER data to load.
+ :return: A new instance of the appropriate type of asymmetric
+ parameters the serialized data contains.
+ :raises ValueError: If the data could not be deserialized.
+
+
.. class:: X509Backend
.. versionadded:: 0.7
@@ -547,9 +549,64 @@ A specific ``backend`` may provide one or more of these interfaces.
:class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
that will be used to generate the request signature.
- :returns: A new object with the
- :class:`~cryptography.x509.CertificateSigningRequest` interface.
+ :returns: A new instance of
+ :class:`~cryptography.x509.CertificateSigningRequest`.
+
+ .. method:: create_x509_certificate(builder, private_key, algorithm)
+
+ .. versionadded:: 1.0
+
+ :param builder: An instance of
+ :class:`~cryptography.x509.CertificateBuilder`.
+
+ :param private_key: The
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`
+ that will be used to sign the certificate.
+
+ :param algorithm: The
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+ that will be used to generate the certificate signature.
+
+ :returns: A new instance of :class:`~cryptography.x509.Certificate`.
+
+ .. method:: create_x509_crl(builder, private_key, algorithm)
+ .. versionadded:: 1.2
+
+ :param builder: An instance of
+ :class:`~cryptography.x509.CertificateRevocationListBuilder`.
+
+ :param private_key: The
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`
+ that will be used to sign the CRL.
+
+ :param algorithm: The
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+ that will be used to generate the CRL signature.
+
+ :returns: A new instance of
+ :class:`~cryptography.x509.CertificateRevocationList`.
+
+ .. method:: create_x509_revoked_certificate(builder)
+
+ .. versionadded:: 1.2
+
+ :param builder: An instance of RevokedCertificateBuilder.
+
+ :returns: A new instance of
+ :class:`~cryptography.x509.RevokedCertificate`.
+
+ .. method:: x509_name_bytes(name)
+
+ .. versionadded:: 1.6
+
+ :param name: An instance of :class:`~cryptography.x509.Name`.
+
+ :return bytes: The DER encoded bytes.
.. class:: DHBackend
@@ -557,33 +614,33 @@ A specific ``backend`` may provide one or more of these interfaces.
A backend with methods for doing Diffie-Hellman key exchange.
- .. method:: generate_dh_parameters(key_size)
+ .. method:: generate_dh_parameters(generator, key_size)
+
+ :param int generator: The generator to use. Often 2 or 5.
:param int key_size: The bit length of the prime modulus to generate.
- :return: A new instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameters`
- provider.
+ :return: A new instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameters`.
:raises ValueError: If ``key_size`` is not at least 512.
.. method:: generate_dh_private_key(parameters)
- :param parameters: A
- :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameters`
- provider.
+ :param parameters: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameters`.
- :return: A new instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKey`
- provider.
+ :return: A new instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKey`.
- .. method:: generate_dh_private_key_and_parameters(self, key_size)
+ .. method:: generate_dh_private_key_and_parameters(generator, key_size)
+
+ :param int generator: The generator to use. Often 2 or 5.
:param int key_size: The bit length of the prime modulus to generate.
- :return: A new instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKey`
- provider.
+ :return: A new instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKey`.
:raises ValueError: If ``key_size`` is not at least 512.
@@ -593,9 +650,8 @@ A specific ``backend`` may provide one or more of these interfaces.
:class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateNumbers`
instance.
- :return: A new instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKey`
- provider.
+ :return: A new instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKey`.
:raises cryptography.exceptions.UnsupportedAlgorithm: This is raised
when any backend specific criteria are not met.
@@ -606,9 +662,8 @@ A specific ``backend`` may provide one or more of these interfaces.
:class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicNumbers`
instance.
- :return: A new instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicKey`
- provider.
+ :return: A new instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicKey`.
:raises cryptography.exceptions.UnsupportedAlgorithm: This is raised
when any backend specific criteria are not met.
@@ -619,18 +674,56 @@ A specific ``backend`` may provide one or more of these interfaces.
:class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameterNumbers`
instance.
- :return: A new instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameters`
- provider.
+ :return: A new instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameters`.
:raises cryptography.exceptions.UnsupportedAlgorithm: This is raised
when any backend specific criteria are not met.
- .. method:: dh_parameters_supported(p, g)
+ .. method:: dh_parameters_supported(p, g, q=None)
:param int p: The p value of the DH key.
:param int g: The g value of the DH key.
- :returns: ``True`` if the given values of ``p`` and ``g`` are supported
- by this backend, otherwise ``False``.
+ :param int q: The q value of the DH key.
+
+ :returns: ``True`` if the given values of ``p``, ``g`` and ``q``
+ are supported by this backend, otherwise ``False``.
+
+ .. versionadded:: 1.8
+
+ .. method:: dh_x942_serialization_supported()
+
+ :returns: True if serialization of DH objects with
+ subgroup order (q) is supported by this backend.
+
+
+.. class:: ScryptBackend
+
+ .. versionadded:: 1.6
+
+ A backend with methods for using Scrypt.
+
+ The following backends implement this interface:
+
+ * :doc:`/hazmat/backends/openssl`
+
+ .. method:: derive_scrypt(self, key_material, salt, length, n, r, p)
+
+ :param bytes key_material: The key material to use as a basis for
+ the derived key. This is typically a password.
+
+ :param bytes salt: A salt.
+
+ :param int length: The desired length of the derived key.
+
+ :param int n: CPU/Memory cost parameter. It must be larger than 1 and be a
+ power of 2.
+
+ :param int r: Block size parameter.
+
+ :param int p: Parallelization parameter.
+
+ :return bytes: Derived key.
+
diff --git a/docs/hazmat/backends/multibackend.rst b/docs/hazmat/backends/multibackend.rst
deleted file mode 100644
index 0aae04a7..00000000
--- a/docs/hazmat/backends/multibackend.rst
+++ /dev/null
@@ -1,45 +0,0 @@
-.. hazmat::
-
-MultiBackend
-============
-
-.. currentmodule:: cryptography.hazmat.backends.multibackend
-
-.. class:: MultiBackend(backends)
-
- .. versionadded:: 0.2
-
- This class allows you to combine multiple backends into a single backend
- that offers the combined features of all of its constituents.
-
- .. testsetup::
-
- from cryptography import utils
- from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
- from cryptography.hazmat.backends.interfaces import HashBackend
- from cryptography.hazmat.backends.openssl.backend import backend as backend2
-
- @utils.register_interface(HashBackend)
- class DummyHashBackend(object):
- def hash_supported(self, algorithm):
- return False
-
- def create_hash_ctx(self, algorithm):
- raise UnsupportedAlgorithm("", _Reasons.UNSUPPORTED_HASH)
-
- backend1 = DummyHashBackend()
-
- .. doctest::
-
- >>> from cryptography.hazmat.backends.multibackend import MultiBackend
- >>> from cryptography.hazmat.primitives import hashes
- >>> backend1.hash_supported(hashes.SHA256())
- False
- >>> backend2.hash_supported(hashes.SHA256())
- True
- >>> multi_backend = MultiBackend([backend1, backend2])
- >>> multi_backend.hash_supported(hashes.SHA256())
- True
-
- :param backends: A ``list`` of backend objects. Backends are checked for
- feature support in the order they appear in this list.
diff --git a/docs/hazmat/backends/openssl.rst b/docs/hazmat/backends/openssl.rst
index 03ac5570..56121cb5 100644
--- a/docs/hazmat/backends/openssl.rst
+++ b/docs/hazmat/backends/openssl.rst
@@ -3,9 +3,8 @@
OpenSSL backend
===============
-The `OpenSSL`_ C library. Cryptography supports version ``0.9.8e`` (present in
-Red Hat Enterprise Linux 5) and greater. Earlier versions may work but are
-**not tested or supported**.
+The `OpenSSL`_ C library. Cryptography supports OpenSSL version 1.0.2 and
+greater.
.. data:: cryptography.hazmat.backends.openssl.backend
@@ -16,6 +15,7 @@ Red Hat Enterprise Linux 5) and greater. Earlier versions may work but are
* :class:`~cryptography.hazmat.backends.interfaces.CipherBackend`
* :class:`~cryptography.hazmat.backends.interfaces.CMACBackend`
* :class:`~cryptography.hazmat.backends.interfaces.DERSerializationBackend`
+ * :class:`~cryptography.hazmat.backends.interfaces.DHBackend`
* :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
* :class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`
* :class:`~cryptography.hazmat.backends.interfaces.HashBackend`
@@ -25,17 +25,42 @@ Red Hat Enterprise Linux 5) and greater. Earlier versions may work but are
* :class:`~cryptography.hazmat.backends.interfaces.PEMSerializationBackend`
* :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
+ It also implements the following interface for OpenSSL versions ``1.1.0``
+ and above.
+
+ * :class:`~cryptography.hazmat.backends.interfaces.ScryptBackend`
+
It also exposes the following:
.. attribute:: name
The string name of this backend: ``"openssl"``
+ .. method:: openssl_version_text()
+
+ :return text: The friendly string name of the loaded OpenSSL library.
+ This is not necessarily the same version as it was compiled against.
+
+ .. method:: openssl_version_number()
+
+ .. versionadded:: 1.8
+
+ :return int: The integer version of the loaded OpenSSL library. This is
+ defined in ``opensslv.h`` as ``OPENSSL_VERSION_NUMBER`` and is
+ typically shown in hexadecimal (e.g. ``0x1010003f``). This is
+ not necessarily the same version as it was compiled against.
+
.. method:: activate_osrandom_engine()
Activates the OS random engine. This will effectively disable OpenSSL's
default CSPRNG.
+ .. method:: osrandom_engine_implementation()
+
+ .. versionadded:: 1.7
+
+ Returns the implementation of OS random engine.
+
.. method:: activate_builtin_random()
This will activate the default OpenSSL CSPRNG.
@@ -43,7 +68,7 @@ Red Hat Enterprise Linux 5) and greater. Earlier versions may work but are
OS random engine
----------------
-OpenSSL uses a user-space CSPRNG that is seeded from system random (
+By default OpenSSL uses a user-space CSPRNG that is seeded from system random (
``/dev/urandom`` or ``CryptGenRandom``). This CSPRNG is not reseeded
automatically when a process calls ``fork()``. This can result in situations
where two different processes can return similar or identical keys and
@@ -67,8 +92,9 @@ When importing only the binding it is added to the engine list but
OS random sources
-----------------
-On OS X and FreeBSD ``/dev/urandom`` is an alias for ``/dev/random`` and
-utilizes the `Yarrow`_ algorithm.
+On macOS and FreeBSD ``/dev/urandom`` is an alias for ``/dev/random``. The
+implementation on macOS uses the `Yarrow`_ algorithm. FreeBSD uses the
+`Fortuna`_ algorithm.
On Windows the implementation of ``CryptGenRandom`` depends on which version of
the operation system you are using. See the `Microsoft documentation`_ for more
@@ -77,8 +103,24 @@ details.
Linux uses its own PRNG design. ``/dev/urandom`` is a non-blocking source
seeded from the same pool as ``/dev/random``.
++------------------------------------------+------------------------------+
+| Windows | ``CryptGenRandom()`` |
++------------------------------------------+------------------------------+
+| Linux >= 3.17 with working | ``getrandom()`` |
+| ``SYS_getrandom`` syscall | |
++------------------------------------------+------------------------------+
+| OpenBSD >= 5.6 | ``getentropy()`` |
++------------------------------------------+------------------------------+
+| BSD family (including macOS 10.12+) with | ``getentropy()`` |
+| ``SYS_getentropy`` in ``sys/syscall.h`` | |
++------------------------------------------+------------------------------+
+| fallback | ``/dev/urandom`` with |
+| | cached file descriptor |
++------------------------------------------+------------------------------+
+
.. _`OpenSSL`: https://www.openssl.org/
.. _`initializing the RNG`: https://en.wikipedia.org/wiki/OpenSSL#Predictable_private_keys_.28Debian-specific.29
+.. _`Fortuna`: https://en.wikipedia.org/wiki/Fortuna_(PRNG)
.. _`Yarrow`: https://en.wikipedia.org/wiki/Yarrow_algorithm
-.. _`Microsoft documentation`: https://msdn.microsoft.com/en-us/library/windows/desktop/aa379942(v=vs.85).aspx
+.. _`Microsoft documentation`: https://docs.microsoft.com/en-us/windows/desktop/api/wincrypt/nf-wincrypt-cryptgenrandom
diff --git a/docs/hazmat/bindings/commoncrypto.rst b/docs/hazmat/bindings/commoncrypto.rst
deleted file mode 100644
index 4f58a6d3..00000000
--- a/docs/hazmat/bindings/commoncrypto.rst
+++ /dev/null
@@ -1,30 +0,0 @@
-.. hazmat::
-
-CommonCrypto binding
-====================
-
-.. currentmodule:: cryptography.hazmat.bindings.commoncrypto.binding
-
-.. versionadded:: 0.2
-
-These are `CFFI`_ bindings to the `CommonCrypto`_ C library. It is only
-available on Mac OS X versions 10.8 and above.
-
-.. class:: cryptography.hazmat.bindings.commoncrypto.binding.Binding()
-
- This is the exposed API for the CommonCrypto bindings. It has two public
- attributes:
-
- .. attribute:: ffi
-
- This is a ``cffi.FFI`` instance. It can be used to allocate and
- otherwise manipulate CommonCrypto structures.
-
- .. attribute:: lib
-
- This is a ``cffi`` library. It can be used to call CommonCrypto
- functions, and access constants.
-
-
-.. _`CFFI`: https://cffi.readthedocs.org/
-.. _`CommonCrypto`: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/Common%20Crypto.3cc.html
diff --git a/docs/hazmat/bindings/index.rst b/docs/hazmat/bindings/index.rst
index 8075be14..655f4620 100644
--- a/docs/hazmat/bindings/index.rst
+++ b/docs/hazmat/bindings/index.rst
@@ -20,4 +20,3 @@ Individual bindings
:maxdepth: 1
openssl
- commoncrypto
diff --git a/docs/hazmat/bindings/openssl.rst b/docs/hazmat/bindings/openssl.rst
index 446c450c..bc7ec2d9 100644
--- a/docs/hazmat/bindings/openssl.rst
+++ b/docs/hazmat/bindings/openssl.rst
@@ -6,8 +6,7 @@ OpenSSL binding
.. currentmodule:: cryptography.hazmat.bindings.openssl.binding
These are `CFFI`_ bindings to the `OpenSSL`_ C library. Cryptography supports
-version ``0.9.8e`` (present in Red Hat Enterprise Linux 5) and greater. Earlier
-versions may work but are **not tested or supported**.
+OpenSSL version 1.0.2 and greater.
.. class:: cryptography.hazmat.bindings.openssl.binding.Binding()
@@ -34,16 +33,15 @@ versions may work but are **not tested or supported**.
Threading
---------
-``cryptography`` enables OpenSSLs `thread safety facilities`_ in two different
-ways depending on the configuration of your system. Normally the locking
-callbacks provided by your Python implementation specifically for OpenSSL will
-be used. However if you have linked ``cryptography`` to a different version of
-OpenSSL than that used by your Python implementation we enable an alternative
-locking callback. This version is implemented in Python and so may result in
-lower performance in some situations. In particular parallelism is reduced
-because it has to acquire the GIL whenever any lock operations occur within
-OpenSSL.
-
-.. _`CFFI`: https://cffi.readthedocs.org/
+``cryptography`` enables OpenSSLs `thread safety facilities`_ in several
+different ways depending on the configuration of your system. For users on
+OpenSSL 1.1.0 or newer (including anyone who uses a binary wheel) the OpenSSL
+internal locking callbacks are automatically used. Otherwise, we first attempt
+to use the callbacks provided by your Python implementation specifically for
+OpenSSL. This will work in every case except where ``cryptography`` is linked
+against a different version of OpenSSL than the one used by your Python
+implementation. For this final case we have a C-based locking callback.
+
+.. _`CFFI`: https://cffi.readthedocs.io
.. _`OpenSSL`: https://www.openssl.org/
-.. _`thread safety facilities`: https://www.openssl.org/docs/crypto/threads.html
+.. _`thread safety facilities`: https://www.openssl.org/docs/man1.0.2/man3/CRYPTO_THREADID_set_callback.html
diff --git a/docs/hazmat/primitives/aead.rst b/docs/hazmat/primitives/aead.rst
new file mode 100644
index 00000000..d318367b
--- /dev/null
+++ b/docs/hazmat/primitives/aead.rst
@@ -0,0 +1,248 @@
+.. hazmat::
+
+
+Authenticated encryption
+========================
+
+.. module:: cryptography.hazmat.primitives.ciphers.aead
+
+Authenticated encryption with associated data (AEAD) are encryption schemes
+which provide both confidentiality and integrity for their ciphertext. They
+also support providing integrity for associated data which is not encrypted.
+
+.. class:: ChaCha20Poly1305(key)
+
+ .. versionadded:: 2.0
+
+ The ChaCha20Poly1305 construction is defined in :rfc:`7539` section 2.8.
+ It is a stream cipher combined with a MAC that offers strong integrity
+ guarantees.
+
+ :param key: A 32-byte key. This **must** be kept secret.
+ :type key: :term:`bytes-like`
+
+ :raises cryptography.exceptions.UnsupportedAlgorithm: If the version of
+ OpenSSL does not support ChaCha20Poly1305.
+
+ .. doctest::
+
+ >>> import os
+ >>> from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305
+ >>> data = b"a secret message"
+ >>> aad = b"authenticated but unencrypted data"
+ >>> key = ChaCha20Poly1305.generate_key()
+ >>> chacha = ChaCha20Poly1305(key)
+ >>> nonce = os.urandom(12)
+ >>> ct = chacha.encrypt(nonce, data, aad)
+ >>> chacha.decrypt(nonce, ct, aad)
+ b'a secret message'
+
+ .. classmethod:: generate_key()
+
+ Securely generates a random ChaCha20Poly1305 key.
+
+ :returns bytes: A 32 byte key.
+
+ .. method:: encrypt(nonce, data, associated_data)
+
+ .. warning::
+
+ Reuse of a ``nonce`` with a given ``key`` compromises the security
+ of any message with that ``nonce`` and ``key`` pair.
+
+ Encrypts the ``data`` provided and authenticates the
+ ``associated_data``. The output of this can be passed directly
+ to the ``decrypt`` method.
+
+ :param nonce: A 12 byte value. **NEVER REUSE A NONCE** with a key.
+ :type nonce: :term:`bytes-like`
+ :param bytes data: The data to encrypt.
+ :param bytes associated_data: Additional data that should be
+ authenticated with the key, but does not need to be encrypted. Can
+ be ``None``.
+ :returns bytes: The ciphertext bytes with the 16 byte tag appended.
+ :raises OverflowError: If ``data`` or ``associated_data`` is larger
+ than 2\ :sup:`32` bytes.
+
+ .. method:: decrypt(nonce, data, associated_data)
+
+ Decrypts the ``data`` and authenticates the ``associated_data``. If you
+ called encrypt with ``associated_data`` you must pass the same
+ ``associated_data`` in decrypt or the integrity check will fail.
+
+ :param nonce: A 12 byte value. **NEVER REUSE A NONCE** with a
+ key.
+ :type nonce: :term:`bytes-like`
+ :param bytes data: The data to decrypt (with tag appended).
+ :param bytes associated_data: Additional data to authenticate. Can be
+ ``None`` if none was passed during encryption.
+ :returns bytes: The original plaintext.
+ :raises cryptography.exceptions.InvalidTag: If the authentication tag
+ doesn't validate this exception will be raised. This will occur
+ when the ciphertext has been changed, but will also occur when the
+ key, nonce, or associated data are wrong.
+
+.. class:: AESGCM(key)
+
+ .. versionadded:: 2.0
+
+ The AES-GCM construction is composed of the
+ :class:`~cryptography.hazmat.primitives.ciphers.algorithms.AES` block
+ cipher utilizing Galois Counter Mode (GCM).
+
+ :param key: A 128, 192, or 256-bit key. This **must** be kept secret.
+ :type key: :term:`bytes-like`
+
+ .. doctest::
+
+ >>> import os
+ >>> from cryptography.hazmat.primitives.ciphers.aead import AESGCM
+ >>> data = b"a secret message"
+ >>> aad = b"authenticated but unencrypted data"
+ >>> key = AESGCM.generate_key(bit_length=128)
+ >>> aesgcm = AESGCM(key)
+ >>> nonce = os.urandom(12)
+ >>> ct = aesgcm.encrypt(nonce, data, aad)
+ >>> aesgcm.decrypt(nonce, ct, aad)
+ b'a secret message'
+
+ .. classmethod:: generate_key(bit_length)
+
+ Securely generates a random AES-GCM key.
+
+ :param bit_length: The bit length of the key to generate. Must be
+ 128, 192, or 256.
+
+ :returns bytes: The generated key.
+
+ .. method:: encrypt(nonce, data, associated_data)
+
+ .. warning::
+
+ Reuse of a ``nonce`` with a given ``key`` compromises the security
+ of any message with that ``nonce`` and ``key`` pair.
+
+ Encrypts and authenticates the ``data`` provided as well as
+ authenticating the ``associated_data``. The output of this can be
+ passed directly to the ``decrypt`` method.
+
+ :param nonce: NIST `recommends a 96-bit IV length`_ for best
+ performance but it can be up to 2\ :sup:`64` - 1 :term:`bits`.
+ **NEVER REUSE A NONCE** with a key.
+ :type nonce: :term:`bytes-like`
+ :param bytes data: The data to encrypt.
+ :param bytes associated_data: Additional data that should be
+ authenticated with the key, but is not encrypted. Can be ``None``.
+ :returns bytes: The ciphertext bytes with the 16 byte tag appended.
+ :raises OverflowError: If ``data`` or ``associated_data`` is larger
+ than 2\ :sup:`32` bytes.
+
+ .. method:: decrypt(nonce, data, associated_data)
+
+ Decrypts the ``data`` and authenticates the ``associated_data``. If you
+ called encrypt with ``associated_data`` you must pass the same
+ ``associated_data`` in decrypt or the integrity check will fail.
+
+ :param nonce: NIST `recommends a 96-bit IV length`_ for best
+ performance but it can be up to 2\ :sup:`64` - 1 :term:`bits`.
+ **NEVER REUSE A NONCE** with a key.
+ :type nonce: :term:`bytes-like`
+ :param bytes data: The data to decrypt (with tag appended).
+ :param bytes associated_data: Additional data to authenticate. Can be
+ ``None`` if none was passed during encryption.
+ :returns bytes: The original plaintext.
+ :raises cryptography.exceptions.InvalidTag: If the authentication tag
+ doesn't validate this exception will be raised. This will occur
+ when the ciphertext has been changed, but will also occur when the
+ key, nonce, or associated data are wrong.
+
+.. class:: AESCCM(key, tag_length=16)
+
+ .. versionadded:: 2.0
+
+ .. note:
+
+ AES-CCM is provided largely for compatibility with existing protocols.
+ Due to its construction it is not as computationally efficient as
+ other AEAD ciphers.
+
+ The AES-CCM construction is composed of the
+ :class:`~cryptography.hazmat.primitives.ciphers.algorithms.AES` block
+ cipher utilizing Counter with CBC-MAC (CCM) (specified in :rfc:`3610`).
+
+ :param key: A 128, 192, or 256-bit key. This **must** be kept secret.
+ :type key: :term:`bytes-like`
+ :param int tag_length: The length of the authentication tag. This
+ defaults to 16 bytes and it is **strongly** recommended that you
+ do not make it shorter unless absolutely necessary. Valid tag
+ lengths are 4, 6, 8, 10, 12, 14, and 16.
+
+ :raises cryptography.exceptions.UnsupportedAlgorithm: If the version of
+ OpenSSL does not support AES-CCM.
+
+ .. doctest::
+
+ >>> import os
+ >>> from cryptography.hazmat.primitives.ciphers.aead import AESCCM
+ >>> data = b"a secret message"
+ >>> aad = b"authenticated but unencrypted data"
+ >>> key = AESCCM.generate_key(bit_length=128)
+ >>> aesccm = AESCCM(key)
+ >>> nonce = os.urandom(13)
+ >>> ct = aesccm.encrypt(nonce, data, aad)
+ >>> aesccm.decrypt(nonce, ct, aad)
+ b'a secret message'
+
+ .. classmethod:: generate_key(bit_length)
+
+ Securely generates a random AES-CCM key.
+
+ :param bit_length: The bit length of the key to generate. Must be
+ 128, 192, or 256.
+
+ :returns bytes: The generated key.
+
+ .. method:: encrypt(nonce, data, associated_data)
+
+ .. warning::
+
+ Reuse of a ``nonce`` with a given ``key`` compromises the security
+ of any message with that ``nonce`` and ``key`` pair.
+
+ Encrypts and authenticates the ``data`` provided as well as
+ authenticating the ``associated_data``. The output of this can be
+ passed directly to the ``decrypt`` method.
+
+ :param nonce: A value of between 7 and 13 bytes. The maximum
+ length is determined by the length of the ciphertext you are
+ encrypting and must satisfy the condition:
+ ``len(data) < 2 ** (8 * (15 - len(nonce)))``
+ **NEVER REUSE A NONCE** with a key.
+ :type nonce: :term:`bytes-like`
+ :param bytes data: The data to encrypt.
+ :param bytes associated_data: Additional data that should be
+ authenticated with the key, but is not encrypted. Can be ``None``.
+ :returns bytes: The ciphertext bytes with the tag appended.
+ :raises OverflowError: If ``data`` or ``associated_data`` is larger
+ than 2\ :sup:`32` bytes.
+
+ .. method:: decrypt(nonce, data, associated_data)
+
+ Decrypts the ``data`` and authenticates the ``associated_data``. If you
+ called encrypt with ``associated_data`` you must pass the same
+ ``associated_data`` in decrypt or the integrity check will fail.
+
+ :param nonce: A value of between 7 and 13 bytes. This
+ is the same value used when you originally called encrypt.
+ **NEVER REUSE A NONCE** with a key.
+ :type nonce: :term:`bytes-like`
+ :param bytes data: The data to decrypt (with tag appended).
+ :param bytes associated_data: Additional data to authenticate. Can be
+ ``None`` if none was passed during encryption.
+ :returns bytes: The original plaintext.
+ :raises cryptography.exceptions.InvalidTag: If the authentication tag
+ doesn't validate this exception will be raised. This will occur
+ when the ciphertext has been changed, but will also occur when the
+ key, nonce, or associated data are wrong.
+
+.. _`recommends a 96-bit IV length`: https://csrc.nist.gov/publications/detail/sp/800-38d/final
diff --git a/docs/hazmat/primitives/asymmetric/dh.rst b/docs/hazmat/primitives/asymmetric/dh.rst
index dde18cf7..edfe6143 100644
--- a/docs/hazmat/primitives/asymmetric/dh.rst
+++ b/docs/hazmat/primitives/asymmetric/dh.rst
@@ -5,114 +5,282 @@ Diffie-Hellman key exchange
.. currentmodule:: cryptography.hazmat.primitives.asymmetric.dh
+.. note::
+ For security and performance reasons we suggest using
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.ECDH` instead of DH
+ where possible.
+
+
+`Diffie-Hellman key exchange`_ (D–H) is a method that allows two parties
+to jointly agree on a shared secret using an insecure channel.
+
+
+Exchange Algorithm
+~~~~~~~~~~~~~~~~~~
+
+For most applications the ``shared_key`` should be passed to a key
+derivation function. This allows mixing of additional information into the
+key, derivation of multiple keys, and destroys any structure that may be
+present.
+
+.. warning::
+
+ This example does not give `forward secrecy`_ and is only provided as a
+ demonstration of the basic Diffie-Hellman construction. For real world
+ applications always use the ephemeral form described after this example.
+
+.. code-block:: pycon
+
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> from cryptography.hazmat.primitives.asymmetric import dh
+ >>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
+ >>> # Generate some parameters. These can be reused.
+ >>> parameters = dh.generate_parameters(generator=2, key_size=2048,
+ ... backend=default_backend())
+ >>> # Generate a private key for use in the exchange.
+ >>> server_private_key = parameters.generate_private_key()
+ >>> # In a real handshake the peer is a remote client. For this
+ >>> # example we'll generate another local private key though. Note that in
+ >>> # a DH handshake both peers must agree on a common set of parameters.
+ >>> peer_private_key = parameters.generate_private_key()
+ >>> shared_key = server_private_key.exchange(peer_private_key.public_key())
+ >>> # Perform key derivation.
+ >>> derived_key = HKDF(
+ ... algorithm=hashes.SHA256(),
+ ... length=32,
+ ... salt=None,
+ ... info=b'handshake data',
+ ... backend=default_backend()
+ ... ).derive(shared_key)
+ >>> # And now we can demonstrate that the handshake performed in the
+ >>> # opposite direction gives the same final value
+ >>> same_shared_key = peer_private_key.exchange(
+ ... server_private_key.public_key()
+ ... )
+ >>> same_derived_key = HKDF(
+ ... algorithm=hashes.SHA256(),
+ ... length=32,
+ ... salt=None,
+ ... info=b'handshake data',
+ ... backend=default_backend()
+ ... ).derive(same_shared_key)
+ >>> derived_key == same_derived_key
+
+DHE (or EDH), the ephemeral form of this exchange, is **strongly
+preferred** over simple DH and provides `forward secrecy`_ when used. You must
+generate a new private key using :func:`~DHParameters.generate_private_key` for
+each :meth:`~DHPrivateKey.exchange` when performing an DHE key exchange. An
+example of the ephemeral form:
+
+.. code-block:: pycon
+
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> from cryptography.hazmat.primitives.asymmetric import dh
+ >>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
+ >>> # Generate some parameters. These can be reused.
+ >>> parameters = dh.generate_parameters(generator=2, key_size=2048,
+ ... backend=default_backend())
+ >>> # Generate a private key for use in the exchange.
+ >>> private_key = parameters.generate_private_key()
+ >>> # In a real handshake the peer_public_key will be received from the
+ >>> # other party. For this example we'll generate another private key and
+ >>> # get a public key from that. Note that in a DH handshake both peers
+ >>> # must agree on a common set of parameters.
+ >>> peer_public_key = parameters.generate_private_key().public_key()
+ >>> shared_key = private_key.exchange(peer_public_key)
+ >>> # Perform key derivation.
+ >>> derived_key = HKDF(
+ ... algorithm=hashes.SHA256(),
+ ... length=32,
+ ... salt=None,
+ ... info=b'handshake data',
+ ... backend=default_backend()
+ ... ).derive(shared_key)
+ >>> # For the next handshake we MUST generate another private key, but
+ >>> # we can reuse the parameters.
+ >>> private_key_2 = parameters.generate_private_key()
+ >>> peer_public_key_2 = parameters.generate_private_key().public_key()
+ >>> shared_key_2 = private_key_2.exchange(peer_public_key_2)
+ >>> derived_key_2 = HKDF(
+ ... algorithm=hashes.SHA256(),
+ ... length=32,
+ ... salt=None,
+ ... info=b'handshake data',
+ ... backend=default_backend()
+ ... ).derive(shared_key_2)
+
+To assemble a :class:`~DHParameters` and a :class:`~DHPublicKey` from
+primitive integers, you must first create the
+:class:`~DHParameterNumbers` and :class:`~DHPublicNumbers` objects. For
+example, if **p**, **g**, and **y** are :class:`int` objects received from a
+peer::
+
+ pn = dh.DHParameterNumbers(p, g)
+ parameters = pn.parameters(default_backend())
+ peer_public_numbers = dh.DHPublicNumbers(y, pn)
+ peer_public_key = peer_public_numbers.public_key(default_backend())
+
+
+See also the :class:`~cryptography.hazmat.backends.interfaces.DHBackend`
+API for additional functionality.
+
+Group parameters
+~~~~~~~~~~~~~~~~
+
+.. function:: generate_parameters(generator, key_size, backend)
+
+ .. versionadded:: 1.7
+
+ Generate a new DH parameter group for use with ``backend``.
+
+ :param generator: The :class:`int` to use as a generator. Must be
+ 2 or 5.
+
+ :param key_size: The bit length of the prime modulus to generate.
+
+ :param backend: A
+ :class:`~cryptography.hazmat.backends.interfaces.DHBackend`
+ instance.
+
+ :returns: DH parameters as a new instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameters`.
+
+ :raises ValueError: If ``key_size`` is not at least 512.
-Numbers
-~~~~~~~
-.. class:: DHPrivateNumbers(x, public_numbers)
+.. class:: DHParameters
- .. versionadded:: 0.8
+ .. versionadded:: 1.7
- The collection of integers that make up a Diffie-Hellman private key.
- .. attribute:: public_numbers
+ .. method:: generate_private_key()
- :type: :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicNumbers`
+ Generate a DH private key. This method can be used to generate many
+ new private keys from a single set of parameters.
- The :class:`DHPublicNumbers` which makes up the DH public
- key associated with this DH private key.
+ :return: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKey`.
- .. attribute:: x
+ .. method:: parameter_numbers()
- :type: int
+ Return the numbers that make up this set of parameters.
- The private value.
+ :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameterNumbers`.
+ .. method:: parameter_bytes(encoding, format)
-.. class:: DHPublicNumbers(parameters, y)
+ .. versionadded:: 2.0
- .. versionadded:: 0.8
+ Allows serialization of the parameters to bytes. Encoding (
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM` or
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`) and
+ format (
+ :attr:`~cryptography.hazmat.primitives.serialization.ParameterFormat.PKCS3`)
+ are chosen to define the exact serialization.
- The collection of integers that make up a Diffie-Hellman public key.
+ :param encoding: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
- .. attribute:: parameter_numbers
+ :param format: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.ParameterFormat`
+ enum. At the moment only ``PKCS3`` is supported.
- :type: :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameterNumbers`
+ :return bytes: Serialized parameters.
- The parameters for this DH group.
+.. class:: DHParametersWithSerialization
- .. attribute:: y
+ .. versionadded:: 1.7
- :type: int
+ Alias for :class:`DHParameters`.
- The public value.
+Key interfaces
+~~~~~~~~~~~~~~
-.. class:: DHParameterNumbers(p, g)
+.. class:: DHPrivateKey
- .. versionadded:: 0.8
+ .. versionadded:: 1.7
- The collection of integers that define a Diffie-Hellman group.
+ A DH private key that is not an :term:`opaque key` also implements
+ :class:`DHPrivateKeyWithSerialization` to provide serialization methods.
- .. attribute:: p
+ .. attribute:: key_size
- :type: int
+ The bit length of the prime modulus.
- The prime modulus value.
+ .. method:: public_key()
- .. attribute:: g
+ Return the public key associated with this private key.
- :type: int
+ :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicKey`.
- The generator value.
+ .. method:: parameters()
+ Return the parameters associated with this private key.
-Key interfaces
-~~~~~~~~~~~~~~
+ :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameters`.
-.. class:: DHParameters
+ .. method:: exchange(peer_public_key)
- .. versionadded:: 0.9
+ .. versionadded:: 1.7
+ :param DHPublicKey peer_public_key: The public key for
+ the peer.
- .. method:: generate_private_key()
+ :return bytes: The agreed key. The bytes are ordered in 'big' endian.
- .. versionadded:: 0.9
- Generate a DH private key. This method can be used to generate many
- new private keys from a single set of parameters.
+.. class:: DHPrivateKeyWithSerialization
- :return: A
- :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKey`
- provider.
+ .. versionadded:: 1.7
+ This interface contains additional methods relating to serialization.
+ Any object with this interface also has all the methods from
+ :class:`DHPrivateKey`.
-.. class:: DHParametersWithSerialization
+ .. method:: private_numbers()
- .. versionadded:: 0.9
+ Return the numbers that make up this private key.
- Inherits from :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameters`.
+ :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateNumbers`.
- .. method:: parameter_numbers()
+ .. method:: private_bytes(encoding, format, encryption_algorithm)
- Return the numbers that make up this set of parameters.
+ .. versionadded:: 1.8
- :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameterNumbers`.
+ Allows serialization of the key to bytes. Encoding (
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM` or
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`),
+ format (
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`)
+ and encryption algorithm (such as
+ :class:`~cryptography.hazmat.primitives.serialization.BestAvailableEncryption`
+ or :class:`~cryptography.hazmat.primitives.serialization.NoEncryption`)
+ are chosen to define the exact serialization.
+ :param encoding: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
-.. class:: DHPrivateKey
+ :param format: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.PrivateFormat`
+ enum.
- .. versionadded:: 0.9
+ :param encryption_algorithm: An instance of an object conforming to the
+ :class:`~cryptography.hazmat.primitives.serialization.KeySerializationEncryption`
+ interface.
- .. attribute:: key_size
+ :return bytes: Serialized key.
- The bit length of the prime modulus.
- .. method:: public_key()
+.. class:: DHPublicKey
- Return the public key associated with this private key.
+ .. versionadded:: 1.7
- :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicKey`.
+ .. attribute:: key_size
+
+ The bit length of the prime modulus.
.. method:: parameters()
@@ -120,43 +288,132 @@ Key interfaces
:return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameters`.
+ .. method:: public_numbers()
-.. class:: DHPrivateKeyWithSerialization
+ Return the numbers that make up this public key.
- .. versionadded:: 0.9
+ :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicNumbers`.
- Inherits from :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKey`.
+ .. method:: public_bytes(encoding, format)
- .. method:: private_numbers()
+ .. versionadded:: 1.8
- Return the numbers that make up this private key.
+ Allows serialization of the key to bytes. Encoding (
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM` or
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`) and
+ format (
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`)
+ are chosen to define the exact serialization.
- :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateNumbers`.
+ :param encoding: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
+ :param format: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.PublicFormat` enum.
-.. class:: DHPublicKey
+ :return bytes: Serialized key.
- .. versionadded:: 0.9
+.. class:: DHPublicKeyWithSerialization
- .. attribute:: key_size
+ .. versionadded:: 1.7
- The bit length of the prime modulus.
+ Alias for :class:`DHPublicKey`.
- .. method:: parameters()
- Return the parameters associated with this private key.
+Numbers
+~~~~~~~
- :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameters`.
+.. class:: DHParameterNumbers(p, g, q=None)
+ .. versionadded:: 0.8
-.. class:: DHPublicKeyWithSerialization
+ The collection of integers that define a Diffie-Hellman group.
- .. versionadded:: 0.9
+ .. attribute:: p
- Inherits from :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicKey`.
+ :type: int
- .. method:: public_numbers()
+ The prime modulus value.
- Return the numbers that make up this public key.
+ .. attribute:: g
- :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicNumbers`.
+ :type: int
+
+ The generator value. Must be 2 or greater.
+
+ .. attribute:: q
+
+ .. versionadded:: 1.8
+
+ :type: int
+
+ p subgroup order value.
+
+ .. method:: parameters(backend)
+
+ .. versionadded:: 1.7
+
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.DHBackend`.
+
+ :returns: A new instance of :class:`DHParameters`.
+
+.. class:: DHPrivateNumbers(x, public_numbers)
+
+ .. versionadded:: 0.8
+
+ The collection of integers that make up a Diffie-Hellman private key.
+
+ .. attribute:: public_numbers
+
+ :type: :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicNumbers`
+
+ The :class:`DHPublicNumbers` which makes up the DH public
+ key associated with this DH private key.
+
+ .. attribute:: x
+
+ :type: int
+
+ The private value.
+
+ .. method:: private_key(backend)
+
+ .. versionadded:: 1.7
+
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.DHBackend`.
+
+ :returns: A new instance of :class:`DHPrivateKey`.
+
+
+.. class:: DHPublicNumbers(y, parameter_numbers)
+
+ .. versionadded:: 0.8
+
+ The collection of integers that make up a Diffie-Hellman public key.
+
+ .. attribute:: parameter_numbers
+
+ :type: :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameterNumbers`
+
+ The parameters for this DH group.
+
+ .. attribute:: y
+
+ :type: int
+
+ The public value.
+
+ .. method:: public_key(backend)
+
+ .. versionadded:: 1.7
+
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.DHBackend`.
+
+ :returns: A new instance of :class:`DHPublicKey`.
+
+
+.. _`Diffie-Hellman key exchange`: https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange
+.. _`forward secrecy`: https://en.wikipedia.org/wiki/Forward_secrecy
diff --git a/docs/hazmat/primitives/asymmetric/dsa.rst b/docs/hazmat/primitives/asymmetric/dsa.rst
index 179bb8d1..7b059869 100644
--- a/docs/hazmat/primitives/asymmetric/dsa.rst
+++ b/docs/hazmat/primitives/asymmetric/dsa.rst
@@ -17,19 +17,18 @@ Generation
Generate a DSA private key from the given key size. This function will
generate a new set of parameters and key in one step.
- :param int key_size: The length of the modulus in bits. It should be
- either 1024, 2048 or 3072. For keys generated in 2015 this should
+ :param int key_size: The length of the modulus in :term:`bits`. It should
+ be either 1024, 2048 or 3072. For keys generated in 2015 this should
be `at least 2048`_ (See page 41). Note that some applications
(such as SSH) have not yet gained support for larger key sizes
specified in FIPS 186-3 and are still restricted to only the
1024-bit keys specified in FIPS 186-2.
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.DSABackend`.
- :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`
- provider.
+ :return: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`.
:raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if
the provided ``backend`` does not implement
@@ -41,19 +40,18 @@ Generation
Generate DSA parameters using the provided ``backend``.
- :param int key_size: The length of the modulus in bits. It should be
- either 1024, 2048 or 3072. For keys generated in 2015 this should
- be `at least 2048`_ (See page 41). Note that some applications
+ :param int key_size: The length of :attr:`~DSAParameterNumbers.q`. It
+ should be either 1024, 2048 or 3072. For keys generated in 2015 this
+ should be `at least 2048`_ (See page 41). Note that some applications
(such as SSH) have not yet gained support for larger key sizes
specified in FIPS 186-3 and are still restricted to only the
1024-bit keys specified in FIPS 186-2.
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.DSABackend`.
- :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAParameters`
- provider.
+ :return: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAParameters`.
:raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if
the provided ``backend`` does not implement
@@ -63,7 +61,7 @@ Signing
~~~~~~~
Using a :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`
-provider.
+instance.
.. doctest::
@@ -74,34 +72,77 @@ provider.
... key_size=1024,
... backend=default_backend()
... )
- >>> signer = private_key.signer(hashes.SHA256())
>>> data = b"this is some data I'd like to sign"
- >>> signer.update(data)
- >>> signature = signer.finalize()
+ >>> signature = private_key.sign(
+ ... data,
+ ... hashes.SHA256()
+ ... )
The ``signature`` is a ``bytes`` object, whose contents is DER encoded as
-described in :rfc:`6979`. This can be decoded using
-:func:`~cryptography.hazmat.primitives.asymmetric.utils.decode_rfc6979_signature`.
+described in :rfc:`3279`. This can be decoded using
+:func:`~cryptography.hazmat.primitives.asymmetric.utils.decode_dss_signature`.
+
+If your data is too large to be passed in a single call, you can hash it
+separately and pass that value using
+:class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`.
+
+.. doctest::
+
+ >>> from cryptography.hazmat.primitives.asymmetric import utils
+ >>> chosen_hash = hashes.SHA256()
+ >>> hasher = hashes.Hash(chosen_hash, default_backend())
+ >>> hasher.update(b"data & ")
+ >>> hasher.update(b"more data")
+ >>> digest = hasher.finalize()
+ >>> sig = private_key.sign(
+ ... digest,
+ ... utils.Prehashed(chosen_hash)
+ ... )
Verification
~~~~~~~~~~~~
-Using a :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`
-provider.
+Verification is performed using a
+:class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey` instance.
+You can get a public key object with
+:func:`~cryptography.hazmat.primitives.serialization.load_pem_public_key`,
+:func:`~cryptography.hazmat.primitives.serialization.load_der_public_key`,
+:meth:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicNumbers.public_key`
+, or
+:meth:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey.public_key`.
.. doctest::
>>> public_key = private_key.public_key()
- >>> verifier = public_key.verifier(signature, hashes.SHA256())
- >>> verifier.update(data)
- >>> verifier.verify()
+ >>> public_key.verify(
+ ... signature,
+ ... data,
+ ... hashes.SHA256()
+ ... )
-``verifier()`` takes the signature in the same format as is returned by
-``signer.finalize()``.
+``verify()`` takes the signature in the same format as is returned by
+``sign()``.
``verify()`` will raise an :class:`~cryptography.exceptions.InvalidSignature`
exception if the signature isn't valid.
+If your data is too large to be passed in a single call, you can hash it
+separately and pass that value using
+:class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`.
+
+.. doctest::
+
+ >>> chosen_hash = hashes.SHA256()
+ >>> hasher = hashes.Hash(chosen_hash, default_backend())
+ >>> hasher.update(b"data & ")
+ >>> hasher.update(b"more data")
+ >>> digest = hasher.finalize()
+ >>> public_key.verify(
+ ... sig,
+ ... digest,
+ ... utils.Prehashed(chosen_hash)
+ ... )
+
Numbers
~~~~~~~
@@ -131,13 +172,11 @@ Numbers
.. method:: parameters(backend)
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.DSABackend`.
- :returns: A new instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAParameters`
- provider.
+ :returns: A new instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAParameters`.
.. class:: DSAPublicNumbers(y, parameter_numbers)
@@ -160,13 +199,11 @@ Numbers
.. method:: public_key(backend)
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.DSABackend`.
- :returns: A new instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`
- provider.
+ :returns: A new instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`.
.. class:: DSAPrivateNumbers(x, public_numbers)
@@ -194,13 +231,11 @@ Numbers
.. method:: private_key(backend)
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.DSABackend`.
- :returns: A new instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`
- provider.
+ :returns: A new instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`.
Key interfaces
~~~~~~~~~~~~~~
@@ -218,9 +253,8 @@ Key interfaces
Generate a DSA private key. This method can be used to generate many
new private keys from a single set of parameters.
- :return: A
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`
- provider.
+ :return: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`.
.. class:: DSAParametersWithNumbers
@@ -244,7 +278,9 @@ Key interfaces
.. versionadded:: 0.3
- A `DSA`_ private key.
+ A `DSA`_ private key. A DSA private key that is not an
+ :term:`opaque key` also implements :class:`DSAPrivateKeyWithSerialization`
+ to provide serialization methods.
.. method:: public_key()
@@ -258,54 +294,39 @@ Key interfaces
The DSAParameters object associated with this private key.
- .. method:: signer(algorithm, backend)
-
- .. versionadded:: 0.4
-
- Sign data which can be verified later by others using the public key.
- The signature is formatted as DER-encoded bytes, as specified in
- :rfc:`6979`.
-
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- provider.
-
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
- provider.
-
- :returns:
- :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricSignatureContext`
-
.. attribute:: key_size
:type: int
- The bit length of the modulus.
+ The bit length of :attr:`~DSAParameterNumbers.q`.
+ .. method:: sign(data, algorithm)
-.. class:: DSAPrivateKeyWithNumbers
+ .. versionadded:: 1.5
+ .. versionchanged:: 1.6
+ :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`
+ can now be used as an ``algorithm``.
- .. versionadded:: 0.5
+ Sign one block of data which can be verified later by others using the
+ public key.
- Extends :class:`DSAPrivateKey`.
+ :param bytes data: The message string to sign.
- .. method:: private_numbers()
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`
+ if the ``data`` you want to sign has already been hashed.
- Create a
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateNumbers`
- object.
-
- :returns: A
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateNumbers`
- instance.
+ :return bytes: Signature.
.. class:: DSAPrivateKeyWithSerialization
.. versionadded:: 0.8
- Extends :class:`DSAPrivateKey`.
+ This interface contains additional methods relating to serialization.
+ Any object with this interface also has all the methods from
+ :class:`DSAPrivateKey`.
.. method:: private_numbers()
@@ -355,7 +376,7 @@ Key interfaces
:type: int
- The bit length of the modulus.
+ The bit length of :attr:`~DSAParameterNumbers.q`.
.. method:: parameters()
@@ -363,50 +384,6 @@ Key interfaces
The DSAParameters object associated with this public key.
- .. method:: verifier(signature, algorithm, backend)
-
- .. versionadded:: 0.4
-
- Verify data was signed by the private key associated with this public
- key.
-
- :param bytes signature: The signature to verify. DER encoded as
- specified in :rfc:`6979`.
-
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- provider.
-
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
- provider.
-
- :returns:
- :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricVerificationContext`
-
-
-.. class:: DSAPublicKeyWithNumbers
-
- .. versionadded:: 0.5
-
- Extends :class:`DSAPublicKey`.
-
- .. method:: public_numbers()
-
- Create a
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicNumbers`
- object.
-
- :returns: A
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicNumbers`
- instance.
-
-.. class:: DSAPublicKeyWithSerialization
-
- .. versionadded:: 0.8
-
- Extends :class:`DSAPublicKey`.
-
.. method:: public_numbers()
Create a
@@ -434,8 +411,37 @@ Key interfaces
:return bytes: Serialized key.
+ .. method:: verify(signature, data, algorithm)
+
+ .. versionadded:: 1.5
+ .. versionchanged:: 1.6
+ :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`
+ can now be used as an ``algorithm``.
+
+ Verify one block of data was signed by the private key
+ associated with this public key.
+
+ :param bytes signature: The signature to verify.
+
+ :param bytes data: The message string that was signed.
+
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`
+ if the ``data`` you want to sign has already been hashed.
+
+ :raises cryptography.exceptions.InvalidSignature: If the signature does
+ not validate.
+
+
+.. class:: DSAPublicKeyWithSerialization
+
+ .. versionadded:: 0.8
+
+ Alias for :class:`DSAPublicKey`.
+
.. _`DSA`: https://en.wikipedia.org/wiki/Digital_Signature_Algorithm
.. _`public-key`: https://en.wikipedia.org/wiki/Public-key_cryptography
-.. _`FIPS 186-4`: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
-.. _`at least 2048`: http://www.ecrypt.eu.org/ecrypt2/documents/D.SPA.20.pdf
+.. _`FIPS 186-4`: https://csrc.nist.gov/publications/detail/fips/186/4/final
+.. _`at least 2048`: https://www.cosic.esat.kuleuven.be/ecrypt/ecrypt2/documents/D.SPA.20.pdf
diff --git a/docs/hazmat/primitives/asymmetric/ec.rst b/docs/hazmat/primitives/asymmetric/ec.rst
index 71f6e6fd..bd52aeee 100644
--- a/docs/hazmat/primitives/asymmetric/ec.rst
+++ b/docs/hazmat/primitives/asymmetric/ec.rst
@@ -12,13 +12,29 @@ Elliptic curve cryptography
Generate a new private key on ``curve`` for use with ``backend``.
- :param backend: A :class:`EllipticCurve` provider.
+ :param curve: An instance of :class:`EllipticCurve`.
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`.
- :returns: A new instance of a :class:`EllipticCurvePrivateKey` provider.
+ :returns: A new instance of :class:`EllipticCurvePrivateKey`.
+
+
+.. function:: derive_private_key(private_value, curve, backend)
+
+ .. versionadded:: 1.6
+
+ Derive a private key from ``private_value`` on ``curve`` for use with
+ ``backend``.
+
+ :param int private_value: The secret scalar value.
+
+ :param curve: An instance of :class:`EllipticCurve`.
+
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`.
+
+ :returns: A new instance of :class:`EllipticCurvePrivateKey`.
Elliptic Curve Signature Algorithms
@@ -31,9 +47,8 @@ Elliptic Curve Signature Algorithms
The ECDSA signature algorithm first standardized in NIST publication
`FIPS 186-3`_, and later in `FIPS 186-4`_.
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- provider.
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
.. doctest::
@@ -43,15 +58,71 @@ Elliptic Curve Signature Algorithms
>>> private_key = ec.generate_private_key(
... ec.SECP384R1(), default_backend()
... )
- >>> signer = private_key.signer(ec.ECDSA(hashes.SHA256()))
- >>> signer.update(b"this is some data I'd like")
- >>> signer.update(b" to sign")
- >>> signature = signer.finalize()
+ >>> data = b"this is some data I'd like to sign"
+ >>> signature = private_key.sign(
+ ... data,
+ ... ec.ECDSA(hashes.SHA256())
+ ... )
+
+ The ``signature`` is a ``bytes`` object, whose contents are DER encoded as
+ described in :rfc:`3279`. This can be decoded using
+ :func:`~cryptography.hazmat.primitives.asymmetric.utils.decode_dss_signature`.
+
+ If your data is too large to be passed in a single call, you can hash it
+ separately and pass that value using
+ :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`.
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.primitives.asymmetric import utils
+ >>> chosen_hash = hashes.SHA256()
+ >>> hasher = hashes.Hash(chosen_hash, default_backend())
+ >>> hasher.update(b"data & ")
+ >>> hasher.update(b"more data")
+ >>> digest = hasher.finalize()
+ >>> sig = private_key.sign(
+ ... digest,
+ ... ec.ECDSA(utils.Prehashed(chosen_hash))
+ ... )
+
+
+ Verification requires the public key, the DER-encoded signature itself, the
+ signed data, and knowledge of the hashing algorithm that was used when
+ producing the signature:
- The ``signature`` is a ``bytes`` object, whose contents is DER encoded as
- described in :rfc:`6979`. This can be decoded using
- :func:`~cryptography.hazmat.primitives.asymmetric.utils.decode_rfc6979_signature`.
+ >>> public_key = private_key.public_key()
+ >>> public_key.verify(signature, data, ec.ECDSA(hashes.SHA256()))
+ As above, the ``signature`` is a ``bytes`` object whose contents are DER
+ encoded as described in :rfc:`3279`. It can be created from a raw ``(r,s)``
+ pair by using
+ :func:`~cryptography.hazmat.primitives.asymmetric.utils.encode_dss_signature`.
+
+ If the signature is not valid, an
+ :class:`~cryptography.exceptions.InvalidSignature` exception will be raised.
+
+ If your data is too large to be passed in a single call, you can hash it
+ separately and pass that value using
+ :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`.
+
+ .. doctest::
+
+ >>> chosen_hash = hashes.SHA256()
+ >>> hasher = hashes.Hash(chosen_hash, default_backend())
+ >>> hasher.update(b"data & ")
+ >>> hasher.update(b"more data")
+ >>> digest = hasher.finalize()
+ >>> public_key.verify(
+ ... sig,
+ ... digest,
+ ... ec.ECDSA(utils.Prehashed(chosen_hash))
+ ... )
+
+ .. note::
+ Although in this case the public key was derived from the private one,
+ in a typical setting you will not possess the private key. The
+ `Key loading`_ section explains how to load the public key from other
+ sources.
.. class:: EllipticCurvePrivateNumbers(private_value, public_numbers)
@@ -78,16 +149,21 @@ Elliptic Curve Signature Algorithms
Convert a collection of numbers into a private key suitable for doing
actual cryptographic operations.
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`.
- :returns: A new instance of a :class:`EllipticCurvePrivateKey`
- provider.
+ :returns: A new instance of :class:`EllipticCurvePrivateKey`.
.. class:: EllipticCurvePublicNumbers(x, y, curve)
+ .. warning::
+ The point represented by this object is not validated in any way until
+ :meth:`EllipticCurvePublicNumbers.public_key` is called and may not
+ represent a valid point on the curve. You should not attempt to perform
+ any computations using the values from this class until you have either
+ validated it yourself or called ``public_key()`` successfully.
+
.. versionadded:: 0.5
The collection of integers that make up an EC public key.
@@ -115,148 +191,330 @@ Elliptic Curve Signature Algorithms
Convert a collection of numbers into a public key suitable for doing
actual cryptographic operations.
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`.
+
+ :raises ValueError: Raised if the point is invalid for the curve.
+ :returns: A new instance of :class:`EllipticCurvePublicKey`.
+
+ .. method:: encode_point()
+
+ .. warning::
+
+ This method is deprecated as of version 2.5. Callers should migrate
+ to using
+ :meth:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey.public_bytes`.
+
+ .. versionadded:: 1.1
+
+ Encodes an elliptic curve point to a byte string as described in
+ `SEC 1 v2.0`_ section 2.3.3. This method only supports uncompressed
+ points.
+
+ :return bytes: The encoded point.
+
+ .. classmethod:: from_encoded_point(curve, data)
+
+ .. versionadded:: 1.1
- :returns: A new instance of a :class:`EllipticCurvePublicKey`
- provider.
+ .. note::
+
+ This has been deprecated in favor of
+ :meth:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey.from_encoded_point`
+
+ Decodes a byte string as described in `SEC 1 v2.0`_ section 2.3.3 and
+ returns an :class:`EllipticCurvePublicNumbers`. This method only
+ supports uncompressed points.
+
+ :param curve: An
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurve`
+ instance.
+
+ :param bytes data: The serialized point byte string.
+
+ :returns: An :class:`EllipticCurvePublicNumbers` instance.
+
+ :raises ValueError: Raised on invalid point type or data length.
+
+ :raises TypeError: Raised when curve is not an
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurve`.
+
+Elliptic Curve Key Exchange algorithm
+-------------------------------------
+
+.. class:: ECDH()
+
+ .. versionadded:: 1.1
+
+ The Elliptic Curve Diffie-Hellman Key Exchange algorithm first standardized
+ in NIST publication `800-56A`_, and later in `800-56Ar2`_.
+
+ For most applications the ``shared_key`` should be passed to a key
+ derivation function. This allows mixing of additional information into the
+ key, derivation of multiple keys, and destroys any structure that may be
+ present.
+
+ .. warning::
+
+ This example does not give `forward secrecy`_ and is only provided as a
+ demonstration of the basic Diffie-Hellman construction. For real world
+ applications always use the ephemeral form described after this example.
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> from cryptography.hazmat.primitives.asymmetric import ec
+ >>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
+ >>> # Generate a private key for use in the exchange.
+ >>> server_private_key = ec.generate_private_key(
+ ... ec.SECP384R1(), default_backend()
+ ... )
+ >>> # In a real handshake the peer is a remote client. For this
+ >>> # example we'll generate another local private key though.
+ >>> peer_private_key = ec.generate_private_key(
+ ... ec.SECP384R1(), default_backend()
+ ... )
+ >>> shared_key = server_private_key.exchange(
+ ... ec.ECDH(), peer_private_key.public_key())
+ >>> # Perform key derivation.
+ >>> derived_key = HKDF(
+ ... algorithm=hashes.SHA256(),
+ ... length=32,
+ ... salt=None,
+ ... info=b'handshake data',
+ ... backend=default_backend()
+ ... ).derive(shared_key)
+ >>> # And now we can demonstrate that the handshake performed in the
+ >>> # opposite direction gives the same final value
+ >>> same_shared_key = peer_private_key.exchange(
+ ... ec.ECDH(), server_private_key.public_key())
+ >>> # Perform key derivation.
+ >>> same_derived_key = HKDF(
+ ... algorithm=hashes.SHA256(),
+ ... length=32,
+ ... salt=None,
+ ... info=b'handshake data',
+ ... backend=default_backend()
+ ... ).derive(same_shared_key)
+ >>> derived_key == same_derived_key
+ True
+
+ ECDHE (or EECDH), the ephemeral form of this exchange, is **strongly
+ preferred** over simple ECDH and provides `forward secrecy`_ when used.
+ You must generate a new private key using :func:`generate_private_key` for
+ each :meth:`~EllipticCurvePrivateKey.exchange` when performing an ECDHE key
+ exchange. An example of the ephemeral form:
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> from cryptography.hazmat.primitives.asymmetric import ec
+ >>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
+ >>> # Generate a private key for use in the exchange.
+ >>> private_key = ec.generate_private_key(
+ ... ec.SECP384R1(), default_backend()
+ ... )
+ >>> # In a real handshake the peer_public_key will be received from the
+ >>> # other party. For this example we'll generate another private key
+ >>> # and get a public key from that.
+ >>> peer_public_key = ec.generate_private_key(
+ ... ec.SECP384R1(), default_backend()
+ ... ).public_key()
+ >>> shared_key = private_key.exchange(ec.ECDH(), peer_public_key)
+ >>> # Perform key derivation.
+ >>> derived_key = HKDF(
+ ... algorithm=hashes.SHA256(),
+ ... length=32,
+ ... salt=None,
+ ... info=b'handshake data',
+ ... backend=default_backend()
+ ... ).derive(shared_key)
+ >>> # For the next handshake we MUST generate another private key.
+ >>> private_key_2 = ec.generate_private_key(
+ ... ec.SECP384R1(), default_backend()
+ ... )
+ >>> peer_public_key_2 = ec.generate_private_key(
+ ... ec.SECP384R1(), default_backend()
+ ... ).public_key()
+ >>> shared_key_2 = private_key_2.exchange(ec.ECDH(), peer_public_key_2)
+ >>> derived_key_2 = HKDF(
+ ... algorithm=hashes.SHA256(),
+ ... length=32,
+ ... salt=None,
+ ... info=b'handshake data',
+ ... backend=default_backend()
+ ... ).derive(shared_key_2)
Elliptic Curves
---------------
Elliptic curves provide equivalent security at much smaller key sizes than
-asymmetric cryptography systems such as RSA or DSA. For some operations they
-can also provide higher performance at every security level. According to NIST
-they can have as much as a `64x lower computational cost than DH`_.
+other asymmetric cryptography systems such as RSA or DSA. For many operations
+elliptic curves are also significantly faster; `elliptic curve diffie-hellman
+is faster than diffie-hellman`_.
.. note::
Curves with a size of `less than 224 bits`_ should not be used. You should
- strongly consider using curves of at least 224 bits.
+ strongly consider using curves of at least 224 :term:`bits`.
Generally the NIST prime field ("P") curves are significantly faster than the
other types suggested by NIST at both signing and verifying with ECDSA.
Prime fields also `minimize the number of security concerns for elliptic-curve
-cryptography`_. However there is `some concern`_ that both the prime field and
+cryptography`_. However, there is `some concern`_ that both the prime field and
binary field ("B") NIST curves may have been weakened during their generation.
Currently `cryptography` only supports NIST curves, none of which are
considered "safe" by the `SafeCurves`_ project run by Daniel J. Bernstein and
Tanja Lange.
-All named curves are providers of :class:`EllipticCurve`.
+All named curves are instances of :class:`EllipticCurve`.
-.. class:: SECT571K1
+.. class:: SECP256R1
.. versionadded:: 0.5
- SECG curve ``sect571k1``. Also called NIST K-571.
+ SECG curve ``secp256r1``. Also called NIST P-256.
-.. class:: SECT409K1
+.. class:: SECP384R1
.. versionadded:: 0.5
- SECG curve ``sect409k1``. Also called NIST K-409.
+ SECG curve ``secp384r1``. Also called NIST P-384.
-.. class:: SECT283K1
+.. class:: SECP521R1
.. versionadded:: 0.5
- SECG curve ``sect283k1``. Also called NIST K-283.
+ SECG curve ``secp521r1``. Also called NIST P-521.
-.. class:: SECT233K1
+.. class:: SECP224R1
.. versionadded:: 0.5
- SECG curve ``sect233k1``. Also called NIST K-233.
+ SECG curve ``secp224r1``. Also called NIST P-224.
-.. class:: SECT163K1
+.. class:: SECP192R1
.. versionadded:: 0.5
- SECG curve ``sect163k1``. Also called NIST K-163.
+ SECG curve ``secp192r1``. Also called NIST P-192.
-.. class:: SECT571R1
+.. class:: SECP256K1
- .. versionadded:: 0.5
+ .. versionadded:: 0.9
- SECG curve ``sect571r1``. Also called NIST B-571.
+ SECG curve ``secp256k1``.
-.. class:: SECT409R1
+.. class:: BrainpoolP256R1
+
+ .. versionadded:: 2.2
+
+ Brainpool curve specified in :rfc:`5639`. These curves are discouraged
+ for new systems.
+
+.. class:: BrainpoolP384R1
+
+ .. versionadded:: 2.2
+
+ Brainpool curve specified in :rfc:`5639`. These curves are discouraged
+ for new systems.
+
+.. class:: BrainpoolP512R1
+
+ .. versionadded:: 2.2
+
+ Brainpool curve specified in :rfc:`5639`. These curves are discouraged
+ for new systems.
+
+.. class:: SECT571K1
.. versionadded:: 0.5
- SECG curve ``sect409r1``. Also called NIST B-409.
+ SECG curve ``sect571k1``. Also called NIST K-571. These binary curves are
+ discouraged for new systems.
-.. class:: SECT283R1
+.. class:: SECT409K1
.. versionadded:: 0.5
- SECG curve ``sect283r1``. Also called NIST B-283.
+ SECG curve ``sect409k1``. Also called NIST K-409. These binary curves are
+ discouraged for new systems.
-.. class:: SECT233R1
+.. class:: SECT283K1
.. versionadded:: 0.5
- SECG curve ``sect233r1``. Also called NIST B-233.
+ SECG curve ``sect283k1``. Also called NIST K-283. These binary curves are
+ discouraged for new systems.
-.. class:: SECT163R2
+.. class:: SECT233K1
.. versionadded:: 0.5
- SECG curve ``sect163r2``. Also called NIST B-163.
+ SECG curve ``sect233k1``. Also called NIST K-233. These binary curves are
+ discouraged for new systems.
-.. class:: SECP521R1
+.. class:: SECT163K1
.. versionadded:: 0.5
- SECG curve ``secp521r1``. Also called NIST P-521.
+ SECG curve ``sect163k1``. Also called NIST K-163. These binary curves are
+ discouraged for new systems.
-.. class:: SECP384R1
+.. class:: SECT571R1
.. versionadded:: 0.5
- SECG curve ``secp384r1``. Also called NIST P-384.
+ SECG curve ``sect571r1``. Also called NIST B-571. These binary curves are
+ discouraged for new systems.
-.. class:: SECP256R1
+.. class:: SECT409R1
.. versionadded:: 0.5
- SECG curve ``secp256r1``. Also called NIST P-256.
+ SECG curve ``sect409r1``. Also called NIST B-409. These binary curves are
+ discouraged for new systems.
-.. class:: SECT224R1
+.. class:: SECT283R1
.. versionadded:: 0.5
- SECG curve ``secp224r1``. Also called NIST P-224.
+ SECG curve ``sect283r1``. Also called NIST B-283. These binary curves are
+ discouraged for new systems.
-.. class:: SECP192R1
+.. class:: SECT233R1
.. versionadded:: 0.5
- SECG curve ``secp192r1``. Also called NIST P-192.
+ SECG curve ``sect233r1``. Also called NIST B-233. These binary curves are
+ discouraged for new systems.
-.. class:: SECP256K1
+.. class:: SECT163R2
+
+ .. versionadded:: 0.5
+
+ SECG curve ``sect163r2``. Also called NIST B-163. These binary curves are
+ discouraged for new systems.
- .. versionadded:: 0.9
- SECG curve ``secp256k1``.
Key Interfaces
@@ -270,7 +528,7 @@ Key Interfaces
.. attribute:: name
- :type: string
+ :type: str
The name of the curve. Usually the name used for the ASN.1 OID such as
``secp256k1``.
@@ -279,18 +537,23 @@ Key Interfaces
:type: int
- The bit length of the curve's base point.
+ Size (in :term:`bits`) of a secret scalar for the curve (as generated
+ by :func:`generate_private_key`).
.. class:: EllipticCurveSignatureAlgorithm
.. versionadded:: 0.5
+ .. versionchanged:: 1.6
+ :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`
+ can now be used as an ``algorithm``.
A signature algorithm for use with elliptic curve keys.
.. attribute:: algorithm
- :type: :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+ :type: :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`
The digest algorithm to be used with the signature scheme.
@@ -300,19 +563,30 @@ Key Interfaces
.. versionadded:: 0.5
An elliptic curve private key for use with an algorithm such as `ECDSA`_ or
- `EdDSA`_.
+ `EdDSA`_. An elliptic curve private key that is not an
+ :term:`opaque key` also implements
+ :class:`EllipticCurvePrivateKeyWithSerialization` to provide serialization
+ methods.
+
+ .. method:: exchange(algorithm, peer_public_key)
- .. method:: signer(signature_algorithm)
+ .. versionadded:: 1.1
- Sign data which can be verified later by others using the public key.
- The signature is formatted as DER-encoded bytes, as specified in
- :rfc:`6979`.
+ Performs a key exchange operation using the provided algorithm with
+ the peer's public key.
- :param signature_algorithm: An instance of a
- :class:`EllipticCurveSignatureAlgorithm` provider.
+ For most applications the ``shared_key`` should be passed to a key
+ derivation function. This allows mixing of additional information into the
+ key, derivation of multiple keys, and destroys any structure that may be
+ present.
- :returns:
- :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricSignatureContext`
+ :param algorithm: The key exchange algorithm, currently only
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.ECDH` is
+ supported.
+ :param EllipticCurvePublicKey peer_public_key: The public key for the
+ peer.
+
+ :returns bytes: A shared key.
.. method:: public_key()
@@ -320,25 +594,46 @@ Key Interfaces
The EllipticCurvePublicKey object for this private key.
+ .. method:: sign(data, signature_algorithm)
-.. class:: EllipticCurvePrivateKeyWithNumbers
+ .. versionadded:: 1.5
- .. versionadded:: 0.6
+ Sign one block of data which can be verified later by others using the
+ public key.
- Extends :class:`EllipticCurvePrivateKey`.
+ :param bytes data: The message string to sign.
- .. method:: private_numbers()
+ :param signature_algorithm: An instance of
+ :class:`EllipticCurveSignatureAlgorithm`, such as :class:`ECDSA`.
- Create a :class:`EllipticCurvePrivateNumbers` object.
+ :return bytes: The signature as a ``bytes`` object, whose contents are
+ DER encoded as described in :rfc:`3279`. This can be decoded using
+ :func:`~cryptography.hazmat.primitives.asymmetric.utils.decode_dss_signature`,
+ which returns the decoded tuple ``(r, s)``.
- :returns: An :class:`EllipticCurvePrivateNumbers` instance.
+ .. attribute:: curve
+
+ :type: :class:`EllipticCurve`
+
+ The EllipticCurve that this key is on.
+
+ .. attribute:: key_size
+
+ .. versionadded:: 1.9
+
+ :type: int
+
+ Size (in :term:`bits`) of a secret scalar for the curve (as generated
+ by :func:`generate_private_key`).
.. class:: EllipticCurvePrivateKeyWithSerialization
.. versionadded:: 0.8
- Extends :class:`EllipticCurvePrivateKey`.
+ This interface contains additional methods relating to serialization.
+ Any object with this interface also has all the methods from
+ :class:`EllipticCurvePrivateKey`.
.. method:: private_numbers()
@@ -379,76 +674,300 @@ Key Interfaces
An elliptic curve public key.
- .. method:: verifier(signature, signature_algorithm)
+ .. attribute:: curve
- Verify data was signed by the private key associated with this public
- key.
+ :type: :class:`EllipticCurve`
- :param bytes signature: The signature to verify. DER encoded as
- specified in :rfc:`6979`.
+ The elliptic curve for this key.
- :param signature_algorithm: An instance of a
- :class:`EllipticCurveSignatureAlgorithm` provider.
+ .. method:: public_numbers()
- :returns:
- :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricVerificationContext`
+ Create a :class:`EllipticCurvePublicNumbers` object.
- .. attribute:: curve
+ :returns: An :class:`EllipticCurvePublicNumbers` instance.
- :type: :class:`EllipticCurve`
+ .. method:: public_bytes(encoding, format)
- The elliptic curve for this key.
+ Allows serialization of the key data to bytes. When encoding the public
+ key the encodings (
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`,
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`) and
+ format (
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`)
+ are chosen to define the exact serialization. When encoding the point
+ the encoding
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.X962`
+ should be used with the formats (
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.UncompressedPoint`
+ or
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.CompressedPoint`
+ ).
+ :param encoding: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
-.. class:: EllipticCurvePublicKeyWithNumbers
+ :param format: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.PublicFormat` enum.
- .. versionadded:: 0.6
+ :return bytes: Serialized data.
- Extends :class:`EllipticCurvePublicKey`.
+ .. method:: verify(signature, data, signature_algorithm)
- .. method:: public_numbers()
+ .. versionadded:: 1.5
- Create a :class:`EllipticCurvePublicNumbers` object.
+ Verify one block of data was signed by the private key associated
+ with this public key.
- :returns: An :class:`EllipticCurvePublicNumbers` instance.
+ :param bytes signature: The DER-encoded signature to verify.
+ A raw signature may be DER-encoded by splitting it into the ``r``
+ and ``s`` components and passing them into
+ :func:`~cryptography.hazmat.primitives.asymmetric.utils.encode_dss_signature`.
+
+ :param bytes data: The message string that was signed.
+
+ :param signature_algorithm: An instance of
+ :class:`EllipticCurveSignatureAlgorithm`.
+
+ :raises cryptography.exceptions.InvalidSignature: If the signature does
+ not validate.
+
+ .. attribute:: key_size
+
+ .. versionadded:: 1.9
+
+ :type: int
+
+ Size (in :term:`bits`) of a secret scalar for the curve (as generated
+ by :func:`generate_private_key`).
+
+ .. classmethod:: from_encoded_point(curve, data)
+
+ .. versionadded:: 2.5
+
+ Decodes a byte string as described in `SEC 1 v2.0`_ section 2.3.3 and
+ returns an :class:`EllipticCurvePublicKey`. This class method supports
+ compressed points.
+
+ :param curve: An
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurve`
+ instance.
+
+ :param bytes data: The serialized point byte string.
+
+ :returns: An :class:`EllipticCurvePublicKey` instance.
+
+ :raises ValueError: Raised when an invalid point is supplied.
+
+ :raises TypeError: Raised when curve is not an
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurve`.
.. class:: EllipticCurvePublicKeyWithSerialization
.. versionadded:: 0.6
- Extends :class:`EllipticCurvePublicKey`.
+ Alias for :class:`EllipticCurvePublicKey`.
- .. method:: public_numbers()
- Create a :class:`EllipticCurvePublicNumbers` object.
- :returns: An :class:`EllipticCurvePublicNumbers` instance.
+Serialization
+~~~~~~~~~~~~~
- .. method:: public_bytes(encoding, format)
+This sample demonstrates how to generate a private key and serialize it.
- Allows serialization of the key to bytes. Encoding (
- :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM` or
- :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`) and
- format (
- :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`)
- are chosen to define the exact serialization.
- :param encoding: A value from the
- :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
+.. doctest::
- :param format: A value from the
- :class:`~cryptography.hazmat.primitives.serialization.PublicFormat` enum.
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> from cryptography.hazmat.primitives import serialization
+ >>> from cryptography.hazmat.primitives.asymmetric import ec
- :return bytes: Serialized key.
+ >>> private_key = ec.generate_private_key(ec.SECP384R1(), default_backend())
+
+ >>> serialized_private = private_key.private_bytes(
+ ... encoding=serialization.Encoding.PEM,
+ ... format=serialization.PrivateFormat.PKCS8,
+ ... encryption_algorithm=serialization.BestAvailableEncryption(b'testpassword')
+ ... )
+ >>> serialized_private.splitlines()[0]
+ b'-----BEGIN ENCRYPTED PRIVATE KEY-----'
+
+You can also serialize the key without a password, by relying on
+:class:`~cryptography.hazmat.primitives.serialization.NoEncryption`.
+
+The public key is serialized as follows:
+
+
+.. doctest::
+
+ >>> public_key = private_key.public_key()
+ >>> serialized_public = public_key.public_bytes(
+ ... encoding=serialization.Encoding.PEM,
+ ... format=serialization.PublicFormat.SubjectPublicKeyInfo
+ ... )
+ >>> serialized_public.splitlines()[0]
+ b'-----BEGIN PUBLIC KEY-----'
+
+This is the part that you would normally share with the rest of the world.
+
+
+Key loading
+~~~~~~~~~~~
+
+This extends the sample in the previous section, assuming that the variables
+``serialized_private`` and ``serialized_public`` contain the respective keys
+in PEM format.
+
+.. doctest::
+
+ >>> loaded_public_key = serialization.load_pem_public_key(
+ ... serialized_public,
+ ... backend=default_backend()
+ ... )
+
+ >>> loaded_private_key = serialization.load_pem_private_key(
+ ... serialized_private,
+ ... # or password=None, if in plain text
+ ... password=b'testpassword',
+ ... backend=default_backend()
+ ... )
+
+
+Elliptic Curve Object Identifiers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. class:: EllipticCurveOID
+
+ .. versionadded:: 2.4
+
+ .. attribute:: SECP192R1
+
+ Corresponds to the dotted string ``"1.2.840.10045.3.1.1"``.
+
+ .. attribute:: SECP224R1
+
+ Corresponds to the dotted string ``"1.3.132.0.33"``.
+
+ .. attribute:: SECP256K1
+
+ Corresponds to the dotted string ``"1.3.132.0.10"``.
+
+ .. attribute:: SECP256R1
+
+ Corresponds to the dotted string ``"1.2.840.10045.3.1.7"``.
+
+ .. attribute:: SECP384R1
+
+ Corresponds to the dotted string ``"1.3.132.0.34"``.
+
+ .. attribute:: SECP521R1
+
+ Corresponds to the dotted string ``"1.3.132.0.35"``.
+
+ .. attribute:: BRAINPOOLP256R1
+
+ .. versionadded:: 2.5
+
+ Corresponds to the dotted string ``"1.3.36.3.3.2.8.1.1.7"``.
+
+ .. attribute:: BRAINPOOLP384R1
+
+ .. versionadded:: 2.5
+
+ Corresponds to the dotted string ``"1.3.36.3.3.2.8.1.1.11"``.
+
+ .. attribute:: BRAINPOOLP512R1
+
+ .. versionadded:: 2.5
+
+ Corresponds to the dotted string ``"1.3.36.3.3.2.8.1.1.13"``.
+
+ .. attribute:: SECT163K1
+
+ .. versionadded:: 2.5
+
+ Corresponds to the dotted string ``"1.3.132.0.1"``.
+
+ .. attribute:: SECT163R2
+
+ .. versionadded:: 2.5
+
+ Corresponds to the dotted string ``"1.3.132.0.15"``.
+
+ .. attribute:: SECT233K1
+
+ .. versionadded:: 2.5
+
+ Corresponds to the dotted string ``"1.3.132.0.26"``.
+
+ .. attribute:: SECT233R1
+
+ .. versionadded:: 2.5
+
+ Corresponds to the dotted string ``"1.3.132.0.27"``.
+
+ .. attribute:: SECT283K1
+
+ .. versionadded:: 2.5
+
+ Corresponds to the dotted string ``"1.3.132.0.16"``.
+
+ .. attribute:: SECT283R1
+
+ .. versionadded:: 2.5
+
+ Corresponds to the dotted string ``"1.3.132.0.17"``.
+
+ .. attribute:: SECT409K1
+
+ .. versionadded:: 2.5
+
+ Corresponds to the dotted string ``"1.3.132.0.36"``.
+
+ .. attribute:: SECT409R1
+
+ .. versionadded:: 2.5
+
+ Corresponds to the dotted string ``"1.3.132.0.37"``.
+
+ .. attribute:: SECT571K1
+
+ .. versionadded:: 2.5
+
+ Corresponds to the dotted string ``"1.3.132.0.38"``.
+
+ .. attribute:: SECT571R1
+
+ .. versionadded:: 2.5
+
+ Corresponds to the dotted string ``"1.3.132.0.39"``.
+
+.. function:: get_curve_for_oid(oid)
+
+ .. versionadded:: 2.6
+
+ A function that takes an :class:`~cryptography.x509.ObjectIdentifier`
+ and returns the associated elliptic curve class.
+
+ :param oid: An instance of
+ :class:`~cryptography.x509.ObjectIdentifier`.
+
+ :returns: The matching elliptic curve class. The returned class conforms
+ to the :class:`EllipticCurve` interface.
+ :raises LookupError: Raised if no elliptic curve is found that matches
+ the provided object identifier.
-.. _`FIPS 186-3`: http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf
-.. _`FIPS 186-4`: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
+.. _`FIPS 186-3`: https://csrc.nist.gov/csrc/media/publications/fips/186/3/archive/2009-06-25/documents/fips_186-3.pdf
+.. _`FIPS 186-4`: https://csrc.nist.gov/publications/detail/fips/186/4/final
+.. _`800-56A`: https://csrc.nist.gov/publications/detail/sp/800-56a/revised/archive/2007-03-14
+.. _`800-56Ar2`: https://csrc.nist.gov/publications/detail/sp/800-56a/rev-2/final
.. _`some concern`: https://crypto.stackexchange.com/questions/10263/should-we-trust-the-nist-recommended-ecc-parameters
-.. _`less than 224 bits`: http://www.ecrypt.eu.org/ecrypt2/documents/D.SPA.20.pdf
-.. _`64x lower computational cost than DH`: https://www.nsa.gov/business/programs/elliptic_curve.shtml
-.. _`minimize the number of security concerns for elliptic-curve cryptography`: http://cr.yp.to/ecdh/curve25519-20060209.pdf
-.. _`SafeCurves`: http://safecurves.cr.yp.to/
+.. _`less than 224 bits`: https://www.cosic.esat.kuleuven.be/ecrypt/ecrypt2/documents/D.SPA.20.pdf
+.. _`elliptic curve diffie-hellman is faster than diffie-hellman`: https://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`: 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
+.. _`SEC 1 v2.0`: https://www.secg.org/sec1-v2.pdf
diff --git a/docs/hazmat/primitives/asymmetric/ed25519.rst b/docs/hazmat/primitives/asymmetric/ed25519.rst
new file mode 100644
index 00000000..f9e007c5
--- /dev/null
+++ b/docs/hazmat/primitives/asymmetric/ed25519.rst
@@ -0,0 +1,166 @@
+.. hazmat::
+
+Ed25519 signing
+===============
+
+.. currentmodule:: cryptography.hazmat.primitives.asymmetric.ed25519
+
+
+Ed25519 is an elliptic curve signing algorithm using `EdDSA`_ and
+`Curve25519`_. If you do not have legacy interoperability concerns then you
+should strongly consider using this signature algorithm.
+
+
+Signing & Verification
+~~~~~~~~~~~~~~~~~~~~~~
+
+.. doctest::
+
+ >>> from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
+ >>> private_key = Ed25519PrivateKey.generate()
+ >>> signature = private_key.sign(b"my authenticated message")
+ >>> public_key = private_key.public_key()
+ >>> # Raises InvalidSignature if verification fails
+ >>> public_key.verify(signature, b"my authenticated message")
+
+Key interfaces
+~~~~~~~~~~~~~~
+
+.. class:: Ed25519PrivateKey
+
+ .. versionadded:: 2.6
+
+ .. classmethod:: generate()
+
+ Generate an Ed25519 private key.
+
+ :returns: :class:`Ed25519PrivateKey`
+
+ .. classmethod:: from_private_bytes(data)
+
+ :param data: 32 byte private key.
+ :type data: :term:`bytes-like`
+
+ :returns: :class:`Ed25519PrivateKey`
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.primitives import serialization
+ >>> from cryptography.hazmat.primitives.asymmetric import ed25519
+ >>> private_key = ed25519.Ed25519PrivateKey.generate()
+ >>> private_bytes = private_key.private_bytes(
+ ... encoding=serialization.Encoding.Raw,
+ ... format=serialization.PrivateFormat.Raw,
+ ... encryption_algorithm=serialization.NoEncryption()
+ ... )
+ >>> loaded_private_key = ed25519.Ed25519PrivateKey.from_private_bytes(private_bytes)
+
+
+ .. method:: public_key()
+
+ :returns: :class:`Ed25519PublicKey`
+
+ .. method:: sign(data)
+
+ :param bytes data: The data to sign.
+
+ :returns bytes: The 64 byte signature.
+
+ .. method:: private_bytes(encoding, format, encryption_algorithm)
+
+ Allows serialization of the key to bytes. Encoding (
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`,
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`, or
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`) and
+ format (
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`
+ or
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.Raw`
+ ) are chosen to define the exact serialization.
+
+ :param encoding: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
+
+ :param format: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.PrivateFormat`
+ enum. If the ``encoding`` is
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`
+ then ``format`` must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.Raw`
+ , otherwise it must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`.
+
+ :param encryption_algorithm: An instance of an object conforming to the
+ :class:`~cryptography.hazmat.primitives.serialization.KeySerializationEncryption`
+ interface.
+
+ :return bytes: Serialized key.
+
+.. class:: Ed25519PublicKey
+
+ .. versionadded:: 2.6
+
+ .. classmethod:: from_public_bytes(data)
+
+ :param bytes data: 32 byte public key.
+
+ :returns: :class:`Ed25519PublicKey`
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.primitives import serialization
+ >>> from cryptography.hazmat.primitives.asymmetric import ed25519
+ >>> private_key = ed25519.Ed25519PrivateKey.generate()
+ >>> public_key = private_key.public_key()
+ >>> public_bytes = public_key.public_bytes(
+ ... encoding=serialization.Encoding.Raw,
+ ... format=serialization.PublicFormat.Raw
+ ... )
+ >>> loaded_public_key = ed25519.Ed25519PublicKey.from_public_bytes(public_bytes)
+
+ .. method:: public_bytes(encoding, format)
+
+ Allows serialization of the key to bytes. Encoding (
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`,
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`,
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.OpenSSH`,
+ or
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`) and
+ format (
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`,
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.OpenSSH`
+ , or
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.Raw`
+ ) are chosen to define the exact serialization.
+
+ :param encoding: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
+
+ :param format: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.PublicFormat`
+ enum. If the ``encoding`` is
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`
+ then ``format`` must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.Raw`.
+ If ``encoding`` is
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.OpenSSH`
+ then ``format`` must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.OpenSSH`.
+ In all other cases ``format`` must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`.
+
+ :returns bytes: The public key bytes.
+
+ .. method:: verify(signature, data)
+
+ :param bytes signature: The signature to verify.
+
+ :param bytes data: The data to verify.
+
+ :raises cryptography.exceptions.InvalidSignature: Raised when the
+ signature cannot be verified.
+
+
+
+.. _`EdDSA`: https://en.wikipedia.org/wiki/EdDSA
+.. _`Curve25519`: https://en.wikipedia.org/wiki/Curve25519
diff --git a/docs/hazmat/primitives/asymmetric/ed448.rst b/docs/hazmat/primitives/asymmetric/ed448.rst
new file mode 100644
index 00000000..fb79dcb6
--- /dev/null
+++ b/docs/hazmat/primitives/asymmetric/ed448.rst
@@ -0,0 +1,131 @@
+.. hazmat::
+
+Ed448 signing
+=============
+
+.. currentmodule:: cryptography.hazmat.primitives.asymmetric.ed448
+
+
+Ed448 is an elliptic curve signing algorithm using `EdDSA`_.
+
+
+Signing & Verification
+~~~~~~~~~~~~~~~~~~~~~~
+
+.. doctest::
+
+ >>> from cryptography.hazmat.primitives.asymmetric.ed448 import Ed448PrivateKey
+ >>> private_key = Ed448PrivateKey.generate()
+ >>> signature = private_key.sign(b"my authenticated message")
+ >>> public_key = private_key.public_key()
+ >>> # Raises InvalidSignature if verification fails
+ >>> public_key.verify(signature, b"my authenticated message")
+
+Key interfaces
+~~~~~~~~~~~~~~
+
+.. class:: Ed448PrivateKey
+
+ .. versionadded:: 2.6
+
+ .. classmethod:: generate()
+
+ Generate an Ed448 private key.
+
+ :returns: :class:`Ed448PrivateKey`
+
+ .. classmethod:: from_private_bytes(data)
+
+ :param data: 57 byte private key.
+ :type data: :term:`bytes-like`
+
+ :returns: :class:`Ed448PrivateKey`
+
+ .. method:: public_key()
+
+ :returns: :class:`Ed448PublicKey`
+
+ .. method:: sign(data)
+
+ :param bytes data: The data to sign.
+
+ :returns bytes: The 114 byte signature.
+
+ .. method:: private_bytes(encoding, format, encryption_algorithm)
+
+ Allows serialization of the key to bytes. Encoding (
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`,
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`, or
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`) and
+ format (
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`
+ or
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.Raw`
+ ) are chosen to define the exact serialization.
+
+ :param encoding: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
+
+ :param format: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.PrivateFormat`
+ enum. If the ``encoding`` is
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`
+ then ``format`` must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.Raw`
+ , otherwise it must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`.
+
+ :param encryption_algorithm: An instance of an object conforming to the
+ :class:`~cryptography.hazmat.primitives.serialization.KeySerializationEncryption`
+ interface.
+
+ :return bytes: Serialized key.
+
+.. class:: Ed448PublicKey
+
+ .. versionadded:: 2.6
+
+ .. classmethod:: from_public_bytes(data)
+
+ :param bytes data: 57 byte public key.
+
+ :returns: :class:`Ed448PublicKey`
+
+ .. method:: public_bytes(encoding, format)
+
+ Allows serialization of the key to bytes. Encoding (
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`,
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`, or
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`) and
+ format (
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`
+ or
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.Raw`
+ ) are chosen to define the exact serialization.
+
+ :param encoding: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
+
+ :param format: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.PublicFormat`
+ enum. If the ``encoding`` is
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`
+ then ``format`` must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.Raw`
+ , otherwise it must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`.
+
+ :returns bytes: The public key bytes.
+
+ .. method:: verify(signature, data)
+
+ :param bytes signature: The signature to verify.
+
+ :param bytes data: The data to verify.
+
+ :raises cryptography.exceptions.InvalidSignature: Raised when the
+ signature cannot be verified.
+
+
+
+.. _`EdDSA`: https://en.wikipedia.org/wiki/EdDSA
diff --git a/docs/hazmat/primitives/asymmetric/index.rst b/docs/hazmat/primitives/asymmetric/index.rst
index 4242a0bd..c27e1781 100644
--- a/docs/hazmat/primitives/asymmetric/index.rst
+++ b/docs/hazmat/primitives/asymmetric/index.rst
@@ -20,18 +20,18 @@ symmetric encryption. Someone with the public key is able to encrypt a message,
providing confidentiality, and then only the person in possession of the
private key is able to decrypt it.
-Cryptography supports three different sets of asymmetric algorithms: RSA, DSA,
-and Elliptic Curve.
-
.. toctree::
:maxdepth: 1
- dsa
+ ed25519
+ x25519
+ ed448
+ x448
ec
rsa
dh
+ dsa
serialization
- interfaces
utils
diff --git a/docs/hazmat/primitives/asymmetric/interfaces.rst b/docs/hazmat/primitives/asymmetric/interfaces.rst
deleted file mode 100644
index c4f176c6..00000000
--- a/docs/hazmat/primitives/asymmetric/interfaces.rst
+++ /dev/null
@@ -1,32 +0,0 @@
-.. hazmat::
-
-.. module:: cryptography.hazmat.primitives.asymmetric
-
-Signature Interfaces
-====================
-
-.. class:: AsymmetricSignatureContext
-
- .. versionadded:: 0.2
-
- .. method:: update(data)
-
- :param bytes data: The data you want to sign.
-
- .. method:: finalize()
-
- :return bytes signature: The signature.
-
-
-.. class:: AsymmetricVerificationContext
-
- .. versionadded:: 0.2
-
- .. method:: update(data)
-
- :param bytes data: The data you wish to verify using the signature.
-
- .. method:: verify()
-
- :raises cryptography.exceptions.InvalidSignature: If the signature does
- not validate.
diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst
index 3b5b677b..dab90964 100644
--- a/docs/hazmat/primitives/asymmetric/rsa.rst
+++ b/docs/hazmat/primitives/asymmetric/rsa.rst
@@ -19,11 +19,12 @@ mathematical properties`_.
.. versionadded:: 0.5
Generates a new RSA private key using the provided ``backend``.
- ``key_size`` describes how many bits long the key should be, larger keys
- provide more security, currently ``1024`` and below are considered
- breakable, and ``2048`` or ``4096`` are reasonable default key sizes for
+ ``key_size`` describes how many :term:`bits` long the key should be. Larger
+ keys provide more security; currently ``1024`` and below are considered
+ breakable while ``2048`` or ``4096`` are reasonable default key sizes for
new keys. The ``public_exponent`` indicates what one mathematical property
- of the key generation will be, ``65537`` should almost always be used.
+ of the key generation will be. Unless you have a specific reason to do
+ otherwise, you should always `use 65537`_.
.. doctest::
@@ -39,12 +40,12 @@ mathematical properties`_.
Usually one of the small Fermat primes 3, 5, 17, 257, 65537. If in
doubt you should `use 65537`_.
- :param int key_size: The length of the modulus in bits. For keys
+ :param int key_size: The length of the modulus in :term:`bits`. For keys
generated in 2015 it is strongly recommended to be
`at least 2048`_ (See page 41). It must not be less than 512.
Some backends may have additional limitations.
- :param backend: A backend which provides
+ :param backend: A backend which implements
:class:`~cryptography.hazmat.backends.interfaces.RSABackend`.
:return: An instance of
@@ -63,6 +64,7 @@ markers), you can load it:
.. code-block:: pycon
+ >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import serialization
>>> with open("path/to/key.pem", "rb") as key_file:
@@ -98,7 +100,7 @@ to serialize the key.
... encryption_algorithm=serialization.BestAvailableEncryption(b'mypassword')
... )
>>> pem.splitlines()[0]
- '-----BEGIN ENCRYPTED PRIVATE KEY-----'
+ b'-----BEGIN ENCRYPTED PRIVATE KEY-----'
It is also possible to serialize without encryption using
:class:`~cryptography.hazmat.primitives.serialization.NoEncryption`.
@@ -111,12 +113,10 @@ It is also possible to serialize without encryption using
... encryption_algorithm=serialization.NoEncryption()
... )
>>> pem.splitlines()[0]
- '-----BEGIN RSA PRIVATE KEY-----'
+ b'-----BEGIN RSA PRIVATE KEY-----'
-Similarly, if your public key implements
-:class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKeyWithSerialization`
-interface you can use
-:meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKeyWithSerialization.public_bytes`
+For public keys you can use
+:meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey.public_bytes`
to serialize the key.
.. doctest::
@@ -128,7 +128,7 @@ to serialize the key.
... format=serialization.PublicFormat.SubjectPublicKeyInfo
... )
>>> pem.splitlines()[0]
- '-----BEGIN PUBLIC KEY-----'
+ b'-----BEGIN PUBLIC KEY-----'
Signing
~~~~~~~
@@ -143,17 +143,15 @@ secure hash function and padding:
>>> from cryptography.hazmat.primitives import hashes
>>> from cryptography.hazmat.primitives.asymmetric import padding
-
- >>> signer = private_key.signer(
+ >>> message = b"A message I want to sign"
+ >>> signature = private_key.sign(
+ ... message,
... padding.PSS(
... mgf=padding.MGF1(hashes.SHA256()),
... salt_length=padding.PSS.MAX_LENGTH
... ),
... hashes.SHA256()
... )
- >>> message = b"A message I want to sign"
- >>> signer.update(message)
- >>> signature = signer.finalize()
Valid paddings for signatures are
:class:`~cryptography.hazmat.primitives.asymmetric.padding.PSS` and
@@ -161,31 +159,78 @@ Valid paddings for signatures are
is the recommended choice for any new protocols or applications, ``PKCS1v15``
should only be used to support legacy protocols.
+If your data is too large to be passed in a single call, you can hash it
+separately and pass that value using
+:class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`.
+
+.. doctest::
+
+ >>> from cryptography.hazmat.primitives.asymmetric import utils
+ >>> chosen_hash = hashes.SHA256()
+ >>> hasher = hashes.Hash(chosen_hash, default_backend())
+ >>> hasher.update(b"data & ")
+ >>> hasher.update(b"more data")
+ >>> digest = hasher.finalize()
+ >>> sig = private_key.sign(
+ ... digest,
+ ... padding.PSS(
+ ... mgf=padding.MGF1(hashes.SHA256()),
+ ... salt_length=padding.PSS.MAX_LENGTH
+ ... ),
+ ... utils.Prehashed(chosen_hash)
+ ... )
+
Verification
~~~~~~~~~~~~
The previous section describes what to do if you have a private key and want to
-sign something. If you have a public key, a message, and a signature, you can
-check that the public key genuinely was used to sign that specific message. You
-also need to know which signing algorithm was used:
+sign something. If you have a public key, a message, a signature, and the
+signing algorithm that was used you can check that the private key associated
+with a given public key was used to sign that specific message. You can obtain
+a public key to use in verification using
+:func:`~cryptography.hazmat.primitives.serialization.load_pem_public_key`,
+:func:`~cryptography.hazmat.primitives.serialization.load_der_public_key`,
+:meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicNumbers.public_key`
+, or
+:meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey.public_key`.
.. doctest::
>>> public_key = private_key.public_key()
- >>> verifier = public_key.verifier(
+ >>> public_key.verify(
... signature,
+ ... message,
... padding.PSS(
... mgf=padding.MGF1(hashes.SHA256()),
... salt_length=padding.PSS.MAX_LENGTH
... ),
... hashes.SHA256()
... )
- >>> verifier.update(message)
- >>> verifier.verify()
If the signature does not match, ``verify()`` will raise an
:class:`~cryptography.exceptions.InvalidSignature` exception.
+If your data is too large to be passed in a single call, you can hash it
+separately and pass that value using
+:class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`.
+
+.. doctest::
+
+ >>> chosen_hash = hashes.SHA256()
+ >>> hasher = hashes.Hash(chosen_hash, default_backend())
+ >>> hasher.update(b"data & ")
+ >>> hasher.update(b"more data")
+ >>> digest = hasher.finalize()
+ >>> public_key.verify(
+ ... sig,
+ ... digest,
+ ... padding.PSS(
+ ... mgf=padding.MGF1(hashes.SHA256()),
+ ... salt_length=padding.PSS.MAX_LENGTH
+ ... ),
+ ... utils.Prehashed(chosen_hash)
+ ... )
+
Encryption
~~~~~~~~~~
@@ -202,8 +247,8 @@ options. Here's an example using a secure padding and hash function:
>>> ciphertext = public_key.encrypt(
... message,
... padding.OAEP(
- ... mgf=padding.MGF1(algorithm=hashes.SHA1()),
- ... algorithm=hashes.SHA1(),
+ ... mgf=padding.MGF1(algorithm=hashes.SHA256()),
+ ... algorithm=hashes.SHA256(),
... label=None
... )
... )
@@ -225,8 +270,8 @@ Once you have an encrypted message, it can be decrypted using the private key:
>>> plaintext = private_key.decrypt(
... ciphertext,
... padding.OAEP(
- ... mgf=padding.MGF1(algorithm=hashes.SHA1()),
- ... algorithm=hashes.SHA1(),
+ ... mgf=padding.MGF1(algorithm=hashes.SHA256()),
+ ... algorithm=hashes.SHA256(),
... label=None
... )
... )
@@ -267,7 +312,7 @@ Padding
Pass this attribute to ``salt_length`` to get the maximum salt length
available.
-.. class:: OAEP(mgf, label)
+.. class:: OAEP(mgf, algorithm, label)
.. versionadded:: 0.4
@@ -279,6 +324,9 @@ Padding
:param mgf: A mask generation function object. At this time the only
supported MGF is :class:`MGF1`.
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
+
:param bytes label: A label to apply. This is a rarely used field and
should typically be set to ``None`` or ``b""``, which are equivalent.
@@ -294,6 +342,20 @@ Padding
:class:`OAEP` should be preferred for encryption and :class:`PSS` should be
preferred for signatures.
+
+.. function:: calculate_max_pss_salt_length(key, hash_algorithm)
+
+ .. versionadded:: 1.5
+
+ :param key: An RSA public or private key.
+ :param hash_algorithm: A
+ :class:`cryptography.hazmat.primitives.hashes.HashAlgorithm`.
+ :returns int: The computed salt length.
+
+ Computes the length of the salt that :class:`PSS` will use if
+ :data:`PSS.MAX_LENGTH` is used.
+
+
Mask generation functions
-------------------------
@@ -305,11 +367,10 @@ Mask generation functions
Removed the deprecated ``salt_length`` parameter.
MGF1 (Mask Generation Function 1) is used as the mask generation function
- in :class:`PSS` padding. It takes a hash algorithm and a salt length.
+ in :class:`PSS` and :class:`OAEP` padding. It takes a hash algorithm.
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- provider.
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
Numbers
~~~~~~~
@@ -340,13 +401,11 @@ is unavailable.
.. method:: public_key(backend)
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.RSABackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.RSABackend`.
- :returns: A new instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`
- provider.
+ :returns: A new instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`.
.. class:: RSAPrivateNumbers(p, q, d, dmp1, dmq1, iqmp, public_numbers)
@@ -409,13 +468,11 @@ is unavailable.
.. method:: private_key(backend)
- :param backend: A new instance of a
- :class:`~cryptography.hazmat.backends.interfaces.RSABackend`
- provider.
+ :param backend: A new instance of
+ :class:`~cryptography.hazmat.backends.interfaces.RSABackend`.
- :returns: A
- :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`
- provider.
+ :returns: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`.
Handling partial RSA private keys
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -423,7 +480,7 @@ Handling partial RSA private keys
If you are trying to load RSA private keys yourself you may find that not all
parameters required by ``RSAPrivateNumbers`` are available. In particular the
`Chinese Remainder Theorem`_ (CRT) values ``dmp1``, ``dmq1``, ``iqmp`` may be
-missing or present in a different form. For example `OpenPGP`_ does not include
+missing or present in a different form. For example, `OpenPGP`_ does not include
the ``iqmp``, ``dmp1`` or ``dmq1`` parameters.
The following functions are provided for users who want to work with keys like
@@ -440,15 +497,15 @@ this without having to do the math themselves.
.. versionadded:: 0.4
- Computes the ``dmp1`` parameter from the RSA private exponent and prime
- ``p``.
+ Computes the ``dmp1`` parameter from the RSA private exponent (``d``) and
+ prime ``p``.
.. function:: rsa_crt_dmq1(private_exponent, q)
.. versionadded:: 0.4
- Computes the ``dmq1`` parameter from the RSA private exponent and prime
- ``q``.
+ Computes the ``dmq1`` parameter from the RSA private exponent (``d``) and
+ prime ``q``.
.. function:: rsa_recover_prime_factors(n, e, d)
@@ -460,7 +517,9 @@ this without having to do the math themselves.
.. note::
When recovering prime factors this algorithm will always return ``p``
- and ``q`` such that ``p < q``.
+ and ``q`` such that ``p > q``. Note: before 1.5, this function always
+ returned ``p`` and ``q`` such that ``p < q``. It was changed because
+ libraries commonly require ``p > q``.
:return: A tuple ``(p, q)``
@@ -472,24 +531,9 @@ Key interfaces
.. versionadded:: 0.2
- An `RSA`_ private key.
-
- .. method:: signer(padding, algorithm)
-
- .. versionadded:: 0.3
-
- Sign data which can be verified later by others using the public key.
-
- :param padding: An instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`
- provider.
-
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- provider.
-
- :returns:
- :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricSignatureContext`
+ An `RSA`_ private key. An RSA private key that is not an
+ :term:`opaque key` also implements :class:`RSAPrivateKeyWithSerialization`
+ to provide serialization methods.
.. method:: decrypt(ciphertext, padding)
@@ -499,9 +543,8 @@ Key interfaces
:param bytes ciphertext: The ciphertext to decrypt.
- :param padding: An instance of an
- :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`
- provider.
+ :param padding: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`.
:return bytes: Decrypted data.
@@ -517,29 +560,36 @@ Key interfaces
The bit length of the modulus.
+ .. method:: sign(data, padding, algorithm)
-.. class:: RSAPrivateKeyWithNumbers
+ .. versionadded:: 1.4
+ .. versionchanged:: 1.6
+ :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`
+ can now be used as an ``algorithm``.
- .. versionadded:: 0.5
+ Sign one block of data which can be verified later by others using the
+ public key.
- Extends :class:`RSAPrivateKey`.
+ :param bytes data: The message string to sign.
- .. method:: private_numbers()
+ :param padding: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`.
- Create a
- :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateNumbers`
- object.
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`
+ if the ``data`` you want to sign has already been hashed.
- :returns: An
- :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateNumbers`
- instance.
+ :return bytes: Signature.
.. class:: RSAPrivateKeyWithSerialization
.. versionadded:: 0.8
- Extends :class:`RSAPrivateKey`.
+ This interface contains additional methods relating to serialization.
+ Any object with this interface also has all the methods from
+ :class:`RSAPrivateKey`.
.. method:: private_numbers()
@@ -585,26 +635,6 @@ Key interfaces
An `RSA`_ public key.
- .. method:: verifier(signature, padding, algorithm)
-
- .. versionadded:: 0.3
-
- Verify data was signed by the private key associated with this public
- key.
-
- :param bytes signature: The signature to verify.
-
- :param padding: An instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`
- provider.
-
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- provider.
-
- :returns:
- :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricVerificationContext`
-
.. method:: encrypt(plaintext, padding)
.. versionadded:: 0.4
@@ -613,9 +643,8 @@ Key interfaces
:param bytes plaintext: The plaintext to encrypt.
- :param padding: An instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`
- provider.
+ :param padding: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`.
:return bytes: Encrypted data.
@@ -625,30 +654,6 @@ Key interfaces
The bit length of the modulus.
-
-.. class:: RSAPublicKeyWithNumbers
-
- .. versionadded:: 0.5
-
- Extends :class:`RSAPublicKey`.
-
- .. method:: public_numbers()
-
- Create a
- :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicNumbers`
- object.
-
- :returns: An
- :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicNumbers`
- instance.
-
-
-.. class:: RSAPublicKeyWithSerialization
-
- .. versionadded:: 0.8
-
- Extends :class:`RSAPublicKey`.
-
.. method:: public_numbers()
Create a
@@ -678,14 +683,46 @@ Key interfaces
:return bytes: Serialized key.
+ .. method:: verify(signature, data, padding, algorithm)
+
+ .. versionadded:: 1.4
+ .. versionchanged:: 1.6
+ :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`
+ can now be used as an ``algorithm``.
+
+ Verify one block of data was signed by the private key
+ associated with this public key.
+
+ :param bytes signature: The signature to verify.
+
+ :param bytes data: The message string that was signed.
+
+ :param padding: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`.
+
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`
+ if the ``data`` you want to verify has already been hashed.
+
+ :raises cryptography.exceptions.InvalidSignature: If the signature does
+ not validate.
+
+
+.. class:: RSAPublicKeyWithSerialization
+
+ .. versionadded:: 0.8
+
+ Alias for :class:`RSAPublicKey`.
+
.. _`RSA`: https://en.wikipedia.org/wiki/RSA_(cryptosystem)
.. _`public-key`: https://en.wikipedia.org/wiki/Public-key_cryptography
.. _`specific mathematical properties`: https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Key_generation
-.. _`use 65537`: http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html
-.. _`at least 2048`: http://www.ecrypt.eu.org/ecrypt2/documents/D.SPA.20.pdf
+.. _`use 65537`: https://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html
+.. _`at least 2048`: https://www.cosic.esat.kuleuven.be/ecrypt/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
-.. _`recommended padding algorithm`: http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html
-.. _`proven secure`: http://cseweb.ucsd.edu/~mihir/papers/oae.pdf
+.. _`security proof`: https://eprint.iacr.org/2001/062.pdf
+.. _`recommended padding algorithm`: https://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/asymmetric/serialization.rst b/docs/hazmat/primitives/asymmetric/serialization.rst
index 7839f346..7c1fc82e 100644
--- a/docs/hazmat/primitives/asymmetric/serialization.rst
+++ b/docs/hazmat/primitives/asymmetric/serialization.rst
@@ -63,6 +63,20 @@ Key Serialization
def sign_with_dsa_key(key, message):
return b""
+ parameters_pem_data = b"""
+ -----BEGIN DH PARAMETERS-----
+ MIGHAoGBALsrWt44U1ojqTy88o0wfjysBE51V6Vtarjm2+5BslQK/RtlndHde3gx
+ +ccNs+InANszcuJFI8AHt4743kGRzy5XSlul4q4dDJENOHoyqYxueFuFVJELEwLQ
+ XrX/McKw+hS6GPVQnw6tZhgGo9apdNdYgeLQeQded8Bum8jqzP3rAgEC
+ -----END DH PARAMETERS-----
+ """.strip()
+
+ parameters_der_data = base64.b64decode(
+ b"MIGHAoGBALsrWt44U1ojqTy88o0wfjysBE51V6Vtarjm2+5BslQK/RtlndHde3gx+ccNs+In"
+ b"ANsz\ncuJFI8AHt4743kGRzy5XSlul4q4dDJENOHoyqYxueFuFVJELEwLQXrX/McKw+hS6GP"
+ b"VQnw6tZhgG\no9apdNdYgeLQeQded8Bum8jqzP3rAgEC"
+ )
+
There are several common schemes for serializing asymmetric private and public
keys to bytes. They generally support encryption of private keys and additional
key metadata.
@@ -85,6 +99,16 @@ methods.
... else:
... raise TypeError
+Key dumping
+~~~~~~~~~~~
+
+The ``serialization`` module contains functions for loading keys from
+``bytes``. To dump a ``key`` object to ``bytes``, you must call the appropriate
+method on the key object. Documentation for these methods in found in the
+:mod:`~cryptography.hazmat.primitives.asymmetric.rsa`,
+:mod:`~cryptography.hazmat.primitives.asymmetric.dsa`, and
+:mod:`~cryptography.hazmat.primitives.asymmetric.ec` module documentation.
+
PEM
~~~
@@ -97,8 +121,8 @@ all begin with ``-----BEGIN {format}-----`` and end with ``-----END
.. note::
A PEM block which starts with ``-----BEGIN CERTIFICATE-----`` is not a
- public or private key, it's an :doc:`X.509 Certificate </x509>`. You can
- load it using :func:`~cryptography.x509.load_pem_x509_certificate` and
+ public or private key, it's an :doc:`X.509 Certificate </x509/index>`. You
+ can load it using :func:`~cryptography.x509.load_pem_x509_certificate` and
extract the public key with
:meth:`Certificate.public_key <cryptography.x509.Certificate.public_key>`.
@@ -109,16 +133,23 @@ all begin with ``-----BEGIN {format}-----`` and end with ``-----END
Deserialize a private key from PEM encoded data to one of the supported
asymmetric private key types.
- :param bytes data: The PEM encoded key data.
+ :param data: The PEM encoded key data.
+ :type data: :term:`bytes-like`
- :param bytes password: The password to use to decrypt the data. Should
+ :param password: The password to use to decrypt the data. Should
be ``None`` if the private key is not encrypted.
+ :type data: :term:`bytes-like`
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.PEMSerializationBackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.PEMSerializationBackend`.
- :returns: A new instance of a private key.
+ :returns: One of
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKey`,
+ or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`
+ depending on the contents of ``data``.
:raises ValueError: If the PEM data could not be decrypted or if its
structure could not be decoded successfully.
@@ -136,7 +167,8 @@ all begin with ``-----BEGIN {format}-----`` and end with ``-----END
.. versionadded:: 0.6
Deserialize a public key from PEM encoded data to one of the supported
- asymmetric public key types.
+ asymmetric public key types. The PEM encoded data is typically a
+ ``subjectPublicKeyInfo`` payload as specified in :rfc:`5280`.
.. doctest::
@@ -147,11 +179,17 @@ all begin with ``-----BEGIN {format}-----`` and end with ``-----END
:param bytes data: The PEM encoded key data.
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.PEMSerializationBackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.PEMSerializationBackend`.
- :returns: A new instance of a public key.
+
+ :returns: One of
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicKey`,
+ or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`
+ depending on the contents of ``data``.
:raises ValueError: If the PEM data's structure could not be decoded
successfully.
@@ -159,6 +197,37 @@ all begin with ``-----BEGIN {format}-----`` and end with ``-----END
:raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized key
is of a type that is not supported by the backend.
+.. function:: load_pem_parameters(data, backend)
+
+ .. versionadded:: 2.0
+
+ Deserialize parameters from PEM encoded data to one of the supported
+ asymmetric parameters types.
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.primitives.serialization import load_pem_parameters
+ >>> from cryptography.hazmat.primitives.asymmetric import dh
+ >>> parameters = load_pem_parameters(parameters_pem_data, backend=default_backend())
+ >>> isinstance(parameters, dh.DHParameters)
+ True
+
+ :param bytes data: The PEM encoded parameters data.
+
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.PEMSerializationBackend`.
+
+
+ :returns: Currently only
+ :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameters`
+ supported.
+
+ :raises ValueError: If the PEM data's structure could not be decoded
+ successfully.
+
+ :raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized parameters
+ is of a type that is not supported by the backend.
+
DER
~~~
@@ -174,16 +243,23 @@ the rest.
Deserialize a private key from DER encoded data to one of the supported
asymmetric private key types.
- :param bytes data: The DER encoded key data.
+ :param data: The DER encoded key data.
+ :type data: :term:`bytes-like`
- :param bytes password: The password to use to decrypt the data. Should
+ :param password: The password to use to decrypt the data. Should
be ``None`` if the private key is not encrypted.
+ :type password: :term:`bytes-like`
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.DERSerializationBackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.DERSerializationBackend`.
- :returns: A new instance of a private key.
+ :returns: One of
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKey`,
+ or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`
+ depending on the contents of ``data``.
:raises ValueError: If the DER data could not be decrypted or if its
structure could not be decoded successfully.
@@ -210,15 +286,21 @@ the rest.
.. versionadded:: 0.8
Deserialize a public key from DER encoded data to one of the supported
- asymmetric public key types.
+ asymmetric public key types. The DER encoded data is typically a
+ ``subjectPublicKeyInfo`` payload as specified in :rfc:`5280`.
:param bytes data: The DER encoded key data.
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.DERSerializationBackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.DERSerializationBackend`.
- :returns: A new instance of a public key.
+ :returns: One of
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicKey`,
+ or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`
+ depending on the contents of ``data``.
:raises ValueError: If the DER data's structure could not be decoded
successfully.
@@ -235,6 +317,37 @@ the rest.
>>> isinstance(key, rsa.RSAPublicKey)
True
+.. function:: load_der_parameters(data, backend)
+
+ .. versionadded:: 2.0
+
+ Deserialize parameters from DER encoded data to one of the supported
+ asymmetric parameters types.
+
+ :param bytes data: The DER encoded parameters data.
+
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.DERSerializationBackend`.
+
+ :returns: Currently only
+ :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameters`
+ supported.
+
+ :raises ValueError: If the DER data's structure could not be decoded
+ successfully.
+
+ :raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized key is of a type that
+ is not supported by the backend.
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> from cryptography.hazmat.primitives.asymmetric import dh
+ >>> from cryptography.hazmat.primitives.serialization import load_der_parameters
+ >>> parameters = load_der_parameters(parameters_der_data, backend=default_backend())
+ >>> isinstance(parameters, dh.DHParameters)
+ True
+
OpenSSH Public Key
~~~~~~~~~~~~~~~~~~
@@ -263,19 +376,21 @@ DSA keys look almost identical but begin with ``ssh-dss`` rather than
Deserialize a public key from OpenSSH (:rfc:`4253`) encoded data to an
instance of the public key type for the specified backend.
- .. note::
-
- Currently Ed25519 keys are not supported.
-
:param bytes data: The OpenSSH encoded key data.
- :param backend: A backend providing
+ :param backend: A backend which implements
:class:`~cryptography.hazmat.backends.interfaces.RSABackend`,
:class:`~cryptography.hazmat.backends.interfaces.DSABackend`, or
:class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`
depending on the key's type.
- :returns: A new instance of a public key type.
+ :returns: One of
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`
+ , or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey`,
+ depending on the contents of ``data``.
:raises ValueError: If the OpenSSH data could not be properly decoded or
if the key is not in the proper format.
@@ -283,9 +398,48 @@ DSA keys look almost identical but begin with ``ssh-dss`` rather than
:raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized
key is of a type that is not supported.
+PKCS12
+~~~~~~
+
+.. currentmodule:: cryptography.hazmat.primitives.serialization.pkcs12
+
+PKCS12 is a binary format described in :rfc:`7292`. It can contain
+certificates, keys, and more. PKCS12 files commonly have a ``pfx`` or ``p12``
+file suffix.
+
+.. note::
+
+ ``cryptography`` only supports a single private key and associated
+ certificates when parsing PKCS12 files at this time.
+
+.. function:: load_key_and_certificates(data, password, backend)
+
+ .. versionadded:: 2.5
+
+ Deserialize a PKCS12 blob.
+
+ :param data: The binary data.
+ :type data: :term:`bytes-like`
+
+ :param password: The password to use to decrypt the data. ``None``
+ if the PKCS12 is not encrypted.
+ :type password: :term:`bytes-like`
+
+ :param backend: A backend instance.
+
+ :returns: A tuple of
+ ``(private_key, certificate, additional_certificates)``.
+ ``private_key`` is a private key type or ``None``, ``certificate``
+ is either the :class:`~cryptography.x509.Certificate` whose public key
+ matches the private key in the PKCS 12 object or ``None``, and
+ ``additional_certificates`` is a list of all other
+ :class:`~cryptography.x509.Certificate` instances in the PKCS12 object.
+
Serialization Formats
~~~~~~~~~~~~~~~~~~~~~
+.. currentmodule:: cryptography.hazmat.primitives.serialization
+
.. class:: PrivateFormat
.. versionadded:: 0.8
@@ -295,6 +449,7 @@ Serialization Formats
:class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization`
,
:class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKeyWithSerialization`
+ , :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKeyWithSerialization`
and
:class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKeyWithSerialization`.
@@ -303,12 +458,31 @@ Serialization Formats
Frequently known as PKCS#1 format. Still a widely used format, but
generally considered legacy.
+ A PEM encoded RSA key will look like::
+
+ -----BEGIN RSA PRIVATE KEY-----
+ ...
+ -----END RSA PRIVATE KEY-----
+
.. attribute:: PKCS8
A more modern format for serializing keys which allows for better
encryption. Choose this unless you have explicit legacy compatibility
requirements.
+ A PEM encoded key will look like::
+
+ -----BEGIN PRIVATE KEY-----
+ ...
+ -----END PRIVATE KEY-----
+
+ .. attribute:: Raw
+
+ .. versionadded:: 2.5
+
+ A raw format used by :doc:`/hazmat/primitives/asymmetric/x448`. It is a
+ binary format and is invalid for other key types.
+
.. class:: PublicFormat
.. versionadded:: 0.8
@@ -318,6 +492,7 @@ Serialization Formats
:class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKeyWithSerialization`
,
:class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKeyWithSerialization`
+ , :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicKeyWithSerialization`
, and
:class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKeyWithSerialization`.
@@ -327,38 +502,116 @@ Serialization Formats
identifier and the public key as a bit string. Choose this unless
you have specific needs.
+ A PEM encoded key will look like::
+
+ -----BEGIN PUBLIC KEY-----
+ ...
+ -----END PUBLIC KEY-----
+
.. attribute:: PKCS1
Just the public key elements (without the algorithm identifier). This
format is RSA only, but is used by some older systems.
+ A PEM encoded key will look like::
+
+ -----BEGIN RSA PUBLIC KEY-----
+ ...
+ -----END RSA PUBLIC KEY-----
+
+ .. attribute:: OpenSSH
+
+ .. versionadded:: 1.4
+
+ The public key format used by OpenSSH (e.g. as found in
+ ``~/.ssh/id_rsa.pub`` or ``~/.ssh/authorized_keys``).
+
+ .. attribute:: Raw
+
+ .. versionadded:: 2.5
+
+ A raw format used by :doc:`/hazmat/primitives/asymmetric/x448`. It is a
+ binary format and is invalid for other key types.
+
+ .. attribute:: CompressedPoint
+
+ .. versionadded:: 2.5
+
+ A compressed elliptic curve public key as defined in ANSI X9.62 section
+ 4.3.6 (as well as `SEC 1 v2.0`_).
+
+ .. attribute:: UncompressedPoint
+
+ .. versionadded:: 2.5
+
+ An uncompressed elliptic curve public key as defined in ANSI X9.62
+ section 4.3.6 (as well as `SEC 1 v2.0`_).
+
+.. class:: ParameterFormat
+
+ .. versionadded:: 2.0
+
+ An enumeration for parameters formats. Used with the ``parameter_bytes``
+ method available on
+ :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParametersWithSerialization`.
+
+ .. attribute:: PKCS3
+
+ ASN1 DH parameters sequence as defined in `PKCS3`_.
+
Serialization Encodings
~~~~~~~~~~~~~~~~~~~~~~~
.. class:: Encoding
- .. versionadded:: 0.8
-
An enumeration for encoding types. Used with the ``private_bytes`` method
available on
:class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization`
,
:class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKeyWithSerialization`
+ , :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKeyWithSerialization`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKeyWithSerialization`,
and
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKeyWithSerialization`
+ :class:`~cryptography.hazmat.primitives.asymmetric.x448.X448PrivateKey`
as well as ``public_bytes`` on
- :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKeyWithSerialization`
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`,
and
- :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKeyWithSerialization`.
+ :class:`~cryptography.hazmat.primitives.asymmetric.x448.X448PublicKey`.
.. attribute:: PEM
+ .. versionadded:: 0.8
+
For PEM format. This is a base64 format with delimiters.
.. attribute:: DER
+ .. versionadded:: 0.9
+
For DER format. This is a binary format.
+ .. attribute:: OpenSSH
+
+ .. versionadded:: 1.4
+
+ The format used by OpenSSH public keys. This is a text format.
+
+ .. attribute:: Raw
+
+ .. versionadded:: 2.5
+
+ A raw format used by :doc:`/hazmat/primitives/asymmetric/x448`. It is a
+ binary format and is invalid for other key types.
+
+ .. attribute:: X962
+
+ .. versionadded:: 2.5
+
+ The format used by elliptic curve point encodings. This is a binary
+ format.
+
Serialization Encryption Types
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -370,6 +623,7 @@ Serialization Encryption Types
:class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization`
,
:class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKeyWithSerialization`
+ , :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKeyWithSerialization`
and
:class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKeyWithSerialization`.
All other classes in this section represent the available choices for
@@ -387,3 +641,7 @@ Serialization Encryption Types
.. class:: NoEncryption
Do not encrypt.
+
+
+.. _`PKCS3`: https://www.teletrust.de/fileadmin/files/oid/oid_pkcs-3v1-4.pdf
+.. _`SEC 1 v2.0`: https://www.secg.org/sec1-v2.pdf
diff --git a/docs/hazmat/primitives/asymmetric/utils.rst b/docs/hazmat/primitives/asymmetric/utils.rst
index 7380f0b5..f46acb2e 100644
--- a/docs/hazmat/primitives/asymmetric/utils.rst
+++ b/docs/hazmat/primitives/asymmetric/utils.rst
@@ -6,10 +6,11 @@ Asymmetric Utilities
.. currentmodule:: cryptography.hazmat.primitives.asymmetric.utils
-.. function:: decode_rfc6979_signature(signature)
+.. function:: decode_dss_signature(signature)
- Takes in :rfc:`6979` signatures generated by the DSA/ECDSA signers and
- returns a tuple ``(r, s)``.
+ Takes in signatures generated by the DSA/ECDSA signers and returns a
+ tuple ``(r, s)``. These signatures are ASN.1 encoded ``Dss-Sig-Value``
+ sequences (as defined in :rfc:`3279`)
:param bytes signature: The signature to decode.
@@ -17,12 +18,71 @@ Asymmetric Utilities
:raises ValueError: Raised if the signature is malformed.
-.. function:: encode_rfc6979_signature(r, s)
+.. function:: encode_dss_signature(r, s)
- Creates an :rfc:`6979` byte string from raw signature values.
+ Creates an ASN.1 encoded ``Dss-Sig-Value`` (as defined in :rfc:`3279`) from
+ raw ``r`` and ``s`` values.
:param int r: The raw signature value ``r``.
:param int s: The raw signature value ``s``.
:return bytes: The encoded signature.
+
+.. class:: Prehashed(algorithm)
+
+ .. versionadded:: 1.6
+
+ ``Prehashed`` can be passed as the ``algorithm`` in the RSA
+ :meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey.sign`
+ and
+ :meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey.verify`
+ as well as DSA
+ :meth:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey.sign`
+ and
+ :meth:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey.verify`
+ methods.
+
+ For elliptic curves it can be passed as the ``algorithm`` in
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.ECDSA` and then used
+ with
+ :meth:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey.sign`
+ and
+ :meth:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey.verify`
+ .
+
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
+
+ .. doctest::
+
+ >>> import hashlib
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> from cryptography.hazmat.primitives.asymmetric import (
+ ... padding, rsa, utils
+ ... )
+ >>> private_key = rsa.generate_private_key(
+ ... public_exponent=65537,
+ ... key_size=2048,
+ ... backend=default_backend()
+ ... )
+ >>> prehashed_msg = hashlib.sha256(b"A message I want to sign").digest()
+ >>> signature = private_key.sign(
+ ... prehashed_msg,
+ ... padding.PSS(
+ ... mgf=padding.MGF1(hashes.SHA256()),
+ ... salt_length=padding.PSS.MAX_LENGTH
+ ... ),
+ ... utils.Prehashed(hashes.SHA256())
+ ... )
+ >>> public_key = private_key.public_key()
+ >>> public_key.verify(
+ ... signature,
+ ... prehashed_msg,
+ ... padding.PSS(
+ ... mgf=padding.MGF1(hashes.SHA256()),
+ ... salt_length=padding.PSS.MAX_LENGTH
+ ... ),
+ ... utils.Prehashed(hashes.SHA256())
+ ... )
diff --git a/docs/hazmat/primitives/asymmetric/x25519.rst b/docs/hazmat/primitives/asymmetric/x25519.rst
new file mode 100644
index 00000000..ea01fbaa
--- /dev/null
+++ b/docs/hazmat/primitives/asymmetric/x25519.rst
@@ -0,0 +1,184 @@
+.. hazmat::
+
+X25519 key exchange
+===================
+
+.. currentmodule:: cryptography.hazmat.primitives.asymmetric.x25519
+
+
+X25519 is an elliptic curve `Diffie-Hellman key exchange`_ using `Curve25519`_.
+It allows two parties to jointly agree on a shared secret using an insecure
+channel.
+
+
+Exchange Algorithm
+~~~~~~~~~~~~~~~~~~
+
+For most applications the ``shared_key`` should be passed to a key
+derivation function. This allows mixing of additional information into the
+key, derivation of multiple keys, and destroys any structure that may be
+present.
+
+.. doctest::
+
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey
+ >>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
+ >>> # Generate a private key for use in the exchange.
+ >>> private_key = X25519PrivateKey.generate()
+ >>> # In a real handshake the peer_public_key will be received from the
+ >>> # other party. For this example we'll generate another private key and
+ >>> # get a public key from that. Note that in a DH handshake both peers
+ >>> # must agree on a common set of parameters.
+ >>> peer_public_key = X25519PrivateKey.generate().public_key()
+ >>> shared_key = private_key.exchange(peer_public_key)
+ >>> # Perform key derivation.
+ >>> derived_key = HKDF(
+ ... algorithm=hashes.SHA256(),
+ ... length=32,
+ ... salt=None,
+ ... info=b'handshake data',
+ ... backend=default_backend()
+ ... ).derive(shared_key)
+ >>> # For the next handshake we MUST generate another private key.
+ >>> private_key_2 = X25519PrivateKey.generate()
+ >>> peer_public_key_2 = X25519PrivateKey.generate().public_key()
+ >>> shared_key_2 = private_key_2.exchange(peer_public_key_2)
+ >>> derived_key_2 = HKDF(
+ ... algorithm=hashes.SHA256(),
+ ... length=32,
+ ... salt=None,
+ ... info=b'handshake data',
+ ... backend=default_backend()
+ ... ).derive(shared_key_2)
+
+Key interfaces
+~~~~~~~~~~~~~~
+
+.. class:: X25519PrivateKey
+
+ .. versionadded:: 2.0
+
+ .. classmethod:: generate()
+
+ Generate an X25519 private key.
+
+ :returns: :class:`X25519PrivateKey`
+
+ .. classmethod:: from_private_bytes(data)
+
+ .. versionadded:: 2.5
+
+ A class method for loading an X25519 key encoded as
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`.
+
+ :param bytes data: 32 byte private key.
+
+ :returns: :class:`X25519PrivateKey`
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.primitives import serialization
+ >>> from cryptography.hazmat.primitives.asymmetric import x25519
+ >>> private_key = x25519.X25519PrivateKey.generate()
+ >>> private_bytes = private_key.private_bytes(
+ ... encoding=serialization.Encoding.Raw,
+ ... format=serialization.PrivateFormat.Raw,
+ ... encryption_algorithm=serialization.NoEncryption()
+ ... )
+ >>> loaded_private_key = x25519.X25519PrivateKey.from_private_bytes(private_bytes)
+
+ .. method:: public_key()
+
+ :returns: :class:`X25519PublicKey`
+
+ .. method:: exchange(peer_public_key)
+
+ :param X25519PublicKey peer_public_key: The public key for the
+ peer.
+
+ :returns bytes: A shared key.
+
+ .. method:: private_bytes(encoding, format, encryption_algorithm)
+
+ .. versionadded:: 2.5
+
+ Allows serialization of the key to bytes. Encoding (
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`,
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`, or
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`) and
+ format (
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`
+ or
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.Raw`
+ ) are chosen to define the exact serialization.
+
+ :param encoding: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
+
+ :param format: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.PrivateFormat`
+ enum. If the ``encoding`` is
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`
+ then ``format`` must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.Raw`
+ , otherwise it must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`.
+
+ :param encryption_algorithm: An instance of an object conforming to the
+ :class:`~cryptography.hazmat.primitives.serialization.KeySerializationEncryption`
+ interface.
+
+ :return bytes: Serialized key.
+
+.. class:: X25519PublicKey
+
+ .. versionadded:: 2.0
+
+ .. classmethod:: from_public_bytes(data)
+
+ :param bytes data: 32 byte public key.
+
+ :returns: :class:`X25519PublicKey`
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.primitives.asymmetric import x25519
+ >>> private_key = x25519.X25519PrivateKey.generate()
+ >>> public_key = private_key.public_key()
+ >>> public_bytes = public_key.public_bytes(
+ ... encoding=serialization.Encoding.Raw,
+ ... format=serialization.PublicFormat.Raw
+ ... )
+ >>> loaded_public_key = x25519.X25519PublicKey.from_public_bytes(public_bytes)
+
+ .. method:: public_bytes(encoding, format)
+
+ Allows serialization of the key to bytes. Encoding (
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`,
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`, or
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`) and
+ format (
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`
+ or
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.Raw`
+ ) are chosen to define the exact serialization.
+
+ :param encoding: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
+
+ :param format: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.PublicFormat`
+ enum. If the ``encoding`` is
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`
+ then ``format`` must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.Raw`
+ , otherwise it must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`.
+
+ :returns bytes: The public key bytes.
+
+
+.. _`Diffie-Hellman key exchange`: https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange
+.. _`Curve25519`: https://en.wikipedia.org/wiki/Curve25519
diff --git a/docs/hazmat/primitives/asymmetric/x448.rst b/docs/hazmat/primitives/asymmetric/x448.rst
new file mode 100644
index 00000000..4e1f0421
--- /dev/null
+++ b/docs/hazmat/primitives/asymmetric/x448.rst
@@ -0,0 +1,179 @@
+.. hazmat::
+
+X448 key exchange
+===================
+
+.. currentmodule:: cryptography.hazmat.primitives.asymmetric.x448
+
+
+X448 is an elliptic curve `Diffie-Hellman key exchange`_ using `Curve448`_.
+It allows two parties to jointly agree on a shared secret using an insecure
+channel.
+
+
+Exchange Algorithm
+~~~~~~~~~~~~~~~~~~
+
+For most applications the ``shared_key`` should be passed to a key
+derivation function. This allows mixing of additional information into the
+key, derivation of multiple keys, and destroys any structure that may be
+present.
+
+.. doctest::
+
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> from cryptography.hazmat.primitives.asymmetric.x448 import X448PrivateKey
+ >>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
+ >>> # Generate a private key for use in the exchange.
+ >>> private_key = X448PrivateKey.generate()
+ >>> # In a real handshake the peer_public_key will be received from the
+ >>> # other party. For this example we'll generate another private key and
+ >>> # get a public key from that. Note that in a DH handshake both peers
+ >>> # must agree on a common set of parameters.
+ >>> peer_public_key = X448PrivateKey.generate().public_key()
+ >>> shared_key = private_key.exchange(peer_public_key)
+ >>> # Perform key derivation.
+ >>> derived_key = HKDF(
+ ... algorithm=hashes.SHA256(),
+ ... length=32,
+ ... salt=None,
+ ... info=b'handshake data',
+ ... backend=default_backend()
+ ... ).derive(shared_key)
+ >>> # For the next handshake we MUST generate another private key.
+ >>> private_key_2 = X448PrivateKey.generate()
+ >>> peer_public_key_2 = X448PrivateKey.generate().public_key()
+ >>> shared_key_2 = private_key_2.exchange(peer_public_key_2)
+ >>> derived_key_2 = HKDF(
+ ... algorithm=hashes.SHA256(),
+ ... length=32,
+ ... salt=None,
+ ... info=b'handshake data',
+ ... backend=default_backend()
+ ... ).derive(shared_key_2)
+
+Key interfaces
+~~~~~~~~~~~~~~
+
+.. class:: X448PrivateKey
+
+ .. versionadded:: 2.5
+
+ .. classmethod:: generate()
+
+ Generate an X448 private key.
+
+ :returns: :class:`X448PrivateKey`
+
+ .. classmethod:: from_private_bytes(data)
+
+ :param data: 56 byte private key.
+ :type data: :term:`bytes-like`
+
+ :returns: :class:`X448PrivateKey`
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.primitives import serialization
+ >>> from cryptography.hazmat.primitives.asymmetric import x448
+ >>> private_key = x448.X448PrivateKey.generate()
+ >>> private_bytes = private_key.private_bytes(
+ ... encoding=serialization.Encoding.Raw,
+ ... format=serialization.PrivateFormat.Raw,
+ ... encryption_algorithm=serialization.NoEncryption()
+ ... )
+ >>> loaded_private_key = x448.X448PrivateKey.from_private_bytes(private_bytes)
+
+ .. method:: public_key()
+
+ :returns: :class:`X448PublicKey`
+
+ .. method:: exchange(peer_public_key)
+
+ :param X448PublicKey peer_public_key: The public key for the
+ peer.
+
+ :returns bytes: A shared key.
+
+ .. method:: private_bytes(encoding, format, encryption_algorithm)
+
+ Allows serialization of the key to bytes. Encoding (
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`,
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`, or
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`) and
+ format (
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`
+ or
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.Raw`
+ ) are chosen to define the exact serialization.
+
+ :param encoding: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
+
+ :param format: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.PrivateFormat`
+ enum. If the ``encoding`` is
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`
+ then ``format`` must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.Raw`
+ , otherwise it must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`.
+
+ :param encryption_algorithm: An instance of an object conforming to the
+ :class:`~cryptography.hazmat.primitives.serialization.KeySerializationEncryption`
+ interface.
+
+ :return bytes: Serialized key.
+
+.. class:: X448PublicKey
+
+ .. versionadded:: 2.5
+
+ .. classmethod:: from_public_bytes(data)
+
+ :param bytes data: 56 byte public key.
+
+ :returns: :class:`X448PublicKey`
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.primitives import serialization
+ >>> from cryptography.hazmat.primitives.asymmetric import x448
+ >>> private_key = x448.X448PrivateKey.generate()
+ >>> public_key = private_key.public_key()
+ >>> public_bytes = public_key.public_bytes(
+ ... encoding=serialization.Encoding.Raw,
+ ... format=serialization.PublicFormat.Raw
+ ... )
+ >>> loaded_public_key = x448.X448PublicKey.from_public_bytes(public_bytes)
+
+ .. method:: public_bytes(encoding, format)
+
+ Allows serialization of the key to bytes. Encoding (
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`,
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`, or
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`) and
+ format (
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`
+ or
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.Raw`
+ ) are chosen to define the exact serialization.
+
+ :param encoding: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
+
+ :param format: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.PublicFormat`
+ enum. If the ``encoding`` is
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`
+ then ``format`` must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.Raw`
+ , otherwise it must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`.
+
+ :returns bytes: The public key bytes.
+
+
+.. _`Diffie-Hellman key exchange`: https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange
+.. _`Curve448`: https://en.wikipedia.org/wiki/Curve448
diff --git a/docs/hazmat/primitives/constant-time.rst b/docs/hazmat/primitives/constant-time.rst
index 1394b6b3..1c1d544f 100644
--- a/docs/hazmat/primitives/constant-time.rst
+++ b/docs/hazmat/primitives/constant-time.rst
@@ -40,4 +40,4 @@ about the timing attacks on KeyCzar and Java's ``MessageDigest.isEqual()``.
``bytes``.
-.. _`Coda Hale's blog post`: http://codahale.com/a-lesson-in-timing-attacks/
+.. _`Coda Hale's blog post`: https://codahale.com/a-lesson-in-timing-attacks/
diff --git a/docs/hazmat/primitives/cryptographic-hashes.rst b/docs/hazmat/primitives/cryptographic-hashes.rst
index 49288326..24cc70b5 100644
--- a/docs/hazmat/primitives/cryptographic-hashes.rst
+++ b/docs/hazmat/primitives/cryptographic-hashes.rst
@@ -1,7 +1,7 @@
.. hazmat::
-Message digests
-===============
+Message digests (Hashing)
+=========================
.. module:: cryptography.hazmat.primitives.hashes
@@ -26,7 +26,7 @@ Message digests
>>> digest.update(b"abc")
>>> digest.update(b"123")
>>> digest.finalize()
- 'l\xa1=R\xcap\xc8\x83\xe0\xf0\xbb\x10\x1eBZ\x89\xe8bM\xe5\x1d\xb2\xd29%\x93\xafj\x84\x11\x80\x90'
+ b'l\xa1=R\xcap\xc8\x83\xe0\xf0\xbb\x10\x1eBZ\x89\xe8bM\xe5\x1d\xb2\xd29%\x93\xafj\x84\x11\x80\x90'
If the backend doesn't support the requested ``algorithm`` an
:class:`~cryptography.exceptions.UnsupportedAlgorithm` exception will be
@@ -40,11 +40,11 @@ Message digests
:param algorithm: A
:class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- provider such as those described in
+ instance such as those described in
:ref:`below <cryptographic-hash-algorithms>`.
:param backend: A
:class:`~cryptography.hazmat.backends.interfaces.HashBackend`
- provider.
+ instance.
:raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
provided ``backend`` does not implement
@@ -79,19 +79,6 @@ Message digests
.. _cryptographic-hash-algorithms:
-SHA-1
-~~~~~
-
-.. attention::
-
- NIST has deprecated SHA-1 in favor of the SHA-2 variants. New applications
- are strongly suggested to use SHA-2 over SHA-1.
-
-.. class:: SHA1()
-
- SHA-1 is a cryptographic hash function standardized by NIST. It produces an
- 160-bit message digest.
-
SHA-2 family
~~~~~~~~~~~~
@@ -115,21 +102,134 @@ SHA-2 family
SHA-512 is a cryptographic hash function from the SHA-2 family and is
standardized by NIST. It produces a 512-bit message digest.
-RIPEMD160
-~~~~~~~~~
+.. class:: SHA512_224()
+
+ .. versionadded:: 2.5
+
+ SHA-512/224 is a cryptographic hash function from the SHA-2 family and is
+ standardized by NIST. It produces a 224-bit message digest.
+
+.. class:: SHA512_256()
+
+ .. versionadded:: 2.5
+
+ SHA-512/256 is a cryptographic hash function from the SHA-2 family and is
+ standardized by NIST. It produces a 256-bit message digest.
+
+BLAKE2
+~~~~~~
+
+`BLAKE2`_ is a cryptographic hash function specified in :rfc:`7693`. BLAKE2's
+design makes it immune to `length-extension attacks`_, an advantage over the
+SHA-family of hashes.
+
+.. note::
+
+ While the RFC specifies keying, personalization, and salting features,
+ these are not supported at this time due to limitations in OpenSSL 1.1.0.
+
+.. class:: BLAKE2b(digest_size)
+
+ BLAKE2b is optimized for 64-bit platforms and produces an 1 to 64-byte
+ message digest.
+
+ :param int digest_size: The desired size of the hash output in bytes. Only
+ ``64`` is supported at this time.
+
+ :raises ValueError: If the ``digest_size`` is invalid.
+
+.. class:: BLAKE2s(digest_size)
+
+ BLAKE2s is optimized for 8 to 32-bit platforms and produces a
+ 1 to 32-byte message digest.
+
+ :param int digest_size: The desired size of the hash output in bytes. Only
+ ``32`` is supported at this time.
+
+ :raises ValueError: If the ``digest_size`` is invalid.
+
+SHA-3 family
+~~~~~~~~~~~~
+
+SHA-3 is the most recent NIST secure hash algorithm standard. Despite the
+larger number SHA-3 is not considered to be better than SHA-2. Instead, it uses
+a significantly different internal structure so that **if** an attack appears
+against SHA-2 it is unlikely to apply to SHA-3. SHA-3 is significantly slower
+than SHA-2 so at this time most users should choose SHA-2.
+
+.. class:: SHA3_224()
+
+ .. versionadded:: 2.5
+
+ SHA3/224 is a cryptographic hash function from the SHA-3 family and is
+ standardized by NIST. It produces a 224-bit message digest.
+
+.. class:: SHA3_256()
+
+ .. versionadded:: 2.5
+
+ SHA3/256 is a cryptographic hash function from the SHA-3 family and is
+ standardized by NIST. It produces a 256-bit message digest.
+
+.. class:: SHA3_384()
+
+ .. versionadded:: 2.5
+
+ SHA3/384 is a cryptographic hash function from the SHA-3 family and is
+ standardized by NIST. It produces a 384-bit message digest.
+
+.. class:: SHA3_512()
+
+ .. versionadded:: 2.5
+
+ SHA3/512 is a cryptographic hash function from the SHA-3 family and is
+ standardized by NIST. It produces a 512-bit message digest.
+
+.. class:: SHAKE128(digest_size)
+
+ .. versionadded:: 2.5
+
+ SHAKE128 is an extendable output function (XOF) based on the same core
+ permutations as SHA3. It allows the caller to obtain an arbitrarily long
+ digest length. Longer lengths, however, do not increase security or
+ collision resistance and lengths shorter than 128 bit (16 bytes) will
+ decrease it.
+
+ :param int digest_size: The length of output desired. Must be greater than
+ zero.
-.. class:: RIPEMD160()
+ :raises ValueError: If the ``digest_size`` is invalid.
- RIPEMD160 is a cryptographic hash function that is part of ISO/IEC
- 10118-3:2004. It produces a 160-bit message digest.
+.. class:: SHAKE256(digest_size)
-Whirlpool
-~~~~~~~~~
+ .. versionadded:: 2.5
-.. class:: Whirlpool()
+ SHAKE256 is an extendable output function (XOF) based on the same core
+ permutations as SHA3. It allows the caller to obtain an arbitrarily long
+ digest length. Longer lengths, however, do not increase security or
+ collision resistance and lengths shorter than 256 bit (32 bytes) will
+ decrease it.
- Whirlpool is a cryptographic hash function that is part of ISO/IEC
- 10118-3:2004. It produces a 512-bit message digest.
+ :param int digest_size: The length of output desired. Must be greater than
+ zero.
+
+ :raises ValueError: If the ``digest_size`` is invalid.
+
+SHA-1
+~~~~~
+
+.. warning::
+
+ SHA-1 is a deprecated hash algorithm that has practical known collision
+ attacks. You are strongly discouraged from using it. Existing applications
+ should strongly consider moving away.
+
+.. class:: SHA1()
+
+ SHA-1 is a cryptographic hash function standardized by NIST. It produces an
+ 160-bit message digest. Cryptanalysis of SHA-1 has demonstrated that it is
+ vulnerable to practical collision attacks, and collisions have been
+ demonstrated.
MD5
~~~
@@ -156,7 +256,7 @@ Interfaces
:type: str
The standard name for the hash algorithm, for example: ``"sha256"`` or
- ``"whirlpool"``.
+ ``"blake2b"``.
.. attribute:: digest_size
@@ -164,12 +264,6 @@ Interfaces
The size of the resulting digest in bytes.
- .. attribute:: block_size
-
- :type: int
-
- The internal block size of the hash algorithm in bytes.
-
.. class:: HashContext
@@ -190,4 +284,6 @@ Interfaces
:return: A :class:`HashContext` that is a copy of the current context.
-.. _`Lifetimes of cryptographic hash functions`: http://valerieaurora.org/hash.html
+.. _`Lifetimes of cryptographic hash functions`: https://valerieaurora.org/hash.html
+.. _`BLAKE2`: https://blake2.net
+.. _`length-extension attacks`: https://en.wikipedia.org/wiki/Length_extension_attack
diff --git a/docs/hazmat/primitives/index.rst b/docs/hazmat/primitives/index.rst
index a9ab38a0..72e5b26c 100644
--- a/docs/hazmat/primitives/index.rst
+++ b/docs/hazmat/primitives/index.rst
@@ -6,12 +6,13 @@ Primitives
.. toctree::
:maxdepth: 1
- cryptographic-hashes
+ aead
+ asymmetric/index
+ constant-time
+ key-derivation-functions
+ keywrap
mac/index
+ cryptographic-hashes
symmetric-encryption
padding
- key-derivation-functions
- asymmetric/index
- constant-time
- interfaces
twofactor
diff --git a/docs/hazmat/primitives/interfaces.rst b/docs/hazmat/primitives/interfaces.rst
deleted file mode 100644
index d60fe186..00000000
--- a/docs/hazmat/primitives/interfaces.rst
+++ /dev/null
@@ -1,80 +0,0 @@
-.. hazmat::
-
-.. module:: cryptography.hazmat.primitives.interfaces
-
-Interfaces
-==========
-
-
-``cryptography`` uses `Abstract Base Classes`_ as interfaces to describe the
-properties and methods of most primitive constructs. Backends may also use
-this information to influence their operation. Interfaces should also be used
-to document argument and return types.
-
-.. _`Abstract Base Classes`: https://docs.python.org/3/library/abc.html
-
-
-Asymmetric interfaces
----------------------
-
-In 0.8 the asymmetric signature and verification interfaces were moved to the
-:mod:`cryptography.hazmat.primitives.asymmetric` module.
-
-In 0.8 the asymmetric padding interface was moved to the
-:mod:`cryptography.hazmat.primitives.asymmetric.padding` module.
-
-DSA
-~~~
-
-In 0.8 the DSA key interfaces were moved to the
-:mod:`cryptography.hazmat.primitives.asymmetric.dsa` module.
-
-
-RSA
-~~~
-
-In 0.8 the RSA key interfaces were moved to the
-:mod:`cryptography.hazmat.primitives.asymmetric.rsa` module.
-
-
-Elliptic Curve
-~~~~~~~~~~~~~~
-
-In 0.8 the EC key interfaces were moved to the
-:mod:`cryptography.hazmat.primitives.asymmetric.ec` module.
-
-
-Key derivation functions
-------------------------
-
-In 0.8 the key derivation function interface was moved to the
-:mod:`cryptography.hazmat.primitives.kdf` module.
-
-
-.. class:: MACContext
-
- .. versionadded:: 0.7
-
- .. method:: update(data)
-
- :param bytes data: The data you want to authenticate.
-
- .. method:: finalize()
-
- :return: The message authentication code.
-
- .. method:: copy()
-
- :return: A
- :class:`~cryptography.hazmat.primitives.interfaces.MACContext` that
- is a copy of the current context.
-
- .. method:: verify(signature)
-
- :param bytes signature: The signature to verify.
-
- :raises cryptography.exceptions.InvalidSignature: This is raised when
- the provided signature does not match the expected signature.
-
-
-.. _`CMAC`: https://en.wikipedia.org/wiki/CMAC
diff --git a/docs/hazmat/primitives/key-derivation-functions.rst b/docs/hazmat/primitives/key-derivation-functions.rst
index 35e2dd87..4b474124 100644
--- a/docs/hazmat/primitives/key-derivation-functions.rst
+++ b/docs/hazmat/primitives/key-derivation-functions.rst
@@ -34,7 +34,8 @@ Different KDFs are suitable for different tasks such as:
`PBKDF2`_ (Password Based Key Derivation Function 2) is typically used for
deriving a cryptographic key from a password. It may also be used for
- key storage, but an alternate key storage KDF such as `scrypt`_ is generally
+ key storage, but an alternate key storage KDF such as
+ :class:`~cryptography.hazmat.primitives.kdf.scrypt.Scrypt` is generally
considered a better solution.
This class conforms to the
@@ -48,6 +49,7 @@ Different KDFs are suitable for different tasks such as:
>>> from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
>>> from cryptography.hazmat.backends import default_backend
>>> backend = default_backend()
+ >>> # Salts should be randomly generated
>>> salt = os.urandom(16)
>>> # derive
>>> kdf = PBKDF2HMAC(
@@ -68,21 +70,19 @@ Different KDFs are suitable for different tasks such as:
... )
>>> kdf.verify(b"my great password", key)
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- provider.
- :param int length: The desired length of the derived key. Maximum is
- (2\ :sup:`32` - 1) * ``algorithm.digest_size``.
- :param bytes salt: A salt. `NIST SP 800-132`_ recommends 128-bits or
- longer.
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
+ :param int length: The desired length of the derived key in bytes. Maximum
+ is (2\ :sup:`32` - 1) * ``algorithm.digest_size``.
+ :param bytes salt: A salt. Secure values [#nist]_ are 128-bits (16 bytes)
+ or longer and randomly generated.
:param int iterations: The number of iterations to perform of the hash
function. This can be used to control the length of time the operation
takes. Higher numbers help mitigate brute force attacks against derived
- keys. See OWASP's `Password Storage Cheat Sheet`_ for more
- detailed recommendations if you intend to use this for password storage.
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.PBKDF2HMACBackend`
- provider.
+ keys. A `more detailed description`_ can be consulted for additional
+ information.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.PBKDF2HMACBackend`.
:raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
provided ``backend`` does not implement
@@ -92,8 +92,9 @@ Different KDFs are suitable for different tasks such as:
.. method:: derive(key_material)
- :param bytes key_material: The input key material. For PBKDF2 this
+ :param key_material: The input key material. For PBKDF2 this
should be a password.
+ :type key_material: :term:`bytes-like`
:return bytes: the derived key.
:raises cryptography.exceptions.AlreadyFinalized: This is raised when
:meth:`derive` or
@@ -168,12 +169,11 @@ Different KDFs are suitable for different tasks such as:
... )
>>> hkdf.verify(b"input key", key)
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- provider.
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
- :param int length: The desired length of the derived key. Maximum is
- ``255 * (algorithm.digest_size // 8)``.
+ :param int length: The desired length of the derived key in bytes. Maximum
+ is ``255 * (algorithm.digest_size // 8)``.
:param bytes salt: A salt. Randomizes the KDF's output. Optional, but
highly recommended. Ideally as many bits of entropy as the security
@@ -181,16 +181,15 @@ Different KDFs are suitable for different tasks such as:
long as the hash output. Worse (shorter, less entropy) salt values can
still meaningfully contribute to security. May be reused. Does not have
to be secret, but may cause stronger security guarantees if secret; see
- `RFC 5869`_ and the `HKDF paper`_ for more details. If ``None`` is
+ :rfc:`5869` and the `HKDF paper`_ for more details. If ``None`` is
explicitly passed a default salt of ``algorithm.digest_size // 8`` null
bytes will be used.
:param bytes info: Application specific context information. If ``None``
is explicitly passed an empty byte string will be used.
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`.
:raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
provided ``backend`` does not implement
@@ -201,10 +200,16 @@ Different KDFs are suitable for different tasks such as:
.. method:: derive(key_material)
- :param bytes key_material: The input key material.
+ :param key_material: The input key material.
+ :type key_material: :term:`bytes-like`
:return bytes: The derived key.
:raises TypeError: This exception is raised if ``key_material`` is not
``bytes``.
+ :raises cryptography.exceptions.AlreadyFinalized: This is raised when
+ :meth:`derive` or
+ :meth:`verify` is
+ called more than
+ once.
Derives a new key from the input key material by performing both the
extract and expand operations.
@@ -269,24 +274,21 @@ Different KDFs are suitable for different tasks such as:
... )
>>> hkdf.verify(key_material, key)
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- provider.
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
- :param int length: The desired length of the derived key. Maximum is
- ``255 * (algorithm.digest_size // 8)``.
+ :param int length: The desired length of the derived key in bytes. Maximum
+ is ``255 * (algorithm.digest_size // 8)``.
:param bytes info: Application specific context information. If ``None``
is explicitly passed an empty byte string will be used.
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`.
:raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
provided ``backend`` does not implement
:class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
- :raises TypeError: This is raised if the provided ``info`` is a unicode object
:raises TypeError: This exception is raised if ``info`` is not ``bytes``.
.. method:: derive(key_material)
@@ -294,10 +296,13 @@ Different KDFs are suitable for different tasks such as:
:param bytes key_material: The input key material.
:return bytes: The derived key.
- :raises TypeError: This is raised if the provided ``key_material`` is
- a unicode object
:raises TypeError: This exception is raised if ``key_material`` is not
``bytes``.
+ :raises cryptography.exceptions.AlreadyFinalized: This is raised when
+ :meth:`derive` or
+ :meth:`verify` is
+ called more than
+ once.
Derives a new key from the input key material by performing both the
extract and expand operations.
@@ -318,7 +323,7 @@ Different KDFs are suitable for different tasks such as:
called more than
once.
:raises TypeError: This is raised if the provided ``key_material`` is
- a unicode object
+ a ``unicode`` object
This checks whether deriving a new key from the supplied
``key_material`` generates the same key as the ``expected_key``, and
@@ -348,22 +353,21 @@ Different KDFs are suitable for different tasks such as:
>>> otherinfo = b"concatkdf-example"
>>> ckdf = ConcatKDFHash(
... algorithm=hashes.SHA256(),
- ... length=256,
+ ... length=32,
... otherinfo=otherinfo,
... backend=backend
... )
>>> key = ckdf.derive(b"input key")
>>> ckdf = ConcatKDFHash(
... algorithm=hashes.SHA256(),
- ... length=256,
+ ... length=32,
... otherinfo=otherinfo,
... backend=backend
... )
>>> ckdf.verify(b"input key", key)
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- provider
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
:param int length: The desired length of the derived key in bytes.
Maximum is ``hashlen * (2^32 -1)``.
@@ -371,9 +375,8 @@ Different KDFs are suitable for different tasks such as:
:param bytes otherinfo: Application specific context information.
If ``None`` is explicitly passed an empty byte string will be used.
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.HashBackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.HashBackend`.
:raises cryptography.exceptions.UnsupportedAlgorithm: This is raised
if the provided ``backend`` does not implement
@@ -384,10 +387,16 @@ Different KDFs are suitable for different tasks such as:
.. method:: derive(key_material)
- :param bytes key_material: The input key material.
+ :param key_material: The input key material.
+ :type key_material: :term:`bytes-like`
:return bytes: The derived key.
:raises TypeError: This exception is raised if ``key_material`` is
not ``bytes``.
+ :raises cryptography.exceptions.AlreadyFinalized: This is raised when
+ :meth:`derive` or
+ :meth:`verify` is
+ called more than
+ once.
Derives a new key from the input key material.
@@ -433,7 +442,7 @@ Different KDFs are suitable for different tasks such as:
>>> otherinfo = b"concatkdf-example"
>>> ckdf = ConcatKDFHMAC(
... algorithm=hashes.SHA256(),
- ... length=256,
+ ... length=32,
... salt=salt,
... otherinfo=otherinfo,
... backend=backend
@@ -441,16 +450,15 @@ Different KDFs are suitable for different tasks such as:
>>> key = ckdf.derive(b"input key")
>>> ckdf = ConcatKDFHMAC(
... algorithm=hashes.SHA256(),
- ... length=256,
+ ... length=32,
... salt=salt,
... otherinfo=otherinfo,
... backend=backend
... )
>>> ckdf.verify(b"input key", key)
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- provider
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
:param int length: The desired length of the derived key in bytes. Maximum
is ``hashlen * (2^32 -1)``.
@@ -466,9 +474,8 @@ Different KDFs are suitable for different tasks such as:
:param bytes otherinfo: Application specific context information.
If ``None`` is explicitly passed an empty byte string will be used.
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`.
:raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
provided ``backend`` does not implement
@@ -483,6 +490,241 @@ Different KDFs are suitable for different tasks such as:
:return bytes: The derived key.
:raises TypeError: This exception is raised if ``key_material`` is not
``bytes``.
+ :raises cryptography.exceptions.AlreadyFinalized: This is raised when
+ :meth:`derive` or
+ :meth:`verify` is
+ called more than
+ once.
+
+ Derives a new key from the input key material.
+
+ .. method:: verify(key_material, expected_key)
+
+ :param bytes key_material: The input key material. This is the same as
+ ``key_material`` in :meth:`derive`.
+ :param bytes expected_key: The expected result of deriving a new key,
+ this is the same as the return value of
+ :meth:`derive`.
+ :raises cryptography.exceptions.InvalidKey: This is raised when the
+ derived key does not match
+ the expected key.
+ :raises cryptography.exceptions.AlreadyFinalized: This is raised when
+ :meth:`derive` or
+ :meth:`verify` is
+ called more than
+ once.
+
+ This checks whether deriving a new key from the supplied
+ ``key_material`` generates the same key as the ``expected_key``, and
+ raises an exception if they do not match.
+
+.. currentmodule:: cryptography.hazmat.primitives.kdf.x963kdf
+
+.. class:: X963KDF(algorithm, length, otherinfo, backend)
+
+ .. versionadded:: 1.1
+
+ X963KDF (ANSI X9.63 Key Derivation Function) is defined by ANSI
+ in the `ANSI X9.63:2001`_ document, to be used to derive keys for use
+ after a Key Exchange negotiation operation.
+
+ SECG in `SEC 1 v2.0`_ recommends that
+ :class:`~cryptography.hazmat.primitives.kdf.concatkdf.ConcatKDFHash` be
+ used for new projects. This KDF should only be used for backwards
+ compatibility with pre-existing protocols.
+
+
+ .. warning::
+
+ X963KDF should not be used for password storage.
+
+ .. doctest::
+
+ >>> import os
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> from cryptography.hazmat.primitives.kdf.x963kdf import X963KDF
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> backend = default_backend()
+ >>> sharedinfo = b"ANSI X9.63 Example"
+ >>> xkdf = X963KDF(
+ ... algorithm=hashes.SHA256(),
+ ... length=32,
+ ... sharedinfo=sharedinfo,
+ ... backend=backend
+ ... )
+ >>> key = xkdf.derive(b"input key")
+ >>> xkdf = X963KDF(
+ ... algorithm=hashes.SHA256(),
+ ... length=32,
+ ... sharedinfo=sharedinfo,
+ ... backend=backend
+ ... )
+ >>> xkdf.verify(b"input key", key)
+
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
+
+ :param int length: The desired length of the derived key in bytes.
+ Maximum is ``hashlen * (2^32 -1)``.
+
+ :param bytes sharedinfo: Application specific context information.
+ If ``None`` is explicitly passed an empty byte string will be used.
+
+ :param backend: A cryptography backend
+ :class:`~cryptography.hazmat.backends.interfaces.HashBackend`
+ instance.
+
+ :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised
+ if the provided ``backend`` does not implement
+ :class:`~cryptography.hazmat.backends.interfaces.HashBackend`
+
+ :raises TypeError: This exception is raised if ``sharedinfo`` is not
+ ``bytes``.
+
+ .. method:: derive(key_material)
+
+ :param key_material: The input key material.
+ :type key_material: :term:`bytes-like`
+ :return bytes: The derived key.
+ :raises TypeError: This exception is raised if ``key_material`` is
+ not ``bytes``.
+ :raises cryptography.exceptions.AlreadyFinalized: This is raised when
+ :meth:`derive` or
+ :meth:`verify` is
+ called more than
+ once.
+
+ Derives a new key from the input key material.
+
+ .. method:: verify(key_material, expected_key)
+
+ :param bytes key_material: The input key material. This is the same as
+ ``key_material`` in :meth:`derive`.
+ :param bytes expected_key: The expected result of deriving a new key,
+ this is the same as the return value of
+ :meth:`derive`.
+ :raises cryptography.exceptions.InvalidKey: This is raised when the
+ derived key does not match
+ the expected key.
+ :raises cryptography.exceptions.AlreadyFinalized: This is raised when
+ :meth:`derive` or
+ :meth:`verify` is
+ called more than
+ once.
+
+ This checks whether deriving a new key from the supplied
+ ``key_material`` generates the same key as the ``expected_key``, and
+ raises an exception if they do not match.
+
+
+.. currentmodule:: cryptography.hazmat.primitives.kdf.kbkdf
+
+.. class:: KBKDFHMAC(algorithm, mode, length, rlen, llen, location,\
+ label, context, fixed, backend)
+
+ .. versionadded:: 1.4
+
+ KBKDF (Key Based Key Derivation Function) is defined by the
+ `NIST SP 800-108`_ document, to be used to derive additional
+ keys from a key that has been established through an automated
+ key-establishment scheme.
+
+ .. warning::
+
+ KBKDFHMAC should not be used for password storage.
+
+ .. doctest::
+
+ >>> import os
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> from cryptography.hazmat.primitives.kdf.kbkdf import (
+ ... CounterLocation, KBKDFHMAC, Mode
+ ... )
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> backend = default_backend()
+ >>> label = b"KBKDF HMAC Label"
+ >>> context = b"KBKDF HMAC Context"
+ >>> kdf = KBKDFHMAC(
+ ... algorithm=hashes.SHA256(),
+ ... mode=Mode.CounterMode,
+ ... length=32,
+ ... rlen=4,
+ ... llen=4,
+ ... location=CounterLocation.BeforeFixed,
+ ... label=label,
+ ... context=context,
+ ... fixed=None,
+ ... backend=backend
+ ... )
+ >>> key = kdf.derive(b"input key")
+ >>> kdf = KBKDFHMAC(
+ ... algorithm=hashes.SHA256(),
+ ... mode=Mode.CounterMode,
+ ... length=32,
+ ... rlen=4,
+ ... llen=4,
+ ... location=CounterLocation.BeforeFixed,
+ ... label=label,
+ ... context=context,
+ ... fixed=None,
+ ... backend=backend
+ ... )
+ >>> kdf.verify(b"input key", key)
+
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
+
+ :param mode: The desired mode of the PRF. A value from the
+ :class:`~cryptography.hazmat.primitives.kdf.kbkdf.Mode` enum.
+
+ :param int length: The desired length of the derived key in bytes.
+
+ :param int rlen: An integer that indicates the length of the binary
+ representation of the counter in bytes.
+
+ :param int llen: An integer that indicates the binary
+ representation of the ``length`` in bytes.
+
+ :param location: The desired location of the counter. A value from the
+ :class:`~cryptography.hazmat.primitives.kdf.kbkdf.CounterLocation` enum.
+
+ :param bytes label: Application specific label information. If ``None``
+ is explicitly passed an empty byte string will be used.
+
+ :param bytes context: Application specific context information. If ``None``
+ is explicitly passed an empty byte string will be used.
+
+ :param bytes fixed: Instead of specifying ``label`` and ``context`` you
+ may supply your own fixed data. If ``fixed`` is specified, ``label``
+ and ``context`` is ignored.
+
+ :param backend: A cryptography backend
+ :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
+ instance.
+
+ :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised
+ if the provided ``backend`` does not implement
+ :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
+
+ :raises TypeError: This exception is raised if ``label`` or ``context``
+ is not ``bytes``. Also raised if ``rlen`` or ``llen`` is not ``int``.
+
+ :raises ValueError: This exception is raised if ``rlen`` or ``llen``
+ is greater than 4 or less than 1. This exception is also raised if
+ you specify a ``label`` or ``context`` and ``fixed``.
+
+ .. method:: derive(key_material)
+
+ :param key_material: The input key material.
+ :type key_material: :term:`bytes-like`
+ :return bytes: The derived key.
+ :raises TypeError: This exception is raised if ``key_material`` is
+ not ``bytes``.
+ :raises cryptography.exceptions.AlreadyFinalized: This is raised when
+ :meth:`derive` or
+ :meth:`verify` is
+ called more than
+ once.
Derives a new key from the input key material.
@@ -506,6 +748,137 @@ Different KDFs are suitable for different tasks such as:
``key_material`` generates the same key as the ``expected_key``, and
raises an exception if they do not match.
+.. class:: Mode
+
+ An enumeration for the key based key derivative modes.
+
+ .. attribute:: CounterMode
+
+ The output of the PRF is computed with a counter
+ as the iteration variable.
+
+.. class:: CounterLocation
+
+ An enumeration for the key based key derivative counter location.
+
+ .. attribute:: BeforeFixed
+
+ The counter iteration variable will be concatenated before
+ the fixed input data.
+
+ .. attribute:: AfterFixed
+
+ The counter iteration variable will be concatenated after
+ the fixed input data.
+
+.. currentmodule:: cryptography.hazmat.primitives.kdf.scrypt
+
+.. class:: Scrypt(salt, length, n, r, p, backend)
+
+ .. versionadded:: 1.6
+
+ Scrypt is a KDF designed for password storage by Colin Percival to be
+ resistant against hardware-assisted attackers by having a tunable memory
+ cost. It is described in :rfc:`7914`.
+
+ This class conforms to the
+ :class:`~cryptography.hazmat.primitives.kdf.KeyDerivationFunction`
+ interface.
+
+ .. doctest::
+
+ >>> import os
+ >>> from cryptography.hazmat.primitives.kdf.scrypt import Scrypt
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> backend = default_backend()
+ >>> salt = os.urandom(16)
+ >>> # derive
+ >>> kdf = Scrypt(
+ ... salt=salt,
+ ... length=32,
+ ... n=2**14,
+ ... r=8,
+ ... p=1,
+ ... backend=backend
+ ... )
+ >>> key = kdf.derive(b"my great password")
+ >>> # verify
+ >>> kdf = Scrypt(
+ ... salt=salt,
+ ... length=32,
+ ... n=2**14,
+ ... r=8,
+ ... p=1,
+ ... backend=backend
+ ... )
+ >>> kdf.verify(b"my great password", key)
+
+ :param bytes salt: A salt.
+ :param int length: The desired length of the derived key in bytes.
+ :param int n: CPU/Memory cost parameter. It must be larger than 1 and be a
+ power of 2.
+ :param int r: Block size parameter.
+ :param int p: Parallelization parameter.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.ScryptBackend`.
+
+ The computational and memory cost of Scrypt can be adjusted by manipulating
+ the 3 parameters: ``n``, ``r``, and ``p``. In general, the memory cost of
+ Scrypt is affected by the values of both ``n`` and ``r``, while ``n`` also
+ determines the number of iterations performed. ``p`` increases the
+ computational cost without affecting memory usage. A more in-depth
+ explanation of the 3 parameters can be found `here`_.
+
+ :rfc:`7914` `recommends`_ values of ``r=8`` and ``p=1`` while scaling ``n``
+ to a number appropriate for your system. `The scrypt paper`_ suggests a
+ minimum value of ``n=2**14`` for interactive logins (t < 100ms), or
+ ``n=2**20`` for more sensitive files (t < 5s).
+
+ :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
+ provided ``backend`` does not implement
+ :class:`~cryptography.hazmat.backends.interfaces.ScryptBackend`
+
+ :raises TypeError: This exception is raised if ``salt`` is not ``bytes``.
+ :raises ValueError: This exception is raised if ``n`` is less than 2, if
+ ``n`` is not a power of 2, if ``r`` is less than 1 or if ``p`` is less
+ than 1.
+
+ .. method:: derive(key_material)
+
+ :param key_material: The input key material.
+ :type key_material: :term:`bytes-like`
+ :return bytes: the derived key.
+ :raises TypeError: This exception is raised if ``key_material`` is not
+ ``bytes``.
+ :raises cryptography.exceptions.AlreadyFinalized: This is raised when
+ :meth:`derive` or
+ :meth:`verify` is
+ called more than
+ once.
+
+ This generates and returns a new key from the supplied password.
+
+ .. method:: verify(key_material, expected_key)
+
+ :param bytes key_material: The input key material. This is the same as
+ ``key_material`` in :meth:`derive`.
+ :param bytes expected_key: The expected result of deriving a new key,
+ this is the same as the return value of
+ :meth:`derive`.
+ :raises cryptography.exceptions.InvalidKey: This is raised when the
+ derived key does not match
+ the expected key.
+ :raises cryptography.exceptions.AlreadyFinalized: This is raised when
+ :meth:`derive` or
+ :meth:`verify` is
+ called more than
+ once.
+
+ This checks whether deriving a new key from the supplied
+ ``key_material`` generates the same key as the ``expected_key``, and
+ raises an exception if they do not match. This can be used for
+ checking whether the password a user provides matches the stored derived
+ key.
Interface
~~~~~~~~~
@@ -554,12 +927,18 @@ Interface
stored derived key.
-.. _`NIST SP 800-132`: http://csrc.nist.gov/publications/nistpubs/800-132/nist-sp800-132.pdf
-.. _`NIST SP 800-56Ar2`: http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar2.pdf
-.. _`Password Storage Cheat Sheet`: https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet
+.. [#nist] See `NIST SP 800-132`_.
+
+.. _`NIST SP 800-132`: https://csrc.nist.gov/publications/detail/sp/800-132/final
+.. _`NIST SP 800-108`: https://csrc.nist.gov/publications/detail/sp/800-108/final
+.. _`NIST SP 800-56Ar2`: https://csrc.nist.gov/publications/detail/sp/800-56a/rev-2/final
+.. _`ANSI X9.63:2001`: https://webstore.ansi.org
+.. _`SEC 1 v2.0`: https://www.secg.org/sec1-v2.pdf
+.. _`more detailed description`: https://security.stackexchange.com/a/3993/43116
.. _`PBKDF2`: https://en.wikipedia.org/wiki/PBKDF2
-.. _`scrypt`: https://en.wikipedia.org/wiki/Scrypt
.. _`key stretching`: https://en.wikipedia.org/wiki/Key_stretching
-.. _`HKDF`:
-.. _`RFC 5869`: https://tools.ietf.org/html/rfc5869
+.. _`HKDF`: https://en.wikipedia.org/wiki/HKDF
.. _`HKDF paper`: https://eprint.iacr.org/2010/264
+.. _`here`: https://stackoverflow.com/a/30308723/1170681
+.. _`recommends`: https://tools.ietf.org/html/rfc7914#section-2
+.. _`The scrypt paper`: https://www.tarsnap.com/scrypt/scrypt.pdf
diff --git a/docs/hazmat/primitives/keywrap.rst b/docs/hazmat/primitives/keywrap.rst
new file mode 100644
index 00000000..1c15f9d1
--- /dev/null
+++ b/docs/hazmat/primitives/keywrap.rst
@@ -0,0 +1,98 @@
+.. hazmat::
+
+.. module:: cryptography.hazmat.primitives.keywrap
+
+Key wrapping
+============
+
+Key wrapping is a cryptographic construct that uses symmetric encryption to
+encapsulate key material. Key wrapping algorithms are occasionally utilized
+to protect keys at rest or transmit them over insecure networks. Many of the
+protections offered by key wrapping are also offered by using authenticated
+:doc:`symmetric encryption </hazmat/primitives/symmetric-encryption>`.
+
+.. function:: aes_key_wrap(wrapping_key, key_to_wrap, backend)
+
+ .. versionadded:: 1.1
+
+ This function performs AES key wrap (without padding) as specified in
+ :rfc:`3394`.
+
+ :param bytes wrapping_key: The wrapping key.
+
+ :param bytes key_to_wrap: The key to wrap.
+
+ :param backend: A
+ :class:`~cryptography.hazmat.backends.interfaces.CipherBackend`
+ instance that supports
+ :class:`~cryptography.hazmat.primitives.ciphers.algorithms.AES`.
+
+ :return bytes: The wrapped key as bytes.
+
+.. function:: aes_key_unwrap(wrapping_key, wrapped_key, backend)
+
+ .. versionadded:: 1.1
+
+ This function performs AES key unwrap (without padding) as specified in
+ :rfc:`3394`.
+
+ :param bytes wrapping_key: The wrapping key.
+
+ :param bytes wrapped_key: The wrapped key.
+
+ :param backend: A
+ :class:`~cryptography.hazmat.backends.interfaces.CipherBackend`
+ instance that supports
+ :class:`~cryptography.hazmat.primitives.ciphers.algorithms.AES`.
+
+ :return bytes: The unwrapped key as bytes.
+
+ :raises cryptography.hazmat.primitives.keywrap.InvalidUnwrap: This is
+ raised if the key is not successfully unwrapped.
+
+.. function:: aes_key_wrap_with_padding(wrapping_key, key_to_wrap, backend)
+
+ .. versionadded:: 2.2
+
+ This function performs AES key wrap with padding as specified in
+ :rfc:`5649`.
+
+ :param bytes wrapping_key: The wrapping key.
+
+ :param bytes key_to_wrap: The key to wrap.
+
+ :param backend: A
+ :class:`~cryptography.hazmat.backends.interfaces.CipherBackend`
+ instance that supports
+ :class:`~cryptography.hazmat.primitives.ciphers.algorithms.AES`.
+
+ :return bytes: The wrapped key as bytes.
+
+.. function:: aes_key_unwrap_with_padding(wrapping_key, wrapped_key, backend)
+
+ .. versionadded:: 2.2
+
+ This function performs AES key unwrap with padding as specified in
+ :rfc:`5649`.
+
+ :param bytes wrapping_key: The wrapping key.
+
+ :param bytes wrapped_key: The wrapped key.
+
+ :param backend: A
+ :class:`~cryptography.hazmat.backends.interfaces.CipherBackend`
+ instance that supports
+ :class:`~cryptography.hazmat.primitives.ciphers.algorithms.AES`.
+
+ :return bytes: The unwrapped key as bytes.
+
+ :raises cryptography.hazmat.primitives.keywrap.InvalidUnwrap: This is
+ raised if the key is not successfully unwrapped.
+
+Exceptions
+~~~~~~~~~~
+
+.. class:: InvalidUnwrap
+
+ This is raised when a wrapped key fails to unwrap. It can be caused by a
+ corrupted or invalid wrapped key or an invalid wrapping key.
diff --git a/docs/hazmat/primitives/mac/cmac.rst b/docs/hazmat/primitives/mac/cmac.rst
index e04a849f..a5b13caf 100644
--- a/docs/hazmat/primitives/mac/cmac.rst
+++ b/docs/hazmat/primitives/mac/cmac.rst
@@ -1,7 +1,7 @@
.. hazmat::
-Cipher-based message authentication code
-========================================
+Cipher-based message authentication code (CMAC)
+===============================================
.. currentmodule:: cryptography.hazmat.primitives.cmac
@@ -22,7 +22,7 @@ A subset of CMAC with the AES-128 algorithm is described in :rfc:`4493`.
.. versionadded:: 0.4
CMAC objects take a
- :class:`~cryptography.hazmat.primitives.ciphers.BlockCipherAlgorithm` provider.
+ :class:`~cryptography.hazmat.primitives.ciphers.BlockCipherAlgorithm` instance.
.. doctest::
@@ -32,7 +32,7 @@ A subset of CMAC with the AES-128 algorithm is described in :rfc:`4493`.
>>> c = cmac.CMAC(algorithms.AES(key), backend=default_backend())
>>> c.update(b"message to authenticate")
>>> c.finalize()
- 'CT\x1d\xc8\x0e\x15\xbe4e\xdb\xb6\x84\xca\xd9Xk'
+ b'CT\x1d\xc8\x0e\x15\xbe4e\xdb\xb6\x84\xca\xd9Xk'
If the backend doesn't support the requested ``algorithm`` an
:class:`~cryptography.exceptions.UnsupportedAlgorithm` exception will be
@@ -40,7 +40,7 @@ A subset of CMAC with the AES-128 algorithm is described in :rfc:`4493`.
If ``algorithm`` isn't a
:class:`~cryptography.hazmat.primitives.ciphers.BlockCipherAlgorithm`
- provider then ``TypeError`` will be raised.
+ instance then ``TypeError`` will be raised.
To check that a given signature is correct use the :meth:`verify` method.
You will receive an exception if the signature is wrong:
@@ -54,12 +54,10 @@ A subset of CMAC with the AES-128 algorithm is described in :rfc:`4493`.
...
cryptography.exceptions.InvalidSignature: Signature did not match digest.
- :param algorithm: An
- :class:`~cryptography.hazmat.primitives.ciphers.BlockCipherAlgorithm`
- provider.
- :param backend: An
- :class:`~cryptography.hazmat.backends.interfaces.CMACBackend`
- provider.
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.ciphers.BlockCipherAlgorithm`.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.CMACBackend`.
:raises TypeError: This is raised if the provided ``algorithm`` is not an instance of
:class:`~cryptography.hazmat.primitives.ciphers.BlockCipherAlgorithm`
:raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
diff --git a/docs/hazmat/primitives/mac/hmac.rst b/docs/hazmat/primitives/mac/hmac.rst
index 2515ac91..9d11694b 100644
--- a/docs/hazmat/primitives/mac/hmac.rst
+++ b/docs/hazmat/primitives/mac/hmac.rst
@@ -1,7 +1,7 @@
.. hazmat::
-Hash-based message authentication codes
-=======================================
+Hash-based message authentication codes (HMAC)
+==============================================
.. currentmodule:: cryptography.hazmat.primitives.hmac
@@ -18,7 +18,7 @@ of a message.
.. class:: HMAC(key, algorithm, backend)
HMAC objects take a ``key`` and a
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` provider.
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` instance.
The ``key`` should be :doc:`randomly generated bytes </random-numbers>` and
is recommended to be equal in length to the ``digest_size`` of the hash
function chosen. You must keep the ``key`` secret.
@@ -32,14 +32,14 @@ of a message.
>>> h = hmac.HMAC(key, hashes.SHA256(), backend=default_backend())
>>> h.update(b"message to hash")
>>> h.finalize()
- '#F\xdaI\x8b"e\xc4\xf1\xbb\x9a\x8fc\xff\xf5\xdex.\xbc\xcd/+\x8a\x86\x1d\x84\'\xc3\xa6\x1d\xd8J'
+ b'#F\xdaI\x8b"e\xc4\xf1\xbb\x9a\x8fc\xff\xf5\xdex.\xbc\xcd/+\x8a\x86\x1d\x84\'\xc3\xa6\x1d\xd8J'
If the backend doesn't support the requested ``algorithm`` an
:class:`~cryptography.exceptions.UnsupportedAlgorithm` exception will be
raised.
If ``algorithm`` isn't a
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` provider
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` instance
then ``TypeError`` will be raised.
To check that a given signature is correct use the :meth:`verify` method.
@@ -54,14 +54,15 @@ of a message.
...
cryptography.exceptions.InvalidSignature: Signature did not match digest.
- :param bytes key: Secret key as ``bytes``.
+ :param key: Secret key as ``bytes``.
+ :type key: :term:`bytes-like`
:param algorithm: An
:class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- provider such as those described in
+ instance such as those described in
:ref:`Cryptographic Hashes <cryptographic-hash-algorithms>`.
:param backend: An
:class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
- provider.
+ instance.
:raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
provided ``backend`` does not implement
@@ -69,7 +70,8 @@ of a message.
.. method:: update(msg)
- :param bytes msg: The bytes to hash and authenticate.
+ :param msg: The bytes to hash and authenticate.
+ :type msg: :term:`bytes-like`
:raises cryptography.exceptions.AlreadyFinalized: See :meth:`finalize`
:raises TypeError: This exception is raised if ``msg`` is not ``bytes``.
diff --git a/docs/hazmat/primitives/mac/index.rst b/docs/hazmat/primitives/mac/index.rst
index bc54bae4..8bfe29e3 100644
--- a/docs/hazmat/primitives/mac/index.rst
+++ b/docs/hazmat/primitives/mac/index.rst
@@ -3,16 +3,17 @@
Message authentication codes
============================
-While cryptography supports both the CMAC and HMAC algorithms, we strongly
-recommend that HMAC should be used unless you have a good reason otherwise.
+While cryptography supports multiple MAC algorithms, we strongly
+recommend that HMAC should be used unless you have a very specific need.
For more information on why HMAC is preferred, see `Use cases for CMAC vs.
HMAC?`_
-.. _`Use cases for CMAC vs. HMAC?`: http://crypto.stackexchange.com/questions/15721/use-cases-for-cmac-vs-hmac
-
.. toctree::
:maxdepth: 1
cmac
hmac
+ poly1305
+
+.. _`Use cases for CMAC vs. HMAC?`: https://crypto.stackexchange.com/questions/15721/use-cases-for-cmac-vs-hmac
diff --git a/docs/hazmat/primitives/mac/poly1305.rst b/docs/hazmat/primitives/mac/poly1305.rst
new file mode 100644
index 00000000..7504a076
--- /dev/null
+++ b/docs/hazmat/primitives/mac/poly1305.rst
@@ -0,0 +1,132 @@
+.. hazmat::
+
+Poly1305
+========
+
+.. currentmodule:: cryptography.hazmat.primitives.poly1305
+
+.. testsetup::
+
+ key = b"\x01" * 32
+
+Poly1305 is an authenticator that takes a 32-byte key and a message and
+produces a 16-byte tag. This tag is used to authenticate the message. Each key
+**must** only be used once. Using the same key to generate tags for multiple
+messages allows an attacker to forge tags. Poly1305 is described in
+:rfc:`7539`.
+
+.. class:: Poly1305(key)
+
+ .. versionadded:: 2.7
+
+ .. warning::
+
+ Using the same key to generate tags for multiple messages allows an
+ attacker to forge tags. Always generate a new key per message you want
+ to authenticate. If you are using this as a MAC for
+ symmetric encryption please use
+ :class:`~cryptography.hazmat.primitives.ciphers.aead.ChaCha20Poly1305`
+ instead.
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.primitives import poly1305
+ >>> p = poly1305.Poly1305(key)
+ >>> p.update(b"message to authenticate")
+ >>> p.finalize()
+ b'T\xae\xff3\xbdW\xef\xd5r\x01\xe2n=\xb7\xd2h'
+
+ To check that a given tag is correct use the :meth:`verify` method.
+ You will receive an exception if the tag is wrong:
+
+ .. doctest::
+
+ >>> p = poly1305.Poly1305(key)
+ >>> p.update(b"message to authenticate")
+ >>> p.verify(b"an incorrect tag")
+ Traceback (most recent call last):
+ ...
+ cryptography.exceptions.InvalidSignature: Value did not match computed tag.
+
+ :param key: Secret key as ``bytes``.
+ :type key: :term:`bytes-like`
+ :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if
+ the version of OpenSSL ``cryptography`` is compiled against does not
+ support this algorithm.
+
+ .. method:: update(data)
+
+ :param data: The bytes to hash and authenticate.
+ :type data: :term:`bytes-like`
+ :raises cryptography.exceptions.AlreadyFinalized: See :meth:`finalize`
+ :raises TypeError: This exception is raised if ``data`` is not ``bytes``.
+
+ .. method:: verify(tag)
+
+ Finalize the current context and securely compare the MAC to
+ ``tag``.
+
+ :param bytes tag: The bytes to compare against.
+ :raises cryptography.exceptions.AlreadyFinalized: See :meth:`finalize`
+ :raises cryptography.exceptions.InvalidSignature: If tag does not
+ match.
+ :raises TypeError: This exception is raised if ``tag`` is not
+ ``bytes``.
+
+ .. method:: finalize()
+
+ Finalize the current context and return the message authentication code
+ as bytes.
+
+ After ``finalize`` has been called this object can no longer be used
+ and :meth:`update`, :meth:`verify`, and :meth:`finalize`
+ will raise an :class:`~cryptography.exceptions.AlreadyFinalized`
+ exception.
+
+ :return bytes: The message authentication code as bytes.
+ :raises cryptography.exceptions.AlreadyFinalized:
+
+ .. classmethod:: generate_tag(key, data)
+
+ A single step alternative to do sign operations. Returns the message
+ authentication code as ``bytes`` for the given ``key`` and ``data``.
+
+ :param key: Secret key as ``bytes``.
+ :type key: :term:`bytes-like`
+ :param data: The bytes to hash and authenticate.
+ :type data: :term:`bytes-like`
+ :return bytes: The message authentication code as bytes.
+ :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if
+ the version of OpenSSL ``cryptography`` is compiled against does not
+ support this algorithm.
+ :raises TypeError: This exception is raised if ``key`` or ``data`` are
+ not ``bytes``.
+
+ .. doctest::
+
+ >>> poly1305.Poly1305.generate_tag(key, b"message to authenticate")
+ b'T\xae\xff3\xbdW\xef\xd5r\x01\xe2n=\xb7\xd2h'
+
+ .. classmethod:: verify_tag(key, data, tag)
+
+ A single step alternative to do verify operations. Securely compares the
+ MAC to ``tag``, using the given ``key`` and ``data``.
+
+ :param key: Secret key as ``bytes``.
+ :type key: :term:`bytes-like`
+ :param data: The bytes to hash and authenticate.
+ :type data: :term:`bytes-like`
+ :param bytes tag: The bytes to compare against.
+ :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if
+ the version of OpenSSL ``cryptography`` is compiled against does not
+ support this algorithm.
+ :raises TypeError: This exception is raised if ``key``, ``data`` or
+ ``tag`` are not ``bytes``.
+ :raises cryptography.exceptions.InvalidSignature: If tag does not match.
+
+ .. doctest::
+
+ >>> poly1305.Poly1305.verify_tag(key, b"message to authenticate", b"an incorrect tag")
+ Traceback (most recent call last):
+ ...
+ cryptography.exceptions.InvalidSignature: Value did not match computed tag.
diff --git a/docs/hazmat/primitives/padding.rst b/docs/hazmat/primitives/padding.rst
index a60f5ac8..9581df88 100644
--- a/docs/hazmat/primitives/padding.rst
+++ b/docs/hazmat/primitives/padding.rst
@@ -1,7 +1,7 @@
.. hazmat::
-Padding
-=======
+Symmetric Padding
+=================
.. module:: cryptography.hazmat.primitives.padding
@@ -25,33 +25,76 @@ multiple of the block size.
>>> padder = padding.PKCS7(128).padder()
>>> padded_data = padder.update(b"11111111111111112222222222")
>>> padded_data
- '1111111111111111'
+ b'1111111111111111'
>>> padded_data += padder.finalize()
>>> padded_data
- '11111111111111112222222222\x06\x06\x06\x06\x06\x06'
+ b'11111111111111112222222222\x06\x06\x06\x06\x06\x06'
>>> unpadder = padding.PKCS7(128).unpadder()
>>> data = unpadder.update(padded_data)
>>> data
- '1111111111111111'
+ b'1111111111111111'
>>> data + unpadder.finalize()
- '11111111111111112222222222'
+ b'11111111111111112222222222'
- :param block_size: The size of the block in bits that the data is being
- padded to.
+ :param block_size: The size of the block in :term:`bits` that the data is
+ being padded to.
:raises ValueError: Raised if block size is not a multiple of 8 or is not
- between 0 and 256.
+ between 0 and 2040 inclusive.
.. method:: padder()
:returns: A padding
:class:`~cryptography.hazmat.primitives.padding.PaddingContext`
- provider.
+ instance.
.. method:: unpadder()
:returns: An unpadding
:class:`~cryptography.hazmat.primitives.padding.PaddingContext`
- provider.
+ instance.
+
+
+.. class:: ANSIX923(block_size)
+
+ .. versionadded:: 1.3
+
+ `ANSI X.923`_ padding works by appending ``N-1`` bytes with the value of
+ ``0`` and a last byte with the value of ``chr(N)``, where ``N`` is the
+ number of bytes required to make the final block of data the same size as
+ the block size. A simple example of padding is:
+
+ .. doctest::
+
+ >>> padder = padding.ANSIX923(128).padder()
+ >>> padded_data = padder.update(b"11111111111111112222222222")
+ >>> padded_data
+ b'1111111111111111'
+ >>> padded_data += padder.finalize()
+ >>> padded_data
+ b'11111111111111112222222222\x00\x00\x00\x00\x00\x06'
+ >>> unpadder = padding.ANSIX923(128).unpadder()
+ >>> data = unpadder.update(padded_data)
+ >>> data
+ b'1111111111111111'
+ >>> data + unpadder.finalize()
+ b'11111111111111112222222222'
+
+ :param block_size: The size of the block in :term:`bits` that the data is
+ being padded to.
+ :raises ValueError: Raised if block size is not a multiple of 8 or is not
+ between 0 and 2040 inclusive.
+
+ .. method:: padder()
+
+ :returns: A padding
+ :class:`~cryptography.hazmat.primitives.padding.PaddingContext`
+ instance.
+
+ .. method:: unpadder()
+
+ :returns: An unpadding
+ :class:`~cryptography.hazmat.primitives.padding.PaddingContext`
+ instance.
.. class:: PaddingContext
@@ -82,3 +125,5 @@ multiple of the block size.
:raises TypeError: Raised if data is not bytes.
:raises ValueError: When trying to remove padding from incorrectly
padded data.
+
+.. _`ANSI X.923`: https://en.wikipedia.org/wiki/Padding_%28cryptography%29#ANSI_X9.23
diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst
index 309c6fd0..46f0786d 100644
--- a/docs/hazmat/primitives/symmetric-encryption.rst
+++ b/docs/hazmat/primitives/symmetric-encryption.rst
@@ -16,6 +16,9 @@ decrypt them.
For this reason it is **strongly** recommended to combine encryption with a
message authentication code, such as :doc:`HMAC </hazmat/primitives/mac/hmac>`,
in an "encrypt-then-MAC" formulation as `described by Colin Percival`_.
+``cryptography`` includes a recipe named :doc:`/fernet` that does this for you.
+**To minimize the risk of security issues you should evaluate Fernet to see if
+it fits your needs before implementing anything using this module.**
.. class:: Cipher(algorithm, mode, backend)
@@ -39,18 +42,18 @@ in an "encrypt-then-MAC" formulation as `described by Colin Percival`_.
>>> ct = encryptor.update(b"a secret message") + encryptor.finalize()
>>> decryptor = cipher.decryptor()
>>> decryptor.update(ct) + decryptor.finalize()
- 'a secret message'
+ b'a secret message'
- :param algorithms: A
+ :param algorithm: A
:class:`~cryptography.hazmat.primitives.ciphers.CipherAlgorithm`
- provider such as those described
+ instance such as those described
:ref:`below <symmetric-encryption-algorithms>`.
:param mode: A :class:`~cryptography.hazmat.primitives.ciphers.modes.Mode`
- provider such as those described
+ instance such as those described
:ref:`below <symmetric-encryption-modes>`.
:param backend: A
:class:`~cryptography.hazmat.backends.interfaces.CipherBackend`
- provider.
+ instance.
:raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
provided ``backend`` does not implement
@@ -60,7 +63,7 @@ in an "encrypt-then-MAC" formulation as `described by Colin Percival`_.
:return: An encrypting
:class:`~cryptography.hazmat.primitives.ciphers.CipherContext`
- provider.
+ instance.
If the backend doesn't support the requested combination of ``cipher``
and ``mode`` an :class:`~cryptography.exceptions.UnsupportedAlgorithm`
@@ -70,7 +73,7 @@ in an "encrypt-then-MAC" formulation as `described by Colin Percival`_.
:return: A decrypting
:class:`~cryptography.hazmat.primitives.ciphers.CipherContext`
- provider.
+ instance.
If the backend doesn't support the requested combination of ``cipher``
and ``mode`` an :class:`~cryptography.exceptions.UnsupportedAlgorithm`
@@ -89,8 +92,9 @@ Algorithms
AES is both fast, and cryptographically strong. It is a good default
choice for encryption.
- :param bytes key: The secret key. This must be kept secret. Either ``128``,
- ``192``, or ``256`` bits long.
+ :param key: The secret key. This must be kept secret. Either ``128``,
+ ``192``, or ``256`` :term:`bits` long.
+ :type key: :term:`bytes-like`
.. class:: Camellia(key)
@@ -98,22 +102,76 @@ Algorithms
It is considered to have comparable security and performance to AES but
is not as widely studied or deployed.
- :param bytes key: The secret key. This must be kept secret. Either ``128``,
- ``192``, or ``256`` bits long.
+ :param key: The secret key. This must be kept secret. Either ``128``,
+ ``192``, or ``256`` :term:`bits` long.
+ :type key: :term:`bytes-like`
+
+.. class:: ChaCha20(key)
+
+ .. versionadded:: 2.1
+
+ .. note::
+
+ In most cases users should use
+ :class:`~cryptography.hazmat.primitives.ciphers.aead.ChaCha20Poly1305`
+ instead of this class. `ChaCha20` alone does not provide integrity
+ so it must be combined with a MAC to be secure.
+ :class:`~cryptography.hazmat.primitives.ciphers.aead.ChaCha20Poly1305`
+ does this for you.
+
+ ChaCha20 is a stream cipher used in several IETF protocols. It is
+ standardized in :rfc:`7539`.
+
+ :param key: The secret key. This must be kept secret. ``256``
+ :term:`bits` (32 bytes) in length.
+ :type key: :term:`bytes-like`
+
+ :param nonce: Should be unique, a :term:`nonce`. It is
+ critical to never reuse a ``nonce`` with a given key. Any reuse of a
+ nonce with the same key compromises the security of every message
+ encrypted with that key. The nonce does not need to be kept secret
+ and may be included with the ciphertext. This must be ``128``
+ :term:`bits` in length.
+ :type nonce: :term:`bytes-like`
+
+ .. note::
+
+ In :rfc:`7539` the nonce is defined as a 96-bit value that is later
+ concatenated with a block counter (encoded as a 32-bit
+ little-endian). If you have a separate nonce and block counter
+ you will need to concatenate it yourself before passing it. For
+ example, if you have an initial block counter of 2 and a 96-bit
+ nonce the concatenated nonce would be
+ ``struct.pack("<i", 2) + nonce``.
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> nonce = os.urandom(16)
+ >>> algorithm = algorithms.ChaCha20(key, nonce)
+ >>> cipher = Cipher(algorithm, mode=None, backend=default_backend())
+ >>> encryptor = cipher.encryptor()
+ >>> ct = encryptor.update(b"a secret message")
+ >>> decryptor = cipher.decryptor()
+ >>> decryptor.update(ct)
+ b'a secret message'
.. class:: TripleDES(key)
Triple DES (Data Encryption Standard), sometimes referred to as 3DES, is a
block cipher standardized by NIST. Triple DES has known crypto-analytic
flaws, however none of them currently enable a practical attack.
- Nonetheless, Triples DES is not recommended for new applications because it
+ Nonetheless, Triple DES is not recommended for new applications because it
is incredibly slow; old applications should consider moving away from it.
- :param bytes key: The secret key. This must be kept secret. Either ``64``,
- ``128``, or ``192`` bits long. DES only uses ``56``, ``112``, or ``168``
- bits of the key as there is a parity byte in each component of the key.
- Some writing refers to there being up to three separate keys that are each
- ``56`` bits long, they can simply be concatenated to produce the full key.
+ :param key: The secret key. This must be kept secret. Either ``64``,
+ ``128``, or ``192`` :term:`bits` long. DES only uses ``56``, ``112``,
+ or ``168`` bits of the key as there is a parity byte in each component
+ of the key. Some writing refers to there being up to three separate
+ keys that are each ``56`` bits long, they can simply be concatenated
+ to produce the full key.
+ :type key: :term:`bytes-like`
.. class:: CAST5(key)
@@ -121,10 +179,12 @@ Algorithms
CAST5 (also known as CAST-128) is a block cipher approved for use in the
Canadian government by the `Communications Security Establishment`_. It is
- a variable key length cipher and supports keys from 40-128 bits in length.
+ a variable key length cipher and supports keys from 40-128 :term:`bits` in
+ length.
- :param bytes key: The secret key, This must be kept secret. 40 to 128 bits
- in length in increments of 8 bits.
+ :param key: The secret key, This must be kept secret. 40 to 128
+ :term:`bits` in length in increments of 8 bits.
+ :type key: :term:`bytes-like`
.. class:: SEED(key)
@@ -134,8 +194,9 @@ Algorithms
(KISA). It is defined in :rfc:`4269` and is used broadly throughout South
Korean industry, but rarely found elsewhere.
- :param bytes key: The secret key. This must be kept secret. ``128`` bits in
- length.
+ :param key: The secret key. This must be kept secret. ``128``
+ :term:`bits` in length.
+ :type key: :term:`bytes-like`
Weak ciphers
------------
@@ -152,8 +213,9 @@ Weak ciphers
susceptible to attacks when using weak keys. The author has recommended
that users of Blowfish move to newer algorithms such as :class:`AES`.
- :param bytes key: The secret key. This must be kept secret. 32 to 448 bits
- in length in increments of 8 bits.
+ :param key: The secret key. This must be kept secret. 32 to 448
+ :term:`bits` in length in increments of 8 bits.
+ :type key: :term:`bytes-like`
.. class:: ARC4(key)
@@ -161,8 +223,10 @@ Weak ciphers
initial stream output. Its use is strongly discouraged. ARC4 does not use
mode constructions.
- :param bytes key: The secret key. This must be kept secret. Either ``40``,
- ``56``, ``64``, ``80``, ``128``, ``192``, or ``256`` bits in length.
+ :param key: The secret key. This must be kept secret. Either ``40``,
+ ``56``, ``64``, ``80``, ``128``, ``192``, or ``256`` :term:`bits` in
+ length.
+ :type key: :term:`bytes-like`
.. doctest::
@@ -174,7 +238,7 @@ Weak ciphers
>>> ct = encryptor.update(b"a secret message")
>>> decryptor = cipher.decryptor()
>>> decryptor.update(ct)
- 'a secret message'
+ b'a secret message'
.. class:: IDEA(key)
@@ -183,8 +247,9 @@ Weak ciphers
is susceptible to attacks when using weak keys. It is recommended that you
do not use this cipher for new applications.
- :param bytes key: The secret key. This must be kept secret. ``128`` bits in
- length.
+ :param key: The secret key. This must be kept secret. ``128``
+ :term:`bits` in length.
+ :type key: :term:`bytes-like`
.. _symmetric-encryption-modes:
@@ -201,13 +266,14 @@ Modes
**Padding is required when using this mode.**
- :param bytes initialization_vector: Must be :doc:`random bytes
+ :param initialization_vector: Must be :doc:`random bytes
</random-numbers>`. They do not need to be kept secret and they can be
included in a transmitted message. Must be the same number of bytes as
the ``block_size`` of the cipher. Each time something is encrypted a
new ``initialization_vector`` should be generated. Do not reuse an
``initialization_vector`` with a given ``key``, and particularly do not
use a constant ``initialization_vector``.
+ :type initialization_vector: :term:`bytes-like`
A good construction looks like:
@@ -223,7 +289,7 @@ Modes
.. doctest::
>>> from cryptography.hazmat.primitives.ciphers.modes import CBC
- >>> iv = "a" * 16
+ >>> iv = b"a" * 16
>>> mode = CBC(iv)
@@ -232,7 +298,7 @@ Modes
.. warning::
Counter mode is not recommended for use with block ciphers that have a
- block size of less than 128-bits.
+ block size of less than 128-:term:`bits`.
CTR (Counter) is a mode of operation for block ciphers. It is considered
cryptographically strong. It transforms a block cipher into a stream
@@ -240,12 +306,13 @@ Modes
**This mode does not require padding.**
- :param bytes nonce: Should be unique, a :term:`nonce`. It is
+ :param nonce: Should be unique, a :term:`nonce`. It is
critical to never reuse a ``nonce`` with a given key. Any reuse of a
nonce with the same key compromises the security of every message
encrypted with that key. Must be the same number of bytes as the
``block_size`` of the cipher with a given key. The nonce does not need
to be kept secret and may be included with the ciphertext.
+ :type nonce: :term:`bytes-like`
.. class:: OFB(initialization_vector)
@@ -254,11 +321,12 @@ Modes
**This mode does not require padding.**
- :param bytes initialization_vector: Must be :doc:`random bytes
+ :param initialization_vector: Must be :doc:`random bytes
</random-numbers>`. They do not need to be kept secret and they can be
included in a transmitted message. Must be the same number of bytes as
the ``block_size`` of the cipher. Do not reuse an
``initialization_vector`` with a given ``key``.
+ :type initialization_vector: :term:`bytes-like`
.. class:: CFB(initialization_vector)
@@ -267,11 +335,12 @@ Modes
**This mode does not require padding.**
- :param bytes initialization_vector: Must be :doc:`random bytes
+ :param initialization_vector: Must be :doc:`random bytes
</random-numbers>`. They do not need to be kept secret and they can be
included in a transmitted message. Must be the same number of bytes as
the ``block_size`` of the cipher. Do not reuse an
``initialization_vector`` with a given ``key``.
+ :type initialization_vector: :term:`bytes-like`
.. class:: CFB8(initialization_vector)
@@ -281,18 +350,27 @@ Modes
**This mode does not require padding.**
- :param bytes initialization_vector: Must be :doc:`random bytes
+ :param initialization_vector: Must be :doc:`random bytes
</random-numbers>`. They do not need to be kept secret and they can be
included in a transmitted message. Must be the same number of bytes as
the ``block_size`` of the cipher. Do not reuse an
``initialization_vector`` with a given ``key``.
+ :type initialization_vector: :term:`bytes-like`
.. class:: GCM(initialization_vector, tag=None, min_tag_length=16)
.. danger::
+ If you are encrypting data that can fit into memory you should strongly
+ consider using
+ :class:`~cryptography.hazmat.primitives.ciphers.aead.AESGCM` instead
+ of this.
+
When using this mode you **must** not use the decrypted data until
- :meth:`~cryptography.hazmat.primitives.ciphers.CipherContext.finalize`
+ the appropriate finalization method
+ (:meth:`~cryptography.hazmat.primitives.ciphers.CipherContext.finalize`
+ or
+ :meth:`~cryptography.hazmat.primitives.ciphers.AEADDecryptionContext.finalize_with_tag`)
has been called. GCM provides **no** guarantees of ciphertext integrity
until decryption is complete.
@@ -305,20 +383,22 @@ Modes
**This mode does not require padding.**
- :param bytes initialization_vector: Must be unique, a :term:`nonce`.
+ :param initialization_vector: Must be unique, a :term:`nonce`.
They do not need to be kept secret and they can be included in a
transmitted message. NIST `recommends a 96-bit IV length`_ for
performance critical situations but it can be up to 2\ :sup:`64` - 1
- bits. Do not reuse an ``initialization_vector`` with a given ``key``.
+ :term:`bits`. Do not reuse an ``initialization_vector`` with a given
+ ``key``.
+ :type initialization_vector: :term:`bytes-like`
.. note::
Cryptography will generate a 128-bit tag when finalizing encryption.
You can shorten a tag by truncating it to the desired length but this
- is **not recommended** as it lowers the security margins of the
- authentication (`NIST SP-800-38D`_ recommends 96-bits or greater).
- Applications wishing to allow truncation must pass the
- ``min_tag_length`` parameter.
+ is **not recommended** as it makes it easier to forge messages, and
+ also potentially leaks the key (`NIST SP-800-38D`_ recommends
+ 96-:term:`bits` or greater). Applications wishing to allow truncation
+ can pass the ``min_tag_length`` parameter.
.. versionchanged:: 0.5
@@ -326,18 +406,26 @@ Modes
truncation down to ``4`` bytes was always allowed.
:param bytes tag: The tag bytes to verify during decryption. When
- encrypting this must be ``None``.
+ encrypting this must be ``None``. When decrypting, it may be ``None``
+ if the tag is supplied on finalization using
+ :meth:`~cryptography.hazmat.primitives.ciphers.AEADDecryptionContext.finalize_with_tag`.
+ Otherwise, the tag is mandatory.
- :param bytes min_tag_length: The minimum length ``tag`` must be. By default
+ :param int min_tag_length: The minimum length ``tag`` must be. By default
this is ``16``, meaning tag truncation is not allowed. Allowing tag
truncation is strongly discouraged for most applications.
- :raises ValueError: This is raised if ``len(tag) < min_tag_length``.
+ :raises ValueError: This is raised if ``len(tag) < min_tag_length`` or the
+ ``initialization_vector`` is too short.
+
+ An example of securely encrypting and decrypting data with ``AES`` in the
+ ``GCM`` mode looks like:
.. testcode::
import os
+ from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.ciphers import (
Cipher, algorithms, modes
)
@@ -397,8 +485,34 @@ Modes
.. testoutput::
- a secret message!
+ b'a secret message!'
+
+.. class:: XTS(tweak)
+
+ .. versionadded:: 2.1
+
+ .. warning::
+
+ XTS mode is meant for disk encryption and should not be used in other
+ contexts. ``cryptography`` only supports XTS mode with
+ :class:`~cryptography.hazmat.primitives.ciphers.algorithms.AES`.
+ .. note::
+
+ AES XTS keys are double length. This means that to do AES-128
+ encryption in XTS mode you need a 256-bit key. Similarly, AES-256
+ requires passing a 512-bit key. AES 192 is not supported in XTS mode.
+
+ XTS (XEX-based tweaked-codebook mode with ciphertext stealing) is a mode
+ of operation for the AES block cipher that is used for `disk encryption`_.
+
+ **This mode does not require padding.**
+
+ :param tweak: The tweak is a 16 byte value typically derived from
+ something like the disk sector number. A given ``(tweak, key)`` pair
+ should not be reused, although doing so is less catastrophic than
+ in CTR mode.
+ :type tweak: :term:`bytes-like`
Insecure modes
--------------
@@ -419,7 +533,7 @@ Insecure modes
**Padding is required when using this mode.**
Interfaces
-----------
+~~~~~~~~~~
.. currentmodule:: cryptography.hazmat.primitives.ciphers
@@ -443,7 +557,8 @@ Interfaces
.. method:: update(data)
- :param bytes data: The data you wish to pass into the context.
+ :param data: The data you wish to pass into the context.
+ :type data: :term:`bytes-like`
:return bytes: Returns the data that was encrypted or decrypted.
:raises cryptography.exceptions.AlreadyFinalized: See :meth:`finalize`
@@ -453,6 +568,50 @@ Interfaces
return bytes immediately, however in other modes it will return chunks
whose size is determined by the cipher's block size.
+ .. method:: update_into(data, buf)
+
+ .. versionadded:: 1.8
+
+ .. warning::
+
+ This method allows you to avoid a memory copy by passing a writable
+ buffer and reading the resulting data. You are responsible for
+ correctly sizing the buffer and properly handling the data. This
+ method should only be used when extremely high performance is a
+ requirement and you will be making many small calls to
+ ``update_into``.
+
+ :param data: The data you wish to pass into the context.
+ :type data: :term:`bytes-like`
+ :param buf: A writable Python buffer that the data will be written
+ into. This buffer should be ``len(data) + n - 1`` bytes where ``n``
+ is the block size (in bytes) of the cipher and mode combination.
+ :return int: Number of bytes written.
+ :raises NotImplementedError: This is raised if the version of ``cffi``
+ used is too old (this can happen on older PyPy releases).
+ :raises ValueError: This is raised if the supplied buffer is too small.
+
+ .. doctest::
+
+ >>> import os
+ >>> from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> backend = default_backend()
+ >>> key = os.urandom(32)
+ >>> iv = os.urandom(16)
+ >>> cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=backend)
+ >>> encryptor = cipher.encryptor()
+ >>> # the buffer needs to be at least len(data) + n - 1 where n is cipher/mode block size in bytes
+ >>> buf = bytearray(31)
+ >>> len_encrypted = encryptor.update_into(b"a secret message", buf)
+ >>> # get the ciphertext from the buffer reading only the bytes written to it (len_encrypted)
+ >>> ct = bytes(buf[:len_encrypted]) + encryptor.finalize()
+ >>> decryptor = cipher.decryptor()
+ >>> len_decrypted = decryptor.update_into(ct, buf)
+ >>> # get the plaintext from the buffer reading only the bytes written (len_decrypted)
+ >>> bytes(buf[:len_decrypted]) + decryptor.finalize()
+ b'a secret message'
+
.. method:: finalize()
:return bytes: Returns the remainder of the data.
@@ -469,12 +628,12 @@ Interfaces
with an AEAD mode (e.g.
:class:`~cryptography.hazmat.primitives.ciphers.modes.GCM`) the result will
conform to the ``AEADCipherContext`` and ``CipherContext`` interfaces. If
- it is an encryption context it will additionally be an
- ``AEADEncryptionContext`` provider. ``AEADCipherContext`` contains an
- additional method :meth:`authenticate_additional_data` for adding
- additional authenticated but unencrypted data (see note below). You should
- call this before calls to ``update``. When you are done call ``finalize``
- to finish the operation.
+ it is an encryption or decryption context it will additionally be an
+ ``AEADEncryptionContext`` or ``AEADDecryptionContext`` instance,
+ respectively. ``AEADCipherContext`` contains an additional method
+ :meth:`authenticate_additional_data` for adding additional authenticated
+ but unencrypted data (see note below). You should call this before calls to
+ ``update``. When you are done call ``finalize`` to finish the operation.
.. note::
@@ -485,7 +644,8 @@ Interfaces
.. method:: authenticate_additional_data(data)
- :param bytes data: Any data you wish to authenticate but not encrypt.
+ :param data: Any data you wish to authenticate but not encrypt.
+ :type data: :term:`bytes-like`
:raises: :class:`~cryptography.exceptions.AlreadyFinalized`
.. class:: AEADEncryptionContext
@@ -504,6 +664,32 @@ Interfaces
:raises: :class:`~cryptography.exceptions.NotYetFinalized` if called
before the context is finalized.
+.. class:: AEADDecryptionContext
+
+ .. versionadded:: 1.9
+
+ When creating an encryption context using ``decryptor`` on a ``Cipher``
+ object with an AEAD mode such as
+ :class:`~cryptography.hazmat.primitives.ciphers.modes.GCM` an object
+ conforming to both the ``AEADDecryptionContext`` and ``AEADCipherContext``
+ interfaces will be returned. This interface provides one additional method
+ :meth:`finalize_with_tag` that allows passing the authentication tag for
+ validation after the ciphertext has been decrypted.
+
+ .. method:: finalize_with_tag(tag)
+
+ :param bytes tag: The tag bytes to verify after decryption.
+ :return bytes: Returns the remainder of the data.
+ :raises ValueError: This is raised when the data provided isn't
+ a multiple of the algorithm's block size, if ``min_tag_length`` is
+ less than 4, or if ``len(tag) < min_tag_length``.
+ ``min_tag_length`` is an argument to the ``GCM`` constructor.
+
+ If the authentication tag was not already supplied to the constructor
+ of the :class:`~cryptography.hazmat.primitives.ciphers.modes.GCM` mode
+ object, this method must be used instead of
+ :meth:`~cryptography.hazmat.primitives.ciphers.CipherContext.finalize`.
+
.. class:: CipherAlgorithm
A named symmetric encryption algorithm.
@@ -519,7 +705,7 @@ Interfaces
:type: int
- The number of bits in the key being used.
+ The number of :term:`bits` in the key being used.
.. class:: BlockCipherAlgorithm
@@ -530,7 +716,7 @@ Interfaces
:type: int
- The number of bits in a block.
+ The number of :term:`bits` in a block.
Interfaces used by the symmetric cipher modes described in
:ref:`Symmetric Encryption Modes <symmetric-encryption-modes>`.
@@ -571,7 +757,7 @@ Interfaces used by the symmetric cipher modes described in
.. attribute:: initialization_vector
- :type: bytes
+ :type: :term:`bytes-like`
Exact requirements of the initialization are described by the
documentation of individual modes.
@@ -583,7 +769,7 @@ Interfaces used by the symmetric cipher modes described in
.. attribute:: nonce
- :type: bytes
+ :type: :term:`bytes-like`
Exact requirements of the nonce are described by the documentation of
individual modes.
@@ -595,19 +781,45 @@ Interfaces used by the symmetric cipher modes described in
.. attribute:: tag
- :type: bytes
+ :type: :term:`bytes-like`
Exact requirements of the tag are described by the documentation of
individual modes.
+.. class:: ModeWithTweak
+
+ .. versionadded:: 2.1
+
+ A cipher mode with a tweak.
+
+ .. attribute:: tweak
+
+ :type: :term:`bytes-like`
+
+ Exact requirements of the tweak are described by the documentation of
+ individual modes.
+
+Exceptions
+~~~~~~~~~~
+
+.. currentmodule:: cryptography.exceptions
+
+
+.. class:: InvalidTag
+
+ This is raised if an authenticated encryption tag fails to verify during
+ decryption.
+
+
-.. _`described by Colin Percival`: http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html
-.. _`recommends a 96-bit IV length`: http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf
-.. _`NIST SP-800-38D`: http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
+.. _`described by Colin Percival`: https://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html
+.. _`recommends a 96-bit IV length`: https://csrc.nist.gov/publications/detail/sp/800-38d/final
+.. _`NIST SP-800-38D`: https://csrc.nist.gov/publications/detail/sp/800-38d/final
.. _`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/
-.. _`significant patterns in the output`: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_Codebook_.28ECB.29
+.. _`encrypt`: https://ssd.eff.org/en/module/what-should-i-know-about-encryption
+.. _`CRYPTREC`: https://www.cryptrec.go.jp/english/
+.. _`significant patterns in the output`: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_codebook_(ECB)
.. _`International Data Encryption Algorithm`: https://en.wikipedia.org/wiki/International_Data_Encryption_Algorithm
-.. _`OpenPGP`: http://www.openpgp.org
+.. _`OpenPGP`: https://www.openpgp.org/
+.. _`disk encryption`: https://en.wikipedia.org/wiki/Disk_encryption_theory#XTS
diff --git a/docs/hazmat/primitives/twofactor.rst b/docs/hazmat/primitives/twofactor.rst
index df70a58a..51625dfc 100644
--- a/docs/hazmat/primitives/twofactor.rst
+++ b/docs/hazmat/primitives/twofactor.rst
@@ -18,14 +18,15 @@ codes (HMAC).
.. currentmodule:: cryptography.hazmat.primitives.twofactor.hotp
-.. class:: HOTP(key, length, algorithm, backend)
+.. class:: HOTP(key, length, algorithm, backend, enforce_key_length=True)
.. versionadded:: 0.3
HOTP objects take a ``key``, ``length`` and ``algorithm`` parameter. The
``key`` should be :doc:`randomly generated bytes </random-numbers>` and is
- recommended to be 160 bits in length. The ``length`` parameter controls the
- length of the generated one time password and must be >= 6 and <= 8.
+ recommended to be 160 :term:`bits` in length. The ``length`` parameter
+ controls the length of the generated one time password and must be >= 6
+ and <= 8.
This is an implementation of :rfc:`4226`.
@@ -35,23 +36,34 @@ codes (HMAC).
>>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives.twofactor.hotp import HOTP
>>> from cryptography.hazmat.primitives.hashes import SHA1
- >>> key = os.urandom(16)
+ >>> key = os.urandom(20)
>>> hotp = HOTP(key, 6, SHA1(), backend=default_backend())
>>> hotp_value = hotp.generate(0)
>>> hotp.verify(hotp_value, 0)
- :param bytes key: Per-user secret key. This value must be kept secret
- and be at least 128 bits. It is recommended that the
- key be 160 bits.
+ :param key: Per-user secret key. This value must be kept secret
+ and be at least 128 :term:`bits`. It is recommended that
+ the key be 160 bits.
+ :type key: :term:`bytes-like`
:param int length: Length of generated one time password as ``int``.
:param cryptography.hazmat.primitives.hashes.HashAlgorithm algorithm: A
:class:`~cryptography.hazmat.primitives.hashes`
- provider.
+ instance.
:param backend: A
:class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
- provider.
+ instance.
+ :param enforce_key_length: A boolean flag defaulting to True that toggles
+ whether a minimum key length of 128 :term:`bits` is enforced. This
+ exists to work around the fact that as documented in `Issue #2915`_,
+ the Google Authenticator PAM module by default generates 80 bit keys.
+ If this flag is set to False, the application develop should implement
+ additional checks of the key length before passing it into
+ :class:`~cryptography.hazmat.primitives.twofactor.hotp.HOTP`.
+
+ .. versionadded:: 1.5
+
:raises ValueError: This is raised if the provided ``key`` is shorter than
- 128 bits or if the ``length`` parameter is not 6, 7 or 8.
+ 128 :term:`bits` or if the ``length`` parameter is not 6, 7 or 8.
:raises TypeError: This is raised if the provided ``algorithm`` is not
:class:`~cryptography.hazmat.primitives.hashes.SHA1()`,
:class:`~cryptography.hazmat.primitives.hashes.SHA256()` or
@@ -76,6 +88,8 @@ codes (HMAC).
.. method:: get_provisioning_uri(account_name, counter, issuer)
+ .. versionadded:: 1.0
+
:param account_name: The display name of account, such as
``'Alice Smith'`` or ``'alice@example.com'``.
:type account_name: :term:`text`
@@ -127,7 +141,7 @@ similar to the following code.
.. currentmodule:: cryptography.hazmat.primitives.twofactor.totp
-.. class:: TOTP(key, length, algorithm, time_step, backend)
+.. class:: TOTP(key, length, algorithm, time_step, backend, enforce_key_length=True)
TOTP objects take a ``key``, ``length``, ``algorithm`` and ``time_step``
parameter. The ``key`` should be :doc:`randomly generated bytes
@@ -144,25 +158,35 @@ similar to the following code.
>>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives.twofactor.totp import TOTP
>>> from cryptography.hazmat.primitives.hashes import SHA1
- >>> key = os.urandom(16)
+ >>> key = os.urandom(20)
>>> totp = TOTP(key, 8, SHA1(), 30, backend=default_backend())
>>> time_value = time.time()
>>> totp_value = totp.generate(time_value)
>>> totp.verify(totp_value, time_value)
- :param bytes key: Per-user secret key. This value must be kept secret
- and be at least 128 bits. It is recommended that the
- key be 160 bits.
+ :param key: Per-user secret key. This value must be kept secret
+ and be at least 128 :term:`bits`. It is recommended that the
+ key be 160 bits.
+ :type key: :term:`bytes-like`
:param int length: Length of generated one time password as ``int``.
:param cryptography.hazmat.primitives.hashes.HashAlgorithm algorithm: A
:class:`~cryptography.hazmat.primitives.hashes`
- provider.
+ instance.
:param int time_step: The time step size. The recommended size is 30.
:param backend: A
:class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
- provider.
+ instance.
+ :param enforce_key_length: A boolean flag defaulting to True that toggles
+ whether a minimum key length of 128 :term:`bits` is enforced. This exists to
+ work around the fact that as documented in `Issue #2915`_, the
+ Google Authenticator PAM module by default generates 80 bit keys. If
+ this flag is set to False, the application develop should implement
+ additional checks of the key length before passing it into
+ :class:`~cryptography.hazmat.primitives.twofactor.totp.TOTP`.
+
+ .. versionadded:: 1.5
:raises ValueError: This is raised if the provided ``key`` is shorter than
- 128 bits or if the ``length`` parameter is not 6, 7 or 8.
+ 128 :term:`bits` or if the ``length`` parameter is not 6, 7 or 8.
:raises TypeError: This is raised if the provided ``algorithm`` is not
:class:`~cryptography.hazmat.primitives.hashes.SHA1()`,
:class:`~cryptography.hazmat.primitives.hashes.SHA256()` or
@@ -186,9 +210,11 @@ similar to the following code.
.. method:: get_provisioning_uri(account_name, issuer)
+ .. versionadded:: 1.0
+
:param account_name: The display name of account, such as
``'Alice Smith'`` or ``'alice@example.com'``.
- :type: :term:`text`
+ :type account_name: :term:`text`
:param issuer: The optional display name of issuer. This is typically
the provider or service the user wants to access using the OTP
token.
@@ -198,11 +224,11 @@ similar to the following code.
Provisioning URI
~~~~~~~~~~~~~~~~
-The provisioning URI of HOTP and TOTP is not actual the part of RFC 4226 and
-RFC 6238, but a `spec of Google Authenticator`_. It is widely supported by web
-sites and mobile applications which are using Two-Factor authentication.
+The provisioning URI of HOTP and TOTP is a `feature of Google Authenticator`_
+and not actually part of the HOTP or TOTP RFCs. However, it is widely supported
+by web sites and mobile applications which are using Two-Factor authentication.
-For generating a provisioning URI, you could use the ``get_provisioning_uri``
+For generating a provisioning URI you can use the ``get_provisioning_uri``
method of HOTP/TOTP instances.
.. code-block:: python
@@ -217,4 +243,5 @@ method of HOTP/TOTP instances.
A common usage is encoding the provisioning URI into QR code and guiding users
to scan it with Two-Factor authentication applications in their mobile devices.
-.. _`spec of Google Authenticator`: https://github.com/google/google-authenticator/wiki/Key-Uri-Format
+.. _`feature of Google Authenticator`: https://github.com/google/google-authenticator/wiki/Key-Uri-Format
+.. _`Issue #2915`: https://github.com/pyca/cryptography/issues/2915
diff --git a/docs/index.rst b/docs/index.rst
index 35f80a2d..396ed0b6 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -1,10 +1,26 @@
-Welcome to ``cryptography``
-===========================
-
-``cryptography`` is a Python library which exposes cryptographic recipes and
-primitives. Our goal is for it to be your "cryptographic standard library". If
-you are interested in learning more about the field of cryptography, we
-recommend `Crypto 101, by Laurens Van Houtven`_.
+Welcome to ``pyca/cryptography``
+================================
+
+``cryptography`` includes both high level recipes and low level interfaces to
+common cryptographic algorithms such as symmetric ciphers, message digests, and
+key derivation functions. For example, to encrypt something with
+``cryptography``'s high level symmetric encryption recipe:
+
+.. code-block:: pycon
+
+ >>> from cryptography.fernet import Fernet
+ >>> # Put this somewhere safe!
+ >>> key = Fernet.generate_key()
+ >>> f = Fernet(key)
+ >>> token = f.encrypt(b"A really secret message. Not for prying eyes.")
+ >>> token
+ '...'
+ >>> f.decrypt(token)
+ 'A really secret message. Not for prying eyes.'
+
+If you are interested in learning more about the field of cryptography, we
+recommend `Crypto 101, by Laurens Van Houtven`_ and `The Cryptopals Crypto
+Challenges`_.
Installation
------------
@@ -16,34 +32,15 @@ You can install ``cryptography`` with ``pip``:
See :doc:`Installation <installation>` for more information.
-Why a new crypto library for Python?
-------------------------------------
-
-If you've done cryptographic work in Python before, you've probably seen some
-other libraries in Python, such as *M2Crypto*, *PyCrypto*, or *PyOpenSSL*. In
-building ``cryptography`` we wanted to address a few issues we observed in the
-existing libraries:
-
-* Lack of PyPy and Python 3 support.
-* Lack of maintenance.
-* Use of poor implementations of algorithms (i.e. ones with known side-channel
- attacks).
-* Lack of high level, "Cryptography for humans", APIs.
-* Absence of algorithms such as
- :class:`AES-GCM <cryptography.hazmat.primitives.ciphers.modes.GCM>` and
- :class:`~cryptography.hazmat.primitives.kdf.hkdf.HKDF`.
-* Poor introspectability, and thus poor testability.
-* Extremely error prone APIs, and bad defaults.
-
-
.. _cryptography-layout:
+
Layout
------
``cryptography`` is broadly divided into two levels. One with safe
-cryptographic recipes, "cryptography for humans" if you will. These are safe
-and easy to use and don't require developers to make many decisions.
+cryptographic recipes that require little to no configuration choices. These
+are safe and easy to use and don't require developers to make many decisions.
The other level is low-level cryptographic primitives. These are often
dangerous and can be used incorrectly. They require making decisions and having
@@ -56,43 +53,37 @@ admonition at the top.
We recommend using the recipes layer whenever possible, and falling back to the
hazmat layer only when necessary.
-The recipes layer
-~~~~~~~~~~~~~~~~~
-
.. toctree::
:maxdepth: 2
+ :caption: The recipes layer
fernet
- x509
- random-numbers
- exceptions
- faq
- glossary
-
-The hazardous materials layer
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ x509/index
.. toctree::
:maxdepth: 2
+ :caption: The hazardous materials layer
hazmat/primitives/index
+ exceptions
+ random-numbers
hazmat/backends/index
hazmat/bindings/index
-The ``cryptography`` open source project
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
.. toctree::
:maxdepth: 2
+ :caption: The cryptography open source project
installation
+ changelog
+ faq
development/index
security
limitations
api-stability
doing-a-release
- changelog
community
+ glossary
.. note::
@@ -102,3 +93,4 @@ The ``cryptography`` open source project
:doc:`get in touch </community>`.
.. _`Crypto 101, by Laurens Van Houtven`: https://www.crypto101.io/
+.. _`The Cryptopals Crypto Challenges`: https://cryptopals.com/
diff --git a/docs/installation.rst b/docs/installation.rst
index 1c25ff78..a9b0f3af 100644
--- a/docs/installation.rst
+++ b/docs/installation.rst
@@ -10,90 +10,117 @@ You can install ``cryptography`` with ``pip``:
Supported platforms
-------------------
-Currently we test ``cryptography`` on Python 2.6, 2.7, 3.3, 3.4 and PyPy
-on these operating systems.
-
-* x86-64 CentOS 7.x, 6.4 and CentOS 5.x
-* x86-64 FreeBSD 10
-* OS X 10.10 Yosemite, 10.9 Mavericks, 10.8 Mountain Lion, and 10.7 Lion
-* x86-64 Ubuntu 12.04 LTS
-* x86-64 Debian Wheezy (7.x) and Jessie (8.x)
-* 32-bit Python on 64-bit Windows Server 2008
-* 64-bit Python on 64-bit Windows Server 2012
+Currently we test ``cryptography`` on Python 2.7, 3.5+,
+PyPy 7.1+, and PyPy3 7.0 on these operating systems.
+
+* x86-64 CentOS 7.x
+* x86-64 Fedora (latest)
+* macOS 10.15 Catalina
+* x86-64 Ubuntu 16.04 and rolling
+* x86-64 Debian Stretch (9.x), Buster (10.x), Bullseye (11.x), and Sid
+ (unstable)
+* x86-64 Alpine (latest)
+* 32-bit and 64-bit Python on 64-bit Windows Server 2019
We test compiling with ``clang`` as well as ``gcc`` and use the following
OpenSSL releases:
-* ``OpenSSL 0.9.8e-fips-rhel5`` (``RHEL/CentOS 5``)
-* ``OpenSSL 0.9.8k``
-* ``OpenSSL 0.9.8za``
-* ``OpenSSL 1.0.0-fips`` (``RHEL/CentOS 6.4``)
-* ``OpenSSL 1.0.1``
-* ``OpenSSL 1.0.1e-fips`` (``RHEL/CentOS 7``)
-* ``OpenSSL 1.0.1j-freebsd``
-* ``OpenSSL 1.0.1-latest`` (The most recent 1.0.1 release)
-* ``OpenSSL 1.0.2``
+* ``OpenSSL 1.0.2-latest``
+* ``OpenSSL 1.1.0-latest``
+* ``OpenSSL 1.1.1-latest``
-On Windows
-----------
+Building cryptography on Windows
+--------------------------------
The wheel package on Windows is a statically linked build (as of 0.5) so all
-dependencies are included. Just run
+dependencies are included. To install ``cryptography``, you will typically
+just run
.. code-block:: console
$ pip install cryptography
If you prefer to compile it yourself you'll need to have OpenSSL installed.
-There are `pre-compiled binaries`_ available. If your installation is in an
-unusual location set the ``LIB`` and ``INCLUDE`` environment variables to
-include the corresponding locations.For example:
+You can compile OpenSSL yourself as well or use `a binary distribution`_.
+Be sure to download the proper version for your architecture and Python
+(VC2010 works for Python 2.7 while VC2015 is required for 3.5 and above).
+Wherever you place your copy of OpenSSL you'll need to set the ``LIB`` and ``INCLUDE``
+environment variables to include the proper locations. For example:
.. code-block:: console
C:\> \path\to\vcvarsall.bat x86_amd64
- C:\> set LIB=C:\OpenSSL\lib\VC\static;C:\OpenSSL\lib;%LIB%
- C:\> set INCLUDE=C:\OpenSSL\include;%INCLUDE%
+ C:\> set LIB=C:\OpenSSL-win64\lib;%LIB%
+ C:\> set INCLUDE=C:\OpenSSL-win64\include;%INCLUDE%
C:\> pip install cryptography
-You can also choose to build statically or dynamically using the
-``PYCA_WINDOWS_LINK_TYPE`` variable. Allowed values are ``static`` (default)
-and ``dynamic``.
+As of OpenSSL 1.1.0 the library names have changed from ``libeay32`` and
+``ssleay32`` to ``libcrypto`` and ``libssl`` (matching their names on all other
+platforms). ``cryptography`` links against the new 1.1.0 names by default. If
+you need to compile ``cryptography`` against an older version then you **must**
+set ``CRYPTOGRAPHY_WINDOWS_LINK_LEGACY_OPENSSL`` or else installation will fail.
-.. code-block:: console
+If you need to rebuild ``cryptography`` for any reason be sure to clear the
+local `wheel cache`_.
- C:\> \path\to\vcvarsall.bat x86_amd64
- C:\> set LIB=C:\OpenSSL\lib\VC\static;C:\OpenSSL\lib;%LIB%
- C:\> set INCLUDE=C:\OpenSSL\include;%INCLUDE%
- C:\> set PYCA_WINDOWS_LINK_TYPE=dynamic
- C:\> pip install cryptography
+.. _build-on-linux:
Building cryptography on Linux
------------------------------
-``cryptography`` should build very easily on Linux provided you have a C
-compiler, headers for Python (if you're not using ``pypy``), and headers for
-the OpenSSL and ``libffi`` libraries available on your system.
+``cryptography`` ships ``manylinux`` wheels (as of 2.0) so all dependencies
+are included. For users on pip 8.1 or above running on a ``manylinux1`` or
+``manylinux2010`` compatible distribution (almost everything except Alpine)
+all you should need to do is:
+
+.. code-block:: console
+
+ $ pip install cryptography
+
+If you are on Alpine or just want to compile it yourself then
+``cryptography`` requires a compiler, headers for Python (if you're not
+using ``pypy``), and headers for the OpenSSL and ``libffi`` libraries
+available on your system.
+
+Alpine
+~~~~~~
-For Debian and Ubuntu, the following command will ensure that the required
-dependencies are installed:
+Replace ``python3-dev`` with ``python-dev`` if you're using Python 2.
.. code-block:: console
- $ sudo apt-get install build-essential libssl-dev libffi-dev python-dev
+ $ sudo apk add gcc musl-dev python3-dev libffi-dev openssl-dev
-For Fedora and RHEL-derivatives, the following command will ensure that the
-required dependencies are installed:
+If you get an error with ``openssl-dev`` you may have to use ``libressl-dev``.
+
+Debian/Ubuntu
+~~~~~~~~~~~~~
+
+Replace ``python3-dev`` with ``python-dev`` if you're using Python 2.
.. code-block:: console
- $ sudo yum install gcc libffi-devel python-devel openssl-devel
+ $ sudo apt-get install build-essential libssl-dev libffi-dev python3-dev
-You should now be able to build and install cryptography with the usual
+RHEL/CentOS
+~~~~~~~~~~~
.. code-block:: console
- $ pip install cryptography
+ $ sudo yum install redhat-rpm-config gcc libffi-devel python-devel \
+ openssl-devel
+
+
+Building
+~~~~~~~~
+
+You should now be able to build and install cryptography. To avoid getting
+the pre-built wheel on ``manylinux`` compatible distributions you'll need to
+use ``--no-binary``.
+
+.. code-block:: console
+
+ $ pip install cryptography --no-binary cryptography
Using your own OpenSSL on Linux
@@ -117,7 +144,7 @@ this when configuring OpenSSL:
You'll also need to generate your own ``openssl.ld`` file. For example::
- OPENSSL_1.0.1F_CUSTOM {
+ OPENSSL_1.1.0E_CUSTOM {
global:
*;
};
@@ -125,52 +152,128 @@ You'll also need to generate your own ``openssl.ld`` file. For example::
You should replace the version string on the first line as appropriate for your
build.
-Using your own OpenSSL on OS X
+Static Wheels
+~~~~~~~~~~~~~
+
+Cryptography ships statically-linked wheels for macOS, Windows, and Linux (via
+``manylinux``). This allows compatible environments to use the most recent
+OpenSSL, regardless of what is shipped by default on those platforms. Some
+Linux distributions (most notably Alpine) are not ``manylinux`` compatible so
+we cannot distribute wheels for them.
+
+However, you can build your own statically-linked wheels that will work on your
+own systems. This will allow you to continue to use relatively old Linux
+distributions (such as LTS releases), while making sure you have the most
+recent OpenSSL available to your Python programs.
+
+To do so, you should find yourself a machine that is as similar as possible to
+your target environment (e.g. your production environment): for example, spin
+up a new cloud server running your target Linux distribution. On this machine,
+install the Cryptography dependencies as mentioned in :ref:`build-on-linux`.
+Please also make sure you have `virtualenv`_ installed: this should be
+available from your system package manager.
+
+Then, paste the following into a shell script. You'll need to populate the
+``OPENSSL_VERSION`` variable. To do that, visit `openssl.org`_ and find the
+latest non-FIPS release version number, then set the string appropriately. For
+example, for OpenSSL 1.0.2k, use ``OPENSSL_VERSION="1.0.2k"``.
+
+When this shell script is complete, you'll find a collection of wheel files in
+a directory called ``wheelhouse``. These wheels can be installed by a
+sufficiently-recent version of ``pip``. The Cryptography wheel in this
+directory contains a statically-linked OpenSSL binding, which ensures that you
+have access to the most-recent OpenSSL releases without corrupting your system
+dependencies.
+
+.. code-block:: console
+
+ set -e
+
+ OPENSSL_VERSION="VERSIONGOESHERE"
+ CWD=$(pwd)
+
+ virtualenv env
+ . env/bin/activate
+ pip install -U setuptools
+ pip install -U wheel pip
+ curl -O https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz
+ tar xvf openssl-${OPENSSL_VERSION}.tar.gz
+ cd openssl-${OPENSSL_VERSION}
+ ./config no-shared no-ssl2 no-ssl3 -fPIC --prefix=${CWD}/openssl
+ make && make install
+ cd ..
+ CFLAGS="-I${CWD}/openssl/include" LDFLAGS="-L${CWD}/openssl/lib" pip wheel --no-binary :all: cryptography
+
+Building cryptography on macOS
------------------------------
-To link cryptography against a custom version of OpenSSL you'll need to set
-``ARCHFLAGS``, ``LDFLAGS``, and ``CFLAGS``. OpenSSL can be installed via
-`Homebrew`_ or `MacPorts`_:
+.. note::
+
+ If installation gives a ``fatal error: 'openssl/aes.h' file not found``
+ see the :doc:`FAQ </faq>` for information about how to fix this issue.
+
+The wheel package on macOS is a statically linked build (as of 1.0.1) so for
+users with pip 8 or above you only need one step:
+
+.. code-block:: console
+
+ $ pip install cryptography
+
+If you want to build cryptography yourself or are on an older macOS version,
+cryptography requires the presence of a C compiler, development headers, and
+the proper libraries. On macOS much of this is provided by Apple's Xcode
+development tools. To install the Xcode command line tools (on macOS 10.9+)
+open a terminal window and run:
+
+.. code-block:: console
+
+ $ xcode-select --install
+
+This will install a compiler (clang) along with (most of) the required
+development headers.
+
+You'll also need OpenSSL, which you can obtain from `Homebrew`_ or `MacPorts`_.
+Cryptography does **not** support Apple's deprecated OpenSSL distribution.
+
+To build cryptography and dynamically link it:
`Homebrew`_
.. code-block:: console
- $ brew install openssl
- $ env ARCHFLAGS="-arch x86_64" LDFLAGS="-L/usr/local/opt/openssl/lib" CFLAGS="-I/usr/local/opt/openssl/include" pip install cryptography
+ $ brew install openssl@1.1
+ $ env LDFLAGS="-L$(brew --prefix openssl@1.1)/lib" CFLAGS="-I$(brew --prefix openssl@1.1)/include" pip install cryptography
-or `MacPorts`_:
+`MacPorts`_:
.. code-block:: console
$ sudo port install openssl
- $ env ARCHFLAGS="-arch x86_64" LDFLAGS="-L/opt/local/lib" CFLAGS="-I/opt/local/include" pip install cryptography
-
-Building cryptography with conda
---------------------------------
+ $ env LDFLAGS="-L/opt/local/lib" CFLAGS="-I/opt/local/include" pip install cryptography
-Because of a `bug in conda`_, attempting to install cryptography out of the box
-will result in an error. This can be resolved by setting the library path
-environment variable for your platform.
+You can also build cryptography statically:
-On OS X:
+`Homebrew`_
.. code-block:: console
- $ env DYLD_LIBRARY_PATH="$HOME/anaconda/lib" pip install cryptography
+ $ brew install openssl@1.1
+ $ env CRYPTOGRAPHY_SUPPRESS_LINK_FLAGS=1 LDFLAGS="$(brew --prefix openssl@1.1)/lib/libssl.a $(brew --prefix openssl@1.1)/lib/libcrypto.a" CFLAGS="-I$(brew --prefix openssl@1.1)/include" pip install cryptography
-and on Linux:
+`MacPorts`_:
.. code-block:: console
- $ env LD_LIBRARY_PATH="$HOME/anaconda/lib" pip install cryptography
+ $ sudo port install openssl
+ $ env CRYPTOGRAPHY_SUPPRESS_LINK_FLAGS=1 LDFLAGS="/opt/local/lib/libssl.a /opt/local/lib/libcrypto.a" CFLAGS="-I/opt/local/include" pip install cryptography
-You will need to set this variable every time you start Python. For more
-information, consult `Greg Wilson's blog post`_ on the subject.
+If you need to rebuild ``cryptography`` for any reason be sure to clear the
+local `wheel cache`_.
-.. _`Homebrew`: http://brew.sh
-.. _`MacPorts`: http://www.macports.org
-.. _`pre-compiled binaries`: https://www.openssl.org/related/binaries.html
-.. _`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
+.. _`Homebrew`: https://brew.sh
+.. _`MacPorts`: https://www.macports.org
+.. _`a binary distribution`: https://wiki.openssl.org/index.php/Binaries
+.. _virtualenv: https://virtualenv.pypa.io/en/latest/
+.. _openssl.org: https://www.openssl.org/source/
+.. _`wheel cache`: https://pip.pypa.io/en/stable/reference/pip_install/#caching
diff --git a/docs/limitations.rst b/docs/limitations.rst
index 0dfc49ca..092d8a7c 100644
--- a/docs/limitations.rst
+++ b/docs/limitations.rst
@@ -1,19 +1,24 @@
Known security limitations
---------------------------
+==========================
-Lack of secure memory wiping
-============================
+Secure memory wiping
+--------------------
`Memory wiping`_ is used to protect secret data or key material from attackers
-with access to uninitialized memory. This can be either because the attacker
-has some kind of local user access or because of how other software uses
-uninitialized memory.
+with access to deallocated memory. This is a defense-in-depth measure against
+vulnerabilities that leak application memory.
-Python exposes no API for us to implement this reliably and as such almost all
-software in Python is potentially vulnerable to this attack. The
+Many ``cryptography`` APIs which accept ``bytes`` also accept types which
+implement the buffer interface. Thus, users wishing to do so can pass
+``memoryview`` or another mutable type to ``cryptography`` APIs, and overwrite
+the contents once the data is no longer needed.
+
+However, ``cryptography`` does not clear memory by default, as there is no way
+to clear immutable structures such as ``bytes``. As a result, ``cryptography``,
+like almost all software in Python is potentially vulnerable to this attack. The
`CERT secure coding guidelines`_ assesses this issue as "Severity: medium,
Likelihood: unlikely, Remediation Cost: expensive to repair" and we do not
consider this a high risk for most users.
-.. _`Memory wiping`: http://blogs.msdn.com/b/oldnewthing/archive/2013/05/29/10421912.aspx
-.. _`CERT secure coding guidelines`: https://www.securecoding.cert.org/confluence/display/c/MEM03-C.+Clear+sensitive+information+stored+in+reusable+resources
+.. _`Memory wiping`: https://devblogs.microsoft.com/oldnewthing/?p=4223
+.. _`CERT secure coding guidelines`: https://wiki.sei.cmu.edu/confluence/display/c/MEM03-C.+Clear+sensitive+information+stored+in+reusable+resources
diff --git a/docs/random-numbers.rst b/docs/random-numbers.rst
index 8b119a3e..c6acd5b1 100644
--- a/docs/random-numbers.rst
+++ b/docs/random-numbers.rst
@@ -21,4 +21,17 @@ you can obtain them with:
This will use ``/dev/urandom`` on UNIX platforms, and ``CryptGenRandom`` on
Windows.
-.. _`always use your operating system's provided random number generator`: http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/
+If you need your random number as an integer (for example, for
+:meth:`~cryptography.x509.CertificateBuilder.serial_number`), you can use
+``int.from_bytes`` to convert the result of ``os.urandom``:
+
+.. code-block:: pycon
+
+ >>> serial = int.from_bytes(os.urandom(20), byteorder="big")
+
+Starting with Python 3.6 the `standard library includes`_ the ``secrets``
+module, which can be used for generating cryptographically secure random
+numbers, with specific helpers for text-based formats.
+
+.. _`always use your operating system's provided random number generator`: https://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/
+.. _`standard library includes`: https://docs.python.org/3/library/secrets.html
diff --git a/docs/security.rst b/docs/security.rst
index 50253457..8cdd2d11 100644
--- a/docs/security.rst
+++ b/docs/security.rst
@@ -5,6 +5,47 @@ 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.
+Infrastructure
+--------------
+
+In addition to ``cryptography``'s code, we're also concerned with the security
+of the infrastructure we run (primarily ``cryptography.io``). If you discover
+a security vulnerability in our infrastructure, we ask you to report it using
+the same procedure.
+
+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 public issue.
+
Reporting a security issue
--------------------------
@@ -14,7 +55,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,12 +66,13 @@ 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
--------------------------------
-As of version 0.5, ``cryptography`` statically links OpenSSL on Windows to ease
+As of versions 0.5, 1.0.1, and 2.0.0, ``cryptography`` statically links OpenSSL
+in binary distributions for Windows, macOS, and Linux respectively, to ease
installation. Due to this, ``cryptography`` will release a new version whenever
OpenSSL has a security or bug fix release to avoid shipping insecure software.
@@ -40,42 +82,12 @@ strongly recommend that you upgrade as soon as possible.
Disclosure Process
------------------
-Our process for taking a security issue from private discussion to public
-disclosure involves multiple steps.
-
-Approximately one week before full public disclosure, we will send advance
-notification of the issue to a list of people and organizations, primarily
-composed of operating-system vendors and other distributors of
-``cryptography``. This notification will consist of an email message
-containing:
-
-* A full description of the issue and the affected versions of
- ``cryptography``.
-* The steps we will be taking to remedy the issue.
-* The patches, if any, that will be applied to ``cryptography``.
-* The date on which the ``cryptography`` team will apply these patches, issue
- new releases, and publicly disclose the issue.
-
-Simultaneously, the reporter of the issue will receive notification of the date
-on which we plan to take the issue public.
-
-On the day of disclosure, we will take the following steps:
-
-* Apply the relevant patches to the ``cryptography`` repository. The commit
- messages for these patches will indicate that they are for security issues,
- but will not describe the issue in any detail; instead, they will warn of
- upcoming disclosure.
-* Issue the relevant releases.
-* Post a notice to the cryptography mailing list that describes the issue in
- detail, point to the new release and crediting the reporter of the issue.
-
-If a reported issue is believed to be particularly time-sensitive – due to a
-known exploit in the wild, for example – the time between advance notification
-and public disclosure may be shortened considerably.
-
-The list of people and organizations who receives advanced notification of
-security issues is not and will not be made public. This list generally
-consists of high profile downstream distributors and is entirely at the
-discretion of the ``cryptography`` team.
+When we become aware of a security bug in ``cryptography``, we will endeavor to
+fix it and issue a release as quickly as possible. We will generally issue a new
+release for any security issue.
+
+The steps for issuing a security release are described in our
+:doc:`/doing-a-release` documentation.
+
.. _`master`: https://github.com/pyca/cryptography
diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt
index 235e08d4..68711533 100644
--- a/docs/spelling_wordlist.txt
+++ b/docs/spelling_wordlist.txt
@@ -1,33 +1,62 @@
+accessor
affine
+Authenticator
+authenticator
backend
-backends
Backends
+backends
+bcrypt
Blowfish
boolean
Botan
+Brainpool
+Bullseye
+Capitan
+changelog
Changelog
ciphertext
+codebook
committer
committers
conda
+Cryptanalysis
crypto
cryptographic
cryptographically
Debian
-Diffie
+deallocated
decrypt
+decrypts
+Decrypts
decrypted
decrypting
+deprecations
+DER
deserialize
deserialized
+Deserialization
+deserializing
Diffie
+Diffie
+disambiguating
+Django
Docstrings
+El
Encodings
-fernet
+endian
+extendable
+fallback
Fernet
+fernet
+FIPS
+Google
hazmat
+Homebrew
+hostname
+idna
indistinguishability
initialisms
+interoperability
interoperable
introspectability
invariants
@@ -35,31 +64,56 @@ iOS
iterable
Koblitz
Lange
+logins
metadata
+Mozilla
multi
-naïve
namespace
namespaces
+macOS
+naïve
Nonces
+nonces
online
paddings
+Parallelization
+personalization
pickleable
plaintext
+Poly
+pre
+precompute
preprocessor
preprocessors
+presentational
pseudorandom
pyOpenSSL
relicensed
+responder
+runtime
Schneier
scrypt
-Serializers
serializer
+Serializers
+SHA
Solaris
+syscall
Tanja
testability
+timestamp
+timestamps
+tunable
Ubuntu
unencrypted
+unicode
unpadded
unpadding
+verifier
+Verifier
Verisign
+versioning
wildcard
+WoSign
+Wycheproof
+Xcode
+XEX
diff --git a/docs/x509.rst b/docs/x509.rst
deleted file mode 100644
index f94f50eb..00000000
--- a/docs/x509.rst
+++ /dev/null
@@ -1,1569 +0,0 @@
-X.509
-=====
-
-.. currentmodule:: cryptography.x509
-
-.. testsetup::
-
- pem_req_data = b"""
- -----BEGIN CERTIFICATE REQUEST-----
- MIIC0zCCAbsCAQAwWTELMAkGA1UEBhMCVVMxETAPBgNVBAgMCElsbGlub2lzMRAw
- DgYDVQQHDAdDaGljYWdvMREwDwYDVQQKDAhyNTA5IExMQzESMBAGA1UEAwwJaGVs
- bG8uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqhZx+Mo9VRd9
- vsnWWa6NBCws21rZ0+1B/JGgB4hDsZS7iDE4Bj5z4idheFRtl8bBbdjPknq7BfoF
- 8v15Zq/Zv7i2xMSDL+LUrTBZezRd4bRTGqCm6YJ5EYkhqdcqeZleHCFImguHoq1J
- Fh0+kObQrTHXw3ZP57a3o1IvyIUA3nNoCBL0QQhwBXaDXOojMKNR+bqB5ve8GS1y
- Elr0AM/+cJsfaIahNQUgFKx3Eu3GeEOMKYOAG1lycgdQdmTUybLrT3U7vkClTseM
- xHg1r5En7ALjONIhqRuq3rddYahrP8HXozb3zUy3cJ7P6IeaosuvNzvMXOX9P6HD
- Ha9urDAJ1wIDAQABoDUwMwYJKoZIhvcNAQkOMSYwJDAiBgNVHREEGzAZggl3b3Js
- ZC5jb22CDHdoYXRldmVyLmNvbTANBgkqhkiG9w0BAQUFAAOCAQEAS4Ro6h+z52SK
- YSLCYARpnEu/rmh4jdqndt8naqcNb6uLx9mlKZ2W9on9XDjnSdQD9q+ZP5aZfESw
- R0+rJhW9ZrNa/g1pt6M24ihclHYDAxYMWxT1z/TXXGM3TmZZ6gfYlNE1kkBuODHa
- UYsR/1Ht1E1EsmmUimt2n+zQR2K8T9Coa+boaUW/GsTEuz1aaJAkj5ZvTDiIhRG4
- AOCqFZOLAQmCCNgJnnspD9hDz/Ons085LF5wnYjN4/Nsk5tS6AGs3xjZ3jPoOGGn
- 82WQ9m4dBGoVDZXsobVTaN592JEYwN5iu72zRn7Einb4V4H5y3yD2dD4yWPlt4pk
- 5wFkeYsZEA==
- -----END CERTIFICATE REQUEST-----
- """.strip()
-
- pem_data = b"""
- -----BEGIN CERTIFICATE-----
- MIIDfDCCAmSgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
- MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
- QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowQDELMAkGA1UE
- BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExEDAOBgNVBAMT
- B0dvb2QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCQWJpHYo37
- Xfb7oJSPe+WvfTlzIG21WQ7MyMbGtK/m8mejCzR6c+f/pJhEH/OcDSMsXq8h5kXa
- BGqWK+vSwD/Pzp5OYGptXmGPcthDtAwlrafkGOS4GqIJ8+k9XGKs+vQUXJKsOk47
- RuzD6PZupq4s16xaLVqYbUC26UcY08GpnoLNHJZS/EmXw1ZZ3d4YZjNlpIpWFNHn
- UGmdiGKXUPX/9H0fVjIAaQwjnGAbpgyCumWgzIwPpX+ElFOUr3z7BoVnFKhIXze+
- VmQGSWxZxvWDUN90Ul0tLEpLgk3OVxUB4VUGuf15OJOpgo1xibINPmWt14Vda2N9
- yrNKloJGZNqLAgMBAAGjfDB6MB8GA1UdIwQYMBaAFOR9X9FclYYILAWuvnW2ZafZ
- XahmMB0GA1UdDgQWBBRYAYQkG7wrUpRKPaUQchRR9a86yTAOBgNVHQ8BAf8EBAMC
- AQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
- KoZIhvcNAQELBQADggEBADWHlxbmdTXNwBL/llwhQqwnazK7CC2WsXBBqgNPWj7m
- tvQ+aLG8/50Qc2Sun7o2VnwF9D18UUe8Gj3uPUYH+oSI1vDdyKcjmMbKRU4rk0eo
- 3UHNDXwqIVc9CQS9smyV+x1HCwL4TTrq+LXLKx/qVij0Yqk+UJfAtrg2jnYKXsCu
- FMBQQnWCGrwa1g1TphRp/RmYHnMynYFmZrXtzFz+U9XEA7C+gPq4kqDI/iVfIT1s
- 6lBtdB50lrDVwl2oYfAvW/6sC2se2QleZidUmrziVNP4oEeXINokU6T6p//HM1FG
- QYw2jOvpKcKtWCSAnegEbgsGYzATKjmPJPJ0npHFqzM=
- -----END CERTIFICATE-----
- """.strip()
-
- cryptography_cert_pem = b"""
- -----BEGIN CERTIFICATE-----
- MIIFvTCCBKWgAwIBAgICPyAwDQYJKoZIhvcNAQELBQAwRzELMAkGA1UEBhMCVVMx
- FjAUBgNVBAoTDUdlb1RydXN0IEluYy4xIDAeBgNVBAMTF1JhcGlkU1NMIFNIQTI1
- NiBDQSAtIEczMB4XDTE0MTAxNTEyMDkzMloXDTE4MTExNjAxMTUwM1owgZcxEzAR
- BgNVBAsTCkdUNDg3NDI5NjUxMTAvBgNVBAsTKFNlZSB3d3cucmFwaWRzc2wuY29t
- L3Jlc291cmNlcy9jcHMgKGMpMTQxLzAtBgNVBAsTJkRvbWFpbiBDb250cm9sIFZh
- bGlkYXRlZCAtIFJhcGlkU1NMKFIpMRwwGgYDVQQDExN3d3cuY3J5cHRvZ3JhcGh5
- LmlvMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAom/FebKJIot7Sp3s
- itG1sicpe3thCssjI+g1JDAS7I3GLVNmbms1DOdIIqwf01gZkzzXBN2+9sOnyRaR
- PPfCe1jTr3dk2y6rPE559vPa1nZQkhlzlhMhlPyjaT+S7g4Tio4qV2sCBZU01DZJ
- CaksfohN+5BNVWoJzTbOcrHOEJ+M8B484KlBCiSxqf9cyNQKru4W3bHaCVNVJ8eu
- 6i6KyhzLa0L7yK3LXwwXVs583C0/vwFhccGWsFODqD/9xHUzsBIshE8HKjdjDi7Y
- 3BFQzVUQFjBB50NSZfAA/jcdt1blxJouc7z9T8Oklh+V5DDBowgAsrT4b6Z2Fq6/
- r7D1GqivLK/ypUQmxq2WXWAUBb/Q6xHgxASxI4Br+CByIUQJsm8L2jzc7k+mF4hW
- ltAIUkbo8fGiVnat0505YJgxWEDKOLc4Gda6d/7GVd5AvKrz242bUqeaWo6e4MTx
- diku2Ma3rhdcr044Qvfh9hGyjqNjvhWY/I+VRWgihU7JrYvgwFdJqsQ5eiKT4OHi
- gsejvWwkZzDtiQ+aQTrzM1FsY2swJBJsLSX4ofohlVRlIJCn/ME+XErj553431Lu
- YQ5SzMd3nXzN78Vj6qzTfMUUY72UoT1/AcFiUMobgIqrrmwuNxfrkbVE2b6Bga74
- FsJX63prvrJ41kuHK/16RQBM7fcCAwEAAaOCAWAwggFcMB8GA1UdIwQYMBaAFMOc
- 8/zTRgg0u85Gf6B8W/PiCMtZMFcGCCsGAQUFBwEBBEswSTAfBggrBgEFBQcwAYYT
- aHR0cDovL2d2LnN5bWNkLmNvbTAmBggrBgEFBQcwAoYaaHR0cDovL2d2LnN5bWNi
- LmNvbS9ndi5jcnQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMB
- BggrBgEFBQcDAjAvBgNVHREEKDAmghN3d3cuY3J5cHRvZ3JhcGh5Lmlvgg9jcnlw
- dG9ncmFwaHkuaW8wKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL2d2LnN5bWNiLmNv
- bS9ndi5jcmwwDAYDVR0TAQH/BAIwADBFBgNVHSAEPjA8MDoGCmCGSAGG+EUBBzYw
- LDAqBggrBgEFBQcCARYeaHR0cHM6Ly93d3cucmFwaWRzc2wuY29tL2xlZ2FsMA0G
- CSqGSIb3DQEBCwUAA4IBAQAzIYO2jx7h17FBT74tJ2zbV9OKqGb7QF8y3wUtP4xc
- dH80vprI/Cfji8s86kr77aAvAqjDjaVjHn7UzebhSUivvRPmfzRgyWBacomnXTSt
- Xlt2dp2nDQuwGyK2vB7dMfKnQAkxwq1sYUXznB8i0IhhCAoXp01QGPKq51YoIlnF
- 7DRMk6iEaL1SJbkIrLsCQyZFDf0xtfW9DqXugMMLoxeCsBhZJQzNyS2ryirrv9LH
- aK3+6IZjrcyy9bkpz/gzJucyhU+75c4My/mnRCrtItRbCQuiI5pd5poDowm+HH9i
- GVI9+0lAFwxOUnOnwsoI40iOoxjLMGB+CgFLKCGUcWxP
- -----END CERTIFICATE-----
- """.strip()
-
-X.509 is an ITU-T standard for a `public key infrastructure`_. X.509v3 is
-defined in :rfc:`5280` (which obsoletes :rfc:`2459` and :rfc:`3280`). X.509
-certificates are commonly used in protocols like `TLS`_.
-
-Loading Certificates
-~~~~~~~~~~~~~~~~~~~~
-
-.. function:: load_pem_x509_certificate(data, backend)
-
- .. versionadded:: 0.7
-
- Deserialize a certificate from PEM encoded data. PEM certificates are
- base64 decoded and have delimiters that look like
- ``-----BEGIN CERTIFICATE-----``.
-
- :param bytes data: The PEM encoded certificate data.
-
- :param backend: A backend supporting the
- :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
- interface.
-
- :returns: An instance of :class:`~cryptography.x509.Certificate`.
-
-.. function:: load_der_x509_certificate(data, backend)
-
- .. versionadded:: 0.7
-
- Deserialize a certificate from DER encoded data. DER is a binary format
- and is commonly found in files with the ``.cer`` extension (although file
- extensions are not a guarantee of encoding type).
-
- :param bytes data: The DER encoded certificate data.
-
- :param backend: A backend supporting the
- :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
- interface.
-
- :returns: An instance of :class:`~cryptography.x509.Certificate`.
-
-.. doctest::
-
- >>> from cryptography import x509
- >>> from cryptography.hazmat.backends import default_backend
- >>> cert = x509.load_pem_x509_certificate(pem_data, default_backend())
- >>> cert.serial
- 2
-
-Loading Certificate Signing Requests
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. function:: load_pem_x509_csr(data, backend)
-
- .. versionadded:: 0.9
-
- Deserialize a certificate signing request (CSR) from PEM encoded data. PEM
- requests are base64 decoded and have delimiters that look like
- ``-----BEGIN CERTIFICATE REQUEST-----``. This format is also known as
- PKCS#10.
-
- :param bytes data: The PEM encoded request data.
-
- :param backend: A backend supporting the
- :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
- interface.
-
- :returns: An instance of
- :class:`~cryptography.x509.CertificateSigningRequest`.
-
-.. function:: load_der_x509_csr(data, backend)
-
- .. versionadded:: 0.9
-
- Deserialize a certificate signing request (CSR) from DER encoded data. DER
- is a binary format and is not commonly used with CSRs.
-
- :param bytes data: The DER encoded request data.
-
- :param backend: A backend supporting the
- :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
- interface.
-
- :returns: An instance of
- :class:`~cryptography.x509.CertificateSigningRequest`.
-
-.. doctest::
-
- >>> from cryptography import x509
- >>> from cryptography.hazmat.backends import default_backend
- >>> from cryptography.hazmat.primitives import hashes
- >>> csr = x509.load_pem_x509_csr(pem_req_data, default_backend())
- >>> isinstance(csr.signature_hash_algorithm, hashes.SHA1)
- True
-
-X.509 Certificate Object
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. class:: Certificate
-
- .. versionadded:: 0.7
-
- .. attribute:: version
-
- :type: :class:`~cryptography.x509.Version`
-
- The certificate version as an enumeration. Version 3 certificates are
- the latest version and also the only type you should see in practice.
-
- :raises cryptography.x509.InvalidVersion: If the version in the
- certificate is not a known
- :class:`X.509 version <cryptography.x509.Version>`.
-
- .. doctest::
-
- >>> cert.version
- <Version.v3: 2>
-
- .. method:: fingerprint(algorithm)
-
- :param algorithm: The
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- that will be used to generate the fingerprint.
-
- :return bytes: The fingerprint using the supplied hash algorithm, as
- bytes.
-
- .. doctest::
-
- >>> from cryptography.hazmat.primitives import hashes
- >>> cert.fingerprint(hashes.SHA256())
- '\x86\xd2\x187Gc\xfc\xe7}[+E9\x8d\xb4\x8f\x10\xe5S\xda\x18u\xbe}a\x03\x08[\xac\xa04?'
-
- .. attribute:: serial
-
- :type: int
-
- The serial as a Python integer.
-
- .. doctest::
-
- >>> cert.serial
- 2
-
- .. method:: public_key()
-
- :type:
- :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey` or
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey` or
- :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`
-
- The public key associated with the certificate.
-
- .. doctest::
-
- >>> from cryptography.hazmat.primitives.asymmetric import rsa
- >>> public_key = cert.public_key()
- >>> isinstance(public_key, rsa.RSAPublicKey)
- True
-
- .. attribute:: not_valid_before
-
- :type: :class:`datetime.datetime`
-
- A naïve datetime representing the beginning of the validity period for
- the certificate in UTC. This value is inclusive.
-
- .. doctest::
-
- >>> cert.not_valid_before
- datetime.datetime(2010, 1, 1, 8, 30)
-
- .. attribute:: not_valid_after
-
- :type: :class:`datetime.datetime`
-
- A naïve datetime representing the end of the validity period for the
- certificate in UTC. This value is inclusive.
-
- .. doctest::
-
- >>> cert.not_valid_after
- datetime.datetime(2030, 12, 31, 8, 30)
-
- .. attribute:: issuer
-
- .. versionadded:: 0.8
-
- :type: :class:`Name`
-
- The :class:`Name` of the issuer.
-
- .. attribute:: subject
-
- .. versionadded:: 0.8
-
- :type: :class:`Name`
-
- The :class:`Name` of the subject.
-
- .. attribute:: signature_hash_algorithm
-
- :type: :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
-
- Returns the
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` which
- was used in signing this certificate.
-
- .. doctest::
-
- >>> from cryptography.hazmat.primitives import hashes
- >>> isinstance(cert.signature_hash_algorithm, hashes.SHA256)
- True
-
- .. attribute:: extensions
-
- :type: :class:`Extensions`
-
- The extensions encoded in the certificate.
-
- :raises cryptography.x509.DuplicateExtension: If more than one
- extension of the same type is found within the certificate.
-
- :raises cryptography.x509.UnsupportedExtension: If the certificate
- contains an extension that is not supported.
-
- :raises cryptography.x509.UnsupportedGeneralNameType: If an extension
- contains a general name that is not supported.
-
- :raises UnicodeError: If an extension contains IDNA encoding that is
- invalid or not compliant with IDNA 2008.
-
- .. doctest::
-
- >>> for ext in cert.extensions:
- ... print(ext)
- <Extension(oid=<ObjectIdentifier(oid=2.5.29.35, name=authorityKeyIdentifier)>, critical=False, value=<AuthorityKeyIdentifier(key_identifier='\xe4}_\xd1\\\x95\x86\x08,\x05\xae\xbeu\xb6e\xa7\xd9]\xa8f', authority_cert_issuer=None, authority_cert_serial_number=None)>)>
- <Extension(oid=<ObjectIdentifier(oid=2.5.29.14, name=subjectKeyIdentifier)>, critical=False, value=<SubjectKeyIdentifier(digest='X\x01\x84$\x1b\xbc+R\x94J=\xa5\x10r\x14Q\xf5\xaf:\xc9')>)>
- <Extension(oid=<ObjectIdentifier(oid=2.5.29.15, name=keyUsage)>, critical=True, value=<KeyUsage(digital_signature=False, content_commitment=False, key_encipherment=False, data_encipherment=False, key_agreement=False, key_cert_sign=True, crl_sign=True, encipher_only=None, decipher_only=None)>)>
- <Extension(oid=<ObjectIdentifier(oid=2.5.29.32, name=certificatePolicies)>, critical=False, value=<CertificatePolicies([<PolicyInformation(policy_identifier=<ObjectIdentifier(oid=2.16.840.1.101.3.2.1.48.1, name=Unknown OID)>, policy_qualifiers=None)>])>)>
- <Extension(oid=<ObjectIdentifier(oid=2.5.29.19, name=basicConstraints)>, critical=True, value=<BasicConstraints(ca=True, path_length=None)>)>
-
- .. method:: public_bytes(encoding)
-
- :param encoding: The
- :class:`~cryptography.hazmat.primitives.serialization.Encoding`
- that will be used to serialize the certificate.
-
- :return bytes: The data that can be written to a file or sent
- over the network to be verified by clients.
-
-X.509 CRL (Certificate Revocation List) Object
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. class:: CertificateRevocationList
-
- .. versionadded:: 1.0
-
- .. method:: fingerprint(algorithm)
-
- :param algorithm: The
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- that will be used to generate the fingerprint.
-
- :return bytes: The fingerprint using the supplied hash algorithm, as
- bytes.
-
- .. attribute:: signature_hash_algorithm
-
- :type: :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
-
- Returns the
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` which
- was used in signing this CRL.
-
- .. attribute:: issuer
-
- :type: :class:`Name`
-
- The :class:`Name` of the issuer.
-
- .. attribute:: next_update
-
- :type: :class:`datetime.datetime`
-
- A naïve datetime representing when the next update to this CRL is
- expected.
-
- .. attribute:: last_update
-
- :type: :class:`datetime.datetime`
-
- A naïve datetime representing when the this CRL was last updated.
-
- .. attribute:: revoked_certificates
-
- :type: list of :class:`RevokedCertificate`
-
- The revoked certificates listed in this CRL.
-
- .. attribute:: extensions
-
- :type: :class:`Extensions`
-
- The extensions encoded in the CRL.
-
-X.509 CSR (Certificate Signing Request) Object
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. class:: CertificateSigningRequest
-
- .. versionadded:: 0.9
-
- .. method:: public_key()
-
- :type:
- :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey` or
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey` or
- :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`
-
- The public key associated with the request.
-
- .. doctest::
-
- >>> from cryptography.hazmat.primitives.asymmetric import rsa
- >>> public_key = csr.public_key()
- >>> isinstance(public_key, rsa.RSAPublicKey)
- True
-
- .. attribute:: subject
-
- :type: :class:`Name`
-
- The :class:`Name` of the subject.
-
- .. attribute:: signature_hash_algorithm
-
- :type: :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
-
- Returns the
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` which
- was used in signing this request.
-
- .. doctest::
-
- >>> from cryptography.hazmat.primitives import hashes
- >>> isinstance(csr.signature_hash_algorithm, hashes.SHA1)
- True
-
- .. method:: public_bytes(encoding)
-
- :param encoding: The
- :class:`~cryptography.hazmat.primitives.serialization.Encoding`
- that will be used to serialize the certificate request.
-
- :return bytes: The data that can be written to a file or sent
- over the network to be signed by the certificate
- authority.
-
-X.509 Revoked Certificate Object
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. class:: RevokedCertificate
-
- .. versionadded:: 1.0
-
- .. attribute:: serial_number
-
- :type: :class:`int`
-
- An integer representing the serial number of the revoked certificate.
-
- .. attribute:: revocation_date
-
- :type: :class:`datetime.datetime`
-
- A naïve datetime representing the date this certificates was revoked.
-
- .. attribute:: extensions
-
- :type: :class:`Extensions`
-
- The extensions encoded in the revoked certificate.
-
-X.509 CSR (Certificate Signing Request) Builder Object
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. class:: CertificateSigningRequestBuilder
-
- .. versionadded:: 1.0
-
- .. doctest::
-
- >>> from cryptography import x509
- >>> from cryptography.hazmat.backends import default_backend
- >>> from cryptography.hazmat.primitives import hashes
- >>> from cryptography.hazmat.primitives.asymmetric import rsa
- >>> private_key = rsa.generate_private_key(
- ... public_exponent=65537,
- ... key_size=2048,
- ... backend=default_backend()
- ... )
- >>> builder = x509.CertificateSigningRequestBuilder()
- >>> builder = builder.subject_name(x509.Name([
- ... x509.NameAttribute(x509.OID_COMMON_NAME, u'cryptography.io'),
- ... ]))
- >>> builder = builder.add_extension(
- ... x509.BasicConstraints(ca=False, path_length=None), critical=True,
- ... )
- >>> request = builder.sign(
- ... private_key, hashes.SHA256(), default_backend()
- ... )
- >>> isinstance(request, x509.CertificateSigningRequest)
- True
-
- .. method:: subject_name(name)
-
- :param name: The :class:`~cryptography.x509.Name` of the certificate
- subject.
- :returns: A new
- :class:`~cryptography.x509.CertificateSigningRequestBuilder`.
-
- .. method:: add_extension(extension, critical)
-
- :param extension: The :class:`~cryptography.x509.Extension` to add to
- the request.
- :param critical: Set to `True` if the extension must be understood and
- handled by whoever reads the certificate.
- :returns: A new
- :class:`~cryptography.x509.CertificateSigningRequestBuilder`.
-
- .. method:: sign(private_key, algorithm, backend)
-
- :param backend: Backend that will be used to sign the request.
- Must support the
- :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
- interface.
-
- :param private_key: The
- :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`,
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey` or
- :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`
- that will be used to sign the request. When the request is
- signed by a certificate authority, the private key's associated
- public key will be stored in the resulting certificate.
-
- :param algorithm: The
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- that will be used to generate the request signature.
-
- :returns: A new
- :class:`~cryptography.x509.CertificateSigningRequest`.
-
-
-.. class:: Name
-
- .. versionadded:: 0.8
-
- An X509 Name is an ordered list of attributes. The object is iterable to
- get every attribute or you can use :meth:`Name.get_attributes_for_oid` to
- obtain the specific type you want. Names are sometimes represented as a
- slash or comma delimited string (e.g. ``/CN=mydomain.com/O=My Org/C=US`` or
- ``CN=mydomain.com, O=My Org, C=US``).
-
- .. doctest::
-
- >>> len(cert.subject)
- 3
- >>> for attribute in cert.subject:
- ... print(attribute)
- <NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.6, name=countryName)>, value=u'US')>
- <NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.10, name=organizationName)>, value=u'Test Certificates 2011')>
- <NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commonName)>, value=u'Good CA')>
-
- .. method:: get_attributes_for_oid(oid)
-
- :param oid: An :class:`ObjectIdentifier` instance.
-
- :returns: A list of :class:`NameAttribute` instances that match the
- OID provided. If nothing matches an empty list will be returned.
-
- .. doctest::
-
- >>> cert.subject.get_attributes_for_oid(x509.OID_COMMON_NAME)
- [<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commonName)>, value=u'Good CA')>]
-
-.. class:: Version
-
- .. versionadded:: 0.7
-
- An enumeration for X.509 versions.
-
- .. attribute:: v1
-
- For version 1 X.509 certificates.
-
- .. attribute:: v3
-
- For version 3 X.509 certificates.
-
-.. class:: NameAttribute
-
- .. versionadded:: 0.8
-
- An X.509 name consists of a list of NameAttribute instances.
-
- .. attribute:: oid
-
- :type: :class:`ObjectIdentifier`
-
- The attribute OID.
-
- .. attribute:: value
-
- :type: :term:`text`
-
- The value of the attribute.
-
-.. class:: ObjectIdentifier
-
- .. versionadded:: 0.8
-
- Object identifiers (frequently seen abbreviated as OID) identify the type
- of a value (see: :class:`NameAttribute`).
-
- .. attribute:: dotted_string
-
- :type: :class:`str`
-
- The dotted string value of the OID (e.g. ``"2.5.4.3"``)
-
-.. _general_name_classes:
-
-General Name Classes
-~~~~~~~~~~~~~~~~~~~~
-
-.. class:: GeneralName
-
- .. versionadded:: 0.9
-
- This is the generic interface that all the following classes are registered
- against.
-
-.. class:: RFC822Name
-
- .. versionadded:: 0.9
-
- This corresponds to an email address. For example, ``user@example.com``.
-
- .. attribute:: value
-
- :type: :term:`text`
-
-.. class:: DNSName
-
- .. versionadded:: 0.9
-
- This corresponds to a domain name. For example, ``cryptography.io``.
-
- .. attribute:: value
-
- :type: :term:`text`
-
-.. class:: DirectoryName
-
- .. versionadded:: 0.9
-
- This corresponds to a directory name.
-
- .. attribute:: value
-
- :type: :class:`Name`
-
-.. class:: UniformResourceIdentifier
-
- .. versionadded:: 0.9
-
- This corresponds to a uniform resource identifier. For example,
- ``https://cryptography.io``. The URI is parsed and IDNA decoded (see
- :rfc:`5895`).
-
- .. note::
-
- URIs that do not contain ``://`` in them will not be decoded.
-
- .. attribute:: value
-
- :type: :term:`text`
-
-.. class:: IPAddress
-
- .. versionadded:: 0.9
-
- This corresponds to an IP address.
-
- .. attribute:: value
-
- :type: :class:`~ipaddress.IPv4Address`,
- :class:`~ipaddress.IPv6Address`, :class:`~ipaddress.IPv4Network`,
- or :class:`~ipaddress.IPv6Network`.
-
-.. class:: RegisteredID
-
- .. versionadded:: 0.9
-
- This corresponds to a registered ID.
-
- .. attribute:: value
-
- :type: :class:`ObjectIdentifier`
-
-X.509 Extensions
-~~~~~~~~~~~~~~~~
-
-.. class:: Extensions
-
- .. versionadded:: 0.9
-
- An X.509 Extensions instance is an ordered list of extensions. The object
- is iterable to get every extension.
-
- .. method:: get_extension_for_oid(oid)
-
- :param oid: An :class:`ObjectIdentifier` instance.
-
- :returns: An instance of the extension class.
-
- :raises cryptography.x509.ExtensionNotFound: If the certificate does
- not have the extension requested.
-
- .. doctest::
-
- >>> cert.extensions.get_extension_for_oid(x509.OID_BASIC_CONSTRAINTS)
- <Extension(oid=<ObjectIdentifier(oid=2.5.29.19, name=basicConstraints)>, critical=True, value=<BasicConstraints(ca=True, path_length=None)>)>
-
-.. class:: Extension
-
- .. versionadded:: 0.9
-
- .. attribute:: oid
-
- :type: :class:`ObjectIdentifier`
-
- The :ref:`extension OID <extension_oids>`.
-
- .. attribute:: critical
-
- :type: bool
-
- Determines whether a given extension is critical or not. :rfc:`5280`
- requires that "A certificate-using system MUST reject the certificate
- if it encounters a critical extension it does not recognize or a
- critical extension that contains information that it cannot process".
-
- .. attribute:: value
-
- Returns an instance of the extension type corresponding to the OID.
-
-.. class:: KeyUsage
-
- .. versionadded:: 0.9
-
- The key usage extension defines the purpose of the key contained in the
- certificate. The usage restriction might be employed when a key that could
- be used for more than one operation is to be restricted. It corresponds to
- :data:`OID_KEY_USAGE`.
-
- .. attribute:: digital_signature
-
- :type: bool
-
- This purpose is set to true when the subject public key is used for verifying
- digital signatures, other than signatures on certificates
- (``key_cert_sign``) and CRLs (``crl_sign``).
-
- .. attribute:: content_commitment
-
- :type: bool
-
- This purpose is set to true when the subject public key is used for verifying
- digital signatures, other than signatures on certificates
- (``key_cert_sign``) and CRLs (``crl_sign``). It is used to provide a
- non-repudiation service that protects against the signing entity
- falsely denying some action. In the case of later conflict, a
- reliable third party may determine the authenticity of the signed
- data. This was called ``non_repudiation`` in older revisions of the
- X.509 specification.
-
- .. attribute:: key_encipherment
-
- :type: bool
-
- This purpose is set to true when the subject public key is used for
- enciphering private or secret keys.
-
- .. attribute:: data_encipherment
-
- :type: bool
-
- This purpose is set to true when the subject public key is used for
- directly enciphering raw user data without the use of an intermediate
- symmetric cipher.
-
- .. attribute:: key_agreement
-
- :type: bool
-
- This purpose is set to true when the subject public key is used for key
- agreement. For example, when a Diffie-Hellman key is to be used for
- key management, then this purpose is set to true.
-
- .. attribute:: key_cert_sign
-
- :type: bool
-
- This purpose is set to true when the subject public key is used for
- verifying signatures on public key certificates. If this purpose is set
- to true then ``ca`` must be true in the :class:`BasicConstraints`
- extension.
-
- .. attribute:: crl_sign
-
- :type: bool
-
- This purpose is set to true when the subject public key is used for
- verifying signatures on certificate revocation lists.
-
- .. attribute:: encipher_only
-
- :type: bool
-
- When this purposes is set to true and the ``key_agreement`` purpose is
- also set, the subject public key may be used only for enciphering data
- while performing key agreement.
-
- :raises ValueError: This is raised if accessed when ``key_agreement``
- is false.
-
- .. attribute:: decipher_only
-
- :type: bool
-
- When this purposes is set to true and the ``key_agreement`` purpose is
- also set, the subject public key may be used only for deciphering data
- while performing key agreement.
-
- :raises ValueError: This is raised if accessed when ``key_agreement``
- is false.
-
-
-.. class:: BasicConstraints
-
- .. versionadded:: 0.9
-
- Basic constraints is an X.509 extension type that defines whether a given
- certificate is allowed to sign additional certificates and what path
- length restrictions may exist. It corresponds to
- :data:`OID_BASIC_CONSTRAINTS`.
-
- .. attribute:: ca
-
- :type: bool
-
- Whether the certificate can sign certificates.
-
- .. attribute:: path_length
-
- :type: int or None
-
- The maximum path length for certificates subordinate to this
- certificate. This attribute only has meaning if ``ca`` is true.
- If ``ca`` is true then a path length of None means there's no
- restriction on the number of subordinate CAs in the certificate chain.
- If it is zero or greater then it defines the maximum length for a
- subordinate CA's certificate chain. For example, a ``path_length`` of 1
- means the certificate can sign a subordinate CA, but the subordinate CA
- is not allowed to create subordinates with ``ca`` set to true.
-
-.. class:: ExtendedKeyUsage
-
- .. versionadded:: 0.9
-
- This extension indicates one or more purposes for which the certified
- public key may be used, in addition to or in place of the basic
- purposes indicated in the key usage extension. The object is
- iterable to obtain the list of :ref:`extended key usage OIDs <eku_oids>`.
-
-.. class:: OCSPNoCheck
-
- .. versionadded:: 1.0
-
- This presence of this extension indicates that an OCSP client can trust a
- responder for the lifetime of the responder's certificate. CAs issuing
- such a certificate should realize that a compromise of the responder's key
- is as serious as the compromise of a CA key used to sign CRLs, at least for
- the validity period of this certificate. CA's may choose to issue this type
- of certificate with a very short lifetime and renew it frequently. This
- extension is only relevant when the certificate is an authorized OCSP
- responder.
-
-.. class:: NameConstraints
-
- .. versionadded:: 1.0
-
- The name constraints extension, which only has meaning in a CA certificate,
- defines a name space within which all subject names in certificates issued
- beneath the CA certificate must (or must not) be in. For specific details
- on the way this extension should be processed see :rfc:`5280`.
-
- .. attribute:: permitted_subtrees
-
- :type: list of :class:`GeneralName` objects or None
-
- The set of permitted name patterns. If a name matches this and an
- element in ``excluded_subtrees`` it is invalid. At least one of
- ``permitted_subtrees`` and ``excluded_subtrees`` will be non-None.
-
- .. attribute:: excluded_subtrees
-
- :type: list of :class:`GeneralName` objects or None
-
- Any name matching a restriction in the ``excluded_subtrees`` field is
- invalid regardless of information appearing in the
- ``permitted_subtrees``. At least one of ``permitted_subtrees`` and
- ``excluded_subtrees`` will be non-None.
-
-.. class:: AuthorityKeyIdentifier
-
- .. versionadded:: 0.9
-
- The authority key identifier extension provides a means of identifying the
- public key corresponding to the private key used to sign a certificate.
- This extension is typically used to assist in determining the appropriate
- certificate chain. For more information about generation and use of this
- extension see `RFC 5280 section 4.2.1.1`_.
-
- .. attribute:: key_identifier
-
- :type: bytes
-
- A value derived from the public key used to verify the certificate's
- signature.
-
- .. attribute:: authority_cert_issuer
-
- :type: :class:`Name` or None
-
- The :class:`Name` of the issuer's issuer.
-
- .. attribute:: authority_cert_serial_number
-
- :type: int or None
-
- The serial number of the issuer's issuer.
-
-.. class:: SubjectKeyIdentifier
-
- .. versionadded:: 0.9
-
- The subject key identifier extension provides a means of identifying
- certificates that contain a particular public key.
-
- .. attribute:: digest
-
- :type: bytes
-
- The binary value of the identifier.
-
-.. class:: SubjectAlternativeName
-
- .. versionadded:: 0.9
-
- Subject alternative name is an X.509 extension that provides a list of
- :ref:`general name <general_name_classes>` instances that provide a set
- of identities for which the certificate is valid. The object is iterable to
- get every element.
-
- .. method:: get_values_for_type(type)
-
- :param type: A :class:`GeneralName` provider. This is one of the
- :ref:`general name classes <general_name_classes>`.
-
- :returns: A list of values extracted from the matched general names.
-
- .. doctest::
-
- >>> from cryptography import x509
- >>> from cryptography.hazmat.backends import default_backend
- >>> from cryptography.hazmat.primitives import hashes
- >>> cert = x509.load_pem_x509_certificate(cryptography_cert_pem, default_backend())
- >>> # Get the subjectAltName extension from the certificate
- >>> ext = cert.extensions.get_extension_for_oid(x509.OID_SUBJECT_ALTERNATIVE_NAME)
- >>> # Get the dNSName entries from the SAN extension
- >>> ext.value.get_values_for_type(x509.DNSName)
- [u'www.cryptography.io', u'cryptography.io']
-
-
-.. class:: IssuerAlternativeName
-
- .. versionadded:: 1.0
-
- Issuer alternative name is an X.509 extension that provides a list of
- :ref:`general name <general_name_classes>` instances that provide a set
- of identities for the certificate issuer. The object is iterable to
- get every element.
-
- .. method:: get_values_for_type(type)
-
- :param type: A :class:`GeneralName` provider. This is one of the
- :ref:`general name classes <general_name_classes>`.
-
- :returns: A list of values extracted from the matched general names.
-
-
-.. class:: AuthorityInformationAccess
-
- .. versionadded:: 0.9
-
- The authority information access extension indicates how to access
- information and services for the issuer of the certificate in which
- the extension appears. Information and services may include online
- validation services (such as OCSP) and issuer data. It is an iterable,
- containing one or more :class:`AccessDescription` instances.
-
-
-.. class:: AccessDescription
-
- .. versionadded:: 0.9
-
- .. attribute:: access_method
-
- :type: :class:`ObjectIdentifier`
-
- The access method defines what the ``access_location`` means. It must
- be either :data:`OID_OCSP` or :data:`OID_CA_ISSUERS`. If it is
- :data:`OID_OCSP` the access location will be where to obtain OCSP
- information for the certificate. If it is :data:`OID_CA_ISSUERS` the
- access location will provide additional information about the issuing
- certificate.
-
- .. attribute:: access_location
-
- :type: :class:`GeneralName`
-
- Where to access the information defined by the access method.
-
-.. class:: CRLDistributionPoints
-
- .. versionadded:: 0.9
-
- The CRL distribution points extension identifies how CRL information is
- obtained. It is an iterable, containing one or more
- :class:`DistributionPoint` instances.
-
-.. class:: DistributionPoint
-
- .. versionadded:: 0.9
-
- .. attribute:: full_name
-
- :type: list of :class:`GeneralName` instances or None
-
- This field describes methods to retrieve the CRL. At most one of
- ``full_name`` or ``relative_name`` will be non-None.
-
- .. attribute:: relative_name
-
- :type: :class:`Name` or None
-
- This field describes methods to retrieve the CRL relative to the CRL
- issuer. At most one of ``full_name`` or ``relative_name`` will be
- non-None.
-
- .. attribute:: crl_issuer
-
- :type: list of :class:`GeneralName` instances or None
-
- Information about the issuer of the CRL.
-
- .. attribute:: reasons
-
- :type: frozenset of :class:`ReasonFlags` or None
-
- The reasons a given distribution point may be used for when performing
- revocation checks.
-
-.. class:: ReasonFlags
-
- .. versionadded:: 0.9
-
- An enumeration for CRL reasons.
-
- .. attribute:: unspecified
-
- It is unspecified why the certificate was revoked. This reason cannot
- be used as a reason flag in a :class:`DistributionPoint`.
-
- .. attribute:: key_compromise
-
- This reason indicates that the private key was compromised.
-
- .. attribute:: ca_compromise
-
- This reason indicates that the CA issuing the certificate was
- compromised.
-
- .. attribute:: affiliation_changed
-
- This reason indicates that the subject's name or other information has
- changed.
-
- .. attribute:: superseded
-
- This reason indicates that a certificate has been superseded.
-
- .. attribute:: cessation_of_operation
-
- This reason indicates that the certificate is no longer required.
-
- .. attribute:: certificate_hold
-
- This reason indicates that the certificate is on hold.
-
- .. attribute:: privilege_withdrawn
-
- This reason indicates that the privilege granted by this certificate
- have been withdrawn.
-
- .. attribute:: aa_compromise
-
- When an attribute authority has been compromised.
-
- .. attribute:: remove_from_crl
-
- This reason indicates that the certificate was on hold and should be
- removed from the CRL. This reason cannot be used as a reason flag
- in a :class:`DistributionPoint`.
-
-.. class:: InhibitAnyPolicy
-
- .. versionadded:: 1.0
-
- The inhibit ``anyPolicy`` extension indicates that the special OID
- :data:`OID_ANY_POLICY`, is not considered an explicit match for other
- :class:`CertificatePolicies` except when it appears in an intermediate
- self-issued CA certificate. The value indicates the number of additional
- non-self-issued certificates that may appear in the path before
- :data:`OID_ANY_POLICY` is no longer permitted. For example, a value
- of one indicates that :data:`OID_ANY_POLICY` may be processed in
- certificates issued by the subject of this certificate, but not in
- additional certificates in the path.
-
- .. attribute:: skip_certs
-
- :type: int
-
-.. class:: CertificatePolicies
-
- .. versionadded:: 0.9
-
- The certificate policies extension is an iterable, containing one or more
- :class:`PolicyInformation` instances.
-
-Certificate Policies Classes
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-These classes may be present within a :class:`CertificatePolicies` instance.
-
-.. class:: PolicyInformation
-
- .. versionadded:: 0.9
-
- Contains a policy identifier and an optional list of qualifiers.
-
- .. attribute:: policy_identifier
-
- :type: :class:`ObjectIdentifier`
-
- .. attribute:: policy_qualifiers
-
- :type: list
-
- A list consisting of :term:`text` and/or :class:`UserNotice` objects.
- If the value is text it is a pointer to the practice statement
- published by the certificate authority. If it is a user notice it is
- meant for display to the relying party when the certificate is
- used.
-
-.. class:: UserNotice
-
- .. versionadded:: 0.9
-
- User notices are intended for display to a relying party when a certificate
- is used. In practice, few if any UIs expose this data and it is a rarely
- encoded component.
-
- .. attribute:: notice_reference
-
- :type: :class:`NoticeReference` or None
-
- The notice reference field names an organization and identifies,
- by number, a particular statement prepared by that organization.
-
- .. attribute:: explicit_text
-
- This field includes an arbitrary textual statement directly in the
- certificate.
-
- :type: :term:`text`
-
-.. class:: NoticeReference
-
- Notice reference can name an organization and provide information about
- notices related to the certificate. For example, it might identify the
- organization name and notice number 1. Application software could
- have a notice file containing the current set of notices for the named
- organization; the application would then extract the notice text from the
- file and display it. In practice this is rarely seen.
-
- .. versionadded:: 0.9
-
- .. attribute:: organization
-
- :type: :term:`text`
-
- .. attribute:: notice_numbers
-
- :type: list
-
- A list of integers.
-
-Object Identifiers
-~~~~~~~~~~~~~~~~~~
-
-X.509 elements are frequently identified by :class:`ObjectIdentifier`
-instances. The following common OIDs are available as constants.
-
-Name OIDs
-~~~~~~~~~
-
-.. data:: OID_COMMON_NAME
-
- Corresponds to the dotted string ``"2.5.4.3"``. Historically the domain
- name would be encoded here for server certificates. :rfc:`2818` deprecates
- this practice and names of that type should now be located in a
- SubjectAlternativeName extension. This OID is typically seen in X.509 names.
-
-.. data:: OID_COUNTRY_NAME
-
- Corresponds to the dotted string ``"2.5.4.6"``. This OID is typically seen
- in X.509 names.
-
-.. data:: OID_LOCALITY_NAME
-
- Corresponds to the dotted string ``"2.5.4.7"``. This OID is typically seen
- in X.509 names.
-
-.. data:: OID_STATE_OR_PROVINCE_NAME
-
- Corresponds to the dotted string ``"2.5.4.8"``. This OID is typically seen
- in X.509 names.
-
-.. data:: OID_ORGANIZATION_NAME
-
- Corresponds to the dotted string ``"2.5.4.10"``. This OID is typically seen
- in X.509 names.
-
-.. data:: OID_ORGANIZATIONAL_UNIT_NAME
-
- Corresponds to the dotted string ``"2.5.4.11"``. This OID is typically seen
- in X.509 names.
-
-.. data:: OID_SERIAL_NUMBER
-
- Corresponds to the dotted string ``"2.5.4.5"``. This is distinct from the
- serial number of the certificate itself (which can be obtained with
- :func:`Certificate.serial`). This OID is typically seen in X.509 names.
-
-.. data:: OID_SURNAME
-
- Corresponds to the dotted string ``"2.5.4.4"``. This OID is typically seen
- in X.509 names.
-
-.. data:: OID_GIVEN_NAME
-
- Corresponds to the dotted string ``"2.5.4.42"``. This OID is typically seen
- in X.509 names.
-
-.. data:: OID_TITLE
-
- Corresponds to the dotted string ``"2.5.4.12"``. This OID is typically seen
- in X.509 names.
-
-.. data:: OID_GENERATION_QUALIFIER
-
- Corresponds to the dotted string ``"2.5.4.44"``. This OID is typically seen
- in X.509 names.
-
-.. data:: OID_DN_QUALIFIER
-
- Corresponds to the dotted string ``"2.5.4.46"``. This specifies
- disambiguating information to add to the relative distinguished name of an
- entry. See :rfc:`2256`. This OID is typically seen in X.509 names.
-
-.. data:: OID_PSEUDONYM
-
- Corresponds to the dotted string ``"2.5.4.65"``. This OID is typically seen
- in X.509 names.
-
-.. data:: OID_DOMAIN_COMPONENT
-
- Corresponds to the dotted string ``"0.9.2342.19200300.100.1.25"``. A string
- holding one component of a domain name. See :rfc:`4519`. This OID is
- typically seen in X.509 names.
-
-.. data:: OID_EMAIL_ADDRESS
-
- Corresponds to the dotted string ``"1.2.840.113549.1.9.1"``. This OID is
- typically seen in X.509 names.
-
-Signature Algorithm OIDs
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. data:: OID_RSA_WITH_MD5
-
- Corresponds to the dotted string ``"1.2.840.113549.1.1.4"``. This is
- an MD5 digest signed by an RSA key.
-
-.. data:: OID_RSA_WITH_SHA1
-
- Corresponds to the dotted string ``"1.2.840.113549.1.1.5"``. This is
- a SHA1 digest signed by an RSA key.
-
-.. data:: OID_RSA_WITH_SHA224
-
- Corresponds to the dotted string ``"1.2.840.113549.1.1.14"``. This is
- a SHA224 digest signed by an RSA key.
-
-.. data:: OID_RSA_WITH_SHA256
-
- Corresponds to the dotted string ``"1.2.840.113549.1.1.11"``. This is
- a SHA256 digest signed by an RSA key.
-
-.. data:: OID_RSA_WITH_SHA384
-
- Corresponds to the dotted string ``"1.2.840.113549.1.1.12"``. This is
- a SHA384 digest signed by an RSA key.
-
-.. data:: OID_RSA_WITH_SHA512
-
- Corresponds to the dotted string ``"1.2.840.113549.1.1.13"``. This is
- a SHA512 digest signed by an RSA key.
-
-.. data:: OID_ECDSA_WITH_SHA1
-
- Corresponds to the dotted string ``"1.2.840.10045.4.1"``. This is a SHA1
- digest signed by an ECDSA key.
-
-.. data:: OID_ECDSA_WITH_SHA224
-
- Corresponds to the dotted string ``"1.2.840.10045.4.3.1"``. This is
- a SHA224 digest signed by an ECDSA key.
-
-.. data:: OID_ECDSA_WITH_SHA256
-
- Corresponds to the dotted string ``"1.2.840.10045.4.3.2"``. This is
- a SHA256 digest signed by an ECDSA key.
-
-.. data:: OID_ECDSA_WITH_SHA384
-
- Corresponds to the dotted string ``"1.2.840.10045.4.3.3"``. This is
- a SHA384 digest signed by an ECDSA key.
-
-.. data:: OID_ECDSA_WITH_SHA512
-
- Corresponds to the dotted string ``"1.2.840.10045.4.3.4"``. This is
- a SHA512 digest signed by an ECDSA key.
-
-.. data:: OID_DSA_WITH_SHA1
-
- Corresponds to the dotted string ``"1.2.840.10040.4.3"``. This is
- a SHA1 digest signed by a DSA key.
-
-.. data:: OID_DSA_WITH_SHA224
-
- Corresponds to the dotted string ``"2.16.840.1.101.3.4.3.1"``. This is
- a SHA224 digest signed by a DSA key.
-
-.. data:: OID_DSA_WITH_SHA256
-
- Corresponds to the dotted string ``"2.16.840.1.101.3.4.3.2"``. This is
- a SHA256 digest signed by a DSA key.
-
-.. _eku_oids:
-
-Extended Key Usage OIDs
-~~~~~~~~~~~~~~~~~~~~~~~
-
-.. data:: OID_SERVER_AUTH
-
- Corresponds to the dotted string ``"1.3.6.1.5.5.7.3.1"``. This is used to
- denote that a certificate may be used for TLS web server authentication.
-
-.. data:: OID_CLIENT_AUTH
-
- Corresponds to the dotted string ``"1.3.6.1.5.5.7.3.2"``. This is used to
- denote that a certificate may be used for TLS web client authentication.
-
-.. data:: OID_CODE_SIGNING
-
- Corresponds to the dotted string ``"1.3.6.1.5.5.7.3.3"``. This is used to
- denote that a certificate may be used for code signing.
-
-.. data:: OID_EMAIL_PROTECTION
-
- Corresponds to the dotted string ``"1.3.6.1.5.5.7.3.4"``. This is used to
- denote that a certificate may be used for email protection.
-
-.. data:: OID_TIME_STAMPING
-
- Corresponds to the dotted string ``"1.3.6.1.5.5.7.3.8"``. This is used to
- denote that a certificate may be used for time stamping.
-
-.. data:: OID_OCSP_SIGNING
-
- Corresponds to the dotted string ``"1.3.6.1.5.5.7.3.9"``. This is used to
- denote that a certificate may be used for signing OCSP responses.
-
-Authority Information Access OIDs
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. data:: OID_OCSP
-
- Corresponds to the dotted string ``"1.3.6.1.5.5.7.48.1"``. Used as the
- identifier for OCSP data in :class:`AccessDescription` objects.
-
-.. data:: OID_CA_ISSUERS
-
- Corresponds to the dotted string ``"1.3.6.1.5.5.7.48.2"``. Used as the
- identifier for CA issuer data in :class:`AccessDescription` objects.
-
-Policy Qualifier OIDs
-~~~~~~~~~~~~~~~~~~~~~
-
-.. data:: OID_CPS_QUALIFIER
-
- Corresponds to the dotted string ``"1.3.6.1.5.5.7.2.1"``.
-
-.. data:: OID_CPS_USER_NOTICE
-
- Corresponds to the dotted string ``"1.3.6.1.5.5.7.2.2"``.
-
-.. data:: OID_ANY_POLICY
-
- Corresponds to the dotted string ``"2.5.29.32.0"``.
-
-.. _extension_oids:
-
-Extension OIDs
-~~~~~~~~~~~~~~
-
-.. data:: OID_BASIC_CONSTRAINTS
-
- Corresponds to the dotted string ``"2.5.29.19"``. The identifier for the
- :class:`BasicConstraints` extension type.
-
-.. data:: OID_KEY_USAGE
-
- Corresponds to the dotted string ``"2.5.29.15"``. The identifier for the
- :class:`KeyUsage` extension type.
-
-.. data:: OID_SUBJECT_ALTERNATIVE_NAME
-
- Corresponds to the dotted string ``"2.5.29.17"``. The identifier for the
- :class:`SubjectAlternativeName` extension type.
-
-.. data:: OID_ISSUER_ALTERNATIVE_NAME
-
- Corresponds to the dotted string ``"2.5.29.18"``. The identifier for the
- :class:`IssuerAlternativeName` extension type.
-
-.. data:: OID_SUBJECT_KEY_IDENTIFIER
-
- Corresponds to the dotted string ``"2.5.29.14"``. The identifier for the
- :class:`SubjectKeyIdentifier` extension type.
-
-.. data:: OID_NAME_CONSTRAINTS
-
- Corresponds to the dotted string ``"2.5.29.30"``. The identifier for the
- :class:`NameConstraints` extension type.
-
-.. data:: OID_CRL_DISTRIBUTION_POINTS
-
- Corresponds to the dotted string ``"2.5.29.31"``. The identifier for the
- :class:`CRLDistributionPoints` extension type.
-
-.. data:: OID_CERTIFICATE_POLICIES
-
- Corresponds to the dotted string ``"2.5.29.32"``. The identifier for the
- :class:`CertificatePolicies` extension type.
-
-.. data:: OID_AUTHORITY_KEY_IDENTIFIER
-
- Corresponds to the dotted string ``"2.5.29.35"``. The identifier for the
- :class:`AuthorityKeyIdentifier` extension type.
-
-.. data:: OID_EXTENDED_KEY_USAGE
-
- Corresponds to the dotted string ``"2.5.29.37"``. The identifier for the
- :class:`ExtendedKeyUsage` extension type.
-
-.. data:: OID_AUTHORITY_INFORMATION_ACCESS
-
- Corresponds to the dotted string ``"1.3.6.1.5.5.7.1.1"``. The identifier
- for the :class:`AuthorityInformationAccess` extension type.
-
-.. data:: OID_OCSP_NO_CHECK
-
- Corresponds to the dotted string ``"1.3.6.1.5.5.7.48.1.5"``. The identifier
- for the :class:`OCSPNoCheck` extension type.
-
-Exceptions
-~~~~~~~~~~
-
-.. class:: InvalidVersion
-
- This is raised when an X.509 certificate has an invalid version number.
-
- .. attribute:: parsed_version
-
- :type: int
-
- Returns the raw version that was parsed from the certificate.
-
-.. class:: DuplicateExtension
-
- This is raised when more than one X.509 extension of the same type is
- found within a certificate.
-
- .. attribute:: oid
-
- :type: :class:`ObjectIdentifier`
-
- Returns the OID.
-
-.. class:: UnsupportedExtension
-
- This is raised when a certificate contains an unsupported extension type.
-
- .. attribute:: oid
-
- :type: :class:`ObjectIdentifier`
-
- Returns the OID.
-
-.. class:: ExtensionNotFound
-
- This is raised when calling :meth:`Extensions.get_extension_for_oid` with
- an extension OID that is not present in the certificate.
-
- .. attribute:: oid
-
- :type: :class:`ObjectIdentifier`
-
- Returns the OID.
-
-.. class:: UnsupportedGeneralNameType
-
- This is raised when a certificate contains an unsupported general name
- type in an extension.
-
- .. attribute:: type
-
- :type: int
-
- The integer value of the unsupported type. The complete list of
- types can be found in `RFC 5280 section 4.2.1.6`_.
-
-
-.. _`public key infrastructure`: https://en.wikipedia.org/wiki/Public_key_infrastructure
-.. _`TLS`: https://en.wikipedia.org/wiki/Transport_Layer_Security
-.. _`RFC 5280 section 4.2.1.1`: https://tools.ietf.org/html/rfc5280#section-4.2.1.1
-.. _`RFC 5280 section 4.2.1.6`: https://tools.ietf.org/html/rfc5280#section-4.2.1.6
diff --git a/docs/x509/certificate-transparency.rst b/docs/x509/certificate-transparency.rst
new file mode 100644
index 00000000..f9e651ed
--- /dev/null
+++ b/docs/x509/certificate-transparency.rst
@@ -0,0 +1,79 @@
+Certificate Transparency
+========================
+
+.. currentmodule:: cryptography.x509.certificate_transparency
+
+`Certificate Transparency`_ is a set of protocols specified in :rfc:`6962`
+which allow X.509 certificates to be sent to append-only logs and have small
+cryptographic proofs that a certificate has been publicly logged. This allows
+for external auditing of the certificates that a certificate authority has
+issued.
+
+.. class:: SignedCertificateTimestamp
+
+ .. versionadded:: 2.0
+
+ SignedCertificateTimestamps (SCTs) are small cryptographically signed
+ assertions that the specified certificate has been submitted to a
+ Certificate Transparency Log, and that it will be part of the public log
+ within some time period, this is called the "maximum merge delay" (MMD) and
+ each log specifies its own.
+
+ .. attribute:: version
+
+ :type: :class:`~cryptography.x509.certificate_transparency.Version`
+
+ The SCT version as an enumeration. Currently only one version has been
+ specified.
+
+ .. attribute:: log_id
+
+ :type: bytes
+
+ An opaque identifier, indicating which log this SCT is from. This is
+ the SHA256 hash of the log's public key.
+
+ .. attribute:: timestamp
+
+ :type: :class:`datetime.datetime`
+
+ A naïve datetime representing the time in UTC at which the log asserts
+ the certificate had been submitted to it.
+
+ .. attribute:: entry_type
+
+ :type:
+ :class:`~cryptography.x509.certificate_transparency.LogEntryType`
+
+ The type of submission to the log that this SCT is for. Log submissions
+ can either be certificates themselves or "pre-certificates" which
+ indicate a binding-intent to issue a certificate for the same data,
+ with SCTs embedded in it.
+
+
+.. class:: Version
+
+ .. versionadded:: 2.0
+
+ An enumeration for SignedCertificateTimestamp versions.
+
+ .. attribute:: v1
+
+ For version 1 SignedCertificateTimestamps.
+
+.. class:: LogEntryType
+
+ .. versionadded:: 2.0
+
+ An enumeration for SignedCertificateTimestamp log entry types.
+
+ .. attribute:: X509_CERTIFICATE
+
+ For SCTs corresponding to X.509 certificates.
+
+ .. attribute:: PRE_CERTIFICATE
+
+ For SCTs corresponding to pre-certificates.
+
+
+.. _`Certificate Transparency`: https://www.certificate-transparency.org/
diff --git a/docs/x509/index.rst b/docs/x509/index.rst
new file mode 100644
index 00000000..ef51fbf6
--- /dev/null
+++ b/docs/x509/index.rst
@@ -0,0 +1,17 @@
+X.509
+=====
+
+X.509 is an ITU-T standard for a `public key infrastructure`_. X.509v3 is
+defined in :rfc:`5280` (which obsoletes :rfc:`2459` and :rfc:`3280`). X.509
+certificates are commonly used in protocols like `TLS`_.
+
+.. toctree::
+ :maxdepth: 2
+
+ tutorial
+ certificate-transparency
+ ocsp
+ reference
+
+.. _`public key infrastructure`: https://en.wikipedia.org/wiki/Public_key_infrastructure
+.. _`TLS`: https://en.wikipedia.org/wiki/Transport_Layer_Security
diff --git a/docs/x509/ocsp.rst b/docs/x509/ocsp.rst
new file mode 100644
index 00000000..80ff9908
--- /dev/null
+++ b/docs/x509/ocsp.rst
@@ -0,0 +1,689 @@
+OCSP
+====
+
+.. currentmodule:: cryptography.x509.ocsp
+
+.. testsetup::
+
+ import base64
+ pem_cert = b"""
+ -----BEGIN CERTIFICATE-----
+ MIIFvTCCBKWgAwIBAgICPyAwDQYJKoZIhvcNAQELBQAwRzELMAkGA1UEBhMCVVMx
+ FjAUBgNVBAoTDUdlb1RydXN0IEluYy4xIDAeBgNVBAMTF1JhcGlkU1NMIFNIQTI1
+ NiBDQSAtIEczMB4XDTE0MTAxNTEyMDkzMloXDTE4MTExNjAxMTUwM1owgZcxEzAR
+ BgNVBAsTCkdUNDg3NDI5NjUxMTAvBgNVBAsTKFNlZSB3d3cucmFwaWRzc2wuY29t
+ L3Jlc291cmNlcy9jcHMgKGMpMTQxLzAtBgNVBAsTJkRvbWFpbiBDb250cm9sIFZh
+ bGlkYXRlZCAtIFJhcGlkU1NMKFIpMRwwGgYDVQQDExN3d3cuY3J5cHRvZ3JhcGh5
+ LmlvMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAom/FebKJIot7Sp3s
+ itG1sicpe3thCssjI+g1JDAS7I3GLVNmbms1DOdIIqwf01gZkzzXBN2+9sOnyRaR
+ PPfCe1jTr3dk2y6rPE559vPa1nZQkhlzlhMhlPyjaT+S7g4Tio4qV2sCBZU01DZJ
+ CaksfohN+5BNVWoJzTbOcrHOEJ+M8B484KlBCiSxqf9cyNQKru4W3bHaCVNVJ8eu
+ 6i6KyhzLa0L7yK3LXwwXVs583C0/vwFhccGWsFODqD/9xHUzsBIshE8HKjdjDi7Y
+ 3BFQzVUQFjBB50NSZfAA/jcdt1blxJouc7z9T8Oklh+V5DDBowgAsrT4b6Z2Fq6/
+ r7D1GqivLK/ypUQmxq2WXWAUBb/Q6xHgxASxI4Br+CByIUQJsm8L2jzc7k+mF4hW
+ ltAIUkbo8fGiVnat0505YJgxWEDKOLc4Gda6d/7GVd5AvKrz242bUqeaWo6e4MTx
+ diku2Ma3rhdcr044Qvfh9hGyjqNjvhWY/I+VRWgihU7JrYvgwFdJqsQ5eiKT4OHi
+ gsejvWwkZzDtiQ+aQTrzM1FsY2swJBJsLSX4ofohlVRlIJCn/ME+XErj553431Lu
+ YQ5SzMd3nXzN78Vj6qzTfMUUY72UoT1/AcFiUMobgIqrrmwuNxfrkbVE2b6Bga74
+ FsJX63prvrJ41kuHK/16RQBM7fcCAwEAAaOCAWAwggFcMB8GA1UdIwQYMBaAFMOc
+ 8/zTRgg0u85Gf6B8W/PiCMtZMFcGCCsGAQUFBwEBBEswSTAfBggrBgEFBQcwAYYT
+ aHR0cDovL2d2LnN5bWNkLmNvbTAmBggrBgEFBQcwAoYaaHR0cDovL2d2LnN5bWNi
+ LmNvbS9ndi5jcnQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMB
+ BggrBgEFBQcDAjAvBgNVHREEKDAmghN3d3cuY3J5cHRvZ3JhcGh5Lmlvgg9jcnlw
+ dG9ncmFwaHkuaW8wKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL2d2LnN5bWNiLmNv
+ bS9ndi5jcmwwDAYDVR0TAQH/BAIwADBFBgNVHSAEPjA8MDoGCmCGSAGG+EUBBzYw
+ LDAqBggrBgEFBQcCARYeaHR0cHM6Ly93d3cucmFwaWRzc2wuY29tL2xlZ2FsMA0G
+ CSqGSIb3DQEBCwUAA4IBAQAzIYO2jx7h17FBT74tJ2zbV9OKqGb7QF8y3wUtP4xc
+ dH80vprI/Cfji8s86kr77aAvAqjDjaVjHn7UzebhSUivvRPmfzRgyWBacomnXTSt
+ Xlt2dp2nDQuwGyK2vB7dMfKnQAkxwq1sYUXznB8i0IhhCAoXp01QGPKq51YoIlnF
+ 7DRMk6iEaL1SJbkIrLsCQyZFDf0xtfW9DqXugMMLoxeCsBhZJQzNyS2ryirrv9LH
+ aK3+6IZjrcyy9bkpz/gzJucyhU+75c4My/mnRCrtItRbCQuiI5pd5poDowm+HH9i
+ GVI9+0lAFwxOUnOnwsoI40iOoxjLMGB+CgFLKCGUcWxP
+ -----END CERTIFICATE-----
+ """
+ pem_issuer = b"""
+ -----BEGIN CERTIFICATE-----
+ MIIEJTCCAw2gAwIBAgIDAjp3MA0GCSqGSIb3DQEBCwUAMEIxCzAJBgNVBAYTAlVT
+ MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
+ YWwgQ0EwHhcNMTQwODI5MjEzOTMyWhcNMjIwNTIwMjEzOTMyWjBHMQswCQYDVQQG
+ EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXUmFwaWRTU0wg
+ U0hBMjU2IENBIC0gRzMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCv
+ VJvZWF0eLFbG1eh/9H0WA//Qi1rkjqfdVC7UBMBdmJyNkA+8EGVf2prWRHzAn7Xp
+ SowLBkMEu/SW4ib2YQGRZjEiwzQ0Xz8/kS9EX9zHFLYDn4ZLDqP/oIACg8PTH2lS
+ 1p1kD8mD5xvEcKyU58Okaiy9uJ5p2L4KjxZjWmhxgHsw3hUEv8zTvz5IBVV6s9cQ
+ DAP8m/0Ip4yM26eO8R5j3LMBL3+vV8M8SKeDaCGnL+enP/C1DPz1hNFTvA5yT2AM
+ QriYrRmIV9cE7Ie/fodOoyH5U/02mEiN1vi7SPIpyGTRzFRIU4uvt2UevykzKdkp
+ YEj4/5G8V1jlNS67abZZAgMBAAGjggEdMIIBGTAfBgNVHSMEGDAWgBTAephojYn7
+ qwVkDBF9qn1luMrMTjAdBgNVHQ4EFgQUw5zz/NNGCDS7zkZ/oHxb8+IIy1kwEgYD
+ VR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwNQYDVR0fBC4wLDAqoCig
+ JoYkaHR0cDovL2cuc3ltY2IuY29tL2NybHMvZ3RnbG9iYWwuY3JsMC4GCCsGAQUF
+ BwEBBCIwIDAeBggrBgEFBQcwAYYSaHR0cDovL2cuc3ltY2QuY29tMEwGA1UdIARF
+ MEMwQQYKYIZIAYb4RQEHNjAzMDEGCCsGAQUFBwIBFiVodHRwOi8vd3d3Lmdlb3Ry
+ dXN0LmNvbS9yZXNvdXJjZXMvY3BzMA0GCSqGSIb3DQEBCwUAA4IBAQCjWB7GQzKs
+ rC+TeLfqrlRARy1+eI1Q9vhmrNZPc9ZE768LzFvB9E+aj0l+YK/CJ8cW8fuTgZCp
+ fO9vfm5FlBaEvexJ8cQO9K8EWYOHDyw7l8NaEpt7BDV7o5UzCHuTcSJCs6nZb0+B
+ kvwHtnm8hEqddwnxxYny8LScVKoSew26T++TGezvfU5ho452nFnPjJSxhJf3GrkH
+ uLLGTxN5279PURt/aQ1RKsHWFf83UTRlUfQevjhq7A6rvz17OQV79PP7GqHQyH5O
+ ZI3NjGFVkP46yl0lD/gdo0p0Vk8aVUBwdSWmMy66S6VdU5oNMOGNX2Esr8zvsJmh
+ gP8L8mJMcCaY
+ -----END CERTIFICATE-----
+ """
+ pem_responder_cert = b"""
+ -----BEGIN CERTIFICATE-----
+ MIIBPjCB5KADAgECAgQHW80VMAoGCCqGSM49BAMCMCcxCzAJBgNVBAYTAlVTMRgw
+ FgYDVQQDDA9DcnlwdG9ncmFwaHkgQ0EwHhcNMTgxMDA3MTIzNTEwWhcNMjgxMDA0
+ MTIzNTEwWjAnMQswCQYDVQQGEwJVUzEYMBYGA1UEAwwPQ3J5cHRvZ3JhcGh5IENB
+ MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEbQ2E0N/E3R0zEG+qa+yAFXBY6Fte
+ QzyvFdq7EZHDktlyUllaVJBrbX1ItV0MlayFwwQPhZmuLPpQBzuVKyrUfTAKBggq
+ hkjOPQQDAgNJADBGAiEAo0NQRmfPvhWQpSvJzV+2Ag441Zeckk+bib7swduQIjIC
+ IQCqYD9pArB2SWfmhQCSZkNEATlsPIML8lvlSkbNcrmrqQ==
+ -----END CERTIFICATE-----
+ """
+ pem_responder_key = b"""
+ -----BEGIN PRIVATE KEY-----
+ MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgO+vsRu8xDIVZE+xh
+ s8ESqJqcpJlwmj8CtF8HPHxrDSGhRANCAARtDYTQ38TdHTMQb6pr7IAVcFjoW15D
+ PK8V2rsRkcOS2XJSWVpUkGttfUi1XQyVrIXDBA+Fma4s+lAHO5UrKtR9
+ -----END PRIVATE KEY-----
+ """
+ der_ocsp_req = (
+ b"0V0T0R0P0N0\t\x06\x05+\x0e\x03\x02\x1a\x05\x00\x04\x148\xcaF\x8c"
+ b"\x07D\x8d\xf4\x81\x96\xc7mmLpQ\x9e`\xa7\xbd\x04\x14yu\xbb\x84:\xcb"
+ b",\xdez\t\xbe1\x1bC\xbc\x1c*MSX\x02\x15\x00\x98\xd9\xe5\xc0\xb4\xc3"
+ b"sU-\xf7|]\x0f\x1e\xb5\x12\x8eIE\xf9"
+ )
+ der_ocsp_resp_unauth = b"0\x03\n\x01\x06"
+
+OCSP (Online Certificate Status Protocol) is a method of checking the
+revocation status of certificates. It is specified in :rfc:`6960`, as well
+as other obsoleted RFCs.
+
+
+Loading Requests
+~~~~~~~~~~~~~~~~
+
+.. function:: load_der_ocsp_request(data)
+
+ .. versionadded:: 2.4
+
+ Deserialize an OCSP request from DER encoded data.
+
+ :param bytes data: The DER encoded OCSP request data.
+
+ :returns: An instance of :class:`~cryptography.x509.ocsp.OCSPRequest`.
+
+ .. doctest::
+
+ >>> from cryptography.x509 import ocsp
+ >>> ocsp_req = ocsp.load_der_ocsp_request(der_ocsp_req)
+ >>> print(ocsp_req.serial_number)
+ 872625873161273451176241581705670534707360122361
+
+
+Creating Requests
+~~~~~~~~~~~~~~~~~
+
+.. class:: OCSPRequestBuilder
+
+ .. versionadded:: 2.4
+
+ This class is used to create :class:`~cryptography.x509.ocsp.OCSPRequest`
+ objects.
+
+
+ .. method:: add_certificate(cert, issuer, algorithm)
+
+ Adds a request using a certificate, issuer certificate, and hash
+ algorithm. This can only be called once.
+
+ :param cert: The :class:`~cryptography.x509.Certificate` whose validity
+ is being checked.
+
+ :param issuer: The issuer :class:`~cryptography.x509.Certificate` of
+ the certificate that is being checked.
+
+ :param algorithm: A
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+ instance. For OCSP only
+ :class:`~cryptography.hazmat.primitives.hashes.SHA1`,
+ :class:`~cryptography.hazmat.primitives.hashes.SHA224`,
+ :class:`~cryptography.hazmat.primitives.hashes.SHA256`,
+ :class:`~cryptography.hazmat.primitives.hashes.SHA384`, and
+ :class:`~cryptography.hazmat.primitives.hashes.SHA512` are allowed.
+
+ .. method:: add_extension(extension, critical)
+
+ Adds an extension to the request.
+
+ :param extension: An extension conforming to the
+ :class:`~cryptography.x509.ExtensionType` interface.
+
+ :param critical: Set to ``True`` if the extension must be understood and
+ handled.
+
+ .. method:: build()
+
+ :returns: A new :class:`~cryptography.x509.ocsp.OCSPRequest`.
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> from cryptography.hazmat.primitives import serialization
+ >>> from cryptography.hazmat.primitives.hashes import SHA1
+ >>> from cryptography.x509 import load_pem_x509_certificate, ocsp
+ >>> cert = load_pem_x509_certificate(pem_cert, default_backend())
+ >>> issuer = load_pem_x509_certificate(pem_issuer, default_backend())
+ >>> builder = ocsp.OCSPRequestBuilder()
+ >>> # SHA1 is in this example because RFC 5019 mandates its use.
+ >>> builder = builder.add_certificate(cert, issuer, SHA1())
+ >>> req = builder.build()
+ >>> base64.b64encode(req.public_bytes(serialization.Encoding.DER))
+ b'MEMwQTA/MD0wOzAJBgUrDgMCGgUABBRAC0Z68eay0wmDug1gfn5ZN0gkxAQUw5zz/NNGCDS7zkZ/oHxb8+IIy1kCAj8g'
+
+Loading Responses
+~~~~~~~~~~~~~~~~~
+
+.. function:: load_der_ocsp_response(data)
+
+ .. versionadded:: 2.4
+
+ Deserialize an OCSP response from DER encoded data.
+
+ :param bytes data: The DER encoded OCSP response data.
+
+ :returns: An instance of :class:`~cryptography.x509.ocsp.OCSPResponse`.
+
+ .. doctest::
+
+ >>> from cryptography.x509 import ocsp
+ >>> ocsp_resp = ocsp.load_der_ocsp_response(der_ocsp_resp_unauth)
+ >>> print(ocsp_resp.response_status)
+ OCSPResponseStatus.UNAUTHORIZED
+
+
+Creating Responses
+~~~~~~~~~~~~~~~~~~
+
+.. class:: OCSPResponseBuilder
+
+ .. versionadded:: 2.4
+
+ This class is used to create :class:`~cryptography.x509.ocsp.OCSPResponse`
+ objects. You cannot set ``produced_at`` on OCSP responses at this time.
+ Instead the field is set to current UTC time when calling ``sign``. For
+ unsuccessful statuses call the class method
+ :meth:`~cryptography.x509.ocsp.OCSPResponseBuilder.build_unsuccessful`.
+
+ .. method:: add_response(cert, issuer, algorithm, cert_status, this_update, next_update, revocation_time, revocation_reason)
+
+ This method adds status information about the certificate that was
+ requested to the response.
+
+ :param cert: The :class:`~cryptography.x509.Certificate` whose validity
+ is being checked.
+
+ :param issuer: The issuer :class:`~cryptography.x509.Certificate` of
+ the certificate that is being checked.
+
+ :param algorithm: A
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+ instance. For OCSP only
+ :class:`~cryptography.hazmat.primitives.hashes.SHA1`,
+ :class:`~cryptography.hazmat.primitives.hashes.SHA224`,
+ :class:`~cryptography.hazmat.primitives.hashes.SHA256`,
+ :class:`~cryptography.hazmat.primitives.hashes.SHA384`, and
+ :class:`~cryptography.hazmat.primitives.hashes.SHA512` are allowed.
+
+ :param cert_status: An item from the
+ :class:`~cryptography.x509.ocsp.OCSPCertStatus` enumeration.
+
+ :param this_update: A naïve :class:`datetime.datetime` object
+ representing the most recent time in UTC at which the status being
+ indicated is known by the responder to be correct.
+
+ :param next_update: A naïve :class:`datetime.datetime` object or
+ ``None``. The time in UTC at or before which newer information will
+ be available about the status of the certificate.
+
+ :param revocation_time: A naïve :class:`datetime.datetime` object or
+ ``None`` if the ``cert`` is not revoked. The time in UTC at which
+ the certificate was revoked.
+
+ :param revocation_reason: An item from the
+ :class:`~cryptography.x509.ReasonFlags` enumeration or ``None`` if
+ the ``cert`` is not revoked.
+
+ .. method:: certificates(certs)
+
+ Add additional certificates that should be used to verify the
+ signature on the response. This is typically used when the responder
+ utilizes an OCSP delegate.
+
+ :param list certs: A list of :class:`~cryptography.x509.Certificate`
+ objects.
+
+ .. method:: responder_id(encoding, responder_cert)
+
+ Set the ``responderID`` on the OCSP response. This is the data a
+ client will use to determine what certificate signed the response.
+
+ :param responder_cert: The :class:`~cryptography.x509.Certificate`
+ object for the certificate whose private key will sign the
+ OCSP response. If the certificate and key do not match an
+ error will be raised when calling ``sign``.
+ :param encoding: Either
+ :attr:`~cryptography.x509.ocsp.OCSPResponderEncoding.HASH` or
+ :attr:`~cryptography.x509.ocsp.OCSPResponderEncoding.NAME`.
+
+ .. method:: add_extension(extension, critical)
+
+ Adds an extension to the response.
+
+ :param extension: An extension conforming to the
+ :class:`~cryptography.x509.ExtensionType` interface.
+
+ :param critical: Set to ``True`` if the extension must be understood and
+ handled.
+
+ .. method:: sign(private_key, algorithm)
+
+ Creates the OCSP response that can then be serialized and sent to
+ clients. This method will create a
+ :attr:`~cryptography.x509.ocsp.OCSPResponseStatus.SUCCESSFUL` response.
+
+ :param private_key: The
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey`
+ that will be used to sign the certificate.
+
+ :param algorithm: The
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` that
+ will be used to generate the signature. This must be ``None`` if
+ the ``private_key`` is an
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey`
+ or an
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey`
+ and an instance of a
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+ otherwise.
+
+ :returns: A new :class:`~cryptography.x509.ocsp.OCSPResponse`.
+
+ .. doctest::
+
+ >>> import datetime
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> from cryptography.hazmat.primitives import hashes, serialization
+ >>> from cryptography.x509 import load_pem_x509_certificate, ocsp
+ >>> cert = load_pem_x509_certificate(pem_cert, default_backend())
+ >>> issuer = load_pem_x509_certificate(pem_issuer, default_backend())
+ >>> responder_cert = load_pem_x509_certificate(pem_responder_cert, default_backend())
+ >>> responder_key = serialization.load_pem_private_key(pem_responder_key, None, default_backend())
+ >>> builder = ocsp.OCSPResponseBuilder()
+ >>> # SHA1 is in this example because RFC 5019 mandates its use.
+ >>> builder = builder.add_response(
+ ... cert=cert, issuer=issuer, algorithm=hashes.SHA1(),
+ ... cert_status=ocsp.OCSPCertStatus.GOOD,
+ ... this_update=datetime.datetime.now(),
+ ... next_update=datetime.datetime.now(),
+ ... revocation_time=None, revocation_reason=None
+ ... ).responder_id(
+ ... ocsp.OCSPResponderEncoding.HASH, responder_cert
+ ... )
+ >>> response = builder.sign(responder_key, hashes.SHA256())
+ >>> response.certificate_status
+ <OCSPCertStatus.GOOD: 0>
+
+ .. classmethod:: build_unsuccessful(response_status)
+
+ Creates an unsigned OCSP response which can then be serialized and
+ sent to clients. ``build_unsuccessful`` may only be called with a
+ :class:`~cryptography.x509.ocsp.OCSPResponseStatus` that is not
+ ``SUCCESSFUL``. Since this is a class method note that no other
+ methods can or should be called as unsuccessful statuses do not
+ encode additional data.
+
+ :returns: A new :class:`~cryptography.x509.ocsp.OCSPResponse`.
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> from cryptography.hazmat.primitives import hashes, serialization
+ >>> from cryptography.x509 import load_pem_x509_certificate, ocsp
+ >>> response = ocsp.OCSPResponseBuilder.build_unsuccessful(
+ ... ocsp.OCSPResponseStatus.UNAUTHORIZED
+ ... )
+ >>> response.response_status
+ <OCSPResponseStatus.UNAUTHORIZED: 6>
+
+
+Interfaces
+~~~~~~~~~~
+
+.. class:: OCSPRequest
+
+ .. versionadded:: 2.4
+
+ An ``OCSPRequest`` is an object containing information about a certificate
+ whose status is being checked.
+
+ .. attribute:: issuer_key_hash
+
+ :type: bytes
+
+ The hash of the certificate issuer's key. The hash algorithm used
+ is defined by the ``hash_algorithm`` property.
+
+ .. attribute:: issuer_name_hash
+
+ :type: bytes
+
+ The hash of the certificate issuer's name. The hash algorithm used
+ is defined by the ``hash_algorithm`` property.
+
+ .. attribute:: hash_algorithm
+
+ :type: :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+
+ The algorithm used to generate the ``issuer_key_hash`` and
+ ``issuer_name_hash``.
+
+ .. attribute:: serial_number
+
+ :type: int
+
+ The serial number of the certificate to check.
+
+ .. attribute:: extensions
+
+ :type: :class:`~cryptography.x509.Extensions`
+
+ The extensions encoded in the request.
+
+ .. method:: public_bytes(encoding)
+
+ :param encoding: The encoding to use. Only
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`
+ is supported.
+
+ :return bytes: The serialized OCSP request.
+
+.. class:: OCSPResponse
+
+ .. versionadded:: 2.4
+
+ An ``OCSPResponse`` is the data provided by an OCSP responder in response
+ to an ``OCSPRequest``.
+
+ .. attribute:: response_status
+
+ :type: :class:`~cryptography.x509.ocsp.OCSPResponseStatus`
+
+ The status of the response.
+
+ .. attribute:: signature_algorithm_oid
+
+ :type: :class:`~cryptography.x509.ObjectIdentifier`
+
+ Returns the object identifier of the signature algorithm used
+ to sign the response. This will be one of the OIDs from
+ :class:`~cryptography.x509.oid.SignatureAlgorithmOID`.
+
+ :raises ValueError: If ``response_status`` is not
+ :class:`~cryptography.x509.ocsp.OCSPResponseStatus.SUCCESSFUL`.
+
+ .. attribute:: signature_hash_algorithm
+
+ .. versionadded:: 2.5
+
+ :type: :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+
+ Returns the
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` which
+ was used in signing this response. Can be ``None`` if signature
+ did not use separate hash
+ (:attr:`~cryptography.x509.oid.SignatureAlgorithmOID.ED25519`,
+ :attr:`~cryptography.x509.oid.SignatureAlgorithmOID.ED448`).
+
+ .. attribute:: signature
+
+ :type: bytes
+
+ The signature bytes.
+
+ :raises ValueError: If ``response_status`` is not
+ :class:`~cryptography.x509.ocsp.OCSPResponseStatus.SUCCESSFUL`.
+
+ .. attribute:: tbs_response_bytes
+
+ :type: bytes
+
+ The DER encoded bytes payload that is hashed and then signed. This
+ data may be used to validate the signature on the OCSP response.
+
+ :raises ValueError: If ``response_status`` is not
+ :class:`~cryptography.x509.ocsp.OCSPResponseStatus.SUCCESSFUL`.
+
+ .. attribute:: certificates
+
+ :type: list
+
+ A list of zero or more :class:`~cryptography.x509.Certificate` objects
+ used to help build a chain to verify the OCSP response. This situation
+ occurs when the OCSP responder uses a delegate certificate.
+
+ :raises ValueError: If ``response_status`` is not
+ :class:`~cryptography.x509.ocsp.OCSPResponseStatus.SUCCESSFUL`.
+
+ .. attribute:: responder_key_hash
+
+ :type: bytes or None
+
+ The responder's key hash or ``None`` if the response has a
+ ``responder_name``.
+
+ :raises ValueError: If ``response_status`` is not
+ :class:`~cryptography.x509.ocsp.OCSPResponseStatus.SUCCESSFUL`.
+
+ .. attribute:: responder_name
+
+ :type: :class:`~cryptography.x509.Name` or None
+
+ The responder's ``Name`` or ``None`` if the response has a
+ ``responder_key_hash``.
+
+ :raises ValueError: If ``response_status`` is not
+ :class:`~cryptography.x509.ocsp.OCSPResponseStatus.SUCCESSFUL`.
+
+ .. attribute:: produced_at
+
+ :type: :class:`datetime.datetime`
+
+ A naïve datetime representing the time when the response was produced.
+
+ :raises ValueError: If ``response_status`` is not
+ :class:`~cryptography.x509.ocsp.OCSPResponseStatus.SUCCESSFUL`.
+
+ .. attribute:: certificate_status
+
+ :type: :class:`~cryptography.x509.ocsp.OCSPCertStatus`
+
+ The status of the certificate being checked.
+
+ :raises ValueError: If ``response_status`` is not
+ :class:`~cryptography.x509.ocsp.OCSPResponseStatus.SUCCESSFUL`.
+
+ .. attribute:: revocation_time
+
+ :type: :class:`datetime.datetime` or None
+
+ A naïve datetime representing the time when the certificate was revoked
+ or ``None`` if the certificate has not been revoked.
+
+ :raises ValueError: If ``response_status`` is not
+ :class:`~cryptography.x509.ocsp.OCSPResponseStatus.SUCCESSFUL`.
+
+ .. attribute:: revocation_reason
+
+ :type: :class:`~cryptography.x509.ReasonFlags` or None
+
+ The reason the certificate was revoked or ``None`` if not specified or
+ not revoked.
+
+ :raises ValueError: If ``response_status`` is not
+ :class:`~cryptography.x509.ocsp.OCSPResponseStatus.SUCCESSFUL`.
+
+ .. attribute:: this_update
+
+ :type: :class:`datetime.datetime`
+
+ A naïve datetime representing the most recent time at which the status
+ being indicated is known by the responder to have been correct.
+
+ :raises ValueError: If ``response_status`` is not
+ :class:`~cryptography.x509.ocsp.OCSPResponseStatus.SUCCESSFUL`.
+
+ .. attribute:: next_update
+
+ :type: :class:`datetime.datetime`
+
+ A naïve datetime representing the time when newer information will
+ be available.
+
+ :raises ValueError: If ``response_status`` is not
+ :class:`~cryptography.x509.ocsp.OCSPResponseStatus.SUCCESSFUL`.
+
+ .. attribute:: issuer_key_hash
+
+ :type: bytes
+
+ The hash of the certificate issuer's key. The hash algorithm used
+ is defined by the ``hash_algorithm`` property.
+
+ :raises ValueError: If ``response_status`` is not
+ :class:`~cryptography.x509.ocsp.OCSPResponseStatus.SUCCESSFUL`.
+
+ .. attribute:: issuer_name_hash
+
+ :type: bytes
+
+ The hash of the certificate issuer's name. The hash algorithm used
+ is defined by the ``hash_algorithm`` property.
+
+ :raises ValueError: If ``response_status`` is not
+ :class:`~cryptography.x509.ocsp.OCSPResponseStatus.SUCCESSFUL`.
+
+ .. attribute:: hash_algorithm
+
+ :type: :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+
+ The algorithm used to generate the ``issuer_key_hash`` and
+ ``issuer_name_hash``.
+
+ :raises ValueError: If ``response_status`` is not
+ :class:`~cryptography.x509.ocsp.OCSPResponseStatus.SUCCESSFUL`.
+
+ .. attribute:: serial_number
+
+ :type: int
+
+ The serial number of the certificate that was checked.
+
+ :raises ValueError: If ``response_status`` is not
+ :class:`~cryptography.x509.ocsp.OCSPResponseStatus.SUCCESSFUL`.
+
+ .. attribute:: extensions
+
+ :type: :class:`~cryptography.x509.Extensions`
+
+ The extensions encoded in the response.
+
+ .. attribute:: single_extensions
+
+ .. versionadded:: 2.9
+
+ :type: :class:`~cryptography.x509.Extensions`
+
+ The single extensions encoded in the response.
+
+ .. method:: public_bytes(encoding)
+
+ :param encoding: The encoding to use. Only
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`
+ is supported.
+
+ :return bytes: The serialized OCSP response.
+
+.. class:: OCSPResponseStatus
+
+ .. versionadded:: 2.4
+
+ An enumeration of response statuses.
+
+ .. attribute:: SUCCESSFUL
+
+ Represents a successful OCSP response.
+
+ .. attribute:: MALFORMED_REQUEST
+
+ May be returned by an OCSP responder that is unable to parse a
+ given request.
+
+ .. attribute:: INTERNAL_ERROR
+
+ May be returned by an OCSP responder that is currently experiencing
+ operational problems.
+
+ .. attribute:: TRY_LATER
+
+ May be returned by an OCSP responder that is overloaded.
+
+ .. attribute:: SIG_REQUIRED
+
+ May be returned by an OCSP responder that requires signed OCSP
+ requests.
+
+ .. attribute:: UNAUTHORIZED
+
+ May be returned by an OCSP responder when queried for a certificate for
+ which the responder is unaware or an issuer for which the responder is
+ not authoritative.
+
+
+.. class:: OCSPCertStatus
+
+ .. versionadded:: 2.4
+
+ An enumeration of certificate statuses in an OCSP response.
+
+ .. attribute:: GOOD
+
+ The value for a certificate that is not revoked.
+
+ .. attribute:: REVOKED
+
+ The certificate being checked is revoked.
+
+ .. attribute:: UNKNOWN
+
+ The certificate being checked is not known to the OCSP responder.
+
+.. class:: OCSPResponderEncoding
+
+ .. versionadded:: 2.4
+
+ An enumeration of ``responderID`` encodings that can be passed to
+ :meth:`~cryptography.x509.ocsp.OCSPResponseBuilder.responder_id`.
+
+ .. attribute:: HASH
+
+ Encode the hash of the public key whose corresponding private key
+ signed the response.
+
+ .. attribute:: NAME
+
+ Encode the X.509 ``Name`` of the certificate whose private key signed
+ the response.
diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst
new file mode 100644
index 00000000..fac2a351
--- /dev/null
+++ b/docs/x509/reference.rst
@@ -0,0 +1,3200 @@
+X.509 Reference
+===============
+
+.. currentmodule:: cryptography.x509
+
+.. testsetup::
+
+ pem_crl_data = b"""
+ -----BEGIN X509 CRL-----
+ MIIBtDCBnQIBAjANBgkqhkiG9w0BAQsFADAnMQswCQYDVQQGEwJVUzEYMBYGA1UE
+ AwwPY3J5cHRvZ3JhcGh5LmlvGA8yMDE1MDEwMTAwMDAwMFoYDzIwMTYwMTAxMDAw
+ MDAwWjA+MDwCAQAYDzIwMTUwMTAxMDAwMDAwWjAmMBgGA1UdGAQRGA8yMDE1MDEw
+ MTAwMDAwMFowCgYDVR0VBAMKAQEwDQYJKoZIhvcNAQELBQADggEBABRA4ww50Lz5
+ zk1j2+aluC4HPHqb7o06h4pTDcCGeXUKXIGeP5ntGGmIoxa26sNoLeOr8+5b43Gf
+ yWraHertllOwaOpNFEe+YZFaE9femtoDbf+GLMvRx/0wDfd3KxPoXnXKMXb2d1w4
+ RCLgmkYx6JyvS+5ciuLQVIKC+l7jwIUeZFLJMUJ8msM4pFYoGameeZmtjMbd/TNg
+ cVBfmZxNMHuLladJxvSo2esARo0TYPhYsgrREKoHwhpzSxdynjn4bOVkILfguwsN
+ qtEEMZFEv5Kb0GqRp2+Iagv2S6dg9JGvxVdsoGjaB6EbYSZ3Psx4aODasIn11uwo
+ X4B9vUQNXqc=
+ -----END X509 CRL-----
+ """.strip()
+
+ pem_req_data = b"""
+ -----BEGIN CERTIFICATE REQUEST-----
+ MIIC0zCCAbsCAQAwWTELMAkGA1UEBhMCVVMxETAPBgNVBAgMCElsbGlub2lzMRAw
+ DgYDVQQHDAdDaGljYWdvMREwDwYDVQQKDAhyNTA5IExMQzESMBAGA1UEAwwJaGVs
+ bG8uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqhZx+Mo9VRd9
+ vsnWWa6NBCws21rZ0+1B/JGgB4hDsZS7iDE4Bj5z4idheFRtl8bBbdjPknq7BfoF
+ 8v15Zq/Zv7i2xMSDL+LUrTBZezRd4bRTGqCm6YJ5EYkhqdcqeZleHCFImguHoq1J
+ Fh0+kObQrTHXw3ZP57a3o1IvyIUA3nNoCBL0QQhwBXaDXOojMKNR+bqB5ve8GS1y
+ Elr0AM/+cJsfaIahNQUgFKx3Eu3GeEOMKYOAG1lycgdQdmTUybLrT3U7vkClTseM
+ xHg1r5En7ALjONIhqRuq3rddYahrP8HXozb3zUy3cJ7P6IeaosuvNzvMXOX9P6HD
+ Ha9urDAJ1wIDAQABoDUwMwYJKoZIhvcNAQkOMSYwJDAiBgNVHREEGzAZggl3b3Js
+ ZC5jb22CDHdoYXRldmVyLmNvbTANBgkqhkiG9w0BAQUFAAOCAQEAS4Ro6h+z52SK
+ YSLCYARpnEu/rmh4jdqndt8naqcNb6uLx9mlKZ2W9on9XDjnSdQD9q+ZP5aZfESw
+ R0+rJhW9ZrNa/g1pt6M24ihclHYDAxYMWxT1z/TXXGM3TmZZ6gfYlNE1kkBuODHa
+ UYsR/1Ht1E1EsmmUimt2n+zQR2K8T9Coa+boaUW/GsTEuz1aaJAkj5ZvTDiIhRG4
+ AOCqFZOLAQmCCNgJnnspD9hDz/Ons085LF5wnYjN4/Nsk5tS6AGs3xjZ3jPoOGGn
+ 82WQ9m4dBGoVDZXsobVTaN592JEYwN5iu72zRn7Einb4V4H5y3yD2dD4yWPlt4pk
+ 5wFkeYsZEA==
+ -----END CERTIFICATE REQUEST-----
+ """.strip()
+
+ pem_data = b"""
+ -----BEGIN CERTIFICATE-----
+ MIIDfDCCAmSgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEf
+ MB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3Qg
+ QW5jaG9yMB4XDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowQDELMAkGA1UE
+ BhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExEDAOBgNVBAMT
+ B0dvb2QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCQWJpHYo37
+ Xfb7oJSPe+WvfTlzIG21WQ7MyMbGtK/m8mejCzR6c+f/pJhEH/OcDSMsXq8h5kXa
+ BGqWK+vSwD/Pzp5OYGptXmGPcthDtAwlrafkGOS4GqIJ8+k9XGKs+vQUXJKsOk47
+ RuzD6PZupq4s16xaLVqYbUC26UcY08GpnoLNHJZS/EmXw1ZZ3d4YZjNlpIpWFNHn
+ UGmdiGKXUPX/9H0fVjIAaQwjnGAbpgyCumWgzIwPpX+ElFOUr3z7BoVnFKhIXze+
+ VmQGSWxZxvWDUN90Ul0tLEpLgk3OVxUB4VUGuf15OJOpgo1xibINPmWt14Vda2N9
+ yrNKloJGZNqLAgMBAAGjfDB6MB8GA1UdIwQYMBaAFOR9X9FclYYILAWuvnW2ZafZ
+ XahmMB0GA1UdDgQWBBRYAYQkG7wrUpRKPaUQchRR9a86yTAOBgNVHQ8BAf8EBAMC
+ AQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
+ KoZIhvcNAQELBQADggEBADWHlxbmdTXNwBL/llwhQqwnazK7CC2WsXBBqgNPWj7m
+ tvQ+aLG8/50Qc2Sun7o2VnwF9D18UUe8Gj3uPUYH+oSI1vDdyKcjmMbKRU4rk0eo
+ 3UHNDXwqIVc9CQS9smyV+x1HCwL4TTrq+LXLKx/qVij0Yqk+UJfAtrg2jnYKXsCu
+ FMBQQnWCGrwa1g1TphRp/RmYHnMynYFmZrXtzFz+U9XEA7C+gPq4kqDI/iVfIT1s
+ 6lBtdB50lrDVwl2oYfAvW/6sC2se2QleZidUmrziVNP4oEeXINokU6T6p//HM1FG
+ QYw2jOvpKcKtWCSAnegEbgsGYzATKjmPJPJ0npHFqzM=
+ -----END CERTIFICATE-----
+ """.strip()
+
+ cryptography_cert_pem = b"""
+ -----BEGIN CERTIFICATE-----
+ MIIFvTCCBKWgAwIBAgICPyAwDQYJKoZIhvcNAQELBQAwRzELMAkGA1UEBhMCVVMx
+ FjAUBgNVBAoTDUdlb1RydXN0IEluYy4xIDAeBgNVBAMTF1JhcGlkU1NMIFNIQTI1
+ NiBDQSAtIEczMB4XDTE0MTAxNTEyMDkzMloXDTE4MTExNjAxMTUwM1owgZcxEzAR
+ BgNVBAsTCkdUNDg3NDI5NjUxMTAvBgNVBAsTKFNlZSB3d3cucmFwaWRzc2wuY29t
+ L3Jlc291cmNlcy9jcHMgKGMpMTQxLzAtBgNVBAsTJkRvbWFpbiBDb250cm9sIFZh
+ bGlkYXRlZCAtIFJhcGlkU1NMKFIpMRwwGgYDVQQDExN3d3cuY3J5cHRvZ3JhcGh5
+ LmlvMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAom/FebKJIot7Sp3s
+ itG1sicpe3thCssjI+g1JDAS7I3GLVNmbms1DOdIIqwf01gZkzzXBN2+9sOnyRaR
+ PPfCe1jTr3dk2y6rPE559vPa1nZQkhlzlhMhlPyjaT+S7g4Tio4qV2sCBZU01DZJ
+ CaksfohN+5BNVWoJzTbOcrHOEJ+M8B484KlBCiSxqf9cyNQKru4W3bHaCVNVJ8eu
+ 6i6KyhzLa0L7yK3LXwwXVs583C0/vwFhccGWsFODqD/9xHUzsBIshE8HKjdjDi7Y
+ 3BFQzVUQFjBB50NSZfAA/jcdt1blxJouc7z9T8Oklh+V5DDBowgAsrT4b6Z2Fq6/
+ r7D1GqivLK/ypUQmxq2WXWAUBb/Q6xHgxASxI4Br+CByIUQJsm8L2jzc7k+mF4hW
+ ltAIUkbo8fGiVnat0505YJgxWEDKOLc4Gda6d/7GVd5AvKrz242bUqeaWo6e4MTx
+ diku2Ma3rhdcr044Qvfh9hGyjqNjvhWY/I+VRWgihU7JrYvgwFdJqsQ5eiKT4OHi
+ gsejvWwkZzDtiQ+aQTrzM1FsY2swJBJsLSX4ofohlVRlIJCn/ME+XErj553431Lu
+ YQ5SzMd3nXzN78Vj6qzTfMUUY72UoT1/AcFiUMobgIqrrmwuNxfrkbVE2b6Bga74
+ FsJX63prvrJ41kuHK/16RQBM7fcCAwEAAaOCAWAwggFcMB8GA1UdIwQYMBaAFMOc
+ 8/zTRgg0u85Gf6B8W/PiCMtZMFcGCCsGAQUFBwEBBEswSTAfBggrBgEFBQcwAYYT
+ aHR0cDovL2d2LnN5bWNkLmNvbTAmBggrBgEFBQcwAoYaaHR0cDovL2d2LnN5bWNi
+ LmNvbS9ndi5jcnQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMB
+ BggrBgEFBQcDAjAvBgNVHREEKDAmghN3d3cuY3J5cHRvZ3JhcGh5Lmlvgg9jcnlw
+ dG9ncmFwaHkuaW8wKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL2d2LnN5bWNiLmNv
+ bS9ndi5jcmwwDAYDVR0TAQH/BAIwADBFBgNVHSAEPjA8MDoGCmCGSAGG+EUBBzYw
+ LDAqBggrBgEFBQcCARYeaHR0cHM6Ly93d3cucmFwaWRzc2wuY29tL2xlZ2FsMA0G
+ CSqGSIb3DQEBCwUAA4IBAQAzIYO2jx7h17FBT74tJ2zbV9OKqGb7QF8y3wUtP4xc
+ dH80vprI/Cfji8s86kr77aAvAqjDjaVjHn7UzebhSUivvRPmfzRgyWBacomnXTSt
+ Xlt2dp2nDQuwGyK2vB7dMfKnQAkxwq1sYUXznB8i0IhhCAoXp01QGPKq51YoIlnF
+ 7DRMk6iEaL1SJbkIrLsCQyZFDf0xtfW9DqXugMMLoxeCsBhZJQzNyS2ryirrv9LH
+ aK3+6IZjrcyy9bkpz/gzJucyhU+75c4My/mnRCrtItRbCQuiI5pd5poDowm+HH9i
+ GVI9+0lAFwxOUnOnwsoI40iOoxjLMGB+CgFLKCGUcWxP
+ -----END CERTIFICATE-----
+ """.strip()
+
+ pem_issuer_public_key = b"""
+ -----BEGIN RSA PUBLIC KEY-----
+ MIICCgKCAgEAyYcqyuT6oQxpvg/VSn2Zc68wZ823D0VAJ2woramFx+2KPWB7B7Ot
+ tVSNRfm0OxJOU3TFAoep54Z2wgOoz0zRmeW6/7gvIuBKp2TW0qZAt3l9sgpE29iw
+ CsoZQlMrLKiDPzCC6Fptk+YPSST9sqwhWDKK1QvOg68DKRxTpEek1hBpC0XRsnuX
+ fvJJQqP39vxzpA0PsicI/wrvWX3vO8z+j9+botPerbeamoeHCsc0xgTLyIygWysB
+ rNskxlzC2U4Kw6mQhGghlLReo1rFsO2/hLTnvLs+Y1lQhnFeOKCx1WVXhzBIyO9B
+ dVVH5Cinb5wBNKvxbevRf4icdWcwtknmgKf69xj7yvFjt/vft74BB1Y5ltLYFmEb
+ 0JBxm5MAJfW4YnMQr0AxdjOhjHq4MN7X4ZzwEpJaYJdRmvMsMGN88cyjYPxsaOG+
+ dZ/E9MmTjh0gnTjyD4gmsvR/gtTR/XFJ2wkbnnL1RyxNi6j2UW8C7tpNv0TIuArx
+ 3SHGPZN0WsaKTxZPb0L/ob1WBT0mhiq1GzB431cXgbxyh8EdKk+xSptA3V+ca2V2
+ NuXlJIJaOoPMj/qjDW4I/peKGnk9tLknJ0hpRzz11j77pJsV0dGoGKVHIR2oZqT5
+ 0ZJJb5DXNbiTnspKLNmBt0YlNiXtlCIPxVUkhL141FuCLc8h6FjD6E0CAwEAAQ==
+ -----END RSA PUBLIC KEY-----
+ """.strip()
+
+ pem_data_to_check = b"""
+ -----BEGIN CERTIFICATE-----
+ MIIErjCCApagAwIBAgIUUrUZsZrrBmRD2hvRuspp+lPsZXcwDQYJKoZIhvcNAQEN
+ BQAwETEPMA0GA1UEAwwGSXNzdWVyMB4XDTE4MTAwODEzNDg1NFoXDTE4MTAxODEz
+ NDg1NFowETEPMA0GA1UEAwwGSXNzdWVyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
+ MIICCgKCAgEAyYcqyuT6oQxpvg/VSn2Zc68wZ823D0VAJ2woramFx+2KPWB7B7Ot
+ tVSNRfm0OxJOU3TFAoep54Z2wgOoz0zRmeW6/7gvIuBKp2TW0qZAt3l9sgpE29iw
+ CsoZQlMrLKiDPzCC6Fptk+YPSST9sqwhWDKK1QvOg68DKRxTpEek1hBpC0XRsnuX
+ fvJJQqP39vxzpA0PsicI/wrvWX3vO8z+j9+botPerbeamoeHCsc0xgTLyIygWysB
+ rNskxlzC2U4Kw6mQhGghlLReo1rFsO2/hLTnvLs+Y1lQhnFeOKCx1WVXhzBIyO9B
+ dVVH5Cinb5wBNKvxbevRf4icdWcwtknmgKf69xj7yvFjt/vft74BB1Y5ltLYFmEb
+ 0JBxm5MAJfW4YnMQr0AxdjOhjHq4MN7X4ZzwEpJaYJdRmvMsMGN88cyjYPxsaOG+
+ dZ/E9MmTjh0gnTjyD4gmsvR/gtTR/XFJ2wkbnnL1RyxNi6j2UW8C7tpNv0TIuArx
+ 3SHGPZN0WsaKTxZPb0L/ob1WBT0mhiq1GzB431cXgbxyh8EdKk+xSptA3V+ca2V2
+ NuXlJIJaOoPMj/qjDW4I/peKGnk9tLknJ0hpRzz11j77pJsV0dGoGKVHIR2oZqT5
+ 0ZJJb5DXNbiTnspKLNmBt0YlNiXtlCIPxVUkhL141FuCLc8h6FjD6E0CAwEAATAN
+ BgkqhkiG9w0BAQ0FAAOCAgEAVFzNKhEpkH8V8l0NEBAZHNi1e+lcg35fZZ9plqcw
+ Pvk+6M7LW0KD0QWYQWm/dJme4DFsM7lh5u4/m+H4yS7/RP9pads9YwBudchvGR1c
+ S4CCrRAmO8/A0vpQJcEwdS7fdYShBsqMrZ2TvzceVn2dvQbxB6pLkK7KIbDPVJA2
+ HXFFXe2npHmdc80iTz2ShbdVSvyPvk6vc6NFFCg6lSQFuif3vV0+aYqi6DXv4h92
+ 9qAdES8ZLDfDulxyajyPbtF35f2Of99CumP5UzG4RQbvtI8gShuK1YFYe2sWJFE0
+ MgSsqGCbl5mcrWxm9YxysRKMZ+Hc4tnkvfmG6GsKtp8u/5pG11XgxXaQl4fZ7JNa
+ QFuD5gEXkEC1mCnhWlnguJgjQlpKadMOORmVTqG9dNQ6GEsha+XWpinm5L9fEZuA
+ F88nNyubKLwEl68N7WWWKQlIl4q8Pe5FEp1pd9rLjOW4gzgYBccIfBK3oMC7uFJg
+ a/9GeOKPiq90UMrCI+CAsIbzuPOaAp3g69JonuDwcs4cu8ui1udxs9q7ox3qSWGZ
+ G1U/hmwvZH9kfIv5BKIzNLy4oxXPDJ7MZIBsxVxaNv8KUQ/JLtpVJa3oYqEx18+V
+ JNr8Pr3y61X8pLmJnaCu+ixshiy2gjxXxDFBVEEt1G9JHrSs3R+yvcHxCrM3+ian
+ Nh4=
+ -----END CERTIFICATE-----
+ """.strip()
+
+Loading Certificates
+~~~~~~~~~~~~~~~~~~~~
+
+.. function:: load_pem_x509_certificate(data, backend)
+
+ .. versionadded:: 0.7
+
+ Deserialize a certificate from PEM encoded data. PEM certificates are
+ base64 decoded and have delimiters that look like
+ ``-----BEGIN CERTIFICATE-----``.
+
+ :param bytes data: The PEM encoded certificate data.
+
+ :param backend: A backend supporting the
+ :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
+ interface.
+
+ :returns: An instance of :class:`~cryptography.x509.Certificate`.
+
+ .. doctest::
+
+ >>> from cryptography import x509
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> cert = x509.load_pem_x509_certificate(pem_data, default_backend())
+ >>> cert.serial_number
+ 2
+
+.. function:: load_der_x509_certificate(data, backend)
+
+ .. versionadded:: 0.7
+
+ Deserialize a certificate from DER encoded data. DER is a binary format
+ and is commonly found in files with the ``.cer`` extension (although file
+ extensions are not a guarantee of encoding type).
+
+ :param bytes data: The DER encoded certificate data.
+
+ :param backend: A backend supporting the
+ :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
+ interface.
+
+ :returns: An instance of :class:`~cryptography.x509.Certificate`.
+
+Loading Certificate Revocation Lists
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. function:: load_pem_x509_crl(data, backend)
+
+ .. versionadded:: 1.1
+
+ Deserialize a certificate revocation list (CRL) from PEM encoded data. PEM
+ requests are base64 decoded and have delimiters that look like
+ ``-----BEGIN X509 CRL-----``.
+
+ :param bytes data: The PEM encoded request data.
+
+ :param backend: A backend supporting the
+ :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
+ interface.
+
+ :returns: An instance of
+ :class:`~cryptography.x509.CertificateRevocationList`.
+
+ .. doctest::
+
+ >>> from cryptography import x509
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> crl = x509.load_pem_x509_crl(pem_crl_data, default_backend())
+ >>> isinstance(crl.signature_hash_algorithm, hashes.SHA256)
+ True
+
+.. function:: load_der_x509_crl(data, backend)
+
+ .. versionadded:: 1.1
+
+ Deserialize a certificate revocation list (CRL) from DER encoded data. DER
+ is a binary format.
+
+ :param bytes data: The DER encoded request data.
+
+ :param backend: A backend supporting the
+ :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
+ interface.
+
+ :returns: An instance of
+ :class:`~cryptography.x509.CertificateRevocationList`.
+
+Loading Certificate Signing Requests
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. function:: load_pem_x509_csr(data, backend)
+
+ .. versionadded:: 0.9
+
+ Deserialize a certificate signing request (CSR) from PEM encoded data. PEM
+ requests are base64 decoded and have delimiters that look like
+ ``-----BEGIN CERTIFICATE REQUEST-----``. This format is also known as
+ PKCS#10.
+
+ :param bytes data: The PEM encoded request data.
+
+ :param backend: A backend supporting the
+ :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
+ interface.
+
+ :returns: An instance of
+ :class:`~cryptography.x509.CertificateSigningRequest`.
+
+ .. doctest::
+
+ >>> from cryptography import x509
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> csr = x509.load_pem_x509_csr(pem_req_data, default_backend())
+ >>> isinstance(csr.signature_hash_algorithm, hashes.SHA1)
+ True
+
+.. function:: load_der_x509_csr(data, backend)
+
+ .. versionadded:: 0.9
+
+ Deserialize a certificate signing request (CSR) from DER encoded data. DER
+ is a binary format and is not commonly used with CSRs.
+
+ :param bytes data: The DER encoded request data.
+
+ :param backend: A backend supporting the
+ :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
+ interface.
+
+ :returns: An instance of
+ :class:`~cryptography.x509.CertificateSigningRequest`.
+
+X.509 Certificate Object
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. class:: Certificate
+
+ .. versionadded:: 0.7
+
+ .. attribute:: version
+
+ :type: :class:`~cryptography.x509.Version`
+
+ The certificate version as an enumeration. Version 3 certificates are
+ the latest version and also the only type you should see in practice.
+
+ :raises cryptography.x509.InvalidVersion: If the version in the
+ certificate is not a known
+ :class:`X.509 version <cryptography.x509.Version>`.
+
+ .. doctest::
+
+ >>> cert.version
+ <Version.v3: 2>
+
+ .. method:: fingerprint(algorithm)
+
+ :param algorithm: The
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+ that will be used to generate the fingerprint.
+
+ :return bytes: The fingerprint using the supplied hash algorithm, as
+ bytes.
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> cert.fingerprint(hashes.SHA256())
+ b'\x86\xd2\x187Gc\xfc\xe7}[+E9\x8d\xb4\x8f\x10\xe5S\xda\x18u\xbe}a\x03\x08[\xac\xa04?'
+
+ .. attribute:: serial_number
+
+ :type: int
+
+ The serial as a Python integer.
+
+ .. doctest::
+
+ >>> cert.serial_number
+ 2
+
+ .. method:: public_key()
+
+ The public key associated with the certificate.
+
+ :returns: One of
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PublicKey`
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.primitives.asymmetric import rsa
+ >>> public_key = cert.public_key()
+ >>> isinstance(public_key, rsa.RSAPublicKey)
+ True
+
+ .. attribute:: not_valid_before
+
+ :type: :class:`datetime.datetime`
+
+ A naïve datetime representing the beginning of the validity period for
+ the certificate in UTC. This value is inclusive.
+
+ .. doctest::
+
+ >>> cert.not_valid_before
+ datetime.datetime(2010, 1, 1, 8, 30)
+
+ .. attribute:: not_valid_after
+
+ :type: :class:`datetime.datetime`
+
+ A naïve datetime representing the end of the validity period for the
+ certificate in UTC. This value is inclusive.
+
+ .. doctest::
+
+ >>> cert.not_valid_after
+ datetime.datetime(2030, 12, 31, 8, 30)
+
+ .. attribute:: issuer
+
+ .. versionadded:: 0.8
+
+ :type: :class:`Name`
+
+ The :class:`Name` of the issuer.
+
+ .. attribute:: subject
+
+ .. versionadded:: 0.8
+
+ :type: :class:`Name`
+
+ The :class:`Name` of the subject.
+
+ .. attribute:: signature_hash_algorithm
+
+ :type: :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+
+ Returns the
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` which
+ was used in signing this certificate. Can be ``None`` if signature
+ did not use separate hash
+ (:attr:`~cryptography.x509.oid.SignatureAlgorithmOID.ED25519`,
+ :attr:`~cryptography.x509.oid.SignatureAlgorithmOID.ED448`).
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> isinstance(cert.signature_hash_algorithm, hashes.SHA256)
+ True
+
+ .. attribute:: signature_algorithm_oid
+
+ .. versionadded:: 1.6
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns the :class:`ObjectIdentifier` of the signature algorithm used
+ to sign the certificate. This will be one of the OIDs from
+ :class:`~cryptography.x509.oid.SignatureAlgorithmOID`.
+
+
+ .. doctest::
+
+ >>> cert.signature_algorithm_oid
+ <ObjectIdentifier(oid=1.2.840.113549.1.1.11, name=sha256WithRSAEncryption)>
+
+ .. attribute:: extensions
+
+ :type: :class:`Extensions`
+
+ The extensions encoded in the certificate.
+
+ :raises cryptography.x509.DuplicateExtension: If more than one
+ extension of the same type is found within the certificate.
+
+ :raises cryptography.x509.UnsupportedGeneralNameType: If an extension
+ contains a general name that is not supported.
+
+ :raises UnicodeError: If an extension contains IDNA encoding that is
+ invalid or not compliant with IDNA 2008.
+
+ .. doctest::
+
+ >>> for ext in cert.extensions:
+ ... print(ext)
+ <Extension(oid=<ObjectIdentifier(oid=2.5.29.35, name=authorityKeyIdentifier)>, critical=False, value=<AuthorityKeyIdentifier(key_identifier=b'\xe4}_\xd1\\\x95\x86\x08,\x05\xae\xbeu\xb6e\xa7\xd9]\xa8f', authority_cert_issuer=None, authority_cert_serial_number=None)>)>
+ <Extension(oid=<ObjectIdentifier(oid=2.5.29.14, name=subjectKeyIdentifier)>, critical=False, value=<SubjectKeyIdentifier(digest=b'X\x01\x84$\x1b\xbc+R\x94J=\xa5\x10r\x14Q\xf5\xaf:\xc9')>)>
+ <Extension(oid=<ObjectIdentifier(oid=2.5.29.15, name=keyUsage)>, critical=True, value=<KeyUsage(digital_signature=False, content_commitment=False, key_encipherment=False, data_encipherment=False, key_agreement=False, key_cert_sign=True, crl_sign=True, encipher_only=None, decipher_only=None)>)>
+ <Extension(oid=<ObjectIdentifier(oid=2.5.29.32, name=certificatePolicies)>, critical=False, value=<CertificatePolicies([<PolicyInformation(policy_identifier=<ObjectIdentifier(oid=2.16.840.1.101.3.2.1.48.1, name=Unknown OID)>, policy_qualifiers=None)>])>)>
+ <Extension(oid=<ObjectIdentifier(oid=2.5.29.19, name=basicConstraints)>, critical=True, value=<BasicConstraints(ca=True, path_length=None)>)>
+
+ .. attribute:: signature
+
+ .. versionadded:: 1.2
+
+ :type: bytes
+
+ The bytes of the certificate's signature.
+
+ .. attribute:: tbs_certificate_bytes
+
+ .. versionadded:: 1.2
+
+ :type: bytes
+
+ The DER encoded bytes payload (as defined by :rfc:`5280`) that is hashed
+ and then signed by the private key of the certificate's issuer. This
+ data may be used to validate a signature, but use extreme caution as
+ certificate validation is a complex problem that involves much more
+ than just signature checks.
+
+ To validate the signature on a certificate you can do the following.
+ Note: This only verifies that the certificate was signed with the
+ private key associated with the public key provided and does not
+ perform any of the other checks needed for secure certificate
+ validation. Additionally, this example will only work for RSA public
+ keys with ``PKCS1v15`` signatures, and so it can't be used for general
+ purpose signature verification.
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.primitives.serialization import load_pem_public_key
+ >>> from cryptography.hazmat.primitives.asymmetric import padding
+ >>> issuer_public_key = load_pem_public_key(pem_issuer_public_key, default_backend())
+ >>> cert_to_check = x509.load_pem_x509_certificate(pem_data_to_check, default_backend())
+ >>> issuer_public_key.verify(
+ ... cert_to_check.signature,
+ ... cert_to_check.tbs_certificate_bytes,
+ ... # Depends on the algorithm used to create the certificate
+ ... padding.PKCS1v15(),
+ ... cert_to_check.signature_hash_algorithm,
+ ... )
+
+ An
+ :class:`~cryptography.exceptions.InvalidSignature`
+ exception will be raised if the signature fails to verify.
+
+ .. method:: public_bytes(encoding)
+
+ .. versionadded:: 1.0
+
+ :param encoding: The
+ :class:`~cryptography.hazmat.primitives.serialization.Encoding`
+ that will be used to serialize the certificate.
+
+ :return bytes: The data that can be written to a file or sent
+ over the network to be verified by clients.
+
+X.509 CRL (Certificate Revocation List) Object
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. class:: CertificateRevocationList
+
+ .. versionadded:: 1.0
+
+ A CertificateRevocationList is an object representing a list of revoked
+ certificates. The object is iterable and will yield the RevokedCertificate
+ objects stored in this CRL.
+
+ .. doctest::
+
+ >>> len(crl)
+ 1
+ >>> revoked_certificate = crl[0]
+ >>> type(revoked_certificate)
+ <class 'cryptography.hazmat.backends.openssl.x509._RevokedCertificate'>
+ >>> for r in crl:
+ ... print(r.serial_number)
+ 0
+
+ .. method:: fingerprint(algorithm)
+
+ :param algorithm: The
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+ that will be used to generate the fingerprint.
+
+ :return bytes: The fingerprint using the supplied hash algorithm, as
+ bytes.
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> crl.fingerprint(hashes.SHA256())
+ b'e\xcf.\xc4:\x83?1\xdc\xf3\xfc\x95\xd7\xb3\x87\xb3\x8e\xf8\xb93!\x87\x07\x9d\x1b\xb4!\xb9\xe4W\xf4\x1f'
+
+ .. method:: get_revoked_certificate_by_serial_number(serial_number)
+
+ .. versionadded:: 2.3
+
+ :param serial_number: The serial as a Python integer.
+ :returns: :class:`~cryptography.x509.RevokedCertificate` if the
+ ``serial_number`` is present in the CRL or ``None`` if it
+ is not.
+
+ .. attribute:: signature_hash_algorithm
+
+ :type: :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+
+ Returns the
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` which
+ was used in signing this CRL. Can be ``None`` if signature
+ did not use separate hash
+ (:attr:`~cryptography.x509.oid.SignatureAlgorithmOID.ED25519`,
+ :attr:`~cryptography.x509.oid.SignatureAlgorithmOID.ED448`).
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> isinstance(crl.signature_hash_algorithm, hashes.SHA256)
+ True
+
+ .. attribute:: signature_algorithm_oid
+
+ .. versionadded:: 1.6
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns the :class:`ObjectIdentifier` of the signature algorithm used
+ to sign the CRL. This will be one of the OIDs from
+ :class:`~cryptography.x509.oid.SignatureAlgorithmOID`.
+
+ .. doctest::
+
+ >>> crl.signature_algorithm_oid
+ <ObjectIdentifier(oid=1.2.840.113549.1.1.11, name=sha256WithRSAEncryption)>
+
+ .. attribute:: issuer
+
+ :type: :class:`Name`
+
+ The :class:`Name` of the issuer.
+
+ .. doctest::
+
+ >>> crl.issuer
+ <Name(C=US,CN=cryptography.io)>
+
+ .. attribute:: next_update
+
+ :type: :class:`datetime.datetime`
+
+ A naïve datetime representing when the next update to this CRL is
+ expected.
+
+ .. doctest::
+
+ >>> crl.next_update
+ datetime.datetime(2016, 1, 1, 0, 0)
+
+ .. attribute:: last_update
+
+ :type: :class:`datetime.datetime`
+
+ A naïve datetime representing when this CRL was last updated.
+
+ .. doctest::
+
+ >>> crl.last_update
+ datetime.datetime(2015, 1, 1, 0, 0)
+
+ .. attribute:: extensions
+
+ :type: :class:`Extensions`
+
+ The extensions encoded in the CRL.
+
+ .. attribute:: signature
+
+ .. versionadded:: 1.2
+
+ :type: bytes
+
+ The bytes of the CRL's signature.
+
+ .. attribute:: tbs_certlist_bytes
+
+ .. versionadded:: 1.2
+
+ :type: bytes
+
+ The DER encoded bytes payload (as defined by :rfc:`5280`) that is hashed
+ and then signed by the private key of the CRL's issuer. This data may be
+ used to validate a signature, but use extreme caution as CRL validation
+ is a complex problem that involves much more than just signature checks.
+
+ .. method:: public_bytes(encoding)
+
+ .. versionadded:: 1.2
+
+ :param encoding: The
+ :class:`~cryptography.hazmat.primitives.serialization.Encoding`
+ that will be used to serialize the certificate revocation list.
+
+ :return bytes: The data that can be written to a file or sent
+ over the network and used as part of a certificate verification
+ process.
+
+ .. method:: is_signature_valid(public_key)
+
+ .. versionadded:: 2.1
+
+ .. warning::
+
+ Checking the validity of the signature on the CRL is insufficient
+ to know if the CRL should be trusted. More details are available
+ in :rfc:`5280`.
+
+ Returns True if the CRL signature is correct for given public key,
+ False otherwise.
+
+X.509 Certificate Builder
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. class:: CertificateBuilder
+
+ .. versionadded:: 1.0
+
+ .. doctest::
+
+ >>> from cryptography import x509
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> from cryptography.hazmat.primitives.asymmetric import rsa
+ >>> from cryptography.x509.oid import NameOID
+ >>> import datetime
+ >>> one_day = datetime.timedelta(1, 0, 0)
+ >>> private_key = rsa.generate_private_key(
+ ... public_exponent=65537,
+ ... key_size=2048,
+ ... backend=default_backend()
+ ... )
+ >>> public_key = private_key.public_key()
+ >>> builder = x509.CertificateBuilder()
+ >>> builder = builder.subject_name(x509.Name([
+ ... x509.NameAttribute(NameOID.COMMON_NAME, u'cryptography.io'),
+ ... ]))
+ >>> builder = builder.issuer_name(x509.Name([
+ ... x509.NameAttribute(NameOID.COMMON_NAME, u'cryptography.io'),
+ ... ]))
+ >>> builder = builder.not_valid_before(datetime.datetime.today() - one_day)
+ >>> builder = builder.not_valid_after(datetime.datetime.today() + (one_day * 30))
+ >>> builder = builder.serial_number(x509.random_serial_number())
+ >>> builder = builder.public_key(public_key)
+ >>> builder = builder.add_extension(
+ ... x509.SubjectAlternativeName(
+ ... [x509.DNSName(u'cryptography.io')]
+ ... ),
+ ... critical=False
+ ... )
+ >>> builder = builder.add_extension(
+ ... x509.BasicConstraints(ca=False, path_length=None), critical=True,
+ ... )
+ >>> certificate = builder.sign(
+ ... private_key=private_key, algorithm=hashes.SHA256(),
+ ... backend=default_backend()
+ ... )
+ >>> isinstance(certificate, x509.Certificate)
+ True
+
+ .. method:: issuer_name(name)
+
+ Sets the issuer's distinguished name.
+
+ :param name: The :class:`~cryptography.x509.Name` that describes the
+ issuer (CA).
+
+ .. method:: subject_name(name)
+
+ Sets the subject's distinguished name.
+
+ :param name: The :class:`~cryptography.x509.Name` that describes the
+ subject.
+
+ .. method:: public_key(public_key)
+
+ Sets the subject's public key.
+
+ :param public_key: The subject's public key. This can be one of
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PublicKey`.
+
+ .. method:: serial_number(serial_number)
+
+ Sets the certificate's serial number (an integer). The CA's policy
+ determines how it attributes serial numbers to certificates. This
+ number must uniquely identify the certificate given the issuer.
+ `CABForum Guidelines`_ require entropy in the serial number
+ to provide protection against hash collision attacks. For more
+ information on secure random number generation, see
+ :doc:`/random-numbers`.
+
+ :param serial_number: Integer number that will be used by the CA to
+ identify this certificate (most notably during certificate
+ revocation checking). Users should consider using
+ :func:`~cryptography.x509.random_serial_number` when possible.
+
+ .. method:: not_valid_before(time)
+
+ Sets the certificate's activation time. This is the time from which
+ clients can start trusting the certificate. It may be different from
+ the time at which the certificate was created.
+
+ :param time: The :class:`datetime.datetime` object (in UTC) that marks the
+ activation time for the certificate. The certificate may not be
+ trusted clients if it is used before this time.
+
+ .. method:: not_valid_after(time)
+
+ Sets the certificate's expiration time. This is the time from which
+ clients should no longer trust the certificate. The CA's policy will
+ determine how long the certificate should remain in use.
+
+ :param time: The :class:`datetime.datetime` object (in UTC) that marks the
+ expiration time for the certificate. The certificate may not be
+ trusted clients if it is used after this time.
+
+ .. method:: add_extension(extension, critical)
+
+ Adds an X.509 extension to the certificate.
+
+ :param extension: An extension conforming to the
+ :class:`~cryptography.x509.ExtensionType` interface.
+
+ :param critical: Set to ``True`` if the extension must be understood and
+ handled by whoever reads the certificate.
+
+ .. method:: sign(private_key, algorithm, backend)
+
+ Sign the certificate using the CA's private key.
+
+ :param private_key: The
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey`
+ that will be used to sign the certificate.
+
+ :param algorithm: The
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` that
+ will be used to generate the signature. This must be ``None`` if
+ the ``private_key`` is an
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey`
+ or an
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey`
+ and an instance of a
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+ otherwise.
+
+ :param backend: Backend that will be used to build the certificate.
+ Must support the
+ :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
+ interface.
+
+ :returns: :class:`~cryptography.x509.Certificate`
+
+
+X.509 CSR (Certificate Signing Request) Object
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. class:: CertificateSigningRequest
+
+ .. versionadded:: 0.9
+
+ .. method:: public_key()
+
+ The public key associated with the request.
+
+ :returns: One of
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PublicKey`.
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.primitives.asymmetric import rsa
+ >>> public_key = csr.public_key()
+ >>> isinstance(public_key, rsa.RSAPublicKey)
+ True
+
+ .. attribute:: subject
+
+ :type: :class:`Name`
+
+ The :class:`Name` of the subject.
+
+ .. attribute:: signature_hash_algorithm
+
+ :type: :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+
+ Returns the
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` which
+ was used in signing this request. Can be ``None`` if signature
+ did not use separate hash
+ (:attr:`~cryptography.x509.oid.SignatureAlgorithmOID.ED25519`,
+ :attr:`~cryptography.x509.oid.SignatureAlgorithmOID.ED448`).
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> isinstance(csr.signature_hash_algorithm, hashes.SHA1)
+ True
+
+ .. attribute:: signature_algorithm_oid
+
+ .. versionadded:: 1.6
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns the :class:`ObjectIdentifier` of the signature algorithm used
+ to sign the request. This will be one of the OIDs from
+ :class:`~cryptography.x509.oid.SignatureAlgorithmOID`.
+
+ .. doctest::
+
+ >>> csr.signature_algorithm_oid
+ <ObjectIdentifier(oid=1.2.840.113549.1.1.5, name=sha1WithRSAEncryption)>
+
+ .. attribute:: extensions
+
+ :type: :class:`Extensions`
+
+ The extensions encoded in the certificate signing request.
+
+ :raises cryptography.x509.DuplicateExtension: If more than one
+ extension of the same type is found within the certificate signing request.
+
+ :raises cryptography.x509.UnsupportedGeneralNameType: If an extension
+ contains a general name that is not supported.
+
+ :raises UnicodeError: If an extension contains IDNA encoding that is
+ invalid or not compliant with IDNA 2008.
+
+
+ .. method:: public_bytes(encoding)
+
+ .. versionadded:: 1.0
+
+ :param encoding: The
+ :class:`~cryptography.hazmat.primitives.serialization.Encoding`
+ that will be used to serialize the certificate request.
+
+ :return bytes: The data that can be written to a file or sent
+ over the network to be signed by the certificate
+ authority.
+
+ .. attribute:: signature
+
+ .. versionadded:: 1.2
+
+ :type: bytes
+
+ The bytes of the certificate signing request's signature.
+
+ .. attribute:: tbs_certrequest_bytes
+
+ .. versionadded:: 1.2
+
+ :type: bytes
+
+ The DER encoded bytes payload (as defined by :rfc:`2986`) that is
+ hashed and then signed by the private key (corresponding to the public
+ 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
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. class:: CertificateRevocationListBuilder
+
+ .. versionadded:: 1.2
+
+ .. doctest::
+
+ >>> from cryptography import x509
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> from cryptography.hazmat.primitives.asymmetric import rsa
+ >>> from cryptography.x509.oid import NameOID
+ >>> import datetime
+ >>> one_day = datetime.timedelta(1, 0, 0)
+ >>> private_key = rsa.generate_private_key(
+ ... public_exponent=65537,
+ ... key_size=2048,
+ ... backend=default_backend()
+ ... )
+ >>> builder = x509.CertificateRevocationListBuilder()
+ >>> builder = builder.issuer_name(x509.Name([
+ ... x509.NameAttribute(NameOID.COMMON_NAME, u'cryptography.io CA'),
+ ... ]))
+ >>> builder = builder.last_update(datetime.datetime.today())
+ >>> builder = builder.next_update(datetime.datetime.today() + one_day)
+ >>> revoked_cert = x509.RevokedCertificateBuilder().serial_number(
+ ... 333
+ ... ).revocation_date(
+ ... datetime.datetime.today()
+ ... ).build(default_backend())
+ >>> builder = builder.add_revoked_certificate(revoked_cert)
+ >>> crl = builder.sign(
+ ... private_key=private_key, algorithm=hashes.SHA256(),
+ ... backend=default_backend()
+ ... )
+ >>> len(crl)
+ 1
+
+ .. method:: issuer_name(name)
+
+ Sets the issuer's distinguished name.
+
+ :param name: The :class:`~cryptography.x509.Name` that describes the
+ issuer (CA).
+
+ .. method:: last_update(time)
+
+ Sets this CRL's activation time. This is the time from which
+ clients can start trusting this CRL. It may be different from
+ the time at which this CRL was created. This is also known as the
+ ``thisUpdate`` time.
+
+ :param time: The :class:`datetime.datetime` object (in UTC) that marks
+ the activation time for this CRL. The CRL may not be trusted if it
+ is used before this time.
+
+ .. method:: next_update(time)
+
+ Sets this CRL's next update time. This is the time by which
+ a new CRL will be issued. The CA is allowed to issue a new CRL before
+ this date, however clients are not required to check for it.
+
+ :param time: The :class:`datetime.datetime` object (in UTC) that marks
+ the next update time for this CRL.
+
+ .. method:: add_extension(extension, critical)
+
+ Adds an X.509 extension to this CRL.
+
+ :param extension: An extension with the
+ :class:`~cryptography.x509.ExtensionType` interface.
+
+ :param critical: Set to ``True`` if the extension must be understood and
+ handled by whoever reads the CRL.
+
+ .. method:: add_revoked_certificate(revoked_certificate)
+
+ Adds a revoked certificate to this CRL.
+
+ :param revoked_certificate: An instance of
+ :class:`~cryptography.x509.RevokedCertificate`. These can be
+ obtained from an existing CRL or created with
+ :class:`~cryptography.x509.RevokedCertificateBuilder`.
+
+ .. method:: sign(private_key, algorithm, backend)
+
+ Sign this CRL using the CA's private key.
+
+ :param private_key: The
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey`
+ that will be used to sign the certificate.
+
+ :param algorithm: The
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` that
+ will be used to generate the signature.
+ This must be ``None`` if the ``private_key`` is an
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey`
+ or an
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey`
+ and an instance of a
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+ otherwise.
+
+ :param backend: Backend that will be used to build the CRL.
+ Must support the
+ :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
+ interface.
+
+ :returns: :class:`~cryptography.x509.CertificateRevocationList`
+
+X.509 Revoked Certificate Object
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. class:: RevokedCertificate
+
+ .. versionadded:: 1.0
+
+ .. attribute:: serial_number
+
+ :type: :class:`int`
+
+ An integer representing the serial number of the revoked certificate.
+
+ .. doctest::
+
+ >>> revoked_certificate.serial_number
+ 0
+
+ .. attribute:: revocation_date
+
+ :type: :class:`datetime.datetime`
+
+ A naïve datetime representing the date this certificates was revoked.
+
+ .. doctest::
+
+ >>> revoked_certificate.revocation_date
+ datetime.datetime(2015, 1, 1, 0, 0)
+
+ .. attribute:: extensions
+
+ :type: :class:`Extensions`
+
+ The extensions encoded in the revoked certificate.
+
+ .. doctest::
+
+ >>> for ext in revoked_certificate.extensions:
+ ... print(ext)
+ <Extension(oid=<ObjectIdentifier(oid=2.5.29.24, name=invalidityDate)>, critical=False, value=<InvalidityDate(invalidity_date=2015-01-01 00:00:00)>)>
+ <Extension(oid=<ObjectIdentifier(oid=2.5.29.21, name=cRLReason)>, critical=False, value=<CRLReason(reason=ReasonFlags.key_compromise)>)>
+
+X.509 Revoked Certificate Builder
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. class:: RevokedCertificateBuilder
+
+ This class is used to create :class:`~cryptography.x509.RevokedCertificate`
+ objects that can be used with the
+ :class:`~cryptography.x509.CertificateRevocationListBuilder`.
+
+ .. versionadded:: 1.2
+
+ .. doctest::
+
+ >>> from cryptography import x509
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> import datetime
+ >>> builder = x509.RevokedCertificateBuilder()
+ >>> builder = builder.revocation_date(datetime.datetime.today())
+ >>> builder = builder.serial_number(3333)
+ >>> revoked_certificate = builder.build(default_backend())
+ >>> isinstance(revoked_certificate, x509.RevokedCertificate)
+ True
+
+ .. method:: serial_number(serial_number)
+
+ Sets the revoked certificate's serial number.
+
+ :param serial_number: Integer number that is used to identify the
+ revoked certificate.
+
+ .. method:: revocation_date(time)
+
+ Sets the certificate's revocation date.
+
+ :param time: The :class:`datetime.datetime` object (in UTC) that marks the
+ revocation time for the certificate.
+
+ .. method:: add_extension(extension, critical)
+
+ Adds an X.509 extension to this revoked certificate.
+
+ :param extension: An instance of one of the
+ :ref:`CRL entry extensions <crl_entry_extensions>`.
+
+ :param critical: Set to ``True`` if the extension must be understood and
+ handled.
+
+ .. method:: build(backend)
+
+ Create a revoked certificate object using the provided backend.
+
+ :param backend: Backend that will be used to build the revoked
+ certificate. Must support the
+ :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
+ interface.
+
+ :returns: :class:`~cryptography.x509.RevokedCertificate`
+
+X.509 CSR (Certificate Signing Request) Builder Object
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. class:: CertificateSigningRequestBuilder
+
+ .. versionadded:: 1.0
+
+ .. doctest::
+
+ >>> from cryptography import x509
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> from cryptography.hazmat.primitives.asymmetric import rsa
+ >>> from cryptography.x509.oid import NameOID
+ >>> private_key = rsa.generate_private_key(
+ ... public_exponent=65537,
+ ... key_size=2048,
+ ... backend=default_backend()
+ ... )
+ >>> builder = x509.CertificateSigningRequestBuilder()
+ >>> builder = builder.subject_name(x509.Name([
+ ... x509.NameAttribute(NameOID.COMMON_NAME, u'cryptography.io'),
+ ... ]))
+ >>> builder = builder.add_extension(
+ ... x509.BasicConstraints(ca=False, path_length=None), critical=True,
+ ... )
+ >>> request = builder.sign(
+ ... private_key, hashes.SHA256(), default_backend()
+ ... )
+ >>> isinstance(request, x509.CertificateSigningRequest)
+ True
+
+ .. method:: subject_name(name)
+
+ :param name: The :class:`~cryptography.x509.Name` of the certificate
+ subject.
+ :returns: A new
+ :class:`~cryptography.x509.CertificateSigningRequestBuilder`.
+
+ .. method:: add_extension(extension, critical)
+
+ :param extension: An extension conforming to the
+ :class:`~cryptography.x509.ExtensionType` interface.
+ :param critical: Set to `True` if the extension must be understood and
+ handled by whoever reads the certificate.
+ :returns: A new
+ :class:`~cryptography.x509.CertificateSigningRequestBuilder`.
+
+ .. method:: sign(private_key, algorithm, backend)
+
+ :param backend: Backend that will be used to sign the request.
+ Must support the
+ :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
+ interface.
+
+ :param private_key: The
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey`
+ that will be used to sign the request. When the request is
+ signed by a certificate authority, the private key's associated
+ public key will be stored in the resulting certificate.
+
+ :param algorithm: The
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+ that will be used to generate the request signature.
+ This must be ``None`` if the ``private_key`` is an
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey`
+ or an
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey`
+ and an instance of a
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+ otherwise.
+
+ :returns: A new
+ :class:`~cryptography.x509.CertificateSigningRequest`.
+
+
+.. class:: Name
+
+ .. versionadded:: 0.8
+
+ An X509 Name is an ordered list of attributes. The object is iterable to
+ get every attribute or you can use :meth:`Name.get_attributes_for_oid` to
+ obtain the specific type you want. Names are sometimes represented as a
+ slash or comma delimited string (e.g. ``/CN=mydomain.com/O=My Org/C=US`` or
+ ``CN=mydomain.com,O=My Org,C=US``).
+
+ Technically, a Name is a list of *sets* of attributes, called *Relative
+ Distinguished Names* or *RDNs*, although multi-valued RDNs are rarely
+ encountered. The iteration order of values within a multi-valued RDN is
+ preserved. If you need to handle multi-valued RDNs, the ``rdns`` property
+ gives access to an ordered list of :class:`RelativeDistinguishedName`
+ objects.
+
+ A Name can be initialized with an iterable of :class:`NameAttribute` (the
+ common case where each RDN has a single attribute) or an iterable of
+ :class:`RelativeDistinguishedName` objects (in the rare case of
+ multi-valued RDNs).
+
+ .. doctest::
+
+ >>> len(cert.subject)
+ 3
+ >>> for attribute in cert.subject:
+ ... print(attribute)
+ <NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.6, name=countryName)>, value='US')>
+ <NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.10, name=organizationName)>, value='Test Certificates 2011')>
+ <NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commonName)>, value='Good CA')>
+
+ .. attribute:: rdns
+
+ .. versionadded:: 1.6
+
+ :type: list of :class:`RelativeDistinguishedName`
+
+ .. method:: get_attributes_for_oid(oid)
+
+ :param oid: An :class:`ObjectIdentifier` instance.
+
+ :returns: A list of :class:`NameAttribute` instances that match the
+ OID provided. If nothing matches an empty list will be returned.
+
+ .. doctest::
+
+ >>> cert.subject.get_attributes_for_oid(NameOID.COMMON_NAME)
+ [<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commonName)>, value='Good CA')>]
+
+ .. method:: public_bytes(backend)
+
+ .. versionadded:: 1.6
+
+ :param backend: A backend supporting the
+ :class:`~cryptography.hazmat.backends.interfaces.X509Backend`
+ interface.
+
+ :return bytes: The DER encoded name.
+
+ .. method:: rfc4514_string()
+
+ .. versionadded:: 2.5
+
+ :return str: Format the given name as a :rfc:`4514` Distinguished Name
+ string, for example ``CN=mydomain.com,O=My Org,C=US``.
+
+
+.. class:: Version
+
+ .. versionadded:: 0.7
+
+ An enumeration for X.509 versions.
+
+ .. attribute:: v1
+
+ For version 1 X.509 certificates.
+
+ .. attribute:: v3
+
+ For version 3 X.509 certificates.
+
+.. class:: NameAttribute
+
+ .. versionadded:: 0.8
+
+ An X.509 name consists of a list of :class:`RelativeDistinguishedName`
+ instances, which consist of a set of :class:`NameAttribute` instances.
+
+ .. attribute:: oid
+
+ :type: :class:`ObjectIdentifier`
+
+ The attribute OID.
+
+ .. attribute:: value
+
+ :type: :term:`text`
+
+ The value of the attribute.
+
+ .. method:: rfc4514_string()
+
+ .. versionadded:: 2.5
+
+ :return str: Format the given attribute as a :rfc:`4514` Distinguished
+ Name string.
+
+
+.. class:: RelativeDistinguishedName(attributes)
+
+ .. versionadded:: 1.6
+
+ A relative distinguished name is a non-empty set of name attributes. The
+ object is iterable to get every attribute, preserving the original order.
+ Passing duplicate attributes to the constructor raises ``ValueError``.
+
+ .. method:: get_attributes_for_oid(oid)
+
+ :param oid: An :class:`ObjectIdentifier` instance.
+
+ :returns: A list of :class:`NameAttribute` instances that match the OID
+ provided. The list should contain zero or one values.
+
+ .. method:: rfc4514_string()
+
+ .. versionadded:: 2.5
+
+ :return str: Format the given RDN set as a :rfc:`4514` Distinguished
+ Name string.
+
+
+.. class:: ObjectIdentifier
+
+ .. versionadded:: 0.8
+
+ Object identifiers (frequently seen abbreviated as OID) identify the type
+ of a value (see: :class:`NameAttribute`).
+
+ .. attribute:: dotted_string
+
+ :type: :class:`str`
+
+ The dotted string value of the OID (e.g. ``"2.5.4.3"``)
+
+
+.. _general_name_classes:
+
+General Name Classes
+~~~~~~~~~~~~~~~~~~~~
+
+.. class:: GeneralName
+
+ .. versionadded:: 0.9
+
+ This is the generic interface that all the following classes are registered
+ against.
+
+.. class:: RFC822Name(value)
+
+ .. versionadded:: 0.9
+
+ .. versionchanged:: 2.1
+
+ .. warning::
+
+ Starting with version 2.1 :term:`U-label` input is deprecated. If
+ passing an internationalized domain name (IDN) you should first IDNA
+ encode the value and then pass the result as a string. Accessing
+ ``value`` will return the :term:`A-label` encoded form even if you pass
+ a U-label. This breaks backwards compatibility, but only for
+ internationalized domain names.
+
+
+ This corresponds to an email address. For example, ``user@example.com``.
+
+ :param value: The email address. If the address contains an
+ internationalized domain name then it must be encoded to an
+ :term:`A-label` string before being passed.
+
+ .. attribute:: value
+
+ :type: :term:`text`
+
+.. class:: DNSName(value)
+
+ .. versionadded:: 0.9
+
+ .. versionchanged:: 2.1
+
+ .. warning::
+
+ Starting with version 2.1 :term:`U-label` input is deprecated. If
+ passing an internationalized domain name (IDN) you should first IDNA
+ encode the value and then pass the result as a string. Accessing
+ ``value`` will return the :term:`A-label` encoded form even if you pass
+ a U-label. This breaks backwards compatibility, but only for
+ internationalized domain names.
+
+ This corresponds to a domain name. For example, ``cryptography.io``.
+
+ :param value: The domain name. If it is an internationalized domain
+ name then it must be encoded to an :term:`A-label` string before being
+ passed.
+
+ :type: :term:`text`
+
+ .. attribute:: value
+
+ :type: :term:`text`
+
+.. class:: DirectoryName(value)
+
+ .. versionadded:: 0.9
+
+ This corresponds to a directory name.
+
+ .. attribute:: value
+
+ :type: :class:`Name`
+
+.. class:: UniformResourceIdentifier(value)
+
+ .. versionadded:: 0.9
+
+ .. versionchanged:: 2.1
+
+ .. warning::
+
+ Starting with version 2.1 :term:`U-label` input is deprecated. If
+ passing an internationalized domain name (IDN) you should first IDNA
+ encode the value and then pass the result as a string. Accessing
+ ``value`` will return the :term:`A-label` encoded form even if you pass
+ a U-label. This breaks backwards compatibility, but only for
+ internationalized domain names.
+
+ This corresponds to a uniform resource identifier. For example,
+ ``https://cryptography.io``.
+
+ :param value: The URI. If it contains an internationalized domain
+ name then it must be encoded to an :term:`A-label` string before
+ being passed.
+
+ .. attribute:: value
+
+ :type: :term:`text`
+
+.. class:: IPAddress(value)
+
+ .. versionadded:: 0.9
+
+ This corresponds to an IP address.
+
+ .. attribute:: value
+
+ :type: :class:`~ipaddress.IPv4Address`,
+ :class:`~ipaddress.IPv6Address`, :class:`~ipaddress.IPv4Network`,
+ or :class:`~ipaddress.IPv6Network`.
+
+.. class:: RegisteredID(value)
+
+ .. versionadded:: 0.9
+
+ This corresponds to a registered ID.
+
+ .. attribute:: value
+
+ :type: :class:`ObjectIdentifier`
+
+.. class:: OtherName(type_id, value)
+
+ .. versionadded:: 1.0
+
+ This corresponds to an ``otherName.`` An ``otherName`` has a type identifier and a value represented in binary DER format.
+
+ .. attribute:: type_id
+
+ :type: :class:`ObjectIdentifier`
+
+ .. attribute:: value
+
+ :type: bytes
+
+X.509 Extensions
+~~~~~~~~~~~~~~~~
+
+.. class:: Extensions
+
+ .. versionadded:: 0.9
+
+ An X.509 Extensions instance is an ordered list of extensions. The object
+ is iterable to get every extension.
+
+ .. method:: get_extension_for_oid(oid)
+
+ :param oid: An :class:`ObjectIdentifier` instance.
+
+ :returns: An instance of the extension class.
+
+ :raises cryptography.x509.ExtensionNotFound: If the certificate does
+ not have the extension requested.
+
+ .. doctest::
+
+ >>> from cryptography.x509.oid import ExtensionOID
+ >>> cert.extensions.get_extension_for_oid(ExtensionOID.BASIC_CONSTRAINTS)
+ <Extension(oid=<ObjectIdentifier(oid=2.5.29.19, name=basicConstraints)>, critical=True, value=<BasicConstraints(ca=True, path_length=None)>)>
+
+ .. method:: get_extension_for_class(extclass)
+
+ .. versionadded:: 1.1
+
+ :param extclass: An extension class.
+
+ :returns: An instance of the extension class.
+
+ :raises cryptography.x509.ExtensionNotFound: If the certificate does
+ not have the extension requested.
+
+ .. doctest::
+
+ >>> from cryptography import x509
+ >>> cert.extensions.get_extension_for_class(x509.BasicConstraints)
+ <Extension(oid=<ObjectIdentifier(oid=2.5.29.19, name=basicConstraints)>, critical=True, value=<BasicConstraints(ca=True, path_length=None)>)>
+
+.. class:: Extension
+
+ .. versionadded:: 0.9
+
+ .. attribute:: oid
+
+ :type: :class:`ObjectIdentifier`
+
+ One of the :class:`~cryptography.x509.oid.ExtensionOID` OIDs.
+
+ .. attribute:: critical
+
+ :type: bool
+
+ Determines whether a given extension is critical or not. :rfc:`5280`
+ requires that "A certificate-using system MUST reject the certificate
+ if it encounters a critical extension it does not recognize or a
+ critical extension that contains information that it cannot process".
+
+ .. attribute:: value
+
+ Returns an instance of the extension type corresponding to the OID.
+
+.. class:: ExtensionType
+
+ .. versionadded:: 1.0
+
+ This is the interface against which all the following extension types are
+ registered.
+
+.. class:: KeyUsage(digital_signature, content_commitment, key_encipherment, data_encipherment, key_agreement, key_cert_sign, crl_sign, encipher_only, decipher_only)
+
+ .. versionadded:: 0.9
+
+ The key usage extension defines the purpose of the key contained in the
+ certificate. The usage restriction might be employed when a key that could
+ be used for more than one operation is to be restricted.
+
+ .. attribute:: oid
+
+ .. versionadded:: 1.0
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns :attr:`~cryptography.x509.oid.ExtensionOID.KEY_USAGE`.
+
+ .. attribute:: digital_signature
+
+ :type: bool
+
+ This purpose is set to true when the subject public key is used for verifying
+ digital signatures, other than signatures on certificates
+ (``key_cert_sign``) and CRLs (``crl_sign``).
+
+ .. attribute:: content_commitment
+
+ :type: bool
+
+ This purpose is set to true when the subject public key is used for verifying
+ digital signatures, other than signatures on certificates
+ (``key_cert_sign``) and CRLs (``crl_sign``). It is used to provide a
+ non-repudiation service that protects against the signing entity
+ falsely denying some action. In the case of later conflict, a
+ reliable third party may determine the authenticity of the signed
+ data. This was called ``non_repudiation`` in older revisions of the
+ X.509 specification.
+
+ .. attribute:: key_encipherment
+
+ :type: bool
+
+ This purpose is set to true when the subject public key is used for
+ enciphering private or secret keys.
+
+ .. attribute:: data_encipherment
+
+ :type: bool
+
+ This purpose is set to true when the subject public key is used for
+ directly enciphering raw user data without the use of an intermediate
+ symmetric cipher.
+
+ .. attribute:: key_agreement
+
+ :type: bool
+
+ This purpose is set to true when the subject public key is used for key
+ agreement. For example, when a Diffie-Hellman key is to be used for
+ key management, then this purpose is set to true.
+
+ .. attribute:: key_cert_sign
+
+ :type: bool
+
+ This purpose is set to true when the subject public key is used for
+ verifying signatures on public key certificates. If this purpose is set
+ to true then ``ca`` must be true in the :class:`BasicConstraints`
+ extension.
+
+ .. attribute:: crl_sign
+
+ :type: bool
+
+ This purpose is set to true when the subject public key is used for
+ verifying signatures on certificate revocation lists.
+
+ .. attribute:: encipher_only
+
+ :type: bool
+
+ When this purposes is set to true and the ``key_agreement`` purpose is
+ also set, the subject public key may be used only for enciphering data
+ while performing key agreement.
+
+ :raises ValueError: This is raised if accessed when ``key_agreement``
+ is false.
+
+ .. attribute:: decipher_only
+
+ :type: bool
+
+ When this purposes is set to true and the ``key_agreement`` purpose is
+ also set, the subject public key may be used only for deciphering data
+ while performing key agreement.
+
+ :raises ValueError: This is raised if accessed when ``key_agreement``
+ is false.
+
+
+.. class:: BasicConstraints(ca, path_length)
+
+ .. versionadded:: 0.9
+
+ Basic constraints is an X.509 extension type that defines whether a given
+ certificate is allowed to sign additional certificates and what path
+ length restrictions may exist.
+
+ .. attribute:: oid
+
+ .. versionadded:: 1.0
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns :attr:`~cryptography.x509.oid.ExtensionOID.BASIC_CONSTRAINTS`.
+
+ .. attribute:: ca
+
+ :type: bool
+
+ Whether the certificate can sign certificates.
+
+ .. attribute:: path_length
+
+ :type: int or None
+
+ The maximum path length for certificates subordinate to this
+ certificate. This attribute only has meaning if ``ca`` is true.
+ If ``ca`` is true then a path length of None means there's no
+ restriction on the number of subordinate CAs in the certificate chain.
+ If it is zero or greater then it defines the maximum length for a
+ subordinate CA's certificate chain. For example, a ``path_length`` of 1
+ means the certificate can sign a subordinate CA, but the subordinate CA
+ is not allowed to create subordinates with ``ca`` set to true.
+
+.. class:: ExtendedKeyUsage(usages)
+
+ .. versionadded:: 0.9
+
+ This extension indicates one or more purposes for which the certified
+ public key may be used, in addition to or in place of the basic
+ purposes indicated in the key usage extension. The object is
+ iterable to obtain the list of
+ :class:`~cryptography.x509.oid.ExtendedKeyUsageOID` OIDs present.
+
+ :param list usages: A list of
+ :class:`~cryptography.x509.oid.ExtendedKeyUsageOID` OIDs.
+
+ .. attribute:: oid
+
+ .. versionadded:: 1.0
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns :attr:`~cryptography.x509.oid.ExtensionOID.EXTENDED_KEY_USAGE`.
+
+
+.. class:: OCSPNoCheck()
+
+ .. versionadded:: 1.0
+
+ This presence of this extension indicates that an OCSP client can trust a
+ responder for the lifetime of the responder's certificate. CAs issuing
+ such a certificate should realize that a compromise of the responder's key
+ is as serious as the compromise of a CA key used to sign CRLs, at least for
+ the validity period of this certificate. CA's may choose to issue this type
+ of certificate with a very short lifetime and renew it frequently. This
+ extension is only relevant when the certificate is an authorized OCSP
+ responder.
+
+ .. attribute:: oid
+
+ .. versionadded:: 1.0
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns :attr:`~cryptography.x509.oid.ExtensionOID.OCSP_NO_CHECK`.
+
+
+.. class:: TLSFeature(features)
+
+ .. versionadded:: 2.1
+
+ The TLS Feature extension is defined in :rfc:`7633` and is used in
+ certificates for OCSP Must-Staple. The object is iterable to get every
+ element.
+
+ :param list features: A list of features to enable from the
+ :class:`~cryptography.x509.TLSFeatureType` enum. At this time only
+ ``status_request`` or ``status_request_v2`` are allowed.
+
+ .. attribute:: oid
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns :attr:`~cryptography.x509.oid.ExtensionOID.TLS_FEATURE`.
+
+.. class:: TLSFeatureType
+
+ .. versionadded:: 2.1
+
+ An enumeration of TLS Feature types.
+
+ .. attribute:: status_request
+
+ This feature type is defined in :rfc:`6066` and, when embedded in
+ an X.509 certificate, signals to the client that it should require
+ a stapled OCSP response in the TLS handshake. Commonly known as OCSP
+ Must-Staple in certificates.
+
+ .. attribute:: status_request_v2
+
+ This feature type is defined in :rfc:`6961`. This value is not
+ commonly used and if you want to enable OCSP Must-Staple you should
+ use ``status_request``.
+
+
+.. class:: NameConstraints(permitted_subtrees, excluded_subtrees)
+
+ .. versionadded:: 1.0
+
+ The name constraints extension, which only has meaning in a CA certificate,
+ defines a name space within which all subject names in certificates issued
+ beneath the CA certificate must (or must not) be in. For specific details
+ on the way this extension should be processed see :rfc:`5280`.
+
+ .. attribute:: oid
+
+ .. versionadded:: 1.0
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns :attr:`~cryptography.x509.oid.ExtensionOID.NAME_CONSTRAINTS`.
+
+ .. attribute:: permitted_subtrees
+
+ :type: list of :class:`GeneralName` objects or None
+
+ The set of permitted name patterns. If a name matches this and an
+ element in ``excluded_subtrees`` it is invalid. At least one of
+ ``permitted_subtrees`` and ``excluded_subtrees`` will be non-None.
+
+ .. attribute:: excluded_subtrees
+
+ :type: list of :class:`GeneralName` objects or None
+
+ Any name matching a restriction in the ``excluded_subtrees`` field is
+ invalid regardless of information appearing in the
+ ``permitted_subtrees``. At least one of ``permitted_subtrees`` and
+ ``excluded_subtrees`` will be non-None.
+
+.. class:: AuthorityKeyIdentifier(key_identifier, authority_cert_issuer, authority_cert_serial_number)
+
+ .. versionadded:: 0.9
+
+ The authority key identifier extension provides a means of identifying the
+ public key corresponding to the private key used to sign a certificate.
+ This extension is typically used to assist in determining the appropriate
+ certificate chain. For more information about generation and use of this
+ extension see `RFC 5280 section 4.2.1.1`_.
+
+ .. attribute:: oid
+
+ .. versionadded:: 1.0
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns
+ :attr:`~cryptography.x509.oid.ExtensionOID.AUTHORITY_KEY_IDENTIFIER`.
+
+ .. attribute:: key_identifier
+
+ :type: bytes
+
+ A value derived from the public key used to verify the certificate's
+ signature.
+
+ .. attribute:: authority_cert_issuer
+
+ :type: A list of :class:`GeneralName` instances or None
+
+ The :class:`GeneralName` (one or multiple) of the issuer's issuer.
+
+ .. attribute:: authority_cert_serial_number
+
+ :type: int or None
+
+ The serial number of the issuer's issuer.
+
+ .. classmethod:: from_issuer_public_key(public_key)
+
+ .. 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
+ :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.
+ The generated ``key_identifier`` is the SHA1 hash of the ``subjectPublicKey``
+ ASN.1 bit string. This is the first recommendation in :rfc:`5280`
+ section 4.2.1.2.
+
+ :param public_key: One of
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PublicKey`.
+
+ .. doctest::
+
+ >>> from cryptography import x509
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> issuer_cert = x509.load_pem_x509_certificate(pem_data, default_backend())
+ >>> x509.AuthorityKeyIdentifier.from_issuer_public_key(issuer_cert.public_key())
+ <AuthorityKeyIdentifier(key_identifier=b'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_ext = issuer_cert.extensions.get_extension_for_class(x509.SubjectKeyIdentifier)
+ >>> x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(ski_ext.value)
+ <AuthorityKeyIdentifier(key_identifier=b'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
+
+ The subject key identifier extension provides a means of identifying
+ certificates that contain a particular public key.
+
+ .. attribute:: oid
+
+ .. versionadded:: 1.0
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns
+ :attr:`~cryptography.x509.oid.ExtensionOID.SUBJECT_KEY_IDENTIFIER`.
+
+ .. attribute:: digest
+
+ :type: bytes
+
+ The binary value of the identifier.
+
+ .. classmethod:: from_public_key(public_key)
+
+ .. versionadded:: 1.0
+
+ Creates a new SubjectKeyIdentifier instance using the public key
+ provided to generate the appropriate digest. This should be the public
+ key that is in the certificate. The generated digest is the SHA1 hash
+ of the ``subjectPublicKey`` ASN.1 bit string. This is the first
+ recommendation in :rfc:`5280` section 4.2.1.2.
+
+ :param public_key: One of
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PublicKey`.
+
+ .. doctest::
+
+ >>> from cryptography import x509
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> csr = x509.load_pem_x509_csr(pem_req_data, default_backend())
+ >>> x509.SubjectKeyIdentifier.from_public_key(csr.public_key())
+ <SubjectKeyIdentifier(digest=b'\xdb\xaa\xf0\x06\x11\xdbD\xfe\xbf\x93\x03\x8av\x88WP7\xa6\x91\xf7')>
+
+.. class:: SubjectAlternativeName(general_names)
+
+ .. versionadded:: 0.9
+
+ Subject alternative name is an X.509 extension that provides a list of
+ :ref:`general name <general_name_classes>` instances that provide a set
+ of identities for which the certificate is valid. The object is iterable to
+ get every element.
+
+ :param list general_names: A list of :class:`GeneralName` instances.
+
+ .. attribute:: oid
+
+ .. versionadded:: 1.0
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns
+ :attr:`~cryptography.x509.oid.ExtensionOID.SUBJECT_ALTERNATIVE_NAME`.
+
+ .. method:: get_values_for_type(type)
+
+ :param type: A :class:`GeneralName` instance. This is one of the
+ :ref:`general name classes <general_name_classes>`.
+
+ :returns: A list of values extracted from the matched general names.
+ The type of the returned values depends on the :class:`GeneralName`.
+
+ .. doctest::
+
+ >>> from cryptography import x509
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> cert = x509.load_pem_x509_certificate(cryptography_cert_pem, default_backend())
+ >>> # Get the subjectAltName extension from the certificate
+ >>> ext = cert.extensions.get_extension_for_oid(ExtensionOID.SUBJECT_ALTERNATIVE_NAME)
+ >>> # Get the dNSName entries from the SAN extension
+ >>> ext.value.get_values_for_type(x509.DNSName)
+ ['www.cryptography.io', 'cryptography.io']
+
+
+.. class:: IssuerAlternativeName(general_names)
+
+ .. versionadded:: 1.0
+
+ Issuer alternative name is an X.509 extension that provides a list of
+ :ref:`general name <general_name_classes>` instances that provide a set
+ of identities for the certificate issuer. The object is iterable to
+ get every element.
+
+ :param list general_names: A list of :class:`GeneralName` instances.
+
+ .. attribute:: oid
+
+ .. versionadded:: 1.0
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns
+ :attr:`~cryptography.x509.oid.ExtensionOID.ISSUER_ALTERNATIVE_NAME`.
+
+ .. method:: get_values_for_type(type)
+
+ :param type: A :class:`GeneralName` instance. This is one of the
+ :ref:`general name classes <general_name_classes>`.
+
+ :returns: A list of values extracted from the matched general names.
+
+
+.. class:: PrecertificateSignedCertificateTimestamps(scts)
+
+ .. versionadded:: 2.0
+
+ This extension contains
+ :class:`~cryptography.x509.certificate_transparency.SignedCertificateTimestamp`
+ instances which were issued for the pre-certificate corresponding to this
+ certificate. These can be used to verify that the certificate is included
+ in a public Certificate Transparency log.
+
+ It is an iterable containing one or more
+ :class:`~cryptography.x509.certificate_transparency.SignedCertificateTimestamp`
+ objects.
+
+ :param list scts: A ``list`` of
+ :class:`~cryptography.x509.certificate_transparency.SignedCertificateTimestamp`
+ objects.
+
+ .. attribute:: oid
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns
+ :attr:`~cryptography.x509.oid.ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS`.
+
+
+.. class:: PrecertPoison()
+
+ .. versionadded:: 2.4
+
+ This extension indicates that the certificate should not be treated as a
+ certificate for the purposes of validation, but is instead for submission
+ to a certificate transparency log in order to obtain SCTs which will be
+ embedded in a :class:`PrecertificateSignedCertificateTimestamps` extension
+ on the final certificate.
+
+ .. attribute:: oid
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns :attr:`~cryptography.x509.oid.ExtensionOID.PRECERT_POISON`.
+
+
+.. class:: DeltaCRLIndicator(crl_number)
+
+ .. versionadded:: 2.1
+
+ The delta CRL indicator is a CRL extension that identifies a CRL as being
+ a delta CRL. Delta CRLs contain updates to revocation information
+ previously distributed, rather than all the information that would appear
+ in a complete CRL.
+
+ :param int crl_number: The CRL number of the complete CRL that the
+ delta CRL is updating.
+
+ .. attribute:: oid
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns
+ :attr:`~cryptography.x509.oid.ExtensionOID.DELTA_CRL_INDICATOR`.
+
+ .. attribute:: crl_number
+
+ :type: int
+
+
+.. class:: AuthorityInformationAccess(descriptions)
+
+ .. versionadded:: 0.9
+
+ The authority information access extension indicates how to access
+ information and services for the issuer of the certificate in which
+ the extension appears. Information and services may include online
+ validation services (such as OCSP) and issuer data. It is an iterable,
+ containing one or more :class:`~cryptography.x509.AccessDescription`
+ instances.
+
+ :param list descriptions: A list of :class:`AccessDescription` objects.
+
+ .. attribute:: oid
+
+ .. versionadded:: 1.0
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns
+ :attr:`~cryptography.x509.oid.ExtensionOID.AUTHORITY_INFORMATION_ACCESS`.
+
+
+.. class:: AccessDescription(access_method, access_location)
+
+ .. versionadded:: 0.9
+
+ .. attribute:: access_method
+
+ :type: :class:`ObjectIdentifier`
+
+ The access method defines what the ``access_location`` means. It must
+ be either
+ :attr:`~cryptography.x509.oid.AuthorityInformationAccessOID.OCSP` or
+ :attr:`~cryptography.x509.oid.AuthorityInformationAccessOID.CA_ISSUERS`.
+ If it is
+ :attr:`~cryptography.x509.oid.AuthorityInformationAccessOID.OCSP`
+ the access location will be where to obtain OCSP
+ information for the certificate. If it is
+ :attr:`~cryptography.x509.oid.AuthorityInformationAccessOID.CA_ISSUERS`
+ the access location will provide additional information about the
+ issuing certificate.
+
+ .. attribute:: access_location
+
+ :type: :class:`GeneralName`
+
+ Where to access the information defined by the access method.
+
+.. class:: FreshestCRL(distribution_points)
+
+ .. versionadded:: 2.1
+
+ The freshest CRL extension (also known as Delta CRL Distribution Point)
+ identifies how delta CRL information is obtained. It is an iterable,
+ containing one or more :class:`DistributionPoint` instances.
+
+ :param list distribution_points: A list of :class:`DistributionPoint`
+ instances.
+
+ .. attribute:: oid
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns
+ :attr:`~cryptography.x509.oid.ExtensionOID.FRESHEST_CRL`.
+
+.. class:: CRLDistributionPoints(distribution_points)
+
+ .. versionadded:: 0.9
+
+ The CRL distribution points extension identifies how CRL information is
+ obtained. It is an iterable, containing one or more
+ :class:`DistributionPoint` instances.
+
+ :param list distribution_points: A list of :class:`DistributionPoint`
+ instances.
+
+ .. attribute:: oid
+
+ .. versionadded:: 1.0
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns
+ :attr:`~cryptography.x509.oid.ExtensionOID.CRL_DISTRIBUTION_POINTS`.
+
+.. class:: DistributionPoint(full_name, relative_name, reasons, crl_issuer)
+
+ .. versionadded:: 0.9
+
+ .. attribute:: full_name
+
+ :type: list of :class:`GeneralName` instances or None
+
+ This field describes methods to retrieve the CRL. At most one of
+ ``full_name`` or ``relative_name`` will be non-None.
+
+ .. attribute:: relative_name
+
+ :type: :class:`RelativeDistinguishedName` or None
+
+ This field describes methods to retrieve the CRL relative to the CRL
+ issuer. At most one of ``full_name`` or ``relative_name`` will be
+ non-None.
+
+ .. versionchanged:: 1.6
+ Changed from :class:`Name` to :class:`RelativeDistinguishedName`.
+
+ .. attribute:: crl_issuer
+
+ :type: list of :class:`GeneralName` instances or None
+
+ Information about the issuer of the CRL.
+
+ .. attribute:: reasons
+
+ :type: frozenset of :class:`ReasonFlags` or None
+
+ The reasons a given distribution point may be used for when performing
+ revocation checks.
+
+.. class:: ReasonFlags
+
+ .. versionadded:: 0.9
+
+ An enumeration for CRL reasons.
+
+ .. attribute:: unspecified
+
+ It is unspecified why the certificate was revoked. This reason cannot
+ be used as a reason flag in a :class:`DistributionPoint`.
+
+ .. attribute:: key_compromise
+
+ This reason indicates that the private key was compromised.
+
+ .. attribute:: ca_compromise
+
+ This reason indicates that the CA issuing the certificate was
+ compromised.
+
+ .. attribute:: affiliation_changed
+
+ This reason indicates that the subject's name or other information has
+ changed.
+
+ .. attribute:: superseded
+
+ This reason indicates that a certificate has been superseded.
+
+ .. attribute:: cessation_of_operation
+
+ This reason indicates that the certificate is no longer required.
+
+ .. attribute:: certificate_hold
+
+ This reason indicates that the certificate is on hold.
+
+ .. attribute:: privilege_withdrawn
+
+ This reason indicates that the privilege granted by this certificate
+ have been withdrawn.
+
+ .. attribute:: aa_compromise
+
+ When an attribute authority has been compromised.
+
+ .. attribute:: remove_from_crl
+
+ This reason indicates that the certificate was on hold and should be
+ removed from the CRL. This reason cannot be used as a reason flag
+ in a :class:`DistributionPoint`.
+
+.. class:: InhibitAnyPolicy(skip_certs)
+
+ .. versionadded:: 1.0
+
+ The inhibit ``anyPolicy`` extension indicates that the special OID
+ :attr:`~cryptography.x509.oid.CertificatePoliciesOID.ANY_POLICY`, is not
+ considered an explicit match for other :class:`CertificatePolicies` except
+ when it appears in an intermediate self-issued CA certificate. The value
+ indicates the number of additional non-self-issued certificates that may
+ appear in the path before
+ :attr:`~cryptography.x509.oid.CertificatePoliciesOID.ANY_POLICY` is no
+ longer permitted. For example, a value of one indicates that
+ :attr:`~cryptography.x509.oid.CertificatePoliciesOID.ANY_POLICY` may be
+ processed in certificates issued by the subject of this certificate, but
+ not in additional certificates in the path.
+
+ .. attribute:: oid
+
+ .. versionadded:: 1.0
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns
+ :attr:`~cryptography.x509.oid.ExtensionOID.INHIBIT_ANY_POLICY`.
+
+ .. attribute:: skip_certs
+
+ :type: int
+
+.. class:: PolicyConstraints
+
+ .. versionadded:: 1.3
+
+ The policy constraints extension is used to inhibit policy mapping or
+ require that each certificate in a chain contain an acceptable policy
+ identifier. For more information about the use of this extension see
+ :rfc:`5280`.
+
+ .. attribute:: oid
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns :attr:`~cryptography.x509.oid.ExtensionOID.POLICY_CONSTRAINTS`.
+
+ .. attribute:: require_explicit_policy
+
+ :type: int or None
+
+ If this field is not None, the value indicates the number of additional
+ certificates that may appear in the chain before an explicit policy is
+ required for the entire path. When an explicit policy is required, it
+ is necessary for all certificates in the chain to contain an acceptable
+ policy identifier in the certificate policies extension. An
+ acceptable policy identifier is the identifier of a policy required
+ by the user of the certification path or the identifier of a policy
+ that has been declared equivalent through policy mapping.
+
+ .. attribute:: inhibit_policy_mapping
+
+ :type: int or None
+
+ If this field is not None, the value indicates the number of additional
+ certificates that may appear in the chain before policy mapping is no
+ longer permitted. For example, a value of one indicates that policy
+ mapping may be processed in certificates issued by the subject of this
+ certificate, but not in additional certificates in the chain.
+
+.. class:: CRLNumber(crl_number)
+
+ .. versionadded:: 1.2
+
+ The CRL number is a CRL extension that conveys a monotonically increasing
+ sequence number for a given CRL scope and CRL issuer. This extension allows
+ users to easily determine when a particular CRL supersedes another CRL.
+ :rfc:`5280` requires that this extension be present in conforming CRLs.
+
+ .. attribute:: oid
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns
+ :attr:`~cryptography.x509.oid.ExtensionOID.CRL_NUMBER`.
+
+ .. attribute:: crl_number
+
+ :type: int
+
+.. class:: IssuingDistributionPoint(full_name, relative_name,\
+ only_contains_user_certs, only_contains_ca_certs, only_some_reasons,\
+ indirect_crl, only_contains_attribute_certs)
+
+ .. versionadded:: 2.5
+
+ Issuing distribution point is a CRL extension that identifies the CRL
+ distribution point and scope for a particular CRL. It indicates whether
+ the CRL covers revocation for end entity certificates only, CA certificates
+ only, attribute certificates only, or a limited set of reason codes. For
+ specific details on the way this extension should be processed see
+ :rfc:`5280`.
+
+ .. attribute:: oid
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns
+ :attr:`~cryptography.x509.oid.ExtensionOID.ISSUING_DISTRIBUTION_POINT`.
+
+ .. attribute:: only_contains_user_certs
+
+ :type: bool
+
+ Set to ``True`` if the CRL this extension is embedded within only
+ contains information about user certificates.
+
+ .. attribute:: only_contains_ca_certs
+
+ :type: bool
+
+ Set to ``True`` if the CRL this extension is embedded within only
+ contains information about CA certificates.
+
+ .. attribute:: indirect_crl
+
+ :type: bool
+
+ Set to ``True`` if the CRL this extension is embedded within includes
+ certificates issued by one or more authorities other than the CRL
+ issuer.
+
+ .. attribute:: only_contains_attribute_certs
+
+ :type: bool
+
+ Set to ``True`` if the CRL this extension is embedded within only
+ contains information about attribute certificates.
+
+ .. attribute:: only_some_reasons
+
+ :type: frozenset of :class:`ReasonFlags` or None
+
+ The reasons for which the issuing distribution point is valid. None
+ indicates that it is valid for all reasons.
+
+ .. attribute:: full_name
+
+ :type: list of :class:`GeneralName` instances or None
+
+ This field describes methods to retrieve the CRL. At most one of
+ ``full_name`` or ``relative_name`` will be non-None.
+
+ .. attribute:: relative_name
+
+ :type: :class:`RelativeDistinguishedName` or None
+
+ This field describes methods to retrieve the CRL relative to the CRL
+ issuer. At most one of ``full_name`` or ``relative_name`` will be
+ non-None.
+
+.. class:: UnrecognizedExtension
+
+ .. versionadded:: 1.2
+
+ A generic extension class used to hold the raw value of extensions that
+ ``cryptography`` does not know how to parse. This can also be used when
+ creating new certificates, CRLs, or OCSP requests and responses to encode
+ extensions that ``cryptography`` does not know how to generate.
+
+ .. attribute:: oid
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns the OID associated with this extension.
+
+ .. attribute:: value
+
+ :type: bytes
+
+ Returns the DER encoded bytes payload of the extension.
+
+.. class:: CertificatePolicies(policies)
+
+ .. versionadded:: 0.9
+
+ The certificate policies extension is an iterable, containing one or more
+ :class:`PolicyInformation` instances.
+
+ :param list policies: A list of :class:`PolicyInformation` instances.
+
+ As an example of how ``CertificatePolicies`` might be used, if you wanted
+ to check if a certificated contained the CAB Forum's "domain-validated"
+ policy, you might write code like:
+
+ .. code-block:: python
+
+ def contains_domain_validated(policies):
+ return any(
+ policy.oid.dotted_string == "2.23.140.1.2.1"
+ for policy in policies
+ )
+
+ .. attribute:: oid
+
+ .. versionadded:: 1.0
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns
+ :attr:`~cryptography.x509.oid.ExtensionOID.CERTIFICATE_POLICIES`.
+
+Certificate Policies Classes
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+These classes may be present within a :class:`CertificatePolicies` instance.
+
+.. class:: PolicyInformation(policy_identifier, policy_qualifiers)
+
+ .. versionadded:: 0.9
+
+ Contains a policy identifier and an optional list of qualifiers.
+
+ .. attribute:: policy_identifier
+
+ :type: :class:`ObjectIdentifier`
+
+ .. attribute:: policy_qualifiers
+
+ :type: list
+
+ A list consisting of :term:`text` and/or :class:`UserNotice` objects.
+ If the value is text it is a pointer to the practice statement
+ published by the certificate authority. If it is a user notice it is
+ meant for display to the relying party when the certificate is
+ used.
+
+.. class:: UserNotice(notice_reference, explicit_text)
+
+ .. versionadded:: 0.9
+
+ User notices are intended for display to a relying party when a certificate
+ is used. In practice, few if any UIs expose this data and it is a rarely
+ encoded component.
+
+ .. attribute:: notice_reference
+
+ :type: :class:`NoticeReference` or None
+
+ The notice reference field names an organization and identifies,
+ by number, a particular statement prepared by that organization.
+
+ .. attribute:: explicit_text
+
+ This field includes an arbitrary textual statement directly in the
+ certificate.
+
+ :type: :term:`text`
+
+.. class:: NoticeReference(organization, notice_numbers)
+
+ Notice reference can name an organization and provide information about
+ notices related to the certificate. For example, it might identify the
+ organization name and notice number 1. Application software could
+ have a notice file containing the current set of notices for the named
+ organization; the application would then extract the notice text from the
+ file and display it. In practice this is rarely seen.
+
+ .. versionadded:: 0.9
+
+ .. attribute:: organization
+
+ :type: :term:`text`
+
+ .. attribute:: notice_numbers
+
+ :type: list
+
+ A list of integers.
+
+.. _crl_entry_extensions:
+
+CRL Entry Extensions
+~~~~~~~~~~~~~~~~~~~~
+
+These extensions are only valid within a :class:`RevokedCertificate` object.
+
+.. class:: CertificateIssuer(general_names)
+
+ .. versionadded:: 1.2
+
+ The certificate issuer is an extension that is only valid inside
+ :class:`~cryptography.x509.RevokedCertificate` objects. If the
+ ``indirectCRL`` property of the parent CRL's IssuingDistributionPoint
+ extension is set, then this extension identifies the certificate issuer
+ associated with the revoked certificate. The object is iterable to get
+ every element.
+
+ :param list general_names: A list of :class:`GeneralName` instances.
+
+ .. attribute:: oid
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns
+ :attr:`~cryptography.x509.oid.CRLEntryExtensionOID.CERTIFICATE_ISSUER`.
+
+ .. method:: get_values_for_type(type)
+
+ :param type: A :class:`GeneralName` instance. This is one of the
+ :ref:`general name classes <general_name_classes>`.
+
+ :returns: A list of values extracted from the matched general names.
+ The type of the returned values depends on the :class:`GeneralName`.
+
+.. class:: CRLReason(reason)
+
+ .. versionadded:: 1.2
+
+ CRL reason (also known as ``reasonCode``) is an extension that is only
+ valid inside :class:`~cryptography.x509.RevokedCertificate` objects. It
+ identifies a reason for the certificate revocation.
+
+ :param reason: An element from :class:`~cryptography.x509.ReasonFlags`.
+
+ .. attribute:: oid
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns
+ :attr:`~cryptography.x509.oid.CRLEntryExtensionOID.CRL_REASON`.
+
+ .. attribute:: reason
+
+ :type: An element from :class:`~cryptography.x509.ReasonFlags`
+
+.. class:: InvalidityDate(invalidity_date)
+
+ .. versionadded:: 1.2
+
+ Invalidity date is an extension that is only valid inside
+ :class:`~cryptography.x509.RevokedCertificate` objects. It provides
+ the date on which it is known or suspected that the private key was
+ compromised or that the certificate otherwise became invalid.
+ This date may be earlier than the revocation date in the CRL entry,
+ which is the date at which the CA processed the revocation.
+
+ :param invalidity_date: The :class:`datetime.datetime` when it is known
+ or suspected that the private key was compromised.
+
+ .. attribute:: oid
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns
+ :attr:`~cryptography.x509.oid.CRLEntryExtensionOID.INVALIDITY_DATE`.
+
+ .. attribute:: invalidity_date
+
+ :type: :class:`datetime.datetime`
+
+OCSP Extensions
+~~~~~~~~~~~~~~~
+
+.. class:: OCSPNonce(nonce)
+
+ .. versionadded:: 2.4
+
+ OCSP nonce is an extension that is only valid inside
+ :class:`~cryptography.x509.ocsp.OCSPRequest` and
+ :class:`~cryptography.x509.ocsp.OCSPResponse` objects. The nonce
+ cryptographically binds a request and a response to prevent replay attacks.
+ In practice nonces are rarely used in OCSP due to the desire to precompute
+ OCSP responses at large scale.
+
+ .. attribute:: oid
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns
+ :attr:`~cryptography.x509.oid.OCSPExtensionOID.NONCE`.
+
+ .. attribute:: nonce
+
+ :type: bytes
+
+Object Identifiers
+~~~~~~~~~~~~~~~~~~
+
+X.509 elements are frequently identified by :class:`ObjectIdentifier`
+instances. The following common OIDs are available as constants.
+
+.. currentmodule:: cryptography.x509.oid
+
+.. class:: NameOID
+
+ These OIDs are typically seen in X.509 names.
+
+ .. versionadded:: 1.0
+
+ .. attribute:: COMMON_NAME
+
+ Corresponds to the dotted string ``"2.5.4.3"``. Historically the domain
+ name would be encoded here for server certificates. :rfc:`2818`
+ deprecates this practice and names of that type should now be located
+ in a :class:`~cryptography.x509.SubjectAlternativeName` extension.
+
+ .. attribute:: COUNTRY_NAME
+
+ Corresponds to the dotted string ``"2.5.4.6"``.
+
+ .. attribute:: LOCALITY_NAME
+
+ Corresponds to the dotted string ``"2.5.4.7"``.
+
+ .. attribute:: STATE_OR_PROVINCE_NAME
+
+ Corresponds to the dotted string ``"2.5.4.8"``.
+
+ .. attribute:: STREET_ADDRESS
+
+ .. versionadded:: 1.6
+
+ Corresponds to the dotted string ``"2.5.4.9"``.
+
+ .. attribute:: ORGANIZATION_NAME
+
+ Corresponds to the dotted string ``"2.5.4.10"``.
+
+ .. attribute:: ORGANIZATIONAL_UNIT_NAME
+
+ Corresponds to the dotted string ``"2.5.4.11"``.
+
+ .. attribute:: SERIAL_NUMBER
+
+ Corresponds to the dotted string ``"2.5.4.5"``. This is distinct from
+ the serial number of the certificate itself (which can be obtained with
+ :func:`~cryptography.x509.Certificate.serial_number`).
+
+ .. attribute:: SURNAME
+
+ Corresponds to the dotted string ``"2.5.4.4"``.
+
+ .. attribute:: GIVEN_NAME
+
+ Corresponds to the dotted string ``"2.5.4.42"``.
+
+ .. attribute:: TITLE
+
+ Corresponds to the dotted string ``"2.5.4.12"``.
+
+ .. attribute:: GENERATION_QUALIFIER
+
+ Corresponds to the dotted string ``"2.5.4.44"``.
+
+ .. attribute:: X500_UNIQUE_IDENTIFIER
+
+ .. versionadded:: 1.6
+
+ Corresponds to the dotted string ``"2.5.4.45"``.
+
+ .. attribute:: DN_QUALIFIER
+
+ Corresponds to the dotted string ``"2.5.4.46"``. This specifies
+ disambiguating information to add to the relative distinguished name of an
+ entry. See :rfc:`2256`.
+
+ .. attribute:: PSEUDONYM
+
+ Corresponds to the dotted string ``"2.5.4.65"``.
+
+ .. attribute:: USER_ID
+
+ .. versionadded:: 1.6
+
+ Corresponds to the dotted string ``"0.9.2342.19200300.100.1.1"``.
+
+ .. attribute:: DOMAIN_COMPONENT
+
+ Corresponds to the dotted string ``"0.9.2342.19200300.100.1.25"``. A string
+ holding one component of a domain name. See :rfc:`4519`.
+
+ .. attribute:: EMAIL_ADDRESS
+
+ Corresponds to the dotted string ``"1.2.840.113549.1.9.1"``.
+
+ .. attribute:: JURISDICTION_COUNTRY_NAME
+
+ Corresponds to the dotted string ``"1.3.6.1.4.1.311.60.2.1.3"``.
+
+ .. attribute:: JURISDICTION_LOCALITY_NAME
+
+ Corresponds to the dotted string ``"1.3.6.1.4.1.311.60.2.1.1"``.
+
+ .. attribute:: JURISDICTION_STATE_OR_PROVINCE_NAME
+
+ Corresponds to the dotted string ``"1.3.6.1.4.1.311.60.2.1.2"``.
+
+ .. attribute:: BUSINESS_CATEGORY
+
+ Corresponds to the dotted string ``"2.5.4.15"``.
+
+ .. attribute:: POSTAL_ADDRESS
+
+ .. versionadded:: 1.6
+
+ Corresponds to the dotted string ``"2.5.4.16"``.
+
+ .. attribute:: POSTAL_CODE
+
+ .. versionadded:: 1.6
+
+ Corresponds to the dotted string ``"2.5.4.17"``.
+
+
+.. class:: SignatureAlgorithmOID
+
+ .. versionadded:: 1.0
+
+ .. attribute:: RSA_WITH_MD5
+
+ Corresponds to the dotted string ``"1.2.840.113549.1.1.4"``. This is
+ an MD5 digest signed by an RSA key.
+
+ .. attribute:: RSA_WITH_SHA1
+
+ Corresponds to the dotted string ``"1.2.840.113549.1.1.5"``. This is
+ a SHA1 digest signed by an RSA key.
+
+ .. attribute:: RSA_WITH_SHA224
+
+ Corresponds to the dotted string ``"1.2.840.113549.1.1.14"``. This is
+ a SHA224 digest signed by an RSA key.
+
+ .. attribute:: RSA_WITH_SHA256
+
+ Corresponds to the dotted string ``"1.2.840.113549.1.1.11"``. This is
+ a SHA256 digest signed by an RSA key.
+
+ .. attribute:: RSA_WITH_SHA384
+
+ Corresponds to the dotted string ``"1.2.840.113549.1.1.12"``. This is
+ a SHA384 digest signed by an RSA key.
+
+ .. attribute:: RSA_WITH_SHA512
+
+ Corresponds to the dotted string ``"1.2.840.113549.1.1.13"``. This is
+ a SHA512 digest signed by an RSA key.
+
+ .. attribute:: RSASSA_PSS
+
+ .. versionadded:: 2.3
+
+ Corresponds to the dotted string ``"1.2.840.113549.1.1.10"``. This is
+ signed by an RSA key using the Probabilistic Signature Scheme (PSS)
+ padding from :rfc:`4055`. The hash function and padding are defined by
+ signature algorithm parameters.
+
+ .. attribute:: ECDSA_WITH_SHA1
+
+ Corresponds to the dotted string ``"1.2.840.10045.4.1"``. This is a SHA1
+ digest signed by an ECDSA key.
+
+ .. attribute:: ECDSA_WITH_SHA224
+
+ Corresponds to the dotted string ``"1.2.840.10045.4.3.1"``. This is
+ a SHA224 digest signed by an ECDSA key.
+
+ .. attribute:: ECDSA_WITH_SHA256
+
+ Corresponds to the dotted string ``"1.2.840.10045.4.3.2"``. This is
+ a SHA256 digest signed by an ECDSA key.
+
+ .. attribute:: ECDSA_WITH_SHA384
+
+ Corresponds to the dotted string ``"1.2.840.10045.4.3.3"``. This is
+ a SHA384 digest signed by an ECDSA key.
+
+ .. attribute:: ECDSA_WITH_SHA512
+
+ Corresponds to the dotted string ``"1.2.840.10045.4.3.4"``. This is
+ a SHA512 digest signed by an ECDSA key.
+
+ .. attribute:: DSA_WITH_SHA1
+
+ Corresponds to the dotted string ``"1.2.840.10040.4.3"``. This is
+ a SHA1 digest signed by a DSA key.
+
+ .. attribute:: DSA_WITH_SHA224
+
+ Corresponds to the dotted string ``"2.16.840.1.101.3.4.3.1"``. This is
+ a SHA224 digest signed by a DSA key.
+
+ .. attribute:: DSA_WITH_SHA256
+
+ Corresponds to the dotted string ``"2.16.840.1.101.3.4.3.2"``. This is
+ a SHA256 digest signed by a DSA key.
+
+ .. attribute:: ED25519
+
+ .. versionadded:: 2.8
+
+ Corresponds to the dotted string ``"1.3.101.112"``. This is a signature
+ using an ed25519 key.
+
+ .. attribute:: ED448
+
+ .. versionadded:: 2.8
+
+ Corresponds to the dotted string ``"1.3.101.113"``. This is a signature
+ using an ed448 key.
+
+
+.. class:: ExtendedKeyUsageOID
+
+ .. versionadded:: 1.0
+
+ .. attribute:: SERVER_AUTH
+
+ Corresponds to the dotted string ``"1.3.6.1.5.5.7.3.1"``. This is used
+ to denote that a certificate may be used for TLS web server
+ authentication.
+
+ .. attribute:: CLIENT_AUTH
+
+ Corresponds to the dotted string ``"1.3.6.1.5.5.7.3.2"``. This is used
+ to denote that a certificate may be used for TLS web client
+ authentication.
+
+ .. attribute:: CODE_SIGNING
+
+ Corresponds to the dotted string ``"1.3.6.1.5.5.7.3.3"``. This is used
+ to denote that a certificate may be used for code signing.
+
+ .. attribute:: EMAIL_PROTECTION
+
+ Corresponds to the dotted string ``"1.3.6.1.5.5.7.3.4"``. This is used
+ to denote that a certificate may be used for email protection.
+
+ .. attribute:: TIME_STAMPING
+
+ Corresponds to the dotted string ``"1.3.6.1.5.5.7.3.8"``. This is used
+ to denote that a certificate may be used for time stamping.
+
+ .. attribute:: OCSP_SIGNING
+
+ Corresponds to the dotted string ``"1.3.6.1.5.5.7.3.9"``. This is used
+ to denote that a certificate may be used for signing OCSP responses.
+
+ .. attribute:: ANY_EXTENDED_KEY_USAGE
+
+ .. versionadded:: 2.0
+
+ Corresponds to the dotted string ``"2.5.29.37.0"``. This is used to
+ denote that a certificate may be used for _any_ purposes. However,
+ :rfc:`5280` additionally notes that applications that require the
+ presence of a particular purpose _MAY_ reject certificates that include
+ the ``anyExtendedKeyUsage`` OID but not the particular OID expected for
+ the application. Therefore, the presence of this OID does not mean a
+ given application will accept the certificate for all purposes.
+
+
+.. class:: AuthorityInformationAccessOID
+
+ .. versionadded:: 1.0
+
+ .. attribute:: OCSP
+
+ Corresponds to the dotted string ``"1.3.6.1.5.5.7.48.1"``. Used as the
+ identifier for OCSP data in
+ :class:`~cryptography.x509.AccessDescription` objects.
+
+ .. attribute:: CA_ISSUERS
+
+ Corresponds to the dotted string ``"1.3.6.1.5.5.7.48.2"``. Used as the
+ identifier for CA issuer data in
+ :class:`~cryptography.x509.AccessDescription` objects.
+
+
+.. class:: CertificatePoliciesOID
+
+ .. versionadded:: 1.0
+
+ .. attribute:: CPS_QUALIFIER
+
+ Corresponds to the dotted string ``"1.3.6.1.5.5.7.2.1"``.
+
+ .. attribute:: CPS_USER_NOTICE
+
+ Corresponds to the dotted string ``"1.3.6.1.5.5.7.2.2"``.
+
+ .. attribute:: ANY_POLICY
+
+ Corresponds to the dotted string ``"2.5.29.32.0"``.
+
+
+.. class:: ExtensionOID
+
+ .. versionadded:: 1.0
+
+ .. attribute:: BASIC_CONSTRAINTS
+
+ Corresponds to the dotted string ``"2.5.29.19"``. The identifier for the
+ :class:`~cryptography.x509.BasicConstraints` extension type.
+
+ .. attribute:: KEY_USAGE
+
+ Corresponds to the dotted string ``"2.5.29.15"``. The identifier for the
+ :class:`~cryptography.x509.KeyUsage` extension type.
+
+ .. attribute:: SUBJECT_ALTERNATIVE_NAME
+
+ Corresponds to the dotted string ``"2.5.29.17"``. The identifier for the
+ :class:`~cryptography.x509.SubjectAlternativeName` extension type.
+
+ .. attribute:: ISSUER_ALTERNATIVE_NAME
+
+ Corresponds to the dotted string ``"2.5.29.18"``. The identifier for the
+ :class:`~cryptography.x509.IssuerAlternativeName` extension type.
+
+ .. attribute:: SUBJECT_KEY_IDENTIFIER
+
+ Corresponds to the dotted string ``"2.5.29.14"``. The identifier for the
+ :class:`~cryptography.x509.SubjectKeyIdentifier` extension type.
+
+ .. attribute:: NAME_CONSTRAINTS
+
+ Corresponds to the dotted string ``"2.5.29.30"``. The identifier for the
+ :class:`~cryptography.x509.NameConstraints` extension type.
+
+ .. attribute:: CRL_DISTRIBUTION_POINTS
+
+ Corresponds to the dotted string ``"2.5.29.31"``. The identifier for the
+ :class:`~cryptography.x509.CRLDistributionPoints` extension type.
+
+ .. attribute:: CERTIFICATE_POLICIES
+
+ Corresponds to the dotted string ``"2.5.29.32"``. The identifier for the
+ :class:`~cryptography.x509.CertificatePolicies` extension type.
+
+ .. attribute:: AUTHORITY_KEY_IDENTIFIER
+
+ Corresponds to the dotted string ``"2.5.29.35"``. The identifier for the
+ :class:`~cryptography.x509.AuthorityKeyIdentifier` extension type.
+
+ .. attribute:: EXTENDED_KEY_USAGE
+
+ Corresponds to the dotted string ``"2.5.29.37"``. The identifier for the
+ :class:`~cryptography.x509.ExtendedKeyUsage` extension type.
+
+ .. attribute:: AUTHORITY_INFORMATION_ACCESS
+
+ Corresponds to the dotted string ``"1.3.6.1.5.5.7.1.1"``. The identifier
+ for the :class:`~cryptography.x509.AuthorityInformationAccess` extension
+ type.
+
+ .. attribute:: INHIBIT_ANY_POLICY
+
+ Corresponds to the dotted string ``"2.5.29.54"``. The identifier
+ for the :class:`~cryptography.x509.InhibitAnyPolicy` extension type.
+
+ .. attribute:: OCSP_NO_CHECK
+
+ Corresponds to the dotted string ``"1.3.6.1.5.5.7.48.1.5"``. The
+ identifier for the :class:`~cryptography.x509.OCSPNoCheck` extension
+ type.
+
+ .. attribute:: TLS_FEATURE
+
+ Corresponds to the dotted string ``"1.3.6.1.5.5.7.1.24"``. The
+ identifier for the :class:`~cryptography.x509.TLSFeature` extension
+ type.
+
+ .. attribute:: CRL_NUMBER
+
+ Corresponds to the dotted string ``"2.5.29.20"``. The identifier for
+ the ``CRLNumber`` extension type. This extension only has meaning
+ for certificate revocation lists.
+
+ .. attribute:: DELTA_CRL_INDICATOR
+
+ .. versionadded:: 2.1
+
+ Corresponds to the dotted string ``"2.5.29.27"``. The identifier for
+ the ``DeltaCRLIndicator`` extension type. This extension only has
+ meaning for certificate revocation lists.
+
+ .. attribute:: PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS
+
+ .. versionadded:: 1.9
+
+ Corresponds to the dotted string ``"1.3.6.1.4.1.11129.2.4.2"``.
+
+ .. attribute:: PRECERT_POISON
+
+ .. versionadded:: 2.4
+
+ Corresponds to the dotted string ``"1.3.6.1.4.1.11129.2.4.3"``.
+
+ .. attribute:: POLICY_CONSTRAINTS
+
+ Corresponds to the dotted string ``"2.5.29.36"``. The identifier for the
+ :class:`~cryptography.x509.PolicyConstraints` extension type.
+
+ .. attribute:: FRESHEST_CRL
+
+ Corresponds to the dotted string ``"2.5.29.46"``. The identifier for the
+ :class:`~cryptography.x509.FreshestCRL` extension type.
+
+ .. attribute:: ISSUING_DISTRIBUTION_POINT
+
+ .. versionadded:: 2.4
+
+ Corresponds to the dotted string ``"2.5.29.28"``.
+
+
+.. class:: CRLEntryExtensionOID
+
+ .. versionadded:: 1.2
+
+ .. attribute:: CERTIFICATE_ISSUER
+
+ Corresponds to the dotted string ``"2.5.29.29"``.
+
+ .. attribute:: CRL_REASON
+
+ Corresponds to the dotted string ``"2.5.29.21"``.
+
+ .. attribute:: INVALIDITY_DATE
+
+ Corresponds to the dotted string ``"2.5.29.24"``.
+
+
+.. class:: OCSPExtensionOID
+
+ .. versionadded:: 2.4
+
+ .. attribute:: NONCE
+
+ Corresponds to the dotted string ``"1.3.6.1.5.5.7.48.1.2"``.
+
+Helper Functions
+~~~~~~~~~~~~~~~~
+.. currentmodule:: cryptography.x509
+
+.. function:: random_serial_number()
+
+ .. versionadded:: 1.6
+
+ Generates a random serial number suitable for use when constructing
+ certificates.
+
+Exceptions
+~~~~~~~~~~
+.. currentmodule:: cryptography.x509
+
+.. class:: InvalidVersion
+
+ This is raised when an X.509 certificate has an invalid version number.
+
+ .. attribute:: parsed_version
+
+ :type: int
+
+ Returns the raw version that was parsed from the certificate.
+
+.. class:: DuplicateExtension
+
+ This is raised when more than one X.509 extension of the same type is
+ found within a certificate.
+
+ .. attribute:: oid
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns the OID.
+
+.. class:: ExtensionNotFound
+
+ This is raised when calling :meth:`Extensions.get_extension_for_oid` with
+ an extension OID that is not present in the certificate.
+
+ .. attribute:: oid
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns the OID.
+
+.. class:: UnsupportedGeneralNameType
+
+ This is raised when a certificate contains an unsupported general name
+ type in an extension.
+
+ .. attribute:: type
+
+ :type: int
+
+ The integer value of the unsupported type. The complete list of
+ types can be found in `RFC 5280 section 4.2.1.6`_.
+
+
+.. _`RFC 5280 section 4.2.1.1`: https://tools.ietf.org/html/rfc5280#section-4.2.1.1
+.. _`RFC 5280 section 4.2.1.6`: https://tools.ietf.org/html/rfc5280#section-4.2.1.6
+.. _`CABForum Guidelines`: https://cabforum.org/baseline-requirements-documents/
diff --git a/docs/x509/tutorial.rst b/docs/x509/tutorial.rst
new file mode 100644
index 00000000..cc2ffb77
--- /dev/null
+++ b/docs/x509/tutorial.rst
@@ -0,0 +1,171 @@
+Tutorial
+========
+
+X.509 certificates are used to authenticate clients and servers. The most
+common use case is for web servers using HTTPS.
+
+Creating a Certificate Signing Request (CSR)
+--------------------------------------------
+
+When obtaining a certificate from a certificate authority (CA), the usual
+flow is:
+
+1. You generate a private/public key pair.
+2. You create a request for a certificate, which is signed by your key (to
+ prove that you own that key).
+3. You give your CSR to a CA (but *not* the private key).
+4. The CA validates that you own the resource (e.g. domain) you want a
+ certificate for.
+5. The CA gives you a certificate, signed by them, which identifies your public
+ key, and the resource you are authenticated for.
+6. You configure your server to use that certificate, combined with your
+ private key, to server traffic.
+
+If you want to obtain a certificate from a typical commercial CA, here's how.
+First, you'll need to generate a private key, we'll generate an RSA key (these
+are the most common types of keys on the web right now):
+
+.. code-block:: pycon
+
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> from cryptography.hazmat.primitives import serialization
+ >>> from cryptography.hazmat.primitives.asymmetric import rsa
+ >>> # 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"),
+ ... ))
+
+If you've already generated a key you can load it with
+:func:`~cryptography.hazmat.primitives.serialization.load_pem_private_key`.
+
+Next we need to generate a certificate signing request. A typical CSR contains
+a few details:
+
+* Information about our public key (including a signature of the entire body).
+* Information about who *we* are.
+* Information about what domains this certificate is for.
+
+.. code-block:: pycon
+
+ >>> from cryptography import x509
+ >>> from cryptography.x509.oid import NameOID
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> # Generate a CSR
+ >>> csr = x509.CertificateSigningRequestBuilder().subject_name(x509.Name([
+ ... # Provide various details about who we are.
+ ... x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
+ ... x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"California"),
+ ... x509.NameAttribute(NameOID.LOCALITY_NAME, u"San Francisco"),
+ ... x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"My Company"),
+ ... x509.NameAttribute(NameOID.COMMON_NAME, u"mysite.com"),
+ ... ])).add_extension(
+ ... x509.SubjectAlternativeName([
+ ... # Describe what sites we want this certificate for.
+ ... x509.DNSName(u"mysite.com"),
+ ... x509.DNSName(u"www.mysite.com"),
+ ... x509.DNSName(u"subdomain.mysite.com"),
+ ... ]),
+ ... critical=False,
+ ... # Sign the CSR with our private key.
+ ... ).sign(key, hashes.SHA256(), default_backend())
+ >>> # Write our CSR out to disk.
+ >>> with open("path/to/csr.pem", "wb") as f:
+ ... 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"California"),
+ ... 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(
+ ... key.public_key()
+ ... ).serial_number(
+ ... x509.random_serial_number()
+ ... ).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(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.
+
+Determining Certificate or Certificate Signing Request Key Type
+---------------------------------------------------------------
+
+Certificates and certificate signing requests can be issued with multiple
+key types. You can determine what the key type is by using ``isinstance``
+checks:
+
+.. code-block:: pycon
+
+ >>> public_key = cert.public_key()
+ >>> if isinstance(public_key, rsa.RSAPublicKey):
+ ... # Do something RSA specific
+ ... elif isinstance(public_key, ec.EllipticCurvePublicKey):
+ ... # Do something EC specific
+ ... else:
+ ... # Remember to handle this case