import re
import sys

from pipenv.utils.dependencies import get_lockfile_section_using_pipfile_category
from pipenv.vendor import click


def requirements_from_deps(deps, include_hashes=True, include_markers=True):
    pip_packages = []

    for package_name, package_info in deps.items():
        # Handling git repositories
        if "git" in package_info:
            git = package_info["git"]
            ref = package_info.get("ref", "")
            extras = (
                "[{}]".format(",".join(package_info.get("extras", [])))
                if "extras" in package_info
                else ""
            )
            pip_package = f"{package_name}{extras} @ git+{git}@{ref}"
        else:
            # Handling packages with hashes and markers
            version = package_info.get("version", "").replace("==", "")
            hashes = (
                " --hash={}".format(" --hash=".join(package_info["hashes"]))
                if include_hashes and "hashes" in package_info
                else ""
            )
            markers = (
                "; {}".format(package_info["markers"])
                if include_markers and "markers" in package_info
                else ""
            )
            pip_package = f"{package_name}=={version}{hashes}{markers}"

        # Append to the list
        pip_packages.append(pip_package)

    # pip_packages contains the pip-installable lines
    return pip_packages


def generate_requirements(
    project,
    dev=False,
    dev_only=False,
    include_hashes=False,
    include_markers=True,
    categories="",
):
    lockfile = project.load_lockfile(expand_env_vars=False)

    for i, package_index in enumerate(lockfile["_meta"]["sources"]):
        prefix = "-i" if i == 0 else "--extra-index-url"
        click.echo(" ".join([prefix, package_index["url"]]))

    deps = {}
    categories_list = re.split(r", *| ", categories) if categories else []

    if categories_list:
        for category in categories_list:
            category = get_lockfile_section_using_pipfile_category(category.strip())
            deps.update(lockfile.get(category, {}))
    else:
        if dev or dev_only:
            deps.update(lockfile["develop"])
        if not dev_only:
            deps.update(lockfile["default"])

    pip_installable_lines = requirements_from_deps(
        deps, include_hashes=include_hashes, include_markers=include_markers
    )

    for line in pip_installable_lines:
        click.echo(line)

    sys.exit(0)

pipenv/routines/requirements.py
import re
import sys

from pipenv.utils.dependencies import get_lockfile_section_using_pipfile_category
from pipenv.vendor import click


def requirements_from_deps(deps, include_hashes=True, include_markers=True):
    pip_packages = []

    for package_name, package_info in deps.items():
        # Handling git repositories
        if "git" in package_info:
            git = package_info["git"]
            ref = package_info.get("ref", "")
            extras = (
                "[{}]".format(",".join(package_info.get("extras", [])))
                if "extras" in package_info
                else ""
            )
            pip_package = f"{package_name}{extras} @ git+{git}@{ref}"
        else:
            # Handling packages with hashes and markers
            version = package_info.get("version", "").replace("==", "")
            hashes = (
                " --hash={}".format(" --hash=".join(package_info["hashes"]))
                if include_hashes and "hashes" in package_info
                else ""
            )
            markers = (
                "; {}".format(package_info["markers"])
                if include_markers and "markers" in package_info
                else ""
            )
            pip_package = f"{package_name}=={version}{markers}{hashes}"

        # Append to the list
        pip_packages.append(pip_package)

    # pip_packages contains the pip-installable lines
    return pip_packages


def generate_requirements(
    project,
    dev=False,
    dev_only=False,
    include_hashes=False,
    include_markers=True,
    categories="",
):
    lockfile = project.load_lockfile(expand_env_vars=False)

    for i, package_index in enumerate(lockfile["_meta"]["sources"]):
        prefix = "-i" if i == 0 else "--extra-index-url"
        click.echo(" ".join([prefix, package_index["url"]]))

    deps = {}
    categories_list = re.split(r", *| ", categories) if categories else []

    if categories_list:
        for category in categories_list:
            category = get_lockfile_section_using_pipfile_category(category.strip())
            deps.update(lockfile.get(category, {}))
    else:
        if dev or dev_only:
            deps.update(lockfile["develop"])
        if not dev_only:
            deps.update(lockfile["default"])

    pip_installable_lines = requirements_from_deps(
        deps, include_hashes=include_hashes, include_markers=include_markers
    )

    for line in pip_installable_lines:
        click.echo(line)

    sys.exit(0)

pipenv/routines/requirements.py
diff --git a/news/5777.bugfix.rst b/news/5777.bugfix.rst
new file mode 100644
index 0000000000..8ad522f389
--- /dev/null
+++ b/news/5777.bugfix.rst
@@ -0,0 +1 @@
+Ensure hashes included in a generated requirements file are after any markers.
diff --git a/pipenv/routines/requirements.py b/pipenv/routines/requirements.py
index de48db446d..0e4c6102d5 100644
--- a/pipenv/routines/requirements.py
+++ b/pipenv/routines/requirements.py
@@ -32,7 +32,7 @@ def requirements_from_deps(deps, include_hashes=True, include_markers=True):
                 if include_markers and "markers" in package_info
                 else ""
             )
