prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Make it harder to allow truncation on a GCM tag
  `GCM()` should take a `min_tag_length` parameter, which defaults to `GCM.MAX_TAG_LENGTH`, then we can make it error out on truncated tags by default, while still allowing truncation for use cases that need it.
  
  This is technically a backwards compatibility break, but I argue that it should be allowed as a security hardening measure. Thoughts?
  
  
  </issue>
  <code>
  [start of cryptography/__about__.py]
  1 # Licensed under the Apache License, Version 2.0 (the "License");
  2 # you may not use this file except in compliance with the License.
  3 # You may obtain a copy of the License at
  4 #
  5 #    http://www.apache.org/licenses/LICENSE-2.0
  6 #
  7 # Unless required by applicable law or agreed to in writing, software
  8 # distributed under the License is distributed on an "AS IS" BASIS,
  9 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  10 # implied.
  11 # See the License for the specific language governing permissions and
  12 # limitations under the License.
  13 from __future__ import absolute_import, division, print_function
  14 
  15 __all__ = [
  16     "__title__", "__summary__", "__uri__", "__version__", "__author__",
  17     "__email__", "__license__", "__copyright__",
  18 ]
  19 
  20 __title__ = "cryptography"
  21 __summary__ = ("cryptography is a package which provides cryptographic recipes"
  22                " and primitives to Python developers.")
  23 __uri__ = "https://github.com/pyca/cryptography"
  24 
  25 __version__ = "0.5.dev1"
  26 
  27 __author__ = "The cryptography developers"
  28 __email__ = "cryptography-dev@python.org"
  29 
  30 __license__ = "Apache License, Version 2.0"
  31 __copyright__ = "Copyright 2013-2014 %s" % __author__
  32
  [end of cryptography/__about__.py]
  [start of cryptography/hazmat/primitives/ciphers/modes.py]
  1 # Licensed under the Apache License, Version 2.0 (the "License");
  2 # you may not use this file except in compliance with the License.
  3 # You may obtain a copy of the License at
  4 #
  5 #    http://www.apache.org/licenses/LICENSE-2.0
  6 #
  7 # Unless required by applicable law or agreed to in writing, software
  8 # distributed under the License is distributed on an "AS IS" BASIS,
  9 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  10 # implied.
  11 # See the License for the specific language governing permissions and
  12 # limitations under the License.
  13 
  14 from __future__ import absolute_import, division, print_function
  15 
  16 from cryptography import utils
  17 from cryptography.hazmat.primitives import interfaces
  18 
  19 
  20 def _check_iv_length(mode, algorithm):
  21     if len(mode.initialization_vector) * 8 != algorithm.block_size:
  22         raise ValueError("Invalid IV size ({0}) for {1}.".format(
  23             len(mode.initialization_vector), mode.name
  24         ))
  25 
  26 
  27 @utils.register_interface(interfaces.Mode)
  28 @utils.register_interface(interfaces.ModeWithInitializationVector)
  29 class CBC(object):
  30     name = "CBC"
  31 
  32     def __init__(self, initialization_vector):
  33         self.initialization_vector = initialization_vector
  34 
  35     validate_for_algorithm = _check_iv_length
  36 
  37 
  38 @utils.register_interface(interfaces.Mode)
  39 class ECB(object):
  40     name = "ECB"
  41 
  42     def validate_for_algorithm(self, algorithm):
  43         pass
  44 
  45 
  46 @utils.register_interface(interfaces.Mode)
  47 @utils.register_interface(interfaces.ModeWithInitializationVector)
  48 class OFB(object):
  49     name = "OFB"
  50 
  51     def __init__(self, initialization_vector):
  52         self.initialization_vector = initialization_vector
  53 
  54     validate_for_algorithm = _check_iv_length
  55 
  56 
  57 @utils.register_interface(interfaces.Mode)
  58 @utils.register_interface(interfaces.ModeWithInitializationVector)
  59 class CFB(object):
  60     name = "CFB"
  61 
  62     def __init__(self, initialization_vector):
  63         self.initialization_vector = initialization_vector
  64 
  65     validate_for_algorithm = _check_iv_length
  66 
  67 
  68 @utils.register_interface(interfaces.Mode)
  69 @utils.register_interface(interfaces.ModeWithInitializationVector)
  70 class CFB8(object):
  71     name = "CFB8"
  72 
  73     def __init__(self, initialization_vector):
  74         self.initialization_vector = initialization_vector
  75 
  76     validate_for_algorithm = _check_iv_length
  77 
  78 
  79 @utils.register_interface(interfaces.Mode)
  80 @utils.register_interface(interfaces.ModeWithNonce)
  81 class CTR(object):
  82     name = "CTR"
  83 
  84     def __init__(self, nonce):
  85         self.nonce = nonce
  86 
  87     def validate_for_algorithm(self, algorithm):
  88         if len(self.nonce) * 8 != algorithm.block_size:
  89             raise ValueError("Invalid nonce size ({0}) for {1}.".format(
  90                 len(self.nonce), self.name
  91             ))
  92 
  93 
  94 @utils.register_interface(interfaces.Mode)
  95 @utils.register_interface(interfaces.ModeWithInitializationVector)
  96 @utils.register_interface(interfaces.ModeWithAuthenticationTag)
  97 class GCM(object):
  98     name = "GCM"
  99 
  100     def __init__(self, initialization_vector, tag=None):
  101         # len(initialization_vector) must in [1, 2 ** 64), but it's impossible
  102         # to actually construct a bytes object that large, so we don't check
  103         # for it
  104         if tag is not None and len(tag) < 4:
  105             raise ValueError(
  106                 "Authentication tag must be 4 bytes or longer."
  107             )
  108 
  109         self.initialization_vector = initialization_vector
  110         self.tag = tag
  111 
  112     def validate_for_algorithm(self, algorithm):
  113         pass
  114
  [end of cryptography/hazmat/primitives/ciphers/modes.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/cryptography/__about__.py b/cryptography/__about__.py
  --- a/cryptography/__about__.py
  +++ b/cryptography/__about__.py
  @@ -28,4 +28,4 @@
   __email__ = "cryptography-dev@python.org"
   
   __license__ = "Apache License, Version 2.0"
  -__copyright__ = "Copyright 2013-2014 %s" % __author__
  +__copyright__ = "Copyright 2013-2014 {0}".format(__author__)
  diff --git a/cryptography/hazmat/primitives/ciphers/modes.py b/cryptography/hazmat/primitives/ciphers/modes.py
  --- a/cryptography/hazmat/primitives/ciphers/modes.py
  +++ b/cryptography/hazmat/primitives/ciphers/modes.py
  @@ -97,13 +97,16 @@
   class GCM(object):
       name = "GCM"
   
  -    def __init__(self, initialization_vector, tag=None):
  +    def __init__(self, initialization_vector, tag=None, min_tag_length=16):
           # len(initialization_vector) must in [1, 2 ** 64), but it's impossible
           # to actually construct a bytes object that large, so we don't check
           # for it
  -        if tag is not None and len(tag) < 4:
  +        if min_tag_length < 4:
  +            raise ValueError("min_tag_length must be >= 4")
  +        if tag is not None and len(tag) < min_tag_length:
               raise ValueError(
  -                "Authentication tag must be 4 bytes or longer."
  +                "Authentication tag must be {0} bytes or longer.".format(
  +                    min_tag_length)
               )
   
           self.initialization_vector = initialization_vector
  
verification_info: {"golden_diff": "diff --git a/cryptography/__about__.py b/cryptography/__about__.py\n--- a/cryptography/__about__.py\n+++ b/cryptography/__about__.py\n@@ -28,4 +28,4 @@\n __email__ = \"cryptography-dev@python.org\"\n \n __license__ = \"Apache License, Version 2.0\"\n-__copyright__ = \"Copyright 2013-2014 %s\" % __author__\n+__copyright__ = \"Copyright 2013-2014 {0}\".format(__author__)\ndiff --git a/cryptography/hazmat/primitives/ciphers/modes.py b/cryptography/hazmat/primitives/ciphers/modes.py\n--- a/cryptography/hazmat/primitives/ciphers/modes.py\n+++ b/cryptography/hazmat/primitives/ciphers/modes.py\n@@ -97,13 +97,16 @@\n class GCM(object):\n     name = \"GCM\"\n \n-    def __init__(self, initialization_vector, tag=None):\n+    def __init__(self, initialization_vector, tag=None, min_tag_length=16):\n         # len(initialization_vector) must in [1, 2 ** 64), but it's impossible\n         # to actually construct a bytes object that large, so we don't check\n         # for it\n-        if tag is not None and len(tag) < 4:\n+        if min_tag_length < 4:\n+            raise ValueError(\"min_tag_length must be >= 4\")\n+        if tag is not None and len(tag) < min_tag_length:\n             raise ValueError(\n-                \"Authentication tag must be 4 bytes or longer.\"\n+                \"Authentication tag must be {0} bytes or longer.\".format(\n+                    min_tag_length)\n             )\n \n         self.initialization_vector = initialization_vector\n", "issue": "Make it harder to allow truncation on a GCM tag\n`GCM()` should take a `min_tag_length` parameter, which defaults to `GCM.MAX_TAG_LENGTH`, then we can make it error out on truncated tags by default, while still allowing truncation for use cases that need it.\n\nThis is technically a backwards compatibility break, but I argue that it should be allowed as a security hardening measure. Thoughts?\n\n", "before_files": [{"content": "# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n# implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom __future__ import absolute_import, division, print_function\n\n__all__ = [\n    \"__title__\", \"__summary__\", \"__uri__\", \"__version__\", \"__author__\",\n    \"__email__\", \"__license__\", \"__copyright__\",\n]\n\n__title__ = \"cryptography\"\n__summary__ = (\"cryptography is a package which provides cryptographic recipes\"\n               \" and primitives to Python developers.\")\n__uri__ = \"https://github.com/pyca/cryptography\"\n\n__version__ = \"0.5.dev1\"\n\n__author__ = \"The cryptography developers\"\n__email__ = \"cryptography-dev@python.org\"\n\n__license__ = \"Apache License, Version 2.0\"\n__copyright__ = \"Copyright 2013-2014 %s\" % __author__\n", "path": "cryptography/__about__.py"}, {"content": "# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n# implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom __future__ import absolute_import, division, print_function\n\nfrom cryptography import utils\nfrom cryptography.hazmat.primitives import interfaces\n\n\ndef _check_iv_length(mode, algorithm):\n    if len(mode.initialization_vector) * 8 != algorithm.block_size:\n        raise ValueError(\"Invalid IV size ({0}) for {1}.\".format(\n            len(mode.initialization_vector), mode.name\n        ))\n\n\n@utils.register_interface(interfaces.Mode)\n@utils.register_interface(interfaces.ModeWithInitializationVector)\nclass CBC(object):\n    name = \"CBC\"\n\n    def __init__(self, initialization_vector):\n        self.initialization_vector = initialization_vector\n\n    validate_for_algorithm = _check_iv_length\n\n\n@utils.register_interface(interfaces.Mode)\nclass ECB(object):\n    name = \"ECB\"\n\n    def validate_for_algorithm(self, algorithm):\n        pass\n\n\n@utils.register_interface(interfaces.Mode)\n@utils.register_interface(interfaces.ModeWithInitializationVector)\nclass OFB(object):\n    name = \"OFB\"\n\n    def __init__(self, initialization_vector):\n        self.initialization_vector = initialization_vector\n\n    validate_for_algorithm = _check_iv_length\n\n\n@utils.register_interface(interfaces.Mode)\n@utils.register_interface(interfaces.ModeWithInitializationVector)\nclass CFB(object):\n    name = \"CFB\"\n\n    def __init__(self, initialization_vector):\n        self.initialization_vector = initialization_vector\n\n    validate_for_algorithm = _check_iv_length\n\n\n@utils.register_interface(interfaces.Mode)\n@utils.register_interface(interfaces.ModeWithInitializationVector)\nclass CFB8(object):\n    name = \"CFB8\"\n\n    def __init__(self, initialization_vector):\n        self.initialization_vector = initialization_vector\n\n    validate_for_algorithm = _check_iv_length\n\n\n@utils.register_interface(interfaces.Mode)\n@utils.register_interface(interfaces.ModeWithNonce)\nclass CTR(object):\n    name = \"CTR\"\n\n    def __init__(self, nonce):\n        self.nonce = nonce\n\n    def validate_for_algorithm(self, algorithm):\n        if len(self.nonce) * 8 != algorithm.block_size:\n            raise ValueError(\"Invalid nonce size ({0}) for {1}.\".format(\n                len(self.nonce), self.name\n            ))\n\n\n@utils.register_interface(interfaces.Mode)\n@utils.register_interface(interfaces.ModeWithInitializationVector)\n@utils.register_interface(interfaces.ModeWithAuthenticationTag)\nclass GCM(object):\n    name = \"GCM\"\n\n    def __init__(self, initialization_vector, tag=None):\n        # len(initialization_vector) must in [1, 2 ** 64), but it's impossible\n        # to actually construct a bytes object that large, so we don't check\n        # for it\n        if tag is not None and len(tag) < 4:\n            raise ValueError(\n                \"Authentication tag must be 4 bytes or longer.\"\n            )\n\n        self.initialization_vector = initialization_vector\n        self.tag = tag\n\n    def validate_for_algorithm(self, algorithm):\n        pass\n", "path": "cryptography/hazmat/primitives/ciphers/modes.py"}]}