diff --git a/.travis.yml b/.travis.yml
index 456aba7..bbcb336 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -30,6 +30,7 @@ matrix:
       env: TOXENV=pypy CC=clang
     - python: 2.7
       env: TOXENV=pep8
+    - env: TOXENV=packaging
     - python: 3.5
       env: TOXENV=py3pep8
     - language: generic
diff --git a/MANIFEST.in b/MANIFEST.in
index 622d66b..93a4480 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,3 +1,11 @@
 include LICENSE README.rst
+
+include tox.ini .coveragerc
 include src/build_bcrypt.py
+
 recursive-include src/_csrc *
+recursive-include tests *.py
+
+exclude requirements.txt tasks.py .travis.yml
+
+prune .travis
diff --git a/README.rst b/README.rst
index 0883286..3859bb8 100644
--- a/README.rst
+++ b/README.rst
@@ -40,6 +40,7 @@ Changelog
 3.1.0
 -----
 * Added support for ``checkpw`` as another method of verifying a password.
+* Ensure that you get a ``$2y$`` hash when you input a ``$2y$`` salt.
 
 3.0.0
 -----
@@ -104,7 +105,7 @@ the work factor merely pass the desired number of rounds to
     >>> hashed = bcrypt.hashpw(password, bcrypt.gensalt(14))
     >>> # Check that a unhashed password matches one that has previously been
     >>> #   hashed
-    >>> if bcrypt.hashpw(password, hashed) == hashed:
+    >>> if bcrypt.checkpw(password, hashed):
     ...     print("It Matches!")
     ... else:
     ...     print("It Does not Match :(")
diff --git a/src/bcrypt/__init__.py b/src/bcrypt/__init__.py
index d6acb84..abc9d75 100644
--- a/src/bcrypt/__init__.py
+++ b/src/bcrypt/__init__.py
@@ -39,10 +39,6 @@ __all__ = [
 _normalize_re = re.compile(b"^\$2y\$")
 
 
-def _normalize_prefix(salt):
-    return _normalize_re.sub(b"$2b$", salt)
-
-
 def gensalt(rounds=12, prefix=b"2b"):
     if prefix not in (b"2a", b"2b"):
         raise ValueError("Supported prefixes are b'2a' or b'2b'")
@@ -75,7 +71,13 @@ def hashpw(password, salt):
     # on $2a$, so we do it here to preserve compatibility with 2.0.0
     password = password[:72]
 
-    salt = _normalize_prefix(salt)
+    # When the original 8bit bug was found the original library we supported
+    # added a new prefix, $2y$, that fixes it. This prefix is exactly the same
+    # as the $2b$ prefix added by OpenBSD other than the name. Since the
+    # OpenBSD library does not support the $2y$ prefix, if the salt given to us
+    # is for the $2y$ prefix, we'll just mugne it so that it's a $2b$ prior to
+    # passing it into the C library.
+    original_salt, salt = salt, _normalize_re.sub(b"$2b$", salt)
 
     hashed = _bcrypt.ffi.new("unsigned char[]", 128)
     retval = _bcrypt.lib.bcrypt_hashpass(password, salt, hashed, len(hashed))
@@ -83,7 +85,13 @@ def hashpw(password, salt):
     if retval != 0:
         raise ValueError("Invalid salt")
 
-    return _bcrypt.ffi.string(hashed)
+    # Now that we've gotten our hashed password, we want to ensure that the
+    # prefix we return is the one that was passed in, so we'll use the prefix
+    # from the original salt and concatenate that with the return value (minus
+    # the return value's prefix). This will ensure that if someone passed in a
+    # salt with a $2y$ prefix, that they get back a hash with a $2y$ prefix
+    # even though we munged it to $2b$.
+    return original_salt[:4] + _bcrypt.ffi.string(hashed)[4:]
 
 
 def checkpw(password, hashed_password):
@@ -96,9 +104,6 @@ def checkpw(password, hashed_password):
             "password and hashed_password may not contain NUL bytes"
         )
 
-    # If the user supplies a $2y$ prefix we normalize to $2b$
-    hashed_password = _normalize_prefix(hashed_password)
-
     ret = hashpw(password, hashed_password)
 
     return _bcrypt.lib.timingsafe_bcmp(ret, hashed_password, len(ret)) == 0
diff --git a/tox.ini b/tox.ini
index abc6283..264d9aa 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
 [tox]
