- Always make a new branch for your work.
- Patches should be small to facilitate easier review. Studies have shown that review quality falls off as patch size grows. Sometimes this will result in many small PRs to land a single large feature.
- Larger changes should be discussed on our mailing list before submission.
- New features and significant bug fixes should be documented in the Changelog.
- You must have legal permission to distribute any code you contribute to
cryptography, and it must be available under both the BSD and Apache Software License Version 2.0 licenses.
If you believe you’ve identified a security issue in
follow the directions on the security page.
When in doubt, refer to PEP 8 for Python code. You can check if your code
meets our automated requirements by formatting it with
black and running
flake8 against it. If you’ve installed the development requirements this
will automatically use our configuration. You can also run the
tox job with
tox -e pep8.
Class names which contains acronyms or initialisms should always be
capitalized. A class should be named
Every code file must start with the boilerplate licensing notice:
# 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.
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
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:
If it is necessary to compare a user provided value with a computed value (for example, verifying a signature), there should be an API provided that performs the verification in a secure way (for example, using a constant time comparison), rather than requiring the user to perform the comparison themselves.
If it is incorrect to ignore the result of a method, it should raise an
exception, and not return a boolean
False flag. For example, a
method to verify a signature should raise
InvalidSignature, and not return
whether the signature was valid.
# This is bad. def verify(sig): # ... return is_valid # Good! def verify(sig): # ... if not is_valid: raise InvalidSignature
Every recipe should include a version or algorithmic marker of some sort in its output in order to allow transparent upgrading of the algorithms in use, as the algorithms or parameters needed to achieve a given security margin evolve.
All code changes must be accompanied by unit tests with 100% code coverage (as measured by the combined metrics across our build matrix).
When implementing a new primitive or recipe
cryptography requires that you
provide a set of test vectors. See Test vectors for more
All features should be documented with prose in the
docs section. To ensure
it builds and passes doc8 style checks you can run
tox -e docs.
Because of the inherent challenges in implementing correct cryptographic systems, we want to make our documentation point people in the right directions as much as possible. To that end:
- When documenting a generic interface, use a strong algorithm in examples.
(e.g. when showing a hashing example, don’t use
- When giving prescriptive advice, always provide references and supporting material.
- When there is real disagreement between cryptographic experts, represent both sides of the argument and describe the trade-offs clearly.
When documenting a new module in the
hazmat package, its documentation
should begin with the “Hazardous Materials” warning:
Always prefer terminology that is most broadly accepted. For example:
- When referring to class instances use “an instance of
Foo” instead of “a
When referring to a hypothetical individual (such as “a person receiving an encrypted message”) use gender neutral pronouns (they/them/their).
Docstrings are typically only used when writing abstract classes, but should be written like this if required:
def some_function(some_arg): """ Does some things. :param some_arg: Some argument. """
- Always use three double quotes.
- Put the three double quotes on their own line.
- No blank line at the end.
- Use Sphinx parameter/attribute documentation syntax.