-            pip_package = f"{package_name}=={version}{hashes}{markers}"
+            pip_package = f"{package_name}=={version}{markers}{hashes}"
 
         # Append to the list
         pip_packages.append(pip_package)
diff --git a/tests/integration/test_requirements.py b/tests/integration/test_requirements.py
index 00fe63437e..ed957e892a 100644
--- a/tests/integration/test_requirements.py
+++ b/tests/integration/test_requirements.py
@@ -192,6 +192,33 @@ def test_requirements_markers_get_excluded(pipenv_instance_pypi):
         assert c.returncode == 0
         assert markers not in c.stdout
 
+@pytest.mark.requirements
+def test_requirements_hashes_get_included(pipenv_instance_pypi):
+    package, version, markers = "werkzeug", "==2.1.2", "python_version >= '3.7'"
+    first_hash = "sha256:1ce08e8093ed67d638d63879fd1ba3735817f7a80de3674d293f5984f25fb6e6"
+    second_hash = "sha256:72a4b735692dd3135217911cbeaa1be5fa3f62bffb8745c5215420a03dc55255"
+    lockfile = {
+        "_meta": {"sources": []},
+        "default": {
+            package: {
+                "hashes": [
+                    first_hash,
+                    second_hash
+                ],
+                "markers": markers,
+                "version": version
+            }
+        },
+        "develop": {}
+    }
+
+    with pipenv_instance_pypi(chdir=True) as p:
+        with open(p.lockfile_path, 'w') as f:
+            json.dump(lockfile, f)
+
+        c = p.pipenv('requirements --hash')
+        assert c.returncode == 0
+        assert f'{package}{version}; {markers} --hash={first_hash} --hash={second_hash}' in c.stdout
 
 def test_requirements_generates_requirements_from_lockfile_without_env_var_expansion(
         pipenv_instance_pypi,

Requirements output different since 2023.7.1 causing pip install issues
### Issue description

The output of `pipenv requirements --hash` has changed slightly in `2023.7.1` (#5757) and `pip` appears to be sensitive to it in some scenarios, causing `pip` to be unable to install the package(s) from the generated requirements.txt.

Snippet of requirements.txt generated with `2023.6.26`

```
pyzip==0.2.0 ; python_version >= '3.1' --hash=sha256:c0b10776d798e4be9d5fe6eec541dd0a9740b6550b12fd4cfa238a085686a298
```

Snippet of requirements.txt generated with `2023.7.1` - The hash is now before the marker

```
pyzip==0.2.0 --hash=sha256:c0b10776d798e4be9d5fe6eec541dd0a9740b6550b12fd4cfa238a085686a298; python_version >= '3.1'
```

### Expected result

- `2023.7.1` generates a requirements.txt as per `2023.6.26`

### Actual result

- `2023.7.1` generates a slightly different requirements.txt

### Steps to replicate
Pip successfully installs the package with the `2023.6.26` requirements.txt:

```
$ pipenv run pip --version
pip 23.1.2

$ cat requirements_2023.6.26.txt
pyzip==0.2.0 ; python_version >= '3.1' --hash=sha256:c0b10776d798e4be9d5fe6eec541dd0a9740b6550b12fd4cfa238a085686a298

$ pipenv run pip install -r requirements_2023.6.26.txt -t test_dir
Collecting pyzip==0.2.0 (from -r requirements_2023.6.26.txt (line 1))
  Using cached pyzip-0.2.0-py3-none-any.whl
Installing collected packages: pyzip
Successfully installed pyzip-0.2.0
```

Pip fails to install the package with the `2023.7.3` requirements.txt, thinking there is a hash mismatch even though it displays two identical shas:

```
$ pipenv run pip --version
pip 23.1.2

$ cat requirements_2023.7.1.txt
pyzip==0.2.0 --hash=sha256:c0b10776d798e4be9d5fe6eec541dd0a9740b6550b12fd4cfa238a085686a298; python_version >= '3.1'

$ pipenv run pip install -r requirements_2023.7.1.txt -t test_dir
Collecting pyzip==0.2.0 (from -r requirements_2023.7.1.txt (line 1))
  Using cached pyzip-0.2.0-py3-none-any.whl
  WARNING: The hashes of the source archive found in cache entry don't match, ignoring cached built wheel and re-downloading source.
  Using cached pyzip-0.2.0.tar.gz (6.3 kB)
ERROR: THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS FILE. If you have updated the package versions, please update the hashes. Otherwise, examine the package contents carefully; someone may have tampered with them.
    pyzip==0.2.0 from https://files.pythonhosted.org/packages/40/72/e29470ecfb5f2bc8cdd2a1b8a6aa14af8d44aa08fe5efa407cd991ce2c64/pyzip-0.2.0.tar.gz (from -r requirements_2023.7.1.txt (line 1)):
        Expected sha256 c0b10776d798e4be9d5fe6eec541dd0a9740b6550b12fd4cfa238a085686a298;
             Got        c0b10776d798e4be9d5fe6eec541dd0a9740b6550b12fd4cfa238a085686a298
```

I will raise a PR with a fix for consideration.