-envlist = py26,py27,pypy,py33,py34,py35,pep8,py3pep8
+envlist = py26,py27,pypy,py33,py34,py35,pep8,py3pep8,packaging
 
 [testenv]
 # If you add a new dep here you probably need to add it in setup.py as well
@@ -27,6 +27,15 @@ deps =
 commands =
     flake8 .
 
+[testenv:packaging]
+deps =
+    check-manifest
+    readme_renderer
+commands =
+    check-manifest
+    python setup.py check --metadata --restructuredtext --strict
+
+
 [flake8]
 exclude = .tox,*.egg
 select = E,W,F,N,I

diff --git a/tests/test_bcrypt.py b/tests/test_bcrypt.py
index 47f315a..d9bde72 100644
--- a/tests/test_bcrypt.py
+++ b/tests/test_bcrypt.py
@@ -152,12 +152,12 @@ _2y_test_vectors = [
     (
         b"\xa3",
         b"$2y$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq",
-        b"$2b$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq",
+        b"$2y$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq",
     ),
     (
         b"\xff\xff\xa3",
         b"$2y$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e",
-        b"$2b$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e",
+        b"$2y$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e",
     ),
 ]
 

Find a way to not use == in the README
I don't think it's actually exploitable as a timing attack (in fact I'm pretty sure it's not), but I think it'd be good hygeine to offer a check_password function or similar and use that, so we dont' have to expose a general purpose constant time comparison function.
tests/test_bcrypt.py::test_hashpw_2y_prefix[\xa3-$2y$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq-$2y$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq] tests/test_bcrypt.py::test_hashpw_2y_prefix[\xff\xff\xa3-$2y$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e-$2y$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e]
tests/test_bcrypt.py::test_gensalt_basic tests/test_bcrypt.py::test_gensalt_rounds_valid[4-$2b$04$KB.uKB.uKB.uKB.uKB.uK.] tests/test_bcrypt.py::test_gensalt_rounds_valid[5-$2b$05$KB.uKB.uKB.uKB.uKB.uK.] tests/test_bcrypt.py::test_gensalt_rounds_valid[6-$2b$06$KB.uKB.uKB.uKB.uKB.uK.] tests/test_bcrypt.py::test_gensalt_rounds_valid[7-$2b$07$KB.uKB.uKB.uKB.uKB.uK.] tests/test_bcrypt.py::test_gensalt_rounds_valid[8-$2b$08$KB.uKB.uKB.uKB.uKB.uK.] tests/test_bcrypt.py::test_gensalt_rounds_valid[9-$2b$09$KB.uKB.uKB.uKB.uKB.uK.] tests/test_bcrypt.py::test_gensalt_rounds_valid[10-$2b$10$KB.uKB.uKB.uKB.uKB.uK.] tests/test_bcrypt.py::test_gensalt_rounds_valid[11-$2b$11$KB.uKB.uKB.uKB.uKB.uK.] tests/test_bcrypt.py::test_gensalt_rounds_valid[12-$2b$12$KB.uKB.uKB.uKB.uKB.uK.] tests/test_bcrypt.py::test_gensalt_rounds_valid[13-$2b$13$KB.uKB.uKB.uKB.uKB.uK.] tests/test_bcrypt.py::test_gensalt_rounds_valid[14-$2b$14$KB.uKB.uKB.uKB.uKB.uK.] tests/test_bcrypt.py::test_gensalt_rounds_valid[15-$2b$15$KB.uKB.uKB.uKB.uKB.uK.] tests/test_bcrypt.py::test_gensalt_rounds_valid[16-$2b$16$KB.uKB.uKB.uKB.uKB.uK.] tests/test_bcrypt.py::test_gensalt_rounds_valid[17-$2b$17$KB.uKB.uKB.uKB.uKB.uK.] tests/test_bcrypt.py::test_gensalt_rounds_valid[18-$2b$18$KB.uKB.uKB.uKB.uKB.uK.] tests/test_bcrypt.py::test_gensalt_rounds_valid[19-$2b$19$KB.uKB.uKB.uKB.uKB.uK.] tests/test_bcrypt.py::test_gensalt_rounds_valid[20-$2b$20$KB.uKB.uKB.uKB.uKB.uK.] tests/test_bcrypt.py::test_gensalt_rounds_valid[21-$2b$21$KB.uKB.uKB.uKB.uKB.uK.] tests/test_bcrypt.py::test_gensalt_rounds_valid[22-$2b$22$KB.uKB.uKB.uKB.uKB.uK.] tests/test_bcrypt.py::test_gensalt_rounds_valid[23-$2b$23$KB.uKB.uKB.uKB.uKB.uK.] tests/test_bcrypt.py::test_gensalt_rounds_valid[24-$2b$24$KB.uKB.uKB.uKB.uKB.uK.] tests/test_bcrypt.py::test_gensalt_rounds_invalid[1] tests/test_bcrypt.py::test_gensalt_rounds_invalid[2] tests/test_bcrypt.py::test_gensalt_rounds_invalid[3] tests/test_bcrypt.py::test_gensalt_bad_prefix tests/test_bcrypt.py::test_gensalt_2a_prefix tests/test_bcrypt.py::test_hashpw_new[Kk4DQuMMfZL9o-$2b$04$cVWp4XaNU8a4v1uMRum2SO-$2b$04$cVWp4XaNU8a4v1uMRum2SO026BWLIoQMD/TXg5uZV.0P.uO8m3YEm] tests/test_bcrypt.py::test_hashpw_new[9IeRXmnGxMYbs-$2b$04$pQ7gRO7e6wx/936oXhNjrO-$2b$04$pQ7gRO7e6wx/936oXhNjrOUNOHL1D0h1N2IDbJZYs.1ppzSof6SPy] tests/test_bcrypt.py::test_hashpw_new[xVQVbwa1S0M8r-$2b$04$SQe9knOzepOVKoYXo9xTte-$2b$04$SQe9knOzepOVKoYXo9xTteNYr6MBwVz4tpriJVe3PNgYufGIsgKcW] tests/test_bcrypt.py::test_hashpw_new[Zfgr26LWd22Za-$2b$04$eH8zX.q5Q.j2hO1NkVYJQO-$2b$04$eH8zX.q5Q.j2hO1NkVYJQOM6KxntS/ow3.YzVmFrE4t//CoF4fvne] tests/test_bcrypt.py::test_hashpw_new[Tg4daC27epFBE-$2b$04$ahiTdwRXpUG2JLRcIznxc.-$2b$04$ahiTdwRXpUG2JLRcIznxc.s1.ydaPGD372bsGs8NqyYjLY1inG5n2] tests/test_bcrypt.py::test_hashpw_new[xhQPMmwh5ALzW-$2b$04$nQn78dV0hGHf5wUBe0zOFu-$2b$04$nQn78dV0hGHf5wUBe0zOFu8n07ZbWWOKoGasZKRspZxtt.vBRNMIy] tests/test_bcrypt.py::test_hashpw_new[59je8h5Gj71tg-$2b$04$cvXudZ5ugTg95W.rOjMITu-$2b$04$cvXudZ5ugTg95W.rOjMITuM1jC0piCl3zF5cmGhzCibHZrNHkmckG] tests/test_bcrypt.py::test_hashpw_new[wT4fHJa2N9WSW-$2b$04$YYjtiq4Uh88yUsExO0RNTu-$2b$04$YYjtiq4Uh88yUsExO0RNTuEJ.tZlsONac16A8OcLHleWFjVawfGvO] tests/test_bcrypt.py::test_hashpw_new[uSgFRnQdOgm4S-$2b$04$WLTjgY/pZSyqX/fbMbJzf.-$2b$04$WLTjgY/pZSyqX/fbMbJzf.qxCeTMQOzgL.CimRjMHtMxd/VGKojMu] tests/test_bcrypt.py::test_hashpw_new[tEPtJZXur16Vg-$2b$04$2moPs/x/wnCfeQ5pCheMcu-$2b$04$2moPs/x/wnCfeQ5pCheMcuSJQ/KYjOZG780UjA/SiR.KsYWNrC7SG] tests/test_bcrypt.py::test_hashpw_new[vvho8C6nlVf9K-$2b$04$HrEYC/AQ2HS77G78cQDZQ.-$2b$04$HrEYC/AQ2HS77G78cQDZQ.r44WGcruKw03KHlnp71yVQEwpsi3xl2] tests/test_bcrypt.py::test_hashpw_new[5auCCY9by0Ruf-$2b$04$vVYgSTfB8KVbmhbZE/k3R.-$2b$04$vVYgSTfB8KVbmhbZE/k3R.ux9A0lJUM4CZwCkHI9fifke2.rTF7MG] tests/test_bcrypt.py::test_hashpw_new[GtTkR6qn2QOZW-$2b$04$JfoNrR8.doieoI8..F.C1O-$2b$04$JfoNrR8.doieoI8..F.C1OQgwE3uTeuardy6lw0AjALUzOARoyf2m] tests/test_bcrypt.py::test_hashpw_new[zKo8vdFSnjX0f-$2b$04$HP3I0PUs7KBEzMBNFw7o3O-$2b$04$HP3I0PUs7KBEzMBNFw7o3O7f/uxaZU7aaDot1quHMgB2yrwBXsgyy] tests/test_bcrypt.py::test_hashpw_new[I9VfYlacJiwiK-$2b$04$xnFVhJsTzsFBTeP3PpgbMe-$2b$04$xnFVhJsTzsFBTeP3PpgbMeMREb6rdKV9faW54Sx.yg9plf4jY8qT6] tests/test_bcrypt.py::test_hashpw_new[VFPO7YXnHQbQO-$2b$04$WQp9.igoLqVr6Qk70mz6xu-$2b$04$WQp9.igoLqVr6Qk70mz6xuRxE0RttVXXdukpR9N54x17ecad34ZF6] tests/test_bcrypt.py::test_hashpw_new[VDx5BdxfxstYk-$2b$04$xgZtlonpAHSU/njOCdKztO-$2b$04$xgZtlonpAHSU/njOCdKztOPuPFzCNVpB4LGicO4/OGgHv.uKHkwsS] tests/test_bcrypt.py::test_hashpw_new[dEe6XfVGrrfSH-$2b$04$2Siw3Nv3Q/gTOIPetAyPr.-$2b$04$2Siw3Nv3Q/gTOIPetAyPr.GNj3aO0lb1E5E9UumYGKjP9BYqlNWJe] tests/test_bcrypt.py::test_hashpw_new[cTT0EAFdwJiLn-$2b$04$7/Qj7Kd8BcSahPO4khB8me-$2b$04$7/Qj7Kd8BcSahPO4khB8me4ssDJCW3r4OGYqPF87jxtrSyPj5cS5m] tests/test_bcrypt.py::test_hashpw_new[J8eHUDuxBB520-$2b$04$VvlCUKbTMjaxaYJ.k5juoe-$2b$04$VvlCUKbTMjaxaYJ.k5juoecpG/7IzcH1AkmqKi.lIZMVIOLClWAk.] tests/test_bcrypt.py::test_hashpw_new[U*U-$2a$05$CCCCCCCCCCCCCCCCCCCCC.-$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW] tests/test_bcrypt.py::test_hashpw_new[U*U*-$2a$05$CCCCCCCCCCCCCCCCCCCCC.-$2a$05$CCCCCCCCCCCCCCCCCCCCC.VGOzA784oUp/Z0DY336zx7pLYAy0lwK] tests/test_bcrypt.py::test_hashpw_new[U*U*U-$2a$05$XXXXXXXXXXXXXXXXXXXXXO-$2a$05$XXXXXXXXXXXXXXXXXXXXXOAcXxm9kjPGEMsLznoKqmqw7tc8WCx4a] tests/test_bcrypt.py::test_hashpw_new[0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789chars tests/test_bcrypt.py::test_hashpw_new[\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaachars tests/test_bcrypt.py::test_hashpw_new[\xa3-$2a$05$/OK.fbVrR/bpIqNJ5ianF.-$2a$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq] tests/test_bcrypt.py::test_checkpw[Kk4DQuMMfZL9o-$2b$04$cVWp4XaNU8a4v1uMRum2SO-$2b$04$cVWp4XaNU8a4v1uMRum2SO026BWLIoQMD/TXg5uZV.0P.uO8m3YEm] tests/test_bcrypt.py::test_checkpw[9IeRXmnGxMYbs-$2b$04$pQ7gRO7e6wx/936oXhNjrO-$2b$04$pQ7gRO7e6wx/936oXhNjrOUNOHL1D0h1N2IDbJZYs.1ppzSof6SPy] tests/test_bcrypt.py::test_checkpw[xVQVbwa1S0M8r-$2b$04$SQe9knOzepOVKoYXo9xTte-$2b$04$SQe9knOzepOVKoYXo9xTteNYr6MBwVz4tpriJVe3PNgYufGIsgKcW] tests/test_bcrypt.py::test_checkpw[Zfgr26LWd22Za-$2b$04$eH8zX.q5Q.j2hO1NkVYJQO-$2b$04$eH8zX.q5Q.j2hO1NkVYJQOM6KxntS/ow3.YzVmFrE4t//CoF4fvne] tests/test_bcrypt.py::test_checkpw[Tg4daC27epFBE-$2b$04$ahiTdwRXpUG2JLRcIznxc.-$2b$04$ahiTdwRXpUG2JLRcIznxc.s1.ydaPGD372bsGs8NqyYjLY1inG5n2] tests/test_bcrypt.py::test_checkpw[xhQPMmwh5ALzW-$2b$04$nQn78dV0hGHf5wUBe0zOFu-$2b$04$nQn78dV0hGHf5wUBe0zOFu8n07ZbWWOKoGasZKRspZxtt.vBRNMIy] tests/test_bcrypt.py::test_checkpw[59je8h5Gj71tg-$2b$04$cvXudZ5ugTg95W.rOjMITu-$2b$04$cvXudZ5ugTg95W.rOjMITuM1jC0piCl3zF5cmGhzCibHZrNHkmckG] tests/test_bcrypt.py::test_checkpw[wT4fHJa2N9WSW-$2b$04$YYjtiq4Uh88yUsExO0RNTu-$2b$04$YYjtiq4Uh88yUsExO0RNTuEJ.tZlsONac16A8OcLHleWFjVawfGvO] tests/test_bcrypt.py::test_checkpw[uSgFRnQdOgm4S-$2b$04$WLTjgY/pZSyqX/fbMbJzf.-$2b$04$WLTjgY/pZSyqX/fbMbJzf.qxCeTMQOzgL.CimRjMHtMxd/VGKojMu] tests/test_bcrypt.py::test_checkpw[tEPtJZXur16Vg-$2b$04$2moPs/x/wnCfeQ5pCheMcu-$2b$04$2moPs/x/wnCfeQ5pCheMcuSJQ/KYjOZG780UjA/SiR.KsYWNrC7SG] tests/test_bcrypt.py::test_checkpw[vvho8C6nlVf9K-$2b$04$HrEYC/AQ2HS77G78cQDZQ.-$2b$04$HrEYC/AQ2HS77G78cQDZQ.r44WGcruKw03KHlnp71yVQEwpsi3xl2] tests/test_bcrypt.py::test_checkpw[5auCCY9by0Ruf-$2b$04$vVYgSTfB8KVbmhbZE/k3R.-$2b$04$vVYgSTfB8KVbmhbZE/k3R.ux9A0lJUM4CZwCkHI9fifke2.rTF7MG] tests/test_bcrypt.py::test_checkpw[GtTkR6qn2QOZW-$2b$04$JfoNrR8.doieoI8..F.C1O-$2b$04$JfoNrR8.doieoI8..F.C1OQgwE3uTeuardy6lw0AjALUzOARoyf2m] tests/test_bcrypt.py::test_checkpw[zKo8vdFSnjX0f-$2b$04$HP3I0PUs7KBEzMBNFw7o3O-$2b$04$HP3I0PUs7KBEzMBNFw7o3O7f/uxaZU7aaDot1quHMgB2yrwBXsgyy] tests/test_bcrypt.py::test_checkpw[I9VfYlacJiwiK-$2b$04$xnFVhJsTzsFBTeP3PpgbMe-$2b$04$xnFVhJsTzsFBTeP3PpgbMeMREb6rdKV9faW54Sx.yg9plf4jY8qT6] tests/test_bcrypt.py::test_checkpw[VFPO7YXnHQbQO-$2b$04$WQp9.igoLqVr6Qk70mz6xu-$2b$04$WQp9.igoLqVr6Qk70mz6xuRxE0RttVXXdukpR9N54x17ecad34ZF6] tests/test_bcrypt.py::test_checkpw[VDx5BdxfxstYk-$2b$04$xgZtlonpAHSU/njOCdKztO-$2b$04$xgZtlonpAHSU/njOCdKztOPuPFzCNVpB4LGicO4/OGgHv.uKHkwsS] tests/test_bcrypt.py::test_checkpw[dEe6XfVGrrfSH-$2b$04$2Siw3Nv3Q/gTOIPetAyPr.-$2b$04$2Siw3Nv3Q/gTOIPetAyPr.GNj3aO0lb1E5E9UumYGKjP9BYqlNWJe] tests/test_bcrypt.py::test_checkpw[cTT0EAFdwJiLn-$2b$04$7/Qj7Kd8BcSahPO4khB8me-$2b$04$7/Qj7Kd8BcSahPO4khB8me4ssDJCW3r4OGYqPF87jxtrSyPj5cS5m] tests/test_bcrypt.py::test_checkpw[J8eHUDuxBB520-$2b$04$VvlCUKbTMjaxaYJ.k5juoe-$2b$04$VvlCUKbTMjaxaYJ.k5juoecpG/7IzcH1AkmqKi.lIZMVIOLClWAk.] tests/test_bcrypt.py::test_checkpw[U*U-$2a$05$CCCCCCCCCCCCCCCCCCCCC.-$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW] tests/test_bcrypt.py::test_checkpw[U*U*-$2a$05$CCCCCCCCCCCCCCCCCCCCC.-$2a$05$CCCCCCCCCCCCCCCCCCCCC.VGOzA784oUp/Z0DY336zx7pLYAy0lwK] tests/test_bcrypt.py::test_checkpw[U*U*U-$2a$05$XXXXXXXXXXXXXXXXXXXXXO-$2a$05$XXXXXXXXXXXXXXXXXXXXXOAcXxm9kjPGEMsLznoKqmqw7tc8WCx4a] tests/test_bcrypt.py::test_checkpw[0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789chars tests/test_bcrypt.py::test_checkpw[\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaachars tests/test_bcrypt.py::test_checkpw[\xa3-$2a$05$/OK.fbVrR/bpIqNJ5ianF.-$2a$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq] tests/test_bcrypt.py::test_hashpw_existing[Kk4DQuMMfZL9o-$2b$04$cVWp4XaNU8a4v1uMRum2SO-$2b$04$cVWp4XaNU8a4v1uMRum2SO026BWLIoQMD/TXg5uZV.0P.uO8m3YEm] tests/test_bcrypt.py::test_hashpw_existing[9IeRXmnGxMYbs-$2b$04$pQ7gRO7e6wx/936oXhNjrO-$2b$04$pQ7gRO7e6wx/936oXhNjrOUNOHL1D0h1N2IDbJZYs.1ppzSof6SPy] tests/test_bcrypt.py::test_hashpw_existing[xVQVbwa1S0M8r-$2b$04$SQe9knOzepOVKoYXo9xTte-$2b$04$SQe9knOzepOVKoYXo9xTteNYr6MBwVz4tpriJVe3PNgYufGIsgKcW] tests/test_bcrypt.py::test_hashpw_existing[Zfgr26LWd22Za-$2b$04$eH8zX.q5Q.j2hO1NkVYJQO-$2b$04$eH8zX.q5Q.j2hO1NkVYJQOM6KxntS/ow3.YzVmFrE4t//CoF4fvne] tests/test_bcrypt.py::test_hashpw_existing[Tg4daC27epFBE-$2b$04$ahiTdwRXpUG2JLRcIznxc.-$2b$04$ahiTdwRXpUG2JLRcIznxc.s1.ydaPGD372bsGs8NqyYjLY1inG5n2] tests/test_bcrypt.py::test_hashpw_existing[xhQPMmwh5ALzW-$2b$04$nQn78dV0hGHf5wUBe0zOFu-$2b$04$nQn78dV0hGHf5wUBe0zOFu8n07ZbWWOKoGasZKRspZxtt.vBRNMIy] tests/test_bcrypt.py::test_hashpw_existing[59je8h5Gj71tg-$2b$04$cvXudZ5ugTg95W.rOjMITu-$2b$04$cvXudZ5ugTg95W.rOjMITuM1jC0piCl3zF5cmGhzCibHZrNHkmckG] tests/test_bcrypt.py::test_hashpw_existing[wT4fHJa2N9WSW-$2b$04$YYjtiq4Uh88yUsExO0RNTu-$2b$04$YYjtiq4Uh88yUsExO0RNTuEJ.tZlsONac16A8OcLHleWFjVawfGvO] tests/test_bcrypt.py::test_hashpw_existing[uSgFRnQdOgm4S-$2b$04$WLTjgY/pZSyqX/fbMbJzf.-$2b$04$WLTjgY/pZSyqX/fbMbJzf.qxCeTMQOzgL.CimRjMHtMxd/VGKojMu] tests/test_bcrypt.py::test_hashpw_existing[tEPtJZXur16Vg-$2b$04$2moPs/x/wnCfeQ5pCheMcu-$2b$04$2moPs/x/wnCfeQ5pCheMcuSJQ/KYjOZG780UjA/SiR.KsYWNrC7SG] tests/test_bcrypt.py::test_hashpw_existing[vvho8C6nlVf9K-$2b$04$HrEYC/AQ2HS77G78cQDZQ.-$2b$04$HrEYC/AQ2HS77G78cQDZQ.r44WGcruKw03KHlnp71yVQEwpsi3xl2] tests/test_bcrypt.py::test_hashpw_existing[5auCCY9by0Ruf-$2b$04$vVYgSTfB8KVbmhbZE/k3R.-$2b$04$vVYgSTfB8KVbmhbZE/k3R.ux9A0lJUM4CZwCkHI9fifke2.rTF7MG] tests/test_bcrypt.py::test_hashpw_existing[GtTkR6qn2QOZW-$2b$04$JfoNrR8.doieoI8..F.C1O-$2b$04$JfoNrR8.doieoI8..F.C1OQgwE3uTeuardy6lw0AjALUzOARoyf2m] tests/test_bcrypt.py::test_hashpw_existing[zKo8vdFSnjX0f-$2b$04$HP3I0PUs7KBEzMBNFw7o3O-$2b$04$HP3I0PUs7KBEzMBNFw7o3O7f/uxaZU7aaDot1quHMgB2yrwBXsgyy] tests/test_bcrypt.py::test_hashpw_existing[I9VfYlacJiwiK-$2b$04$xnFVhJsTzsFBTeP3PpgbMe-$2b$04$xnFVhJsTzsFBTeP3PpgbMeMREb6rdKV9faW54Sx.yg9plf4jY8qT6] tests/test_bcrypt.py::test_hashpw_existing[VFPO7YXnHQbQO-$2b$04$WQp9.igoLqVr6Qk70mz6xu-$2b$04$WQp9.igoLqVr6Qk70mz6xuRxE0RttVXXdukpR9N54x17ecad34ZF6] tests/test_bcrypt.py::test_hashpw_existing[VDx5BdxfxstYk-$2b$04$xgZtlonpAHSU/njOCdKztO-$2b$04$xgZtlonpAHSU/njOCdKztOPuPFzCNVpB4LGicO4/OGgHv.uKHkwsS] tests/test_bcrypt.py::test_hashpw_existing[dEe6XfVGrrfSH-$2b$04$2Siw3Nv3Q/gTOIPetAyPr.-$2b$04$2Siw3Nv3Q/gTOIPetAyPr.GNj3aO0lb1E5E9UumYGKjP9BYqlNWJe] tests/test_bcrypt.py::test_hashpw_existing[cTT0EAFdwJiLn-$2b$04$7/Qj7Kd8BcSahPO4khB8me-$2b$04$7/Qj7Kd8BcSahPO4khB8me4ssDJCW3r4OGYqPF87jxtrSyPj5cS5m] tests/test_bcrypt.py::test_hashpw_existing[J8eHUDuxBB520-$2b$04$VvlCUKbTMjaxaYJ.k5juoe-$2b$04$VvlCUKbTMjaxaYJ.k5juoecpG/7IzcH1AkmqKi.lIZMVIOLClWAk.] tests/test_bcrypt.py::test_hashpw_existing[U*U-$2a$05$CCCCCCCCCCCCCCCCCCCCC.-$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW] tests/test_bcrypt.py::test_hashpw_existing[U*U*-$2a$05$CCCCCCCCCCCCCCCCCCCCC.-$2a$05$CCCCCCCCCCCCCCCCCCCCC.VGOzA784oUp/Z0DY336zx7pLYAy0lwK] tests/test_bcrypt.py::test_hashpw_existing[U*U*U-$2a$05$XXXXXXXXXXXXXXXXXXXXXO-$2a$05$XXXXXXXXXXXXXXXXXXXXXOAcXxm9kjPGEMsLznoKqmqw7tc8WCx4a] tests/test_bcrypt.py::test_hashpw_existing[0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789chars tests/test_bcrypt.py::test_hashpw_existing[\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaachars tests/test_bcrypt.py::test_hashpw_existing[\xa3-$2a$05$/OK.fbVrR/bpIqNJ5ianF.-$2a$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq] tests/test_bcrypt.py::test_checkpw_2y_prefix[\xa3-$2y$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq-$2y$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq] tests/test_bcrypt.py::test_checkpw_2y_prefix[\xff\xff\xa3-$2y$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e-$2y$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e] tests/test_bcrypt.py::test_hashpw_invalid tests/test_bcrypt.py::test_checkpw_wrong_password tests/test_bcrypt.py::test_checkpw_bad_salt tests/test_bcrypt.py::test_checkpw_str_password tests/test_bcrypt.py::test_checkpw_str_salt tests/test_bcrypt.py::test_hashpw_str_password tests/test_bcrypt.py::test_hashpw_str_salt tests/test_bcrypt.py::test_checkpw_nul_byte tests/test_bcrypt.py::test_hashpw_nul_byte tests/test_bcrypt.py::test_kdf[4-password-salt-[\xbf\x0c\xc2\x93X\x7f\x1c65U\'ye\x98\xd4~W\x90q\xbfB~\x9d\x8f\xbe\x84*\xba4\xd9] tests/test_bcrypt.py::test_kdf[4-password-\x00-\xc1+Vb5\xee\xe0L!%\x98\x97\nW\x9ag] tests/test_bcrypt.py::test_kdf[4-\x00-salt-`Q\xbe\x18\xc2\xf4\xf8,\xbf\x0e\xfe\xe5G\x1bK\xb9] tests/test_bcrypt.py::test_kdf[4-password\x00-salt\x00-t\x10\xe4L\xf4\xfa\x07\xbf\xaa\xc8\xa9(\xb1r\x7f\xac\x00\x13u\xe7\xbfs\x847\x0fH\xef\xd1!t0P] tests/test_bcrypt.py::test_kdf[4-pass\x00wor-sa\x00l-\xc2\xbf\xfd\x9d\xb3\x8fei\xef\xefCr\xf4\xde\x83\xc0] tests/test_bcrypt.py::test_kdf[4-pass\x00word-sa\x00lt-K\xa4\xac9%\xc0\xe8\xd7\xf0\xcd\xb6\xbb\x16\x84\xa5o] tests/test_bcrypt.py::test_kdf[8-password-salt-\xe16~\xc5\x15\x1a3\xfa\xacL\xc1\xc1D\xcd#\xfa\x15\xd5T\x84\x93\xec\xc9\x9b\x9b]\x9c\r;'\xbe\xc7b'\xeaf\x08\x8b\x84\x9b tests/test_bcrypt.py::test_kdf[42-password-salt-\x83<\xf0\xdc\xf5m\xb6V\x08\xe8\xf0\xdc\x0c\xe8\x82\xbd] tests/test_bcrypt.py::test_kdf[8-Lorem tests/test_bcrypt.py::test_kdf[8-\r\xb3\xac\x94\xb3\xeeS(OJ"\x89;<$\xae-:b\xf0\xf0\xdb\xce\xf8#\xcf\xcc\x85HV\xea\x10(- tests/test_bcrypt.py::test_kdf[8-\xe1\xbd\x88\xce\xb4\xcf\x85\xcf\x83\xcf\x83\xce\xb5\xcf\x8d\xcf\x82-\xce\xa4\xce\xb7\xce\xbb\xce\xad\xce\xbc\xce\xb1\xcf\x87\xce\xbf\xcf\x82-Cfl\x9b\t\xef3\xed\x8c'\xe8\xe8\xf3\xe2\xd8\xe6] tests/test_bcrypt.py::test_kdf_str_password tests/test_bcrypt.py::test_kdf_str_salt tests/test_bcrypt.py::test_invalid_params[pass-$2b$04$cVWp4XaNU8a4v1uMRum2SO-10-10-TypeError] tests/test_bcrypt.py::test_invalid_params[password-salt-10-10-TypeError] tests/test_bcrypt.py::test_invalid_params[-$2b$04$cVWp4XaNU8a4v1uMRum2SO-10-10-ValueError] tests/test_bcrypt.py::test_invalid_params[password--10-10-ValueError] tests/test_bcrypt.py::test_invalid_params[password-$2b$04$cVWp4XaNU8a4v1uMRum2SO-0-10-ValueError] tests/test_bcrypt.py::test_invalid_params[password-$2b$04$cVWp4XaNU8a4v1uMRum2SO--3-10-ValueError] tests/test_bcrypt.py::test_invalid_params[password-$2b$04$cVWp4XaNU8a4v1uMRum2SO-513-10-ValueError] tests/test_bcrypt.py::test_invalid_params[password-$2b$04$cVWp4XaNU8a4v1uMRum2SO-20-0-ValueError] tests/test_bcrypt.py::test_bcrypt_assert tests/test_bcrypt.py::test_2a_wraparound_bug