Alex Stapleton | c5fffd3 | 2014-03-18 15:29:00 +0000 | [diff] [blame] | 1 | Submitting patches |
Paul Kehrer | 0839aa8 | 2014-02-11 22:36:51 -0600 | [diff] [blame] | 2 | ================== |
| 3 | |
| 4 | * Always make a new branch for your work. |
| 5 | * Patches should be small to facilitate easier review. `Studies have shown`_ |
| 6 | that review quality falls off as patch size grows. Sometimes this will result |
| 7 | in many small PRs to land a single large feature. |
| 8 | * Larger changes should be discussed on `our mailing list`_ before submission. |
| 9 | * New features and significant bug fixes should be documented in the |
| 10 | :doc:`/changelog`. |
| 11 | |
| 12 | If you believe you've identified a security issue in ``cryptography``, please |
| 13 | follow the directions on the :doc:`security page </security>`. |
| 14 | |
| 15 | Code |
| 16 | ---- |
| 17 | |
Paul Kehrer | 5b6ce2a | 2014-02-24 20:16:10 -0600 | [diff] [blame] | 18 | When in doubt, refer to :pep:`8` for Python code. You can check if your code |
| 19 | meets our automated requirements by running ``flake8`` against it. If you've |
| 20 | installed the development requirements this will automatically use our |
| 21 | configuration. You can also run the ``tox`` job with ``tox -e pep8``. |
Paul Kehrer | 0839aa8 | 2014-02-11 22:36:51 -0600 | [diff] [blame] | 22 | |
| 23 | `Write comments as complete sentences.`_ |
| 24 | |
| 25 | Every code file must start with the boilerplate notice of the Apache License. |
| 26 | Additionally, every Python code file must contain |
| 27 | |
| 28 | .. code-block:: python |
| 29 | |
| 30 | from __future__ import absolute_import, division, print_function |
| 31 | |
Alex Stapleton | c5fffd3 | 2014-03-18 15:29:00 +0000 | [diff] [blame] | 32 | API considerations |
Paul Kehrer | 0839aa8 | 2014-02-11 22:36:51 -0600 | [diff] [blame] | 33 | ~~~~~~~~~~~~~~~~~~ |
| 34 | |
| 35 | Most projects' APIs are designed with a philosophy of "make easy things easy, |
| 36 | and make hard things possible". One of the perils of writing cryptographic code |
| 37 | is that secure code looks just like insecure code, and its results are almost |
| 38 | always indistinguishable. As a result ``cryptography`` has, as a design |
| 39 | philosophy: "make it hard to do insecure things". Here are a few strategies for |
| 40 | API design that should be both followed, and should inspire other API choices: |
| 41 | |
| 42 | If it is necessary to compare a user provided value with a computed value (for |
| 43 | example, verifying a signature), there should be an API provided that performs |
| 44 | the verification in a secure way (for example, using a constant time |
| 45 | comparison), rather than requiring the user to perform the comparison |
| 46 | themselves. |
| 47 | |
| 48 | If it is incorrect to ignore the result of a method, it should raise an |
| 49 | exception, and not return a boolean ``True``/``False`` flag. For example, a |
| 50 | method to verify a signature should raise ``InvalidSignature``, and not return |
| 51 | whether the signature was valid. |
| 52 | |
| 53 | .. code-block:: python |
| 54 | |
| 55 | # This is bad. |
| 56 | def verify(sig): |
| 57 | # ... |
| 58 | return is_valid |
| 59 | |
| 60 | # Good! |
| 61 | def verify(sig): |
| 62 | # ... |
| 63 | if not is_valid: |
| 64 | raise InvalidSignature |
| 65 | |
| 66 | Every recipe should include a version or algorithmic marker of some sort in its |
| 67 | output in order to allow transparent upgrading of the algorithms in use, as |
| 68 | the algorithms or parameters needed to achieve a given security margin evolve. |
| 69 | |
| 70 | APIs at the :doc:`/hazmat/primitives/index` layer should always take an |
| 71 | explicit backend, APIs at the recipes layer should automatically use the |
| 72 | :func:`~cryptography.hazmat.backends.default_backend`, but optionally allow |
| 73 | specifying a different backend. |
| 74 | |
| 75 | C bindings |
| 76 | ~~~~~~~~~~ |
| 77 | |
| 78 | When binding C code with ``cffi`` we have our own style guide, it's pretty |
| 79 | simple. |
| 80 | |
| 81 | Don't name parameters: |
| 82 | |
| 83 | .. code-block:: c |
| 84 | |
| 85 | // Good |
| 86 | long f(long); |
| 87 | // Bad |
| 88 | long f(long x); |
| 89 | |
| 90 | ...unless they're inside a struct: |
| 91 | |
| 92 | .. code-block:: c |
| 93 | |
| 94 | struct my_struct { |
| 95 | char *name; |
| 96 | int number; |
| 97 | ...; |
| 98 | }; |
| 99 | |
| 100 | Include ``void`` if the function takes no arguments: |
| 101 | |
| 102 | .. code-block:: c |
| 103 | |
| 104 | // Good |
| 105 | long f(void); |
| 106 | // Bad |
| 107 | long f(); |
| 108 | |
| 109 | Wrap lines at 80 characters like so: |
| 110 | |
| 111 | .. code-block:: c |
| 112 | |
| 113 | // Pretend this went to 80 characters |
| 114 | long f(long, long, |
| 115 | int *) |
| 116 | |
| 117 | Include a space after commas between parameters: |
| 118 | |
| 119 | .. code-block:: c |
| 120 | |
| 121 | // Good |
| 122 | long f(int, char *) |
| 123 | // Bad |
| 124 | long f(int,char *) |
| 125 | |
| 126 | Values set by ``#define`` should be assigned the appropriate type. If you see |
| 127 | this: |
| 128 | |
| 129 | .. code-block:: c |
| 130 | |
| 131 | #define SOME_INTEGER_LITERAL 0x0; |
| 132 | #define SOME_UNSIGNED_INTEGER_LITERAL 0x0001U; |
| 133 | #define SOME_STRING_LITERAL "hello"; |
| 134 | |
| 135 | ...it should be added to the bindings like so: |
| 136 | |
| 137 | .. code-block:: c |
| 138 | |
| 139 | static const int SOME_INTEGER_LITERAL; |
| 140 | static const unsigned int SOME_UNSIGNED_INTEGER_LITERAL; |
| 141 | static const char *const SOME_STRING_LITERAL; |
| 142 | |
| 143 | Tests |
| 144 | ----- |
| 145 | |
| 146 | All code changes must be accompanied by unit tests with 100% code coverage (as |
| 147 | measured by the combined metrics across our build matrix). |
| 148 | |
| 149 | When implementing a new primitive or recipe ``cryptography`` requires that you |
Paul Kehrer | 1681a69 | 2014-02-11 23:43:51 -0600 | [diff] [blame] | 150 | provide a set of test vectors. See :doc:`/development/test-vectors` for more |
| 151 | details. |
Paul Kehrer | 0839aa8 | 2014-02-11 22:36:51 -0600 | [diff] [blame] | 152 | |
| 153 | Documentation |
| 154 | ------------- |
| 155 | |
Paul Kehrer | 813b294 | 2014-06-05 12:40:56 -0500 | [diff] [blame^] | 156 | All features should be documented with prose in the ``docs`` section. To ensure |
| 157 | it builds and passes `doc8`_ style checks you can run ``tox -e docs``. |
Paul Kehrer | 0839aa8 | 2014-02-11 22:36:51 -0600 | [diff] [blame] | 158 | |
| 159 | Because of the inherent challenges in implementing correct cryptographic |
| 160 | systems, we want to make our documentation point people in the right directions |
| 161 | as much as possible. To that end: |
| 162 | |
| 163 | * When documenting a generic interface, use a strong algorithm in examples. |
| 164 | (e.g. when showing a hashing example, don't use |
| 165 | :class:`~cryptography.hazmat.primitives.hashes.MD5`) |
| 166 | * When giving prescriptive advice, always provide references and supporting |
| 167 | material. |
| 168 | * When there is real disagreement between cryptographic experts, represent both |
| 169 | sides of the argument and describe the trade-offs clearly. |
| 170 | |
| 171 | When documenting a new module in the ``hazmat`` package, its documentation |
| 172 | should begin with the "Hazardous Materials" warning: |
| 173 | |
| 174 | .. code-block:: rest |
| 175 | |
| 176 | .. hazmat:: |
| 177 | |
| 178 | When referring to a hypothetical individual (such as "a person receiving an |
| 179 | encrypted message") use gender neutral pronouns (they/them/their). |
| 180 | |
| 181 | Docstrings are typically only used when writing abstract classes, but should |
| 182 | be written like this if required: |
| 183 | |
| 184 | .. code-block:: python |
| 185 | |
| 186 | def some_function(some_arg): |
| 187 | """ |
| 188 | Does some things. |
| 189 | |
| 190 | :param some_arg: Some argument. |
| 191 | """ |
| 192 | |
| 193 | So, specifically: |
| 194 | |
| 195 | * Always use three double quotes. |
| 196 | * Put the three double quotes on their own line. |
| 197 | * No blank line at the end. |
| 198 | * Use Sphinx parameter/attribute documentation `syntax`_. |
| 199 | |
| 200 | |
| 201 | .. _`Write comments as complete sentences.`: http://nedbatchelder.com/blog/201401/comments_should_be_sentences.html |
| 202 | .. _`syntax`: http://sphinx-doc.org/domains.html#info-field-lists |
| 203 | .. _`Studies have shown`: http://www.ibm.com/developerworks/rational/library/11-proven-practices-for-peer-review/ |
| 204 | .. _`our mailing list`: https://mail.python.org/mailman/listinfo/cryptography-dev |
Paul Kehrer | 813b294 | 2014-06-05 12:40:56 -0500 | [diff] [blame^] | 205 | .. _`doc8`: https://github.com/stackforge/doc8 |